diff --git a/source/Applications.cmake b/source/Applications.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..d42ccdd37f34fc3bac81849bd37e9cd35ac3364c
--- /dev/null
+++ b/source/Applications.cmake
@@ -0,0 +1,44 @@
+#add_subdirectory(tests)
+#add_subdirectory(Applications/gridRf)
+#add_subdirectory(Applications/greenvortex)
+# add_subdirectory(Applications/micropart)
+# add_subdirectory(Applications/sphere)
+#add_subdirectory(Applications/vfscript)
+#add_subdirectory(Applications/reefer)
+#add_subdirectory(Applications/bananas)
+#add_subdirectory(Applications/test1)
+#add_subdirectory(Applications/test2)
+#add_subdirectory(Applications/bananas2)
+# add_subdirectory(Applications/plate)
+# add_subdirectory(Applications/plate2)
+# add_subdirectory(Applications/FlowAroundCylinder)
+# add_subdirectory(Applications/LaminarTubeFlow)
+# add_subdirectory(Applications/LaminarTubeFlowConv)
+#add_subdirectory(Applications/cylinderSt)
+#add_subdirectory(Applications/mpichTest)
+# add_subdirectory(Applications/block_test)
+# add_subdirectory(Applications/bond_test)
+# add_subdirectory(Applications/bond_benchmark)
+# add_subdirectory(Applications/musis)
+# add_subdirectory(Applications/Hagen_Poiseuille_flow)
+# add_subdirectory(Applications/mpi_benchmark)
+# add_subdirectory(Applications/shear)
+# add_subdirectory(Applications/wing)
+# add_subdirectory(Applications/bKanal)
+# add_subdirectory(Applications/bKanal2)
+# add_subdirectory(Applications/bKanalAv)
+# add_subdirectory(Applications/fetol_demo)
+# add_subdirectory(Applications/insitu_demo)
+# add_subdirectory(Applications/insitu_demoserver)
+# add_subdirectory(Applications/PlateWithPorousInlay)
+# add_subdirectory(Applications/stick)
+# add_subdirectory(Applications/band)
+# add_subdirectory(Applications/bone)
+# add_subdirectory(Applications/sbone)
+# add_subdirectory(Applications/bbone)
+# add_subdirectory(Applications/porplate2)
+# add_subdirectory(Applications/BeadPack)
+# add_subdirectory(Applications/town)
+# add_subdirectory(Applications/perm)
+add_subdirectory(Applications/pChannel)
+#add_subdirectory(Applications/pDisk)
\ No newline at end of file
diff --git a/source/Applications/BeadPack/CMakeLists.txt b/source/Applications/BeadPack/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4a12b93fe4e384840145d2ae1d96c85bd12ef9c0
--- /dev/null
+++ b/source/Applications/BeadPack/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(beadpack)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(beadpack BINARY)
diff --git a/source/Applications/BeadPack/beadpack.cpp b/source/Applications/BeadPack/beadpack.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e4c95117a9597a30becaa1a1e63c83bb10d9674e
--- /dev/null
+++ b/source/Applications/BeadPack/beadpack.cpp
@@ -0,0 +1,438 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void sbonepd(const char *configname)
+{
+   try
+   {
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname, pathGeo;
+      int numOfThreads;
+      double availMem;
+
+      ConfigFileReader cf(configname);
+      if (!cf.read())
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if (machine == "BOMBADIL")
+      {
+         numOfThreads = 4;
+         pathname = "d:/temp/bbone";
+         pathGeo = "d:/Data/Bone/BigBone";
+         availMem = 15.0e9;
+      }
+      else if (machine == "M01" || machine == "M02")
+      {
+         numOfThreads = 8;
+         pathname = cf.getValue("pathname");
+         pathGeo = cf.getValue("pathGeo");
+         availMem = 12.0e9;
+
+#if defined(__unix__)
+         if (myid == 0)
+         {
+            const char* str = pathname.c_str();
+            int status = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+         }
+#endif 
+
+         if (myid == 0)
+         {
+            stringstream logFilename;
+            logFilename << pathname + "/logfile" + UbSystem::toString(UbSystem::getTimeStamp()) + ".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+
+
+      if (myid == 0) UBLOG(logINFO, "Testcase big bone");
+
+      Grid3DPtr grid(new Grid3D(comm));
+      double deltaVoxel = 11.658e-6;
+
+      double dx = deltaVoxel;
+
+      const int blocknx1 = 64;
+      const int blocknx2 = 64;
+      const int blocknx3 = 64;
+
+      LBMReal rho_LB = 0.0;
+      //nueWasser = 1e-6 m^2/s
+      double nu_real = 1e-6;
+      LBMReal dt = 5e-8; // s (frei gewählt)
+      //dx - frei gewählt
+      //
+      LBMReal nu_LB = nu_real / (dx*dx / dt);
+
+
+      //dp = 50000 Pa - 0 Pa = 50000 Pa
+      double dp_real = UbSystem::stringTo<double>(cf.getValue("pressure")); //5000;
+      //rho wasser = 1000 kg*m^-3
+      double rho_real = 1000;
+      //dp/rho = 50000/1000 = 50 m^2/s^2
+      double dp_div_rho_real = dp_real / rho_real;
+
+      double dp_LB = dp_div_rho_real / ((dx / dt)*(dx / dt));
+
+      bool with_forcing = true;
+
+      double rhoLBinflow;
+      if (with_forcing)
+      {
+         rhoLBinflow = 0.0;
+      }
+      else
+      {
+         rhoLBinflow = dp_LB*3.0;
+      }
+      double deltax = dx;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      double coord[6];
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(50000, 50000, 10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+         if (myid == 0) UBLOG(logINFO, "Neustart..");
+
+         string boneFilename = pathGeo + "/cyl_bone2.raw";
+
+         int pmNX1 = 1164;  //abmessung einzelbild in x-richtung
+         int pmNX2 = 972; //abmessung einzelbild in y richtung
+         int pmNX3 = 900; //anzahl der bilder
+         //int pmNX3 = 10; //anzahl der bilder
+         float lthreshold = 109.0;
+         float uthreshold = 255.0;
+
+         GbVoxelMatrix3DPtr bone(new GbVoxelMatrix3D(pmNX1, pmNX2, pmNX3, 0, lthreshold, uthreshold));
+         bone->readMatrixFromRawFile<unsigned char>(boneFilename, GbVoxelMatrix3D::BigEndian);
+
+         
+         bone->setVoxelMatrixDelta(deltaVoxel, deltaVoxel, deltaVoxel);
+
+         bone->setVoxelMatrixMininum(0.0, 0.0, 0.0);
+
+         if (myid == 0) bone->writeToVTKImageDataASCII(pathname + "/geo/bone");
+
+         ///////////////////////////////////////////////////////
+
+         ////////////////////////////////////////////////////////////////////////
+
+         double offset = 0.5e-3;
+         //bounding box
+         double g_minX1 = bone->getX1Minimum();
+         double g_minX2 = bone->getX2Minimum();
+         double g_minX3 = bone->getX3Minimum() - offset;
+
+         double g_maxX1 = bone->getX1Maximum();
+         double g_maxX2 = bone->getX2Maximum();
+         double g_maxX3 = bone->getX3Maximum() + offset;
+
+         double blockLength = (double)blocknx1*deltax;
+
+         grid->setPeriodicX1(false);
+         grid->setPeriodicX2(false);
+         grid->setPeriodicX3(true);
+         grid->setDeltaX(deltax);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         double forcing = 0;
+         if (with_forcing)
+         {
+            forcing = dp_LB / (blocknx3*grid->getNX3());
+         }
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Parameters:");
+            UBLOG(logINFO, "with forcing = " << with_forcing);
+            UBLOG(logINFO, "rho_LB = " << rho_LB);
+            UBLOG(logINFO, "nu_LB = " << nu_LB);
+            UBLOG(logINFO, "dp_LB = " << dp_LB);
+            UBLOG(logINFO, "forcing = " << forcing);
+            UBLOG(logINFO, "dx = " << dx << " m");
+            UBLOG(logINFO, "dt = " << dt << " s");
+            UBLOG(logINFO, "rho_real = " << rho_real << " kg*m^-3");
+            UBLOG(logINFO, "nu_real = " << nu_real << " m^2/s");
+            UBLOG(logINFO, "dp_real = " << dp_real << " Pa");
+
+            UBLOG(logINFO, "number of levels = " << refineLevel + 1);
+            UBLOG(logINFO, "numOfThreads = " << numOfThreads);
+            UBLOG(logINFO, "path = " << pathname);
+            UBLOG(logINFO, "Preprozess - start");
+         }
+
+         //cylinder
+         double radius = 0.0036;
+         double cx1 = 0.007;
+         double cx2 = 0.0046;
+
+         GbObject3DPtr cylinder(new GbCylinder3D(cx1, cx2, g_minX3 - offset, cx1, cx2, g_maxX3 + offset, radius));
+         GbSystem3D::writeGeoObject(cylinder.get(), pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow(new GbCuboid3D(g_minX1 - blockLength, g_minX2 - blockLength, g_minX3 - blockLength, g_maxX1 + blockLength, g_maxX2 + blockLength, g_minX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname + "/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow(new GbCuboid3D(g_minX1 - blockLength, g_minX2 - blockLength, g_maxX3, g_maxX1 + blockLength, g_maxX2 + blockLength, g_maxX3 + blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname + "/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+         //bone interactor
+         int bcOptionBone = 0; //0=simple Bounce Back, 1=quadr. BB, 2=thin wall
+         D3Q27BoundaryConditionAdapterPtr bcBone(new D3Q27NoSlipBCAdapter(bcOptionBone));
+         D3Q27InteractorPtr boneInt(new D3Q27Interactor(bone, grid, bcBone, Interactor3D::SOLID));
+
+         //wall interactors
+         int bcOptionWall = 0; //0=simple Bounce Back, 1=quadr. BB, 2=thin wall
+         D3Q27BoundaryConditionAdapterPtr bcWall(new D3Q27NoSlipBCAdapter(bcOptionWall));
+         D3Q27InteractorPtr cylInt(new D3Q27Interactor(cylinder, grid, bcWall, Interactor3D::INVERSESOLID));
+
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterInflow(new D3Q27DensityBCAdapter(rhoLBinflow));
+         denBCAdapterInflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoInflow, grid, denBCAdapterInflow, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterOutflow(new D3Q27DensityBCAdapter(rho_LB));
+         denBCAdapterOutflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoOutflow, grid, denBCAdapterOutflow, Interactor3D::SOLID));
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::BSW));
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(boneInt);
+         intHelper.addInteractor(cylInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - end");
+         //////////////////////////////////////
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nod = nob * (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nodg = nob * (blocknx1 + gl) * (blocknx2 + gl) * (blocknx3 + gl);
+         double needMemAll = double(nodg*(27 * sizeof(double) + sizeof(int) + sizeof(float) * 4));
+         double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Number of blocks = " << nob);
+            UBLOG(logINFO, "Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for (int level = minInitLevel; level <= maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO, "Number of blocks for level " << level << " = " << nobl);
+               UBLOG(logINFO, "Number of nodes for level " << level << " = " << nobl*nodb);
+            }
+            UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+            UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+            UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         mu::Parser fctForcingX3;
+         fctForcingX3.SetExpr("Fx3");
+         fctForcingX3.DefineConst("Fx3", forcing);
+
+         kernel->setForcingX3(fctForcingX3);
+         kernel->setWithForcing(true);
+
+         //BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nu_LB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+
+         //BC
+         intHelper.setBC();
+
+         //Press*1.6e8+(14.76-coordsX)/3.5*5000
+         //initialization of distributions
+         //mu::Parser fct;
+         //fct.SetExpr("(x1max-x1)/l*dp*3.0");
+         //fct.DefineConst("dp", dp_LB);
+         //fct.DefineConst("x3max", g_maxX3);
+         //fct.DefineConst("l", g_maxX3-g_minX3);
+
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nu_LB, rho_LB);
+         //initVisitor.setRho(fct);
+         //initVisitor.setVx1(fct);
+         initVisitor.setVx1(0.0);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+
+         coord[0] = bone->getX1Minimum();
+         coord[1] = bone->getX2Minimum();
+         coord[2] = cylinder->getX3Centroid();
+         coord[3] = bone->getX1Maximum();
+         coord[4] = bone->getX2Maximum();
+         coord[5] = cylinder->getX3Centroid();
+
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "w");
+         fprintf(pFile, "%f\n", coord[0]);
+         fprintf(pFile, "%f\n", coord[1]);
+         fprintf(pFile, "%f\n", coord[2]);
+         fprintf(pFile, "%f\n", coord[3]);
+         fprintf(pFile, "%f\n", coord[4]);
+         fprintf(pFile, "%f\n", coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+         if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+      }
+      else
+      {
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "r");
+         fscanf(pFile, "%f\n", &coord[0]);
+         fscanf(pFile, "%f\n", &coord[1]);
+         fscanf(pFile, "%f\n", &coord[2]);
+         fscanf(pFile, "%f\n", &coord[3]);
+         fscanf(pFile, "%f\n", &coord[4]);
+         fscanf(pFile, "%f\n", &coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+      }
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      double outTime = 30000;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      stepSch->addSchedule(10, 10, 10);
+      stepSch->addSchedule(100, 100, 100);
+      stepSch->addSchedule(1000, 1000, 1000);
+      stepSch->addSchedule(100, 1500, 2000);
+      stepSch->addSchedule(10000, 10000, 10000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+      double dxd2 = deltax / 2.0;
+      D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, coord[0] - dxd2, coord[1] - dxd2, coord[2] - dxd2,
+         coord[3] + dxd2, coord[4] + dxd2, coord[5] + dxd2));
+      if (myid == 0) GbSystem3D::writeGeoObject(ih1->getBoundingBox().get(), pathname + "/geo/ih1", WbWriterVtkXmlBinary::getInstance());
+
+      double factorp = dp_real / dp_LB;
+      double factorv = dx / dt;
+      UbSchedulerPtr stepMV(new UbScheduler(100));
+      D3Q27MeanValuesPostprocessor mvp1(grid, stepMV, pathname + "/mv/mv1.txt", comm, ih1, factorp, factorv);
+
+
+      //D3Q27IntegrateValuesHelperPtr ih2(new D3Q27IntegrateValuesHelper(grid, comm, g_maxX1-2.0*deltax, g_minX2, g_minX3,
+      //   g_maxX1 - deltax, g_maxX2, g_maxX3));
+      //if (myid == 0) GbSystem3D::writeGeoObject(ih2->getBoundingBox().get(), pathname + "/geo/ih2", WbWriterVtkXmlBinary::getInstance());
+
+      //D3Q27MeanValuesPostprocessor mvp2(grid, stepSch, pathname + "/mv/mv2.txt", comm, ih2, factorp, factorv);
+
+      if (myid == 0)
+      {
+         UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      double endTime = UbSystem::stringTo<double>(cf.getValue("endTime")); //100001;//10001.0;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepMV));
+      if (myid == 0) UBLOG(logINFO, "Simulation-start");
+      calculation->calculate();
+      if (myid == 0) UBLOG(logINFO, "Simulation-end");
+   }
+   catch (exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch (string& s)
+   {
+      cerr << s << endl;
+   }
+   catch (...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+
+   if (argv != NULL)
+   {
+      sbonepd(argv[1]);
+   }
+
+   return 0;
+}
diff --git a/source/Applications/BeadPack/data/NewCentroids.txt b/source/Applications/BeadPack/data/NewCentroids.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ba415e9a87146cfac5004a4a3c1fd2fb6ad75d6f
--- /dev/null
+++ b/source/Applications/BeadPack/data/NewCentroids.txt
@@ -0,0 +1,6864 @@
+2.397382	1.487592	0.417539
+2.368312	0.792199	0.414552
+2.404938	2.334875	0.417688
+2.408864	2.601136	0.404545
+2.452162	1.733784	0.398378
+2.472830	1.032642	0.402264
+2.468872	3.203534	0.411805
+2.490606	0.355152	0.398030
+2.500741	2.847513	0.410899
+2.501491	3.461930	0.407456
+2.500772	4.533719	0.422211
+2.531121	0.099776	0.408834
+2.558878	2.130816	0.400204
+2.620484	3.703871	0.402419
+2.614297	4.973498	0.416388
+2.644836	0.817089	0.406291
+2.635581	1.892093	0.398605
+2.677556	1.652444	0.397556
+2.669632	3.966691	0.414338
+2.683929	4.230982	0.409732
+2.728095	3.262286	0.423016
+2.753871	2.333710	0.405806
+2.750204	2.847755	0.402449
+2.777037	1.429630	0.408025
+2.798280	1.170376	0.417204
+2.312500	1.244167	0.411111
+2.366619	3.733986	0.428577
+2.363713	4.770099	0.427030
+2.408919	3.997405	0.428757
+2.491375	6.236543	0.430558
+2.589587	5.468347	0.425744
+2.608462	6.005923	0.420077
+2.637723	5.740660	0.427030
+2.664545	2.572893	0.415289
+2.690426	4.716170	0.410213
+2.780526	0.172632	0.401579
+2.783232	3.521717	0.414343
+2.810497	2.085580	0.424530
+2.819956	0.425200	0.421333
+2.819569	4.457682	0.438086
+2.875584	0.925455	0.419610
+2.877581	1.836613	0.423629
+2.265437	0.469612	0.424563
+2.259412	3.500980	0.424902
+2.288827	0.202793	0.432346
+2.302544	3.008402	0.430059
+2.356620	5.347183	0.421549
+2.368495	5.600430	0.424516
+2.375093	5.864472	0.428385
+2.432959	4.265867	0.430612
+2.563371	1.290400	0.426457
+2.602632	0.558421	0.415789
+2.740566	6.211321	0.420189
+2.829774	5.125338	0.431955
+2.838870	5.382435	0.429739
+2.865577	3.788462	0.439872
+2.847897	5.915187	0.440374
+2.898192	3.055346	0.439769
+2.216304	1.783152	0.435652
+2.221633	2.760476	0.439932
+2.223838	3.253838	0.437576
+2.250484	4.436290	0.429677
+2.258552	6.356552	0.438069
+2.916866	4.065791	0.447194
+2.928049	2.513049	0.436402
+2.940404	4.720594	0.456318
+2.975446	0.030792	0.433267
+2.969467	1.592311	0.446756
+2.144865	1.535811	0.449392
+2.156744	2.021163	0.442558
+2.156667	2.267901	0.445185
+2.171579	1.063509	0.437193
+2.166571	4.189810	0.458810
+2.274286	6.090571	0.440714
+2.369961	5.077266	0.455352
+2.385510	1.964898	0.432857
+2.858182	0.678939	0.442879
+2.971250	3.340000	0.438750
+3.004615	1.326731	0.444615
+3.000741	2.265926	0.441296
+3.042338	0.280260	0.452403
+2.094858	0.035330	0.467264
+2.132318	4.651060	0.462185
+2.142250	5.478550	0.466050
+2.161797	3.918125	0.455859
+2.145514	4.923730	0.474622
+2.148750	5.214632	0.460147
+2.195714	2.506786	0.443214
+2.941860	6.391395	0.446977
+2.974000	6.154833	0.451167
+3.055106	0.528723	0.445106
+3.058617	2.027766	0.457766
+3.081667	1.067250	0.460333
+2.063247	0.837273	0.473961
+2.092911	3.675443	0.462532
+3.048129	4.291367	0.465396
+3.094164	0.790214	0.473523
+3.061724	5.223448	0.463448
+3.056184	5.756579	0.467895
+2.057681	0.324525	0.483042
+2.045430	1.293333	0.479194
+2.045737	2.946526	0.479158
+3.079532	5.489169	0.491065
+3.134628	2.888512	0.480992
+3.128677	3.869613	0.492581
+3.152727	1.765818	0.473273
+2.025338	3.420912	0.495304
+2.006329	4.409306	0.504913
+2.036471	6.218431	0.481765
+2.057520	5.966545	0.494797
+2.167024	5.732976	0.489167
+3.130435	4.535217	0.484493
+3.143043	2.634348	0.473478
+3.159627	3.167801	0.492116
+1.969557	1.845897	0.512681
+1.978909	0.585527	0.508655
+1.986923	2.689615	0.482308
+3.154933	6.001600	0.499933
+3.226455	0.106636	0.502455
+1.936972	1.054404	0.508532
+1.932615	2.168769	0.506000
+1.962500	2.444196	0.512768
+2.852981	5.625481	0.504904
+3.215521	2.400097	0.521671
+3.209871	4.781484	0.511806
+3.218000	3.433500	0.505750
+3.216122	4.110204	0.500204
+1.918834	3.856632	0.534275
+1.918261	1.586087	0.504348
+1.929562	5.083577	0.526350
+1.934507	5.338169	0.511831
+3.030447	4.983610	0.530000
+2.612966	5.216525	0.531949
+3.242780	1.275415	0.540361
+3.314545	1.517576	0.523939
+1.873882	0.138118	0.530235
+1.905200	4.762945	0.545200
+1.923365	5.594952	0.546346
+2.643443	3.031721	0.542787
+3.010687	3.587694	0.553548
+3.297042	3.669437	0.530282
+3.293654	4.351346	0.529038
+3.295675	5.044810	0.548927
+3.291660	5.332648	0.545929
+3.289350	5.657870	0.552599
+3.337926	0.339407	0.535407
+1.850217	3.090290	0.545290
+1.844217	5.836627	0.546988
+2.929859	2.756268	0.541761
+2.944545	3.086364	0.571364
+3.348621	0.782759	0.532414
+3.345065	2.166623	0.540909
+3.371015	1.038609	0.557594
+1.814949	0.388788	0.556465
+1.812745	1.256863	0.548039
+1.816522	2.840435	0.547391
+1.818585	3.604906	0.553491
+1.825911	4.121921	0.567340
+1.828148	0.835556	0.546481
+1.831011	6.089787	0.562926
+3.382353	1.753382	0.547941
+3.368929	4.582321	0.556071
+1.778737	4.525051	0.577929
+1.796909	6.365164	0.573091
+3.363967	6.160516	0.584321
+3.379647	3.914706	0.564000
+1.767957	2.000215	0.570860
+1.753034	2.605655	0.586414
+1.769918	3.343607	0.589536
+2.227092	0.668723	0.587943
+2.603869	1.503065	0.580352
+2.651250	1.001705	0.577614
+3.131751	6.325036	0.591823
+3.367500	5.897833	0.567167
+1.737204	1.734194	0.585806
+1.728414	2.337252	0.609207
+2.333005	2.151913	0.587432
+2.593492	2.401270	0.574921
+3.454105	2.508158	0.592842
+3.444286	4.162381	0.593401
+1.720179	1.479107	0.599524
+1.723238	4.936238	0.603238
+1.724337	5.434217	0.596747
+1.732581	0.618065	0.579032
+2.322714	0.020714	0.597714
+2.545033	3.848301	0.600458
+2.598500	0.265500	0.598375
+3.245395	1.952500	0.594211
+3.340714	2.715000	0.579286
+3.369130	6.396087	0.583913
+3.460809	3.489223	0.615469
+3.477054	0.140536	0.591339
+3.486379	0.603966	0.590000
+3.484865	1.971757	0.596892
+3.490536	1.330357	0.596964
+1.704972	1.040608	0.610442
+2.438477	0.507531	0.615103
+2.538158	4.723947	0.610197
+2.589894	4.377447	0.608511
+3.237879	0.587677	0.603838
+2.265368	1.378896	0.628067
+2.326066	1.646256	0.622701
+2.519722	1.812917	0.617639
+2.744512	1.927439	0.623963
+2.758642	0.061204	0.626296
+2.791951	1.679024	0.607073
+3.489624	5.489286	0.629023
+1.651161	4.308968	0.633935
+1.670833	5.676019	0.623889
+2.076077	3.182488	0.631675
+2.324197	4.569663	0.641580
+2.448690	1.151508	0.636111
+2.462908	6.001454	0.641684
+2.576327	3.291927	0.642218
+2.818669	6.096730	0.638403
+2.861266	2.353418	0.621899
+3.103488	1.480233	0.623605
+3.498596	5.195000	0.624561
+3.535577	1.580769	0.622115
+1.643774	0.225849	0.635094
+1.632230	2.987311	0.648918
+1.633757	5.196618	0.654538
+1.673731	3.804231	0.641154
+2.306959	2.417872	0.650372
+2.321044	3.387071	0.650135
+2.348478	4.144042	0.655643
+2.480896	5.739254	0.629701
+2.488994	0.820828	0.637515
+2.526848	3.567994	0.648854
+2.658209	6.280000	0.635970
+2.679266	2.178807	0.637982
+2.701818	2.794034	0.645966
+2.798589	4.234896	0.640290
+2.812050	3.416584	0.643043
+2.890765	1.048412	0.644824
+2.950000	3.040000	0.610000
+3.439524	4.813061	0.635374
+3.537865	3.738989	0.638315
+3.550663	0.866188	0.646906
+1.634384	5.934155	0.654292
+1.621625	6.201875	0.647625
+2.259130	3.634565	0.638696
+2.279091	1.907172	0.646768
+2.483165	2.612615	0.651927
+2.701071	1.248049	0.660769
+2.689926	5.880370	0.650815
+2.705106	0.497690	0.661489
+2.743851	0.777905	0.649730
+2.762778	4.604747	0.657424
+3.002613	1.862484	0.655871
+3.590247	0.387407	0.653765
+1.602545	1.265636	0.650364
+1.596048	3.544948	0.670447
+1.614746	4.711695	0.648983
+2.158065	2.643706	0.671853
+2.292331	5.574942	0.675315
+2.304000	3.869143	0.651143
+2.337895	3.117953	0.663450
+2.348532	4.893257	0.658807
+2.441409	5.354228	0.656644
+2.457704	2.882185	0.665333
+2.738983	5.419322	0.649831
+2.833563	4.860063	0.657250
+2.956210	2.968629	0.684435
+2.967804	4.436682	0.663318
+2.984370	5.906296	0.655037
+3.559372	2.208010	0.660471
+3.562955	5.792386	0.655568
+3.604661	1.123898	0.657542
+1.576404	4.068090	0.667978
+2.065062	2.033765	0.675741
+2.071416	4.043382	0.679075
+2.176311	6.350299	0.676013
+2.762201	3.713491	0.680252
+2.968413	0.645329	0.676617
+3.012778	0.133611	0.653889
+3.033940	2.537616	0.682848
+3.572809	6.316340	0.672723
+3.592857	4.620893	0.660893
+1.559213	0.475354	0.682677
+1.555547	0.748984	0.683672
+1.563000	1.879714	0.677571
+1.569689	2.137358	0.676684
+1.557460	2.729206	0.682222
+2.197280	2.908640	0.676000
+2.207910	6.061721	0.693238
+2.269611	0.946833	0.678389
+2.357645	0.259504	0.684545
+2.420127	6.254051	0.673291
+2.633662	5.012817	0.682629
+2.861502	5.178115	0.690990
+2.918478	2.112536	0.677681
+3.020902	3.278443	0.685984
+3.608667	3.989714	0.674476
+2.074688	2.294531	0.676563
+2.112326	1.160066	0.697841
+3.035946	5.656284	0.699527
+3.071687	0.387055	0.701963
+3.126940	5.192672	0.700043
+3.615870	4.983804	0.682391
+3.615655	6.046773	0.702843
+2.020390	3.669894	0.710496
+2.090877	1.557544	0.683860
+2.098194	0.179226	0.711387
+2.131899	4.748354	0.702658
+2.168091	0.433727	0.696273
+2.729212	3.980242	0.704545
+2.910952	6.396190	0.685238
+3.149504	4.244771	0.710458
+3.669000	2.437100	0.696400
+1.515508	2.456017	0.708559
+1.512258	5.511505	0.705699
+2.166268	5.266197	0.709014
+2.795035	3.161678	0.712448
+2.974080	4.058000	0.703120
+3.001826	1.270609	0.702435
+3.161604	1.084528	0.703396
+3.160127	2.172278	0.700000
+3.196029	3.030588	0.695735
+3.455374	4.407357	0.714361
+3.662241	4.262586	0.704741
+3.678974	1.781496	0.707863
+3.663786	3.310214	0.714643
+3.697296	0.664025	0.715597
+1.499756	3.242033	0.724350
+1.506481	4.499568	0.716358
+1.493799	4.973436	0.735307
+2.005123	0.905215	0.727362
+3.007302	3.800476	0.711111
+3.148400	2.783300	0.722600
+1.478393	1.002917	0.735417
+1.496667	1.485145	0.724565
+1.501742	6.389318	0.731136
+1.933623	1.371739	0.724493
+1.962326	4.279457	0.727442
+2.127321	5.007143	0.725089
+2.504146	2.023902	0.720732
+2.734013	2.545405	0.737864
+3.234436	1.664812	0.721278
+3.690556	3.560000	0.713611
+3.728997	0.185350	0.745380
+2.085038	4.496241	0.741729
+2.782862	5.656325	0.749399
+2.835618	0.285843	0.732697
+2.997536	4.684058	0.727246
+3.140611	6.086889	0.740611
+3.147182	0.826364	0.735273
+3.209386	4.514910	0.749675
+3.219636	3.986545	0.746727
+3.225019	5.491407	0.749011
+3.703736	5.610220	0.739011
+3.738947	1.494842	0.738632
+1.905000	0.011429	0.742143
+1.904796	5.291403	0.758100
+2.081667	3.412667	0.750667
+2.795053	1.484526	0.744000
+3.232353	0.188067	0.747059
+3.322683	1.427642	0.751951
+3.350551	2.319291	0.748425
+3.711596	5.226702	0.740000
+1.442583	3.743432	0.763100
+1.426824	4.257882	0.759294
+1.430851	5.808617	0.763298
+1.444762	6.077302	0.748571
+1.840419	2.143263	0.770210
+1.955492	5.879590	0.762705
+1.986272	6.176805	0.759882
+2.368182	5.130545	0.745455
+3.177489	3.459910	0.762960
+3.752035	3.803451	0.760619
+1.432299	0.271839	0.758851
+1.851186	0.237119	0.757627
+1.932055	0.469589	0.760137
+2.486620	1.367512	0.779390
+2.956429	5.419571	0.774429
+3.223431	4.790962	0.775816
+3.234353	3.723882	0.768588
+3.285859	2.574978	0.780661
+3.391176	1.184118	0.762941
+3.408194	3.053965	0.795507
+3.777143	0.920000	0.770286
+1.404593	2.972185	0.789444
+1.406768	4.725253	0.773434
+1.412171	5.260465	0.774961
+1.822931	4.681034	0.765690
+1.836053	1.868947	0.766579
+1.849159	0.705421	0.777290
+1.860621	1.616158	0.789209
+1.921852	2.600926	0.770185
+1.953125	6.397500	0.764375
+2.076073	1.796164	0.781826
+2.203869	5.809311	0.792066
+2.989551	1.631910	0.777865
+3.758429	4.754031	0.781047
+3.784390	2.231220	0.765122
+1.389431	1.249701	0.804251
+1.389762	1.734762	0.780476
+1.852257	2.850817	0.793035
+1.849811	5.538679	0.778868
+2.476749	0.052792	0.797138
+2.506463	2.266463	0.785122
+2.535452	5.552776	0.798194
+2.585108	4.191477	0.794554
+3.028158	4.963474	0.794263
+3.316235	0.435608	0.800314
+3.368723	0.699734	0.789681
+3.362439	2.064024	0.790610
+3.377851	5.004050	0.791240
+3.786757	2.847568	0.786216
+3.809590	0.439147	0.800341
+3.811440	1.186070	0.799728
+1.380195	2.258878	0.803366
+1.375563	3.466406	0.813000
+1.375208	1.987292	0.801875
+1.734930	3.178944	0.795634
+1.866233	1.137860	0.801349
+2.077397	5.481233	0.790000
+2.555560	1.630474	0.803319
+2.629226	5.252440	0.808542
+2.907613	2.741757	0.803964
+3.173286	5.840143	0.795143
+3.377489	5.698018	0.799780
+3.374660	5.999796	0.809048
+3.777983	5.866481	0.799313
+3.803864	4.073977	0.808750
+1.371229	4.010000	0.817973
+1.871671	3.861671	0.825633
+2.091046	0.659346	0.813007
+2.388529	4.367157	0.808922
+2.544516	0.647097	0.802419
+3.323380	6.306852	0.809630
+3.350526	5.261316	0.803684
+3.435177	1.800851	0.822979
+3.770916	6.232977	0.811527
+3.816222	3.103889	0.797222
+1.794958	5.065714	0.816387
+1.839585	3.474473	0.824984
+2.329545	0.741970	0.813485
+2.403438	3.724063	0.813750
+2.536557	3.081639	0.809344
+2.561082	4.564131	0.822754
+2.908693	0.863660	0.825229
+2.943148	3.586296	0.808889
+3.010943	2.320000	0.819057
+3.348889	0.951556	0.810889
+3.471038	0.236415	0.817642
+3.601707	2.000610	0.813171
+1.611400	1.677600	0.823800
+1.774286	4.110000	0.828869
+2.650233	4.804884	0.814884
+2.710141	1.034930	0.819014
+3.193696	1.892174	0.825761
+3.396579	3.332105	0.824737
+3.593151	1.313836	0.823973
+3.857794	1.988578	0.837990
+1.340148	0.490815	0.833852
+1.674087	5.383652	0.834087
+1.680149	0.067139	0.856219
+1.709560	1.397170	0.842327
+1.727326	6.336028	0.852009
+1.721634	0.921206	0.850428
+1.952759	4.875241	0.839103
+2.040645	3.022258	0.828925
+2.299583	2.060625	0.837708
+2.563333	0.351026	0.835449
+2.573607	6.145689	0.849208
+2.779414	4.403555	0.845391
+3.715385	2.627179	0.827436
+3.835978	5.421285	0.837933
+3.871071	2.445893	0.830536
+1.312034	5.530339	0.846356
+1.330120	0.053593	0.843952
+1.309809	2.524306	0.868565
+1.683378	2.599392	0.848986
+1.745817	5.753983	0.866361
+1.777284	6.041802	0.862741
+2.160153	3.857691	0.865294
+2.176571	4.218476	0.853714
+2.433579	3.974632	0.848211
+2.525333	6.392889	0.842222
+2.654748	3.441978	0.854676
+2.744180	2.941719	0.859688
+2.753918	2.295448	0.861493
+2.803908	6.258621	0.842759
+3.069479	6.320274	0.856192
+3.383600	2.793600	0.836000
+3.435035	4.647588	0.862084
+3.447405	3.606997	0.862624
+3.490390	4.128485	0.853030
+3.801609	5.013166	0.863958
+3.861077	4.320615	0.836308
+1.296452	4.491290	0.850484
+1.299860	6.307378	0.869755
+1.739548	4.398404	0.866506
+1.820364	2.390727	0.846545
+2.143789	1.369158	0.869158
+2.203188	3.227536	0.864855
+2.316842	1.180351	0.848421
+2.379250	1.824600	0.870000
+2.445319	3.295319	0.853404
+2.460857	0.950429	0.858429
+2.533789	5.812484	0.860248
+2.847848	1.960000	0.855696
+2.920777	0.050971	0.855243
+3.476173	3.863086	0.858272
+3.562095	5.394775	0.870133
+3.662546	4.487056	0.868488
+3.895920	1.723731	0.864925
+3.885516	3.349008	0.869405
+3.906026	0.689423	0.873429
+1.293172	1.526621	0.866276
+1.281688	3.230130	0.863636
+1.285058	5.057965	0.873256
+1.610789	3.921842	0.861579
+1.662078	0.334416	0.867662
+2.208000	3.591231	0.867385
+2.320694	1.550417	0.862083
+2.352879	0.491629	0.876402
+2.563237	2.743734	0.873817
+2.623462	1.873077	0.860577
+3.510606	1.536364	0.861818
+1.621017	1.161864	0.868305
+1.656279	1.985581	0.875349
+1.685665	3.674162	0.886069
+2.064332	2.429170	0.887148
+2.302759	5.397085	0.888621
+2.427705	2.495738	0.867049
+2.700635	0.150000	0.877460
+2.937527	5.810430	0.879247
+3.138703	0.616444	0.885649
+3.177879	3.224545	0.874444
+3.507094	2.474926	0.882118
+1.264448	0.979178	0.905042
+1.641003	0.599027	0.903186
+1.958750	3.250500	0.875500
+2.284030	2.305970	0.879104
+2.737640	5.954944	0.884719
+2.828667	4.147000	0.882000
+3.547773	0.535547	0.896761
+3.887363	3.622239	0.891294
+3.909011	4.569780	0.884066
+3.940263	1.468684	0.890526
+1.253410	6.032605	0.907241
+1.625374	2.241905	0.911871
+1.622440	4.635833	0.903333
+2.078704	2.168889	0.891481
+2.320027	2.874521	0.902986
+2.358804	5.992919	0.904976
+2.417100	4.796283	0.907063
+2.774314	5.044216	0.895196
+2.901889	3.355056	0.898611
+3.000382	1.095038	0.890916
+3.532148	6.196242	0.901611
+3.568757	1.035444	0.898757
+3.915479	5.668537	0.911755
+3.916205	6.058554	0.902590
+3.943674	0.168295	0.906023
+1.245827	0.711575	0.906299
+1.633989	2.975426	0.913936
+1.998702	5.681985	0.906489
+2.249545	4.605227	0.899886
+2.344211	6.250752	0.905338
+2.520085	5.037627	0.909576
+2.629735	3.707743	0.917168
+2.796157	0.483843	0.911065
+2.852662	3.842230	0.909281
+2.965039	3.091836	0.920664
+2.975780	1.418688	0.917589
+3.199946	1.266965	0.922195
+3.569256	4.878837	0.912140
+3.558571	5.131224	0.902653
+3.942876	3.881046	0.912222
+3.955171	2.686844	0.921217
+1.235251	3.672040	0.926488
+1.223385	4.813231	0.913692
+1.222681	5.767101	0.924275
+1.467032	2.747385	0.926042
+1.484718	0.822077	0.926232
+1.579177	5.140823	0.925127
+2.101038	6.019937	0.930692
+2.746882	5.460000	0.921118
+2.790596	1.666358	0.924503
+2.960647	6.077314	0.937627
+3.058412	2.082575	0.926223
+3.139735	5.320596	0.923576
+3.194096	2.945000	0.927711
+3.599104	2.952939	0.932616
+3.926241	6.387092	0.921135
+3.969286	1.005000	0.906429
+3.968000	2.232333	0.916500
+1.223284	0.286418	0.920448
+1.216129	2.753226	0.915806
+1.219004	5.307229	0.933939
+1.517917	5.647188	0.926979
+1.604080	3.430800	0.932800
+2.000000	4.640552	0.935521
+2.062077	0.040831	0.932971
+2.120691	6.368351	0.923298
+2.669925	0.813284	0.930672
+2.859073	4.746537	0.928683
+3.009104	4.522127	0.931642
+3.522596	2.210894	0.936255
+3.952545	5.216545	0.919636
+2.102935	0.413478	0.947754
+2.160833	2.668854	0.933646
+2.197617	0.917584	0.945336
+2.295225	0.241892	0.935225
+2.340513	5.653718	0.933974
+2.898299	2.515910	0.949433
+3.136286	5.645143	0.939657
+3.248462	4.161026	0.937179
+3.633443	0.782350	0.941366
+3.665512	3.475354	0.943780
+3.966357	4.817214	0.933786
+1.203127	1.761273	0.950873
+1.197041	2.108136	0.959675
+1.198472	3.008908	0.953450
+1.554718	4.157534	0.965147
+1.561045	5.920000	0.938955
+2.081849	5.252798	0.958491
+2.709218	3.189609	0.956034
+2.794648	1.230000	0.958592
+3.029576	4.016186	0.944576
+3.073704	3.737593	0.947963
+3.347132	4.410441	0.951838
+3.582606	5.926649	0.948670
+3.591888	3.224847	0.951480
+3.587091	5.654390	0.965896
+1.177792	3.923766	0.953117
+1.496143	4.414714	0.949429
+1.525031	6.176180	0.968354
+1.729424	4.870373	0.968339
+2.665758	1.448182	0.948333
+3.006909	1.800182	0.963333
+3.154424	0.305707	0.968822
+3.156456	1.603291	0.953038
+3.198233	5.064224	0.970517
+3.263884	0.052416	0.968807
+3.645668	1.718704	0.964615
+3.732841	0.033125	0.960227
+3.949706	2.943971	0.949265
+4.015778	0.408444	0.943778
+4.014265	1.241176	0.949412
+1.181769	1.238435	0.965034
+1.166528	3.423194	0.964028
+1.295723	4.267803	0.971272
+1.488462	3.171209	0.967582
+1.962958	3.657324	0.957042
+2.423423	3.518255	0.964094
+2.522401	2.076095	0.975515
+2.660000	3.986567	0.958209
+3.228920	2.395634	0.968263
+3.664131	0.306239	0.982165
+1.523655	1.506948	0.985542
+1.891134	1.993763	0.981546
+1.934558	4.250726	0.992177
+1.963838	0.807374	0.973636
+2.166076	4.845204	0.991090
+2.542938	1.162147	0.980395
+2.641094	2.519688	0.975469
+2.901918	0.263425	0.972466
+3.029474	4.261228	0.975263
+3.092979	2.718723	0.969787
+3.228386	6.131713	0.999114
+3.254305	3.897219	0.988874
+3.345795	5.506705	0.980000
+3.992872	4.125213	0.972660
+1.468807	4.911684	0.995579
+1.476220	5.396457	0.994685
+1.860000	3.054098	0.984918
+1.913974	1.345364	0.990066
+1.932464	5.454493	0.985217
+2.141969	1.937480	0.991260
+2.320667	5.153333	0.977333
+2.911980	5.226040	0.985248
+3.114300	0.859900	0.983100
+3.656426	3.739279	0.999459
+3.682578	4.245781	0.985781
+4.031020	3.180612	0.976327
+1.134942	4.599826	1.005581
+1.807582	5.242008	1.002664
+1.868811	0.223216	1.010617
+2.032481	1.117786	1.010840
+2.315714	0.014405	1.008452
+2.394439	4.184439	0.999112
+2.730625	5.731625	0.988375
+3.102121	4.755606	0.990455
+3.550635	2.701111	1.002910
+3.705417	1.460000	1.006250
+3.751892	2.308919	0.985676
+4.031121	5.446379	0.997500
+4.054758	2.454516	0.999355
+1.128452	2.395000	1.001786
+1.125000	5.531724	1.002069
+1.147391	0.504239	1.004891
+1.388894	4.652304	1.017235
+1.424488	3.841417	1.007953
+1.452677	0.323780	1.008504
+1.527427	2.468299	1.015975
+1.535000	6.400000	0.990000
+1.923284	6.215654	1.020765
+1.965618	1.738146	1.011124
+2.000923	2.847923	1.014077
+2.073362	3.433491	1.013879
+2.373387	1.347661	1.011935
+2.386604	3.112830	1.000377
+3.084390	3.495122	0.997073
+3.334043	4.847518	1.006667
+3.354638	5.844493	1.004493
+4.040190	4.383641	1.020788
+4.054638	2.013957	1.011489
+1.463051	1.779153	1.010000
+1.753936	2.778617	1.013830
+1.863553	0.508711	1.024654
+2.569657	0.531486	1.021943
+2.574615	0.010000	1.018462
+2.614414	4.313862	1.025448
+2.880625	0.700063	1.019688
+3.291429	2.147500	1.006786
+3.451975	1.978642	1.013457
+4.078571	1.640238	1.015238
+1.105259	6.259397	1.030690
+1.467759	2.075862	1.021638
+1.778759	1.550483	1.033862
+2.002813	3.987188	1.015313
+2.184810	4.398228	1.026835
+2.425111	4.488278	1.033000
+2.444648	0.769859	1.025211
+2.512006	5.314904	1.042866
+2.657029	6.349086	1.028114
+2.776438	2.730959	1.016986
+2.821739	0.984203	1.030145
+2.895489	6.382030	1.033759
+2.964153	4.958602	1.041695
+3.121290	5.891720	1.023333
+3.344231	1.454167	1.031731
+3.449132	1.219589	1.032100
+3.506912	0.107353	1.021029
+3.697500	1.198906	1.025469
+3.707475	4.697273	1.030657
+4.044763	5.872145	1.037326
+4.081846	0.825385	1.018923
+1.106707	1.485122	1.028537
+1.097320	5.033608	1.035464
+1.711202	1.809457	1.042907
+1.705263	5.525724	1.038750
+1.711566	3.235301	1.037349
+1.784030	1.093433	1.035224
+1.911446	5.877107	1.045537
+1.923237	2.593816	1.046184
+1.961901	5.028521	1.038873
+2.148022	1.571758	1.031209
+2.150877	5.535263	1.037544
+2.215120	0.650756	1.043643
+2.786273	2.106182	1.039909
+2.868906	3.616875	1.040391
+2.971798	5.471629	1.039438
+3.273469	1.036531	1.023673
+3.401111	0.328254	1.028571
+3.700880	1.968160	1.035520
+3.721598	6.119315	1.048311
+3.731921	3.991854	1.046291
+3.774390	0.974146	1.028537
+4.076887	3.438344	1.039205
+1.458144	3.591237	1.053608
+2.468173	2.330288	1.042019
+2.481825	1.580079	1.059802
+2.562054	2.936811	1.048595
+2.727699	4.552773	1.061475
+3.335229	3.130065	1.044837
+3.355696	3.438386	1.059272
+3.353281	5.256979	1.056719
+3.402579	0.717557	1.049321
+3.387769	6.350808	1.054115
+3.807518	3.127021	1.045745
+4.086526	3.701579	1.042737
+1.075000	4.112500	1.055385
+1.078333	4.355000	1.048889
+1.343299	2.302577	1.052577
+2.146349	3.063983	1.067967
+2.168985	5.794708	1.067600
+2.646436	4.833317	1.060149
+2.684048	0.310357	1.051905
+3.003115	0.489508	1.055246
+3.000920	2.299920	1.073040
+3.306829	2.634512	1.054878
+3.359425	1.720345	1.055402
+3.762390	2.549044	1.070000
+4.086694	6.129008	1.061983
+1.409247	0.574603	1.071423
+1.415899	1.281079	1.066978
+1.542207	1.036207	1.063793
+1.759046	3.960871	1.070913
+2.254000	2.151273	1.057818
+2.311180	3.944438	1.079551
+2.757742	1.863871	1.059677
+3.741739	5.469217	1.065130
+4.123350	0.045583	1.069369
+4.102563	4.650094	1.081313
+1.069763	0.777515	1.088876
+1.383464	5.171508	1.086927
+1.816339	4.535268	1.076339
+2.310297	1.106441	1.090424
+2.696045	6.091921	1.086384
+2.812427	0.058074	1.090923
+3.219877	1.920370	1.072222
+3.776679	2.824723	1.090000
+3.947168	5.034740	1.083353
+1.062269	1.039244	1.085462
+1.055388	1.927397	1.096895
+1.312022	0.120815	1.100730
+1.368933	3.352135	1.094663
+1.410439	5.798596	1.091140
+1.438595	2.953388	1.083306
+1.673463	1.318382	1.101974
+1.770277	2.383391	1.092907
+1.821115	3.462446	1.092086
+2.190444	3.713556	1.091444
+2.334571	2.555276	1.093436
+2.434861	5.820025	1.104810
+2.524808	1.835385	1.076923
+2.586500	5.563400	1.080500
+3.137896	6.375648	1.105043
+3.260388	0.512816	1.083981
+3.409390	2.889512	1.085488
+3.451176	4.225000	1.083971
+4.016903	0.600265	1.089912
+4.136770	1.069503	1.095590
+4.127400	3.944200	1.078000
+4.142364	2.240909	1.082182
+1.050250	0.294500	1.097500
+1.046941	2.731647	1.093176
+1.049630	3.244321	1.098580
+1.047273	3.737727	1.089394
+1.076241	6.011879	1.110709
+1.602805	0.115732	1.099512
+1.754380	0.851570	1.102562
+2.216496	6.175474	1.099416
+2.287222	1.767460	1.100952
+2.453077	6.129744	1.092308
+2.454624	3.727688	1.107052
+2.509065	3.315234	1.094393
+2.750714	3.404643	1.096786
+3.413152	3.729565	1.096304
+3.482273	3.973364	1.100909
+3.543064	4.469306	1.103179
+3.689076	5.017395	1.112227
+3.783444	0.500927	1.102252
+4.113622	6.383214	1.108724
+4.122259	5.229778	1.105630
+4.134774	2.855827	1.103835
+1.035225	5.739075	1.128575
+1.315020	2.638327	1.114286
+1.327222	4.052698	1.105476
+1.975623	2.200038	1.118717
+2.160670	4.157113	1.111495
+2.257073	3.291463	1.096341
+2.660528	5.097520	1.116341
+2.837485	2.954417	1.109141
+2.960945	5.724800	1.122109
+3.229266	4.574321	1.122283
+3.601795	5.271197	1.103590
+3.916301	1.817534	1.110342
+4.153655	1.369379	1.108759
+4.160659	0.300879	1.102967
+1.027251	4.803555	1.124882
+1.318231	6.387846	1.116846
+1.316667	1.568000	1.113111
+1.669193	5.776278	1.132377
+1.712500	4.312917	1.108542
+1.731586	6.035655	1.123103
+1.954286	3.233214	1.111071
+2.116400	0.215326	1.132189
+2.305795	0.414318	1.127008
+2.420592	4.949079	1.119934
+2.462093	0.193811	1.130154
+2.576349	0.949365	1.110635
+2.749035	2.349649	1.111228
+2.835813	1.504581	1.125567
+3.147434	3.286903	1.115752
+3.474736	6.086504	1.134085
+3.824179	0.754478	1.105821
+1.042597	0.036806	1.141403
+1.015289	2.982975	1.133967
+1.304578	1.923494	1.120843
+1.676667	0.349706	1.126373
+1.698793	6.281379	1.117759
+1.922314	4.791616	1.137118
+2.160328	1.308689	1.117541
+2.160164	2.373115	1.116885
+2.373435	6.371174	1.128217
+2.732892	3.820482	1.123735
+2.809591	4.094737	1.126374
+3.057020	1.052879	1.138990
+3.085870	2.533478	1.116087
+3.787529	5.723435	1.144635
+3.808516	4.475137	1.143104
+3.842378	3.523066	1.140372
+3.856058	2.141923	1.135769
+3.909710	1.369275	1.122899
+4.181786	1.825357	1.123214
+1.008873	3.494225	1.134789
+1.329345	0.814940	1.143155
+1.369534	6.052007	1.144731
+1.682694	3.687917	1.154250
+1.720263	2.089868	1.142303
+2.274423	5.321538	1.134423
+2.557638	2.690236	1.137165
+2.987347	3.866854	1.156502
+3.074758	0.084573	1.151293
+3.220732	4.301707	1.135366
+3.498224	0.966044	1.147383
+3.840977	6.325263	1.139699
+3.881721	0.268605	1.144605
+3.872857	3.791286	1.143714
+4.174059	4.190792	1.139109
+1.276575	4.855205	1.142329
+1.300854	1.073293	1.146951
+1.930897	0.029013	1.159193
+1.957391	5.642120	1.152446
+2.750941	5.347569	1.157020
+2.903973	3.208447	1.154612
+2.958254	1.973175	1.137143
+3.085391	3.020348	1.145130
+3.096380	1.454389	1.158643
+3.495410	2.499836	1.134918
+3.529241	0.514388	1.162110
+4.171959	4.923574	1.158179
+1.005208	1.289396	1.163509
+0.992558	5.205814	1.150233
+1.241750	3.552500	1.153750
+1.572026	2.685294	1.157908
+1.577356	4.517788	1.159808
+1.691725	2.970176	1.172817
+1.718028	5.053216	1.172653
+2.100571	4.595842	1.173451
+2.106222	6.383056	1.168333
+2.582894	1.360547	1.173473
+3.106418	0.685672	1.152239
+3.119667	5.242000	1.157778
+3.174783	4.066957	1.153043
+3.525658	4.810000	1.155000
+3.553691	3.085168	1.158523
+3.847615	5.258231	1.153692
+4.177056	3.117850	1.160467
+0.981475	2.277213	1.166393
+1.670117	0.614869	1.179155
+2.359342	2.836447	1.156974
+2.353275	5.568908	1.180387
+2.544195	3.976839	1.175000
+2.675947	0.722392	1.175482
+2.893846	5.970962	1.162212
+3.204839	3.617258	1.156129
+3.219476	5.713886	1.175764
+3.412326	2.273488	1.161395
+3.542567	1.587647	1.173422
+3.537478	5.818457	1.186647
+3.599783	6.319058	1.163188
+3.994650	2.637899	1.187395
+4.187927	5.699634	1.167439
+1.258122	3.126396	1.180305
+1.281478	4.483024	1.187354
+1.989054	0.661892	1.182568
+2.123402	2.691392	1.185155
+2.200373	5.079814	1.187578
+2.460388	4.695874	1.183350
+2.923806	1.266269	1.183731
+2.969677	2.753548	1.169032
+3.143390	1.710847	1.170678
+3.239277	1.234980	1.189518
+3.407509	5.036194	1.192076
+3.573355	3.546513	1.184770
+3.897380	4.793464	1.191054
+3.898947	0.019649	1.193860
+0.976316	0.520263	1.172632
+0.966866	2.522687	1.184627
+0.972500	4.528889	1.185208
+0.973534	5.461802	1.196007
+1.216288	5.338595	1.197391
+1.268571	0.365824	1.186044
+1.463746	4.275549	1.199634
+1.554854	2.274369	1.177767
+1.973971	1.490294	1.183529
+1.989829	0.932457	1.199010
+2.047612	5.378209	1.181194
+2.281799	0.866296	1.193228
+2.677113	5.860928	1.186495
+2.711143	1.138429	1.178429
+2.794024	0.486402	1.187805
+3.041176	6.157529	1.179412
+3.134706	2.116765	1.178529
+3.483315	5.547983	1.200580
+3.553636	1.841091	1.180364
+4.195686	5.460196	1.178627
+4.219247	2.444384	1.191096
+4.232700	0.526000	1.188200
+1.233130	2.864783	1.200522
+1.255333	3.823367	1.211367
+1.561583	1.646834	1.209151
+1.948912	3.704765	1.207206
+2.022527	6.050989	1.189341
+2.322781	3.513841	1.206424
+2.655697	3.126855	1.206439
+2.908750	1.737000	1.185000
+2.987224	4.492571	1.207510
+3.203176	2.811176	1.196118
+3.260543	0.871628	1.198450
+3.605191	2.126565	1.200916
+3.645474	0.021368	1.196421
+3.699377	3.300649	1.216831
+3.863871	1.131290	1.211548
+3.932133	4.033867	1.191600
+0.961502	1.554725	1.220733
+1.538750	1.920240	1.207596
+1.547023	3.915907	1.218605
+1.670119	4.777774	1.219139
+2.389449	2.001356	1.208771
+2.674101	1.688561	1.208273
+2.937399	4.765507	1.219696
+3.242438	0.294492	1.228600
+3.362075	0.053942	1.216307
+3.873204	5.962039	1.206311
+3.934674	2.375761	1.206522
+3.942133	2.992267	1.210267
+4.238052	1.592792	1.209481
+4.214545	4.453896	1.207532
+4.242757	0.852991	1.217804
+1.161917	1.727083	1.216667
+1.175139	2.138333	1.213472
+1.512676	3.168559	1.226324
+1.587367	3.440253	1.232937
+1.921019	1.237321	1.231434
+1.922661	4.099495	1.227431
+2.328993	4.337114	1.215973
+2.435750	0.619625	1.223625
+2.579707	2.188787	1.223138
+2.584300	3.537000	1.208200
+2.790947	2.585758	1.221061
+2.780000	4.336932	1.211364
+2.901224	5.137343	1.228706
+2.928966	0.850517	1.216983
+2.986050	3.460784	1.223697
+3.005648	4.230741	1.220741
+3.151056	4.996056	1.218732
+3.235876	5.454948	1.225000
+3.223860	5.985175	1.219298
+3.542931	0.252291	1.235739
+3.757184	4.219223	1.229320
+3.944364	5.518682	1.218864
+3.963382	3.260676	1.219710
+4.220690	5.938966	1.207069
+4.243544	3.621772	1.213165
+4.251184	2.054342	1.221513
+0.935085	4.010000	1.225085
+1.221944	2.420833	1.223889
+1.244286	1.366310	1.223810
+1.796533	5.373443	1.239552
+1.872292	2.773125	1.232431
+1.914118	1.924118	1.222000
+1.952243	4.373946	1.238135
+2.106504	3.917154	1.225772
+3.197087	2.348058	1.230388
+3.608202	0.748652	1.229213
+3.817568	1.611171	1.223694
+4.241705	3.362171	1.224961
+1.200744	0.608558	1.244233
+1.195580	4.232536	1.251812
+1.441181	5.463386	1.239055
+1.968723	0.401773	1.243546
+2.081929	1.713655	1.240508
+2.133590	2.031410	1.229103
+2.245104	5.972917	1.236771
+2.289583	1.547946	1.247470
+2.561310	0.409524	1.236786
+2.977692	0.320070	1.232937
+3.987723	0.897991	1.245134
+0.926601	4.273861	1.262673
+0.918961	5.001558	1.246234
+0.928209	6.184142	1.254627
+1.209368	5.074349	1.261152
+1.464815	4.984228	1.258981
+1.822110	1.688165	1.254862
+1.957462	5.157868	1.258528
+1.968053	2.441947	1.244956
+2.235692	4.817826	1.254901
+2.388850	3.144985	1.255811
+2.441931	5.168571	1.256757
+2.529577	2.463169	1.250000
+2.562342	4.457627	1.262975
+2.594444	6.251032	1.252222
+2.784205	5.587273	1.239545
+2.842091	6.269682	1.254136
+3.239173	3.850000	1.246241
+3.300349	4.800233	1.248023
+3.362906	2.042075	1.255434
+3.408627	3.270196	1.246078
+3.682017	2.371335	1.266307
+4.239324	6.192324	1.260206
+0.915054	2.063441	1.258495
+1.562464	0.838261	1.253478
+2.334837	2.272561	1.266748
+3.288995	6.235582	1.270767
+3.458150	1.357500	1.269150
+3.706593	1.391209	1.252747
+4.272817	2.683803	1.249859
+1.234016	5.852582	1.278484
+1.417994	4.694922	1.282821
+1.556632	5.239895	1.270895
+1.671720	4.127204	1.261183
+2.016038	3.446462	1.277962
+2.348333	1.292333	1.257333
+2.633853	1.935229	1.273211
+2.698684	4.696842	1.263421
+3.307324	1.561127	1.261549
+4.014045	1.988427	1.261461
+4.273681	4.710833	1.275417
+0.900545	2.820182	1.271818
+0.902540	3.668889	1.266667
+0.904518	1.805361	1.286807
+0.910569	5.917967	1.285285
+1.131903	6.365000	1.288419
+1.489452	0.247945	1.287705
+1.486585	1.401220	1.284146
+1.558714	6.388857	1.277286
+1.775616	3.240616	1.275205
+1.771563	1.037969	1.274688
+1.897778	6.275641	1.284217
+2.661915	2.869574	1.268298
+2.729163	0.224412	1.293643
+2.810000	3.649752	1.288515
+3.420698	2.733721	1.267209
+3.776604	1.938679	1.265660
+3.984275	6.180290	1.279638
+4.277500	4.006394	1.285433
+0.905478	0.722783	1.286261
+0.897876	3.334115	1.293584
+0.910754	0.214563	1.296310
+1.192807	3.352544	1.283333
+1.222201	5.583082	1.290629
+1.458500	2.481231	1.297269
+1.553254	1.148402	1.293669
+1.698462	0.010000	1.280000
+1.812785	0.211646	1.289367
+1.922767	3.028735	1.294269
+2.053412	5.829529	1.288118
+2.129537	3.200556	1.299722
+2.169713	2.926338	1.301083
+2.486207	1.098103	1.291853
+2.533433	5.411045	1.287687
+2.916073	2.165215	1.295446
+2.971407	5.406422	1.298593
+3.404677	4.357419	1.282419
+3.433929	4.603750	1.277321
+3.613864	1.152273	1.288333
+3.653990	2.641347	1.294301
+3.678217	4.659720	1.293881
+3.707610	3.925975	1.287547
+4.035810	0.413429	1.282286
+4.097035	3.814292	1.285531
+4.305370	1.105278	1.294537
+0.921429	0.985979	1.306455
+1.746818	2.555955	1.303545
+2.151045	1.115771	1.298259
+2.344308	4.087231	1.289077
+2.447355	1.759669	1.298347
+2.488227	5.997608	1.312928
+3.434656	5.299246	1.305180
+3.690606	5.418636	1.301818
+3.729651	6.156483	1.308779
+4.085942	0.156957	1.311957
+4.302000	2.935000	1.303063
+0.874149	4.724149	1.310957
+1.140308	2.654954	1.322923
+1.158462	4.679670	1.307308
+1.363647	6.250294	1.314588
+1.479080	0.507701	1.307356
+2.175613	0.547301	1.319724
+2.563146	5.666067	1.301798
+2.599423	4.185577	1.317356
+2.975263	2.433474	1.301895
+3.529494	4.139747	1.301013
+3.999146	4.245244	1.299390
+4.021944	1.482847	1.312083
+4.049314	1.735490	1.310098
+4.312768	0.318839	1.322202
+4.317212	1.372035	1.321327
+0.900000	6.400000	1.290000
+1.450000	0.010000	1.301818
+1.448333	5.699333	1.312833
+1.615981	6.151646	1.328196
+1.787560	3.892337	1.327629
+1.834861	4.601181	1.316389
+2.498667	0.841778	1.308667
+2.710398	4.952898	1.336748
+3.132793	1.916170	1.335559
+3.219355	2.592396	1.323041
+3.231739	3.429435	1.328696
+3.358132	2.968901	1.317143
+3.658475	5.166949	1.324322
+4.039680	3.500581	1.331512
+4.086304	1.233986	1.319130
+4.324355	1.803710	1.317742
+0.867500	3.070938	1.316250
+0.869730	5.667622	1.331351
+1.158635	1.151683	1.343714
+1.179364	0.173410	1.328439
+1.409143	2.746571	1.319714
+1.656441	5.576356	1.323390
+1.825833	0.775000	1.324333
+1.826612	2.229752	1.329174
+2.137075	5.594318	1.341281
+2.324439	3.834081	1.333184
+2.389058	2.658768	1.331522
+2.581344	3.763226	1.330538
+2.739205	6.052159	1.325568
+2.992016	0.555806	1.322177
+3.192179	3.159615	1.341325
+3.249042	0.546518	1.337029
+3.381086	3.644434	1.339095
+3.740415	0.936062	1.337306
+3.865490	5.021863	1.322451
+3.966364	6.395455	1.319091
+4.036400	4.614044	1.336978
+4.078589	0.665394	1.331992
+4.111341	2.253171	1.323537
+4.270000	6.400000	1.300000
+4.308716	5.305405	1.331757
+1.149106	0.854503	1.346126
+1.357895	2.238421	1.338421
+1.396420	3.588210	1.338827
+2.164020	6.189122	1.355898
+2.200957	2.485826	1.345391
+2.279438	0.237871	1.343373
+2.307586	4.560575	1.339483
+2.727000	0.913500	1.330000
+2.768797	3.956015	1.360301
+3.605538	2.901474	1.340518
+3.644286	4.914945	1.339451
+3.824559	0.695441	1.336912
+3.845833	2.806042	1.336667
+4.315200	4.261920	1.333520
+4.313750	5.044728	1.345707
+1.156528	6.096424	1.360000
+1.377477	4.066495	1.353925
+1.384706	0.975588	1.348088
+1.704571	4.378619	1.349333
+1.839889	6.030667	1.346667
+1.875227	4.927879	1.359318
+2.084819	2.243261	1.363080
+2.126173	1.371296	1.352531
+2.157342	3.651266	1.348987
+2.344268	5.771715	1.358410
+2.730000	3.340859	1.358591
+3.060522	3.692450	1.351044
+3.376984	1.788492	1.352738
+3.457834	3.898344	1.351529
+3.738717	0.450831	1.363302
+4.078687	5.148485	1.344545
+1.084583	0.408542	1.355729
+1.135497	3.637016	1.362356
+1.244487	1.955513	1.356282
+1.335696	1.603882	1.357637
+1.457939	5.945420	1.357939
+1.729015	1.359091	1.355985
+2.135015	4.216481	1.369120
+2.758523	1.415485	1.362700
+2.837645	5.802258	1.369613
+2.848545	3.035818	1.347636
+3.036848	5.651630	1.350652
+3.181591	4.399091	1.350227
+3.281456	4.145890	1.374919
+3.404486	2.420841	1.353551
+3.630000	4.404839	1.357419
+3.655556	5.664222	1.364000
+3.775558	0.175012	1.373753
+4.091207	2.804310	1.351552
+4.326549	5.560070	1.359155
+4.344778	0.665167	1.365167
+4.351406	2.237656	1.355156
+0.847818	1.228242	1.374000
+1.377763	2.996484	1.374338
+1.582590	2.116595	1.384269
+1.657879	2.796364	1.372828
+1.713889	0.433278	1.368389
+1.790446	3.553705	1.371473
+2.046124	0.109018	1.380233
+2.233437	5.276000	1.382000
+2.444154	4.926410	1.377436
+2.470517	3.368793	1.369598
+2.526916	1.529626	1.364579
+2.719306	2.353889	1.357500
+2.864492	1.898984	1.373743
+3.023582	4.027575	1.376157
+3.129722	4.659361	1.374972
+3.221282	1.051795	1.365641
+3.384872	5.723077	1.368718
+3.420748	5.985596	1.384709
+3.673100	1.740900	1.373100
+4.360917	0.051835	1.370000
+4.350606	3.778182	1.360606
+0.841000	2.608438	1.384438
+1.089630	2.986173	1.381687
+1.382932	0.724060	1.384286
+1.729583	1.895000	1.371111
+2.225150	1.873593	1.404012
+2.793818	4.511818	1.376182
+2.949115	0.122478	1.378496
+2.984740	6.023149	1.389513
+3.059641	6.287541	1.392238
+3.078446	2.930052	1.390104
+3.112981	0.775321	1.388226
+3.717143	6.391905	1.369048
+3.883071	3.700357	1.380857
+4.346309	3.184497	1.387349
+0.844133	0.483265	1.391173
+0.826000	3.870621	1.392828
+0.829286	4.488714	1.385857
+0.963611	2.389583	1.383472
+1.056606	5.241946	1.400317
+1.082564	3.890000	1.391731
+1.098129	4.437419	1.386516
+1.689801	5.830618	1.404967
+1.883774	5.639057	1.388962
+2.108968	0.797460	1.391706
+2.400566	6.292925	1.387453
+2.430973	2.912324	1.389189
+2.505862	0.143218	1.382874
+2.859053	2.783158	1.394105
+3.071224	5.173017	1.446753
+3.783445	2.159328	1.382773
+3.870891	4.432772	1.390000
+3.878529	5.775735	1.380588
+4.089015	5.650099	1.388670
+4.084909	5.392000	1.384182
+2.000500	2.634500	1.398500
+2.046866	4.727604	1.420346
+2.671796	0.564012	1.394910
+2.970301	4.954060	1.406466
+3.005614	1.461754	1.395614
+3.035809	1.207794	1.404118
+3.376698	0.763396	1.396604
+3.576977	1.961860	1.387442
+3.569504	3.149917	1.404628
+3.673413	5.915449	1.399940
+3.870000	5.277450	1.405839
+4.095899	4.862158	1.396619
+4.097667	3.068128	1.415026
+4.357117	4.510541	1.399369
+4.366977	2.510930	1.392326
+1.050526	1.380526	1.401447
+1.415051	3.335354	1.412475
+1.606606	3.723761	1.403303
+2.205000	6.400000	1.385000
+2.629545	2.674697	1.398333
+2.860000	1.641778	1.399333
+2.962241	3.241207	1.400000
+3.167941	5.842059	1.399265
+3.519714	3.419643	1.407786
+3.533788	0.053515	1.418703
+3.630476	3.667937	1.396032
+3.819254	3.074319	1.424859
+4.123897	2.549632	1.410221
+4.292117	5.823396	1.424528
+0.807556	2.212000	1.411778
+0.807763	5.174474	1.414079
+0.806409	5.432873	1.429282
+1.053097	4.886940	1.424291
+1.752398	5.149240	1.418363
+1.986961	5.359510	1.421029
+2.396250	0.447955	1.410795
+2.723195	5.304436	1.427594
+2.775779	1.144805	1.427955
+3.137885	1.655962	1.408269
+3.198026	2.169828	1.417854
+3.242581	1.373024	1.420282
+3.498679	0.534528	1.409811
+3.507470	0.969398	1.416506
+3.512042	6.241300	1.429443
+3.774858	3.461862	1.427085
+4.392708	0.914792	1.413333
+0.812923	1.482974	1.434308
+1.375444	4.365000	1.424889
+1.700197	3.048816	1.430724
+1.931885	0.573977	1.443977
+1.926968	1.515968	1.439258
+2.224978	3.416211	1.438326
+2.307626	0.958131	1.435455
+2.523114	4.662216	1.430120
+2.663684	6.390921	1.426053
+2.855479	0.735205	1.425548
+2.959091	0.970000	1.428030
+3.498934	1.561726	1.427005
+3.524577	2.209055	1.433532
+3.918663	3.961089	1.446386
+4.373262	3.455638	1.436099
+4.393878	2.010408	1.422857
+1.062055	2.156043	1.455368
+1.307524	5.321768	1.452958
+1.386154	3.824038	1.432500
+1.624685	0.671958	1.432448
+1.634444	4.911111	1.439753
+1.668833	1.595667	1.442722
+2.214474	5.017456	1.442018
+2.365397	5.518254	1.429524
+2.396709	3.608354	1.435570
+2.709792	2.116458	1.431250
+2.854478	0.395970	1.436567
+2.959224	4.347328	1.434310
+3.850247	1.293333	1.440988
+3.896721	6.014262	1.439672
+4.135205	6.029452	1.426164
+0.794451	4.920751	1.450751
+0.789545	1.963636	1.440000
+1.046000	5.488667	1.436000
+1.315153	0.374133	1.448316
+1.612015	4.608408	1.459204
+1.920444	0.949111	1.444667
+2.020000	3.986737	1.446316
+2.355709	0.699459	1.461047
+3.291993	0.155559	1.453706
+3.448842	4.791053	1.451526
+3.453307	5.074213	1.457387
+3.844691	4.802438	1.462346
+3.934620	1.057468	1.457911
+4.132540	4.398254	1.443810
+4.141161	0.895488	1.462665
+4.158165	1.917982	1.447431
+4.375161	6.080000	1.456129
+1.034009	1.632026	1.470881
+1.083352	5.739066	1.458791
+1.664194	2.363963	1.464885
+2.076054	4.456667	1.459660
+2.276301	2.104384	1.455068
+2.521081	3.985135	1.461351
+2.546716	1.290235	1.474604
+2.565544	3.128601	1.457358
+2.647702	1.761925	1.454783
+3.105244	0.339553	1.459268
+3.228527	4.922558	1.463721
+3.413919	1.191757	1.454865
+3.483619	5.517143	1.458571
+3.712296	4.118667	1.458741
+3.758879	1.526034	1.457845
+3.860100	5.536567	1.466667
+4.220435	1.632609	1.455109
+4.403351	2.752577	1.467268
+1.041712	4.145582	1.475479
+1.184957	2.443043	1.467478
+1.361250	4.864231	1.471731
+1.560867	4.207052	1.472543
+1.602414	0.100172	1.457586
+1.686452	0.903226	1.455484
+1.931212	3.245051	1.467172
+1.963409	3.736439	1.477652
+2.078350	0.353786	1.463786
+2.173713	1.621435	1.477848
+2.182375	5.938294	1.482074
+2.421783	4.377984	1.470698
+2.500455	2.231250	1.460795
+2.630492	3.550492	1.456393
+2.714774	5.567806	1.473613
+2.817516	4.755294	1.474444
+3.167261	5.474331	1.479904
+3.209437	6.098451	1.470423
+3.900410	1.866803	1.477336
+0.772708	2.837708	1.470208
+0.780220	4.257665	1.493901
+0.772667	6.136833	1.470833
+0.865840	3.540720	1.475040
+1.062985	0.631306	1.481903
+1.492881	1.762203	1.472373
+1.652105	5.376374	1.478187
+1.904151	4.266038	1.464717
+1.925045	1.778198	1.473784
+1.985544	1.196361	1.489592
+2.034770	2.011925	1.486109
+2.497372	1.972244	1.495160
+2.593307	6.172996	1.489416
+2.822593	2.544815	1.478272
+2.914925	3.488910	1.487744
+3.481295	2.622302	1.481295
+3.623568	0.749296	1.491044
+3.604557	1.332911	1.476456
+3.963407	3.290296	1.473704
+4.119423	4.120962	1.472692
+4.135503	6.272011	1.482328
+4.182327	0.486449	1.495163
+4.392415	4.811220	1.490707
+0.767037	5.896852	1.480370
+0.975932	0.052091	1.497338
+1.040000	1.890213	1.481915
+1.237054	3.171550	1.490388
+1.371509	0.128679	1.479623
+1.456471	5.527206	1.477941
+1.493114	5.120830	1.493806
+1.831138	0.017886	1.494797
+1.922759	2.860172	1.494741
+1.937105	2.412105	1.487105
+2.207647	2.737843	1.476078
+2.294492	1.213136	1.483390
+2.598608	0.341772	1.482025
+2.603097	5.828344	1.500903
+3.143769	2.414154	1.492846
+3.226022	3.914624	1.488065
+3.285193	2.796941	1.497969
+3.961523	2.361695	1.501351
+4.001818	2.099697	1.479848
+4.184000	3.654000	1.476286
+0.770244	0.706707	1.495976
+0.990336	3.218403	1.499412
+0.993832	6.247665	1.503293
+1.415000	1.205313	1.499375
+1.515524	6.316643	1.498112
+1.674980	3.305451	1.502941
+1.717576	1.147172	1.490202
+1.757295	6.291475	1.497705
+1.935255	5.856861	1.493212
+1.987935	6.378261	1.505109
+2.296000	4.758370	1.498667
+2.488413	2.489087	1.501827
+2.530078	5.140625	1.505000
+2.675082	4.338525	1.497541
+2.830833	6.246083	1.504083
+3.579063	0.300625	1.499844
+3.731556	2.497111	1.496667
+3.978500	0.305000	1.493625
+4.426387	1.191355	1.500129
+0.769730	1.730721	1.503784
+0.759173	3.309774	1.512105
+0.758119	6.386139	1.507723
+0.991527	4.633969	1.512824
+1.001000	2.774800	1.495400
+1.582949	3.949615	1.505128
+1.989300	5.113457	1.518889
+2.313013	3.179289	1.513598
+2.661130	2.895391	1.521609
+2.910377	2.314528	1.511887
+3.284897	6.349259	1.506296
+3.366479	2.000845	1.508662
+3.474921	4.530632	1.522079
+3.470196	4.262941	1.501373
+3.883431	6.274891	1.514453
+4.144576	1.386949	1.506610
+4.198478	3.895435	1.498043
+4.390608	6.356225	1.516852
+0.768269	0.270577	1.505769
+0.763622	1.015748	1.516378
+1.139143	3.428143	1.524821
+1.220058	5.075706	1.532680
+1.347322	4.607596	1.536393
+2.274233	4.040476	1.520106
+2.569324	1.014865	1.517838
+2.603963	0.764756	1.527500
+2.841714	4.150143	1.520000
+2.869740	3.757584	1.525651
+3.051639	2.662941	1.521050
+3.640380	5.323919	1.534133
+3.691373	1.102892	1.532647
+3.928506	0.569545	1.535227
+0.748310	4.680000	1.524648
+0.987244	5.990787	1.532441
+1.248358	1.777015	1.526567
+1.550845	0.325070	1.529789
+1.802545	4.053636	1.523091
+1.980920	6.115690	1.547070
+3.099281	0.020327	1.538497
+3.361878	3.238619	1.531271
+3.649297	3.878486	1.533514
+3.695610	2.750854	1.524878
+3.984727	1.617030	1.533030
+4.438533	1.461400	1.540900
+4.442609	1.734783	1.529891
+4.444211	0.239240	1.549357
+0.756059	2.420402	1.549812
+1.260738	6.266510	1.540940
+1.798763	0.263746	1.544089
+1.797333	2.091444	1.530333
+1.984824	3.488176	1.538765
+2.253588	0.060463	1.546250
+2.421066	1.682377	1.533607
+2.985594	2.067548	1.545441
+3.737570	4.579065	1.535140
+3.869872	0.828590	1.540128
+4.180617	1.144074	1.535926
+4.451597	0.504167	1.543403
+0.737656	5.659844	1.543594
+1.224308	5.936308	1.544154
+1.241796	1.002994	1.546347
+1.403705	1.987771	1.554940
+1.431962	5.774522	1.561411
+1.531302	3.529438	1.560947
+1.564082	1.387347	1.535918
+1.631932	2.610386	1.552850
+1.707153	6.052847	1.548681
+1.820317	4.755926	1.553175
+2.288794	2.338227	1.551844
+2.355030	6.114970	1.548698
+2.738489	0.159568	1.545827
+3.347873	0.396284	1.563863
+3.918151	0.035210	1.549874
+4.044706	5.844444	1.553007
+4.192803	0.188662	1.543949
+4.197474	5.242784	1.554794
+4.203944	4.642394	1.537887
+4.235577	2.139038	1.544423
+4.434722	3.936875	1.551806
+4.442787	4.327213	1.538197
+4.448652	3.676067	1.554607
+4.456964	2.344643	1.543750
+0.800000	3.062791	1.545116
+1.004716	1.106114	1.558777
+1.242222	2.874444	1.548889
+1.400196	2.692745	1.550196
+1.424984	2.437210	1.568464
+1.838259	4.488905	1.562587
+2.161698	2.972013	1.563585
+2.174203	5.455362	1.550435
+2.341538	1.445192	1.546154
+2.783852	6.011475	1.558934
+2.923148	5.443148	1.560926
+3.123909	3.354682	1.560045
+3.330597	3.504080	1.560995
+3.367290	5.315576	1.562679
+3.473529	2.971123	1.564278
+3.696269	5.047388	1.557985
+3.700952	6.109841	1.555238
+3.955831	5.078563	1.565887
+4.439916	5.322185	1.551597
+1.234712	5.573077	1.561731
+1.286710	3.651042	1.580684
+1.440571	6.075285	1.583052
+1.447722	0.553544	1.575612
+1.475618	3.141011	1.561124
+1.525000	2.897000	1.553667
+2.601826	4.864348	1.564261
+2.767320	5.070261	1.569216
+2.933440	4.550960	1.574240
+2.993046	0.540152	1.576701
+3.010172	1.798190	1.572543
+3.113846	4.181538	1.563462
+3.271791	0.905075	1.559851
+3.416989	3.758817	1.576559
+3.514000	5.818105	1.567316
+3.519744	1.801744	1.570564
+3.936667	2.870000	1.559216
+3.945766	2.617297	1.574595
+4.224419	2.381628	1.556512
+4.403148	2.995185	1.554630
+4.447183	5.065211	1.560282
+4.475577	0.759423	1.565000
+0.962102	5.076752	1.577261
+1.281275	2.216765	1.574314
+1.308767	4.160308	1.588062
+1.654043	5.636330	1.585213
+2.160443	0.566650	1.584926
+2.451379	2.732759	1.562586
+2.655973	1.533122	1.585204
+3.243027	0.650412	1.593995
+3.297971	1.596087	1.575072
+3.438551	4.027056	1.582991
+4.187818	2.875591	1.580273
+4.190299	5.512989	1.591413
+4.203366	4.981188	1.575347
+4.430524	5.647640	1.583708
+0.728545	3.729552	1.599179
+0.721798	3.993933	1.583596
+0.986327	2.538878	1.587143
+1.165962	0.215625	1.601851
+1.192875	1.284292	1.594875
+1.493164	0.978418	1.590791
+1.850159	5.494762	1.576190
+2.130696	2.535886	1.589747
+2.197714	3.627238	1.583905
+2.269738	5.681937	1.589372
+2.371268	3.810352	1.590211
+2.617372	3.772993	1.592190
+2.892852	3.012814	1.602281
+3.041767	4.790964	1.592450
+3.071364	5.695682	1.590000
+3.155168	3.080638	1.599195
+3.160909	3.696364	1.589636
+3.207455	1.157182	1.588091
+3.345200	2.304480	1.585920
+3.748878	5.743061	1.580510
+3.981260	4.541732	1.585984
+0.726214	1.294612	1.599854
+0.736584	0.035018	1.605089
+1.253784	1.530270	1.590405
+2.025625	5.647344	1.587031
+2.273548	4.529785	1.599140
+2.423152	5.356957	1.605109
+2.584795	3.358493	1.593973
+2.752480	1.945984	1.607402
+2.791207	0.925000	1.586034
+2.815650	3.271073	1.601243
+2.821694	1.340000	1.600242
+3.181145	4.427786	1.596794
+3.261724	4.668736	1.594368
+3.322450	5.647050	1.601750
+3.694539	4.328628	1.617157
+4.021296	3.506605	1.597284
+4.197219	3.269821	1.608724
+0.974479	0.400888	1.611853
+0.983810	4.371905	1.600000
+1.012857	0.844082	1.601224
+1.646993	1.907692	1.604336
+1.846406	0.763488	1.616335
+2.102105	1.405789	1.608852
+2.200965	6.301667	1.609693
+2.506053	5.606263	1.616474
+2.681911	4.584311	1.612222
+3.024609	6.152344	1.610000
+3.276097	5.907000	1.619774
+3.713101	2.263178	1.601705
+3.775961	3.660471	1.618667
+3.918159	4.169683	1.622857
+4.010230	3.770000	1.598851
+4.358293	0.015000	1.620488
+4.472182	4.581455	1.608545
+0.696613	5.090968	1.615000
+0.719866	0.493795	1.627679
+1.017292	3.683538	1.631046
+1.215000	4.397639	1.608194
+1.709596	0.518051	1.627243
+1.778246	4.996579	1.622982
+2.071391	2.232522	1.617913
+2.090305	4.899329	1.623049
+2.449971	6.348657	1.625714
+2.472749	0.193743	1.620877
+2.505934	4.187552	1.627676
+2.691379	2.382512	1.625714
+2.941346	1.552308	1.608846
+3.069811	1.354717	1.606981
+3.583735	2.046867	1.616145
+3.689470	0.110227	1.616364
+3.710000	6.398889	1.607778
+3.973333	5.365859	1.624293
+1.105986	5.352552	1.646334
+1.166204	4.774745	1.632263
+1.339167	0.780648	1.626944
+1.537314	2.208400	1.636057
+1.595452	4.405452	1.640268
+1.887895	2.622836	1.637778
+2.038412	0.179588	1.636765
+2.121786	1.820595	1.627024
+2.192567	0.834358	1.645012
+2.221387	5.193090	1.644307
+2.376127	4.966861	1.642658
+2.503281	0.501797	1.632188
+2.829292	5.775487	1.635708
+2.944620	1.120163	1.629837
+2.986806	3.976806	1.639660
+3.641019	4.799962	1.634264
+3.780306	0.376735	1.636871
+4.248761	2.619381	1.628230
+4.250000	0.701935	1.619032
+4.462857	5.905357	1.628316
+4.477893	3.232587	1.642053
+4.493467	2.113733	1.627467
+0.706134	2.170672	1.636050
+0.702661	2.665000	1.633952
+0.838036	5.289286	1.639643
+0.915652	5.523913	1.634348
+1.034953	2.982978	1.645235
+1.537404	4.792979	1.640128
+2.252240	4.274536	1.639508
+2.256756	0.331073	1.657415
+2.433750	2.984295	1.644103
+2.739123	0.456316	1.632281
+2.927964	0.287725	1.653593
+3.030484	0.797419	1.628226
+3.288969	2.568041	1.631753
+3.481951	6.053537	1.631707
+3.580914	3.487665	1.646802
+3.761316	1.715833	1.640746
+3.770975	3.306441	1.640254
+4.039739	4.786903	1.655970
+4.233115	5.989180	1.634590
+4.297778	4.160741	1.625185
+4.322048	1.933810	1.649143
+4.492160	2.572960	1.637360
+0.695914	4.468657	1.664029
+0.915476	2.030714	1.643452
+1.113953	3.943446	1.653176
+1.774355	1.486129	1.641129
+1.943632	3.071667	1.657265
+2.059400	4.116000	1.642800
+2.113106	3.290429	1.658359
+2.121168	3.866332	1.660326
+2.831393	2.737214	1.657183
+3.252421	1.824105	1.649368
+3.460317	1.049683	1.653571
+3.564028	0.542678	1.664431
+3.727297	2.967946	1.649243
+4.330256	0.937821	1.642179
+0.691250	1.912813	1.653594
+0.910055	4.826565	1.673740
+0.922410	5.780103	1.658821
+0.964932	2.293741	1.671837
+1.358267	3.349318	1.671136
+1.368904	3.922466	1.659041
+1.524912	1.588772	1.650000
+1.778817	5.249785	1.651398
+2.692378	4.008841	1.664634
+2.998027	5.035646	1.663061
+3.251611	5.099667	1.660556
+3.834559	2.046863	1.660882
+4.024505	6.116264	1.656209
+4.263784	3.521622	1.654865
+1.813393	2.298036	1.657500
+1.853136	3.861124	1.669586
+1.955000	0.435336	1.675268
+2.044195	4.621268	1.681512
+2.464138	3.579496	1.686021
+2.598293	2.139634	1.666829
+2.807923	0.693865	1.678406
+3.087521	5.287355	1.665785
+3.308256	1.367326	1.669186
+3.442282	0.176913	1.666107
+3.545322	2.446271	1.680271
+3.845761	5.948152	1.664457
+3.973889	3.106190	1.676270
+4.239911	4.419710	1.681071
+0.672903	6.231613	1.673226
+0.952544	1.772403	1.690318
+1.508011	5.303441	1.680054
+1.589954	0.752857	1.678433
+1.737854	2.847098	1.692122
+1.797099	4.243704	1.685185
+2.019873	4.352785	1.684051
+2.375893	1.028997	1.690502
+2.468286	4.693143	1.673714
+2.662185	5.278403	1.690868
+2.739500	3.557639	1.687333
+3.182638	0.219049	1.688466
+3.496163	6.324070	1.694462
+3.515096	1.504327	1.672788
+3.631197	5.548547	1.672564
+3.954221	5.647662	1.681688
+3.970862	1.375862	1.665690
+4.235410	1.535246	1.676885
+4.485430	6.163620	1.680995
+0.686071	0.840119	1.682024
+0.682757	3.481243	1.694919
+0.934254	3.414420	1.689779
+1.194069	2.670414	1.685724
+1.207066	0.548430	1.691322
+1.576944	1.200000	1.680833
+1.593934	3.782960	1.704357
+1.689830	3.113182	1.684773
+1.727073	0.987805	1.676341
+1.757381	3.561190	1.697619
+1.892667	1.915048	1.695302
+1.978451	0.984965	1.698204
+2.353333	1.861481	1.679074
+2.574662	6.012180	1.701429
+2.659870	3.091948	1.689351
+2.702273	1.141591	1.672727
+2.928421	2.488900	1.698708
+4.125302	1.761581	1.697953
+4.520167	2.826833	1.682333
+0.675414	5.480446	1.700382
+0.674226	5.847484	1.712452
+0.677565	2.916477	1.702953
+0.818763	1.516598	1.691031
+1.140895	6.109579	1.700105
+1.163425	1.948370	1.708204
+1.583333	0.147241	1.689655
+1.830334	1.239554	1.709136
+1.819859	5.782535	1.691690
+1.851429	3.317792	1.696818
+2.007812	5.350443	1.715568
+2.170545	1.175818	1.694000
+2.589126	1.769417	1.695825
+2.971289	4.333822	1.705600
+3.072556	2.850224	1.705426
+3.236045	2.099364	1.704273
+3.266602	6.162492	1.703625
+3.321994	4.233826	1.708296
+3.458267	4.963600	1.691733
+3.548182	3.184318	1.701023
+3.669038	0.913269	1.686346
+3.665476	4.069762	1.710179
+3.750217	1.464130	1.695217
+4.248958	6.224792	1.695521
+4.516889	4.130444	1.693333
+0.928231	0.640615	1.705308
+0.962101	1.308986	1.710000
+1.127143	3.246032	1.702222
+1.284556	3.054497	1.714911
+1.372308	0.345144	1.713365
+1.969246	1.634295	1.716328
+2.064439	5.896257	1.706791
+2.326026	5.913675	1.708377
+2.354870	2.114348	1.702957
+2.430735	0.725588	1.701471
+2.481136	4.439205	1.710852
+2.603632	2.607164	1.717313
+2.683644	6.264810	1.719096
+2.808866	4.839446	1.724106
+3.531286	2.711857	1.709571
+3.599438	1.265542	1.721888
+3.873981	1.131165	1.707864
+4.017748	0.193576	1.718742
+4.027791	0.735465	1.706279
+4.085203	0.993446	1.706014
+4.087789	2.026131	1.709196
+4.090513	3.984359	1.707487
+4.219310	5.750739	1.712660
+4.282021	3.802766	1.700851
+4.295229	0.383119	1.705688
+4.306798	1.292895	1.714868
+4.515061	3.494268	1.712195
+0.658387	4.793548	1.715968
+1.198252	2.410699	1.717063
+1.341818	4.926364	1.705682
+1.431375	5.558768	1.730516
+1.553537	4.138830	1.736056
+2.265521	2.793542	1.708958
+2.351506	2.552108	1.719699
+2.369351	3.326703	1.721081
+2.437557	1.286989	1.717443
+2.755130	5.537642	1.733782
+3.033690	5.921310	1.724310
+3.039137	2.261223	1.719640
+3.447565	0.784555	1.730628
+3.774957	0.692051	1.719829
+4.512482	4.854184	1.720426
+4.536667	1.127576	1.710606
+0.667147	4.199679	1.741410
+0.939191	0.163003	1.745796
+1.056800	6.360750	1.730650
+1.407143	1.382786	1.732464
+1.535682	6.386477	1.724318
+1.597251	5.920584	1.736495
+1.627419	2.428226	1.721774
+1.766871	6.371224	1.726327
+2.026434	2.835035	1.733916
+2.227391	1.614720	1.733851
+3.249157	3.885542	1.725060
+3.792339	5.215088	1.724737
+3.845244	3.899756	1.722317
+4.051800	0.444600	1.722400
+0.670085	0.260085	1.735043
+0.929215	4.564660	1.751675
+0.957786	2.745496	1.734962
+1.097273	4.206676	1.752159
+1.350000	1.127250	1.726250
+1.357246	0.086087	1.731304
+1.460235	1.806235	1.735176
+1.558051	5.050636	1.745466
+1.707887	4.624227	1.744072
+1.723529	1.708382	1.730735
+1.989700	6.284500	1.741100
+2.469211	2.334211	1.729868
+2.730625	4.255208	1.731563
+2.904379	0.040339	1.751977
+3.810997	2.460587	1.748915
+3.947943	6.373698	1.756901
+3.957391	2.250725	1.733768
+4.538054	1.628725	1.744430
+0.661928	1.088373	1.748855
+0.876766	6.063027	1.756439
+1.293458	6.385981	1.751121
+1.605000	3.362813	1.743750
+1.848566	6.026846	1.760108
+1.999664	3.640839	1.760101
+2.251781	4.764658	1.742740
+2.459710	1.542319	1.744203
+2.607610	0.900467	1.760852
+2.638116	0.046014	1.764638
+2.832222	1.732857	1.735079
+2.973258	3.665955	1.740449
+3.130698	0.989369	1.760897
+3.164359	5.508462	1.737821
+3.244433	4.859691	1.748969
+3.523662	5.214085	1.762934
+3.612949	4.550897	1.739872
+3.832077	4.666385	1.756000
+4.077617	2.472228	1.752124
+4.291404	5.109298	1.744211
+4.525140	5.471215	1.744953
+4.542299	0.387126	1.746207
+4.545935	0.108130	1.757317
+4.545273	0.889273	1.743091
+0.883966	4.066724	1.749310
+1.108300	4.985200	1.763650
+1.291156	5.175306	1.756735
+1.694590	5.451475	1.746393
+1.823007	0.114755	1.763881
+1.993542	2.418125	1.754792
+2.122870	2.035093	1.756111
+2.609321	5.021196	1.776984
+2.826739	2.138261	1.745217
+3.126612	1.634973	1.759180
+3.165041	3.513577	1.754797
+3.437705	4.712623	1.752787
+3.815400	4.952560	1.767680
+4.313649	5.354459	1.752973
+4.533721	3.800093	1.764605
+4.550495	1.371287	1.762673
+0.897813	3.169688	1.757344
+1.167071	3.509607	1.782250
+1.380000	4.332763	1.767763
+1.430849	2.850425	1.777028
+1.481852	2.600370	1.755926
+1.712796	2.086452	1.765054
+1.957789	5.092632	1.772526
+2.334559	3.987000	1.782971
+3.354138	4.487069	1.758276
+3.413290	5.467915	1.776059
+3.784074	2.734120	1.769259
+4.049540	2.760460	1.767816
+4.204961	2.250472	1.767638
+4.218242	3.051923	1.769121
+4.435158	0.632127	1.772262
+4.533979	4.380052	1.767958
+4.546462	1.912718	1.775436
+4.544689	2.331340	1.777703
+1.056332	1.543317	1.781005
+1.127021	1.042766	1.774043
+1.223600	4.580400	1.765800
+1.461413	4.586848	1.768370
+2.234722	3.087500	1.791493
+2.253333	5.431354	1.791736
+2.619775	2.859775	1.779213
+2.626923	5.758889	1.778291
+2.860619	6.095773	1.770619
+3.028152	1.967725	1.786540
+3.066245	4.607844	1.786989
+3.430299	1.945373	1.777164
+3.482381	2.203690	1.770476
+3.635591	5.935118	1.776772
+3.786878	6.164049	1.781073
+3.918333	4.389444	1.765741
+3.946087	1.591304	1.777304
+0.646410	3.164038	1.801987
+1.623657	6.173433	1.788955
+1.900724	4.831743	1.800080
+2.178360	6.118818	1.805326
+2.344363	0.047170	1.797170
+2.670833	1.362667	1.790333
+3.096691	0.440216	1.789065
+3.400719	3.615683	1.788417
+3.497626	3.887671	1.804589
+4.265859	4.850391	1.791406
+4.539952	5.109904	1.791483
+0.638440	5.242200	1.808360
+0.851122	5.053163	1.799082
+1.152404	0.784421	1.812552
+1.191529	5.631294	1.791882
+1.429020	3.581520	1.802804
+2.222167	2.328208	1.805042
+2.625152	0.310649	1.802900
+2.768042	3.802917	1.804833
+3.124835	3.264286	1.801648
+3.374620	3.348511	1.810274
+3.671913	1.902696	1.793304
+4.044250	5.909125	1.790625
+4.069301	5.005175	1.800699
+4.100303	3.656162	1.802929
+4.259716	0.151344	1.817261
+4.306178	2.806497	1.804140
+0.639834	3.909006	1.808785
+0.685412	2.476118	1.799412
+1.233151	3.767740	1.807055
+1.705125	0.334750	1.797125
+1.900301	5.572711	1.807470
+2.136870	5.669696	1.809261
+2.275625	3.716250	1.799167
+2.933679	3.426038	1.807453
+3.099167	4.140833	1.803472
+3.315025	2.807635	1.813645
+3.306162	3.085051	1.816061
+3.499698	5.719430	1.814262
+3.511980	1.708416	1.811188
+3.865299	3.494321	1.814891
+3.908630	1.850822	1.804247
+4.098278	4.229569	1.811292
+4.330000	2.471558	1.811558
+4.545000	5.724189	1.796622
+4.563585	3.034340	1.795849
+0.897862	0.868690	1.819448
+1.104310	5.875324	1.829014
+1.221237	2.179175	1.816082
+1.309111	1.621143	1.827810
+1.366310	5.795833	1.811190
+1.411324	2.334412	1.812794
+1.447577	2.053148	1.833983
+1.478288	3.172432	1.823063
+2.020404	0.727879	1.817980
+2.810392	4.498758	1.815163
+3.119536	2.618543	1.843422
+3.163333	0.010000	1.805000
+3.253840	2.342640	1.818480
+3.342589	0.512816	1.827443
+3.531172	2.949448	1.814690
+3.573375	0.329625	1.820438
+4.081818	1.223766	1.809221
+4.077013	4.582554	1.825455
+4.342857	4.618214	1.803214
+0.641742	1.628949	1.840150
+0.646178	0.634522	1.844650
+0.835368	6.311789	1.820947
+0.857317	3.614390	1.819268
+1.360428	6.050272	1.836654
+1.642979	1.385319	1.815319
+1.906335	4.059050	1.831131
+1.934486	2.175081	1.838541
+2.123121	2.621676	1.829422
+2.153662	0.499415	1.844923
+2.227568	1.370811	1.828378
+2.229691	4.450617	1.830062
+2.386491	5.698333	1.826140
+2.525803	1.968705	1.835181
+2.645839	0.572416	1.829396
+2.894848	1.262121	1.826212
+2.982651	5.654419	1.842302
+3.230519	5.752078	1.829913
+3.309177	1.176450	1.830823
+3.533577	4.335122	1.829756
+3.755714	5.721250	1.829464
+3.876006	0.906433	1.839878
+4.080000	5.257462	1.828231
+4.106087	3.393623	1.821449
+4.324221	4.021388	1.836856
+0.846293	0.417857	1.848333
+0.880267	4.326310	1.848930
+0.946172	3.842813	1.842266
+1.314286	4.097619	1.831905
+1.551087	0.957464	1.836159
+1.563429	0.522762	1.834857
+1.646162	5.680669	1.846655
+1.711392	2.629304	1.842278
+1.985111	1.404667	1.826889
+2.188706	3.472824	1.839118
+2.437050	6.187969	1.848621
+2.513032	3.800323	1.835226
+2.517931	5.473687	1.846393
+2.613920	3.374198	1.849599
+2.834133	1.018700	1.852867
+3.061975	6.222654	1.845247
+3.205280	0.748960	1.838800
+3.586787	0.061155	1.844260
+3.768364	3.136614	1.857000
+3.846652	5.437602	1.845701
+0.618938	6.064779	1.842212
+1.110329	0.356548	1.862027
+1.189344	2.862459	1.840000
+1.193067	1.269067	1.848533
+1.841073	4.431512	1.853902
+2.484199	3.140331	1.859282
+2.637258	4.679274	1.844677
+2.817318	3.199080	1.853870
+2.853511	0.439008	1.850916
+2.851061	5.124182	1.860242
+2.900266	1.521293	1.854905
+2.980833	0.643571	1.844762
+3.130679	1.375299	1.858451
+3.340513	1.535385	1.846154
+3.402414	5.960000	1.845862
+3.652201	3.660647	1.861748
+3.734896	2.221111	1.859028
+3.800183	0.221005	1.850000
+4.089070	5.514651	1.846667
+4.286825	1.075556	1.839206
+4.283770	0.810656	1.846066
+4.340451	1.776285	1.861701
+0.619115	2.105929	1.858584
+0.625698	0.043605	1.853953
+0.714203	1.317536	1.854638
+0.836517	1.934944	1.854382
+0.954328	5.622313	1.858358
+1.411066	0.735279	1.865736
+1.762482	0.817445	1.857518
+1.823356	0.569726	1.860137
+2.388480	4.245673	1.855731
+2.377813	5.109875	1.864250
+2.404938	0.550000	1.853951
+2.662500	1.605882	1.853382
+3.027500	3.047813	1.859479
+3.026415	4.876792	1.850189
+3.386989	2.559659	1.866080
+3.849830	0.500284	1.859205
+4.199762	0.585595	1.851905
+4.321822	3.276215	1.859766
+4.558580	5.997870	1.858580
+4.572113	4.615493	1.854789
+0.614651	3.656047	1.855581
+0.603939	5.650606	1.865758
+0.612682	4.608492	1.876592
+0.616131	4.981055	1.878593
+0.871656	2.946146	1.882325
+1.237967	5.396429	1.874341
+1.646351	4.842342	1.875360
+2.118047	4.210078	1.875742
+2.133211	0.220183	1.865229
+2.141865	4.942538	1.880734
+2.188727	0.971273	1.861455
+2.771845	2.339821	1.867976
+2.779231	1.933654	1.854231
+2.828517	5.869952	1.876890
+2.874884	4.040388	1.873760
+2.995111	5.387222	1.867556
+3.164277	4.378072	1.870783
+3.630617	3.372901	1.873765
+3.766393	4.243279	1.865246
+3.841224	1.319184	1.855306
+4.228097	6.053545	1.877239
+4.337525	5.581287	1.880248
+4.344611	2.064278	1.869222
+4.350441	3.622687	1.874053
+0.817277	2.277574	1.885248
+0.842570	5.390782	1.879441
+0.883333	1.131959	1.888866
+1.002857	2.442208	1.877143
+1.160650	0.080224	1.902623
+1.681488	5.243962	1.895744
+1.678667	3.957333	1.871778
+1.994531	3.218672	1.881328
+2.013190	1.164724	1.886748
+2.136034	1.811552	1.869828
+2.276061	0.746364	1.879596
+2.445789	4.826526	1.877474
+2.572905	1.143953	1.891588
+2.848247	2.879935	1.880455
+3.056256	3.854566	1.885753
+3.102500	5.107381	1.878690
+3.229880	5.312048	1.867470
+3.349754	0.109344	1.880656
+4.561316	6.395789	1.872895
+4.583798	2.565039	1.879845
+0.754257	2.706824	1.883649
+1.040356	5.210156	1.898022
+1.795131	3.740785	1.891257
+1.872618	2.973168	1.902147
+2.375671	0.298758	1.901443
+2.392806	1.739774	1.900935
+2.397760	2.894792	1.896250
+2.602667	4.106513	1.891231
+3.011782	0.226238	1.882772
+3.348776	5.062092	1.895663
+3.565660	6.147689	1.896085
+4.356725	1.485352	1.897852
+4.368551	5.845072	1.886957
+4.582350	3.265683	1.892186
+0.598883	6.326214	1.901165
+0.853804	5.845435	1.894891
+1.072824	4.722118	1.898529
+1.108393	1.770268	1.894286
+1.335000	4.760367	1.905932
+1.441757	3.893694	1.903559
+1.489929	0.221560	1.902128
+1.563444	1.616325	1.912715
+1.613636	2.980390	1.892857
+1.631085	0.023101	1.901008
+1.646772	1.879494	1.906519
+1.782105	1.064605	1.896316
+1.799063	2.379063	1.885938
+1.805405	1.545541	1.893919
+2.143532	5.217621	1.904498
+2.805277	2.613388	1.906710
+3.279637	1.791613	1.902661
+3.308992	4.049758	1.907702
+3.595976	4.998415	1.891707
+3.635037	4.739526	1.917606
+3.648061	0.801531	1.900000
+3.712469	1.111967	1.902259
+3.742698	1.692540	1.892857
+4.005149	6.171045	1.896493
+4.336339	4.292679	1.894196
+4.581236	4.015674	1.904213
+0.818778	4.757333	1.916000
+1.003008	2.109593	1.909756
+1.033366	3.333366	1.908020
+1.494497	1.212910	1.912593
+1.598904	4.431233	1.896986
+1.736772	3.234055	1.921299
+1.895109	3.456304	1.901630
+1.934252	5.808766	1.920945
+2.037414	3.860948	1.907069
+2.319167	1.164500	1.900667
+3.475545	0.986455	1.916636
+3.627189	1.466959	1.910829
+3.737796	6.373578	1.925687
+3.838714	5.958143	1.900429
+3.906202	2.913876	1.910620
+3.930261	4.063913	1.910957
+0.619701	0.894132	1.922934
+1.102599	3.081864	1.918136
+1.094952	4.445810	1.922000
+1.191317	6.231779	1.924164
+1.305691	2.536334	1.927203
+1.328830	0.494947	1.925426
+1.313681	0.971656	1.919264
+1.444816	6.284041	1.924122
+1.822197	6.223712	1.916136
+1.931591	0.352091	1.925909
+2.264385	6.365246	1.918689
+2.487353	5.909225	1.938102
+2.580691	6.379724	1.924608
+2.608087	4.368634	1.919235
+2.776284	0.769128	1.928349
+2.835910	6.328648	1.930295
+3.170375	6.014250	1.919000
+3.622787	5.517541	1.911967
+4.148733	6.375067	1.909667
+0.607845	3.400276	1.941188
+1.143065	3.965645	1.924032
+1.650435	3.521818	1.936522
+1.894806	1.801395	1.928915
+2.114975	4.675990	1.935939
+2.221935	5.882608	1.943817
+2.434364	4.559364	1.934636
+2.444000	2.197294	1.925882
+2.671799	6.103422	1.937670
+2.982667	1.759667	1.926250
+3.277480	4.658880	1.939240
+3.631765	2.522549	1.918431
+3.761321	4.496011	1.943558
+4.363033	6.259180	1.926393
+4.491238	5.317143	1.932667
+4.593481	2.118191	1.938840
+4.592968	2.821677	1.924645
+0.587750	4.353750	1.932500
+0.875672	1.701940	1.929701
+1.017064	0.594771	1.942615
+1.078911	2.672376	1.940099
+1.717011	4.207346	1.950754
+2.289366	1.996828	1.946082
+2.419091	0.940455	1.937879
+2.418067	3.526267	1.941733
+2.555841	2.470354	1.940442
+2.584231	5.235962	1.935577
+2.881471	4.706569	1.934706
+3.018433	2.388571	1.947465
+3.731520	3.908922	1.940931
+3.948571	2.596000	1.930571
+4.029376	0.329792	1.953222
+4.029186	0.052558	1.939186
+4.064748	3.169928	1.941871
+4.129091	1.916733	1.952614
+4.356326	0.370447	1.952236
+4.442838	1.236824	1.946284
+4.609423	1.064615	1.926346
+0.588276	2.952931	1.940000
+0.909754	0.021921	1.962660
+1.423832	5.248598	1.947944
+1.544714	5.465500	1.945357
+1.807324	5.023239	1.943662
+2.653214	3.619732	1.942411
+3.011233	0.856575	1.947671
+3.283732	6.235455	1.951148
+3.297656	3.778205	1.962784
+3.316973	2.139027	1.955081
+3.482636	6.385182	1.943727
+3.563961	4.107488	1.950097
+3.612580	0.546953	1.968010
+3.901389	3.722500	1.942593
+3.992083	0.694435	1.963512
+4.014368	2.152414	1.947586
+4.109179	3.876188	1.955660
+4.132675	1.633640	1.957807
+4.144792	5.756771	1.944375
+4.184151	2.634717	1.936981
+4.588851	3.529109	1.960517
+4.608621	0.565000	1.952069
+0.599724	1.865690	1.969414
+1.276845	5.027798	1.970516
+1.347785	3.016203	1.957278
+1.569012	2.454691	1.954691
+1.631862	2.211034	1.960897
+2.047892	1.602973	1.967784
+2.160577	2.835192	1.943846
+2.340818	2.647636	1.958364
+2.676269	2.130746	1.951642
+2.845319	4.286596	1.950638
+3.054428	1.125161	1.978270
+3.235781	0.310625	1.957656
+3.516241	3.162766	1.959291
+3.558919	2.064414	1.956937
+3.697763	5.255263	1.950526
+4.106194	0.952090	1.965858
+4.365345	5.015309	1.965855
+4.383235	3.015647	1.965000
+4.591244	4.877358	1.959171
+4.608263	0.274324	1.969846
+0.582742	2.327097	1.966452
+0.586609	4.106781	1.982103
+0.605129	0.398635	1.978007
+1.062565	3.661299	1.982305
+1.221848	1.986250	1.971033
+1.343731	4.488846	1.976962
+1.816048	1.309435	1.974355
+1.920575	5.339342	1.985068
+1.975764	0.926650	1.977931
+1.984815	6.057901	1.966914
+2.453108	1.362973	1.957973
+2.714261	4.879478	1.964522
+2.922346	2.111006	1.972291
+3.515600	1.251000	1.962400
+3.532716	2.745000	1.967840
+3.910978	5.125378	1.969956
+4.594306	5.538056	1.958056
+4.618571	0.818413	1.967778
+0.976269	4.129254	1.965970
+1.000636	1.354162	1.978902
+1.350761	5.618122	1.982284
+1.511677	2.706129	1.978581
+1.529780	5.866154	1.973626
+1.796995	4.662759	1.982906
+1.948786	0.096837	1.990863
+2.303762	3.282257	1.987053
+2.745242	5.613855	1.999758
+2.989757	3.602014	1.991319
+3.247722	5.540116	1.984015
+3.465618	2.341798	1.969663
+3.816589	2.000047	1.982757
+4.129800	1.379200	1.975600
+4.148162	2.900515	1.983971
+4.156206	2.382286	1.997186
+4.399610	2.281818	1.975325
+4.593484	1.729895	1.977317
+0.584767	5.428178	1.993566
+0.589474	1.141789	1.984316
+0.832141	3.188498	2.002268
+0.980847	4.947619	1.988783
+1.262727	3.278977	1.986364
+1.344229	1.410647	1.991592
+1.452771	4.245582	1.999880
+1.747565	5.989026	2.000617
+2.515016	0.101286	1.996945
+2.584270	2.741601	2.002633
+3.248976	3.507831	2.002048
+3.407965	0.733473	2.003650
+3.492736	4.529623	1.980472
+4.252364	5.348909	1.993273
+4.584740	0.019769	1.995376
+4.618125	1.462411	1.993929
+0.577636	2.573273	1.988727
+0.627368	5.862693	2.007926
+1.196559	4.228925	1.998387
+1.394943	0.021364	2.006648
+1.410984	1.815902	1.995164
+2.053976	2.439277	1.987229
+2.361309	5.326806	2.004764
+2.522373	0.713458	2.006305
+2.632372	1.802051	1.998654
+2.657153	3.004555	2.006619
+2.925741	6.073651	2.013307
+2.978488	4.488023	1.998023
+3.057667	2.820444	1.996778
+3.155298	0.566905	2.000774
+3.238784	0.939189	1.990676
+3.897073	2.363780	1.998171
+3.918272	5.634319	2.010930
+4.123545	4.842075	2.007032
+4.593560	6.203400	2.006480
+1.174200	2.322600	2.009200
+1.546163	4.647558	2.001047
+1.555833	5.043222	2.011778
+1.610522	0.687130	2.011043
+1.961404	2.693509	1.997544
+2.041250	6.298672	2.011797
+2.046462	4.439923	2.009000
+2.130658	2.191118	2.007829
+2.268945	5.579592	2.022926
+2.285214	1.526923	2.010342
+3.361429	4.290592	2.014321
+3.431004	5.352450	2.013414
+3.857138	4.864862	2.020069
+3.945433	1.157647	2.022768
+3.984836	4.348770	2.013852
+0.793333	3.738519	2.027619
+0.799692	5.170359	2.018462
+0.802037	4.507506	2.041304
+0.800884	6.062376	2.021768
+0.791084	0.227711	2.015060
+0.815826	0.741826	2.023957
+0.864505	3.472192	2.031892
+1.116316	1.101283	2.027566
+1.278189	5.882189	2.027887
+1.713185	0.223926	2.027506
+2.077531	3.628364	2.030370
+2.255063	3.823797	2.009747
+3.021623	3.330026	2.031597
+3.127602	1.958480	2.023743
+3.166277	1.588701	2.024762
+3.606283	5.935664	2.019292
+3.906634	1.498414	2.026926
+4.254737	4.538195	2.014286
+4.357500	3.831250	2.016750
+4.375567	0.657730	2.033156
+4.492848	4.443671	2.017722
+0.794806	1.491473	2.028062
+0.779167	5.640417	2.028229
+0.818386	2.508133	2.043544
+1.142615	1.556308	2.017231
+1.511642	3.304627	2.029403
+1.814223	2.045340	2.028592
+2.140963	3.076741	2.037370
+2.324270	2.406180	2.028989
+2.436410	3.972308	2.018462
+2.546941	0.455434	2.038950
+2.671716	3.900539	2.032647
+2.741711	0.308684	2.023947
+2.811584	5.326739	2.035870
+2.790000	3.440319	2.031170
+3.379000	2.953600	2.037486
+3.419017	4.856532	2.034682
+3.682273	2.950909	2.037098
+3.874332	3.313529	2.028877
+4.028720	3.519040	2.025440
+4.046115	5.967962	2.031975
+4.398168	0.943194	2.040209
+4.574088	5.787409	2.032336
+4.630323	2.358710	2.016774
+0.561169	4.797922	2.037922
+1.030769	0.855000	2.033077
+1.040110	5.438453	2.040110
+1.116615	5.681385	2.030154
+1.292611	0.273744	2.047734
+1.323064	3.551272	2.042717
+1.390851	2.210213	2.033511
+2.101905	1.350595	2.031548
+2.255849	0.083606	2.049371
+2.709200	1.416267	2.031067
+3.066550	6.373755	2.042751
+3.178140	4.930698	2.031473
+3.324522	1.379478	2.034000
+3.377322	5.756995	2.039945
+3.467260	1.626575	2.042466
+3.493317	0.236277	2.054033
+3.755904	0.051165	2.054940
+3.770923	2.707385	2.035077
+3.773524	6.145619	2.035048
+3.924381	1.772286	2.034000
+4.147148	4.135387	2.052218
+4.264583	3.445000	2.035000
+0.570000	1.378525	2.046721
+1.231121	0.703049	2.050269
+2.262292	4.332708	2.042917
+2.314286	6.101203	2.048647
+2.524220	1.575780	2.050000
+2.643492	0.955794	2.055992
+2.726216	4.554775	2.044234
+2.770989	1.175714	2.046044
+2.951274	1.362972	2.056085
+3.010172	5.816978	2.063440
+3.133100	4.169100	2.057500
+3.241429	2.459206	2.055952
+3.280400	2.703200	2.040200
+3.513308	3.523308	2.048462
+4.246790	0.026914	2.039136
+4.400794	2.517143	2.045714
+4.612660	3.795638	2.056277
+4.611813	5.123212	2.047772
+4.625170	3.061818	2.049318
+4.625298	4.221192	2.052318
+0.556833	5.155833	2.058333
+0.787362	6.321411	2.061166
+0.795714	3.984000	2.049429
+1.279182	2.768931	2.057547
+1.595463	1.401806	2.062685
+1.958232	4.855016	2.064695
+2.005167	5.580958	2.059417
+2.055240	1.947644	2.063750
+2.495191	4.980710	2.064426
+2.930285	4.971585	2.068943
+2.990435	0.390580	2.056812
+3.303876	3.247697	2.062416
+3.536868	3.790495	2.065275
+3.621657	1.837426	2.072130
+3.731875	0.341250	2.059271
+3.971595	4.621396	2.069202
+3.982186	5.365628	2.060283
+4.371243	2.770113	2.060339
+4.377596	4.761672	2.072648
+4.406168	6.012243	2.061589
+0.784043	2.049574	2.055532
+0.985799	1.905465	2.076171
+1.019766	5.918361	2.083396
+1.715368	2.839789	2.060421
+1.778278	2.541483	2.074163
+1.852908	0.718652	2.070142
+1.949181	4.135198	2.081299
+2.288604	0.483063	2.070225
+2.285183	4.821829	2.069939
+2.796049	0.555640	2.083515
+2.814655	1.637471	2.075000
+2.930000	3.290000	2.040000
+3.051017	5.253559	2.058136
+3.412813	6.068854	2.068333
+3.952549	6.355724	2.075054
+4.218827	1.171349	2.082639
+0.573353	3.168699	2.086705
+0.788315	4.237865	2.074270
+0.905652	2.771848	2.076630
+1.027333	0.233200	2.078200
+1.257079	3.807423	2.090550
+1.449377	6.077574	2.083082
+1.570000	4.035109	2.079891
+1.640215	6.242903	2.077204
+1.735085	5.735495	2.090717
+1.794983	3.912594	2.093481
+2.030605	0.536178	2.084936
+2.220339	4.084373	2.094271
+2.479274	3.731129	2.083468
+2.558621	4.723621	2.068793
+2.555447	3.237977	2.089027
+2.992606	5.526704	2.092205
+3.341887	1.132830	2.074906
+3.623694	5.688949	2.096667
+3.740606	1.300152	2.075606
+3.769837	3.553455	2.078659
+4.153537	5.126234	2.094453
+4.164444	6.188593	2.089407
+4.394919	1.922298	2.081815
+0.556320	6.102320	2.083200
+0.561314	3.617371	2.095771
+0.752105	4.927368	2.082281
+0.999333	6.202800	2.079467
+1.501767	0.915700	2.094333
+1.748140	1.677791	2.085465
+1.776667	0.468014	2.087660
+1.827143	6.388667	2.090476
+2.035360	3.362882	2.103343
+2.145714	0.775764	2.091527
+2.162061	1.120611	2.091221
+2.211169	1.748831	2.084286
+2.264348	5.085466	2.091801
+2.478853	4.217202	2.091743
+2.505514	2.022243	2.086075
+2.696595	5.867500	2.091897
+2.711333	5.095333	2.077333
+2.847944	1.895234	2.084673
+2.887076	3.120292	2.098421
+2.916125	0.151500	2.095500
+3.135962	3.048732	2.089624
+3.383502	0.480135	2.099697
+3.540936	5.127362	2.100681
+3.613944	4.327746	2.097218
+3.782905	0.942997	2.095719
+4.155364	0.519136	2.092091
+4.150759	5.555063	2.080253
+4.226458	2.131956	2.094207
+4.409004	4.077925	2.093402
+0.567415	1.635122	2.103415
+0.786949	1.247797	2.095085
+1.540741	2.017325	2.107695
+1.562960	3.770072	2.107509
+1.665532	1.155957	2.092234
+1.879114	2.294629	2.116057
+2.014615	5.112821	2.103590
+2.579267	5.425267	2.098800
+3.075113	4.702105	2.103985
+3.121088	2.208435	2.102109
+3.675556	2.364444	2.086296
+3.816040	4.178020	2.096634
+4.357733	1.653600	2.094400
+4.405106	3.237943	2.099078
+4.621818	4.653826	2.102273
+4.645965	1.235263	2.093158
+0.556133	2.102533	2.099867
+0.568761	0.176018	2.104867
+0.576637	0.655045	2.115646
+0.833603	0.994377	2.121448
+0.846966	0.461241	2.114483
+1.237619	5.288762	2.108048
+1.812065	4.431336	2.119717
+1.898190	3.142381	2.104952
+2.388089	3.035689	2.120578
+2.507339	5.682817	2.118941
+2.922638	3.840624	2.117554
+3.010101	2.598480	2.116453
+3.473810	2.545714	2.097381
+3.901585	0.499390	2.104146
+3.910709	3.065787	2.122756
+0.560725	2.787874	2.119130
+0.760946	2.965946	2.122905
+1.322464	4.056957	2.111739
+1.361250	1.139145	2.118224
+1.703944	5.388239	2.122324
+1.710353	4.871529	2.114235
+1.820206	3.626186	2.117629
+1.900886	1.126835	2.108228
+2.261901	4.569091	2.117769
+2.583000	2.281000	2.102750
+2.825153	2.377761	2.128098
+2.809674	4.093370	2.118804
+3.273712	5.156564	2.127178
+3.635755	3.316763	2.120144
+4.324330	5.761134	2.124089
+4.411787	5.503992	2.131103
+4.649231	1.927885	2.111346
+0.551966	3.885674	2.129719
+0.555569	4.557294	2.138275
+0.546667	5.645580	2.133986
+0.810897	5.401410	2.122949
+0.955714	4.711579	2.124962
+0.997411	3.872946	2.129955
+1.108868	3.441698	2.113019
+1.145826	0.467982	2.131101
+1.152000	4.565286	2.130571
+1.202430	4.822077	2.138063
+1.203784	1.767432	2.120000
+1.456165	4.840226	2.125789
+1.490000	2.903231	2.124000
+1.647093	3.108789	2.138443
+1.776316	3.384211	2.115263
+2.163846	2.611905	2.136190
+2.405021	1.196008	2.134856
+2.684924	6.281667	2.138485
+2.839808	2.870577	2.125577
+3.139823	6.151947	2.129558
+3.196327	4.462836	2.135200
+3.573822	6.255096	2.125987
+3.656811	5.418993	2.147458
+3.825586	5.871650	2.142485
+3.989574	2.774255	2.128617
+4.610000	6.400000	2.115000
+4.651935	2.584839	2.114839
+0.750847	2.276780	2.130339
+1.007343	4.362841	2.146679
+1.054857	3.197048	2.143905
+1.093226	2.130645	2.136290
+1.148511	2.539198	2.146870
+1.397500	1.610972	2.134028
+1.478368	0.429540	2.142887
+1.956739	2.887826	2.131522
+2.071818	5.810341	2.136591
+2.118529	0.291912	2.147831
+2.135816	5.366667	2.136099
+3.140367	0.771193	2.137706
+3.162515	0.126140	2.140058
+3.230968	5.925242	2.142339
+4.174286	3.687143	2.124762
+4.206526	3.093368	2.134211
+4.210357	0.256339	2.136250
+4.407500	3.617000	2.134500
+4.395308	5.213077	2.141615
+4.415162	1.400767	2.152507
+4.631796	5.370299	2.138623
+4.638768	3.329668	2.144739
+0.725769	0.011538	2.143077
+1.189904	2.992596	2.145673
+1.205313	6.091875	2.146250
+1.552146	4.443765	2.151619
+1.863077	6.165275	2.147363
+1.881498	1.473921	2.161145
+2.058674	3.878934	2.163343
+2.267667	3.493250	2.141083
+2.409433	0.275709	2.160324
+2.538093	6.067034	2.156907
+2.706038	4.323585	2.157673
+3.175084	3.926034	2.150838
+3.402000	1.999533	2.150733
+3.403823	4.059932	2.162765
+3.543250	1.409500	2.137750
+3.603115	1.115246	2.137213
+3.640714	4.899524	2.137857
+3.728028	4.658451	2.148451
+3.949091	3.960663	2.165430
+4.095529	3.311294	2.147882
+4.170077	0.777846	2.144538
+0.547103	4.291121	2.163364
+0.763068	1.798125	2.163693
+0.964842	1.645579	2.158947
+0.982316	2.344737	2.153789
+1.188416	6.354505	2.152871
+1.390000	2.435596	2.156943
+1.757308	0.930000	2.168974
+1.762865	5.124568	2.176432
+2.336484	2.193077	2.157637
+2.364068	5.890085	2.159237
+2.873426	0.814143	2.165857
+3.288095	1.775000	2.155833
+3.701152	1.596848	2.158121
+3.820602	2.187349	2.154096
+3.974979	0.170083	2.162075
+3.999014	2.018310	2.161690
+4.458750	0.176977	2.166570
+4.635104	6.004583	2.155313
+0.539452	6.359726	2.162123
+1.111912	5.080735	2.161618
+1.173802	1.315950	2.159421
+1.426538	6.361394	2.163221
+1.493750	0.172880	2.178315
+1.499512	5.719878	2.158780
+1.540522	3.511381	2.185075
+2.233846	6.302010	2.184293
+2.325909	0.944848	2.178636
+2.443762	1.780396	2.166733
+2.510236	4.498850	2.179027
+2.555161	3.489677	2.168581
+2.761429	2.632976	2.161905
+2.953587	4.298804	2.169239
+3.041961	1.763007	2.169346
+3.616667	0.750698	2.163643
+3.654478	4.002836	2.166119
+3.936098	2.528699	2.176748
+4.193073	2.576094	2.179792
+4.403199	6.264412	2.172831
+4.649162	0.438534	2.174712
+4.646818	0.970455	2.173364
+0.562948	0.922500	2.182724
+1.232563	0.929625	2.183000
+1.395391	3.129565	2.177478
+1.455862	5.471724	2.172414
+1.513275	5.228838	2.191690
+1.630000	2.352642	2.173962
+1.975432	1.729388	2.185252
+2.095792	6.066264	2.200000
+2.706423	3.697664	2.179927
+3.352500	2.274000	2.168000
+3.420766	5.547033	2.182392
+3.445309	0.933454	2.184021
+3.774430	5.188228	2.171646
+4.598396	0.698160	2.191132
+1.290494	4.352889	2.207901
+2.199503	2.872762	2.191989
+2.405682	2.716909	2.196227
+2.480121	5.201660	2.198826
+2.684660	0.133223	2.206816
+2.749524	2.126786	2.182857
+2.786192	4.785771	2.201519
+3.142051	1.252692	2.186026
+3.581613	2.164032	2.180161
+3.946216	3.693514	2.183784
+4.071129	5.770040	2.191976
+4.167484	1.799097	2.199161
+4.618390	2.832634	2.196000
+4.660879	2.176374	2.189231
+0.967097	6.395484	2.192581
+1.094411	4.113042	2.204753
+1.440233	0.680543	2.195581
+1.559245	1.776415	2.194717
+2.146484	2.354176	2.199011
+2.554470	2.510000	2.195606
+3.163171	3.668902	2.193171
+3.193924	5.676181	2.206354
+3.329944	4.684551	2.197022
+3.341556	6.256778	2.193222
+3.536947	3.093009	2.209469
+3.739000	6.399000	2.183000
+4.026341	1.337268	2.198976
+4.166885	1.538361	2.191639
+4.198421	6.395000	2.191579
+4.382673	0.435220	2.210094
+4.450755	1.142453	2.191887
+1.297129	2.004484	2.218258
+2.061166	0.045276	2.210491
+2.271905	1.949524	2.199206
+2.357535	0.685634	2.205986
+2.935097	1.081039	2.219662
+3.455878	2.766486	2.208446
+3.908841	0.734663	2.220647
+3.944050	6.113524	2.224622
+3.944964	5.021241	2.210438
+4.167455	4.397818	2.205545
+4.217346	3.927668	2.216756
+4.320909	2.352576	2.199848
+4.644932	4.014527	2.222162
+0.546171	4.967229	2.230286
+0.794988	5.873963	2.237063
+0.938995	1.398141	2.227839
+1.378696	4.616377	2.210145
+1.576901	2.599624	2.226761
+1.709559	0.040662	2.210882
+1.711315	4.204877	2.230247
+1.867353	5.915686	2.214804
+2.139429	1.523048	2.216619
+2.437897	0.026172	2.235483
+2.552532	1.393427	2.237519
+2.779231	6.067527	2.227143
+3.197966	5.394972	2.227712
+3.182977	0.370194	2.229968
+3.527436	4.536026	2.215641
+3.823897	4.436197	2.220939
+4.033324	0.981633	2.229799
+4.051071	2.296952	2.239571
+4.178615	4.682872	2.222103
+4.335427	4.975366	2.224390
+4.437099	3.013969	2.220611
+4.589375	4.924010	2.217031
+4.655200	4.425600	2.218800
+0.539691	1.890619	2.224845
+0.536207	5.345402	2.240000
+0.637690	2.540854	2.240316
+1.261603	0.078092	2.228550
+1.265203	5.713514	2.224459
+1.347788	5.039135	2.224712
+1.779434	1.883208	2.229434
+1.862513	4.668901	2.228534
+1.884957	0.220261	2.224174
+2.224472	3.230081	2.227724
+2.341617	3.891320	2.240231
+2.359027	5.445324	2.240405
+2.907598	4.545196	2.229497
+2.924014	6.293116	2.247746
+2.978594	2.048906	2.220156
+3.152688	2.795336	2.236759
+3.198987	1.003671	2.239968
+3.322577	1.536810	2.232086
+3.683622	2.563465	2.232441
+3.690233	0.518915	2.229690
+4.184185	5.364630	2.240148
+4.646733	3.587833	2.232867
+4.651234	1.701591	2.241396
+0.554754	1.190352	2.241937
+0.550313	3.396677	2.245549
+0.562153	0.419059	2.256757
+0.669000	4.084143	2.231143
+0.727874	4.739275	2.238986
+0.967442	5.256860	2.230000
+1.024021	5.601678	2.250420
+1.320794	3.363730	2.238254
+1.416844	1.364867	2.252625
+1.656827	6.053896	2.240482
+2.027823	0.954962	2.246937
+2.102826	4.716522	2.226304
+2.651552	1.898103	2.232414
+2.844092	5.705036	2.247482
+2.931220	3.522857	2.244821
+3.012581	0.574919	2.247581
+3.070412	1.488765	2.244882
+3.172584	3.419101	2.234045
+3.475926	5.874321	2.231728
+3.649030	6.042313	2.235597
+4.225163	5.981276	2.246142
+4.389205	4.512045	2.230568
+4.463333	4.275789	2.237544
+0.768354	3.583171	2.257866
+0.933128	4.935922	2.248324
+0.950558	0.055020	2.250000
+1.029200	3.636831	2.260369
+1.099021	2.776154	2.248112
+1.679623	0.639434	2.242264
+1.815424	2.718644	2.250678
+1.956966	2.517528	2.247753
+2.034303	2.129084	2.259801
+2.593182	0.785682	2.236364
+2.741245	3.332101	2.256926
+3.815500	1.862333	2.241750
+3.814070	5.604186	2.240349
+3.948471	1.642851	2.255950
+4.208840	2.830552	2.248619
+4.560779	2.402532	2.248312
+0.533282	5.879590	2.266667
+0.540897	2.290493	2.269507
+0.757041	0.234794	2.266067
+0.770000	3.199115	2.255929
+1.187203	1.557106	2.271286
+1.236566	2.272929	2.268283
+1.670353	0.328471	2.261294
+1.718793	2.133448	2.255000
+1.994806	6.348101	2.255853
+2.031186	1.280339	2.270169
+2.036255	4.475404	2.265660
+2.161015	5.617481	2.268722
+2.640056	1.646348	2.268090
+2.629091	2.807500	2.256364
+2.668134	0.403085	2.271294
+2.815392	1.458387	2.260046
+3.056139	5.089430	2.262975
+3.390847	0.081230	2.265628
+3.375505	1.288165	2.264037
+3.417197	4.973131	2.275025
+3.436842	3.339684	2.260526
+3.446073	5.304977	2.272283
+3.704887	3.764561	2.274712
+3.717385	2.820769	2.248462
+3.838925	1.156262	2.263271
+4.656000	1.426333	2.259556
+0.755857	1.567143	2.262571
+0.756000	5.123838	2.268432
+0.757068	5.601142	2.280710
+0.795469	0.665429	2.275184
+0.928729	3.390847	2.272966
+0.973253	2.993373	2.258434
+1.594634	1.550366	2.268415
+1.612051	4.697436	2.268718
+2.101905	4.227619	2.262381
+2.131690	4.963451	2.265423
+2.421176	4.736642	2.286225
+2.561353	4.041014	2.270531
+2.688176	3.060486	2.274863
+2.939231	5.329402	2.273704
+3.019390	5.986098	2.276402
+3.115728	2.407616	2.276594
+3.411257	4.315286	2.279829
+3.853151	3.402059	2.277773
+3.984400	4.248933	2.259600
+4.437121	2.633485	2.268737
+4.436556	2.091000	2.262778
+4.458667	3.832917	2.262000
+4.640505	6.229343	2.266263
+0.760000	2.768070	2.268070
+0.923722	2.574233	2.287670
+0.990000	0.844112	2.271776
+1.468626	2.192748	2.278931
+1.704625	1.330875	2.287125
+1.903922	5.670915	2.287353
+2.006818	3.565808	2.278737
+2.054896	3.059167	2.275000
+2.478623	6.318000	2.294522
+2.552931	1.037915	2.291118
+2.919823	0.318009	2.291416
+2.988000	3.267000	2.273750
+3.001543	4.072394	2.280798
+3.168137	6.387081	2.286087
+3.175388	4.865437	2.286602
+3.513617	1.714468	2.268723
+3.612803	3.508333	2.283182
+3.644044	0.138603	2.278971
+3.911114	4.771969	2.293057
+4.083684	3.521729	2.282857
+4.219635	0.055401	2.279489
+4.430462	3.414740	2.283237
+0.534896	2.981354	2.280208
+0.539762	1.450952	2.285794
+0.738805	6.380377	2.290377
+0.862632	2.106813	2.296199
+1.003663	6.083762	2.282673
+1.064242	1.127980	2.287475
+1.160792	0.667624	2.286931
+1.331145	2.665771	2.295066
+1.322007	3.622847	2.301204
+1.442529	5.917529	2.287241
+1.473026	4.126842	2.287500
+2.294722	4.386333	2.285833
+2.375283	1.582170	2.285566
+2.597759	4.935862	2.284310
+2.993675	2.984701	2.290000
+3.402462	3.823231	2.301169
+3.502902	0.346814	2.300757
+3.815366	0.317154	2.285285
+3.809111	1.414667	2.278889
+3.835000	0.012353	2.288529
+4.049452	0.381918	2.279589
+4.635596	5.791927	2.280917
+0.737525	3.838416	2.291881
+0.766949	6.126949	2.295678
+0.889888	4.544906	2.309288
+0.995919	0.343860	2.305699
+1.243481	5.465414	2.299834
+1.301474	0.317053	2.289158
+1.400891	3.880545	2.307475
+1.549434	3.282453	2.292830
+1.733622	6.297135	2.300270
+1.870260	4.919545	2.303247
+1.878746	5.385559	2.312508
+2.326752	2.496838	2.303419
+2.335321	6.088899	2.294312
+2.372500	4.996176	2.295882
+2.537000	2.147000	2.293667
+2.688077	5.312051	2.294103
+2.806579	5.069123	2.304211
+3.211910	3.179775	2.297865
+3.339164	2.554695	2.312154
+3.331596	2.967766	2.290638
+3.895765	5.356588	2.294235
+4.244308	4.182923	2.289385
+4.662733	3.115291	2.298895
+0.751993	4.313838	2.320000
+1.538627	1.126415	2.318319
+1.645977	3.957931	2.304368
+1.913262	0.464946	2.313692
+1.899444	0.730185	2.318843
+2.133571	0.638333	2.302540
+2.236220	5.210697	2.320590
+2.397732	3.636320	2.316729
+2.633071	5.551929	2.310857
+2.730455	1.218030	2.300909
+3.160326	4.271739	2.299239
+3.530949	2.369854	2.305182
+4.398750	1.773571	2.310357
+4.431007	0.927987	2.306577
+4.654881	5.546071	2.308571
+1.034404	1.827294	2.325275
+1.667129	5.537129	2.315248
+1.808305	2.995254	2.321017
+1.821579	3.259323	2.322406
+1.863754	3.780853	2.326109
+2.280738	0.423839	2.335423
+2.453527	3.169130	2.333961
+2.610513	5.814103	2.330000
+2.789000	3.943400	2.311400
+2.992827	0.062560	2.330107
+3.591910	1.952022	2.310337
+3.616842	1.272406	2.323985
+3.658873	0.963237	2.334393
+4.035135	5.552973	2.315811
+4.373533	0.673952	2.322575
+4.456545	6.058364	2.304727
+4.658056	1.937611	2.342333
+4.635922	5.171714	2.328494
+0.523802	6.131818	2.330661
+0.808188	1.174161	2.334396
+0.886316	4.028246	2.317368
+1.350959	2.928082	2.326233
+1.349774	1.762594	2.337030
+1.436729	6.169159	2.324206
+1.607204	2.830645	2.325161
+1.672965	5.804024	2.345271
+1.764571	3.503905	2.325333
+2.195371	1.752522	2.343501
+2.247810	0.165143	2.324095
+2.769763	0.646126	2.337510
+2.852417	1.800083	2.325917
+2.905813	2.750813	2.332063
+3.351348	3.562809	2.323371
+3.580379	4.759300	2.341137
+3.807800	2.359800	2.333200
+3.993939	2.932727	2.319091
+4.124643	4.903750	2.324107
+4.667572	1.175723	2.336879
+1.100163	4.688455	2.339756
+1.150417	3.856111	2.331944
+1.427724	0.885854	2.339919
+1.627273	4.941818	2.332078
+1.832841	1.112564	2.357460
+2.200502	5.866164	2.344110
+2.211111	1.108889	2.325333
+2.316545	1.326364	2.336000
+2.528876	4.289438	2.332247
+2.919189	2.246892	2.334730
+3.125647	4.609964	2.353345
+3.287625	0.785000	2.335750
+3.481770	0.617472	2.350787
+3.670000	5.776667	2.330575
+3.698936	5.015390	2.349858
+3.800565	4.102177	2.340565
+3.991479	3.188343	2.343728
+4.119919	0.619514	2.344332
+4.165064	2.080833	2.345513
+4.246782	1.087356	2.334253
+4.407130	4.747523	2.345257
+0.522449	3.678571	2.342653
+1.201657	3.132857	2.351943
+1.207157	5.206559	2.364190
+1.202581	5.947903	2.354839
+1.791458	1.662917	2.343542
+1.981179	5.146103	2.355487
+2.331716	4.132781	2.353018
+2.385802	5.702099	2.339753
+2.387885	2.918077	2.356474
+2.680199	2.343625	2.358645
+3.430882	6.086029	2.346912
+3.523671	6.341529	2.362071
+3.776242	3.045839	2.346107
+4.163250	6.223114	2.364565
+4.240382	1.359013	2.355669
+4.447692	5.365128	2.351923
+0.552811	0.081281	2.372792
+0.781872	2.355882	2.364439
+1.157708	4.938819	2.363125
+1.541076	1.959861	2.372396
+1.600880	3.706053	2.370240
+1.730484	4.482881	2.369007
+2.778479	4.192350	2.362166
+2.888904	2.496849	2.354247
+3.046339	0.828142	2.363989
+3.149677	2.155806	2.359113
+3.199487	6.139231	2.358846
+3.768482	6.249805	2.365058
+3.913173	2.709904	2.355865
+4.016631	4.533690	2.366043
+4.303571	3.656964	2.355060
+4.666606	4.712294	2.352936
+4.673146	2.648652	2.353146
+0.528169	1.691831	2.361127
+0.568462	0.743956	2.366374
+0.744884	5.351163	2.362558
+0.764211	0.908129	2.369532
+1.191875	6.205313	2.360000
+1.396070	4.816422	2.376716
+1.811374	2.345906	2.379883
+2.001034	2.834828	2.365402
+2.496292	0.564607	2.365618
+2.776173	0.940864	2.366543
+3.123448	1.909655	2.359655
+3.170500	1.678000	2.359250
+3.240385	4.043846	2.368385
+3.417037	2.139185	2.378543
+3.528723	1.494681	2.360426
+3.653333	3.264651	2.370310
+3.678462	5.280000	2.370513
+4.202590	5.138012	2.372048
+4.401149	5.817241	2.362644
+4.661789	4.229368	2.369368
+0.526343	3.932090	2.382164
+0.532703	2.741689	2.379932
+0.553072	4.472440	2.395361
+0.617107	2.071322	2.378512
+1.112892	2.081010	2.393275
+1.350500	0.543083	2.376167
+1.442102	5.627159	2.380625
+1.863023	4.047674	2.376163
+1.861135	6.098298	2.381418
+1.875315	0.031748	2.380909
+1.987439	1.903049	2.374756
+2.054444	3.331778	2.364444
+2.146615	3.755795	2.387231
+2.271176	3.423971	2.373382
+2.715613	4.459368	2.387589
+2.948476	3.759529	2.385374
+3.267766	5.893040	2.390220
+3.361522	1.868478	2.381449
+3.553596	4.093933	2.371236
+3.623432	5.535680	2.386509
+3.911919	2.113023	2.382965
+4.013902	1.888780	2.376585
+4.205610	0.850732	2.372439
+4.218571	3.042619	2.374524
+4.278618	5.563309	2.391564
+4.592744	0.291353	2.388496
+0.520000	5.649462	2.389785
+1.002201	4.273684	2.394593
+1.240000	6.400000	2.370000
+1.485970	4.360224	2.382761
+1.906618	4.296176	2.381471
+2.107473	4.021648	2.382527
+2.220497	0.852236	2.393230
+2.485274	0.227221	2.411444
+2.591718	3.800264	2.392643
+2.689545	3.561212	2.384091
+2.943923	4.881077	2.390538
+2.958750	1.291389	2.403090
+3.258333	5.177937	2.385397
+3.425702	5.694737	2.387632
+3.430955	1.081180	2.394270
+3.882935	0.534457	2.379239
+3.911004	5.781632	2.390962
+4.280144	0.282383	2.397220
+4.443231	4.063593	2.398078
+4.447670	1.530000	2.393252
+4.438884	0.046884	2.396000
+4.676522	3.811522	2.378261
+0.526633	4.197437	2.406080
+0.524194	4.753978	2.398118
+0.768686	2.989705	2.411528
+0.774160	1.879920	2.403680
+0.961270	1.587540	2.403413
+1.049200	2.371000	2.390900
+1.258919	4.073243	2.403784
+1.479800	5.374200	2.400300
+1.533780	2.407835	2.406850
+2.670702	2.614503	2.396784
+3.052407	5.762685	2.397407
+3.227742	0.552742	2.408656
+3.546164	2.914795	2.389452
+3.721389	0.711944	2.398796
+4.053102	4.046241	2.403431
+4.088291	3.777778	2.397949
+4.210945	3.325879	2.407585
+0.524737	6.376165	2.419286
+0.964446	6.305997	2.426780
+0.995426	5.806628	2.413915
+1.293852	1.102295	2.412623
+1.552945	3.063630	2.408356
+1.601226	0.139811	2.407925
+1.671055	0.901350	2.415654
+2.058261	0.291196	2.409348
+2.223901	4.603369	2.418050
+2.344700	2.260950	2.409650
+2.507903	3.405161	2.401935
+2.609849	6.076679	2.413132
+2.962419	4.376250	2.417782
+3.206049	0.185556	2.398395
+3.667917	2.167917	2.398750
+3.742670	1.610631	2.415777
+3.885373	3.625672	2.408731
+4.044776	0.174627	2.408284
+4.415576	2.850643	2.425630
+4.637895	3.344737	2.398684
+4.669538	0.828615	2.415538
+4.664654	0.551567	2.420276
+0.529371	5.153457	2.427486
+0.532954	3.193077	2.426615
+0.726667	4.917246	2.412174
+0.769685	0.437244	2.420000
+0.974314	5.413268	2.423072
+1.139507	3.376761	2.417042
+1.701048	5.193100	2.422926
+2.111667	5.416250	2.407361
+2.195323	2.681255	2.420875
+2.647500	4.711333	2.411750
+3.201273	1.192061	2.425152
+3.768780	4.591585	2.429065
+4.006111	2.488333	2.417333
+4.038687	1.197879	2.417475
+4.434212	3.170322	2.431768
+4.659278	5.996495	2.413918
+0.736604	3.380377	2.427830
+0.955324	3.192676	2.440971
+0.980706	0.568941	2.418353
+1.113259	0.146593	2.434593
+1.192778	0.869630	2.430494
+1.223846	1.350769	2.417231
+1.453488	5.126628	2.426279
+2.168200	6.331188	2.445840
+2.203514	2.020324	2.428865
+2.572568	5.132568	2.441694
+2.709655	2.036724	2.417759
+2.840769	5.887038	2.442462
+2.945842	5.540368	2.430737
+3.109725	2.625902	2.438043
+3.124560	3.568160	2.429280
+3.553667	2.674000	2.416333
+3.956907	5.141546	2.426186
+4.003960	1.452819	2.425772
+4.173000	5.794667	2.420222
+4.208846	1.605577	2.417885
+4.227353	2.645294	2.424902
+4.233978	2.374199	2.437735
+4.418089	6.271178	2.435796
+4.681974	0.041053	2.433816
+0.532662	0.991295	2.441439
+0.934702	3.803841	2.445232
+0.978132	5.097253	2.432857
+1.279815	2.451296	2.438519
+1.304795	4.578356	2.435479
+1.497143	3.474000	2.433810
+1.694211	0.489158	2.430526
+1.870414	1.449172	2.437724
+2.087391	2.310580	2.427681
+2.102679	0.022321	2.442768
+2.231278	3.102180	2.440000
+2.470667	4.530000	2.436778
+3.207205	5.564083	2.451157
+3.424000	3.157739	2.450261
+3.773910	5.998077	2.453910
+4.036400	6.002450	2.445400
+4.247708	4.530104	2.438438
+4.438636	1.217121	2.427879
+4.460175	2.267544	2.429825
+4.674262	2.174098	2.430000
+0.931732	2.787087	2.442756
+1.360714	0.140833	2.442262
+1.387950	1.532733	2.455776
+1.541882	0.677294	2.440000
+1.864177	2.096203	2.447595
+1.900375	5.866375	2.452000
+2.505056	5.386517	2.438202
+2.544512	1.241674	2.458326
+2.739244	0.213025	2.451092
+2.948033	1.586230	2.437705
+3.191961	3.806078	2.444314
+3.213438	1.448542	2.444271
+3.271757	3.367027	2.448243
+3.330976	2.777886	2.446423
+3.349200	4.725467	2.441867
+4.673119	2.899174	2.447798
+0.527925	2.463145	2.464403
+0.764074	1.397870	2.469398
+0.992407	1.305741	2.453704
+1.137805	2.642195	2.451707
+1.194176	5.656484	2.453407
+1.576593	1.711239	2.464469
+1.754321	2.596605	2.459259
+1.769928	4.751151	2.463237
+1.816641	0.271390	2.461583
+2.029636	4.781844	2.465818
+2.093708	6.063596	2.464326
+2.413761	5.927064	2.451468
+2.444262	2.696230	2.450000
+2.459151	1.971550	2.465203
+2.501385	0.793723	2.470130
+2.851624	6.145635	2.457411
+2.887732	3.142784	2.452268
+3.497612	4.538209	2.455821
+3.846137	4.328164	2.472575
+3.858701	3.877597	2.460390
+4.114797	4.309926	2.470406
+0.730899	2.618820	2.474944
+1.245085	4.331898	2.480305
+1.486869	0.354720	2.469159
+2.189720	1.503808	2.478855
+2.890415	4.640829	2.473594
+2.945641	2.038333	2.460641
+3.271798	4.427472	2.473146
+3.493004	5.144635	2.469528
+3.540185	3.680556	2.457778
+3.592857	4.317619	2.460238
+3.804805	0.151289	2.476484
+4.236471	1.874853	2.461324
+4.396745	4.993632	2.472406
+4.465682	1.961667	2.471515
+4.670575	4.465747	2.465287
+0.933158	3.531228	2.474737
+1.145639	2.908797	2.475338
+1.515775	2.658169	2.472113
+1.568427	6.023387	2.480081
+1.766207	1.875862	2.475172
+1.901289	6.338328	2.482822
+1.988036	1.663571	2.469107
+2.129740	4.346364	2.479675
+2.351016	0.023594	2.497383
+2.633609	2.912782	2.481880
+2.657107	1.786038	2.497201
+2.661127	3.225352	2.474225
+2.657482	6.317482	2.480144
+2.707760	1.517656	2.485885
+3.158406	3.019275	2.468261
+3.277958	2.355870	2.489211
+3.377258	1.637742	2.474839
+3.878877	1.007935	2.485833
+4.058884	5.371373	2.483734
+4.409646	4.324513	2.488820
+4.673761	2.426923	2.478632
+0.640640	5.968160	2.501520
+0.753574	4.669398	2.494779
+0.956716	4.842799	2.499179
+1.348095	2.084603	2.485238
+1.448934	6.362738	2.490490
+1.631931	2.180621	2.486207
+1.687725	4.246825	2.495782
+1.996804	2.534536	2.487732
+2.071593	5.711062	2.488230
+2.300244	0.639593	2.490569
+2.313069	5.522277	2.484950
+2.380992	1.030413	2.500468
+2.462889	1.472000	2.482444
+2.492000	2.458182	2.481818
+2.816371	0.448871	2.484677
+2.967627	6.379831	2.488192
+3.075969	0.361323	2.504923
+3.297514	6.326851	2.499475
+3.425634	5.433239	2.485070
+3.474143	0.843429	2.487286
+3.527765	5.896332	2.504756
+3.684506	0.379691	2.487160
+3.795339	1.908898	2.481441
+3.818738	1.297767	2.485243
+3.860741	5.542525	2.496094
+3.954249	0.750363	2.491036
+4.298636	6.023750	2.486023
+4.659563	5.382313	2.495313
+0.532365	1.252230	2.500541
+0.549219	0.313125	2.494375
+0.709912	3.647478	2.504735
+0.740294	1.650294	2.486176
+1.150186	3.666097	2.500149
+1.367320	3.266000	2.505000
+1.622667	1.452889	2.490444
+1.910952	0.906786	2.503810
+1.981351	3.143649	2.490811
+2.233077	4.952203	2.505455
+2.306966	3.930112	2.495506
+2.484721	4.887462	2.501726
+2.728125	4.936250	2.489750
+2.999009	1.045129	2.503664
+3.086794	5.321435	2.500191
+3.232444	0.956889	2.490667
+3.507929	0.170165	2.507882
+3.491364	3.446136	2.488864
+3.574029	1.792662	2.497122
+4.672532	3.579241	2.492405
+0.529976	5.423501	2.523693
+0.761914	5.723301	2.518182
+0.779319	0.168637	2.532525
+0.925556	6.035291	2.516032
+1.171667	1.700000	2.500000
+1.446493	1.286716	2.507015
+1.543000	4.630150	2.520650
+1.890326	5.551630	2.510326
+1.960270	4.528378	2.497297
+2.399532	1.712222	2.512982
+2.389907	6.181757	2.526505
+2.667162	4.017297	2.501892
+2.739337	5.420422	2.508795
+2.856462	5.192736	2.516792
+3.001469	0.618898	2.510653
+3.033982	3.333009	2.507965
+3.071686	5.054767	2.516105
+3.418487	1.332237	2.508355
+3.703611	2.503889	2.507917
+3.734762	3.456786	2.507262
+3.983616	3.414915	2.512881
+4.046133	4.738267	2.503867
+4.131753	2.861169	2.512403
+4.438609	2.532180	2.513045
+4.652937	5.701599	2.517807
+4.678400	1.504800	2.493600
+0.772952	4.139692	2.521322
+0.766190	5.172619	2.510476
+0.963484	0.806129	2.525806
+1.023050	4.038450	2.519650
+1.389290	5.833470	2.531995
+1.543613	3.912941	2.521345
+1.650732	3.281288	2.527197
+1.948992	3.622868	2.521395
+2.372375	4.324125	2.514500
+2.897143	3.536327	2.502653
+3.310068	4.967055	2.514384
+3.380378	4.194244	2.526176
+3.618125	3.902813	2.511094
+3.743623	2.785217	2.511014
+3.876915	4.923682	2.520448
+3.967176	1.694824	2.514824
+4.307410	3.860392	2.527199
+4.429173	0.455276	2.525157
+4.655197	6.227566	2.518026
+4.665923	1.753462	2.519385
+0.531216	0.555000	2.518243
+0.744429	6.208286	2.526143
+0.934222	2.206111	2.529000
+0.983832	1.066287	2.527904
+1.238395	0.347778	2.525123
+1.672331	6.245276	2.530920
+1.769512	0.699512	2.529512
+2.041377	1.281138	2.541737
+2.053938	0.690702	2.552982
+2.394000	6.400000	2.508000
+2.756695	1.128898	2.522797
+2.853870	0.023448	2.549349
+3.112986	4.190569	2.530711
+3.130260	4.796104	2.526623
+3.303274	0.018053	2.534690
+3.985702	6.348764	2.532837
+4.537069	1.017759	2.516724
+4.673833	4.027667	2.516833
+0.536860	1.515041	2.538140
+0.537128	2.949773	2.560101
+0.755041	0.661488	2.531157
+0.847281	4.425392	2.545530
+1.187961	0.638750	2.541645
+1.235039	5.413586	2.552287
+1.331513	6.116933	2.555819
+1.681478	5.420522	2.532696
+1.692620	1.227380	2.548984
+1.852000	5.019163	2.537953
+1.979944	3.880281	2.548652
+2.128043	1.031304	2.535652
+2.260517	2.463276	2.533448
+2.541786	5.612937	2.544048
+2.556711	2.197763	2.529342
+2.891061	2.903128	2.543464
+2.939326	3.979775	2.541723
+3.015351	2.398129	2.557719
+3.250141	2.026761	2.535493
+3.424741	0.439310	2.531810
+3.580674	6.153820	2.530112
+3.941633	0.359660	2.535442
+4.453465	3.429604	2.532772
+0.521842	3.434803	2.546250
+1.086025	4.543185	2.561531
+1.209908	4.775505	2.547798
+1.459494	4.150759	2.539620
+1.898557	3.371443	2.545155
+1.942182	5.308682	2.556182
+2.185493	3.568028	2.544085
+2.353778	5.231185	2.551704
+2.503462	3.608956	2.560440
+2.816154	0.788077	2.542981
+3.378608	3.930253	2.544684
+3.537847	2.306794	2.555311
+3.833854	3.194688	2.542292
+4.077838	2.209730	2.534595
+4.131368	1.009368	2.552526
+4.168194	0.468472	2.554537
+4.301471	2.131176	2.542647
+0.952720	2.524400	2.559120
+1.414374	3.684019	2.573759
+1.501952	1.035833	2.576571
+2.420899	0.435043	2.573217
+2.628075	4.283054	2.564519
+2.807763	2.220274	2.560457
+3.550405	4.900270	2.563581
+3.610588	1.164163	2.563439
+3.902203	2.956780	2.547627
+4.128602	4.985508	2.564492
+4.203593	3.546587	2.560419
+4.414286	1.723036	2.550714
+4.459975	4.594081	2.565894
+4.480182	5.216364	2.556727
+4.652357	5.026650	2.568809
+4.666839	3.144943	2.557931
+0.525217	2.222717	2.560761
+0.960909	0.010000	2.554545
+0.996034	0.363190	2.565172
+1.359624	3.007970	2.568045
+1.607286	5.004429	2.563000
+1.711377	3.542395	2.569401
+1.768704	3.048611	2.572963
+2.088478	2.946957	2.562609
+2.292674	5.750698	2.563605
+2.644229	0.606432	2.570176
+2.860465	2.651395	2.558372
+2.930095	1.799714	2.577079
+3.091299	6.178468	2.580286
+3.334187	6.067355	2.586667
+3.638261	1.438261	2.560145
+3.727941	5.747647	2.557059
+3.828333	5.295370	2.562037
+3.855796	2.308938	2.578274
+4.091201	3.134047	2.584047
+4.250128	4.114615	2.559872
+4.278000	4.779000	2.565143
+4.436281	0.716942	2.565537
+0.517722	4.935316	2.575823
+0.932987	1.955325	2.584870
+1.174304	2.256311	2.588350
+1.380973	0.792478	2.578938
+1.577108	2.877169	2.578193
+1.685153	5.685194	2.593313
+1.747273	3.787727	2.564318
+1.892587	2.778187	2.591973
+1.988264	4.149097	2.583264
+2.166061	0.452929	2.574545
+2.310107	1.280643	2.591850
+2.367217	3.302565	2.579913
+2.442216	3.045412	2.580206
+2.593061	0.058131	2.597336
+2.624801	5.875909	2.591790
+3.044118	5.918235	2.576471
+3.333813	3.614676	2.574173
+3.600698	0.599070	2.577093
+3.663089	3.010244	2.582033
+4.441494	5.478276	2.585575
+4.494519	5.910000	2.573111
+0.520183	6.182385	2.584587
+0.519800	3.784400	2.584800
+0.521053	1.977895	2.582105
+0.749567	1.152987	2.596017
+0.990458	5.608431	2.601176
+1.175690	1.928103	2.581034
+1.204652	6.358182	2.590588
+1.248383	3.890240	2.589222
+1.316328	2.747574	2.606459
+1.881591	0.486667	2.603258
+2.244855	0.220217	2.587826
+2.451071	4.102262	2.588810
+2.754404	3.731124	2.599679
+2.793585	5.672981	2.591321
+3.433493	2.550478	2.596801
+4.257757	1.243694	2.604037
+4.453023	0.209302	2.580233
+0.740767	3.185879	2.603546
+0.744397	3.889397	2.596810
+0.790373	5.414533	2.606293
+1.141971	5.923019	2.615367
+1.381750	1.808500	2.593000
+1.773226	1.616989	2.592258
+2.696154	3.435128	2.598034
+2.871277	4.219574	2.592128
+3.877872	4.097340	2.592128
+4.055500	5.675900	2.597900
+4.189037	0.752222	2.600444
+4.245577	5.244615	2.587115
+4.325364	5.714904	2.607548
+4.661984	2.685709	2.607935
+4.663902	4.753049	2.602317
+0.532658	0.785443	2.605063
+0.537764	4.045000	2.625590
+0.948269	2.990641	2.609615
+1.086111	1.492778	2.605317
+1.134601	5.013497	2.605276
+1.790406	6.021265	2.628401
+1.995593	0.162667	2.609741
+2.299455	2.827891	2.614727
+2.707650	2.458060	2.629126
+3.076544	0.128456	2.607426
+3.171938	1.671125	2.606063
+3.287411	0.700670	2.615402
+3.312234	5.257056	2.615990
+3.512347	5.632721	2.621190
+3.525854	6.387561	2.603415
+3.709884	5.089884	2.603023
+3.736271	3.712712	2.598136
+3.748874	6.312517	2.605563
+3.915044	2.634167	2.619649
+4.507546	1.370417	2.611111
+4.673267	1.993663	2.601584
+0.531179	4.616829	2.626341
+0.532674	2.661444	2.626898
+0.533346	4.340769	2.633308
+0.728793	2.093621	2.613276
+0.759958	2.359792	2.623792
+0.758000	2.824846	2.617615
+1.151220	3.159762	2.625744
+1.410855	0.544737	2.617171
+1.437373	2.276314	2.626186
+1.461399	5.546923	2.619231
+2.032412	2.038235	2.618000
+2.826098	1.339268	2.606341
+3.130324	2.820926	2.620000
+3.287592	0.259634	2.624817
+3.353770	2.963811	2.623648
+3.675800	0.921400	2.610000
+3.982680	3.723196	2.620722
+4.015613	4.517350	2.630912
+4.144313	6.153359	2.631565
+4.660187	3.802336	2.628785
+4.661563	4.252969	2.612969
+4.682391	1.175652	2.609565
+0.532226	5.705110	2.645799
+0.748947	0.891579	2.620526
+0.960833	1.703214	2.626429
+1.167657	1.247483	2.641434
+1.488025	5.290988	2.634259
+1.526952	2.003524	2.629524
+1.673107	2.405000	2.634854
+1.743444	4.032384	2.633046
+1.765877	4.461801	2.628578
+2.102195	5.506234	2.645337
+2.163140	1.720814	2.623256
+2.241939	2.183091	2.629818
+2.622632	2.712105	2.623474
+2.642069	0.941724	2.619138
+2.806093	4.457417	2.633709
+3.041983	1.457190	2.623223
+3.039667	5.668500	2.622833
+3.076181	0.838611	2.629375
+3.219025	3.202086	2.641247
+3.253366	5.798000	2.630927
+3.459063	2.073750	2.636016
+3.606556	3.268036	2.635589
+3.621702	4.137518	2.638156
+3.701122	2.110102	2.629898
+3.918095	5.874127	2.628095
+3.935977	2.044828	2.629885
+4.188371	0.215140	2.644803
+4.359293	3.012989	2.641033
+4.447660	3.663723	2.622340
+4.664601	0.395460	2.635153
+0.524286	1.745714	2.628000
+1.246996	3.454032	2.643004
+1.248271	0.992944	2.651682
+1.440233	4.839535	2.634341
+1.475615	4.390462	2.642962
+2.129912	5.155242	2.637841
+2.250588	0.851307	2.642353
+2.522614	3.866863	2.639150
+2.920643	4.888006	2.645434
+3.070552	2.149816	2.648098
+3.084753	4.425157	2.647982
+3.367770	1.834865	2.638851
+3.531791	2.792090	2.627463
+3.590686	5.319840	2.647666
+3.680795	4.467500	2.635341
+3.751188	4.736875	2.642875
+3.863457	1.486543	2.631728
+3.900333	6.122111	2.636556
+4.085882	3.951078	2.638333
+4.157468	5.896709	2.637595
+4.187091	1.708182	2.641636
+0.540536	0.125179	2.640357
+0.990984	5.226230	2.637213
+1.023974	4.266538	2.638974
+1.243229	0.090646	2.663274
+1.364333	5.078000	2.644833
+1.573392	0.145636	2.666908
+1.856800	2.241600	2.645333
+2.218293	4.724042	2.655749
+2.657175	0.353234	2.664535
+3.395417	1.053833	2.657458
+3.759247	1.713011	2.647957
+4.079378	2.427772	2.652073
+0.958541	3.336865	2.662649
+1.060385	2.756154	2.661319
+1.186313	2.517095	2.678547
+1.240855	4.141453	2.656581
+1.632649	0.424106	2.665364
+1.921096	1.807123	2.657329
+2.034556	5.916006	2.669852
+2.044006	6.217596	2.666409
+2.068673	2.367092	2.668878
+2.276901	1.928592	2.652394
+2.279524	5.979921	2.651429
+2.305574	3.745574	2.650656
+2.624943	6.142586	2.672069
+2.670597	2.024925	2.650149
+2.711919	4.712551	2.668555
+3.261012	4.626640	2.660243
+3.511509	4.671321	2.660189
+3.970901	1.182973	2.654685
+4.123874	1.461982	2.652703
+4.351744	0.935814	2.650814
+4.667852	0.662349	2.659463
+4.669888	3.386180	2.648315
+0.734359	4.865846	2.673128
+0.775914	0.413710	2.674140
+0.961434	0.595814	2.673372
+1.009304	6.215304	2.671304
+2.137966	2.624068	2.675480
+2.224298	4.201157	2.674298
+2.411455	2.597818	2.668273
+2.594362	1.374947	2.678245
+2.836667	5.994881	2.669167
+2.864074	6.265556	2.682481
+2.937365	5.447814	2.679341
+3.229854	1.267816	2.687694
+3.431245	4.424440	2.677386
+4.266667	3.322510	2.677412
+4.671111	2.257222	2.666825
+0.540851	6.393617	2.672340
+0.736250	3.450357	2.665714
+0.747826	1.818478	2.665435
+1.340270	1.435811	2.683446
+1.450516	2.537613	2.679032
+1.727217	0.910061	2.680214
+1.729315	5.202904	2.686411
+2.187681	3.151304	2.676957
+2.251641	4.458750	2.676484
+2.266667	6.361897	2.691626
+2.526839	4.498705	2.689326
+2.528647	5.355714	2.680451
+2.604428	5.034797	2.690775
+2.903224	0.277632	2.682829
+3.131395	3.714264	2.686512
+3.153793	3.465862	2.668621
+3.342247	1.504270	2.668090
+3.680139	0.062404	2.688362
+4.171818	1.965682	2.673409
+4.181026	2.672821	2.667308
+4.420440	2.745535	2.684214
+4.657319	0.044933	2.687748
+0.529530	5.211745	2.687047
+0.546745	1.028019	2.698396
+0.906400	5.848400	2.676933
+0.920909	1.325207	2.682314
+1.237855	5.672013	2.703729
+1.332735	4.610122	2.694327
+1.503148	3.450247	2.688642
+1.556452	3.104301	2.689677
+1.667838	2.666419	2.690473
+1.861007	1.400104	2.696528
+1.887107	1.125028	2.706713
+2.005664	4.392920	2.687434
+2.031855	4.913345	2.699527
+2.105161	3.382796	2.687634
+2.153529	0.011176	2.680588
+2.346404	1.542959	2.697678
+2.430053	2.340160	2.691016
+2.572645	6.386777	2.690826
+2.585000	1.627097	2.685968
+2.860899	3.202360	2.685056
+3.165149	3.983731	2.696381
+3.503210	3.772399	2.694982
+3.774267	0.725600	2.683733
+3.937322	0.120711	2.708104
+3.956646	5.133634	2.705217
+4.207182	5.491572	2.705203
+4.420446	6.345785	2.700246
+0.776382	1.537884	2.705870
+0.908933	4.682267	2.688933
+1.016542	3.844034	2.700000
+1.513300	1.620800	2.697500
+1.674609	1.819922	2.699531
+1.925135	4.661189	2.699946
+2.172164	3.949179	2.702015
+2.505636	1.853636	2.688909
+3.078203	6.388281	2.708828
+3.200843	5.475172	2.705670
+3.604505	3.527143	2.696813
+3.685130	6.003239	2.708227
+3.790493	0.470987	2.706951
+4.158803	6.388632	2.703675
+4.238129	4.334082	2.709456
+4.430909	2.270000	2.685455
+4.444973	4.172295	2.704809
+1.014737	3.570526	2.694737
+1.602431	0.682099	2.717514
+1.882727	2.540420	2.712448
+1.921250	5.685395	2.708355
+2.512251	1.131602	2.716234
+2.831762	1.576211	2.712291
+2.856641	0.539733	2.715115
+2.868545	0.960933	2.717985
+3.129558	0.517666	2.720442
+3.133700	1.901145	2.721762
+3.387724	3.401870	2.703659
+3.581970	0.323788	2.711212
+3.964842	0.893079	2.724184
+3.998968	0.623175	2.709048
+4.629157	2.933652	2.707303
+4.660055	0.926813	2.714725
+4.657636	4.487818	2.707636
+0.531961	2.417647	2.716275
+0.777677	6.054949	2.711515
+0.966407	0.168982	2.715808
+1.513122	6.248416	2.722127
+2.372299	5.543678	2.717816
+2.448526	0.230842	2.718421
+2.620231	3.173308	2.713846
+2.964299	4.636075	2.719346
+2.986316	1.187632	2.709474
+3.203151	2.501005	2.721781
+3.465669	5.081260	2.714016
+3.526053	1.653947	2.709342
+3.518653	0.775699	2.727306
+3.853548	3.534903	2.715097
+4.370661	6.064793	2.722314
+4.634306	6.075231	2.729364
+4.652209	5.528023	2.713023
+0.595478	1.346752	2.730510
+0.784878	2.599106	2.729919
+1.124651	0.784574	2.734651
+1.309716	2.077441	2.733602
+1.379948	0.319636	2.741429
+1.491071	5.996429	2.724375
+1.585827	1.373309	2.724892
+1.818966	5.454414	2.734966
+2.023030	0.907879	2.726742
+2.070818	3.721727	2.726000
+2.463177	4.775156	2.733646
+2.479805	0.799707	2.732732
+2.709505	2.926847	2.733919
+2.751406	5.273438	2.724063
+2.910544	3.456463	2.742075
+3.604632	1.892316	2.720105
+3.942047	5.431913	2.740906
+3.982486	4.812057	2.741343
+4.250533	4.594533	2.722667
+4.371507	1.557911	2.734349
+4.435698	5.041977	2.717907
+4.438498	1.896197	2.732582
+4.452414	4.802069	2.716897
+4.470000	1.138500	2.723750
+4.650169	5.265932	2.724576
+0.788299	6.337631	2.755755
+0.903357	4.079860	2.743007
+0.988571	2.360268	2.740625
+1.181654	0.486850	2.735354
+1.234600	4.380000	2.728000
+1.434203	3.995942	2.733841
+1.800375	0.259083	2.746042
+1.803390	6.258475	2.743051
+1.815070	2.014930	2.730563
+1.940433	3.179300	2.742667
+2.288533	0.627200	2.739200
+2.450444	2.087667	2.735556
+2.707755	4.103980	2.734490
+3.203448	5.054253	2.736264
+3.252063	4.256349	2.731270
+3.292287	2.245919	2.742960
+3.363737	4.855758	2.730202
+3.418315	0.081573	2.736404
+3.511148	1.330383	2.756530
+3.651667	2.597299	2.743218
+3.765000	1.287222	2.724444
+3.955871	3.295226	2.740903
+3.974063	1.817902	2.746696
+4.014385	2.844115	2.744115
+4.316525	2.478559	2.736780
+4.632598	1.548583	2.734331
+0.543074	5.960777	2.753108
+0.546780	0.342542	2.739153
+0.774047	5.175117	2.764543
+0.790346	3.696199	2.764773
+1.178487	1.717311	2.742521
+1.759851	3.372239	2.746716
+1.880063	0.706313	2.752125
+2.736379	1.804138	2.739828
+2.895298	1.997440	2.748571
+3.284699	6.265060	2.747169
+3.399123	4.074035	2.741754
+3.460672	5.875126	2.750420
+3.863488	4.340349	2.747209
+4.205572	3.750663	2.758163
+4.462105	3.901316	2.736842
+4.649643	5.811786	2.742143
+0.535600	3.117200	2.750800
+0.762108	4.309307	2.767139
+0.754271	5.656042	2.764271
+1.399615	1.199872	2.749231
+1.491938	5.748682	2.760388
+1.776011	4.890730	2.765618
+1.816604	4.240472	2.757170
+2.030909	0.356783	2.758881
+2.129521	1.396322	2.775239
+2.162250	1.120125	2.773125
+2.298234	4.984857	2.769735
+2.436892	5.792243	2.769135
+2.950719	2.546601	2.766928
+3.037373	3.038898	2.760508
+3.332250	2.735700	2.761850
+3.421163	0.530720	2.771801
+3.749589	2.847363	2.769658
+3.915000	6.384521	2.767055
+4.201961	2.213137	2.751667
+4.568899	2.485321	2.757844
+0.537273	3.615795	2.759886
+0.564088	0.596101	2.761321
+0.960757	4.931568	2.776108
+1.042482	2.099433	2.778830
+1.068169	5.411901	2.771479
+1.215385	2.939091	2.771469
+1.228542	3.691146	2.765365
+1.363750	3.240766	2.773266
+1.648255	4.647562	2.778975
+1.762383	0.018135	2.797098
+2.169267	5.723933	2.771200
+2.289873	3.526709	2.760633
+2.515227	3.442500	2.755000
+2.687552	5.523237	2.778880
+2.721789	0.745474	2.762105
+2.926064	2.807128	2.771170
+3.533224	6.212694	2.766653
+4.041166	4.164028	2.778622
+4.395129	5.306258	2.782419
+4.658444	4.051778	2.753556
+0.999477	1.083721	2.791948
+1.185906	5.188898	2.777638
+1.221552	6.183190	2.779397
+1.630548	2.180411	2.791918
+1.636364	1.136667	2.776515
+1.773679	2.914811	2.777736
+1.941089	3.985545	2.779406
+2.278626	0.386565	2.781527
+2.447778	4.258086	2.782407
+2.654342	2.243772	2.780044
+2.754333	1.180889	2.770667
+2.916066	2.297377	2.778525
+3.024259	4.189630	2.764630
+3.163118	1.022971	2.793559
+4.026263	0.377105	2.780526
+4.201429	5.109341	2.778352
+4.384888	0.334218	2.798139
+4.416528	0.064306	2.770139
+4.661509	3.601509	2.774340
+0.552230	2.109189	2.786824
+0.560796	5.465995	2.800498
+0.776098	3.003943	2.800894
+0.983906	4.464017	2.804848
+2.251581	5.333185	2.802450
+2.522237	0.542345	2.801321
+2.928894	0.052211	2.793317
+3.881021	3.938290	2.798812
+4.102404	3.499519	2.797548
+4.238676	0.555588	2.790098
+4.231522	4.858478	2.781957
+0.558624	2.850201	2.814228
+0.731726	0.184772	2.805381
+1.195038	4.804427	2.794656
+1.328407	5.398956	2.798956
+1.444454	0.901965	2.801266
+1.555200	5.036350	2.798950
+1.858580	3.602301	2.815227
+2.022564	1.628974	2.795000
+2.077536	2.952899	2.796232
+2.917843	3.978824	2.793922
+3.124481	4.813485	2.806680
+3.192931	0.021954	2.802701
+3.622527	2.342582	2.803516
+3.672168	5.752937	2.795385
+3.863706	2.444924	2.798731
+3.914733	5.686000	2.798333
+4.163778	1.076044	2.803244
+4.661579	1.789474	2.787895
+0.544545	1.580000	2.798636
+0.549667	3.363067	2.809067
+0.885252	0.799496	2.804748
+1.725562	3.842630	2.820301
+1.739442	5.830172	2.812361
+1.989336	5.285071	2.808815
+2.316182	2.991727	2.808364
+2.395000	4.005000	2.817378
+2.480687	2.795267	2.815458
+2.705878	0.151832	2.808092
+2.739487	5.786769	2.811692
+2.990958	5.851250	2.815708
+3.006972	6.107156	2.805872
+3.120489	0.266895	2.828680
+3.227456	5.993713	2.819474
+3.440515	5.469152	2.819242
+3.599865	1.081892	2.809324
+3.699767	5.497674	2.807829
+3.694194	1.497258	2.802581
+3.780233	4.972907	2.806163
+3.859500	2.189167	2.803500
+4.660500	1.309750	2.802750
+1.005238	6.022585	2.816190
+1.462623	2.916721	2.808525
+2.246889	0.151556	2.820778
+2.423846	0.010000	2.810769
+2.428267	6.061333	2.817200
+2.479134	3.690397	2.821408
+2.830982	5.057991	2.826652
+2.912465	3.731690	2.815775
+3.331184	3.616184	2.824145
+3.509651	2.938488	2.822907
+3.696212	3.096212	2.813788
+4.168136	3.033559	2.808305
+4.159818	5.722000	2.811636
+4.381796	3.515550	2.829142
+4.404800	5.830633	2.831267
+4.466186	0.688186	2.824419
+4.644556	3.195148	2.814675
+0.545783	6.218313	2.833434
+0.574760	3.861336	2.841336
+0.813333	2.206875	2.816250
+0.970211	0.391368	2.821474
+0.988667	1.850000	2.819778
+1.289531	5.897469	2.840375
+1.328988	0.666883	2.836316
+1.402370	4.233642	2.832659
+1.457434	1.836579	2.839967
+1.470444	3.758222	2.829185
+1.600000	5.527407	2.839226
+2.018788	2.178333	2.825227
+2.401940	3.234776	2.831741
+2.686957	4.343430	2.834831
+3.007709	5.244916	2.831006
+3.037314	1.687143	2.828571
+3.294829	1.687222	2.837607
+3.846580	4.593446	2.840959
+4.431607	5.558571	2.819643
+4.446545	4.438091	2.826727
+0.552609	4.746783	2.844348
+1.001827	1.552019	2.831058
+0.999157	3.132410	2.830723
+1.422444	0.029259	2.834370
+2.075393	0.586517	2.835955
+2.458202	5.176404	2.835618
+2.680229	3.867163	2.853954
+2.711356	3.588136	2.828814
+2.965081	0.743257	2.844821
+3.594733	3.965800	2.839733
+3.720891	3.715487	2.850084
+3.759394	5.239091	2.837803
+4.018971	1.339485	2.840662
+4.268873	4.035352	2.842923
+4.636082	4.692990	2.843196
+0.564335	1.843064	2.856821
+0.559474	4.481140	2.862456
+0.755000	1.008173	2.841635
+0.780370	1.964259	2.846852
+0.785723	3.272215	2.860154
+1.134459	3.350796	2.864140
+1.212135	3.940391	2.861744
+1.211509	2.278679	2.839623
+1.935429	6.071333	2.853000
+1.978088	2.729681	2.858685
+2.199812	6.135564	2.858195
+2.231859	2.297692	2.853654
+2.931264	4.415824	2.857637
+3.293438	5.690341	2.856790
+3.337346	2.008499	2.861743
+3.580435	2.094348	2.850435
+3.841543	1.088743	2.850286
+3.934828	3.065000	2.842069
+4.005836	6.168662	2.857695
+4.191637	0.812847	2.856584
+4.333110	1.321159	2.852805
+4.386641	3.170859	2.859805
+4.636063	0.254344	2.854525
+4.646082	2.038144	2.848557
+0.826298	5.422009	2.879142
+0.994683	5.643303	2.874163
+1.115623	4.210101	2.871953
+1.162965	0.244070	2.867638
+1.619528	4.356604	2.852642
+1.635628	4.095953	2.867256
+1.993547	0.125893	2.870587
+2.047526	4.204742	2.868351
+2.096887	4.548675	2.861258
+2.208592	1.771549	2.859437
+2.224318	2.774545	2.849091
+2.352203	1.282203	2.858305
+2.551788	2.499416	2.868978
+2.718065	2.698581	2.859742
+2.997885	1.385962	2.855288
+3.042971	5.599239	2.874964
+3.216967	4.470219	2.874727
+3.257376	5.276540	2.866844
+3.377000	0.287667	2.857083
+3.439677	2.516075	2.860108
+3.485000	3.210250	2.850750
+3.514041	4.247876	2.861503
+3.618968	4.790903	2.855097
+3.731266	3.349177	2.859684
+3.783857	0.268429	2.850000
+3.925894	1.581014	2.860725
+4.626012	6.306607	2.860714
+0.547826	4.994783	2.865362
+0.554017	4.138547	2.868205
+0.577396	0.831245	2.879660
+0.794940	0.569116	2.878594
+1.232000	2.695800	2.861200
+1.319910	5.006306	2.869279
+1.715000	3.165417	2.868125
+1.820732	2.350000	2.868293
+1.853889	4.472111	2.871000
+2.365019	0.985393	2.874869
+2.352108	4.587189	2.875189
+2.437465	1.707465	2.862254
+2.651959	0.965284	2.878325
+2.711473	3.341240	2.877209
+3.210428	3.344385	2.872086
+3.595860	4.499409	2.869946
+3.658588	0.617062	2.878814
+3.675091	6.383727	2.875909
+3.704701	0.869104	2.875522
+3.752941	4.157765	2.864471
+3.884757	5.937427	2.869515
+4.186545	5.976021	2.872513
+4.209742	1.816753	2.878196
+4.244762	6.236190	2.859881
+4.405328	2.110246	2.868443
+4.619400	4.958133	2.877800
+4.633015	2.716332	2.871910
+4.642273	4.278030	2.857879
+0.989286	2.630260	2.879026
+1.098768	1.319783	2.888696
+1.350645	3.494274	2.881694
+1.453417	4.792814	2.885075
+1.525772	0.507805	2.881545
+1.618000	2.490571	2.870429
+1.670000	6.083451	2.891882
+1.828544	1.741553	2.877961
+2.185620	0.803471	2.872562
+2.239863	2.031684	2.890756
+2.746094	1.402969	2.876094
+3.265742	3.085781	2.889180
+3.349922	3.869845	2.876744
+3.385773	0.917629	2.874948
+3.399282	4.666133	2.883149
+4.093054	4.477096	2.887635
+4.120047	2.538821	2.887217
+4.365804	2.897054	2.881339
+0.587417	2.589970	2.904024
+0.795717	5.882245	2.905281
+0.805333	1.714267	2.890000
+1.475362	2.681159	2.882464
+2.001504	1.915398	2.883805
+2.254959	3.802764	2.883740
+2.298175	2.542698	2.890238
+2.638041	1.975773	2.894124
+2.716267	6.030800	2.891511
+2.870189	4.795245	2.897623
+3.280994	1.423205	2.909295
+3.716032	1.722857	2.889048
+3.790059	1.967059	2.892941
+4.048138	2.024575	2.892186
+4.421913	0.937478	2.887826
+0.780663	4.635128	2.909643
+0.820641	1.251352	2.907367
+0.990283	2.888679	2.894434
+1.214394	1.903788	2.898333
+1.241000	1.076235	2.899353
+1.251497	1.532925	2.895170
+1.334063	2.480208	2.891250
+1.591203	5.270886	2.901646
+1.738281	1.505313	2.893906
+1.988533	3.383743	2.913084
+2.048613	2.473323	2.913968
+2.056667	5.519128	2.916744
+2.163088	4.794118	2.900049
+2.498072	6.279699	2.893072
+2.504000	1.468600	2.889000
+2.627000	4.884200	2.893700
+3.079634	2.080650	2.908659
+3.092132	3.572574	2.893750
+3.144036	2.846637	2.906054
+3.577731	0.163529	2.899916
+3.757257	6.151600	2.907714
+4.149273	3.266364	2.909636
+4.210175	0.149605	2.910307
+4.638151	0.517395	2.895714
+0.562613	5.727789	2.910402
+0.575678	1.164746	2.908559
+0.920709	3.499803	2.914921
+1.004144	6.261781	2.917500
+1.062536	0.611312	2.921341
+1.185833	0.010000	2.912083
+1.450863	4.530203	2.915685
+1.985848	5.820939	2.914874
+2.023400	6.304800	2.899800
+2.085569	5.055976	2.917358
+2.251351	4.356351	2.901622
+2.477079	5.428168	2.912079
+2.546971	3.035477	2.918133
+2.600449	4.627978	2.904719
+2.907442	0.387442	2.912558
+3.118970	2.343212	2.913333
+3.513097	5.224773	2.925938
+3.795065	0.030325	2.910844
+3.895146	2.677961	2.902039
+3.978011	3.695966	2.918977
+0.778571	2.765306	2.907551
+0.821531	2.440714	2.927143
+1.410306	6.114585	2.930044
+1.423771	6.373829	2.915829
+1.578886	3.378257	2.931629
+1.821166	5.112914	2.929580
+1.825929	1.270796	2.917345
+2.136087	3.161196	2.923750
+2.674141	1.646520	2.919780
+3.210132	0.757368	2.907500
+3.232430	4.097664	2.926776
+3.507990	3.453920	2.919749
+4.062528	5.268210	2.925795
+4.180732	1.540427	2.930915
+4.373627	2.635840	2.936933
+4.387752	4.669922	2.913488
+4.624673	1.088844	2.920251
+4.627841	2.286705	2.918182
+0.992422	5.164297	2.929219
+1.661173	6.361939	2.926071
+1.685920	1.943793	2.930057
+1.736331	0.977171	2.938768
+1.729010	2.715623	2.942204
+1.825287	5.622184	2.920805
+2.259347	5.891847	2.946705
+2.662846	0.364154	2.924385
+2.862826	5.413913	2.931087
+2.963523	3.280783	2.939075
+3.121375	6.280750	2.925625
+3.380063	1.173365	2.940283
+3.905000	0.725987	2.924013
+4.047445	2.288248	2.935401
+4.057355	4.977806	2.936710
+4.456875	1.716354	2.917500
+0.585404	2.304485	2.949522
+0.582712	5.236356	2.933983
+1.043333	3.735310	2.948178
+1.346042	5.667292	2.935417
+2.273591	6.372317	2.940270
+2.824747	2.143434	2.936061
+2.844615	6.230256	2.929744
+2.853065	4.171429	2.955377
+3.097868	3.863807	2.938629
+4.608776	5.418299	2.942313
+0.745729	6.141563	2.938125
+1.975950	1.084380	2.948264
+2.113418	3.606962	2.942532
+2.268871	1.552097	2.938710
+2.325197	5.636535	2.947717
+2.677410	5.228584	2.962410
+2.859203	1.822319	2.949420
+3.056356	5.022712	2.964350
+3.131000	2.590000	2.942800
+3.350226	4.983982	2.951538
+3.522110	5.682110	2.957156
+3.519710	1.598696	2.946667
+4.369305	2.353874	2.966556
+4.382044	3.815660	2.962013
+4.609503	3.429752	2.954876
+4.607908	5.681503	2.950392
+0.630000	6.400000	2.930000
+0.778592	4.123944	2.948732
+0.793213	4.993371	2.972081
+0.832313	3.873955	2.958507
+1.043587	4.672310	2.966474
+1.068624	0.886746	2.972963
+1.201522	4.449755	2.972364
+1.211739	3.118804	2.956087
+1.293286	0.441714	2.954143
+1.439294	2.073176	2.971676
+1.506768	1.572348	2.971311
+1.582976	0.756976	2.961756
+1.610675	0.124262	2.966793
+1.640513	3.638376	2.960684
+1.724115	0.362718	2.975062
+1.905962	3.031122	2.966218
+1.954537	0.825610	2.966244
+2.029538	3.835692	2.952154
+2.570364	5.664227	2.963500
+2.589734	1.220631	2.963688
+2.589788	4.111555	2.964488
+2.772178	0.599530	2.967054
+2.963931	0.982901	2.966069
+3.381854	6.183609	2.969371
+3.428922	2.257059	2.956863
+3.856667	0.476250	2.954896
+4.061374	5.553132	2.958626
+4.440645	4.195806	2.954194
+4.451496	6.150709	2.956142
+4.604857	2.972714	2.969171
+4.603529	5.945529	2.962059
+4.634242	0.822121	2.950606
+0.673841	3.557256	2.963659
+1.010698	2.274767	2.969767
+1.446349	3.097460	2.960794
+1.589677	1.322581	2.967097
+1.821967	5.375738	2.974098
+2.251799	3.397226	2.975488
+2.409465	0.290053	2.969626
+2.556105	0.736105	2.965684
+3.122000	1.208667	2.971111
+3.323333	6.397778	2.955000
+3.438519	0.697593	2.970556
+3.540000	1.878205	2.964188
+3.787949	1.307564	2.956795
+4.147686	2.791843	2.971843
+4.140172	4.728970	2.980129
+4.279718	5.443099	2.967606
+4.378636	4.918818	2.973182
+4.623243	3.737027	2.958919
+0.584430	1.404051	2.971772
+0.591183	0.380860	2.976774
+0.595098	3.049248	2.991732
+1.179446	5.487196	2.990369
+1.379280	0.210800	2.984400
+1.489661	1.083842	2.990367
+1.803846	0.618173	2.979760
+1.970240	1.464251	2.979701
+2.468077	2.138154	2.981769
+2.516000	5.915280	2.979360
+2.550647	0.084676	2.982806
+2.820882	2.895882	2.963235
+2.881604	2.427380	2.989626
+3.101616	0.539167	2.990783
+3.372746	0.041051	2.982271
+3.608080	2.766449	2.985435
+3.699009	2.511509	2.990819
+3.931100	3.446100	2.980400
+4.009053	0.951053	2.973684
+4.073558	3.929519	2.973269
+4.205401	4.244453	2.985766
+1.104513	4.938407	2.990442
+1.338686	1.311752	2.985839
+1.430426	4.010426	2.985638
+1.574441	5.748323	3.002484
+1.641067	2.957467	2.976667
+1.978692	0.430093	2.989346
+2.404566	4.815029	2.985838
+2.494366	4.409718	2.982958
+3.157006	1.845150	2.996407
+3.412473	5.913055	2.997527
+3.938529	4.280711	3.002010
+4.599196	4.001929	2.999678
+0.811795	1.493462	2.992179
+0.962454	0.085810	3.014282
+1.059556	5.862111	2.993667
+1.078889	1.711389	2.988056
+1.178089	6.085122	3.002846
+1.487313	2.331194	2.989701
+1.656981	4.911294	3.009865
+1.791356	4.681073	3.002655
+2.552769	3.498769	2.987231
+2.768261	3.131087	2.985652
+2.901264	1.558276	2.995057
+3.052028	0.081538	3.006573
+3.501915	3.710395	3.012948
+3.670876	5.887883	2.996934
+3.885631	6.353584	3.007952
+3.938226	1.796774	2.991129
+3.982487	0.260160	3.016417
+4.313269	5.173948	3.007120
+4.346824	6.392118	3.002471
+4.383024	0.503902	3.007171
+4.563333	5.178148	2.995741
+4.627188	1.560000	2.983125
+4.616522	4.498913	2.992391
+0.574348	5.966087	3.008152
+0.847073	4.360813	3.004797
+0.831297	0.318973	3.015622
+1.309068	2.894472	3.012050
+1.303876	3.712416	3.020758
+1.794305	4.256983	3.015932
+2.146888	1.269947	3.020186
+2.465091	3.864545	3.011727
+2.831880	5.656453	3.015556
+2.868916	1.234011	3.021111
+3.144691	5.851303	3.022443
+3.344422	2.699456	3.012177
+3.641162	5.008485	3.013586
+3.763290	5.653032	3.007806
+3.849693	5.406858	3.014483
+3.853712	2.903939	3.005076
+4.206617	3.605613	3.017361
+4.463099	0.146959	3.014094
+0.619245	0.134340	3.031321
+0.776604	5.644340	3.017107
+1.434645	5.456120	3.025519
+1.858778	2.137443	3.028125
+2.246563	0.470000	3.016172
+2.293333	5.157879	3.012879
+2.409600	1.883920	3.024160
+2.918045	2.687594	3.022481
+2.939975	6.012574	3.032277
+3.015106	3.033404	3.017553
+3.031495	4.592732	3.017268
+3.084866	4.289286	3.023170
+3.090000	5.392331	3.023006
+3.554808	1.361538	3.014615
+3.851057	4.848238	3.024626
+4.112820	0.502762	3.029622
+4.160495	1.222387	3.018288
+0.604194	1.656636	3.030276
+0.785479	0.807671	3.028082
+1.190548	2.123151	3.015616
+1.227989	5.166931	3.035556
+1.328938	0.876372	3.032566
+1.839646	6.226814	3.026726
+1.922000	4.036727	3.014000
+2.036383	1.704823	3.027730
+2.648554	2.311281	3.035289
+2.697941	6.395000	3.018824
+2.807178	0.194724	3.034110
+2.872027	3.916351	3.025946
+3.352867	0.468400	3.027867
+3.596714	5.454714	3.033857
+3.808177	2.271302	3.035573
+4.362868	5.669412	3.031912
+4.402759	1.153276	3.016724
+0.591667	2.059286	3.025714
+0.995349	4.046395	3.033140
+1.310984	1.722131	3.031639
+1.476782	5.098276	3.039425
+1.827576	0.012424	3.030909
+2.165479	0.229175	3.047228
+2.507978	5.039551	3.042135
+3.224842	4.770791	3.050253
+3.665972	1.103833	3.055250
+3.859615	3.197308	3.027308
+3.979545	5.775909	3.028485
+4.076650	3.050911	3.056404
+4.358105	3.354373	3.055452
+4.376240	1.928640	3.036240
+4.411852	1.474568	3.034691
+4.611852	1.865556	3.024815
+4.604184	1.318367	3.039694
+0.603711	4.297062	3.054175
+1.071839	0.389425	3.047241
+1.114377	2.486748	3.062340
+1.291735	4.682653	3.045918
+1.926182	4.897939	3.045758
+2.134639	2.932990	3.040103
+2.226963	3.986667	3.050444
+2.260786	5.418176	3.064025
+2.357424	3.634444	3.051566
+2.357818	2.835273	3.038182
+2.606012	2.816190	3.051905
+2.838409	3.475455	3.036818
+3.208217	0.964650	3.047261
+3.608493	0.433797	3.058464
+3.697647	4.651569	3.046471
+3.711103	3.544412	3.052059
+3.854268	4.025223	3.053185
+3.860929	5.142301	3.056195
+4.229257	2.142012	3.062167
+4.238431	0.978627	3.045294
+4.356806	0.758194	3.044722
+4.580442	2.505959	3.063363
+0.615091	3.318649	3.069221
+0.836852	2.113386	3.071852
+0.937294	6.056706	3.047059
+1.029681	1.944043	3.059894
+1.301309	4.214698	3.071779
+2.036773	5.275100	3.065100
+2.116545	2.195818	3.064682
+2.178099	0.974678	3.067427
+2.326323	0.718215	3.077677
+2.340226	3.089173	3.057669
+2.365336	2.363109	3.079397
+2.504116	0.510145	3.073275
+2.698911	3.694719	3.061386
+2.767626	4.997071	3.080657
+2.955570	6.392405	3.058734
+3.140643	1.590000	3.061053
+3.240539	0.247246	3.057425
+3.342381	5.428294	3.064960
+3.430638	2.936064	3.055745
+3.651544	3.064926	3.056029
+3.754658	1.539530	3.058718
+4.303206	4.470802	3.068473
+0.600556	2.796389	3.063611
+0.629172	0.616847	3.082930
+0.728088	1.871324	3.063824
+0.795752	5.242920	3.068319
+0.868333	1.045591	3.067796
+1.140300	3.509200	3.064400
+1.344414	3.302207	3.081172
+1.667595	4.473797	3.060253
+1.809377	3.813863	3.081713
+1.831977	2.506186	3.080819
+1.851461	3.541685	3.066067
+2.005217	4.402174	3.067702
+2.164639	2.673436	3.075326
+2.366364	4.208267	3.080398
+2.369153	1.141864	3.067119
+2.452162	2.621622	3.063784
+3.166927	6.061094	3.065625
+3.254877	3.647654	3.072222
+3.366824	4.262128	3.082804
+3.492162	4.796967	3.086186
+3.714184	4.397245	3.071429
+3.942389	2.493097	3.064956
+4.570455	4.779318	3.082143
+0.590200	6.240400	3.074400
+0.616429	5.447989	3.089577
+0.620177	0.982920	3.077168
+0.839900	3.130000	3.080348
+1.092000	2.755636	3.087182
+1.332266	2.646059	3.088079
+2.035725	4.664638	3.079420
+2.372338	6.080390	3.065974
+2.629547	6.191317	3.087613
+2.672617	5.463925	3.084346
+2.695846	2.573923	3.081692
+2.907789	5.223579	3.084105
+2.963410	3.686994	3.078728
+3.150000	5.940000	3.050000
+3.327005	2.448122	3.087310
+3.368018	1.743514	3.075946
+3.600000	0.010000	3.060000
+3.626393	4.168525	3.077705
+3.733908	0.198966	3.076782
+0.614457	4.822659	3.091685
+0.629560	3.779223	3.106736
+1.067917	1.485641	3.102564
+1.095000	1.155476	3.081905
+1.276556	5.848222	3.086000
+1.394232	0.628652	3.094569
+1.497568	6.120967	3.122077
+1.664955	5.524324	3.092252
+1.808000	5.792933	3.081467
+1.870442	1.880088	3.090796
+1.941758	6.006703	3.103242
+2.072295	0.638197	3.089344
+2.124315	6.191986	3.089863
+2.228841	4.516522	3.079130
+2.388758	1.400229	3.103693
+2.500719	0.941871	3.090863
+2.728981	5.875370	3.081389
+3.165393	3.217416	3.083483
+3.322698	3.402857	3.086190
+3.414000	3.183400	3.077400
+3.471455	4.509515	3.101381
+3.542456	6.354199	3.094128
+3.628608	3.922152	3.083544
+3.660653	2.063015	3.091658
+3.920761	1.143370	3.087391
+3.958051	4.571186	3.103729
+3.978148	1.383519	3.082407
+4.337213	3.048197	3.078852
+4.581728	0.364938	3.093519
+0.829332	6.313819	3.111169
+1.526292	1.825899	3.097191
+1.545745	4.687660	3.098511
+1.636916	3.183383	3.112246
+1.730515	1.661838	3.103235
+2.133487	5.713026	3.102993
+2.136038	1.920189	3.091509
+2.219130	4.941159	3.093333
+2.480000	1.641707	3.092561
+2.637381	1.462857	3.087619
+2.636863	1.820196	3.088235
+3.044909	0.775455	3.099636
+3.229945	5.170685	3.113151
+3.392329	3.983425	3.096027
+4.089104	6.053582	3.089552
+4.307248	4.019060	3.103490
+4.462569	3.596147	3.088991
+4.578966	2.108828	3.093931
+0.614406	4.554266	3.107063
+0.611190	4.043690	3.106905
+1.078693	3.264602	3.114716
+1.298685	6.285014	3.120630
+1.309775	0.016854	3.114494
+1.494802	0.393164	3.108870
+1.537893	3.816679	3.116643
+1.550377	4.260849	3.103113
+1.569021	2.534000	3.112383
+1.924551	2.799449	3.116435
+2.634435	3.295043	3.115565
+2.638000	4.770286	3.110286
+2.691007	4.519424	3.113381
+3.193438	2.207344	3.100781
+3.602194	0.831484	3.106839
+3.612222	6.101111	3.099667
+3.847700	6.028650	3.112100
+4.132923	1.897769	3.111308
+4.309740	5.918842	3.119385
+4.578312	3.209740	3.104286
+0.854523	2.866231	3.127588
+0.858194	3.640220	3.127048
+0.896061	0.552963	3.122727
+1.044767	5.313837	3.117326
+1.052529	4.288059	3.122471
+1.476947	3.534466	3.132176
+1.639533	5.969844	3.128599
+1.675067	4.032400	3.110533
+1.893800	3.246800	3.119500
+1.912118	0.219082	3.127012
+2.060135	0.019324	3.115135
+2.746538	1.016955	3.133494
+3.053333	4.050476	3.109286
+3.074449	3.454487	3.124601
+3.335948	5.692714	3.121970
+3.400792	2.065667	3.121667
+3.614847	3.313190	3.120123
+3.733200	1.815200	3.113867
+3.825814	3.772326	3.113721
+3.903465	1.997228	3.121683
+4.308075	1.693369	3.133610
+4.560851	6.311560	3.115248
+0.880652	1.692717	3.118804
+0.871169	4.790974	3.133117
+1.044895	5.658531	3.145431
+1.220912	3.957541	3.139751
+1.316803	4.916531	3.125034
+1.528333	2.805238	3.122381
+1.685254	2.297119	3.123559
+1.773426	1.394422	3.137729
+2.090484	4.169677	3.120968
+2.349530	0.054201	3.130940
+2.452821	4.608803	3.125470
+2.486731	5.288770	3.128414
+2.978380	4.827887	3.141502
+3.096190	5.621524	3.122286
+3.477760	0.223120	3.125520
+3.785692	0.646000	3.141577
+4.070934	0.753391	3.133356
+4.570667	0.645487	3.129487
+4.570980	4.299118	3.125588
+0.634694	2.487296	3.143112
+1.291184	1.937763	3.135000
+1.316212	1.504394	3.136818
+1.917964	5.546764	3.142509
+2.592751	0.270106	3.156376
+2.692348	2.069103	3.152902
+2.692326	4.268372	3.128372
+2.994000	1.968000	3.132000
+3.015357	0.295714	3.133690
+3.047959	1.375714	3.132041
+3.224744	4.468590	3.132051
+3.389455	1.498364	3.130364
+3.435285	1.015854	3.139756
+3.581090	2.331280	3.149668
+4.096705	6.305233	3.141783
+4.104336	3.361538	3.144755
+4.352766	2.811064	3.133191
+4.585814	2.760000	3.118372
+0.636207	1.231379	3.141494
+0.858750	3.378523	3.146591
+0.876538	2.556667	3.148718
+1.093429	3.006190	3.145714
+1.638036	2.054286	3.150804
+1.695693	1.144818	3.149489
+2.156349	1.495556	3.142698
+2.256075	1.720093	3.150280
+2.387438	5.779835	3.157769
+2.661560	3.946086	3.162569
+2.939948	2.227959	3.160103
+3.212189	6.331108	3.156216
+3.269810	0.677286	3.152048
+3.273492	1.286508	3.154206
+3.804286	2.696807	3.140924
+4.039974	1.628675	3.157870
+4.074884	4.101163	3.136744
+4.099206	5.115556	3.138571
+4.270000	0.045100	3.165267
+0.628686	5.085200	3.161257
+0.853501	5.846024	3.168457
+0.882227	1.306597	3.163655
+0.963894	5.072861	3.174543
+1.147487	0.696884	3.164271
+1.389164	4.473908	3.171752
+1.620114	0.908523	3.156364
+1.872750	0.972125	3.152875
+2.023167	3.691000	3.148500
+2.067673	3.440204	3.167837
+2.150000	6.397500	3.143333
+2.374500	6.323833	3.164833
+2.808937	0.421884	3.160242
+3.215714	2.989429	3.150286
+3.523583	2.597250	3.160833
+3.631647	5.220884	3.167068
+3.843342	0.916247	3.172986
+4.197966	2.391441	3.155678
+4.324233	4.721104	3.159877
+4.519342	0.894737	3.156053
+4.548725	5.541544	3.161074
+0.617551	5.755510	3.155102
+0.863176	5.468243	3.166284
+1.147528	0.190148	3.183100
+1.304255	5.615691	3.176064
+1.577111	5.295827	3.180938
+1.637439	0.615732	3.159024
+1.704110	6.389863	3.166027
+2.122802	2.435495	3.174835
+2.311452	2.068710	3.156613
+2.562715	3.041900	3.178914
+2.801111	0.754138	3.184215
+2.869286	0.010714	3.150000
+2.915226	4.419095	3.174422
+2.938462	1.730888	3.175207
+4.073960	5.373926	3.175336
+4.205161	1.426022	3.159677
+4.332582	6.215879	3.168297
+4.547045	5.802045	3.168068
+0.852059	4.541324	3.176176
+1.062056	6.219065	3.172991
+1.548302	0.026981	3.185535
+2.157048	3.197048	3.178667
+2.190839	5.973077	3.182168
+3.178317	3.860099	3.179505
+3.935281	5.592809	3.175281
+4.057363	4.873035	3.190000
+4.157851	5.699256	3.173471
+4.287514	0.322977	3.187225
+4.537803	6.064470	3.180227
+4.556304	5.017826	3.168478
+0.644805	2.232857	3.190260
+0.827101	4.172678	3.202531
+1.481391	1.290397	3.192583
+1.662885	0.239808	3.185288
+1.775054	5.050975	3.201552
+1.845149	0.477127	3.198507
+2.828082	3.011289	3.202925
+2.884167	3.277647	3.190588
+3.178375	2.629500	3.178375
+3.447256	5.035915	3.184634
+3.569355	1.652903	3.182581
+3.578505	5.646168	3.193178
+3.829828	0.395603	3.192845
+4.003011	0.052707	3.195663
+4.006403	3.601367	3.196079
+4.006761	2.828732	3.194930
+4.009735	2.215503	3.195291
+4.129688	2.618281	3.176875
+4.562500	1.682500	3.180500
+1.100619	3.725457	3.213540
+1.121461	4.774270	3.194719
+1.254048	0.436587	3.197937
+1.271545	5.357091	3.208409
+1.433535	3.036768	3.203838
+2.089831	0.417119	3.199492
+2.612594	0.021992	3.226729
+2.906904	5.462703	3.206904
+2.986506	6.208476	3.206766
+3.029881	2.836119	3.209284
+3.094375	1.119018	3.201696
+3.506393	0.623279	3.192623
+3.854138	3.368161	3.207414
+4.360326	2.572065	3.194674
+4.552857	3.828000	3.183429
+0.671004	1.478476	3.214535
+0.893686	3.890784	3.215333
+1.093647	5.965176	3.209765
+1.345943	2.165314	3.220457
+1.735185	2.952074	3.208741
+1.854113	4.551210	3.210403
+2.033529	3.938235	3.215147
+2.037834	5.055207	3.216636
+2.245432	4.727037	3.202099
+2.552426	5.985503	3.213077
+2.629018	5.686727	3.215018
+2.841224	1.448776	3.204694
+3.498508	3.529905	3.219937
+3.771905	1.314139	3.213956
+3.780090	5.796937	3.218243
+4.096180	4.346242	3.219410
+4.305568	3.767622	3.214649
+4.306196	4.991196	3.202935
+4.304371	5.495166	3.211656
+4.339828	4.253621	3.195345
+4.521964	4.545018	3.221964
+4.537808	5.290000	3.210959
+4.556061	1.139697	3.198788
+0.672273	0.334034	3.217898
+0.918170	2.316027	3.228571
+1.127735	4.514872	3.229872
+1.149238	0.956000	3.213238
+1.317200	2.420640	3.214000
+1.374259	1.058580	3.227716
+1.879778	0.730556	3.219667
+1.939800	1.572400	3.207800
+1.957241	6.309261	3.225468
+2.248630	3.795260	3.234986
+2.337640	0.324607	3.227865
+2.414355	3.991452	3.215161
+2.651865	1.252694	3.219275
+3.194630	0.438148	3.227259
+3.284820	5.931317	3.229611
+3.409754	6.164472	3.227359
+3.542304	5.899032	3.222811
+3.759279	6.268417	3.234028
+4.063841	3.860530	3.218411
+4.272075	0.603208	3.226478
+4.438263	2.285154	3.228067
+1.100035	1.755140	3.238287
+1.396304	0.204130	3.226087
+1.446935	4.069032	3.225403
+1.473917	5.802581	3.237512
+1.836693	5.308645	3.232829
+1.911972	2.302066	3.231033
+2.041579	1.135439	3.228596
+2.323631	3.400238	3.230298
+2.445578	4.875378	3.234940
+2.501333	4.381583	3.228000
+2.506585	3.742846	3.233659
+2.548824	3.495588	3.222647
+2.710833	1.639792	3.221667
+2.776364	6.355522	3.237037
+2.781136	2.754545	3.219773
+2.853036	4.100714	3.220893
+2.920097	2.539094	3.235825
+3.238390	1.887881	3.228475
+3.514534	1.251093	3.236478
+3.614271	2.876979	3.220000
+3.822205	4.211614	3.234370
+4.080400	0.988400	3.217600
+4.528400	2.982356	3.230178
+0.652368	5.984474	3.239386
+0.666346	2.995321	3.243397
+0.893905	0.227524	3.236952
+0.916875	0.853068	3.237216
+1.228861	1.295730	3.240819
+1.530302	1.574523	3.247236
+1.540603	4.931525	3.247305
+1.717143	3.404347	3.247599
+1.740000	4.770467	3.235421
+1.868088	4.139755	3.240441
+2.540769	0.743793	3.252944
+2.785979	6.059897	3.231959
+3.828168	3.007634	3.234275
+4.311209	1.115055	3.234615
+4.518472	4.076332	3.249782
+0.666284	3.511093	3.249617
+0.678100	0.023100	3.244200
+0.883947	1.902456	3.250000
+1.058477	2.104371	3.247881
+1.779060	6.136410	3.249060
+1.996316	2.048308	3.256805
+2.273600	2.936000	3.237600
+2.300614	5.102982	3.252544
+2.531639	2.486393	3.238525
+2.914909	5.720909	3.240727
+3.135303	2.389773	3.252727
+3.199200	4.942840	3.257160
+3.366212	2.792727	3.258030
+3.734706	5.452549	3.250353
+4.013623	5.884058	3.238116
+4.274386	3.510702	3.255000
+4.534149	1.445319	3.249681
+4.537750	3.417000	3.238500
+0.672097	0.812097	3.246452
+1.258895	2.859448	3.264807
+1.372066	5.128404	3.268873
+1.421961	0.814314	3.255490
+2.162281	4.358947	3.248421
+2.466018	1.822301	3.257788
+2.950806	3.867258	3.251452
+2.981073	0.586590	3.264713
+3.059174	0.086281	3.264876
+3.573616	4.325203	3.270738
+3.756717	0.036919	3.263838
+3.825387	4.978297	3.267678
+4.264125	3.206500	3.249500
+4.284859	0.859366	3.260423
+4.285374	5.239728	3.266463
+4.526383	1.924610	3.258298
+0.667500	1.999500	3.258000
+1.691441	3.670932	3.263390
+1.699643	2.698669	3.283117
+1.718824	4.346387	3.264790
+2.023896	1.788701	3.262468
+2.319667	0.897444	3.267000
+2.320213	2.601915	3.255532
+2.477054	2.794274	3.277676
+2.515971	2.234029	3.268417
+2.738491	2.359340	3.268868
+2.971437	5.062874	3.270958
+3.018412	5.952396	3.281894
+3.070036	4.610253	3.279603
+3.359710	2.269203	3.270580
+3.412261	5.292783	3.269217
+3.494262	1.871557	3.263852
+3.677897	4.744369	3.286799
+4.044340	0.304528	3.256604
+4.205278	2.950556	3.263611
+0.691536	2.706519	3.282321
+0.883673	6.083527	3.285745
+1.351625	1.744750	3.267500
+1.374437	4.724225	3.286690
+1.704851	5.687264	3.291020
+1.708961	1.854156	3.270779
+1.968805	3.049386	3.285358
+1.981371	4.810323	3.279194
+2.282026	1.240727	3.292883
+2.788843	3.496942	3.273388
+2.812378	0.191443	3.297988
+2.817926	4.664815	3.280593
+3.109238	4.291143	3.275238
+3.267059	1.638431	3.276863
+3.486346	0.033109	3.288718
+3.544865	4.053243	3.274324
+3.997885	3.178846	3.271154
+4.103137	1.227451	3.265098
+4.513952	0.192455	3.278024
+0.688708	4.384125	3.291125
+0.703504	1.729562	3.292044
+1.031356	0.411525	3.280339
+1.177556	2.617778	3.284667
+1.231375	3.159625	3.289625
+1.220660	3.423160	3.297264
+1.362374	3.717393	3.291362
+1.959298	2.605165	3.296364
+2.073175	0.882169	3.298254
+2.126652	5.531448	3.292986
+2.765682	5.206477	3.295909
+2.894255	1.223191	3.278298
+2.941932	0.944659	3.282841
+3.178269	0.904038	3.281731
+3.402778	3.042222	3.279167
+3.561203	3.789622	3.295636
+3.750350	3.617273	3.291608
+3.770370	3.951605	3.283704
+4.305909	2.026970	3.279545
+0.677734	6.230156	3.301328
+0.911784	1.534054	3.307351
+0.940000	0.010000	3.270000
+0.968112	1.100629	3.293846
+2.540758	5.101061	3.286515
+2.766400	1.868400	3.294700
+3.076829	3.646341	3.305061
+3.254907	5.501173	3.310247
+3.291830	0.190850	3.299739
+3.400732	6.392317	3.298780
+3.444010	0.411719	3.299115
+3.432021	3.287553	3.295745
+3.647155	0.258707	3.295776
+3.780231	2.260694	3.302486
+3.937465	1.825493	3.293239
+3.985688	6.130182	3.315195
+3.997286	2.449286	3.295000
+4.436531	6.394898	3.303061
+0.711304	1.056877	3.311344
+0.712129	3.251000	3.321581
+0.903538	3.035846	3.304462
+0.952764	2.724874	3.317889
+1.058195	4.084269	3.319914
+1.463140	6.242369	3.324766
+1.470167	1.957333	3.301000
+1.478756	3.270207	3.312280
+1.600000	4.557344	3.300938
+1.959000	5.733900	3.302800
+2.318019	5.355566	3.314057
+2.335828	0.581943	3.316306
+2.369762	3.154206	3.307222
+2.489781	1.073880	3.306721
+2.513500	1.521625	3.306313
+2.582061	4.147576	3.310667
+2.612906	0.487048	3.327368
+3.101185	5.284007	3.320348
+3.116667	2.099964	3.318261
+3.413227	0.825777	3.313108
+3.630116	3.129767	3.301279
+3.647680	1.031438	3.319150
+3.830065	1.559351	3.305325
+3.985270	0.571577	3.307973
+4.482375	0.471167	3.315125
+0.730143	0.572837	3.335931
+1.167188	4.983984	3.314297
+1.239842	4.289974	3.326359
+1.728485	2.442121	3.304848
+2.083719	4.583058	3.316364
+2.237778	1.896481	3.316852
+2.607163	5.402837	3.328365
+2.698647	4.904839	3.334404
+2.739351	3.748442	3.316948
+3.038594	1.547711	3.330683
+3.247910	3.455149	3.317836
+3.320208	3.689375	3.306250
+3.562347	2.128265	3.316327
+4.183710	4.574234	3.329718
+0.704343	4.905182	3.341533
+0.938067	4.379412	3.326807
+1.434355	2.695323	3.317097
+1.581443	2.218247	3.344021
+2.044536	1.378900	3.335601
+2.075455	5.281515	3.330076
+2.078043	2.825652	3.317391
+2.325359	4.527124	3.327778
+2.359091	6.075195	3.318052
+3.127534	3.170434	3.338428
+3.305636	1.109697	3.332242
+3.763161	2.527548	3.337935
+3.830400	5.232000	3.327867
+4.001527	2.827679	3.392439
+4.479174	4.843760	3.333347
+0.689848	3.996667	3.333788
+0.693718	4.637051	3.334103
+1.165525	6.371381	3.336961
+1.191645	5.787500	3.336382
+1.479186	0.600000	3.337209
+1.765105	0.083636	3.340420
+1.836429	1.236508	3.340635
+1.914854	3.570766	3.342956
+2.010439	0.108070	3.337982
+2.026650	6.087340	3.337931
+2.075036	0.622929	3.351357
+2.205199	6.271618	3.350663
+2.313947	2.370614	3.340088
+2.720944	4.409485	3.349270
+3.110397	4.037960	3.359943
+3.137921	5.729406	3.334356
+3.183256	6.134477	3.340407
+3.344367	4.191265	3.345753
+3.347170	3.929811	3.330755
+3.399488	4.795116	3.338419
+3.604627	1.468806	3.330149
+3.733486	6.021101	3.334404
+4.189689	1.810518	3.344560
+4.218923	4.099538	3.329385
+4.248507	6.050149	3.337463
+4.494141	3.640202	3.332222
+0.694255	5.476596	3.340957
+0.960743	3.539459	3.351588
+0.955457	5.313241	3.360055
+0.974037	3.271101	3.343028
+1.160000	0.010000	3.320000
+1.170545	1.526000	3.342182
+1.647168	0.414661	3.362861
+1.666387	0.760126	3.359580
+1.806439	3.905707	3.349707
+2.205125	5.785625	3.360271
+2.342308	4.229128	3.351949
+2.426775	5.592085	3.352769
+2.570470	4.620671	3.347651
+3.359532	2.528857	3.356208
+3.357500	1.414474	3.350000
+3.669065	0.761667	3.354187
+3.780441	2.003676	3.346029
+3.903947	1.105197	3.363750
+3.955556	4.699487	3.344017
+4.408723	5.695213	3.343191
+4.474307	2.744270	3.351049
+0.703883	5.226019	3.356117
+0.928766	6.330519	3.361169
+0.986410	0.641603	3.360577
+1.203947	6.119035	3.364123
+1.477129	5.572327	3.357772
+1.646381	1.380667	3.360952
+1.765496	1.631908	3.364351
+1.808670	5.916543	3.362766
+2.166053	1.615263	3.359145
+2.197257	4.909115	3.360442
+2.258090	0.117990	3.365628
+3.133893	1.304966	3.358993
+3.510227	4.564091	3.347727
+3.674583	0.503250	3.355333
+3.700986	1.766056	3.350704
+3.984545	4.055455	3.351970
+3.995192	6.386250	3.353462
+4.215000	2.237245	3.360612
+0.717593	2.387685	3.371204
+0.733443	3.736437	3.377395
+0.936000	5.586594	3.385125
+0.959219	4.839023	3.375508
+1.244359	1.992821	3.366795
+1.492329	4.334932	3.372808
+1.553333	3.893333	3.361053
+1.596829	6.033537	3.361829
+1.642966	4.127797	3.366695
+1.713297	3.156341	3.374384
+1.755254	0.994746	3.357119
+1.929274	3.300484	3.370242
+1.945629	4.372781	3.377483
+2.094600	4.147133	3.375900
+2.184783	3.568127	3.378462
+2.579851	3.292677	3.376840
+2.684412	0.922353	3.370662
+3.654634	3.378537	3.382561
+4.062946	5.190775	3.373023
+4.229800	4.829800	3.361800
+4.479769	0.730615	3.367615
+4.484519	3.203558	3.360865
+0.719000	5.728667	3.375467
+1.503617	2.464787	3.373511
+1.558000	1.138471	3.386647
+1.873205	0.298974	3.370256
+2.566308	2.013231	3.377308
+2.710959	5.877021	3.382705
+3.004556	3.405089	3.381479
+3.033134	1.858507	3.369552
+3.276524	4.460024	3.386952
+3.375288	5.722404	3.370481
+3.809317	2.788075	3.372609
+4.052438	2.034000	3.386594
+4.223701	6.298110	3.371575
+4.465769	5.930577	3.370385
+4.479692	4.335077	3.368769
+4.477500	5.122639	3.370833
+1.206513	5.529145	3.400461
+1.236098	0.590585	3.394683
+1.395841	1.421327	3.391416
+1.499293	3.516061	3.385960
+1.559850	2.905225	3.397800
+1.670920	5.421954	3.388391
+1.699559	6.314485	3.389265
+1.899748	5.512516	3.393899
+2.503975	0.175607	3.399038
+2.703851	2.586988	3.394689
+3.036400	0.316267	3.389911
+3.508704	5.503333	3.397623
+3.569434	2.693585	3.387925
+3.585949	4.977487	3.403282
+4.200000	5.817963	3.379444
+4.212059	0.170000	3.382941
+4.220891	2.488317	3.388812
+4.469638	0.989783	3.389565
+4.461429	6.181633	3.380816
+4.473043	5.459783	3.382174
+0.762303	1.302191	3.402079
+1.008214	2.479762	3.400595
+1.385273	0.376800	3.406691
+1.374078	5.957670	3.401165
+1.400000	0.010000	3.372500
+1.605376	5.141221	3.408427
+2.099082	2.258163	3.392857
+2.310636	2.122182	3.394818
+2.453523	6.300303	3.406023
+2.458192	5.847910	3.401751
+2.785277	5.594298	3.405277
+3.163502	6.378953	3.411372
+3.302319	0.604589	3.398986
+3.350310	2.030543	3.399302
+3.930986	0.818630	3.415507
+3.959143	1.364000	3.392143
+3.968500	5.430833	3.394500
+4.221932	2.747273	3.392159
+4.227679	1.379464	3.397679
+4.455167	1.258662	3.404201
+0.948082	5.861049	3.425601
+1.032595	1.324524	3.423119
+1.195985	1.097406	3.425761
+1.254394	3.927197	3.414508
+1.429759	5.328072	3.410000
+1.547729	0.176507	3.420306
+2.719419	1.406977	3.404767
+2.949719	2.315082	3.420304
+2.960939	4.839797	3.420203
+3.169821	2.716786	3.398929
+3.473288	1.665856	3.419452
+3.567881	2.368390	3.403559
+3.860154	0.206462	3.406615
+3.907055	3.781650	3.417508
+3.919124	5.677591	3.404161
+4.189924	0.438550	3.415420
+4.460909	3.878523	3.404091
+4.470857	2.481714	3.396571
+0.876481	5.074630	3.412593
+1.240714	0.835000	3.405952
+1.539889	1.760000	3.420667
+2.119273	0.327932	3.437886
+2.182996	3.289401	3.427753
+2.502078	1.295974	3.417273
+2.552551	3.917092	3.422857
+2.877074	2.047340	3.425691
+2.929024	2.712683	3.423049
+3.356792	5.095849	3.407925
+3.620413	5.751770	3.424690
+4.174317	5.569137	3.418561
+4.393981	1.566852	3.414722
+0.762000	2.144909	3.432455
+1.073061	2.910000	3.416735
+1.813571	4.912755	3.426429
+1.823795	2.155281	3.438020
+1.859094	2.857774	3.435736
+2.041282	3.794359	3.438872
+2.290507	3.970254	3.442535
+2.536849	3.005000	3.428767
+2.926563	4.204063	3.418438
+2.925222	6.295611	3.433278
+2.976618	2.966029	3.431127
+3.447737	6.007956	3.425912
+3.933119	3.505505	3.433211
+4.023758	4.934395	3.440637
+4.048842	1.605946	3.433822
+0.762436	0.133846	3.436282
+0.995049	3.809126	3.434175
+1.016585	0.129538	3.452985
+1.197365	5.219606	3.450197
+1.284557	4.532966	3.452446
+1.602663	4.767389	3.452611
+1.832177	0.576122	3.438299
+1.849655	4.665747	3.432069
+1.887389	1.894522	3.445987
+2.167692	2.545846	3.430000
+2.219464	1.031250	3.436429
+2.276897	2.772155	3.434914
+2.726145	1.156867	3.439759
+2.767590	3.118313	3.438494
+2.809948	3.967098	3.438290
+2.831514	1.673267	3.442510
+3.067233	0.752327	3.441384
+3.604090	5.250396	3.453087
+4.152908	3.634610	3.442979
+4.173825	0.698470	3.448415
+4.213556	3.870667	3.423556
+4.238462	4.323718	3.444872
+1.176264	3.641319	3.446044
+1.876234	5.171778	3.462594
+2.200676	3.028514	3.446351
+2.371243	4.744320	3.451243
+2.389252	1.680204	3.453333
+2.564915	6.074542	3.463559
+2.723043	2.846957	3.442899
+2.731190	0.687738	3.447738
+2.897033	5.363445	3.455502
+2.954559	4.453088	3.448603
+3.081200	1.072350	3.453950
+3.542308	2.941209	3.443077
+3.615494	6.208670	3.450043
+3.696286	4.142286	3.440714
+3.983646	4.286133	3.452155
+4.151250	3.120417	3.440417
+1.009744	4.589829	3.468889
+1.021572	1.942704	3.463019
+1.188974	4.773846	3.447179
+1.265739	0.161565	3.453565
+1.273765	2.228704	3.461049
+1.388697	4.959910	3.476472
+1.914797	6.382276	3.454146
+2.307419	1.433065	3.451613
+2.400120	3.700876	3.468167
+2.400805	5.003678	3.455862
+2.612584	3.546292	3.449551
+2.923717	0.027368	3.476776
+3.241155	2.955988	3.464985
+3.257635	1.801554	3.463784
+3.700615	1.251385	3.460103
+4.165758	0.957374	3.455960
+4.409133	3.432954	3.472222
+4.417432	4.568716	3.463268
+0.773524	1.888667	3.474286
+0.804188	2.875550	3.478429
+1.007265	2.232059	3.482941
+1.014430	0.916709	3.458987
+1.007377	1.690328	3.467213
+1.278167	2.481833	3.467833
+1.300968	3.004409	3.476505
+1.641486	1.981622	3.462703
+1.893117	0.816104	3.460000
+1.911757	2.408745	3.471757
+1.971908	1.066151	3.474375
+2.460598	0.862735	3.467009
+2.613200	1.789000	3.464200
+2.871736	6.050826	3.469256
+2.941061	5.792122	3.477510
+3.195745	5.928404	3.473245
+3.874434	3.254660	3.479968
+3.920682	5.926515	3.461364
+4.025422	0.029333	3.475156
+4.411440	1.851206	3.483502
+0.770526	0.788246	3.467719
+1.244783	1.717681	3.477681
+1.497561	0.907195	3.469146
+1.584133	5.819867	3.473333
+1.731273	4.462727	3.478909
+2.391034	3.437586	3.467586
+2.407568	0.393063	3.474414
+2.493813	4.397813	3.475000
+2.664854	0.016505	3.483398
+2.685325	6.297597	3.476883
+2.879163	0.495665	3.483498
+2.888760	3.621405	3.484339
+3.128704	5.038765	3.482654
+3.195870	4.717640	3.487994
+3.278938	0.357611	3.485310
+3.365754	6.242291	3.475251
+3.437944	3.513084	3.474673
+3.647738	0.095714	3.475714
+3.706200	4.559600	3.467400
+3.769000	3.017250	3.472250
+4.261822	5.051051	3.492079
+4.417360	2.133600	3.481240
+4.423878	0.044354	3.477551
+4.435373	2.987910	3.468060
+0.753902	6.006585	3.476341
+0.797816	2.592031	3.499885
+0.804186	0.377535	3.493023
+1.247821	2.743619	3.501362
+1.381667	4.142308	3.491026
+2.190882	4.385539	3.495343
+2.205542	5.146988	3.484819
+2.489651	2.463953	3.483140
+3.131683	2.492970	3.487822
+3.584681	1.944043	3.480319
+4.145551	3.371066	3.496801
+0.801513	4.187697	3.499342
+1.686505	3.745922	3.497087
+1.725340	3.486456	3.505388
+1.836324	6.135784	3.509608
+1.860210	4.147832	3.495594
+2.073947	4.743158	3.494211
+2.104306	2.030417	3.489583
+2.880749	5.102834	3.507166
+3.054516	3.815726	3.493548
+3.241429	2.249365	3.507937
+3.324112	5.320374	3.492056
+3.403786	3.159500	3.499643
+3.749744	5.516282	3.498910
+3.797517	6.380455	3.516818
+3.872024	0.435893	3.500893
+4.402427	4.130921	3.500209
+1.304086	3.273555	3.516080
+1.360000	5.734000	3.512000
+1.842734	1.419820	3.517014
+2.438542	5.248177	3.514740
+2.629204	5.085664	3.508850
+2.688757	0.316836	3.521808
+2.924505	1.293297	3.504615
+3.094264	5.513876	3.510698
+3.284159	0.931416	3.505310
+3.480577	4.035096	3.511442
+3.638841	3.654493	3.514130
+3.809916	4.813866	3.508151
+4.017895	2.277895	3.503553
+4.398525	0.308579	3.513770
+0.788962	3.441038	3.515472
+0.993971	6.129779	3.511691
+1.041897	4.251897	3.513793
+1.055692	0.446443	3.527826
+1.826870	5.722672	3.520687
+1.973503	5.943450	3.603259
+2.250000	5.486522	3.517043
+2.261957	5.989946	3.520924
+2.708000	4.211333	3.523111
+2.743023	4.716434	3.522093
+2.788528	3.369722	3.532472
+2.885842	0.930891	3.518812
+3.201917	3.604889	3.534417
+3.242938	1.551688	3.523000
+3.412978	3.784831	3.521236
+3.493961	1.093052	3.532792
+3.529607	0.312295	3.532000
+3.688077	3.900769	3.507500
+3.809408	5.074737	3.513750
+0.786604	4.450000	3.520755
+1.077148	3.132096	3.540687
+1.519091	6.386883	3.521818
+1.513103	3.132759	3.518276
+2.037143	4.983571	3.526143
+2.063333	5.643141	3.535449
+2.169247	1.246986	3.530959
+2.384167	1.927222	3.517639
+2.502780	0.618976	3.534537
+2.511014	2.206329	3.538841
+2.517432	2.730137	3.539016
+2.707544	2.361930	3.518070
+3.157757	4.240514	3.531028
+3.306923	1.261346	3.522500
+3.402194	0.066367	3.532266
+3.515069	4.297743	3.534688
+3.701127	1.593333	3.528333
+3.881118	1.778882	3.529627
+4.108615	1.187385	3.518462
+4.386084	5.288112	3.527692
+0.783415	6.242683	3.527805
+1.069558	3.402210	3.546022
+1.171906	5.950809	3.552689
+1.433935	3.769379	3.544379
+1.601975	1.550191	3.540000
+1.670513	2.403077	3.533333
+1.723911	2.659815	3.545978
+2.111745	0.030468	3.550170
+2.168486	1.790784	3.554541
+3.149109	0.144368	3.552759
+3.216360	3.326207	3.545900
+3.370914	2.735635	3.542995
+3.519486	0.579673	3.543224
+3.555029	4.746192	3.549477
+3.934834	4.525762	3.542384
+4.114264	6.073953	3.537907
+4.382345	0.568207	3.541379
+0.798571	3.928571	3.545000
+0.795075	4.711940	3.542537
+0.825455	1.038485	3.548182
+0.824388	3.187908	3.555306
+0.835980	1.523660	3.556438
+1.096763	4.988426	3.567339
+1.347276	6.203621	3.555483
+1.406832	0.700495	3.551188
+1.417287	2.041117	3.549043
+1.930345	1.666069	3.551379
+1.978804	3.059185	3.553804
+1.980733	2.659400	3.549933
+2.222301	0.805739	3.558011
+2.225758	0.541273	3.554545
+3.521333	6.396889	3.540667
+3.735049	0.931845	3.545728
+3.796731	2.356731	3.535000
+4.047059	0.272745	3.538039
+4.118435	4.712652	3.552087
+0.826979	5.429532	3.572255
+1.592180	6.166992	3.559549
+2.026656	5.372125	3.575750
+2.419442	3.191076	3.568606
+2.454767	1.098895	3.560756
+2.459337	4.143976	3.567349
+2.517759	1.496207	3.550000
+2.606235	5.709471	3.564000
+2.987215	3.192877	3.566712
+3.121023	0.536093	3.568791
+3.155263	2.006974	3.553947
+3.497115	2.170224	3.567821
+3.480618	1.442542	3.577482
+3.655549	5.980445	3.574036
+3.860755	6.141415	3.561698
+4.139005	4.079147	3.565261
+4.146094	5.335938	3.551250
+4.377450	3.689060	3.554966
+1.000896	2.736418	3.560746
+1.089823	5.689381	3.586047
+1.467798	2.616607	3.569583
+1.520377	4.539811	3.567484
+1.527162	1.311892	3.565541
+1.617700	5.587100	3.571550
+1.742822	1.181245	3.574689
+2.080283	6.242085	3.586862
+2.100789	1.490132	3.561711
+2.668729	5.349171	3.568674
+2.689067	3.752000	3.571067
+3.504744	0.828205	3.563846
+3.638485	2.530758	3.563485
+3.776165	0.665090	3.578746
+4.357639	0.836898	3.579769
+4.364430	4.805436	3.572416
+4.361447	5.825921	3.561711
+4.370833	5.582083	3.559583
+1.032941	4.006176	3.583015
+1.092876	0.714335	3.583219
+1.343956	3.522637	3.578242
+1.585598	4.011624	3.586068
+1.712356	0.289540	3.582069
+1.936200	0.197600	3.571200
+1.994712	4.529640	3.594317
+2.019883	3.432953	3.589357
+2.356000	5.697778	3.569778
+2.885849	2.519245	3.575597
+3.098333	5.269643	3.575714
+3.143341	6.160935	3.591449
+3.242362	3.973568	3.582563
+3.336667	4.914394	3.567576
+3.330278	5.568167	3.580944
+3.814118	2.103529	3.589538
+3.895985	4.012117	3.580730
+4.060552	6.342566	3.588585
+4.077802	5.770055	3.582253
+4.358352	6.075824	3.571978
+4.351011	6.341011	3.581180
+1.239780	1.301282	3.597179
+1.373055	5.489539	3.606455
+1.403016	1.105794	3.584206
+1.573488	0.520640	3.590116
+1.607930	4.280881	3.598943
+1.715376	0.922688	3.587634
+1.812428	3.254529	3.601377
+2.300053	6.379158	3.590526
+2.551389	4.862361	3.588750
+3.038653	1.751036	3.594870
+3.418352	2.426758	3.593077
+3.432773	5.820504	3.585714
+3.638235	3.209804	3.587598
+3.675680	2.792426	3.593550
+3.880611	5.307889	3.590000
+4.120774	1.815806	3.592903
+4.228667	2.943939	3.591879
+4.351444	1.106203	3.593209
+4.368831	2.735455	3.583636
+0.831892	5.699527	3.596216
+0.860798	0.604172	3.598221
+0.953507	5.209478	3.603284
+1.078051	5.422542	3.600169
+1.097869	1.509016	3.595410
+1.353439	1.536688	3.605605
+1.594301	5.327306	3.608342
+1.710547	1.785323	3.605970
+1.711310	2.998363	3.615239
+2.079528	4.009571	3.599442
+2.258778	2.270833	3.609222
+2.293003	0.217157	3.612875
+2.368526	2.934211	3.601158
+2.686800	2.004571	3.601314
+3.000103	4.038144	3.594948
+3.011321	1.499245	3.589057
+3.420137	4.533288	3.591096
+3.771192	4.306995	3.606736
+3.964481	1.008506	3.602597
+0.858421	3.698684	3.618202
+1.118328	6.332958	3.610836
+1.365673	4.730481	3.608462
+1.444706	2.361373	3.608725
+1.609464	2.187321	3.599643
+1.894737	3.653053	3.606947
+2.007513	0.657919	3.615685
+2.127989	2.857759	3.615287
+2.475612	5.491122	3.615306
+2.734535	4.459942	3.609070
+2.926564	0.258650	3.613190
+3.760132	3.454305	3.608874
+3.805699	5.763656	3.620573
+4.095254	2.521949	3.605424
+4.109853	1.424265	3.597794
+4.324235	3.195882	3.617529
+4.353294	1.405059	3.602588
+4.340872	2.481544	3.615235
+1.656794	4.976327	3.627983
+1.832141	3.908049	3.635095
+2.004595	2.219459	3.614189
+2.517605	4.609191	3.631327
+2.900786	0.705286	3.625571
+3.135421	4.493645	3.611776
+3.472200	5.102000	3.616400
+3.833333	0.010000	3.607778
+3.859952	1.409614	3.621981
+3.995315	3.060961	3.633123
+4.036269	5.120896	3.611194
+4.072019	3.826442	3.625577
+4.229516	2.245484	3.609516
+0.842791	4.961744	3.619767
+0.875985	1.274672	3.631606
+1.173196	3.812165	3.627423
+1.288864	0.481761	3.631250
+1.361410	4.357436	3.630641
+1.442927	2.865000	3.625122
+1.461458	5.966667	3.633802
+2.212659	3.615635	3.638690
+2.258171	4.896286	3.629314
+2.621233	1.277808	3.634795
+2.682417	1.008083	3.631917
+2.752484	1.506369	3.641783
+2.743786	5.918786	3.631786
+3.070000	2.739500	3.617000
+3.138867	5.735123	3.629901
+3.296475	0.713852	3.629098
+4.009187	5.524228	3.624309
+4.079085	0.526078	3.637320
+4.238174	0.145434	3.634658
+0.873237	2.058417	3.635252
+1.230324	0.930356	3.647152
+1.416786	1.790982	3.637143
+1.460544	0.299456	3.638095
+1.534621	3.349798	3.650303
+1.734420	5.927800	3.655780
+2.236679	4.626900	3.648524
+2.291632	2.618289	3.647816
+2.901389	5.601389	3.630972
+3.010299	3.456866	3.634478
+3.020556	6.398889	3.624444
+3.389636	1.926727	3.629273
+3.765329	0.243699	3.645517
+3.866575	2.626740	3.639337
+4.319156	1.663556	3.645600
+4.326316	3.926491	3.631404
+1.063832	1.124673	3.648318
+1.129432	4.434545	3.640682
+2.408044	6.151240	3.660744
+2.463636	5.896883	3.641429
+2.540143	0.139810	3.652190
+2.558349	3.405000	3.653761
+2.830933	2.205333	3.641067
+2.850198	2.998218	3.647426
+2.927826	4.289437	3.663299
+2.952154	4.647846	3.646308
+4.058421	2.083289	3.643026
+1.114412	1.811471	3.646471
+1.126947	2.076632	3.652105
+1.128448	2.914138	3.655517
+1.155578	0.248741	3.666871
+1.381409	0.052610	3.675935
+1.427500	5.147440	3.660595
+1.781304	2.026739	3.657174
+1.823369	4.750494	3.678820
+2.090000	2.455522	3.647910
+2.375476	1.312143	3.647857
+2.410528	3.891901	3.674261
+2.649032	3.997097	3.650000
+2.825607	2.746262	3.660748
+2.854724	4.900394	3.656929
+3.423136	2.964746	3.654068
+3.497750	5.390875	3.652250
+0.879020	1.769020	3.653922
+0.900541	5.944472	3.678575
+0.902661	0.228548	3.668226
+1.137848	4.695949	3.672405
+1.174272	2.382722	3.682880
+1.813803	0.019108	3.682629
+2.232843	4.198235	3.662745
+2.256964	3.359107	3.656964
+2.313989	1.565319	3.667979
+2.646986	2.549658	3.671575
+2.663993	3.161282	3.677839
+2.714146	0.519024	3.657805
+2.774667	1.775500	3.661500
+2.937754	1.978941	3.676102
+2.955349	1.105659	3.672713
+2.995269	5.951935	3.681774
+3.048717	2.338586	3.683272
+3.096353	0.852941	3.667412
+3.440046	3.356250	3.675463
+3.450560	6.110960	3.663920
+3.837167	3.723348	3.670129
+4.033214	3.535268	3.665893
+4.046842	0.775000	3.661711
+1.808913	0.505261	3.682609
+1.838953	5.528014	3.688412
+2.227154	1.049112	3.693029
+2.248829	5.300360	3.679820
+2.517407	1.731414	3.690135
+2.660769	0.758803	3.683675
+2.666480	6.156786	3.684235
+3.116240	4.873872	3.694039
+3.209700	1.078300	3.698200
+3.265307	6.376316	3.686272
+3.438344	1.687748	3.680265
+3.675392	1.810506	3.688101
+3.673581	4.077973	3.683514
+4.294481	2.001749	3.681803
+4.275556	4.545313	3.691146
+0.907067	0.850933	3.681600
+0.905059	2.989882	3.688706
+1.354592	3.972602	3.693469
+1.592407	3.616420	3.687593
+1.991146	0.914167	3.695052
+2.038626	0.389121	3.688132
+2.195904	3.108883	3.698883
+2.365789	4.408421	3.686842
+2.761622	6.394865	3.677838
+3.102171	2.983808	3.697651
+3.579631	5.634538	3.699103
+3.661583	4.949778	3.698861
+3.985089	4.884464	3.699196
+4.259547	4.270121	3.705438
+0.895179	4.320893	3.695536
+1.192140	4.176347	3.711107
+1.824200	5.270600	3.693000
+1.903364	6.389813	3.694766
+1.956197	1.864648	3.694225
+1.979416	1.191948	3.709286
+2.188473	5.816158	3.706355
+2.462765	5.069625	3.703481
+2.508131	0.401495	3.697009
+3.235451	2.573819	3.705625
+3.243717	5.109867	3.703982
+3.338710	0.475968	3.691290
+3.643618	4.511709	3.698141
+3.988761	1.620000	3.707212
+4.056410	2.788051	3.703897
+1.149167	3.577667	3.707500
+1.192019	5.234327	3.714904
+1.855158	2.504421	3.702211
+1.898356	5.041507	3.708219
+2.622368	2.898053	3.715632
+2.785364	3.565099	3.715695
+2.903910	5.359799	3.724211
+2.914907	6.217920	3.717547
+3.034556	3.691000	3.710222
+3.189835	1.363992	3.715679
+3.269425	5.950402	3.713966
+3.317425	4.345389	3.714731
+3.591875	0.032500	3.706063
+3.651161	1.283125	3.705804
+3.672727	5.215455	3.705354
+3.958605	5.963688	3.723121
+4.002914	4.344686	3.712686
+4.279778	3.445778	3.704667
+0.919053	4.574852	3.715325
+0.939395	2.542326	3.718419
+1.774891	4.470876	3.719124
+1.892888	2.830036	3.725740
+2.131833	5.089167	3.711167
+2.196483	2.017585	3.737987
+2.444197	0.899343	3.724854
+2.440845	2.417042	3.714789
+2.461032	3.634603	3.716825
+2.788235	0.010000	3.707647
+2.859148	3.873409	3.724432
+3.373578	0.237890	3.721193
+3.576405	3.841373	3.719477
+3.748596	3.016082	3.719766
+3.988727	0.123000	3.724909
+4.249200	5.188100	3.726700
+0.923194	6.218168	3.728586
+0.917119	3.476949	3.722881
+0.933932	2.284274	3.724615
+1.181592	2.648726	3.733503
+1.517328	0.841422	3.738799
+1.789158	4.156842	3.735684
+2.465282	2.023944	3.729085
+2.725344	5.159924	3.739771
+3.140618	0.338146	3.729045
+3.267075	5.371429	3.729728
+3.289306	2.123750	3.721528
+3.666542	0.482712	3.748427
+3.685304	6.185217	3.726522
+3.810000	4.702361	3.723472
+3.930424	3.298545	3.732303
+3.942857	2.360974	3.733636
+4.265306	5.440408	3.725306
+4.283409	0.407045	3.713182
+1.243195	3.140237	3.742071
+1.278407	5.794973	3.751209
+1.462332	6.351989	3.763320
+1.753713	6.207178	3.744455
+1.794405	2.261548	3.736310
+1.937076	5.761345	3.738596
+2.525655	6.372768	3.745238
+2.991322	5.100460	3.739425
+3.276217	4.664957	3.744174
+3.407711	1.238554	3.736627
+3.486901	2.625704	3.741831
+3.567667	3.575400	3.752967
+4.218723	5.932553	3.726809
+1.337426	2.181864	3.762663
+1.545693	5.757154	3.756217
+1.756458	1.574792	3.737500
+1.801667	3.466778	3.752056
+1.948269	1.446346	3.742692
+2.015576	4.283680	3.756320
+2.057742	3.789194	3.748978
+2.363485	0.640644	3.756515
+2.690689	5.537356	3.760467
+2.944967	0.492026	3.752157
+3.281111	3.169630	3.746852
+3.298616	3.739322	3.757627
+3.702703	2.292568	3.741892
+3.794123	5.493070	3.743596
+3.927421	1.895833	3.754206
+3.985020	1.220040	3.756397
+4.196594	0.966006	3.757337
+4.220826	6.191364	3.752645
+4.261449	0.666957	3.741159
+4.259714	5.698857	3.734571
+0.985059	3.232485	3.778491
+1.272739	6.068185	3.769236
+1.285315	0.699505	3.768468
+1.499862	3.074050	3.771433
+1.565455	4.708446	3.771378
+1.575000	1.148276	3.748621
+1.610522	2.521522	3.770478
+1.637533	2.785267	3.756867
+2.047045	4.858864	3.758636
+2.076195	1.657345	3.758938
+2.085028	5.542486	3.766851
+2.093977	0.157614	3.760795
+2.184409	6.069685	3.748976
+3.193821	1.625472	3.768726
+3.223512	3.474762	3.770000
+3.417595	4.050541	3.770622
+3.438681	0.968462	3.755055
+3.629388	2.054694	3.751633
+3.675122	1.037561	3.749024
+0.947723	5.553762	3.763267
+1.261549	4.993662	3.766901
+1.536697	1.448394	3.774312
+1.546081	2.014542	3.773516
+2.135556	6.396667	3.763333
+2.924900	1.341833	3.779100
+3.017800	0.069546	3.777959
+3.646996	1.536567	3.778712
+3.668889	0.801944	3.756389
+4.031692	4.600154	3.777744
+4.236581	1.251453	3.764615
+4.238854	3.688854	3.762604
+0.982157	3.853922	3.785441
+1.004648	0.449805	3.786563
+1.190667	5.552933	3.775867
+1.287440	3.394480	3.781120
+1.608261	0.135280	3.782919
+2.600072	2.238406	3.776594
+2.716133	4.201067	3.777467
+2.740327	4.656797	3.776013
+2.848103	0.899770	3.781954
+3.194101	1.891573	3.778315
+3.487753	6.338590	3.779339
+3.921791	6.226418	3.783358
+4.215491	4.793757	3.779249
+4.239844	2.647813	3.771406
+0.954167	4.811875	3.778750
+1.255373	1.677015	3.795224
+1.266757	1.927838	3.787297
+1.352030	3.718687	3.803851
+1.536410	4.426325	3.795983
+1.574925	3.853134	3.775224
+1.849075	0.247543	3.805377
+1.943402	3.137191	3.806160
+2.075802	2.661975	3.781481
+2.428472	4.796806	3.780278
+2.541972	5.327606	3.777324
+2.762424	0.326212	3.778788
+3.172292	4.153125	3.782917
+3.558060	4.278881	3.800709
+3.951446	0.360602	3.785542
+0.964462	4.112615	3.794000
+0.980444	1.426000	3.789556
+0.979500	2.779300	3.793900
+0.979587	5.060000	3.803140
+1.788588	1.032316	3.809040
+2.287656	1.774531	3.796406
+2.583407	4.404505	3.791209
+2.795714	2.392101	3.799916
+2.943462	1.608590	3.793205
+2.984982	2.597365	3.808845
+3.065603	3.278621	3.799397
+3.108304	3.914620	3.805322
+3.352420	5.722038	3.799936
+3.471351	0.662819	3.807876
+3.543376	5.903939	3.808824
+3.877725	5.102036	3.797305
+3.902031	0.615430	3.810039
+4.029571	5.325643	3.810643
+4.189388	2.389429	3.814327
+1.123409	0.026688	3.818669
+1.575769	1.709231	3.796731
+1.586066	5.495972	3.810664
+1.626818	0.375682	3.797045
+2.287799	0.374654	3.815409
+2.411731	5.713269	3.800769
+2.655126	4.907787	3.823165
+2.852521	5.754062	3.821541
+3.417876	4.945693	3.821298
+3.538654	3.122404	3.805577
+3.560331	4.727769	3.808926
+3.666056	3.334648	3.809437
+4.029684	4.106013	3.808101
+4.197668	1.507720	3.812850
+0.996267	1.932800	3.810800
+1.219149	1.431277	3.809574
+1.293288	4.509452	3.814795
+1.340098	1.202580	3.833317
+1.416392	2.685979	3.809485
+1.554643	4.161964	3.817321
+1.758516	1.305875	3.830326
+1.863944	0.727702	3.828292
+1.960325	2.102927	3.816423
+2.038682	5.289591	3.828773
+2.191282	0.823718	3.817051
+2.621394	3.811010	3.819615
+2.813229	3.329561	3.832853
+3.576476	2.853429	3.828143
+3.714331	2.533622	3.814173
+3.840172	3.935776	3.810690
+3.891606	0.894234	3.821168
+0.989180	5.313115	3.823279
+1.013289	1.667105	3.828026
+1.037898	0.702102	3.836433
+1.305089	2.907054	3.825536
+1.483580	4.952716	3.821111
+1.568846	2.273077	3.813462
+1.600612	5.199592	3.819388
+1.808010	3.725000	3.841505
+2.001864	4.626780	3.826610
+2.226575	4.003119	3.833211
+2.265714	2.813354	3.827391
+2.414140	3.285478	3.830701
+2.484146	4.101341	3.835823
+2.480196	2.657647	3.842745
+2.612025	5.851139	3.826076
+2.653333	1.897895	3.824912
+3.102788	4.388077	3.829135
+3.143949	5.568587	3.835072
+3.451230	5.218095	3.835357
+3.479667	2.236167	3.816500
+1.206214	6.306214	3.841714
+1.355476	5.377143	3.840873
+1.694931	3.245590	3.844271
+1.710000	6.400000	3.820000
+1.969778	4.014222	3.833333
+2.120260	0.577857	3.848409
+2.115833	2.307222	3.847222
+2.321618	5.472228	3.854271
+2.332692	0.100994	3.850577
+2.424881	3.017698	3.843333
+3.190769	2.790385	3.834103
+3.589134	0.245118	3.842362
+3.834236	2.787896	3.853084
+3.847627	3.524350	3.840000
+4.157373	2.994235	3.842196
+4.163709	3.256490	3.841656
+4.177059	0.010000	3.836176
+4.169239	1.831576	3.842989
+4.196250	3.926528	3.826944
+1.024028	5.777109	3.847630
+1.066828	0.964793	3.858069
+1.317531	4.765188	3.860837
+1.410784	0.490833	3.857598
+2.036099	3.546233	3.854798
+2.173925	1.444393	3.843084
+2.185427	4.457607	3.861068
+2.608333	1.107886	3.859756
+2.930259	4.090570	3.849378
+3.003571	0.715238	3.845357
+3.075562	2.114894	3.862766
+3.094457	6.354286	3.849314
+3.303696	6.163519	3.862557
+3.872283	2.141096	3.851370
+3.902742	5.688871	3.837903
+4.017373	2.579407	3.841949
+0.996667	6.400000	3.833333
+1.377303	2.433717	3.867500
+1.607308	6.038615	3.858308
+1.748700	1.876100	3.849500
+2.286061	3.748485	3.846364
+2.297710	3.503588	3.860916
+2.362897	2.215888	3.866308
+2.566667	0.010370	3.850000
+2.659042	1.372682	3.876054
+2.703492	1.647354	3.867725
+2.800518	6.021224	3.870918
+2.799713	2.099936	3.874236
+3.266733	0.804158	3.853564
+3.444808	4.509808	3.856154
+4.011448	3.751136	3.877706
+4.159160	0.245378	3.858824
+1.392857	0.235714	3.866633
+1.630379	0.620530	3.863939
+2.137879	3.307652	3.865833
+2.277927	4.967683	3.862805
+2.767586	0.630251	3.886708
+2.916837	3.086122	3.865000
+3.121379	5.822069	3.860517
+3.238194	2.315139	3.858333
+1.041948	6.053831	3.877857
+1.072161	3.000879	3.886667
+1.071473	4.387649	3.889467
+1.089537	2.161907	3.891526
+1.725268	4.902282	3.888254
+1.741048	2.981210	3.882097
+2.041583	6.221636	3.893298
+2.311548	6.239409	3.899572
+2.343905	5.936381	3.876476
+2.356045	5.205522	3.885149
+2.416818	4.559318	3.871364
+2.457843	1.560667	3.887294
+2.880462	1.830923	3.868308
+3.182508	0.538482	3.889571
+3.414054	0.011351	3.875135
+3.442055	1.854466	3.882648
+3.870278	1.447500	3.865278
+4.133096	2.104184	3.880544
+4.126016	5.020398	3.884382
+1.062308	1.223590	3.880256
+1.332128	0.940426	3.885957
+1.354314	4.280131	3.890588
+1.484259	3.502889	3.902519
+2.215044	4.725575	3.887699
+2.410140	1.281121	3.897383
+2.554127	0.247922	3.900000
+2.539763	6.096746	3.905030
+2.728371	6.302664	3.905145
+2.742199	2.634894	3.886738
+2.950735	4.568382	3.878088
+2.982245	3.511633	3.875918
+3.413097	1.542258	3.890194
+3.821959	1.691031	3.884021
+3.916574	3.094815	3.885463
+4.118641	5.570924	3.889511
+4.135045	0.496396	3.887838
+1.074895	3.447622	3.902238
+1.207647	3.928941	3.897529
+1.760492	5.662077	3.900492
+1.817834	5.914331	3.899299
+2.164541	1.194031	3.909439
+2.281833	2.496000	3.899750
+2.872903	2.840968	3.888226
+2.889346	4.821308	3.899346
+3.058333	6.082613	3.907613
+3.070530	0.945303	3.905530
+3.354669	2.974587	3.899504
+3.417505	5.487027	3.916881
+3.767880	6.019954	3.902028
+3.801765	4.163137	3.887451
+3.819785	4.872366	3.894194
+4.128087	3.507652	3.897913
+1.724321	4.325309	3.907037
+1.803188	5.389710	3.906449
+2.073256	1.860930	3.912558
+2.592700	3.440900	3.906500
+2.782827	0.120169	3.913924
+2.861646	1.128608	3.902785
+2.970928	0.299283	3.917342
+3.104324	1.198649	3.904324
+3.231019	0.160370	3.909861
+3.723417	3.733583	3.905250
+3.757400	4.412700	3.902200
+3.778661	1.199643	3.905625
+4.102824	0.762137	3.912519
+4.092645	5.827025	3.908512
+1.085419	4.653935	3.917097
+1.112279	2.483628	3.927349
+1.140637	0.264111	3.929151
+1.384311	5.622800	3.918356
+1.381343	5.144179	3.916716
+1.735655	3.981138	3.922448
+1.774819	4.632691	3.927108
+1.808542	5.141042	3.908333
+1.885698	1.671396	3.933077
+2.355000	1.030676	3.917297
+3.051471	5.272206	3.913529
+3.431364	2.451061	3.910152
+3.826696	0.189554	3.912143
+1.120667	3.693167	3.917500
+1.410000	0.013659	3.930000
+1.447867	3.982000	3.927200
+1.718065	2.136129	3.920000
+1.875156	0.482595	3.941661
+1.879059	2.657412	3.920941
+2.030288	5.040385	3.924423
+2.393962	4.324528	3.919623
+2.520315	0.521374	3.942027
+2.634545	0.853831	3.927338
+2.745048	5.330571	3.924571
+2.862208	4.337083	3.932917
+3.394216	0.385226	3.938711
+3.462143	3.337619	3.924762
+3.793968	5.326825	3.928175
+1.861351	2.411892	3.927297
+1.970320	0.041715	3.952384
+2.073031	5.947478	3.952876
+2.192685	5.701644	3.947616
+2.620537	3.176157	3.946777
+2.906632	5.521969	3.941451
+2.963333	3.757634	3.933441
+3.534716	1.176023	3.938295
+3.548932	6.144369	3.944612
+3.664707	5.098000	3.951488
+3.702292	1.907000	3.944375
+4.066696	6.085507	3.940088
+1.121394	4.909212	3.953333
+1.417277	3.245982	3.959063
+1.445176	1.852196	3.956549
+1.969375	0.924375	3.943958
+2.076455	0.308973	3.971149
+2.418036	1.910357	3.941250
+2.705797	4.015217	3.939420
+3.003043	2.366242	3.956025
+3.108365	1.459519	3.943942
+3.131439	4.819928	3.951799
+3.307322	1.047541	3.953224
+3.313723	6.391702	3.952128
+3.389401	3.580539	3.947784
+3.433043	3.861159	3.943333
+3.741584	6.339306	3.956377
+1.431587	1.586508	3.950317
+1.421378	6.167774	3.968127
+1.508778	2.872333	3.961556
+1.682638	0.857242	3.978633
+1.946168	4.425911	3.977430
+2.519096	2.406497	3.955593
+2.591886	5.132982	3.959868
+2.752143	3.641224	3.951735
+2.857952	5.097128	3.966862
+3.142857	3.101048	3.961905
+3.325130	1.312597	3.961104
+3.327596	5.915385	3.957596
+3.336505	2.087849	3.962527
+3.401478	2.722435	3.962174
+3.713889	5.775926	3.957222
+3.859000	4.633364	3.959364
+4.059259	4.415231	3.960509
+4.061579	6.356118	3.955526
+1.138643	5.172362	3.970905
+1.146667	1.819677	3.970645
+1.168052	2.745233	3.976919
+1.179963	0.531355	3.974139
+1.438571	0.742294	3.976494
+1.897360	3.363360	3.974960
+1.918000	6.400000	3.944000
+1.969126	2.896764	3.974595
+2.166406	4.217266	3.971875
+2.394024	0.788293	3.963537
+2.478011	3.655580	3.970994
+2.580781	5.653906	3.963906
+2.612491	2.854684	3.972379
+3.203557	2.552420	3.975656
+3.370667	4.737333	3.975778
+4.075000	1.328276	3.963621
+1.229889	5.923667	3.993111
+1.460955	4.584777	3.986115
+1.531410	1.080865	3.989647
+1.679803	1.496908	3.984211
+1.815604	6.149780	3.975824
+2.690690	4.517816	3.977816
+3.072870	1.708148	3.978426
+3.177869	4.567951	3.982787
+3.320537	4.320289	3.976818
+3.480478	0.853072	3.993242
+3.654141	2.157071	3.976667
+3.668633	5.533381	3.978273
+3.708828	0.969609	3.982422
+3.795844	0.445325	3.971169
+4.034076	1.596902	3.988696
+4.060000	1.015278	3.973148
+4.050396	4.790990	3.975941
+1.149490	4.159796	3.985510
+1.163176	3.225203	3.989932
+1.158266	5.433988	3.992775
+1.522937	5.847619	3.991825
+1.923130	1.163652	3.984000
+1.936447	1.413553	3.983684
+1.953333	4.815167	3.983750
+2.555789	4.727594	3.984135
+2.863881	1.485224	3.993582
+3.226452	3.338548	3.975968
+3.272617	4.058505	3.990000
+3.662043	3.972787	4.005809
+3.737778	0.721667	3.971944
+1.480651	2.152055	4.008664
+1.493559	1.335254	3.994576
+1.528309	3.751654	4.008640
+2.003121	3.830709	3.998936
+2.171720	2.095161	3.994839
+2.618046	4.255977	3.996437
+3.209722	3.787639	3.997639
+3.642574	3.508713	3.993366
+3.668765	1.392469	3.997284
+4.014143	2.302929	3.996929
+1.174043	1.569787	4.000851
+1.195385	0.798077	4.011058
+1.552593	2.613992	4.016626
+1.889204	4.162301	4.014248
+2.025264	5.489421	4.020378
+2.149137	1.635268	4.020655
+2.225543	2.970870	4.016957
+2.519130	5.395489	4.016033
+2.749442	0.396000	4.017907
+3.272000	5.287905	4.009048
+3.656526	2.677371	4.018638
+3.971456	1.844175	4.006796
+1.562379	5.342103	4.022172
+2.137395	2.701261	4.015462
+2.422847	3.910569	4.025907
+3.077714	4.229486	4.025600
+3.133553	5.067237	4.014079
+3.624582	0.064558	4.035895
+3.644667	2.401778	4.018556
+3.973489	3.308006	4.026822
+4.021324	0.068971	4.008676
+1.172708	5.679583	4.024583
+1.232868	1.332574	4.037721
+1.635098	6.322451	4.046803
+1.883923	1.985414	4.030608
+3.054423	2.749038	4.020192
+3.261343	5.689627	4.034925
+3.596150	4.847914	4.033155
+3.607051	1.640000	4.034423
+3.620196	4.580833	4.030931
+3.972107	5.170868	4.033802
+3.998970	2.903273	4.028364
+1.211837	1.084490	4.030408
+1.485652	4.833370	4.034130
+1.578532	5.071147	4.051009
+1.629899	0.437475	4.044007
+1.961341	2.226951	4.035366
+2.115556	0.755556	4.032593
+2.622308	1.999038	4.033654
+3.547455	0.576818	4.051273
+3.631944	2.985000	4.044583
+3.663305	3.251674	4.052833
+4.003902	0.329512	4.028537
+1.184935	6.166623	4.036364
+1.258153	2.286908	4.058835
+1.557931	0.159770	4.038046
+1.956522	5.741739	4.044348
+2.046183	3.149167	4.060161
+2.071088	2.455026	4.058549
+2.179605	3.656974	4.046645
+2.284118	0.571000	4.056059
+2.301500	3.211583	4.045667
+2.519739	5.884870	4.047130
+2.977036	0.528458	4.058696
+2.998252	3.286699	4.042233
+3.008382	1.941156	4.055723
+3.042654	3.964691	4.048395
+3.151750	3.553000	4.043250
+3.241519	1.869494	4.046203
+3.424214	5.075000	4.052643
+3.983438	4.137500	4.047031
+3.983469	5.426735	4.044286
+1.235093	4.492500	4.061944
+1.251232	2.021667	4.059420
+1.268105	2.985333	4.072070
+1.540000	4.272745	4.045882
+1.596813	3.092637	4.050659
+1.639075	3.367746	4.068208
+1.669583	1.740556	4.048889
+2.351440	0.314647	4.068152
+2.375349	2.776395	4.059651
+2.573182	1.760455	4.048864
+2.895506	0.788892	4.071139
+3.012622	5.724085	4.059085
+3.150498	0.733817	4.070498
+3.581289	4.230028	4.064818
+3.924339	2.647845	4.075776
+3.974464	0.582679	4.055357
+1.274863	3.451096	4.075479
+1.671325	2.328400	4.080675
+1.736788	2.805907	4.064767
+1.755170	3.593333	4.065850
+1.800112	0.240615	4.068492
+1.968904	5.233151	4.066849
+2.174454	4.886639	4.075042
+2.199159	0.096726	4.077345
+2.199727	5.146909	4.069727
+2.426809	4.941712	4.070934
+2.772703	2.444919	4.077676
+3.155814	6.257519	4.067442
+3.175948	0.351046	4.081307
+3.954922	3.573047	4.065781
+1.293926	6.381846	4.088926
+2.088242	4.624424	4.079697
+2.116387	6.381849	4.077227
+2.166684	1.003211	4.079895
+2.457485	0.062695	4.086437
+2.758406	5.787943	4.094524
+2.820913	1.721142	4.086393
+2.922311	6.366642	4.086764
+2.990517	0.106034	4.072586
+3.123953	5.477945	4.086996
+3.546950	5.312293	4.088392
+3.546667	5.908404	4.080939
+3.612683	0.324146	4.066829
+3.915388	3.894828	4.085862
+3.912196	5.686627	4.087843
+1.306749	2.550000	4.098848
+2.157586	1.378793	4.081034
+2.576116	2.620083	4.086281
+2.694523	4.920492	4.096769
+2.748185	1.009963	4.101593
+2.957197	2.980071	4.099834
+3.270641	1.605385	4.088077
+3.371342	3.154204	4.127942
+3.938875	2.080375	4.086625
+1.283467	3.723467	4.095467
+1.605691	6.049675	4.101301
+1.664854	4.475437	4.093495
+1.698364	1.275636	4.093273
+2.172872	6.140745	4.094362
+2.191875	4.000313	4.093281
+2.269903	5.390388	4.103350
+2.326667	2.314063	4.094271
+2.358774	3.461806	4.101548
+2.376119	4.158209	4.086866
+2.408837	2.085116	4.100349
+2.456364	3.016606	4.103394
+2.781635	1.267788	4.095000
+3.157874	2.207874	4.097087
+3.564692	3.725000	4.103231
+3.870444	6.145444	4.114290
+3.926517	0.824494	4.094157
+1.311690	5.000352	4.114542
+1.344164	0.284947	4.115089
+1.553516	5.631641	4.111563
+1.650806	1.989032	4.095323
+1.828526	5.008237	4.119359
+2.109486	3.411200	4.112400
+2.281979	5.884599	4.111283
+2.342673	4.662508	4.116898
+2.417857	1.427857	4.112083
+2.489187	0.963902	4.112033
+2.623611	2.236389	4.100278
+2.652621	3.795931	4.106000
+2.697075	6.055975	4.120849
+2.813571	2.738661	4.119286
+2.820292	4.686642	4.106058
+2.853112	4.129751	4.111411
+2.906494	2.174113	4.113247
+2.925789	3.559211	4.100263
+2.949097	5.969375	4.103611
+2.995736	1.086822	4.104341
+3.213063	2.912523	4.112252
+3.386466	0.165414	4.109323
+3.519681	1.995745	4.108617
+3.894000	1.411590	4.112615
+3.918298	1.160426	4.103830
+1.280877	4.728596	4.108772
+1.299744	3.987179	4.116538
+1.325789	5.282782	4.130902
+1.732331	5.810339	4.129280
+1.773263	0.648178	4.122246
+1.780719	5.527964	4.118263
+2.229483	4.409138	4.111034
+2.310274	1.201918	4.117397
+2.387547	5.631863	4.129741
+2.411894	6.112727	4.121288
+2.492475	4.436568	4.128515
+2.645389	0.685171	4.128131
+2.653636	1.526783	4.126364
+2.720359	5.517545	4.122395
+2.769535	3.303372	4.116860
+2.928490	5.306615	4.119740
+2.979943	4.489716	4.120398
+3.363703	6.110167	4.131109
+1.586429	4.037857	4.126071
+1.704898	4.776871	4.132313
+2.252638	1.891656	4.125767
+2.357013	6.369497	4.132013
+2.960627	4.914269	4.138478
+3.461948	1.449351	4.137143
+3.486912	5.626324	4.133088
+3.510476	6.327429	4.120095
+3.855654	3.093145	4.137915
+3.873609	4.349112	4.126568
+1.322388	1.714478	4.127164
+1.321087	4.236739	4.136413
+1.365153	0.928282	4.138650
+1.732527	3.841648	4.138242
+1.770343	1.046514	4.147943
+1.804444	3.190667	4.140444
+2.590000	6.288678	4.135289
+2.630282	3.521567	4.153605
+2.681739	0.183370	4.134130
+2.705341	3.027045	4.134318
+3.121439	1.300758	4.140909
+3.422566	2.245044	4.141239
+3.456080	2.552049	4.152606
+3.833010	4.849465	4.149465
+3.839389	1.670229	4.150687
+1.327879	5.537879	4.147273
+1.410866	0.548656	4.161936
+1.765921	2.563026	4.143947
+2.287037	2.557037	4.138889
+2.374528	1.675283	4.138113
+2.434333	5.194833	4.154389
+2.550968	1.215161	4.144194
+2.597183	4.064225	4.142394
+3.472273	3.427348	4.153182
+1.809070	0.018023	4.166628
+1.888000	6.331497	4.180395
+2.685750	5.269250	4.160125
+3.442746	3.962977	4.174827
+3.546120	1.048770	4.167319
+3.786078	5.896667	4.151961
+1.360678	5.784153	4.167712
+1.381646	0.031013	4.161013
+1.418356	1.484612	4.180776
+2.759804	4.372255	4.162647
+2.896541	3.799248	4.169323
+3.003520	2.558715	4.174413
+3.429726	1.767260	4.161370
+3.448776	2.852653	4.164082
+3.835313	0.177604	4.161771
+1.386883	1.198182	4.170779
+1.399200	2.778933	4.176800
+1.905475	1.770380	4.187152
+1.930815	0.849741	4.185630
+2.516944	3.261389	4.187361
+3.037444	1.546457	4.178655
+3.300665	0.925831	4.190818
+3.448285	4.455793	4.185696
+3.832000	2.428909	4.176545
+1.378909	6.042636	4.184636
+1.757206	5.276520	4.190882
+1.863497	4.586993	4.192587
+2.563196	0.421753	4.182990
+3.336488	3.644080	4.195318
+3.760373	5.163593	4.200814
+3.780947	5.434579	4.190421
+3.781049	3.434012	4.195988
+3.796154	2.841692	4.184923
+1.833788	6.043652	4.204573
+1.902731	0.435419	4.201145
+1.913409	1.294091	4.200568
+2.062097	4.175645	4.186774
+2.136757	5.648649	4.193243
+2.364719	3.714607	4.197640
+2.947861	0.314975	4.205323
+3.351898	1.217810	4.195839
+3.397627	0.397966	4.191525
+3.398163	4.867959	4.186327
+3.761321	1.922000	4.205321
+3.778943	0.656179	4.203496
+3.792404	3.701827	4.197692
+3.793765	4.120353	4.197647
+1.442268	4.452862	4.212528
+1.447722	1.905886	4.210506
+1.463909	3.590453	4.220041
+1.564433	0.772296	4.227995
+1.937399	3.959641	4.212960
+1.993729	1.524068	4.198305
+2.002563	0.183266	4.219246
+2.142703	0.384865	4.204324
+2.361239	0.770642	4.212339
+2.799455	1.952228	4.209554
+3.220625	2.420188	4.211250
+3.224818	2.679909	4.206364
+3.265556	4.650427	4.218860
+3.308824	5.862353	4.198627
+3.357396	0.658958	4.206875
+3.370698	4.208372	4.204884
+3.752719	2.192120	4.214424
+1.446917	2.368417	4.215333
+1.456293	3.267854	4.219561
+1.793671	4.280058	4.227312
+1.800128	2.134231	4.229231
+1.878263	2.960297	4.224746
+1.890704	2.371972	4.215775
+1.945145	3.681503	4.212428
+2.050746	5.894030	4.226806
+3.201277	4.390851	4.207872
+3.219358	3.393850	4.229599
+3.304082	2.043469	4.206735
+3.731794	6.356500	4.223941
+3.781351	0.960811	4.213243
+1.746508	1.482937	4.238333
+1.884167	3.422583	4.227333
+1.981121	4.817375	4.244484
+2.039922	2.005273	4.246545
+2.109260	2.827577	4.243903
+2.593720	4.669795	4.235768
+2.600000	2.826092	4.227931
+3.191879	3.855030	4.235697
+3.189310	4.970345	4.225345
+3.341474	5.446421	4.220105
+3.584889	0.795778	4.222667
+3.778846	0.403462	4.214231
+1.457317	3.011463	4.231707
+1.461753	3.854639	4.236701
+3.153958	4.111042	4.240313
+3.302932	5.191152	4.243508
+1.983881	2.596866	4.241194
+2.039935	5.082810	4.252680
+2.124087	2.272198	4.255728
+2.138085	0.630372	4.254787
+2.146279	3.816977	4.246163
+3.092638	3.155337	4.255215
+3.176400	0.153000	4.256500
+3.644798	6.085253	4.259495
+3.705741	5.684136	4.248889
+3.727759	1.208448	4.239310
+1.473950	6.306807	4.252521
+1.523095	4.934000	4.266429
+2.032015	5.383460	4.270228
+2.038216	4.416865	4.266541
+2.220492	3.070758	4.264470
+3.156563	5.672500	4.256172
+3.287015	6.364259	4.268601
+3.688889	1.471242	4.260719
+1.524311	5.436347	4.270539
+1.547198	2.137857	4.270440
+1.549250	0.337500	4.265333
+1.547455	1.041909	4.270000
+1.570251	1.677538	4.273668
+1.595647	0.079483	4.279009
+1.905055	5.683956	4.277418
+2.232347	1.520102	4.276939
+2.486176	5.425588	4.275074
+2.592000	2.445444	4.270500
+2.941571	5.518846	4.278910
+2.951255	3.379176	4.278980
+3.216667	1.756092	4.268621
+3.626197	4.687508	4.284164
+3.683448	3.913966	4.266897
+3.688750	4.433611	4.265417
+3.702593	2.637593	4.265185
+1.508478	5.184348	4.273696
+1.549188	2.591015	4.279239
+3.046726	6.243673	4.288540
+3.055605	0.862803	4.282994
+3.078394	3.624599	4.290255
+1.532941	4.678971	4.281912
+1.548020	4.227228	4.287525
+1.554086	5.898710	4.290645
+1.565714	1.314643	4.287619
+2.265227	3.319773	4.280909
+2.285609	4.986346	4.300128
+2.465328	5.937810	4.282993
+2.937143	5.795866	4.302006
+2.986862	4.295372	4.306676
+3.032062	5.143093	4.282371
+3.582606	0.240394	4.305273
+3.606727	4.963200	4.299345
+3.676000	0.010000	4.280667
+1.978824	1.076824	4.293294
+2.119353	6.258557	4.304677
+2.152924	1.254503	4.302865
+2.246392	6.040619	4.299072
+2.439262	3.935403	4.310940
+2.480400	2.214467	4.301067
+2.779673	5.066667	4.296993
+2.923910	1.298269	4.316597
+2.962195	1.766765	4.316968
+2.997188	0.621875	4.300313
+3.039072	2.827629	4.298557
+3.080297	2.000396	4.294059
+3.128544	5.992492	4.311715
+3.251351	1.465946	4.293694
+3.609955	3.276532	4.304730
+3.667660	3.011702	4.286809
+1.650462	2.837370	4.320636
+2.039000	3.246429	4.305286
+2.140220	1.762802	4.315165
+2.160449	0.895000	4.313596
+2.188302	3.567170	4.318459
+2.180685	4.617808	4.307397
+2.240736	0.192393	4.312577
+2.369253	2.865000	4.314770
+2.479015	4.209562	4.312956
+2.501304	0.212372	4.314032
+2.563879	1.968318	4.315935
+2.686416	1.743410	4.314393
+2.764310	0.509914	4.317586
+2.801656	6.326225	4.312715
+2.928379	0.066421	4.320926
+3.030959	4.724110	4.296986
+3.041673	2.266809	4.319377
+3.147817	1.112792	4.310558
+3.578505	0.533737	4.317153
+3.631702	1.714787	4.301277
+3.624300	2.411200	4.304300
+1.644769	3.426690	4.325587
+2.237667	4.286000	4.310667
+2.249333	5.252417	4.319583
+2.368828	1.049375	4.327930
+2.495314	1.561882	4.329446
+2.562570	4.922793	4.324022
+2.629231	0.010000	4.308462
+2.658502	1.353913	4.319855
+2.741253	2.191798	4.328392
+2.791610	0.785381	4.324831
+2.818996	3.611528	4.323668
+2.840078	3.136039	4.326824
+2.868145	6.060806	4.316290
+3.181016	0.456203	4.322246
+1.658316	3.122105	4.336316
+1.665974	0.552403	4.333442
+1.688981	1.913719	4.340413
+2.303750	2.034259	4.334815
+2.332584	2.411461	4.327753
+2.349630	0.412963	4.314444
+2.702955	3.929167	4.326667
+2.805439	4.805088	4.331930
+2.830843	1.538795	4.324337
+2.855169	4.551356	4.332203
+2.877704	1.035111	4.329037
+2.958047	3.990118	4.332189
+3.137547	5.362642	4.324717
+3.521488	5.847741	4.340854
+3.569650	5.486434	4.331049
+3.604706	3.559412	4.319412
+3.596800	4.215467	4.322933
+1.658459	5.650824	4.343262
+1.638000	6.137226	4.341290
+1.672864	4.486667	4.348967
+2.203143	4.038000	4.327429
+2.253889	5.498889	4.334259
+2.449405	3.471071	4.343571
+2.502727	0.595657	4.361145
+2.535307	5.690000	4.346842
+2.567725	3.052515	4.340299
+2.576524	3.703777	4.347253
+2.697931	5.885172	4.329310
+2.741420	4.193977	4.341761
+2.851932	2.431364	4.335909
+3.537655	5.226966	4.345241
+1.646709	3.728101	4.341392
+2.264980	5.790648	4.358178
+2.377500	0.010000	4.327500
+2.399076	1.312554	4.356304
+2.389434	1.789434	4.345472
+2.606494	6.134945	4.357860
+2.633235	1.086765	4.335000
+2.693206	3.364667	4.363714
+2.726962	2.642405	4.345443
+3.552063	1.941429	4.345397
+1.662475	3.979208	4.352277
+1.695789	2.329035	4.357281
+1.721842	5.092829	4.371382
+2.372953	6.246062	4.360259
+2.382881	4.476017	4.363898
+2.627625	4.442375	4.354625
+2.755682	0.254545	4.353409
+2.803288	2.876301	4.356027
+2.832128	5.303830	4.352979
+3.240448	2.963632	4.358969
+3.490905	3.782387	4.368107
+3.529189	1.289595	4.356486
+3.522604	6.357988	4.357337
+3.542258	2.186452	4.352581
+1.679832	6.383613	4.364454
+1.744808	0.913333	4.367821
+1.762068	1.183346	4.375677
+2.381563	4.749792	4.361875
+2.490851	2.654468	4.362340
+2.545410	0.863934	4.369262
+2.572941	6.385765	4.361059
+2.572308	5.194835	4.373242
+3.506667	2.733548	4.364301
+1.740659	4.811923	4.385714
+2.709459	5.513378	4.369730
+1.766395	0.330349	4.383256
+1.785546	2.573843	4.393100
+1.869191	0.694220	4.391156
+2.250000	2.643855	4.384880
+3.302930	2.251245	4.400330
+3.414346	1.067991	4.399393
+3.413360	6.092400	4.399040
+3.476889	1.529444	4.382333
+1.780150	5.878100	4.403150
+1.839664	0.086765	4.402437
+3.366831	5.626541	4.411715
+3.387686	2.509628	4.411529
+3.418191	0.805106	4.401702
+3.461188	3.092772	4.391287
+1.753871	5.407903	4.404516
+1.790130	1.676364	4.399870
+3.372039	0.088092	4.412895
+3.422033	3.420440	4.405659
+1.832656	3.578984	4.420078
+1.869385	4.101423	4.429231
+3.417193	4.560000	4.413158
+3.422449	4.800612	4.410612
+3.420000	4.073171	4.410976
+1.835120	3.283600	4.426720
+1.854615	3.835804	4.430490
+2.985375	2.620625	4.420500
+3.402115	4.316154	4.420000
+3.396567	5.046269	4.422687
+3.411875	1.763333	4.415417
+1.888414	2.816414	4.439379
+1.921985	6.370773	4.454072
+1.942976	1.352390	4.447024
+2.421905	3.221429	4.430000
+3.267258	3.224839	4.427903
+3.381739	0.334348	4.422609
+1.874386	4.610175	4.446053
+1.895455	6.102216	4.451591
+1.929106	1.872846	4.450244
+2.031634	0.500113	4.465380
+3.285890	3.633252	4.453804
+3.339167	1.993000	4.443167
+3.336800	5.342000	4.445400
+3.357778	0.573056	4.435556
+1.881967	4.357705	4.450984
+1.927667	5.234667	4.459778
+1.941207	4.969310	4.462299
+1.943193	2.361849	4.458739
+1.946067	3.064719	4.449888
+2.281107	3.778730	4.464139
+3.202211	4.889158	4.469579
+3.222500	2.714812	4.468925
+3.276398	1.279814	4.458882
+1.911379	2.111379	4.455517
+1.956587	5.523571	4.473571
+2.021105	5.799830	4.480397
+2.016705	1.605549	4.475780
+2.955467	4.987378	4.470178
+3.297115	5.873654	4.459615
+1.968889	0.906481	4.470556
+2.041504	0.232481	4.475564
+2.030139	3.425486	4.484167
+3.167750	4.372083	4.478500
+3.182201	5.152327	4.488239
+3.202281	6.209298	4.483333
+3.211528	0.930833	4.478750
+3.288889	3.885000	4.465278
+2.023051	2.607712	4.486102
+2.085117	4.752368	4.498889
+2.162039	5.105137	4.514118
+2.188956	0.027071	4.501650
+3.137778	2.434192	4.498485
+3.164298	0.261818	4.490083
+3.178559	4.106695	4.490508
+3.193238	4.630286	4.487714
+3.222206	1.627059	4.479853
+2.112585	4.194153	4.506356
+2.388241	6.031667	4.507454
+3.110000	0.017125	4.501000
+3.133874	1.860270	4.500450
+3.146815	3.428000	4.500444
+3.150125	0.681375	4.496250
+2.043220	3.683559	4.499322
+2.078488	3.928256	4.506163
+2.080877	1.126491	4.502105
+2.143235	2.845252	4.511807
+2.142185	0.737059	4.510000
+2.162036	3.174253	4.515701
+2.195234	1.414299	4.517196
+2.420727	5.516000	4.502909
+3.092024	5.753988	4.513988
+2.083636	4.481091	4.509818
+2.129890	6.037403	4.519945
+2.136481	2.158333	4.517222
+2.147413	5.365035	4.521608
+2.171013	1.912278	4.520253
+2.517957	0.374946	4.532177
+2.611892	2.870579	4.528996
+2.639500	2.342538	4.529577
+2.965216	6.326264	4.529954
+3.017746	0.466879	4.518786
+3.054196	3.141538	4.521748
+3.087407	1.429012	4.517407
+3.125645	2.122581	4.510000
+2.182571	2.419524	4.527810
+2.261818	1.677219	4.531604
+2.284662	3.413818	4.537534
+2.299140	0.529892	4.534140
+2.368175	3.002000	4.546975
+2.898807	3.353263	4.541649
+2.928312	4.164262	4.540295
+2.974531	3.611563	4.533281
+2.984802	5.996980	4.534109
+3.035253	1.178687	4.525758
+3.055048	3.859429	4.526857
+3.099677	5.502903	4.517742
+2.201294	6.287824	4.538647
+2.201583	5.622734	4.538705
+2.387429	2.229968	4.546286
+2.384335	5.253536	4.550875
+2.450701	0.081274	4.545796
+2.657893	2.056588	4.556825
+2.673548	1.546828	4.540538
+2.763293	5.149102	4.553802
+2.802667	3.819304	4.549739
+2.887919	2.252483	4.546309
+2.906238	0.700693	4.542772
+2.928047	1.623395	4.540744
+2.914365	1.994444	4.544683
+2.962179	4.728974	4.541859
+3.044590	2.888197	4.530984
+2.280435	0.271957	4.538913
+2.294800	0.918600	4.542200
+2.301515	4.893788	4.551667
+2.312439	1.174878	4.547073
+2.309103	4.029655	4.550828
+2.726194	4.601754	4.558694
+2.725085	4.331017	4.563941
+2.774916	1.125028	4.553911
+2.844211	5.784737	4.541228
+2.941930	4.460526	4.547018
+2.967167	0.940333	4.540500
+2.979506	5.288395	4.543951
+2.291538	4.609385	4.556769
+2.456503	3.606713	4.563497
+2.515185	1.033426	4.557130
+2.511747	3.871710	4.564758
+2.524069	5.024372	4.568009
+2.575205	1.286712	4.559110
+2.623849	5.376653	4.566318
+2.613053	5.920929	4.567212
+2.669851	0.613806	4.562612
+2.685503	4.064550	4.566720
+2.712057	0.869220	4.561986
+2.715388	3.560728	4.563107
+2.717687	6.388582	4.564104
+2.746135	1.800491	4.560245
+2.738658	4.873087	4.567517
+2.769551	6.130843	4.562978
+2.781688	0.388831	4.558831
+2.833500	3.021857	4.559286
+2.835000	2.745700	4.561000
+2.867373	5.508814	4.558559
+2.935610	0.197561	4.545122
+2.286970	4.363636	4.558182
+2.410946	1.958784	4.560405
+2.410723	5.755904	4.566145
+2.408519	2.482593	4.561111
+2.430769	1.498205	4.565385
+2.454750	0.745000	4.564750
+2.476559	4.215484	4.570753
+2.509652	4.752609	4.570870
+2.621308	2.607196	4.570280
+2.648615	5.639692	4.572615
+2.698732	0.138310	4.561972
+2.851094	1.366250	4.559688
+2.393023	2.731163	4.565581
+2.503182	1.733030	4.570000
+2.523095	6.235595	4.577262
+2.551757	3.370135	4.575676
+2.614267	3.130667	4.572133
+2.845000	2.492000	4.567000
+2.509355	4.466290	4.579032
+3.527562	3.019352	0.627099
+3.443333	3.203333	0.580000
\ No newline at end of file
diff --git a/source/Applications/BeadPack/paper/1-s2.0-S0309170813000183-main.pdf b/source/Applications/BeadPack/paper/1-s2.0-S0309170813000183-main.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..127843eccb4d05dc32b1fbeabc2c81fffc7043fc
Binary files /dev/null and b/source/Applications/BeadPack/paper/1-s2.0-S0309170813000183-main.pdf differ
diff --git a/source/Applications/CylinderSt/CMakeLists.txt b/source/Applications/CylinderSt/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5e13bd6602ede27bcfc4baded712194118506571
--- /dev/null
+++ b/source/Applications/CylinderSt/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(cylinder_st)
+
+INCLUDE(${SOURCE_ROOT}/core/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES core)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(cylinder_st BINARY)
diff --git a/source/Applications/CylinderSt/cylinder_st.cpp b/source/Applications/CylinderSt/cylinder_st.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e25250c0b69af9cc73e8f8dd031cdeebda835309
--- /dev/null
+++ b/source/Applications/CylinderSt/cylinder_st.cpp
@@ -0,0 +1,425 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "D3Q27PressureDifferencePostprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "RestartPostprocessor.h"
+#include "SolidBlocksHelper.h"
+#include "NUPSCounterPostprocessor.h"
+#include "BlocksPostprocessor.h"
+#include "LBMKernelETD3Q27BGK.h"
+#include "EmergencyExitPostprocessor.h"
+#include "D3Q27ForcesPostprocessor.h"
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "c:/temp/cylinder_st";
+         numOfThreads = 3;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/cylinder_st";
+         numOfThreads = 8;
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+           stringstream logFilename;
+           logFilename <<  pathname + "/logfile.txt";
+           UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = 0.00207051;
+
+      double L1 = 2.5;
+      double L2, L3, H;
+      L2 = L3 = H = 0.41;
+
+      LBMReal radius = 0.05;
+      LBMReal uLB = 0.05;
+      LBMReal Re = 1000.0;
+      LBMReal rhoLB = 1.0;
+      LBMReal l = L2 / dx;
+      //LBMReal nueLB = (uLB*l)/Re;
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 2;
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(0.5, 0.2, -0.1, 0.5, 0.2, L3+0.1, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27InteractorPtr cylinderInt;
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = dx;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+
+      const int blocknx1 = 10;
+      const int blocknx2 = 10;
+      const int blocknx3 = 10;
+      
+      dx = (0.41+2*dx)/(20.0*(int)blocknx2);
+
+      double blockLength = blocknx1*dx;
+
+      //refinement area
+      //double rf = cylinder->getLengthX1()/5;
+      //GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-rf, cylinder->getX2Minimum()-rf, cylinder->getX3Minimum(), 
+      //   cylinder->getX1Maximum()+6.0*rf, cylinder->getX2Maximum()+rf, cylinder->getX3Maximum()));
+      GbObject3DPtr refineCube(new  GbCuboid3D(g_minX1 + 20.0*blockLength, g_minX2 + 6.0*blockLength, cylinder->getX3Minimum(), 
+                                               g_minX1 + 33.0*blockLength, g_maxX2 - 6.0*blockLength, cylinder->getX3Maximum()));
+
+      Grid3DPtr grid(new Grid3D());
+
+      UbSchedulerPtr rSch(new UbScheduler(100000, 100000));
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      //UbSchedulerPtr emSch(new UbScheduler(1000, 1000));
+      //EmergencyExitPostprocessor em(grid, emSch, pathname+"/checkpoints/emex.txt", rp, comm);
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         rp->reconnect();
+
+         //cylinderInt = 
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " << l );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+        
+         grid->setDeltaX(dx);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+         
+         // UbTupleDouble6 bouningBox(gridCube->getX1Minimum(),gridCube->getX2Minimum(),gridCube->getX3Minimum(),
+                                   // gridCube->getX1Maximum(),gridCube->getX2Maximum(),gridCube->getX3Maximum());
+         // UbTupleInt3 blockNx(blocknx1, blocknx2, blocknx3);
+         // UbTupleInt3 gridNx(8, 16, 16);
+         // grid = Grid3DPtr(new Grid3D(bouningBox, blockNx, gridNx));
+         
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+      
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+blockLength, d_minX2, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+      
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+blockLength, d_maxX2+blockLength, d_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-blockLength, d_maxX2, d_minX3-blockLength, d_maxX1+blockLength, d_maxX2+2.0*blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_maxX3, d_maxX1+blockLength, d_maxX2+blockLength, d_maxX3+2.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_minX1, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+2.0*blockLength, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectBlockVisitor refVisitor(refineCube, baseLevel, refineLevel-1);
+            grid->accept(refVisitor);
+
+            RatioBlockVisitor ratioVisitor(refineLevel);
+            grid->accept(ratioVisitor);
+
+            RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            grid->accept(ratioSmoothVisitor);
+
+            OverlapBlockVisitor overlapVisitor(refineLevel);
+            grid->accept(overlapVisitor);
+
+            std::vector<int> dirs;
+            D3Q27System::getLBMDirections(dirs);
+            SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            grid->accept(interDirsVisitor);
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         MetisPartitioningGridVisitor metisVisitor(numOfThreads, D3Q27System::B, comm, false);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+         mu::Parser fct;
+         fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+         fct.DefineConst("U", uLB);
+         fct.DefineConst("H", H);
+
+         //inflow
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         sd.addInteractor(cylinderInt);
+         sd.addInteractor(addWallYminInt);
+         sd.addInteractor(addWallZminInt);
+         sd.addInteractor(addWallYmaxInt);
+         sd.addInteractor(addWallZmaxInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+         
+         sd.deleteSolidBlocks();
+         
+         grid->accept( metisVisitor );
+
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //walls
+         grid->addAndInitInteractor(addWallYminInt);
+         grid->addAndInitInteractor(addWallZminInt);
+         grid->addAndInitInteractor(addWallYmaxInt);
+         grid->addAndInitInteractor(addWallZmaxInt);
+
+         //obstacle
+         grid->addAndInitInteractor(cylinderInt);
+
+         //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+         initVisitor.setVx1(fct);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+         
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+
+      double outTime = 50000.0;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      visSch->addSchedule(1000, 1000, 10000);
+      visSch->addSchedule(10000, 10000, 50000);
+      visSch->addSchedule(1, 1, 10000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      double fdx = grid->getDeltaX(grid->getFinestInitializedLevel());
+      double point1[3] = {0.45, 0.20, 0.205};
+      double point2[3] = {0.55, 0.20, 0.205};
+
+      D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+         point1[0]-1.0*fdx, point1[1]-1.0*fdx, point1[2]-1.0*fdx, 
+         point1[0], point1[1], point1[2]));
+      if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+         point2[0], point2[1]-1.0*fdx, point2[2]-1.0*fdx, 
+         point2[0]+1.0*fdx, point2[1], point2[2]));
+      if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, conv, comm);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 10));
+      double area = (radius*radius*H)/fdx;
+      double v    = 4.0*uLB/9.0;
+      D3Q27ForcesPostprocessor fp(grid, visSch, pathname + "/results/forces.txt", cylinderInt, comm, rhoLB, v, area, D3Q27ForcesPostprocessor::X, D3Q27ForcesPostprocessor::Y);
+
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double endTime = 1000001.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/FlowAroundCylinder/CMakeLists.txt b/source/Applications/FlowAroundCylinder/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..528f72a6da15e67f460d0d2438b451cccd350679
--- /dev/null
+++ b/source/Applications/FlowAroundCylinder/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(cylinder)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(cylinder BINARY)
diff --git a/source/Applications/FlowAroundCylinder/cylinder.cpp b/source/Applications/FlowAroundCylinder/cylinder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea310c84f8f2ea691391538bc4a9e6d03777e938
--- /dev/null
+++ b/source/Applications/FlowAroundCylinder/cylinder.cpp
@@ -0,0 +1,755 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/cylinder_20nu";
+         numOfThreads = 4;
+         availMem = 10.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/cylinder_Re20nu2l";
+         numOfThreads = 1;
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = 0.1;
+
+      double L1 = 2.5;
+      double L2, L3, H;
+      L2 = L3 = H = 0.41;
+
+      LBMReal radius = 0.05;
+      LBMReal rhoReal = 1.0; //kg/m^3
+      LBMReal uReal = 0.45;//m/s
+      LBMReal uLB = 0.05;
+      LBMReal Re = 20.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+
+      //LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter(1.0, 1/sqrt(3.0)*(uReal/uLB), 1.0, 1.0/dx, dx*dx*dx));
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 3;
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(0.5, 0.2, -0.1, 0.5, 0.2, L3+0.1, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      GbObject3DPtr refCylinder(new GbCylinder3D(0.5, 0.2, -0.1, 0.5, 0.2, L3+0.1, radius+2.0*dx/(1<<refineLevel)));
+      GbSystem3D::writeGeoObject(refCylinder.get(),pathname + "/geo/refCylinder", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27InteractorPtr cylinderInt;
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = dx;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+
+      const int blocknx1 = 8;
+      const int blocknx2 = 8;
+      const int blocknx3 = 8;
+
+      dx = (0.41+2.0*dx)/(10.0*(int)blocknx2);
+
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+      double blockLength = blocknx1*dx;
+
+      //refinement area
+      double rf = cylinder->getLengthX1()/4;
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-rf, cylinder->getX2Minimum()-rf, cylinder->getX3Minimum(), 
+        cylinder->getX1Maximum()+rf, cylinder->getX2Maximum()+rf, cylinder->getX3Maximum()));
+//       GbObject3DPtr refineCube(new  GbCuboid3D(g_minX1 + 7.05*blockLength, g_minX2 + 3.05*blockLength, cylinder->getX3Minimum(), 
+//          g_minX1 + 12.95*blockLength, g_maxX2 - 3.05*blockLength, cylinder->getX3Maximum()));
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      UbSchedulerPtr rSch(new UbScheduler(100000, 100000));
+      //RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      //UbSchedulerPtr emSch(new UbScheduler(1000, 1000));
+      //EmergencyExitPostprocessor em(grid, emSch, pathname+"/checkpoints/emex.txt", rp, comm);
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         //grid = rp->restart(UbSystem::stringTo<int>(opt));
+         //rp->reconnect();
+
+         //cylinderInt = 
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"Number of processes = " << comm->getNumberOfProcesses() );
+            UBLOG(logINFO,"path = " << pathname );
+            UBLOG(logINFO,"L = " << L1/dx );
+            UBLOG(logINFO,"H = " << H/dx );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Number of level = " << refineLevel+1 );
+            //UBLOG(logINFO,conv->toString() );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         grid->setDeltaX(dx);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+         // UbTupleDouble6 bouningBox(gridCube->getX1Minimum(),gridCube->getX2Minimum(),gridCube->getX3Minimum(),
+         // gridCube->getX1Maximum(),gridCube->getX2Maximum(),gridCube->getX3Maximum());
+         // UbTupleInt3 blockNx(blocknx1, blocknx2, blocknx3);
+         // UbTupleInt3 gridNx(8, 16, 16);
+         // grid = Grid3DPtr(new Grid3D(bouningBox, blockNx, gridNx));
+
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            //refineHelper.addGbObject(refineCube, refineLevel);
+            refineHelper.addGbObject(refCylinder, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+         mu::Parser fct;
+         fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+         fct.DefineConst("U", uLB);
+         fct.DefineConst("H", H);
+
+         //inflow
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         sd.addInteractor(cylinderInt);
+         sd.addInteractor(addWallYminInt);
+         sd.addInteractor(addWallZminInt);
+         sd.addInteractor(addWallYmaxInt);
+         sd.addInteractor(addWallZmaxInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+
+         sd.deleteSolidBlocks();
+
+         grid->accept( metisVisitor );
+
+         sd.setTransBlocks();
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //walls
+         grid->addAndInitInteractor(addWallYminInt);
+         grid->addAndInitInteractor(addWallZminInt);
+         grid->addAndInitInteractor(addWallYmaxInt);
+         grid->addAndInitInteractor(addWallZmaxInt);
+
+         //obstacle
+         grid->addAndInitInteractor(cylinderInt);
+
+         //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+         initVisitor.setVx1(fct);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+
+      double outTime = 10000.0;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      //visSch->addSchedule(1000, 1000, 10000);
+      //visSch->addSchedule(10000, 10000, 50000);
+      //visSch->addSchedule(100, 100, 10000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      double fdx = grid->getDeltaX(grid->getFinestInitializedLevel());
+      double point1[3] = {0.45, 0.20, 0.205};
+      double point2[3] = {0.55, 0.20, 0.205};
+
+      D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+         point1[0]-1.0*fdx, point1[1]-1.0*fdx, point1[2]-1.0*fdx, 
+         point1[0], point1[1], point1[2]));
+      if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+         point2[0], point2[1]-1.0*fdx, point2[2]-1.0*fdx, 
+         point2[0]+1.0*fdx, point2[1], point2[2]));
+      if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      //D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, conv, comm);
+      D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, rhoReal, uReal, uLB, comm);
+      
+      double area = (2.0*radius*H)/(dx*dx);
+      double v    = 4.0*uLB/9.0;
+      D3Q27ForcesPostprocessor fp(grid, visSch, pathname + "/results/forces.txt", comm, v, area);
+      fp.addInteractor(cylinderInt);
+      
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 40));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double endTime = 100001.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+void run2(const char *cstr)
+{
+   try
+   {
+      Sleep(30000);
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/cylinder_20nu";
+         numOfThreads = 4;
+         availMem = 10.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/cylinder_Re20nu4l";
+         numOfThreads = 1;
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = 0.01;
+
+      double L1 = 2.5*2.0;
+      double L2, L3, H;
+      L2 = L3 = H = 0.41*2.0;
+
+      LBMReal radius = 0.05*2.0;
+      LBMReal rhoReal = 1.0; //kg/m^3
+      LBMReal uReal = 0.45;//m/s
+      LBMReal uLB = 0.05;
+      LBMReal Re = 20.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+
+      //LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter(1.0, 1/sqrt(3.0)*(uReal/uLB), 1.0, 1.0/dx, dx*dx*dx));
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 1;
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(0.5*2.0, 0.2*2.0, -0.1, 0.5*2.0, 0.2*2.0, L3+0.1, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      GbObject3DPtr refCylinder(new GbCylinder3D(0.5*2.0, 0.2*2.0, -0.1, 0.5*2.0, 0.2*2.0, L3+0.1, radius+7.0*dx/(1<<refineLevel)));
+      GbSystem3D::writeGeoObject(refCylinder.get(),pathname + "/geo/refCylinder", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27InteractorPtr cylinderInt;
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      //double offs = dx;
+      double offs = 0;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1;
+      double g_minX2 = d_minX2-7.0*dx;
+      double g_minX3 = d_minX3;
+
+      double g_maxX1 = d_maxX1;
+      double g_maxX2 = d_maxX2;
+      double g_maxX3 = d_maxX3;
+
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+
+      const int blocknx1 = 8;
+      const int blocknx2 = 8;
+      const int blocknx3 = 8;
+
+      //dx = (0.41+2.0*dx)/(10.0*(int)blocknx2);
+
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+      double blockLength = blocknx1*dx;
+
+      //refinement area
+      double rf = cylinder->getLengthX1()/4;
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-rf, cylinder->getX2Minimum()-rf, cylinder->getX3Minimum(), 
+         cylinder->getX1Maximum()+rf, cylinder->getX2Maximum()+rf, cylinder->getX3Maximum()));
+      //       GbObject3DPtr refineCube(new  GbCuboid3D(g_minX1 + 7.05*blockLength, g_minX2 + 3.05*blockLength, cylinder->getX3Minimum(), 
+      //          g_minX1 + 12.95*blockLength, g_maxX2 - 3.05*blockLength, cylinder->getX3Maximum()));
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      UbSchedulerPtr rSch(new UbScheduler(100000, 100000));
+      //RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      //UbSchedulerPtr emSch(new UbScheduler(1000, 1000));
+      //EmergencyExitPostprocessor em(grid, emSch, pathname+"/checkpoints/emex.txt", rp, comm);
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         //grid = rp->restart(UbSystem::stringTo<int>(opt));
+         //rp->reconnect();
+
+         //cylinderInt = 
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"Number of processes = " << comm->getNumberOfProcesses() );
+            UBLOG(logINFO,"path = " << pathname );
+            UBLOG(logINFO,"L = " << L1/dx );
+            UBLOG(logINFO,"H = " << H/dx );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Number of level = " << refineLevel+1 );
+            //UBLOG(logINFO,conv->toString() );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         grid->setDeltaX(dx);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+         // UbTupleDouble6 bouningBox(gridCube->getX1Minimum(),gridCube->getX2Minimum(),gridCube->getX3Minimum(),
+         // gridCube->getX1Maximum(),gridCube->getX2Maximum(),gridCube->getX3Maximum());
+         // UbTupleInt3 blockNx(blocknx1, blocknx2, blocknx3);
+         // UbTupleInt3 gridNx(8, 16, 16);
+         // grid = Grid3DPtr(new Grid3D(bouningBox, blockNx, gridNx));
+
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+blockLength, d_minX2, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+blockLength, d_maxX2+blockLength, d_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-blockLength, d_maxX2, d_minX3-blockLength, d_maxX1+blockLength, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_maxX3, d_maxX1+blockLength, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_minX1, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+blockLength, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            //refineHelper.addGbObject(refineCube, refineLevel);
+            refineHelper.addGbObject(refCylinder, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+         mu::Parser fct;
+         fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+         fct.DefineConst("U", uLB);
+         fct.DefineConst("H", H);
+
+         //inflow
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         sd.addInteractor(cylinderInt);
+         sd.addInteractor(addWallYminInt);
+         sd.addInteractor(addWallZminInt);
+         sd.addInteractor(addWallYmaxInt);
+         sd.addInteractor(addWallZmaxInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+
+         sd.deleteSolidBlocks();
+
+         grid->accept( metisVisitor );
+
+         sd.setTransBlocks();
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //walls
+         grid->addAndInitInteractor(addWallYminInt);
+         grid->addAndInitInteractor(addWallZminInt);
+         grid->addAndInitInteractor(addWallYmaxInt);
+         grid->addAndInitInteractor(addWallZmaxInt);
+
+         //obstacle
+         grid->addAndInitInteractor(cylinderInt);
+
+         //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+         initVisitor.setVx1(fct);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+
+      double outTime = 100.0;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      //visSch->addSchedule(1000, 1000, 10000);
+      //visSch->addSchedule(10000, 10000, 50000);
+      //visSch->addSchedule(100, 100, 10000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      double fdx = grid->getDeltaX(grid->getFinestInitializedLevel());
+      double point1[3] = {0.45, 0.20, 0.205};
+      double point2[3] = {0.55, 0.20, 0.205};
+
+      D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+         point1[0]-1.0*fdx, point1[1]-1.0*fdx, point1[2]-1.0*fdx, 
+         point1[0], point1[1], point1[2]));
+      if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+         point2[0], point2[1]-1.0*fdx, point2[2]-1.0*fdx, 
+         point2[0]+1.0*fdx, point2[1], point2[2]));
+      if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      //D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, conv, comm);
+      D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, rhoReal, uReal, uLB, comm);
+
+      double area = (2.0*radius*H)/(dx*dx);
+      double v    = 4.0*uLB/9.0;
+      D3Q27ForcesPostprocessor fp(grid, visSch, pathname + "/results/forces.txt", comm, v, area);
+      fp.addInteractor(cylinderInt);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 40));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double endTime = 100001.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+
+   run2(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/FlowAroundCylinder/cylinder.cpp1 b/source/Applications/FlowAroundCylinder/cylinder.cpp1
new file mode 100644
index 0000000000000000000000000000000000000000..b7ddec982c4a70a153fb1f6bf95de85c903fcc6a
--- /dev/null
+++ b/source/Applications/FlowAroundCylinder/cylinder.cpp1
@@ -0,0 +1,383 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "D3Q27PressureDifferencePostprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "RestartPostprocessor.h"
+#include "SolidBlocksHelper.h"
+#include "NUPSCounterPostprocessor.h"
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "c:/temp/cylinder";
+         numOfThreads = 1;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/cylinder";
+         numOfThreads = 8;
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile.txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      const double dx = 0.00205*5.0;
+
+      double L1 = 2.5;
+      double L2 = 0.41;
+      double L3 = 0.41;
+
+      LBMReal radius = 0.05;
+      LBMReal uLB = 0.01;
+      LBMReal Re = 100.0;
+      LBMReal rhoLB = 1.0;
+      LBMReal l = L2 / dx;
+      //LBMReal nueLB = (uLB*l)/Re;
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(0.5, 0.2, -0.1, 0.5, 0.2, L3+0.1, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      //bounding box
+      double g_minX1 = 0.0;
+      double g_minX2 = 0.0;
+      double g_minX3 = 0.0;
+
+      double g_maxX1 = L1;
+      double g_maxX2 = L2;
+      double g_maxX3 = L3;
+
+      double offs = dx;
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1-offs, g_minX2-offs, g_minX3-offs*2, g_maxX1+offs, g_maxX2+offs, g_maxX3+offs*2));
+
+      //refinement area
+      double rf = cylinder->getLengthX1();
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-rf, cylinder->getX2Minimum()-rf/2, cylinder->getX3Minimum(), 
+                                               cylinder->getX1Maximum()+2*rf, cylinder->getX2Maximum()+rf, cylinder->getX3Maximum()));
+
+      const int blocknx1 = 6;
+      const int blocknx2 = 6;
+      const int blocknx3 = 6;
+      
+      double blockLength = blocknx1*dx;
+
+      Grid3DPtr grid(new Grid3D());
+      UbSchedulerPtr rSch(new UbScheduler(50000, 50000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         grid = rp.restart(UbSystem::stringTo<int>(opt));
+         rp.reconnect();
+
+         SimulationParametersPtr param = SimulationParameters::getInstanz();
+         param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " << l );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         SimulationParametersPtr param = SimulationParameters::getInstanz();
+         param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+         param->setRho(rhoLB);
+         param->setVelocityX(uLB);
+         param->setViscosity(nueLB);
+
+         grid->setDeltaX(dx);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+      
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_minX2, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+      
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(g_minX1-blockLength, g_maxX2, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+2.0*blockLength, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+2.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_minX1, g_maxX2+blockLength, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(g_maxX1, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+2.0*blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectBlockVisitor refVisitor(refineCube, baseLevel, refineLevel-1);
+            grid->accept(refVisitor);
+
+            RatioBlockVisitor ratioVisitor(refineLevel);
+            grid->accept(ratioVisitor);
+
+            RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            grid->accept(ratioSmoothVisitor);
+
+            OverlapBlockVisitor overlapVisitor(refineLevel);
+            grid->accept(overlapVisitor);
+
+            std::vector<int> dirs;
+            D3Q27System::getLBMDirections(dirs);
+            SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            grid->accept(interDirsVisitor);
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         MetisPartitioningGridVisitor metisVisitor(numOfThreads, D3Q27System::B, comm, false);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+      
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27InteractorPtr cylinderInt( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+         sd.addInteractor(cylinderInt);
+         sd.deleteSolidBlocks();
+
+         grid->accept( metisVisitor );
+
+         //if(myid ==0) grid->writeBlocks(pathname + "/grid/blocks" + StringUtil::toString(myid), 0, WbWriterVtkXmlBinary::getInstance(), false);
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNummberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(addWallYminInt);
+
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(addWallZminInt);
+
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(addWallYmaxInt);
+
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(addWallZmaxInt);
+
+         //inflow
+         double Cz = geoInflow->getX3Centroid();
+         double Hz = geoInflow->getLengthX3()-2.0*blockLength;
+         double Cy = geoInflow->getX2Centroid();
+         double Hy = geoInflow->getLengthX2()-2.0*blockLength;
+         mu::Parser fct = MathUtil::getDuctParaboloidX(Cy,Hy,Cz,Hz,uLB);
+
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+         grid->addAndInitInteractor(outflowInt);
+
+         //obstacle
+         grid->addAndInitInteractor(cylinderInt);
+      
+         sd.updateGrid();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         //D3Q27InterpolationProcessorPtr iProcessor(new D3Q27CompactInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         if(myid ==0) grid->writeBlocks(pathname + "/grid/blocks" + StringUtil::toString(myid), 0, WbWriterVtkXmlBinary::getInstance(), false);
+
+         {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, geoSch, comm, true);
+            grid->doPostProcess(0);
+         }
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+
+      double outTime = 50000.0;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      visSch->addSchedule(10000, 10000, 50000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, visSch, comm);
+
+      double fdx = grid->getDeltaX(grid->getCoarsestInitializedLevel());
+      D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+         refineCube->getX1Minimum()-2.0*fdx-blockLength, gridCube->getX2Minimum()-1.0*fdx, cylinder->getX3Minimum()-1.0*fdx, 
+         refineCube->getX1Minimum()-1.0*fdx-blockLength, gridCube->getX2Maximum()+1.0*fdx, cylinder->getX3Maximum()+1.0*fdx));
+      if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+         refineCube->getX1Maximum()+1.0*fdx+blockLength, gridCube->getX2Minimum()-1.0*fdx, cylinder->getX3Minimum()-1.0*fdx, 
+         refineCube->getX1Maximum()+2.0*fdx+blockLength, gridCube->getX2Maximum()+1.0*fdx, cylinder->getX3Maximum()+1.0*fdx));
+      if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      D3Q27PressureDifferencePostprocessor rhopp(grid, pathname + "/results/rho_diff.txt", h1, h2, conv, visSch, comm);
+
+      NUPSCounterPostprocessor npr(grid, visSch, pathname + "/results/nups.txt", comm);
+
+      double endTime = 1000001.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/FlowAroundCylinder/cylinder.cpp2 b/source/Applications/FlowAroundCylinder/cylinder.cpp2
new file mode 100644
index 0000000000000000000000000000000000000000..35d9e975742e0365e4c4827d4bb8f3ebbacf3d4b
--- /dev/null
+++ b/source/Applications/FlowAroundCylinder/cylinder.cpp2
@@ -0,0 +1,400 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "D3Q27PressureDifferencePostprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "RestartPostprocessor.h"
+#include "SolidBlocksHelper.h"
+#include "NUPSCounterPostprocessor.h"
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "c:/temp/cylinder";
+         numOfThreads = 1;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/cylinder3";
+         numOfThreads = 8;
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile.txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else if(machine == "ESLOGIN001" || machine == "ESLOGIN002" || machine == "ESLOGIN003")      
+      {
+         pathname = "/zhome/academic/HLRS/xrm/xrmkuchr/work/cylinder";
+         numOfThreads = 16;
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile.txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE: " + machine);
+
+      const double dx = 0.00205*5.0;
+
+      double L1 = 2.5;
+      double L2 = 0.41;
+      double L3 = 0.41;
+
+      LBMReal radius = 0.05;
+      LBMReal uLB = 0.01;
+      LBMReal Re = 100.0;
+      LBMReal rhoLB = 1.0;
+      LBMReal l = L2 / dx;
+      //LBMReal nueLB = (uLB*l)/Re;
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(0.5, 0.2, -0.1, 0.5, 0.2, L3+0.1, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      //bounding box
+      double g_minX1 = 0.0;
+      double g_minX2 = 0.0;
+      double g_minX3 = 0.0;
+
+      double g_maxX1 = L1;
+      double g_maxX2 = L2;
+      double g_maxX3 = L3;
+
+      double offs = dx;
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1-offs, g_minX2-offs, g_minX3-offs*2, g_maxX1+offs, g_maxX2+offs, g_maxX3+offs*2));
+
+      //refinement area
+      double rf = cylinder->getLengthX1();
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-rf, cylinder->getX2Minimum()-rf/2, cylinder->getX3Minimum(), 
+                                               cylinder->getX1Maximum()+2*rf, cylinder->getX2Maximum()+rf, cylinder->getX3Maximum()));
+
+      const int blocknx1 = 6;
+      const int blocknx2 = 6;
+      const int blocknx3 = 6;
+      
+      double blockLength = blocknx1*dx;
+
+      Grid3DPtr grid(new Grid3D());
+      UbSchedulerPtr rSch(new UbScheduler(50000, 50000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         grid = rp.restart(UbSystem::stringTo<int>(opt));
+         rp.reconnect();
+
+         SimulationParametersPtr param = SimulationParameters::getInstanz();
+         param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"Number of threads = " << numOfThreads );
+            UBLOG(logINFO,"L = " << l );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         SimulationParametersPtr param = SimulationParameters::getInstanz();
+         param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+         param->setRho(rhoLB);
+         param->setVelocityX(uLB);
+         param->setViscosity(nueLB);
+
+         grid->setDeltaX(dx);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+      
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_minX2, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+      
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(g_minX1-blockLength, g_maxX2, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+2.0*blockLength, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+2.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_minX1, g_maxX2+blockLength, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(g_maxX1, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+2.0*blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectBlockVisitor refVisitor(refineCube, baseLevel, refineLevel-1);
+            grid->accept(refVisitor);
+
+            RatioBlockVisitor ratioVisitor(refineLevel);
+            grid->accept(ratioVisitor);
+
+            RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            grid->accept(ratioSmoothVisitor);
+
+            OverlapBlockVisitor overlapVisitor(refineLevel);
+            grid->accept(overlapVisitor);
+
+            std::vector<int> dirs;
+            D3Q27System::getLBMDirections(dirs);
+            SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            grid->accept(interDirsVisitor);
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         MetisPartitioningGridVisitor metisVisitor(numOfThreads, D3Q27System::B, comm, false);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+      
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27InteractorPtr cylinderInt( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+         sd.addInteractor(cylinderInt);
+         sd.deleteSolidBlocks();
+
+         grid->accept( metisVisitor );
+
+         //if(myid ==0) grid->writeBlocks(pathname + "/grid/blocks" + StringUtil::toString(myid), 0, WbWriterVtkXmlBinary::getInstance(), false);
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNummberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(addWallYminInt);
+
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(addWallZminInt);
+
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(addWallYmaxInt);
+
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(addWallZmaxInt);
+
+         //inflow
+         double Cz = geoInflow->getX3Centroid();
+         double Hz = geoInflow->getLengthX3()-2.0*blockLength;
+         double Cy = geoInflow->getX2Centroid();
+         double Hy = geoInflow->getLengthX2()-2.0*blockLength;
+         mu::Parser fct = MathUtil::getDuctParaboloidX(Cy,Hy,Cz,Hz,uLB);
+
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+         grid->addAndInitInteractor(outflowInt);
+
+         //obstacle
+         grid->addAndInitInteractor(cylinderInt);
+      
+         sd.updateGrid();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         //D3Q27InterpolationProcessorPtr iProcessor(new D3Q27CompactInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         if(myid ==0) grid->writeBlocks(pathname + "/grid/blocks" + StringUtil::toString(myid), 0, WbWriterVtkXmlBinary::getInstance(), false);
+
+         {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, geoSch, comm, true);
+            grid->doPostProcess(0);
+         }
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+
+      double outTime = 50000.0;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      visSch->addSchedule(1000, 0, 5001);
+
+      //D3Q27MacroscopicQuantitiesPostprocessor pp(grid, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, visSch, comm);
+//
+      //double fdx = grid->getDeltaX(grid->getFinestInitializedLevel());
+      //double point1[3] = {0.45, 0.20, 0.205};
+      //double point2[3] = {0.55, 0.20, 0.205};
+//
+      //D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+         //point1[0]-2.0*fdx-blockLength, point1[1]-1.0*fdx, point1[2]-1.0*fdx, 
+         //point1[0]-1.0*fdx-blockLength, point1[1]+1.0*fdx, point1[2]+1.0*fdx));
+      //if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      //D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+         //point2[0]+1.0*fdx+blockLength, point2[1]-1.0*fdx, point2[2]-1.0*fdx, 
+         //point2[0]+2.0*fdx+blockLength, point2[1]+1.0*fdx, point2[2]+1.0*fdx));
+      //if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      //D3Q27PressureDifferencePostprocessor rhopp(grid, pathname + "/results/rho_diff.txt", h1, h2, conv, visSch, comm);
+
+      NUPSCounterPostprocessor npr(grid, visSch, pathname + "/results/nups.txt", comm);
+
+      double endTime = 5001.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/Hagen_Poiseuille_flow/CMakeLists.txt b/source/Applications/Hagen_Poiseuille_flow/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..85ff8fdadf812540bebe4c48501092600f66263a
--- /dev/null
+++ b/source/Applications/Hagen_Poiseuille_flow/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(pflow)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(pflow BINARY)
diff --git a/source/Applications/Hagen_Poiseuille_flow/pflow.cpp b/source/Applications/Hagen_Poiseuille_flow/pflow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3672f43f2211f9ec2bccb532724bc4a20aef3e0
--- /dev/null
+++ b/source/Applications/Hagen_Poiseuille_flow/pflow.cpp
@@ -0,0 +1,749 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void pflowForcing(const char *cstr)
+{
+   try
+   {
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 4;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/Hagen_Poiseuille_flow_forcing2";
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/Hagen_Poiseuille_flow_forcing";
+         availMem = 12.0e9;
+
+//         if(myid ==0)
+//         {
+//            stringstream logFilename;
+//            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+//            UbLog::output_policy::setStream(logFilename.str());
+//         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = 1;
+
+      //const int blocknx1 = 16;
+      //const int blocknx2 = 16;
+      //const int blocknx3 = 16;
+
+      const int blocknx1 = 8;
+      const int blocknx2 = 8;
+      const int blocknx3 = 8;
+
+      LBMReal uLB = 0.05;
+      LBMReal rhoLB = 0.0;
+      LBMReal nueLB = 0.05842;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 1;
+
+      //bounding box
+      double g_minX1 = 0;
+      double g_minX2 = 0;
+      double g_minX3 = 0;
+
+      //double g_maxX1 = 16;
+      //double g_maxX2 = 128;
+      //double g_maxX3 = 16;
+
+      double g_maxX1 = 32;
+      double g_maxX2 = 32;
+      double g_maxX3 = 32;
+
+      double blockLength = blocknx1*dx;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setPeriodicX1(true);
+      grid->setPeriodicX2(false);
+      grid->setPeriodicX3(true);
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());      
+
+      //GbObject3DPtr refineCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2/3.0, g_maxX3));
+      //if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+      GbObject3DPtr refineCube(new GbCuboid3D(g_minX1+blockLength+2*dx, g_minX2+blockLength+2*dx, g_minX3+blockLength+2*dx, g_maxX1-blockLength-2*dx, g_maxX2-blockLength-2*dx, g_maxX3-blockLength-2*dx));
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+      
+      //UbSchedulerPtr rSch(new UbScheduler());
+      //rSch->addSchedule(50, 50, 50);
+      //RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         //if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+         //grid = rp->restart(UbSystem::stringTo<int>(opt));
+         //rp->reconnect(grid);
+
+         mu::Parser fctForcingX1;
+         mu::Parser fctForcingX2;
+         mu::Parser fctForcingX3;
+         fctForcingX1.SetExpr("Fx1*dx");
+         fctForcingX1.DefineConst("Fx1", 9.99685e-7);
+         fctForcingX2.SetExpr("0.0");
+         fctForcingX3.SetExpr("0.0");
+
+         SetForcingBlockVisitor forcingVisitor(fctForcingX1, fctForcingX2, fctForcingX3);
+         grid->accept(forcingVisitor);
+
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+      }
+      else
+      {
+
+      GenBlocksGridVisitor genBlocks(gridCube);
+      grid->accept(genBlocks);
+
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"Parameters:");
+         //UBLOG(logINFO,"L = " << L2/dx );
+         UBLOG(logINFO,"v = " << uLB );
+         UBLOG(logINFO,"rho = " << rhoLB );
+         UBLOG(logINFO,"nue = " << nueLB );
+         //UBLOG(logINFO,"Re = " << Re );
+         UBLOG(logINFO,"dx = " << dx );
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+         UBLOG(logINFO,"Preprozess - start");
+      }
+
+      //walls
+      GbCuboid3DPtr addWallYmin (new GbCuboid3D(g_minX1-1.0*blockLength, g_minX2-1.0*blockLength, g_minX3-1.0*blockLength, g_maxX1+1.0*blockLength, g_minX2, g_maxX3+1.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallYmax (new GbCuboid3D(g_minX1-1.0*blockLength, g_maxX2, g_minX3-1.0*blockLength, g_maxX1+1.0*blockLength, g_maxX2+1.0*blockLength, g_maxX3+1.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+      if (refineLevel > 0)
+      {
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+         RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+         refineHelper.addGbObject(refineCube, 1);
+         refineHelper.refine();
+         if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      }
+
+      int bbOption = 0; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+      D3Q27BoundaryConditionAdapterPtr bcObst2(new D3Q27SlipBCAdapter(bbOption));
+
+      //walls
+      D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+
+      ////////////////////////////////////////////
+      //METIS
+      Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));   
+      ////////////////////////////////////////////
+      /////delete solid blocks
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+      InteractorsHelper intHelper(grid, metisVisitor);
+      intHelper.addInteractor(addWallYminInt);
+      intHelper.addInteractor(addWallYmaxInt);
+      intHelper.selectBlocks();
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+      //////////////////////////////////////
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition for threads
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nodb = (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nod = nob * (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+      double needMemAll  = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         int minInitLevel = grid->getCoarsestInitializedLevel();
+         int maxInitLevel = grid->getFinestInitializedLevel();
+         for(int level = minInitLevel; level<=maxInitLevel; level++)
+         {
+            int nobl = grid->getNumberOfBlocks(level);
+            UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nob);
+            UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nob*nodb);
+         }
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      int kernelType = 2;
+      LBMKernel3DPtr kernel;
+      if (kernelType == 0)
+      {
+         rhoLB = 1.0;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+      }
+      else if (kernelType == 1)
+      {
+         rhoLB = 1.0;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+      }
+      else if (kernelType == 2)
+      {
+         rhoLB = 0.0;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+         //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBex2(blocknx1, blocknx2, blocknx3, 0, grid));
+      }
+
+      mu::Parser fctForcingX1;
+      fctForcingX1.SetExpr("Fx1*dx");
+      fctForcingX1.DefineConst("Fx1", 9.99685e-7);
+
+      kernel->setForcingX1(fctForcingX1);
+      kernel->setWithForcing(true);
+      
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      if (refineLevel > 0)
+      {
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+      //walls
+      intHelper.setBC();
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, true));
+      ppgeo->update(0);
+      ppgeo.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+}
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      double outTime = 1;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      //UbSchedulerPtr stepSch(new UbScheduler());
+      //stepSch->addSchedule(10, 100, 1000);
+      //nodeSch->addSchedule(1000, 1000, 10000);
+      //nodeSch->addSchedule(10000, 10000, 50000);
+      //stepSch->addSchedule(100, 100, 1000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv);
+      
+      double fdx = grid->getDeltaX(grid->getFinestInitializedLevel());
+
+      D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+                                       g_minX1, g_minX2, g_minX3, 
+                                       g_minX1+1.0*fdx, g_maxX2, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+                                       g_maxX1-1.0*fdx, g_minX2, g_minX3, 
+                                       g_maxX1, g_maxX2, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      LBMReal rhoReal = rhoLB;
+      LBMReal uReal = uLB;
+      D3Q27PressureDifferencePostprocessor rhopp(grid, stepSch, pathname + "/results/rho_diff.txt", h1, h2, rhoReal, uReal, uLB, comm);
+
+      double endTime =10000;//10001.0;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+void pflowdp(const char *cstr)
+{
+   try
+   {
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/Hagen_Poiseuille_flow_tube_testC";
+         availMem = 4.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/Hagen_Poiseuille_flow_tube5";
+         availMem = 10.0e9;
+         numOfThreads = 8;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = 1;
+
+      const int blocknx1 = 16;
+      const int blocknx2 = 16;
+      const int blocknx3 = 16;
+
+      LBMReal rhoLB = 0.0;//1.4e-7; //0.0;
+      LBMReal nuLB = 0.168666666667;
+
+      double coord[6];
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      double Ri = 16;
+      double f = 1;
+      double r = f*Ri;
+
+      //bounding box
+      double g_minX1 = 0;
+      double g_minX2 = 0;
+      double g_minX3 = 0;
+
+      double g_maxX1 = 2.0*r*4.0;
+      double g_maxX2 = 2.0*r;
+      double g_maxX3 = 2.0*r;
+
+      double blockLength = (double)blocknx1*dx;
+
+      double h = (g_maxX2)/2.0;
+
+      double rhoLBinflow = 0.003;//9e-7;
+      
+    //  rhoLBinflow/=1000.0;
+
+      double dpLB = (rhoLBinflow - rhoLB)/3.0;
+
+      
+      double dex = g_maxX1;
+      double Umax = (1.0/(4.0*nuLB))*(dpLB/dex)*(h*h);
+
+      double Re = (4*h*Umax)/(3*nuLB);
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setPeriodicX1(true);
+      grid->setPeriodicX2(false);
+      grid->setPeriodicX3(false);
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());      
+
+      double k1 = 4;
+      double k2 = 8;
+
+      GbObject3DPtr refineCube1_1(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2/k1-1.0, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube1_1.get(),pathname + "/geo/refineCube1_1", WbWriterVtkXmlBinary::getInstance());
+
+      GbObject3DPtr refineCube1_2(new GbCuboid3D(g_minX1, g_maxX2-g_maxX2/k1+1.0, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube1_2.get(),pathname + "/geo/refineCube1_2", WbWriterVtkXmlBinary::getInstance());
+
+      GbObject3DPtr refineCube2_1(new GbCuboid3D(g_minX1+2*blockLength+2*dx, g_minX2, g_minX3, g_maxX1-2*blockLength-2*dx, g_maxX2/k2-1.0, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube2_1.get(),pathname + "/geo/refineCube2_1", WbWriterVtkXmlBinary::getInstance());
+
+      GbObject3DPtr refineCube2_2(new GbCuboid3D(g_minX1+2*blockLength+2*dx, g_maxX2-g_maxX2/k2+1.0, g_minX3, g_maxX1-2*blockLength-2*dx, g_maxX2, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube2_2.get(),pathname + "/geo/refineCube2_2", WbWriterVtkXmlBinary::getInstance());
+      
+      GbObject3DPtr refineCube2_3(new GbCuboid3D(g_minX1+blockLength+2*dx, g_minX2+blockLength+2*dx, g_minX3+blockLength+2*dx, g_maxX1-blockLength-2*dx, g_maxX2-blockLength-2*dx, g_maxX3-blockLength-2*dx));
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube2_3.get(),pathname + "/geo/refineCube2_3", WbWriterVtkXmlBinary::getInstance());
+
+      //UbSchedulerPtr rSch(new UbScheduler());
+      //rSch->addSchedule(50, 50, 50);
+      //RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      double restartStep = 300000;
+      double restartStart = 200000;
+      UbSchedulerPtr rSch(new UbScheduler(restartStep));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::TXT);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"Parameters:");
+            UBLOG(logINFO,"h = " << h );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nuLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"dpLB = " << dpLB );
+            UBLOG(logINFO,"Umax = " << Umax );
+            UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+            UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+            UBLOG(logINFO,"path = " << pathname );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         //tube
+         GbCylinder3DPtr tube(new GbCylinder3D(gridCube->getX1Minimum(),gridCube->getX2Centroid(),gridCube->getX3Centroid(),
+                                               gridCube->getX1Maximum(),gridCube->getX2Centroid(),gridCube->getX3Centroid(), g_maxX3/2.0));
+
+         coord[0] = tube->getX1Minimum();
+         coord[1] = tube->getX2Minimum();
+         coord[2] = tube->getX3Minimum();
+         coord[3] = tube->getX1Maximum();
+         coord[4] = tube->getX2Maximum();
+         coord[5] = tube->getX3Maximum();
+
+         ////walls
+         //GbCuboid3DPtr addWallYmin (new GbCuboid3D(g_minX1-4.0*blockLength, g_minX2-4.0*blockLength, g_minX3-4.0*blockLength, g_maxX1+4.0*blockLength, g_minX2, g_maxX3+4.0*blockLength));
+         //if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         //GbCuboid3DPtr addWallYmax (new GbCuboid3D(g_minX1-4.0*blockLength, g_maxX2, g_minX3-4.0*blockLength, g_maxX1+4.0*blockLength, g_maxX2+4.0*blockLength, g_maxX3+4.0*blockLength));
+         //if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(g_minX1-4.0*blockLength, g_minX2-4.0*blockLength, g_minX3-4.0*blockLength, g_minX1, g_maxX2+4.0*blockLength, g_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(g_maxX1, g_minX2-4.0*blockLength, g_minX3-4.0*blockLength, g_maxX1+4.0*blockLength, g_maxX2+4.0*blockLength, g_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         ////inflow
+         //GbCuboid3DPtr geoInflow (new GbCuboid3D(g_minX1-4.0*blockLength, g_minX2-4.0*blockLength, g_minX3-4.0*blockLength, g_maxX1+4.0*blockLength, g_maxX2+4.0*blockLength, g_minX3));
+         //if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         ////outflow
+         //GbCuboid3DPtr geoOutflow (new GbCuboid3D(g_minX1-4.0*blockLength, g_minX2-4.0*blockLength, g_maxX3, g_maxX1+4.0*blockLength, g_maxX2+4.0*blockLength, g_maxX3+4.0*blockLength));
+         //if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            //refineHelper.addGbObject(refineCube1_1, 1);
+            //refineHelper.addGbObject(refineCube1_2, 1);
+            //refineHelper.addGbObject(refineCube2_1, 2);
+            //refineHelper.addGbObject(refineCube2_2, 2);
+            refineHelper.addGbObject(refineCube2_3, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         int bbOption = 0; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27BoundaryConditionAdapterPtr bcObst2(new D3Q27SlipBCAdapter(bbOption));
+
+         mu::Parser fct0;
+         fct0.SetExpr("0.0001");
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct0, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+
+         D3Q27InteractorPtr tubeInt(new D3Q27Interactor(tube, grid, bcObst,Interactor3D::INVERSESOLID));
+
+         //walls
+         //D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         //D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         //D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, velBCAdapter,Interactor3D::SOLID));
+
+         //inflow
+         //double dp_Ph=0.1*10000.0;//dp in Bar
+         //double dp_lb=dp_Ph*0.001*(nueLB*dx)*(nueLB*dx);//nue_ph=10e-6
+         //if(myid == 0) UBLOG(logINFO,"dp_lb = " << dp_lb );
+         //double rhoLBinflow = 3.0*(dp_lb-rhoLB);
+
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterFront(new D3Q27DensityBCAdapter(rhoLBinflow));
+         denBCAdapterFront->setSecondaryBcOption(0);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, denBCAdapterFront, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(0);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));   
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(tubeInt);
+         //intHelper.addInteractor(addWallYminInt);
+         //intHelper.addInteractor(addWallYmaxInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1) * (blocknx2) * (blocknx3);
+         unsigned long nod = nob * (blocknx1) * (blocknx2) * (blocknx3);
+         unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+         double needMemAll  = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for(int level = minInitLevel; level<=maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nobl);
+               UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nobl*nodb);
+            }
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         int kernelType = 2;
+         LBMKernel3DPtr kernel;
+         //if (kernelType == 0)
+         //{
+         //   rhoLB = 1.0;
+         //   kernel = LBMKernel3DPtr(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+         //}
+         //else if (kernelType == 1)
+         //{
+         //   rhoLB = 1.0;
+         //   kernel = LBMKernel3DPtr(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+         //}
+         //else if (kernelType == 2)
+         //{
+         //   rhoLB = 0.0;
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+         //}
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+
+         BoundaryConditionPtr densityBC(new NonEqDensityBoundaryCondition());
+         //BoundaryConditionPtr densityBC(new NonReflectingDensityBoundaryCondition());
+         //BoundaryConditionPtr noSlipBC(new HighViscosityNoSlipBoundaryCondition());
+         BoundaryConditionPtr noSlipBC(new NoSlipBoundaryCondition());
+
+         bcProc->addBC(densityBC);
+         bcProc->addBC(noSlipBC);
+
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //walls
+         intHelper.setBC();
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         //initialization of distributions
+         mu::Parser fct;
+         fct.SetExpr("-(1.0/(2.0*nu))*(dp/dx)*((x2-h)^2 - h^2)");
+         fct.DefineConst("dp", dpLB);
+         fct.DefineConst("dx", dex);
+         fct.DefineConst("h", h);
+         fct.DefineConst("nu", nuLB);
+
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nuLB, rhoLB);
+         //initVisitor.setVx1(fct);
+         initVisitor.setVx1(0.0);
+         //initVisitor.setVx3(fct);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         //grid->addInteractor(inflowInt);
+         //grid->addInteractor(outflowInt);
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+      else
+      {
+         Grid3D::Interactor3DSet interactors = grid->getInteractors();
+         interactors[0]->setGrid3D(grid);
+         boost::dynamic_pointer_cast<D3Q27Interactor>(interactors[0])->deleteBCAdapter();
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterFront(new D3Q27DensityBCAdapter(rhoLBinflow));
+         boost::dynamic_pointer_cast<D3Q27Interactor>(interactors[0])->addBCAdapter(denBCAdapterFront);
+         interactors[0]->updateInteractor();
+
+         //BOOST_FOREACH(Interactor3DPtr i, interactors)
+         //{
+         //   i->setGrid3D(grid);
+         //   i->updateInteractor();
+         //}
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+      }
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch,numOfThreads, comm);
+
+      D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]));
+      if (myid == 0) GbSystem3D::writeGeoObject(ih1->getBoundingBox().get(), pathname + "/geo/ih1", WbWriterVtkXmlBinary::getInstance());
+
+      UbSchedulerPtr stepMV(new UbScheduler(5));
+
+      TimeseriesPostprocessor tsp(grid, stepMV, ih1, pathname+"/ts/ts1", comm);
+
+      double outTime = 100;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      stepSch->addSchedule(1000, 1000, 1000);
+      stepSch->addSchedule(384000, 384000, 384000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+      double endTime =400000;//10001.0;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+
+   if ( argv != NULL )
+   {
+//      if (argc > 1)
+//      {
+         //pflowForcing(argv[1]);
+         pflowdp(argv[1]);
+//      }
+//      else
+//      {
+//         cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+//      }
+   }
+
+   return 0;
+}
diff --git a/source/Applications/LaminarTubeFlow/CMakeLists.txt b/source/Applications/LaminarTubeFlow/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..866827f3e9f63ef9f9cb6ce3384246cfe0c5be45
--- /dev/null
+++ b/source/Applications/LaminarTubeFlow/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(ltf)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(ltf BINARY)
diff --git a/source/Applications/LaminarTubeFlow/ltf.cpp b/source/Applications/LaminarTubeFlow/ltf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fa3e0b387681ba1ea761e84859ff75902506c5c4
--- /dev/null
+++ b/source/Applications/LaminarTubeFlow/ltf.cpp
@@ -0,0 +1,288 @@
+#include <iostream>
+#include <string>
+
+#include "vfluids.h"
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/ltf_ref_bc_long2";
+         numOfThreads = 4;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/ltf2";
+         numOfThreads = 8;
+         availMem = 12.0e9;
+
+         //if(myid ==0)
+         //{
+         //   stringstream logFilename;
+         //   logFilename <<  pathname + "/logfile.txt";
+         //   UbLog::output_policy::setStream(logFilename.str());
+         //}
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      const double dx = 1.0;
+
+      double L1 = 32*2;
+      double L2 = 32;
+      double L3 = L2;
+
+      LBMReal dLB = L2;
+      LBMReal uLB = 0.05;
+      LBMReal Re = 10.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+      LBMReal nuLB = (uLB*dLB)/Re;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      //bounding box
+      double g_minX1 = 0.0;
+      double g_minX2 = -L2 / 2.0;
+      double g_minX3 = -L3 / 2.0;
+
+      double g_maxX1 = L1;
+      double g_maxX2 = L2 / 2.0;
+      double g_maxX3 = L3 / 2.0;
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(g_minX1-2.0*dx, 0.0, 0.0, g_maxX1+2.0*dx, 0.0, 0.0, dLB/2.0));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      double offs = dx;
+      //GbObject3DPtr gridCube(new GbCuboid3D(g_minX1-offs, g_minX2-offs, g_minX3-offs, g_maxX1+offs, g_maxX2+offs, g_maxX3+offs));
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+
+      const int blocknx1 = 8;
+      const int blocknx2 = 8;
+      const int blocknx3 = 8;
+      
+      double blockLength = blocknx1*dx;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      UbSchedulerPtr rSch(new UbScheduler(100000, 100000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " << l );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nuLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         grid->setDeltaX(dx);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+         //grid->setPeriodicX3(true);
+
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+      
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         //inflow
+         GbCuboid3DPtr geoInflow(new GbCuboid3D(g_minX1 - 2.0*dx, g_minX2 - dx, g_minX3 - dx, g_minX1, g_maxX2, g_maxX3 + dx));
+          if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(g_maxX1, g_minX2, g_minX3-dx, g_maxX1+2.0*dx, g_maxX2+dx, g_maxX3+dx));
+          if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+         ppblocks->update(0);
+      
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27InteractorPtr cylinderInt( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::INVERSESOLID));
+
+         double r = boost::dynamic_pointer_cast<GbCylinder3D>(cylinder)->getRadius();
+         double cx1 = g_minX1;
+         double cx2 = cylinder->getX2Centroid();
+         double cx3 = cylinder->getX3Centroid();
+         mu::Parser fct;
+         fct.SetExpr("vx1*(1-((x2-y0)^2+(x3-z0)^2)/(R^2))");
+         fct.DefineConst("x2Vmax", 0.0); //x2-Pos fuer vmax
+         fct.DefineConst("x3Vmax", 0.0); //x3-Pos fuer vmax
+         fct.DefineConst("R", r);
+         fct.DefineConst("vx1", uLB);
+         fct.DefineConst("x0", cx1);
+         fct.DefineConst("y0", cx2);
+         fct.DefineConst("z0", cx3);
+         fct.DefineConst("nue", nuLB);
+         //mu::Parser fct;
+         //fct.SetExpr("-vx1*((x2+h)*(x2-h))/(h^2)");
+         //fct.DefineConst("vx1"  , uLB           );
+         //fct.DefineConst("h"  ,    (g_maxX2 - g_minX2)/2.0        );
+
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter(true, false, false, fct, 0, D3Q27BCFunction::INFCONST));
+         //velBCAdapter->setSecondaryBcOption(2);
+
+         D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+         //D3Q27InteractorPtr inflowInt( new D3Q27Interactor(geoInflow, grid, bcObst,Interactor3D::SOLID));
+
+         //D3Q27BoundaryConditionAdapterPtr denBCAdapter1(new D3Q27DensityBCAdapter(rhoLB*1.001));
+         //D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, denBCAdapter1,Interactor3D::SOLID));
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(0);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoOutflow, grid, denBCAdapter, Interactor3D::SOLID));
+         //D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, bcObst,Interactor3D::SOLID));
+         grid->addAndInitInteractor(outflowInt);
+
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(cylinderInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nod = nob * (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nodg = nob * (blocknx1 + gl) * (blocknx2 + gl) * (blocknx3 + gl);
+         double needMemAll = double(nodg*(27 * sizeof(double) + sizeof(int) + sizeof(float) * 4));
+         double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Number of blocks = " << nob);
+            UBLOG(logINFO, "Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for (int level = minInitLevel; level <= maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO, "Number of blocks for level " << level << " = " << nob);
+               UBLOG(logINFO, "Number of nodes for level " << level << " = " << nob*nodb);
+            }
+            UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+            UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+            UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel;
+         rhoLB = 0.0;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         //
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         intHelper.setBC();
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nuLB, rhoLB);
+         //initVisitor.setVx1(fct);
+         //initVisitor.setNu(nuLB);
+         //initVisitor.setVx1(0.01);
+         //initVisitor.setVx2(0.02);
+         //initVisitor.setVx3(0.03);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         //UbSchedulerPtr geoSch(new UbScheduler(1));
+         //D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         //   new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+         //ppgeo->update(0);
+         //ppgeo.reset();
+
+         {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            //D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+            D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+               new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+            //grid->addObserver(ppgeo);
+            grid->doPostProcess(0);
+            //grid->notifyObservers(0);
+            //grid->removeObserver(ppgeo);
+         }
+
+      if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+
+      double outTime = 1000;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      //visSch->addSchedule(1, 1, 10000);
+      //visSch->addSchedule(10000, 10000, 50000);
+      //visSch->addSchedule(1000, 1000, 100000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlASCII::getInstance(), conv);
+
+      double endTime = 1000001.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/LaminarTubeFlowConv/CMakeLists.txt b/source/Applications/LaminarTubeFlowConv/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..31cf787822aedf1f4c43cc6a1eb20a722209306f
--- /dev/null
+++ b/source/Applications/LaminarTubeFlowConv/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(ltfc)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(ltfc BINARY)
diff --git a/source/Applications/LaminarTubeFlowConv/ltf.cpp b/source/Applications/LaminarTubeFlowConv/ltf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..44ed43de11db630ea185b6db89fbe70f420b6cce
--- /dev/null
+++ b/source/Applications/LaminarTubeFlowConv/ltf.cpp
@@ -0,0 +1,279 @@
+#include <iostream>
+#include <string>
+
+#include "vfluids.h"
+
+using namespace std;
+
+
+int x[3] = { 120, 240, 480 };
+int y[3] = { 20, 40, 80 };
+int z[3] = { 20, 40, 80 };
+
+//int x[3] = { 120, 120, 120 };
+//int y[3] = { 20, 20, 20 };
+//int z[3] = { 20, 20, 20 };
+double nuLB = 0.001;
+double dp[3] = { 25000.0, 100000.0, 400000.0 };
+double tout[3] = { 4000.0, 16000.0, 64000.0 };
+double tend[3] = { 100001.0, 400001.0, 1600001.0 };
+//double deltax[3] = { 1.0, 0.5, 0.25 };
+double deltax[3] = { 1.0, 1.0, 1.0 };
+
+
+void run(int tn)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/ltfc" + UbSystem::toString(tn);
+         numOfThreads = 1;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/ltfc"+UbSystem::toString(tn);
+         numOfThreads = 8;
+         availMem = 12.0e9;
+
+#if defined(__unix__)
+         if (myid == 0)
+         {
+            const char* str = pathname.c_str();
+            int status = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+         }
+#endif 
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename << pathname + "/logfile" + UbSystem::toString(UbSystem::getTimeStamp()) + "_" + UbSystem::toString(myid) + ".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = deltax[tn];
+
+      double L1 = x[tn];
+      double L2 = y[tn];
+      double L3 = z[tn];
+
+      LBMReal dLB = L2;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      //bounding box
+      double g_minX1 = 0.0;
+      double g_minX2 = -L2 / 2.0;
+      double g_minX3 = -L3 / 2.0;
+
+      double g_maxX1 = L1;
+      double g_maxX2 = L2 / 2.0;
+      double g_maxX3 = L3 / 2.0;
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(g_minX1-2.0*dx, 0.0, 0.0, g_maxX1+2.0*dx, 0.0, 0.0, dLB/2.0));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      double offs = dx;
+      //GbObject3DPtr gridCube(new GbCuboid3D(g_minX1-offs, g_minX2-offs, g_minX3-offs, g_maxX1+offs, g_maxX2+offs, g_maxX3+offs));
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+
+      const int blocknx1 = 10;
+      const int blocknx2 = 10;
+      const int blocknx3 = 10;
+      
+      double blockLength = blocknx1*dx;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      UbSchedulerPtr rSch(new UbScheduler(100000, 100000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " << l );
+            UBLOG(logINFO,"lLB = " << L1 );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nuLB );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         grid->setDeltaX(dx);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+         //grid->setPeriodicX3(true);
+
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+      
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         //inflow
+         GbCuboid3DPtr geoInflow(new GbCuboid3D(g_minX1 - 2.0*dx, g_minX2 - dx, g_minX3 - dx, g_minX1, g_maxX2, g_maxX3 + dx));
+          if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(g_maxX1, g_minX2, g_minX3-dx, g_maxX1+2.0*dx, g_maxX2+dx, g_maxX3+dx));
+          if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+         ppblocks->update(0);
+      
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27InteractorPtr cylinderInt( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::INVERSESOLID));
+
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter1(new D3Q27DensityBCAdapter(1.0/dp[tn]));
+         D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, denBCAdapter1,Interactor3D::SOLID));
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter2(new D3Q27DensityBCAdapter(-1.0/dp[tn]));
+         denBCAdapter2->setSecondaryBcOption(0);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoOutflow, grid, denBCAdapter2, Interactor3D::SOLID));
+         grid->addAndInitInteractor(outflowInt);
+
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(cylinderInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nod = nob * (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nodg = nob * (blocknx1 + gl) * (blocknx2 + gl) * (blocknx3 + gl);
+         double needMemAll = double(nodg*(27 * sizeof(double) + sizeof(int) + sizeof(float) * 4));
+         double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Number of blocks = " << nob);
+            UBLOG(logINFO, "Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for (int level = minInitLevel; level <= maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO, "Number of blocks for level " << level << " = " << nob);
+               UBLOG(logINFO, "Number of nodes for level " << level << " = " << nob*nodb);
+            }
+            UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+            UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+            UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel;
+         rhoLB = 0.0;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         //
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         intHelper.setBC();
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nuLB, rhoLB);
+
+         mu::Parser vx1;
+         vx1.DefineConst("dp", dp[tn]);
+         vx1.DefineConst("L", x[tn]);
+         vx1.DefineConst("nu", nuLB);
+         vx1.DefineConst("r", z[tn] * 0.5); 
+         vx1.DefineConst("c", 0.0);
+         vx1.SetExpr("(2/dp)/(3.0*4.0*L*nu)*(r^2-((c-x2)^2+(c-x3)^2))");
+
+         initVisitor.setVx1(vx1);
+         grid->accept(initVisitor);
+
+
+         //Postrozess
+         {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+               new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+            ppgeo->update(0);
+            ppgeo.reset();
+         }
+
+      if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+
+      double outTime = tout[tn];
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlASCII::getInstance(), conv);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      double endTime = tend[tn];
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(UbSystem::stringTo<int>(argv[1]));
+
+   return 0;
+}
+
diff --git a/source/Applications/PlateWithPorousInlay/CMakeLists.txt b/source/Applications/PlateWithPorousInlay/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..18fd893e8a6b67bf87a6ab81a88a7b149cbcfc73
--- /dev/null
+++ b/source/Applications/PlateWithPorousInlay/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(porplate)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(porplate BINARY)
diff --git a/source/Applications/PlateWithPorousInlay/plate.cpp b/source/Applications/PlateWithPorousInlay/plate.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea5dca784dd82ffa27b3e9c5de0050438c5b87a7
--- /dev/null
+++ b/source/Applications/PlateWithPorousInlay/plate.cpp
@@ -0,0 +1,700 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////
+void inlay(GbVoxelMatrix3DPtr pmMesh, string& pathname, int myid, int i, Grid3DPtr grid)
+{
+   int bbOptionPM = 2; //quadratic bounce back with for thin walls
+   D3Q27BoundaryConditionAdapterPtr noSlipPM(new D3Q27NoSlipBCAdapter(bbOptionPM));
+   D3Q27InteractorPtr inlayInt = D3Q27InteractorPtr(new D3Q27Interactor(pmMesh, grid, noSlipPM, Interactor3D::SOLID));
+
+   GbCuboid3DPtr inlayBox(new GbCuboid3D(pmMesh->getX1Minimum(), pmMesh->getX2Minimum(), pmMesh->getX3Minimum(), pmMesh->getX1Maximum(), pmMesh->getX2Maximum(), pmMesh->getX3Maximum()));
+   if (myid == 0) GbSystem3D::writeGeoObject(inlayBox.get(), pathname + "/geo/inlay" + UbSystem::toString(i), WbWriterVtkXmlASCII::getInstance());
+   D3Q27InteractorPtr inlayBoxInt = D3Q27InteractorPtr(new D3Q27Interactor(inlayBox, grid, noSlipPM, Interactor3D::SOLID));
+   SetSolidOrTransBlockVisitor v1(inlayBoxInt, SetSolidOrTransBlockVisitor::SOLID);
+   grid->accept(v1);
+   SetSolidOrTransBlockVisitor v2(inlayBoxInt, SetSolidOrTransBlockVisitor::TRANS);
+   grid->accept(v2);
+
+   vector<Block3DPtr> inlayBlocks;
+   vector<Block3DPtr>& sb = inlayBoxInt->getSolidBlockSet();
+   if (myid == 0) UBLOG(logINFO, "sb.size = " << sb.size());
+   inlayBlocks.insert(inlayBlocks.end(), sb.begin(), sb.end());
+   vector<Block3DPtr>& tb = inlayBoxInt->getTransBlockSet();
+   if (myid == 0) UBLOG(logINFO, "tb.size = " << tb.size());
+   inlayBlocks.insert(inlayBlocks.end(), tb.begin(), tb.end());
+
+   if (myid == 0) UBLOG(logINFO, "inlayBlocks.size = " << inlayBlocks.size());
+
+   BOOST_FOREACH(Block3DPtr block, inlayBlocks)
+   {
+      block->setActive(true);
+      inlayInt->setDifferencesToGbObject3D(block);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void run(const char *cstr)
+{
+   try
+   {
+      string pathname;
+      string pathGeo;
+      string pathLog;
+      int numOfThreads = 1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr);
+
+      if (machine == "my")
+      {
+         pathname = "d:/temp/porplate";
+         pathGeo = "d:/Data/plate";
+         pathLog = pathname;
+         numOfThreads = 4;
+         logfile = false;
+         availMem = 15.0e9;
+      }
+      else if (machine == "Ludwig")
+      {
+         pathname = "/work/koskuche/SFB880/porplate";
+         pathGeo = "/home/koskuche/data/plate";
+         pathLog = pathname;
+         numOfThreads = 8;
+         availMem = 12.0e9;///8*numOfThreads;
+         logfile = true;
+      }
+      else if (machine == "HLRS")
+      {
+         pathname = "/univ_1/ws1/ws/xrmkuchr-plate3-0";
+         pathGeo = "/zhome/academic/HLRS/xrm/xrmkuchr/data/plate";
+         pathLog = "/zhome/academic/HLRS/xrm/xrmkuchr/work/plate";
+         numOfThreads = 12;
+         availMem = 2.0e9;
+         logfile = true;
+      }
+      else if (machine == "HLRN")
+      {
+         pathname = "/gfs1/work/niikonst/scratch/porplate";
+         pathGeo = "/gfs1/work/niikonst/data/plate";
+         pathLog = pathname;
+         numOfThreads = 24;
+         availMem = 64.0e9;
+         logfile = true;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+#if defined(__unix__)
+      if (myid==0) 
+      {
+         const char* str = pathLog.c_str();
+         int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      }
+#endif 
+
+      if (myid == 0 && logfile)
+      {
+         //UbLog::reportingLevel() = logDEBUG5;
+         logFilename << pathLog + "/logfile" + UbSystem::toString(UbSystem::getTimeStamp()) + "_" + UbSystem::toString(myid) + ".txt";
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      if (myid == 0) UBLOG(logINFO, "Testcase plate");
+
+      string PlatteFilename = pathGeo + "/Platte_bearbeitet2.stl";
+
+      string ZckbndFilename = pathGeo + "/2zackenbaender0.stl";
+
+      ///////////////Knotenabmessungen:
+      int nx[3], blocknx[3];
+      nx[0] = 90;//240;//120;//60;//86;//43;//65;//50;  //länge
+      nx[1] = 2;//2;//6;///1;//5;// //breite
+      nx[2] = 30;//64;//32;//18;//5;//15;//15; //höhe gebiet
+      blocknx[0] = 16;//10;//6;
+      blocknx[1] = 16;//10;//6;
+      blocknx[2] = 16;//10;//6;
+
+      int baseLevel = 0;
+      int refineLevel = 5;
+
+      double H = 600.0; // Kanalhöhe [mm]
+      double cdx = H / (double)(nx[2] * blocknx[2]);
+      double fdx = cdx / double(1 << refineLevel);
+
+      //double h = 200.0; // gewünschte Plattenhöhe in Gitterpunkten
+      //double fdx = plate->getLengthX3()/h;
+      //double cdx = fdx*double(1<<refineLevel);
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      //////////////////////////////////////////////////////////////////////////
+      // physik
+      //////////////////////////////////////////////////////////////////////////
+
+      //////////////////////////////////////////////////////////////////////////
+      // Experiment Parametr
+      // Re = 1000000
+      // V = 16.05  # m / s
+      // p = 994.7  #hPa(manuell abgelesen von MUB)
+      // T = 21.78  #°C
+      // Luftfeuchte = 50.5   # %
+      //////////////////////////////////////////////////////////////////////////
+      // Simulation Parametr
+      //////////////////////////////////////////////////////////////////////////
+      double Re = 1e6; // 1133333.3333333335;
+      double rhoLB = 0.0;
+      double uLB = 0.1;
+      double lReal = 1000; //Plattenlänge in mm
+      double nuLB = (uLB*(lReal / cdx)) / Re;
+
+      int sizeSP = 4;
+      mu::Parser spongeLayer;
+      spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+      spongeLayer.DefineConst("sizeX", nx[0] * blocknx[0]);
+      spongeLayer.DefineConst("sizeSP", sizeSP*blocknx[0]);
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(1000, 1000, 10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+      bool restart;
+
+      if (grid->getTimeStep() == 0)
+      {
+
+         if (myid == 0) UBLOG(logINFO, "Neustart..");
+         restart = false;
+         //////////////////////////////////////////////////////////////////////////
+         //Platte
+         GbTriFaceMesh3DPtr plate(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(PlatteFilename, "Netz"));
+         if (myid == 0) GbSystem3D::writeGeoObject(plate.get(), pathname + "/geo/platte", WbWriterVtkXmlBinary::getInstance());
+         //////////////////////////////////////////////////////////////////////////
+         // Zackenband
+         //////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr meshBand1(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand"));
+         meshBand1->translate(5.0, -2.86, -14.717);
+         meshBand1->rotate(0.0, -0.5, 0.0);
+         if (myid == 0) GbSystem3D::writeGeoObject(meshBand1.get(), pathname + "/geo/Band1", WbWriterVtkXmlASCII::getInstance());
+         // Zackenband2
+         GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand2"));
+         meshBand2->translate(5.0, -7.86, -14.717);
+         meshBand2->rotate(0.0, -0.5, 0.0);
+         if (myid == 0) GbSystem3D::writeGeoObject(meshBand2.get(), pathname + "/geo/Band2", WbWriterVtkXmlASCII::getInstance());
+         // Zackenband3
+         GbTriFaceMesh3DPtr meshBand3(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand3"));
+         meshBand3->translate(5.0, -2.86, -14.417); //+0.3
+         meshBand3->rotate(0.0, -0.5, 0.0);
+         if (myid == 0) GbSystem3D::writeGeoObject(meshBand3.get(), pathname + "/geo/Band3", WbWriterVtkXmlASCII::getInstance());
+         // Zackenband4
+         GbTriFaceMesh3DPtr meshBand4(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand4"));
+         meshBand4->translate(5.0, -7.86, -14.417);
+         meshBand4->rotate(0.0, -0.5, 0.0);
+         if (myid == 0) GbSystem3D::writeGeoObject(meshBand4.get(), pathname + "/geo/Band4", WbWriterVtkXmlASCII::getInstance());
+         //////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////////
+         //porous inlay
+         // string pmFilename1  = pathGeo + "/CT-2014-039.raw";
+         // int pmNX1t=1333;  //abmessung einzelbild in x-richtung
+         // int pmNX2t=463; //abmessung einzelbild in y richtung
+         // int pmNX3t=1333; //anzahl der bilder
+         // float lthresholdt = 27686.97;
+         // float uthresholdt = 65535.0;
+
+         //// string pmFilename1  = pathGeo + "/membran370x357x101.raw";
+         //// int pmNX1t=370;  //abmessung einzelbild in x-richtung
+         //// int pmNX2t=357; //abmessung einzelbild in y richtung
+         //// int pmNX3t=101; //anzahl der bilder
+         //// float lthresholdt = 55.0;
+         //// float uthresholdt = 182.0;
+
+         // GbVoxelMatrix3DPtr pmMesht(new GbVoxelMatrix3D(pmNX1t,pmNX2t,pmNX3t,0,lthresholdt,uthresholdt));
+         // pmMesht->readMatrixFromRawFile<unsigned short>(pmFilename1);
+         // //pmMesht->readMatrixFromRawFile<unsigned char>(pmFilename1);
+         // double deltaX1 = 0.05/pmNX2t;
+         // double deltaX2 = 0.05/pmNX2t;
+         // double deltaX3 = 0.05/pmNX3t;
+         // double scaleFactort = 0.001;
+         // double deltat = 3.75*scaleFactort;
+         // pmMesht->setVoxelMatrixDelta(deltat, deltat, deltat);
+         // pmMesht->rotate90aroundX(); 
+         // pmMesht->rotate90aroundX();
+         // pmMesht->rotate90aroundX();
+         // double inlayXmin = 0;
+         // double inlayYmin = 0;
+         // double inlayZmin = 0;
+         // pmMesht->setVoxelMatrixMininum(inlayXmin, inlayYmin, inlayZmin);
+         // 
+         // if(myid == 0) pmMesht->writeToLegacyVTKBinary(pathname+"/geo/pmMesh");
+
+         // return;
+         ////////////////////////////////////////////////////////////////////////////
+
+         double blockLengthx1 = blocknx[0] * cdx; //geowerte
+         double blockLengthx2 = blockLengthx1;
+         double blockLengthx3 = blockLengthx1;
+
+         double geoLength[] = { nx[0] * blockLengthx1, nx[1] * blockLengthx2, nx[2] * blockLengthx3 };
+
+         double originX1 = plate->getX1Minimum() - plate->getLengthX1() / 4.0;
+         double originX2 = plate->getX2Minimum();
+         double originX3 = plate->getX3Minimum() - 299.5;
+
+
+         bool periodicx1 = false;
+         bool periodicx2 = true;
+         bool periodicx3 = false;
+
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];;
+
+
+         //set grid
+         grid->setDeltaX(cdx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         gridCube->setCenterCoordinates(gridCube->getX1Centroid(), meshBand1->getX2Centroid(), gridCube->getX3Centroid());
+         if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         originX2 = gridCube->getX2Minimum();
+         g_minX2 = originX2;
+         g_maxX2 = originX2 + geoLength[1];
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         //////////////////////////////////////////////////////////////////////////
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            =" << Re);
+            UBLOG(logINFO, "* nuLB          =" << nuLB);
+            UBLOG(logINFO, "* uLB           =" << uLB);
+            UBLOG(logINFO, "* cdx           =" << cdx);
+            UBLOG(logINFO, "* fdx           =" << fdx);
+            double Hzb = 0.6 / fdx;
+            UBLOG(logINFO, "* Height of Zackenband =" << Hzb);
+            UBLOG(logINFO, "* Re on Zackenband =" << (uLB*Hzb) / (nuLB*double(1 << refineLevel)));
+            UBLOG(logINFO, "* nx1/2/3       =" << nx[0] << "/" << nx[1] << "/" << nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  =" << blocknx[0] << "/" << blocknx[1] << "/" << blocknx[2]);
+            UBLOG(logINFO, "* x1Periodic    =" << periodicx1);
+            UBLOG(logINFO, "* x2Periodic    =" << periodicx2);
+            UBLOG(logINFO, "* x3Periodic    =" << periodicx3);
+            UBLOG(logINFO, "* number of levels  =" << refineLevel + 1);
+            UBLOG(logINFO, "* path          =" << pathname);
+
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* number of threads    =" << numOfThreads);
+            UBLOG(logINFO, "* number of processes  =" << comm->getNumberOfProcesses());
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "*****************************************");
+         }
+         //////////////////////////////////////////////////////////////////////////
+
+
+         //////////////////////////////////////////////////////////////////////////
+         //refinement
+         GbCuboid3DPtr refinePlatteBox(new GbCuboid3D(plate->getX1Minimum() - 1.0, plate->getX2Minimum(), plate->getX3Minimum() + (plate->getX3Maximum() - plate->getX3Minimum()) / 2.0,
+            plate->getX1Maximum() + 40.0, plate->getX2Maximum(), plate->getX3Maximum() + 2.0));
+         if (myid == 0) GbSystem3D::writeGeoObject(refinePlatteBox.get(), pathname + "/geo/refinePlatteBox", WbWriterVtkXmlASCII::getInstance());
+
+         //inlay patch
+         GbCuboid3DPtr refineInlayBox(new GbCuboid3D(plate->getX1Maximum() - 85.0, plate->getX2Minimum(), plate->getX3Minimum() + (plate->getX3Maximum() - plate->getX3Minimum()) / 2.0,
+            plate->getX1Maximum() + 1.0, plate->getX2Maximum(), plate->getX3Maximum() + 1.0));
+         if (myid == 0) GbSystem3D::writeGeoObject(refineInlayBox.get(), pathname + "/geo/refineInlayBox", WbWriterVtkXmlASCII::getInstance());
+
+         if (refineLevel > 0)
+         {
+            if (myid == 0) UBLOG(logINFO, "Refinement - start");
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refinePlatteBox, refineLevel - 1);
+            refineHelper.addGbObject(refineInlayBox, refineLevel);
+
+            refineHelper.refine();
+            if (myid == 0) UBLOG(logINFO, "Refinement - end");
+         }
+
+         //if(myid == 0)
+         //{
+         //   UBLOG(logINFO,"Write blocks - start");
+         //   BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+         //   ppblocks->update(0);
+         //   UBLOG(logINFO,"Write blocks - end");
+         //}
+
+         //return;
+
+
+         {
+
+            ////walls
+            GbCuboid3DPtr addWallZmin(new GbCuboid3D(g_minX1 - blockLengthx1, g_minX2 - blockLengthx1, g_minX3 - blockLengthx1, g_maxX1 + blockLengthx1, g_maxX2 + blockLengthx1, g_minX3));
+            if (myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname + "/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+            GbCuboid3DPtr addWallZmax(new GbCuboid3D(g_minX1 - blockLengthx1, g_minX2 - blockLengthx1, g_maxX3, g_maxX1 + blockLengthx1, g_maxX2 + blockLengthx1, g_maxX3 + blockLengthx1));
+            if (myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname + "/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+            //walls
+            int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+            D3Q27BoundaryConditionAdapterPtr slip(new D3Q27SlipBCAdapter(bbOption));
+            D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, slip, Interactor3D::SOLID));
+            D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, slip, Interactor3D::SOLID));
+
+            /////////////////////////////////////////////////
+            ///interactoren
+            int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+            D3Q27BoundaryConditionAdapterPtr noSlip(new D3Q27NoSlipBCAdapter(bbOption1));
+            D3Q27TriFaceMeshInteractorPtr triPlateInteractor(new D3Q27TriFaceMeshInteractor(plate, grid, noSlip, Interactor3D::SOLID, Interactor3D::POINTS));
+            D3Q27TriFaceMeshInteractorPtr triBand1Interactor(new D3Q27TriFaceMeshInteractor(meshBand1, grid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand2Interactor(new D3Q27TriFaceMeshInteractor(meshBand2, grid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand3Interactor(new D3Q27TriFaceMeshInteractor(meshBand3, grid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand4Interactor(new D3Q27TriFaceMeshInteractor(meshBand4, grid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+
+            //inflow
+            GbCuboid3DPtr velBCCuboid(new GbCuboid3D(originX1 - blockLengthx1, originX2 - blockLengthx1, originX3 - blockLengthx1,
+               originX1, originX2 + geoLength[1] + blockLengthx1, originX3 + geoLength[2] + blockLengthx1));
+            if (myid == 0) GbSystem3D::writeGeoObject(velBCCuboid.get(), pathname + "/geo/velBCCuboid", WbWriterVtkXmlASCII::getInstance());
+            D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(velBCCuboid, grid, Interactor3D::SOLID));
+
+            //inflow
+            double raiseVelSteps = 0;
+            vector<D3Q27BCFunction> velcX1BCs, dummy;
+
+            mu::Parser inflowProfile;
+            inflowProfile.SetExpr("uLB");
+            inflowProfile.DefineConst("uLB", uLB);
+            velcX1BCs.push_back(D3Q27BCFunction(inflowProfile, raiseVelSteps, D3Q27BCFunction::INFCONST));
+
+            D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter(velcX1BCs, dummy, dummy));
+            velBCInteractor->addBCAdapter(velBCAdapter);
+
+            //outflow
+            GbCuboid3DPtr densCuboid(new GbCuboid3D(originX1 + geoLength[0], originX2 - blockLengthx1, originX3 - blockLengthx1,
+               originX1 + geoLength[0] + blockLengthx1, originX2 + geoLength[1] + blockLengthx1, originX3 + geoLength[2] + blockLengthx1));
+            if (myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname + "/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+            D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+            D3Q27InteractorPtr densInteractor(new D3Q27Interactor(densCuboid, grid, denBCAdapter, Interactor3D::SOLID));
+
+            ////////////////////////////////////////////
+            //METIS
+            Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+
+            ////////////////////////////////////////////
+            /////delete solid blocks
+            if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - start");
+            InteractorsHelper intHelper(grid, metisVisitor);
+            intHelper.addInteractor(triPlateInteractor);
+            intHelper.addInteractor(triBand1Interactor);
+            intHelper.addInteractor(triBand2Interactor);
+            intHelper.addInteractor(triBand3Interactor);
+            intHelper.addInteractor(triBand4Interactor);
+            intHelper.addInteractor(addWallZminInt);
+            intHelper.addInteractor(addWallZmaxInt);
+            intHelper.addInteractor(densInteractor);
+            intHelper.addInteractor(velBCInteractor);
+            intHelper.selectBlocks();
+            if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - end");
+            //////////////////////////////////////
+
+            //domain decomposition for threads
+            if (numOfThreads > 1)
+            {
+               PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+               grid->accept(pqPartVisitor);
+            }
+
+            if (myid == 0)
+            {
+               UBLOG(logINFO, "Write blocks - start");
+               BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+               ppblocks->update(0);
+               UBLOG(logINFO, "Write blocks - end");
+            }
+
+            unsigned long nob = grid->getNumberOfBlocks();
+            unsigned long nod = nob * blocknx[0] * blocknx[1] * blocknx[2];
+            unsigned long nod_real = nob * (blocknx[0] + 3)*(blocknx[1] + 3)*(blocknx[2] + 3);
+            unsigned long nodb = (blocknx[0]) * (blocknx[1]) * (blocknx[2]);
+
+            double needMemAll = double(nod_real*(27 * sizeof(double) + sizeof(int)));
+            double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+            double nup = 0;
+
+            if (myid == 0)
+            {
+               UBLOG(logINFO, "Number of blocks = " << nob);
+               UBLOG(logINFO, "Number of nodes  = " << nod);
+               int minInitLevel = grid->getCoarsestInitializedLevel();
+               int maxInitLevel = grid->getFinestInitializedLevel();
+               for (int level = minInitLevel; level <= maxInitLevel; level++)
+               {
+                  int nobl = grid->getNumberOfBlocks(level);
+                  UBLOG(logINFO, "Number of blocks for level " << level << " = " << nobl);
+                  UBLOG(logINFO, "Number of nodes for level " << level << " = " << nobl*nodb);
+                  nup += nobl*nodb*double(1 << level);
+               }
+               UBLOG(logINFO, "Hypothetically time for calculation step for 120 nodes  = " << nup / 6.0e5 / (120 * 8) << " s");
+               UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+               UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+               UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+               UBLOG(logINFO, "Available memory per node/8.0 = " << (availMem / 8.0) << " bytes");
+            }
+
+            //////////////////////////////////////////
+            //set connectors
+            if (myid == 0) UBLOG(logINFO, "set connectors - start");
+            D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+            D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+            grid->accept(setConnsVisitor);
+            if (myid == 0) UBLOG(logINFO, "set connectors - end");
+
+            ////////////////////////////
+            LBMKernel3DPtr kernel;
+            //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+            //with sponge layer
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+            kernel->setWithSpongeLayer(true);
+            kernel->setSpongeLayer(spongeLayer);
+
+            //BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+            BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+            kernel->setBCProcessor(bcProc);
+            SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+            grid->accept(kernelVisitor);
+            //////////////////////////////////
+            //undef nodes
+            if (refineLevel > 0)
+            {
+               D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+               grid->accept(undefNodesVisitor);
+            }
+
+
+            intHelper.setBC();
+
+         }
+         //////////////////////////////////////////////////////////////////////////
+         //porous inlay
+         {
+            string pmFilename = pathGeo + "/CT-2014-039.raw";
+            int pmNX1 = 1333;  //abmessung einzelbild in x-richtung
+            int pmNX2 = 463; //abmessung einzelbild in y richtung
+            int pmNX3 = 1333; //anzahl der bilder
+            float lthreshold = 27686.97;
+            float uthreshold = 65535.0;
+
+            GbVoxelMatrix3DPtr pmMesh(new GbVoxelMatrix3D(pmNX1, pmNX2, pmNX3, 0, lthreshold, uthreshold));
+            pmMesh->readMatrixFromRawFile<unsigned short>(pmFilename, GbVoxelMatrix3D::LittleEndian);
+
+            double scaleFactor = 0.001;
+            double delta = 3.75*scaleFactor;
+            pmMesh->setVoxelMatrixDelta(delta, delta, delta);
+            pmMesh->rotate90aroundX();
+            pmMesh->rotate90aroundX();
+            pmMesh->rotate90aroundX();
+
+            double inlayXmin = plate->getX1Maximum() - 5.0;//995.0;
+            double inlayYmin = gridCube->getX2Minimum();//180.0;
+            double inlayZmin = 8.84 + fdx;//8.73;
+
+            //pmMesh->setVoxelMatrixMininum(inlayXmin, inlayYmin, inlayZmin);
+            //if(myid == 0) pmMesh->writeToLegacyVTKBinary(pathname+"/geo/pmMesh");
+
+            int i = 0;
+            for (int y = 0; y <= 35; y += 10)
+               for (int x = 0; x <= 75; x += 10)
+               {
+                  if (myid == 0) UBLOG(logINFO, "inlay # " << i);
+                  pmMesh->setVoxelMatrixMininum(inlayXmin - (double)x, inlayYmin + (double)y, inlayZmin);
+                  inlay(pmMesh, pathname, myid, i, grid);
+                  i++;
+
+                  if (myid == 0) UBLOG(logINFO, "inlay # " << i);
+                  pmMesh->setVoxelMatrixMininum(inlayXmin - (double)(x + 5), inlayYmin + (double)y, inlayZmin);
+                  pmMesh->mirrorX();
+                  inlay(pmMesh, pathname, myid, i, grid);
+                  i++;
+
+                  if (myid == 0) UBLOG(logINFO, "inlay # " << i);
+                  pmMesh->setVoxelMatrixMininum(inlayXmin - (double)(x + 5), inlayYmin + (double)(y + 5), inlayZmin);
+                  pmMesh->mirrorY();
+                  inlay(pmMesh, pathname, myid, i, grid);
+                  i++;
+
+                  if (myid == 0) UBLOG(logINFO, "inlay # " << i);
+                  pmMesh->setVoxelMatrixMininum(inlayXmin - (double)x, inlayYmin + (double)(y + 5), inlayZmin);
+                  pmMesh->mirrorX();
+                  inlay(pmMesh, pathname, myid, i, grid);
+                  pmMesh->mirrorY();
+                  i++;
+               }
+
+            if (myid == 0)
+            {
+               UBLOG(logINFO, "mit VoxelMatrix");
+               UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+               UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+               UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+            }
+         }
+         //////////////////////////////////////////////////////////////////////////
+
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nuLB, rhoLB);
+         initVisitor.setVx1(uLB);
+         grid->accept(initVisitor);
+
+         //Postprozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(),
+            unitConverter, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+      }
+      else
+      {
+         restart = true;
+
+         ////////////////////////////////////////////////////////////////////////////
+         //change viscosity
+         Re = 1e6;
+         nuLB = ((uLB*(lReal/cdx))/Re)*1.043;
+         if (myid == 0) UBLOG(logINFO, "nuLB =" << nuLB);
+
+         int gridRank = grid->getRank();
+         int minInitLevel = grid->getCoarsestInitializedLevel();
+         int maxInitLevel = grid->getFinestInitializedLevel();
+
+         std::vector<std::vector<Block3DPtr> > blockVector;
+         blockVector.resize(maxInitLevel + 1);
+
+         for (int level = minInitLevel; level <= maxInitLevel; level++)
+         {
+            grid->getBlocks(level, gridRank, true, blockVector[level]);
+
+            BOOST_FOREACH(Block3DPtr block, blockVector[level])
+            {
+               LBMReal collFactor = LBMSystem::calcCollisionFactor(nuLB, block->getLevel());
+               block->getKernel()->setCollisionFactor(collFactor);
+            }
+         }
+         ////////////////////////////////////////////////////////////////////////////
+
+         //domain decomposition for threads
+         if (numOfThreads > 1)
+         {
+            PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+            grid->accept(pqPartVisitor);
+         }
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept(setConnsVisitor);
+         SetSpongeLayerBlockVisitor ssp(spongeLayer);
+         grid->accept(ssp);
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+      }
+      UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(1,0,10);
+      visSch->addSchedule(100, 100, 1000);
+      //visSch->addSchedule(1000,1000,5000);
+      //visSch->addSchedule(5000,5000,100000);
+      //visSch->addSchedule(100000,100000,10000000);
+
+      visSch->addSchedule(1000, 1000, 10000000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      double startStep = 33000;
+
+      UbSchedulerPtr resSchRMS(new UbScheduler());
+      resSchRMS->addSchedule(1000000, startStep, 10000000);
+      UbSchedulerPtr resSchMeans(new UbScheduler());
+      resSchMeans->addSchedule(1000000, startStep, 10000000);
+      UbSchedulerPtr stepAvSch(new UbScheduler());
+      int averageInterval = 100;
+
+      stepAvSch->addSchedule(averageInterval, 0, 10000000);
+      AverageValuesPostprocessor Avpp(grid, pathname, WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/,
+         stepAvSch/*wann wird gemittelt*/, resSchMeans, resSchRMS/*wann wird resettet*/, restart);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      nupsSch->addSchedule(500, 500, 1e6);
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      UbSchedulerPtr emSch(new UbScheduler(10));
+      EmergencyExitPostprocessor empr(grid, emSch, pathname, RestartPostprocessorPtr(&rp), comm);
+
+      if (myid == 0)
+      {
+         UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      double endTime = 100000001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if (myid == 0) UBLOG(logINFO, "Simulation-start");
+      calculation->calculate();
+      if (myid == 0) UBLOG(logINFO, "Simulation-end");
+   }
+   catch (std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch (std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch (...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   if (argc == 1)
+   {
+      cout << "Command line argument isn't specified!" << endl;
+      cout << "plate2 <machine name>" << endl;
+      return 1;
+   }
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/Wing/Bombadil.cfg b/source/Applications/Wing/Bombadil.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..4ee9dd64929b43391ede80ab568d53339b24be63
--- /dev/null
+++ b/source/Applications/Wing/Bombadil.cfg
@@ -0,0 +1,8 @@
+machine=Bombadil
+path="d:/temp/wing/"
+geoFile="d:/Data/SFB/grundgeometrie.stl"
+numOfThreads=1
+availMem=15e9
+refineLevel=5
+blocknx=8
+endTime=10
\ No newline at end of file
diff --git a/source/Applications/Wing/CMakeLists.txt b/source/Applications/Wing/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a507c94a98eede5c4bbc67e71159038f53d5bb80
--- /dev/null
+++ b/source/Applications/Wing/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(wing)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(wing BINARY)
diff --git a/source/Applications/Wing/wing.cpp b/source/Applications/Wing/wing.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78f4763e39d2bdd3fbea3d4e85fad4b30e01f03e
--- /dev/null
+++ b/source/Applications/Wing/wing.cpp
@@ -0,0 +1,414 @@
+#include <iostream>
+#include <string>
+
+#include <boost/pointer_cast.hpp>
+
+#include "vfluids.h"
+
+using namespace std;
+
+
+void setup(const char *cstr1, const char *cstr2)
+{
+   try
+   {
+      //Sleep(30000);
+
+      ConfigFileReader cf(cstr1);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      //parameters from config file
+      string machine = cf.getValue("machine");
+      string pathname = cf.getValue("path");
+      string geoFile = cf.getValue("geoFile");
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+      double availMem = UbSystem::stringTo<double>(cf.getValue("availMem"));
+      int refineLevel = UbSystem::stringTo<int>(cf.getValue("refineLevel"));
+      int blocknx = UbSystem::stringTo<int>(cf.getValue("blocknx"));
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "Bombadil") int dumy=0; 
+      else if(machine == "Ludwig" || machine == "HLRN")      
+      {
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown machine");
+
+      GbTriFaceMesh3DPtr geo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+      if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo", WbWriterVtkXmlASCII::getInstance());
+
+      double dx = (fabs(geo->getX3Maximum()-geo->getX3Minimum())*10e-3)*(double)(1<<refineLevel);
+      dx /= 4.0;
+
+      double blockLength = blocknx*dx;
+
+      double offsetX1 = fabs(geo->getX1Maximum()-geo->getX1Minimum());
+      double h = fabs(geo->getX3Maximum()-geo->getX3Minimum());
+      double offsetX2 = fabs(geo->getX2Maximum()-geo->getX2Minimum())/3.0;
+      double offsetX3 = 3.0*h; //30.0*h;
+
+      double g_minX1 = geo->getX1Minimum()-offsetX1;
+      double g_minX2 = geo->getX2Minimum()+offsetX2;
+      double g_minX3 = geo->getX3Centroid()-offsetX3;
+
+      double g_maxX1 = geo->getX1Maximum()+5.0*offsetX1;
+      double g_maxX2 = g_minX2 + 4.0*blockLength; 
+      double g_maxX3 = geo->getX3Centroid()+offsetX3;
+
+      //##########################################################################
+      //## physical parameters
+      //##########################################################################
+      double Re            = 1e6;
+
+      double rhoLB    = 0.0;
+      double rhoReal  = 1.0;
+      double nueReal  = 0.000015;//0.015;
+
+      double lReal    =  3.0;//<-m     ;//Profile laenge in cm(! cm nicht m !)
+      double uReal    = Re*nueReal/lReal;
+
+      //##Machzahl:
+      //#Ma     = uReal/csReal
+      double Ma      = 0.1;//Ma-Real!
+      double csReal  = uReal/Ma;
+      double hLB     = lReal/dx;
+
+      LBMUnitConverter unitConverter(lReal, csReal, rhoReal, hLB);
+
+      double uLB     = uReal   * unitConverter.getFactorVelocityWToLb();
+      double nueLB   = nueReal * unitConverter.getFactorViscosityWToLb();
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+
+      ////////////////////////////////////////////////////////////////////////
+      //Grid
+      //////////////////////////////////////////////////////////////////////////
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx, blocknx, blocknx);
+      
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      //gridCube->setCenterCoordinates(geo->getX1Centroid(), geo->getX2Centroid(), geo->getX3Centroid());
+      if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(),pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+      GenBlocksGridVisitor genBlocks(gridCube);
+      grid->accept(genBlocks);
+
+      grid->setPeriodicX2(true);
+      grid->setPeriodicX3(true);
+
+      double outTime = 1.0;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      //PostprocessorPtr pp(new D3Q27MacroscopicQuantitiesPostprocessor(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlASCII::getInstance(), conv, comm));
+
+      UbSchedulerPtr rSch(new UbScheduler());
+      rSch->addSchedule(50,50,50);
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::TXT));
+      
+
+      std::string opt;
+
+      if(cstr2!= NULL)
+         opt = std::string(cstr2);
+
+      if/*(cstr== NULL)*/(cstr2!= NULL)
+      {
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         rp->reconnect(grid);
+
+         SetForcingBlockVisitor forcingVisitor(0.0, 0.0, 0.0);
+         grid->accept(forcingVisitor);
+
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+      }
+      else
+{
+      //rp->addPostprocessor(pp);
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"Parameters:");
+         UBLOG(logINFO, "* Re            ="<<Re);
+         UBLOG(logINFO, "* Ma            ="<<Ma);
+         UBLOG(logINFO, "* uReal         ="<<uReal);
+         UBLOG(logINFO, "* nueReal       ="<<nueReal);
+         UBLOG(logINFO, "* nue           ="<<nueLB);
+         UBLOG(logINFO, "* velocity      ="<<uLB);
+         //UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+         //UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+         //UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+         UBLOG(logINFO, "* dx_base       ="<<dx);
+         UBLOG(logINFO, "* dx_refine     ="<<dx/(double)(1<<refineLevel));
+         //UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+         UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx<<"/"<<blocknx<<"/"<<blocknx);
+         //UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+         //UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+         UBLOG(logINFO, "*****************************************");
+         UBLOGML(logINFO, "UnitConverter:"<<unitConverter.toString());
+         UBLOG(logINFO, "*****************************************");    
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"numOfThreads     = " << numOfThreads );
+         UBLOG(logINFO,"Preprozess - start");
+      }
+
+
+      //inflow
+      GbCuboid3DPtr geoInflow (new GbCuboid3D(g_minX1-4.0*blockLength, g_minX2-4.0*blockLength, g_minX3-4.0*blockLength, g_minX1+2.0*dx, g_maxX2+4.0*blockLength, g_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      //outflow
+      GbCuboid3DPtr geoOutflow (new GbCuboid3D(g_maxX1-2.0*dx, g_minX2-4.0*blockLength, g_minX3-4.0*blockLength, g_maxX1+4.0*blockLength, g_maxX2+4.0*blockLength, g_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+      double scaleFactorX = 1.2;
+      double scaleFactorZ = 1.2;
+      //geo->scale(scaleFactorX, 1.0, scaleFactorZ);
+      if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo2", WbWriterVtkXmlASCII::getInstance());
+
+      int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr noSlipBCAdapter(new D3Q27NoSlipBCAdapter(bbOption));
+
+      Interactor3DPtr geoIntr = D3Q27TriFaceMeshInteractorPtr(new D3Q27TriFaceMeshInteractor(geo, grid, noSlipBCAdapter,Interactor3D::SOLID));
+
+      //boost::dynamic_pointer_cast<D3Q27TriFaceMeshInteractor>(geoIntr)->refineBlockGridToLevel(refineLevel, 0.0, 5.0);
+
+      if (refineLevel > 0)
+      {
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+         //RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+         //refineHelper.addGbObject(geo, refineLevel);
+         //refineHelper.refine();
+         RefineAroundGbObjectHelper refineHelper(grid, refineLevel, boost::dynamic_pointer_cast<D3Q27TriFaceMeshInteractor>(geoIntr), 0.0, 0.5);
+         refineHelper.refine();
+         if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      }
+
+      ppblocks->update(0);
+      ppblocks.reset();
+      return;
+
+      //geo->scale(1.0/scaleFactorX, 1.0, 1.0/scaleFactorX);
+      //geo = GbTriFaceMesh3DPtr(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+      if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo3", WbWriterVtkXmlASCII::getInstance());
+
+      MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+      grid->accept( metisVisitor );
+
+      SolidBlocksHelper sd(grid, comm);
+
+      mu::Parser fct;
+      fct.SetExpr("U");
+      fct.DefineConst("U", uLB);
+
+      //inflow
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+      velBCAdapter->setSecondaryBcOption(2);
+      D3Q27InteractorPtr inflowIntr  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+      //outflow
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+      denBCAdapter->setSecondaryBcOption(0);
+      D3Q27InteractorPtr outflowIntr = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+
+      sd.addInteractor(inflowIntr);
+      sd.addInteractor(outflowIntr);
+      sd.addInteractor(geoIntr);
+
+      sd.deleteSolidBlocks();
+
+      grid->accept( metisVisitor );
+
+      sd.setTransBlocks();
+
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition for threads
+      //PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      //grid->accept(pqPartVisitor);
+
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nodb = (blocknx) * (blocknx) * (blocknx);
+      unsigned long nod = nob * (blocknx) * (blocknx) * (blocknx);
+      unsigned long nodg = nob * (blocknx+gl) * (blocknx+gl) * (blocknx+gl);
+      double needMemAll  = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         int minInitLevel = grid->getCoarsestInitializedLevel();
+         int maxInitLevel = grid->getFinestInitializedLevel();
+         for(int level = minInitLevel; level<=maxInitLevel; level++)
+         {
+            int nobl = grid->getNumberOfBlocks(level);
+            UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nobl);
+            UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nobl*nodb);
+         }
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      LBMKernel3DPtr kernel;
+      kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx, blocknx, blocknx, LBMKernelETD3Q27CCLB::NORMAL));
+
+      //mu::Parser fctForcingX1;
+      //fctForcingX1.SetExpr("Fx1");
+      //fctForcingX1.DefineConst("Fx1", 9.99685e-7);
+
+      //kernel->setForcingX1(fctForcingX1);
+      //kernel->setWithForcing(true);
+      //
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      if (refineLevel > 0)
+      {
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+	  //UbSchedulerPtr geoSch(new UbScheduler(1));
+	  //D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+		 // new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+	  //ppgeo->update(0);
+	  //ppgeo.reset();
+
+	  //return;
+
+      //inflow
+      grid->addAndInitInteractor(inflowIntr);
+
+      //outflow
+      grid->addAndInitInteractor(outflowIntr);
+
+      //geo
+      grid->addAndInitInteractor(geoIntr);
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+      initVisitor.setVx1(fct);
+      initVisitor.setNu(nueLB);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      //UbSchedulerPtr geoSch(new UbScheduler(1));
+      //D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+      //   new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+      //ppgeo->update(0);
+      //ppgeo.reset();
+
+      {
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         //D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, true));
+         //grid->addObserver(ppgeo);
+         grid->doPostProcess(0);
+         //grid->notifyObservers(0);
+         //grid->removeObserver(ppgeo);
+      }
+
+      //grid->notifyObservers(0);
+
+      //UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr pp(new D3Q27MacroscopicQuantitiesPostprocessor(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlASCII::getInstance(), conv));
+      rp->addPostprocessor(pp);
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+}
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+     // double outTime = 3.0;
+     // UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      //UbSchedulerPtr stepSch(new UbScheduler());
+      //stepSch->addSchedule(10, 100, 1000);
+      //nodeSch->addSchedule(1000, 1000, 10000);
+      //nodeSch->addSchedule(10000, 10000, 50000);
+      //stepSch->addSchedule(100, 100, 1000);
+
+      //UbSchedulerPtr st(new UbScheduler(100,50,1000));
+      //UbSchedulerPtr rs(new UbScheduler(3));
+      //AverageValuesPostprocessor ap(grid, pathname + "/av/av", WbWriterVtkXmlASCII::getInstance(), stepSch, rs, comm);
+
+      //D3Q27ShearStressPostprocessor shs(grid,pathname + "/shs/shs", WbWriterVtkXmlASCII::getInstance(), stepSch, rs, comm);
+      //shs.addInteractor(boost::dynamic_pointer_cast<D3Q27Interactor>(addWallZminInt));
+
+      //D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlASCII::getInstance(), conv, comm);
+
+      UbSchedulerPtr visSch(new UbScheduler(1));
+      //UbSchedulerPtr visSch(stepSch);
+      double endTime = UbSystem::stringTo<int>(cf.getValue("endTime"));//10001.0;
+
+      //cout << "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem()<<endl;
+      //cout << "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed()<<endl;
+      //cout << "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe()<<endl;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+int main(int argc, char* argv[])
+{
+
+   if ( argv != NULL )
+   {
+      if (argc > 1)
+      {
+         setup(argv[1], argv[2]);
+      }
+      else
+      {
+         cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+      }
+   }
+
+   return 0;
+} 
+
diff --git a/source/Applications/bKanal/CMakeLists.txt b/source/Applications/bKanal/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..305be694406be5f61a51600d71203df5270359f5
--- /dev/null
+++ b/source/Applications/bKanal/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bKanal)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bKanal BINARY)
diff --git a/source/Applications/bKanal/HLRNb/bKanal.cpp b/source/Applications/bKanal/HLRNb/bKanal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d7028dba969d01b409a3fc84b4fc3b83556da69a
--- /dev/null
+++ b/source/Applications/bKanal/HLRNb/bKanal.cpp
@@ -0,0 +1,683 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <sys/types.h> //mkdir rights
+#include <sys/stat.h> //mkdir
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      UBLOG(logINFO,"Testcase BreugemChannel");
+      string pathname; 
+      string pathnameRestart;
+      string pathGeo;
+      int numOfThreads =1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      UbLog::reportingLevel() = logINFO;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+
+         pathname =        "/gfs1/work/niivfcpu/scratch/kucher/BKanaltest";
+         pathnameRestart = "/gfs1/work/niivfcpu/scratch/kucher/BKanaltest";//BKanaltest0Ref2up0612";//BKanaltest0Ref2up1012Out";
+         //pathname =        "/work/koskuche/SFB880/BKanaltestRe260000Out";
+         //pathnameRestart = "/work/koskuche/SFB880/BKanaltestRe260000";//BKanaltest0Ref2up0612";//BKanaltest0Ref2up1012Out";
+
+   	 pathGeo = "/home/koskuche/data/plate";
+         numOfThreads = 1;
+         availMem = 64.0e9;
+         logfile = true;
+
+         if (myid==0) 
+         {
+            const char* str = pathname.c_str();
+#if defined(__unix__)
+            int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+#endif 
+
+         }
+
+         if(myid ==0)
+         {
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         }
+
+
+
+
+      //if(myid ==0 && logfile)
+      //{
+      UbLog::output_policy::setStream(logFilename.str());
+      //}
+
+      int baseLevel, refineLevel,nx[3],blocknx[3];
+      double Re,velocity,rhoInit,vx1Init;//,vx2Init,vx3Init;
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      Re            = 5500;// 13286;//13286;//gemessen 18.98 m/s...*5.0 zum  testen ob was passiert
+      velocity      = 0.01;  
+      vx1Init       = 0.01;  
+      rhoInit       = 0.0;
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+
+      int H=200;//200;//392;
+
+      //  nx[0]      =8;//ok mit 8// (int)(3.0*(double)H/8.0/8.0);//2;// (int)(0.3*(double)H/6.0/4.0);//das "/4" hier ist wegen der verfeinerung da! //länge
+      //  nx[1]      =8;//ok mit 8// (int)(2.0*(double)H/8.0/8.0);//2;// (int)(0.2*(double)H/6.0/4.0);//  //breite
+      nx[2]      = (int)(2.0*(double)H/5.0/8.0);// //höhe gebiet
+
+      //(3/2/2)-ratio:
+      nx[1]=nx[2];
+      nx[0]=15;
+
+      blocknx[0] = 15;//10;//5;
+      blocknx[1] = 15;//10;//5;
+      blocknx[2] = 15;//10;//5;
+
+      baseLevel   = 0;
+      refineLevel = 2;//1;////3;//3 soll 1 test;
+
+
+      ///////////////Weltabmessungen:
+      //double kanallaengeSI = ( 2.0*(double)H);
+      // double kanalbreiteSI = ( 1.0*(double)H);
+      double kanalhoeheSI  = ( 2.0*(double)H);
+
+      // double refinewidth1=kanalhoeheSI/10.0;
+
+      double fineNodeDx   = (kanalhoeheSI) / (double)( blocknx[2]*nx[2]*(1<<refineLevel)+1 ); //+1--> gitter liegt jeweils 0.5dx innerhalb
+      double coarseNodeDx = fineNodeDx * (double)(1<<refineLevel);//geowerte
+
+      double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+      double blockLengthx2 = blockLengthx1;
+      double blockLengthx3 = blockLengthx1;
+
+      double originX1 = 0.0;//-50.0*propellerDurchmesser;  //geowerte
+      double originX2 = 0.0;//-0.5*blockLengthx2*nx2;
+      double originX3 = 0.0;// minX3 + 0.5*fineNodeDx;
+
+      double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      bool periodicx1 = true;
+      bool periodicx2 = true;
+      bool periodicx3 = false;
+
+
+      //##########################################################################
+      //## physical parameters
+      //##########################################################################
+      double smagorinskiConstant = 0.18;
+
+
+      double rhoLB         = 0.0;
+
+      double rhoReal       = 1.0;
+      double nueReal  = 1;//0.000016;//0.015;
+
+      double hReal         = blocknx[2]*nx[2];//H*0.9;//0.0105;//<-m     1.05;//Plattendicke in cm(! cm nicht m !)
+      double uReal         = Re*nueReal/hReal;
+
+      //##Machzahl:
+      //#Ma     = uReal/csReal
+      double csReal=343.0;
+      double Ma      = uReal/csReal;//Ma-Real!
+      //double csReal  = uReal/Ma;
+      double hLB     = hReal/coarseNodeDx;
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(hReal, csReal, rhoReal, hLB));
+
+      double uLB           = uReal   * unitConverter->getFactorVelocityWToLb();
+      double nueLB         = nueReal * unitConverter->getFactorViscosityWToLb();
+      double timestep      = unitConverter->getFactorTimeLbToW(coarseNodeDx);
+
+      velocity = uLB;
+      // double viscosity =nueLB*1000.0;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      //UbSchedulerPtr rSch(new UbScheduler(10000,100000,30000000000));//(50000,50000,1000000));
+      UbSchedulerPtr rSch(new UbScheduler(18000,268250,770000));//(50000,50000,1000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathnameRestart+"/checkpoints", RestartPostprocessor::BINARY);
+
+      //////////////////////////////////////////////////////////////////////////
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if(/*(cstr== NULL)*/cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) {
+            UBLOG(logINFO,"Restart step: " << opt);
+            UBLOG(logINFO, "Restart=:" << pathnameRestart);
+         }
+
+         grid = rp.restart(UbSystem::stringTo<int>(opt));
+         rp.reconnect(grid);
+
+//          mu::Parser fctForcingX1, fctForcingX2, fctForcingX3;
+//          fctForcingX1.SetExpr("Fx1*dx");
+//          fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);
+// 
+//          SetForcingBlockVisitor forcingVisitor(fctForcingX1, fctForcingX2, fctForcingX3);
+//          grid->accept(forcingVisitor);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+      }
+      else
+      {
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];
+
+         //set grid
+         grid->setDeltaX(coarseNodeDx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+
+
+         //bottom and top solid bc
+         //iteractors
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         double geoOverlap = coarseNodeDx;
+         GbCuboid3DPtr bottomBCCuboid(new GbCuboid3D(originX1-geoOverlap, originX2-geoOverlap, originX3-geoOverlap, 
+            originX1+geoLength[0]+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(bottomBCCuboid.get(), pathname+"/geo/bottomBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr bottomBCInteractor(new D3Q27Interactor(bottomBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+
+         GbCuboid3DPtr topBCCuboid(new GbCuboid3D(originX1-geoLength[0]-coarseNodeDx, originX2-geoOverlap, originX3+geoLength[2],//-coarseNodeDx*0.5, 
+            originX1+geoLength[0]+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap));
+         if(myid == 0) GbSystem3D::writeGeoObject(topBCCuboid.get(), pathname+"/geo/topBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr topBCInteractor(new D3Q27Interactor(topBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+         //grid->addAndInitInteractor( bottomBCInteractor ); 
+         // grid->addAndInitInteractor( topBCInteractor ); 
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            ="<<Re);
+            UBLOG(logINFO, "* Ma            ="<<Ma);
+            UBLOG(logINFO, "* uReal         ="<<uReal);
+            UBLOG(logINFO, "* nueReal       ="<<nueReal);
+            UBLOG(logINFO, "* nue           ="<<nueLB);
+            UBLOG(logINFO, "* velocity      ="<<uLB);
+            // UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+            //  UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+            UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+            UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+            UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+            UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+            UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+            UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "*****************************************");
+            UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+            UBLOG(logINFO, "*****************************************");     
+         }
+
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+
+         //////////////////////////////////////////////////////////////////////////
+         // refine
+         //////////////////////////////////////////////////////////////////////////
+         //GbCuboid3DPtr wallsX1X2maxRef1( new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI*0.95
+         //    , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax1(wallsX1X2maxRef1, 0,refineLevel-3);
+         //grid->accept(refineVisitormax1);
+         //
+         //GbCuboid3DPtr wallsX1X2minRef1(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI*0.55
+         //    , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.47));
+         // RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin1(wallsX1X2minRef1, 0,refineLevel-3);
+         // grid->accept(refineVisitormin1);
+
+         //   GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.98));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax2(wallsX1X2maxRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormax2);
+         //   GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.9));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax2(wallsX1X2maxRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormax2);
+
+         // GbCuboid3DPtr wallsX1X2maxRef3(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.9995));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax3(wallsX1X2maxRef3, 0,refineLevel-1);
+         //grid->accept(refineVisitormax3);
+
+         //         GbCuboid3DPtr wallsX1X2minRefl3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.25));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitorminl3(wallsX1X2minRefl3, 0,refineLevel-3);
+         //grid->accept(refineVisitorminl3);
+         /////würfel unten version
+         //      GbCuboid3DPtr wallsX1X2minRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.2));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin2(wallsX1X2minRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormin2);
+
+         //   GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , kanalhoeheSI*0.04
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.18));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin3(wallsX1X2minRef3, 0,refineLevel-1);
+         //grid->accept(refineVisitormin3);
+
+         //      GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , kanalhoeheSI*0.09
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.16));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel);
+         //grid->accept(refineVisitormin4);
+
+
+
+
+         /////würfel anfang version
+         //       GbCuboid3DPtr wallsX1X2minRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.56));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin2(wallsX1X2minRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormin2);
+
+         //   GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.55));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin3(wallsX1X2minRef3, 0,refineLevel-2);
+         //grid->accept(refineVisitormin3);
+
+         //      GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.49
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.53));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel-1);
+         //grid->accept(refineVisitormin4);
+
+
+         /*           GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX1-3.0*geoOverlap
+         , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.1));
+         RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel-1);
+         grid->accept(refineVisitormin4);*/
+
+         ////GbCuboid3DPtr refine1PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3
+         ////   , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+         ////RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP1(refine1PlatteCube, baseLevel, refineLevel-6);
+         ////grid->accept(refineAdapterP1);
+
+         //GbCuboid3DPtr refine2PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3*0.5
+         //  , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP2(refine2PlatteCube, baseLevel, refineLevel-5);
+         //grid->accept(refineAdapterP2);
+
+         //GbCuboid3DPtr refine3PlatteCube(new GbCuboid3D(  originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh-H3*0.5
+         //   , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.5));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP3(refine3PlatteCube, baseLevel, refineLevel-4);
+         //grid->accept(refineAdapterP3);
+
+         //GbCuboid3DPtr refine4PlatteCube(new GbCuboid3D(   originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.0
+         //   ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.25));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine4PlatteCube.get(), pathname+"/geo/refine4PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP4(refine4PlatteCube, baseLevel, refineLevel-3);
+         //grid->accept(refineAdapterP4);
+
+         //GbCuboid3DPtr refine5PlatteCube(new GbCuboid3D(   originX1-geoOverlap , originX2-geoOverlap  ,x3minMesh+deltaX3Platte*0.1/* x3minMesh+deltaX3Platte*0.8*/
+         //   ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.00375));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine5PlatteCube.get(), pathname+"/geo/refine5PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP5(refine5PlatteCube, baseLevel, refineLevel-2);
+         //grid->accept(refineAdapterP5);
+
+
+         //GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX1-3.0*geoOverlap
+         //	  , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.1));
+
+         GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.6/*0.55*/));
+
+         GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.49
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.53));
+
+         GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.9
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         GbCuboid3DPtr wallsX1X2maxRef1(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.95
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         if (refineLevel > 0)
+         {
+
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(wallsX1X2minRef3, refineLevel-1);
+            refineHelper.addGbObject(wallsX1X2minRef4, refineLevel);
+            refineHelper.addGbObject(wallsX1X2maxRef2, refineLevel-1);
+            refineHelper.addGbObject(wallsX1X2maxRef1, refineLevel);
+
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         ///interactoren
+         //int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+         //D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         ///////würfel unten version ende
+         ////////////////////////////////////////////////////////////////////////////////
+         ////////PM grid
+         //Temporär:
+         //double  H=1.0;
+
+         vector<D3Q27InteractorPtr> D3Q27InteractorPtrarray;
+         ////////////////////////////////////////////////////////////////////////////////
+         double inflowCubeDx = coarseNodeDx;///(double)(1<<inflowCubeLevel);
+         double dpCubes=(double)H/20.0;//100.0; //30zum testen 100real
+         double offsetZgrid=H+0.5*inflowCubeDx;
+         double epschoch1drittel= 0.928318;
+         double abstandIn=2.0*dpCubes;
+         double c1oAbst=1.0/abstandIn;
+         for (int Nflowdir=0;Nflowdir<((nx[0]*blocknx[0]*c1oAbst)*coarseNodeDx); Nflowdir++)
+         {
+            // for (int Nhorizon=((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5-2; Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5-1-1; Nhorizon++)
+            // {
+            //  for (int Nhorizon=0;  Nhorizon<(((nx[2]*blocknx[2]+1)*c1oAbst)*coarseNodeDx)*0.1; Nhorizon++)//Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5; Nhorizon++)
+            for (int Nhorizon=0;  Nhorizon<(((nx[2]*blocknx[2]+1)*c1oAbst)*coarseNodeDx)*0.5-1; Nhorizon++)//Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5; Nhorizon++)
+
+            {
+               for (int Nspanw=0; Nspanw<((nx[1]*blocknx[1]*c1oAbst)*coarseNodeDx); Nspanw++)
+               {
+                  // stringstream ss;
+                  //     ss<<"cubeH"<<Nflowdir<<"x"<<Nhorizon<<"x"<<Nspanw;
+                  ////     //   //geoOrigin ist Mitte, nicht vordere Ecke -> korrigieren
+                  // int Nflowdir=1;
+                  //int Nhorizon=0;
+                  //int Nspanw=1;
+                  double xminCubes1=originX1+(Nflowdir*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1);
+                  double xmaxCubes1=originX1+(Nflowdir*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1);
+                  double xminCubes=std::max(xminCubes1,2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double xmaxCubes=std::min(xmaxCubes1,originX1+geoLength[0]-coarseNodeDx/pow(2.0,refineLevel));
+                  double yminCubes=std::max(originX2+(Nspanw*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1),2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double ymaxCubes=std::min(originX2+(Nspanw*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1),originX2+geoLength[1]-coarseNodeDx/pow(2.0,refineLevel));
+                  double zminCubes=std::max(originX3+(Nhorizon*abstandIn)+4.0*coarseNodeDx/pow(2.0,refineLevel-1),2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double zmaxCubes=std::min(originX3+(Nhorizon*abstandIn)+dpCubes+4.0*coarseNodeDx/pow(2.0,refineLevel-1),originX3+geoLength[2]-coarseNodeDx/pow(2.0,refineLevel));
+                  ////     /*GbCuboid3D  *rectTemp = new GbCuboid3D(originX1+(Nflowdir*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, originX2+(Nspanw*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, originX3+(Nhorizon*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, 
+                  ////										 originX1+(Nflowdir*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx, originX2+(Nspanw*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx, originX3+(Nhorizon*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx );
+                  ////*/
+                  ////  
+                  GbCuboid3DPtr rectTemp(new GbCuboid3D(xminCubes, yminCubes, zminCubes, 
+                     xmaxCubes, ymaxCubes, zmaxCubes));
+                  ////
+                  //     ostringstream ostrcubes;
+                  //	 ostrcubes<<pathname <<"/cubeH"<<Nflowdir<<"x"<<Nhorizon<<"x"<<Nspanw;
+                  ////       
+                  ////   
+                  //// // GbSystem3D::writeGeoObject(rectTemp,outpath+cubeschar,WbWriterAvsASCII::getInstance());
+                  ////  GbSystem3D::writeGeoObject(rectTemp,ostrcubes.str(),WbWriterAvsASCII::getInstance()); //??
+                  //        ostrcubes.str("");
+                  //         ostrcubes.clear();
+
+                  ////  boost::shared_ptr<D3Q19AMRInteractor> interactorTemp( new D3Q19AMRInteractor( rectTemp,new D3Q19NoSlipBCAdapter(),AMR3DInteractor::SOLID,ss.str()) );
+                  //  //  interactorService.addInteractor(interactorTemp);
+                  D3Q27BoundaryConditionAdapterPtr cubeBCAdapter(new D3Q27NoSlipBCAdapter());                   //D3Q27DensityBCAdapter(rhoInit));
+                  D3Q27InteractorPtr cubeInteractor( new D3Q27Interactor(rectTemp,grid,cubeBCAdapter,Interactor3D::SOLID));
+                  D3Q27InteractorPtrarray.push_back(cubeInteractor);  
+
+
+               }
+            }}
+         ////////////////
+         //ende cubes
+         //////////
+         ////////////////////////////////////////////
+         //METIS
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+
+
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         SolidBlocksHelper sd(grid, comm);
+
+         sd.addInteractor(topBCInteractor);
+         sd.addInteractor(bottomBCInteractor);
+         for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+         {
+            sd.addInteractor(D3Q27InteractorPtrarray[i]);
+         }
+         sd.deleteSolidBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+         grid->accept( metisVisitor );
+
+         sd.setTransBlocks(); 
+
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+         unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+
+         double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+         // LBMKernel3DPtr kernel(new LBMKernelETD3Q27CascadedTI(blocknx[0], blocknx[1], blocknx[2]));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx[0], blocknx[1], blocknx[2],1));
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+         //	  //scheint neuerdings fuer absturz zu sorgen:
+         mu::Parser fctForcingX1;
+         fctForcingX1.SetExpr("Fx1*dx");
+         fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);//9.99685e-7);
+
+         kernel->setForcingX1(fctForcingX1);
+         kernel->setWithForcing(true); 
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+
+         grid->accept(kernelVisitor);
+
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+         //////////////////////////////////////////
+
+         grid->addAndInitInteractor( bottomBCInteractor ); 
+         grid->addAndInitInteractor( topBCInteractor );
+         for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+         {
+            grid->addAndInitInteractor( D3Q27InteractorPtrarray[i] ); 
+            char numstr[21];
+            sprintf(numstr, "%f", (double)i);
+            std::string pathObstCube = pathname+"/geo/obstBCCuboid"+ numstr;
+            if(myid == 0) GbSystem3D::writeGeoObject(D3Q27InteractorPtrarray[i]->getGbObject3D().get(),
+               /* rectTemp.get(),*/ pathObstCube, WbWriterVtkXmlASCII::getInstance());
+         }
+
+
+         UbTimer timer;
+         timer.start();
+         grid->accept( metisVisitor );
+
+         if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         if(myid == 0) ppblocks->update(0);
+         if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+
+         if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+         grid->accept( metisVisitor );
+         if(myid == 0) ppblocks->update(1);
+         ppblocks.reset();
+         if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+         //inflow
+         double uLB2=uLB;
+         double raiseVelSteps = 0;
+         vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("uLB*0.9"); 
+
+         inflowProfile.DefineConst("uLB",uLB2);
+         velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nueLB,rhoInit);
+         initVisitor.setVx1(inflowProfile);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         //LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter, comm, true));
+
+
+
+         grid->doPostProcess(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+
+      }
+
+
+
+      UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(100,1,1000);
+      //visSch->addSchedule(1000,1000,10000);
+      //visSch->addSchedule(10000,10000,100000);
+      //visSch->addSchedule(20000,20000,800000);
+      //visSch->addSchedule(50,350000,350500);
+      //visSch->addSchedule(50,420000,420500);
+      //visSch->addSchedule(50000,420500,10000000);
+      visSch->addSchedule(2250,268250,592250);
+      UbSchedulerPtr resSch(new UbScheduler());
+      resSch->addSchedule(20000,20,10000000);
+      // AverageValuesPostprocessor       Avpp(grid,  pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/,resSch/*wann wird resettet*/,comm);
+      UbSchedulerPtr resSchRMS(new UbScheduler());
+      resSchRMS->addSchedule(40000,420000,10000000);
+      UbSchedulerPtr resSchMeans(new UbScheduler());
+      resSchMeans->addSchedule(40000,0,10000000);
+      UbSchedulerPtr stepAvSch(new UbScheduler());
+      int averageInterval=20;
+      stepAvSch->addSchedule(averageInterval,0,10000000);
+
+      double restart=10000; //??????????
+      AverageValuesPostprocessor       Avpp(grid,  pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), stepAvSch/*wann wird gemittelt*/, averageInterval,visSch/*wann wird rausgeschrieben*/,resSchMeans,resSchRMS/*wann wird resettet*/,comm,restart);
+
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), unitConverter, comm);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 90050, 90080));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+
+      UbSchedulerPtr AdjForcSch(new UbScheduler());
+      AdjForcSch->addSchedule(100,20,20000000);
+      D3Q27IntegrateValuesHelperPtr IntValHelp(new D3Q27IntegrateValuesHelper(grid, comm, 
+         originX1, originX2, kanalhoeheSI*0.55/*0.501*/, 
+         nx[0]*blockLengthx1, nx[1]*blockLengthx2, kanalhoeheSI*0.999));
+
+      double vxZiel=uLB;
+      //D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel*0.6, comm);//da am 11.3.2013 velo um 1/0.6 zu hoch
+      D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel, comm);//dies sollte zu Re=5500 fuehren..
+
+      UbSchedulerPtr visQSch(new UbScheduler());
+      visQSch->addSchedule(10,90100,90130);
+      QKritPostprocessor QKritPtr(grid,pathname+"/steps/Qq",WbWriterVtkXmlBinary::getInstance(),visQSch, comm);
+
+      mu::Parser decrViscFunc;
+      decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");
+      decrViscFunc.DefineConst("nue0", nueLB);
+      decrViscFunc.DefineConst("c0", 0.1);
+      UbSchedulerPtr DecrViscSch(new UbScheduler());
+      DecrViscSch->addSchedule(10,10,1000);
+      DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch,&decrViscFunc, comm);
+
+      cout << "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe()<<endl;
+
+      double endTime = 520000;//20000001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/bKanal/bKanal.cpp b/source/Applications/bKanal/bKanal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b1bff75b08f2ff6989f02dd8ee7f58ada48263ba
--- /dev/null
+++ b/source/Applications/bKanal/bKanal.cpp
@@ -0,0 +1,565 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <sys/types.h> //mkdir rights
+#include <sys/stat.h> //mkdir
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string pathname; 
+      string pathnameRestart;
+      int numOfThreads =1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      UbLog::reportingLevel() = logINFO;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr);
+
+      if(machine == "my") 
+      {
+         pathname = "d:/temp/BKanal";
+         numOfThreads = 1;
+         logfile = false;
+         availMem = 10.0e9;
+      }
+      else if(machine == "Ludwig")      
+      {
+         pathname =        "/work/koskuche/SFB880/BKanal";
+         pathnameRestart = "/work/koskuche/SFB880/BKanal";
+         numOfThreads = 8;
+         availMem = 1.0e9;
+         logfile = true;
+
+         if (myid==0) 
+         {
+            const char* str = pathname.c_str();
+#if defined(__unix__)
+            int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+#endif 
+         }
+
+         if(myid ==0)
+         {
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         }
+
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      if(myid ==0 && logfile)
+      {
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      UBLOG(logINFO,"Testcase BreugemChannel");
+
+      int baseLevel, refineLevel,nx[3],blocknx[3];
+      double Re,velocity,rhoInit,vx1Init;//,vx2Init,vx3Init;
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      Re            = 5500;// 13286;//13286;//gemessen 18.98 m/s...*5.0 zum  testen ob was passiert
+      velocity      = 0.01;  
+      vx1Init       = 0.01;  
+      rhoInit       = 0.0;
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+
+      int H=200;//200;//392;
+
+      //  nx[0]      =8;//ok mit 8// (int)(3.0*(double)H/8.0/8.0);//2;// (int)(0.3*(double)H/6.0/4.0);//das "/4" hier ist wegen der verfeinerung da! //länge
+      //  nx[1]      =8;//ok mit 8// (int)(2.0*(double)H/8.0/8.0);//2;// (int)(0.2*(double)H/6.0/4.0);//  //breite
+      nx[2]      = (int)(2.0*(double)H/5.0/8.0);// //höhe gebiet
+
+      //(3/2/2)-ratio:
+      nx[1]=nx[2];
+      nx[0]=15;
+
+      blocknx[0] = 15;//10;//5;
+      blocknx[1] = 15;//10;//5;
+      blocknx[2] = 15;//10;//5;
+
+      baseLevel   = 0;
+      refineLevel = 2;//1;////3;//3 soll 1 test;
+
+      ///////////////Weltabmessungen:
+      //double kanallaengeSI = ( 2.0*(double)H);
+      // double kanalbreiteSI = ( 1.0*(double)H);
+      double kanalhoeheSI  = ( 2.0*(double)H);
+
+      // double refinewidth1=kanalhoeheSI/10.0;
+
+      double fineNodeDx   = (kanalhoeheSI) / (double)( blocknx[2]*nx[2]*(1<<refineLevel)+1 ); //+1--> gitter liegt jeweils 0.5dx innerhalb
+      double coarseNodeDx = fineNodeDx * (double)(1<<refineLevel);//geowerte
+
+      double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+      double blockLengthx2 = blockLengthx1;
+      double blockLengthx3 = blockLengthx1;
+
+      double originX1 = 0.0;//-50.0*propellerDurchmesser;  //geowerte
+      double originX2 = 0.0;//-0.5*blockLengthx2*nx2;
+      double originX3 = 0.0;// minX3 + 0.5*fineNodeDx;
+
+      double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      bool periodicx1 = true;
+      bool periodicx2 = true;
+      bool periodicx3 = false;
+
+
+      //##########################################################################
+      //## physical parameters
+      //##########################################################################
+      double smagorinskiConstant = 0.18;
+
+
+      double rhoLB         = 0.0;
+
+      double rhoReal       = 1.0;
+      double nueReal  = 1;//0.000016;//0.015;
+
+      double hReal         = blocknx[2]*nx[2];//H*0.9;//0.0105;//<-m     1.05;//Plattendicke in cm(! cm nicht m !)
+      double uReal         = Re*nueReal/hReal;
+
+      //##Machzahl:
+      //#Ma     = uReal/csReal
+      double csReal=343.0;
+      double Ma      = uReal/csReal;//Ma-Real!
+      //double csReal  = uReal/Ma;
+      double hLB     = hReal/coarseNodeDx;
+
+      //LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(hReal, csReal, rhoReal, hLB));
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+      double uLB          = velocity;
+      double nuLB         = (uLB*hLB)/Re;
+
+      //double uLB           = uReal   * unitConverter->getFactorVelocityWToLb();
+      //double nueLB         = nueReal * unitConverter->getFactorViscosityWToLb();
+      //double timestep      = unitConverter->getFactorTimeLbToW(coarseNodeDx);
+
+      //velocity = uLB;
+      // double viscosity =nueLB*1000.0;
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(10000,10000,10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+      grid = rp.restart(-1);
+      //////////////////////////////////////////////////////////////////////////
+
+       if (grid->getTimeStep() == 0)
+       {
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];
+
+         //set grid
+         grid->setDeltaX(coarseNodeDx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+
+
+         //bottom and top solid bc
+         //iteractors
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         double geoOverlap = coarseNodeDx;
+         GbCuboid3DPtr bottomBCCuboid(new GbCuboid3D(originX1-geoOverlap, originX2-geoOverlap, originX3-geoOverlap, 
+            originX1+geoLength[0]+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(bottomBCCuboid.get(), pathname+"/geo/bottomBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr bottomBCInteractor(new D3Q27Interactor(bottomBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+
+         GbCuboid3DPtr topBCCuboid(new GbCuboid3D(originX1-geoLength[0]-coarseNodeDx, originX2-geoOverlap, originX3+geoLength[2],//-coarseNodeDx*0.5, 
+            originX1+geoLength[0]+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap));
+         if(myid == 0) GbSystem3D::writeGeoObject(topBCCuboid.get(), pathname+"/geo/topBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr topBCInteractor(new D3Q27Interactor(topBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+         //grid->addAndInitInteractor( bottomBCInteractor ); 
+         // grid->addAndInitInteractor( topBCInteractor ); 
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            ="<<Re);
+            UBLOG(logINFO, "* Ma            ="<<Ma);
+            UBLOG(logINFO, "* uReal         ="<<uReal);
+            UBLOG(logINFO, "* nueReal       ="<<nueReal);
+            UBLOG(logINFO, "* nue           ="<<nuLB);
+            UBLOG(logINFO, "* velocity      ="<<uLB);
+            // UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+            //  UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+            UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+            UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+            UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+            UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+            UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+            UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "*****************************************");
+/*            UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+            UBLOG(logINFO, "*****************************************");  */   
+         }
+
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+
+         //////////////////////////////////////////////////////////////////////////
+         // refine
+         //////////////////////////////////////////////////////////////////////////
+         GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.6/*0.55*/));
+
+         GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.49
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.53));
+
+         GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.9
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         GbCuboid3DPtr wallsX1X2maxRef1(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.95
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         if (refineLevel > 0)
+         {
+
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(wallsX1X2minRef3, refineLevel-1);
+            refineHelper.addGbObject(wallsX1X2minRef4, refineLevel);
+            refineHelper.addGbObject(wallsX1X2maxRef2, refineLevel-1);
+            refineHelper.addGbObject(wallsX1X2maxRef1, refineLevel);
+
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         ///interactoren
+         //int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+         //D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         ///////würfel unten version ende
+         ////////////////////////////////////////////////////////////////////////////////
+         ////////PM grid
+         //Temporär:
+         //double  H=1.0;
+
+         vector<D3Q27InteractorPtr> D3Q27InteractorPtrarray;
+         ////////////////////////////////////////////////////////////////////////////////
+         double inflowCubeDx = coarseNodeDx;///(double)(1<<inflowCubeLevel);
+         double dpCubes=(double)H/20.0;//100.0; //30zum testen 100real
+         double offsetZgrid=H+0.5*inflowCubeDx;
+         double epschoch1drittel= 0.928318;
+         double abstandIn=2.0*dpCubes;
+         double c1oAbst=1.0/abstandIn;
+         for (int Nflowdir=0;Nflowdir<((nx[0]*blocknx[0]*c1oAbst)*coarseNodeDx); Nflowdir++)
+         {
+            // for (int Nhorizon=((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5-2; Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5-1-1; Nhorizon++)
+            // {
+            //  for (int Nhorizon=0;  Nhorizon<(((nx[2]*blocknx[2]+1)*c1oAbst)*coarseNodeDx)*0.1; Nhorizon++)//Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5; Nhorizon++)
+            for (int Nhorizon=0;  Nhorizon<(((nx[2]*blocknx[2]+1)*c1oAbst)*coarseNodeDx)*0.5-1; Nhorizon++)//Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5; Nhorizon++)
+
+            {
+               for (int Nspanw=0; Nspanw<((nx[1]*blocknx[1]*c1oAbst)*coarseNodeDx); Nspanw++)
+               {
+                  // stringstream ss;
+                  //     ss<<"cubeH"<<Nflowdir<<"x"<<Nhorizon<<"x"<<Nspanw;
+                  ////     //   //geoOrigin ist Mitte, nicht vordere Ecke -> korrigieren
+                  // int Nflowdir=1;
+                  //int Nhorizon=0;
+                  //int Nspanw=1;
+                  double xminCubes1=originX1+(Nflowdir*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1);
+                  double xmaxCubes1=originX1+(Nflowdir*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1);
+                  double xminCubes=std::max(xminCubes1,2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double xmaxCubes=std::min(xmaxCubes1,originX1+geoLength[0]-coarseNodeDx/pow(2.0,refineLevel));
+                  double yminCubes=std::max(originX2+(Nspanw*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1),2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double ymaxCubes=std::min(originX2+(Nspanw*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1),originX2+geoLength[1]-coarseNodeDx/pow(2.0,refineLevel));
+                  double zminCubes=std::max(originX3+(Nhorizon*abstandIn)+4.0*coarseNodeDx/pow(2.0,refineLevel-1),2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double zmaxCubes=std::min(originX3+(Nhorizon*abstandIn)+dpCubes+4.0*coarseNodeDx/pow(2.0,refineLevel-1),originX3+geoLength[2]-coarseNodeDx/pow(2.0,refineLevel));
+                  ////     /*GbCuboid3D  *rectTemp = new GbCuboid3D(originX1+(Nflowdir*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, originX2+(Nspanw*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, originX3+(Nhorizon*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, 
+                  ////										 originX1+(Nflowdir*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx, originX2+(Nspanw*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx, originX3+(Nhorizon*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx );
+                  ////*/
+                  ////  
+                  GbCuboid3DPtr rectTemp(new GbCuboid3D(xminCubes, yminCubes, zminCubes, 
+                     xmaxCubes, ymaxCubes, zmaxCubes));
+                  ////
+                  //     ostringstream ostrcubes;
+                  //	 ostrcubes<<pathname <<"/cubeH"<<Nflowdir<<"x"<<Nhorizon<<"x"<<Nspanw;
+                  ////       
+                  ////   
+                  //// // GbSystem3D::writeGeoObject(rectTemp,outpath+cubeschar,WbWriterAvsASCII::getInstance());
+                  ////  GbSystem3D::writeGeoObject(rectTemp,ostrcubes.str(),WbWriterAvsASCII::getInstance()); //??
+                  //        ostrcubes.str("");
+                  //         ostrcubes.clear();
+
+                  ////  boost::shared_ptr<D3Q19AMRInteractor> interactorTemp( new D3Q19AMRInteractor( rectTemp,new D3Q19NoSlipBCAdapter(),AMR3DInteractor::SOLID,ss.str()) );
+                  //  //  interactorService.addInteractor(interactorTemp);
+                  D3Q27BoundaryConditionAdapterPtr cubeBCAdapter(new D3Q27NoSlipBCAdapter());                   //D3Q27DensityBCAdapter(rhoInit));
+                  D3Q27InteractorPtr cubeInteractor( new D3Q27Interactor(rectTemp,grid,cubeBCAdapter,Interactor3D::SOLID));
+                  D3Q27InteractorPtrarray.push_back(cubeInteractor);  
+
+
+               }
+            }}
+         ////////////////
+         //ende cubes
+         //////////
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(topBCInteractor);
+         intHelper.addInteractor(bottomBCInteractor);
+         for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+         {
+            intHelper.addInteractor(D3Q27InteractorPtrarray[i]);
+         }
+         intHelper.selectBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+         unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+
+         double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+         // LBMKernel3DPtr kernel(new LBMKernelETD3Q27CascadedTI(blocknx[0], blocknx[1], blocknx[2]));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx[0], blocknx[1], blocknx[2],1));
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+         //	  //scheint neuerdings fuer absturz zu sorgen:
+         mu::Parser fctForcingX1;
+         fctForcingX1.SetExpr("Fx1*dx");
+         fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);//9.99685e-7);
+
+         kernel->setForcingX1(fctForcingX1);
+         kernel->setWithForcing(true); 
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+
+         grid->accept(kernelVisitor);
+
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+         //////////////////////////////////////////
+         intHelper.setBC();
+
+         for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+         {
+            grid->addAndInitInteractor( D3Q27InteractorPtrarray[i] ); 
+            char numstr[21];
+            sprintf(numstr, "%f", (double)i);
+            std::string pathObstCube = pathname+"/geo/obstBCCuboid"+ numstr;
+            if(myid == 0) GbSystem3D::writeGeoObject(D3Q27InteractorPtrarray[i]->getGbObject3D().get(),
+               /* rectTemp.get(),*/ pathObstCube, WbWriterVtkXmlASCII::getInstance());
+         }
+
+         UbTimer timer;
+         timer.start();
+         grid->accept( metisVisitor );
+
+         if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         if(myid == 0) ppblocks->update(0);
+         if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+         if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+         grid->accept( metisVisitor );
+         if(myid == 0) ppblocks->update(1);
+         ppblocks.reset();
+         if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+         //inflow
+         double uLB2=uLB;
+         double raiseVelSteps = 0;
+         vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("uLB*0.9"); 
+
+         inflowProfile.DefineConst("uLB",uLB2);
+         velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nuLB,rhoInit);
+         initVisitor.setVx1(inflowProfile);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         //LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter,true));
+
+
+
+         grid->doPostProcess(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+
+      }
+            else
+            {
+               //set forcing
+               mu::Parser fctForcingX1, fctForcingX2, fctForcingX3;
+               fctForcingX1.SetExpr("Fx1*dx");
+               fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);
+               SetForcingBlockVisitor forcingVisitor(fctForcingX1, fctForcingX2, fctForcingX3);
+               grid->accept(forcingVisitor);
+
+               //set connectors
+               D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+               D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+               grid->accept( setConnsVisitor );
+               if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      }
+
+
+      UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(100,1,1000);
+      //visSch->addSchedule(1000,1000,10000);
+      //visSch->addSchedule(10000,10000,100000);
+      //visSch->addSchedule(20000,20000,800000);
+      //visSch->addSchedule(50,350000,350500);
+      //visSch->addSchedule(50,420000,420500);
+      //visSch->addSchedule(50000,420500,10000000);
+      visSch->addSchedule(2250,140000,450001);
+      UbSchedulerPtr resSch(new UbScheduler());
+      resSch->addSchedule(20000,20,10000000);
+      UbSchedulerPtr resSchRMS(new UbScheduler());
+      resSchRMS->addSchedule(40000,420000,10000000);
+      UbSchedulerPtr resSchMeans(new UbScheduler());
+      resSchMeans->addSchedule(40000,0,10000000);
+      UbSchedulerPtr stepAvSch(new UbScheduler());
+      stepAvSch->addSchedule(20,0,10000000);
+      AverageValuesPostprocessor Avpp(grid, pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), 
+                                      visSch/*wann wird rausgeschrieben*/, stepAvSch/*wann wird gemittelt*/, resSchMeans, resSchRMS/*wann wird resettet*/);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), unitConverter, comm);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 90050, 90080));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+
+      UbSchedulerPtr AdjForcSch(new UbScheduler());
+      AdjForcSch->addSchedule(100,20,20000000);
+      D3Q27IntegrateValuesHelperPtr IntValHelp(new D3Q27IntegrateValuesHelper(grid, comm, 
+         originX1, originX2, kanalhoeheSI*0.55/*0.501*/, 
+         nx[0]*blockLengthx1, nx[1]*blockLengthx2, kanalhoeheSI*0.999));
+
+      double vxZiel=uLB;
+      //D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel*0.6, comm);//da am 11.3.2013 velo um 1/0.6 zu hoch
+      D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel, comm);//dies sollte zu Re=5500 fuehren..
+
+      UbSchedulerPtr visQSch(new UbScheduler());
+      visQSch->addSchedule(10,90100,90130);
+      QCriterionPostprocessor QKritPtr(grid,pathname+"/steps/Qq",WbWriterVtkXmlBinary::getInstance(),visQSch, comm);
+
+      mu::Parser decrViscFunc;
+      decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");
+      decrViscFunc.DefineConst("nue0", nuLB);
+      decrViscFunc.DefineConst("c0", 0.1);
+      UbSchedulerPtr DecrViscSch(new UbScheduler());
+      DecrViscSch->addSchedule(10,10,1000);
+      DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch,&decrViscFunc, comm);
+
+      cout << "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe()<<endl;
+
+      double endTime = 2000000;//20000001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/bKanal/sKanal/bKanal.cpp b/source/Applications/bKanal/sKanal/bKanal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cabea74871a6da507b1c9c9ddf23820a936bdb10
--- /dev/null
+++ b/source/Applications/bKanal/sKanal/bKanal.cpp
@@ -0,0 +1,694 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <sys/types.h> //mkdir rights
+#include <sys/stat.h> //mkdir
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      UBLOG(logINFO,"Testcase BreugemChannel");
+      string pathname; 
+      string pathnameRestart;
+      string pathGeo;
+      int numOfThreads =1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      UbLog::reportingLevel() = logINFO;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "PIPPINNEU") 
+      {
+
+         pathname = "f:/temp/breugemKb";
+         //pathGeo = "c:/Data/plate";
+         numOfThreads = 1;
+         logfile = false;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname =        "/work/koskuche/SFB880/BKanaltest0Ref2up1812Ratio322f5nx15RestartQ";
+         pathnameRestart = "/work/koskuche/SFB880/BKanaltest0Ref2up1212Ratio322";//BKanaltest0Ref2up0612";//BKanaltest0Ref2up1012Out";
+         //pathname =        "/work/koskuche/SFB880/BKanaltestRe260000Out";
+         //pathnameRestart = "/work/koskuche/SFB880/BKanaltestRe260000";//BKanaltest0Ref2up0612";//BKanaltest0Ref2up1012Out";
+
+	pathGeo = "/home/koskuche/data/plate";
+         numOfThreads = 1;
+         availMem = 12.0e9;
+         logfile = true;
+
+         if (myid==0) 
+         {
+            const char* str = pathname.c_str();
+#if defined(__unix__)
+            int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+#endif 
+
+         }
+
+         if(myid ==0)
+         {
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         }
+
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+
+
+      //if(myid ==0 && logfile)
+      //{
+      UbLog::output_policy::setStream(logFilename.str());
+      //}
+
+      int baseLevel, refineLevel,nx[3],blocknx[3];
+      double Re,velocity,rhoInit,vx1Init;//,vx2Init,vx3Init;
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      Re            = 5500;// 13286;//13286;//gemessen 18.98 m/s...*5.0 zum  testen ob was passiert
+      velocity      = 0.01;  
+      vx1Init       = 0.01;  
+      rhoInit       = 0.0;
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+
+      int H=200;//200;//392;
+
+      //  nx[0]      =8;//ok mit 8// (int)(3.0*(double)H/8.0/8.0);//2;// (int)(0.3*(double)H/6.0/4.0);//das "/4" hier ist wegen der verfeinerung da! //länge
+      //  nx[1]      =8;//ok mit 8// (int)(2.0*(double)H/8.0/8.0);//2;// (int)(0.2*(double)H/6.0/4.0);//  //breite
+      nx[2]      = (int)(2.0*(double)H/5.0/8.0);// //höhe gebiet
+
+      //(3/2/2)-ratio:
+      nx[1]=nx[2];
+      nx[0]=15;
+
+      blocknx[0] = 15;//10;//5;
+      blocknx[1] = 15;//10;//5;
+      blocknx[2] = 15;//10;//5;
+
+      baseLevel   = 0;
+      refineLevel = 2;//1;////3;//3 soll 1 test;
+
+
+      ///////////////Weltabmessungen:
+      //double kanallaengeSI = ( 2.0*(double)H);
+      // double kanalbreiteSI = ( 1.0*(double)H);
+      double kanalhoeheSI  = ( 2.0*(double)H);
+
+      // double refinewidth1=kanalhoeheSI/10.0;
+
+      double fineNodeDx   = (kanalhoeheSI) / (double)( blocknx[2]*nx[2]*(1<<refineLevel)+1 ); //+1--> gitter liegt jeweils 0.5dx innerhalb
+      double coarseNodeDx = fineNodeDx * (double)(1<<refineLevel);//geowerte
+
+      double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+      double blockLengthx2 = blockLengthx1;
+      double blockLengthx3 = blockLengthx1;
+
+      double originX1 = 0.0;//-50.0*propellerDurchmesser;  //geowerte
+      double originX2 = 0.0;//-0.5*blockLengthx2*nx2;
+      double originX3 = 0.0;// minX3 + 0.5*fineNodeDx;
+
+      double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      bool periodicx1 = true;
+      bool periodicx2 = true;
+      bool periodicx3 = false;
+
+
+      //##########################################################################
+      //## physical parameters
+      //##########################################################################
+      double smagorinskiConstant = 0.18;
+
+
+      double rhoLB         = 0.0;
+
+      double rhoReal       = 1.0;
+      double nueReal  = 1;//0.000016;//0.015;
+
+      double hReal         = blocknx[2]*nx[2];//H*0.9;//0.0105;//<-m     1.05;//Plattendicke in cm(! cm nicht m !)
+      double uReal         = Re*nueReal/hReal;
+
+      //##Machzahl:
+      //#Ma     = uReal/csReal
+      double csReal=343.0;
+      double Ma      = uReal/csReal;//Ma-Real!
+      //double csReal  = uReal/Ma;
+      double hLB     = hReal/coarseNodeDx;
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(hReal, csReal, rhoReal, hLB));
+
+      double uLB           = uReal   * unitConverter->getFactorVelocityWToLb();
+      double nueLB         = nueReal * unitConverter->getFactorViscosityWToLb();
+      double timestep      = unitConverter->getFactorTimeLbToW(coarseNodeDx);
+
+      velocity = uLB;
+      // double viscosity =nueLB*1000.0;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      UbSchedulerPtr rSch(new UbScheduler(10000,100000,30000000000));//(50000,50000,1000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathnameRestart+"/checkpoints", RestartPostprocessor::BINARY);
+
+      //////////////////////////////////////////////////////////////////////////
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if(/*(cstr== NULL)*/cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) {
+            UBLOG(logINFO,"Restart step: " << opt);
+            UBLOG(logINFO, "Restart=:" << pathnameRestart);
+         }
+
+         grid = rp.restart(UbSystem::stringTo<int>(opt));
+         rp.reconnect(grid);
+
+//          mu::Parser fctForcingX1, fctForcingX2, fctForcingX3;
+//          fctForcingX1.SetExpr("Fx1*dx");
+//          fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);
+// 
+//          SetForcingBlockVisitor forcingVisitor(fctForcingX1, fctForcingX2, fctForcingX3);
+//          grid->accept(forcingVisitor);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+      }
+      else
+      {
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];
+
+         //set grid
+         grid->setDeltaX(coarseNodeDx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+
+
+         //bottom and top solid bc
+         //iteractors
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         double geoOverlap = coarseNodeDx;
+         GbCuboid3DPtr bottomBCCuboid(new GbCuboid3D(originX1-geoOverlap, originX2-geoOverlap, originX3-geoOverlap, 
+            originX1+geoLength[0]+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(bottomBCCuboid.get(), pathname+"/geo/bottomBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr bottomBCInteractor(new D3Q27Interactor(bottomBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+
+         GbCuboid3DPtr topBCCuboid(new GbCuboid3D(originX1-geoLength[0]-coarseNodeDx, originX2-geoOverlap, originX3+geoLength[2],//-coarseNodeDx*0.5, 
+            originX1+geoLength[0]+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap));
+         if(myid == 0) GbSystem3D::writeGeoObject(topBCCuboid.get(), pathname+"/geo/topBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr topBCInteractor(new D3Q27Interactor(topBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+         //grid->addAndInitInteractor( bottomBCInteractor ); 
+         // grid->addAndInitInteractor( topBCInteractor ); 
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            ="<<Re);
+            UBLOG(logINFO, "* Ma            ="<<Ma);
+            UBLOG(logINFO, "* uReal         ="<<uReal);
+            UBLOG(logINFO, "* nueReal       ="<<nueReal);
+            UBLOG(logINFO, "* nue           ="<<nueLB);
+            UBLOG(logINFO, "* velocity      ="<<uLB);
+            // UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+            //  UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+            UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+            UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+            UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+            UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+            UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+            UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "*****************************************");
+            UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+            UBLOG(logINFO, "*****************************************");     
+         }
+
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+
+         //////////////////////////////////////////////////////////////////////////
+         // refine
+         //////////////////////////////////////////////////////////////////////////
+         //GbCuboid3DPtr wallsX1X2maxRef1( new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI*0.95
+         //    , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax1(wallsX1X2maxRef1, 0,refineLevel-3);
+         //grid->accept(refineVisitormax1);
+         //
+         //GbCuboid3DPtr wallsX1X2minRef1(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI*0.55
+         //    , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.47));
+         // RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin1(wallsX1X2minRef1, 0,refineLevel-3);
+         // grid->accept(refineVisitormin1);
+
+         //   GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.98));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax2(wallsX1X2maxRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormax2);
+         //   GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.9));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax2(wallsX1X2maxRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormax2);
+
+         // GbCuboid3DPtr wallsX1X2maxRef3(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.9995));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax3(wallsX1X2maxRef3, 0,refineLevel-1);
+         //grid->accept(refineVisitormax3);
+
+         //         GbCuboid3DPtr wallsX1X2minRefl3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.25));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitorminl3(wallsX1X2minRefl3, 0,refineLevel-3);
+         //grid->accept(refineVisitorminl3);
+         /////würfel unten version
+         //      GbCuboid3DPtr wallsX1X2minRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.2));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin2(wallsX1X2minRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormin2);
+
+         //   GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , kanalhoeheSI*0.04
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.18));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin3(wallsX1X2minRef3, 0,refineLevel-1);
+         //grid->accept(refineVisitormin3);
+
+         //      GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , kanalhoeheSI*0.09
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.16));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel);
+         //grid->accept(refineVisitormin4);
+
+
+
+
+         /////würfel anfang version
+         //       GbCuboid3DPtr wallsX1X2minRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.56));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin2(wallsX1X2minRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormin2);
+
+         //   GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.55));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin3(wallsX1X2minRef3, 0,refineLevel-2);
+         //grid->accept(refineVisitormin3);
+
+         //      GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.49
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.53));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel-1);
+         //grid->accept(refineVisitormin4);
+
+
+         /*           GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX1-3.0*geoOverlap
+         , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.1));
+         RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel-1);
+         grid->accept(refineVisitormin4);*/
+
+         ////GbCuboid3DPtr refine1PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3
+         ////   , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+         ////RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP1(refine1PlatteCube, baseLevel, refineLevel-6);
+         ////grid->accept(refineAdapterP1);
+
+         //GbCuboid3DPtr refine2PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3*0.5
+         //  , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP2(refine2PlatteCube, baseLevel, refineLevel-5);
+         //grid->accept(refineAdapterP2);
+
+         //GbCuboid3DPtr refine3PlatteCube(new GbCuboid3D(  originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh-H3*0.5
+         //   , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.5));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP3(refine3PlatteCube, baseLevel, refineLevel-4);
+         //grid->accept(refineAdapterP3);
+
+         //GbCuboid3DPtr refine4PlatteCube(new GbCuboid3D(   originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.0
+         //   ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.25));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine4PlatteCube.get(), pathname+"/geo/refine4PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP4(refine4PlatteCube, baseLevel, refineLevel-3);
+         //grid->accept(refineAdapterP4);
+
+         //GbCuboid3DPtr refine5PlatteCube(new GbCuboid3D(   originX1-geoOverlap , originX2-geoOverlap  ,x3minMesh+deltaX3Platte*0.1/* x3minMesh+deltaX3Platte*0.8*/
+         //   ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.00375));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine5PlatteCube.get(), pathname+"/geo/refine5PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP5(refine5PlatteCube, baseLevel, refineLevel-2);
+         //grid->accept(refineAdapterP5);
+
+
+         //GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX1-3.0*geoOverlap
+         //	  , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.1));
+
+         GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.6/*0.55*/));
+
+         GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.49
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.53));
+
+         GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.9
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         GbCuboid3DPtr wallsX1X2maxRef1(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.95
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         if (refineLevel > 0)
+         {
+
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(wallsX1X2minRef3, refineLevel-1);
+            refineHelper.addGbObject(wallsX1X2minRef4, refineLevel);
+            refineHelper.addGbObject(wallsX1X2maxRef2, refineLevel-1);
+            refineHelper.addGbObject(wallsX1X2maxRef1, refineLevel);
+
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         ///interactoren
+         //int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+         //D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         ///////würfel unten version ende
+         ////////////////////////////////////////////////////////////////////////////////
+         ////////PM grid
+         //Temporär:
+         //double  H=1.0;
+
+         vector<D3Q27InteractorPtr> D3Q27InteractorPtrarray;
+         ////////////////////////////////////////////////////////////////////////////////
+         double inflowCubeDx = coarseNodeDx;///(double)(1<<inflowCubeLevel);
+         double dpCubes=(double)H/20.0;//100.0; //30zum testen 100real
+         double offsetZgrid=H+0.5*inflowCubeDx;
+         double epschoch1drittel= 0.928318;
+         double abstandIn=2.0*dpCubes;
+         double c1oAbst=1.0/abstandIn;
+         for (int Nflowdir=0;Nflowdir<((nx[0]*blocknx[0]*c1oAbst)*coarseNodeDx); Nflowdir++)
+         {
+            // for (int Nhorizon=((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5-2; Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5-1-1; Nhorizon++)
+            // {
+            //  for (int Nhorizon=0;  Nhorizon<(((nx[2]*blocknx[2]+1)*c1oAbst)*coarseNodeDx)*0.1; Nhorizon++)//Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5; Nhorizon++)
+            for (int Nhorizon=0;  Nhorizon<(((nx[2]*blocknx[2]+1)*c1oAbst)*coarseNodeDx)*0.5-1; Nhorizon++)//Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5; Nhorizon++)
+
+            {
+               for (int Nspanw=0; Nspanw<((nx[1]*blocknx[1]*c1oAbst)*coarseNodeDx); Nspanw++)
+               {
+                  // stringstream ss;
+                  //     ss<<"cubeH"<<Nflowdir<<"x"<<Nhorizon<<"x"<<Nspanw;
+                  ////     //   //geoOrigin ist Mitte, nicht vordere Ecke -> korrigieren
+                  // int Nflowdir=1;
+                  //int Nhorizon=0;
+                  //int Nspanw=1;
+                  double xminCubes1=originX1+(Nflowdir*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1);
+                  double xmaxCubes1=originX1+(Nflowdir*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1);
+                  double xminCubes=std::max(xminCubes1,2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double xmaxCubes=std::min(xmaxCubes1,originX1+geoLength[0]-coarseNodeDx/pow(2.0,refineLevel));
+                  double yminCubes=std::max(originX2+(Nspanw*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1),2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double ymaxCubes=std::min(originX2+(Nspanw*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1),originX2+geoLength[1]-coarseNodeDx/pow(2.0,refineLevel));
+                  double zminCubes=std::max(originX3+(Nhorizon*abstandIn)+4.0*coarseNodeDx/pow(2.0,refineLevel-1),2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double zmaxCubes=std::min(originX3+(Nhorizon*abstandIn)+dpCubes+4.0*coarseNodeDx/pow(2.0,refineLevel-1),originX3+geoLength[2]-coarseNodeDx/pow(2.0,refineLevel));
+                  ////     /*GbCuboid3D  *rectTemp = new GbCuboid3D(originX1+(Nflowdir*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, originX2+(Nspanw*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, originX3+(Nhorizon*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, 
+                  ////										 originX1+(Nflowdir*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx, originX2+(Nspanw*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx, originX3+(Nhorizon*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx );
+                  ////*/
+                  ////  
+                  GbCuboid3DPtr rectTemp(new GbCuboid3D(xminCubes, yminCubes, zminCubes, 
+                     xmaxCubes, ymaxCubes, zmaxCubes));
+                  ////
+                  //     ostringstream ostrcubes;
+                  //	 ostrcubes<<pathname <<"/cubeH"<<Nflowdir<<"x"<<Nhorizon<<"x"<<Nspanw;
+                  ////       
+                  ////   
+                  //// // GbSystem3D::writeGeoObject(rectTemp,outpath+cubeschar,WbWriterAvsASCII::getInstance());
+                  ////  GbSystem3D::writeGeoObject(rectTemp,ostrcubes.str(),WbWriterAvsASCII::getInstance()); //??
+                  //        ostrcubes.str("");
+                  //         ostrcubes.clear();
+
+                  ////  boost::shared_ptr<D3Q19AMRInteractor> interactorTemp( new D3Q19AMRInteractor( rectTemp,new D3Q19NoSlipBCAdapter(),AMR3DInteractor::SOLID,ss.str()) );
+                  //  //  interactorService.addInteractor(interactorTemp);
+                  D3Q27BoundaryConditionAdapterPtr cubeBCAdapter(new D3Q27NoSlipBCAdapter());                   //D3Q27DensityBCAdapter(rhoInit));
+                  D3Q27InteractorPtr cubeInteractor( new D3Q27Interactor(rectTemp,grid,cubeBCAdapter,Interactor3D::SOLID));
+                  D3Q27InteractorPtrarray.push_back(cubeInteractor);  
+
+
+               }
+            }}
+         ////////////////
+         //ende cubes
+         //////////
+         ////////////////////////////////////////////
+         //METIS
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+
+
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         SolidBlocksHelper sd(grid, comm);
+
+         sd.addInteractor(topBCInteractor);
+         sd.addInteractor(bottomBCInteractor);
+         for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+         {
+            sd.addInteractor(D3Q27InteractorPtrarray[i]);
+         }
+         sd.deleteSolidBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+         grid->accept( metisVisitor );
+
+         sd.setTransBlocks(); 
+
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+         unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+
+         double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+         // LBMKernel3DPtr kernel(new LBMKernelETD3Q27CascadedTI(blocknx[0], blocknx[1], blocknx[2]));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx[0], blocknx[1], blocknx[2],1));
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+         //	  //scheint neuerdings fuer absturz zu sorgen:
+         mu::Parser fctForcingX1;
+         fctForcingX1.SetExpr("Fx1*dx");
+         fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);//9.99685e-7);
+
+         kernel->setForcingX1(fctForcingX1);
+         kernel->setWithForcing(true); 
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+
+         grid->accept(kernelVisitor);
+
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+         //////////////////////////////////////////
+
+         grid->addAndInitInteractor( bottomBCInteractor ); 
+         grid->addAndInitInteractor( topBCInteractor );
+         for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+         {
+            grid->addAndInitInteractor( D3Q27InteractorPtrarray[i] ); 
+            char numstr[21];
+            sprintf(numstr, "%f", (double)i);
+            std::string pathObstCube = pathname+"/geo/obstBCCuboid"+ numstr;
+            if(myid == 0) GbSystem3D::writeGeoObject(D3Q27InteractorPtrarray[i]->getGbObject3D().get(),
+               /* rectTemp.get(),*/ pathObstCube, WbWriterVtkXmlASCII::getInstance());
+         }
+
+
+         UbTimer timer;
+         timer.start();
+         grid->accept( metisVisitor );
+
+         if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         if(myid == 0) ppblocks->update(0);
+         if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+
+         if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+         grid->accept( metisVisitor );
+         if(myid == 0) ppblocks->update(1);
+         ppblocks.reset();
+         if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+         //inflow
+         double uLB2=uLB;
+         double raiseVelSteps = 0;
+         vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("uLB*0.9"); 
+
+         inflowProfile.DefineConst("uLB",uLB2);
+         velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nueLB,rhoInit);
+         initVisitor.setVx1(inflowProfile);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         //LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter, comm, true));
+
+
+
+         grid->doPostProcess(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+
+      }
+
+
+
+      UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(100,1,1000);
+      //visSch->addSchedule(1000,1000,10000);
+      //visSch->addSchedule(10000,10000,100000);
+      //visSch->addSchedule(20000,20000,800000);
+      //visSch->addSchedule(50,350000,350500);
+      //visSch->addSchedule(50,420000,420500);
+      //visSch->addSchedule(50000,420500,10000000);
+      visSch->addSchedule(2250,268250,450001);
+      UbSchedulerPtr resSch(new UbScheduler());
+      resSch->addSchedule(20000,20,10000000);
+      // AverageValuesPostprocessor       Avpp(grid,  pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/,resSch/*wann wird resettet*/,comm);
+      UbSchedulerPtr resSchRMS(new UbScheduler());
+      resSchRMS->addSchedule(40000,420000,10000000);
+      UbSchedulerPtr resSchMeans(new UbScheduler());
+      resSchMeans->addSchedule(40000,0,10000000);
+      UbSchedulerPtr stepAvSch(new UbScheduler());
+      int averageInterval=20;
+      stepAvSch->addSchedule(averageInterval,0,10000000);
+
+      double restart=10000; //??????????
+      AverageValuesPostprocessor       Avpp(grid,  pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), stepAvSch/*wann wird gemittelt*/, averageInterval,visSch/*wann wird rausgeschrieben*/,resSchMeans,resSchRMS/*wann wird resettet*/,comm,restart);
+
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), unitConverter, comm);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 90050, 90080));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+
+      UbSchedulerPtr AdjForcSch(new UbScheduler());
+      AdjForcSch->addSchedule(100,20,20000000);
+      D3Q27IntegrateValuesHelperPtr IntValHelp(new D3Q27IntegrateValuesHelper(grid, comm, 
+         originX1, originX2, kanalhoeheSI*0.55/*0.501*/, 
+         nx[0]*blockLengthx1, nx[1]*blockLengthx2, kanalhoeheSI*0.999));
+
+      double vxZiel=uLB;
+      //D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel*0.6, comm);//da am 11.3.2013 velo um 1/0.6 zu hoch
+      D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel, comm);//dies sollte zu Re=5500 fuehren..
+
+      UbSchedulerPtr visQSch(new UbScheduler());
+      visQSch->addSchedule(10,90100,90130);
+      QKritPostprocessor QKritPtr(grid,pathname+"/steps/Qq",WbWriterVtkXmlBinary::getInstance(),visQSch, comm);
+
+      mu::Parser decrViscFunc;
+      decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");
+      decrViscFunc.DefineConst("nue0", nueLB);
+      decrViscFunc.DefineConst("c0", 0.1);
+      UbSchedulerPtr DecrViscSch(new UbScheduler());
+      DecrViscSch->addSchedule(10,10,1000);
+      DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch,&decrViscFunc, comm);
+
+      cout << "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe()<<endl;
+
+      double endTime = 2000000;//20000001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/bKanal2/CMakeLists.txt b/source/Applications/bKanal2/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c54f4ab348b51f05e4b16d498f1345e5c5cdbad0
--- /dev/null
+++ b/source/Applications/bKanal2/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bKanal2)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bKanal2 BINARY)
diff --git a/source/Applications/bKanal2/bKanal2.cpp b/source/Applications/bKanal2/bKanal2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b0175d1652f1ac4e3f0783364ef57b601169445
--- /dev/null
+++ b/source/Applications/bKanal2/bKanal2.cpp
@@ -0,0 +1,466 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <sys/types.h> //mkdir rights
+#include <sys/stat.h> //mkdir
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string pathname; 
+      string pathnameRestart;
+      int numOfThreads =1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      UbLog::reportingLevel() = logINFO;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr);
+
+      if(machine == "my") 
+      {
+         pathname = "d:/temp/BKanal";
+         numOfThreads = 4;
+         logfile = false;
+         availMem = 10.0e9;
+      }
+      else if(machine == "Ludwig")      
+      {
+         pathname =        "/work/koskuche/SFB880/BKanal";
+         pathnameRestart = "/work/koskuche/SFB880/BKanal";
+         numOfThreads = 8;
+         availMem = 1.0e9;
+         logfile = true;
+
+         if (myid==0) 
+         {
+            const char* str = pathname.c_str();
+#if defined(__unix__)
+            int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+#endif 
+         }
+
+         if(myid ==0)
+         {
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         }
+
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      if(myid ==0 && logfile)
+      {
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      UBLOG(logINFO,"Testcase BreugemChannel");
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      double Re    = 5500;
+      double uLB   = 0.1;  
+      double rhoLB = 0.0;
+
+      int blocknx[3];
+      blocknx[0] = 20;//10;//5;
+      blocknx[1] = 20;//10;//5;
+      blocknx[2] = 20;//10;//5;
+
+      int nx[3];
+      nx[0] = 15;
+      nx[1] = 10;
+      nx[2] = 10;
+
+      double coarseNodeDx = 1.0;
+      double H     = (double)(nx[2]*blocknx[2])/2.0;
+      double hLB   = H/coarseNodeDx;
+      double nuLB  = (uLB*hLB)/Re;
+
+      int baseLevel   = 0;
+      int refineLevel = 0;//2;//1;////3;//3 soll 1 test;
+
+      ///////////////Weltabmessungen:
+      double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+      double blockLengthx2 = blockLengthx1;
+      double blockLengthx3 = blockLengthx1;
+
+      double originX1 = 0.0;
+      double originX2 = 0.0;
+      double originX3 = 0.0;
+
+      //bounding box
+      double g_minX1 = originX1;
+      double g_minX2 = originX2;
+      double g_minX3 = originX3;
+
+      double g_maxX1 = originX1 + 3.0*H;
+      double g_maxX2 = originX2 + 2.0*H;
+      double g_maxX3 = originX3 + 2.0*H;
+
+      //double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      bool periodicx1 = true;
+      bool periodicx2 = true;
+      bool periodicx3 = false;
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(10000,10000,10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+      grid = rp.restart(-1);
+      //////////////////////////////////////////////////////////////////////////
+
+       if (grid->getTimeStep() == 0)
+       {
+
+         //set grid
+         grid->setDeltaX(coarseNodeDx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+
+
+         //bottom and top solid bc
+         //iteractors
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         double geoOverlap = coarseNodeDx;
+         GbCuboid3DPtr bottomBCCuboid(new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_minX3-blockLengthx1, g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(bottomBCCuboid.get(), pathname+"/geo/bottomBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr bottomBCInteractor(new D3Q27Interactor(bottomBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+
+         GbCuboid3DPtr topBCCuboid(new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_maxX3, g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1));
+         if(myid == 0) GbSystem3D::writeGeoObject(topBCCuboid.get(), pathname+"/geo/topBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr topBCInteractor(new D3Q27Interactor(topBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+         //grid->addAndInitInteractor( bottomBCInteractor ); 
+         // grid->addAndInitInteractor( topBCInteractor ); 
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            ="<<Re);
+            //UBLOG(logINFO, "* Ma            ="<<Ma);
+            //UBLOG(logINFO, "* uReal         ="<<uReal);
+            //UBLOG(logINFO, "* nueReal       ="<<nueReal);
+            UBLOG(logINFO, "* nue           ="<<nuLB);
+            UBLOG(logINFO, "* velocity      ="<<uLB);
+            // UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+            //  UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+            //UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+            UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+            //UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+            UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+            //UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+            //UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "* number of threads ="<<numOfThreads);
+            UBLOG(logINFO, "* number of processes ="<<comm->getNumberOfProcesses());
+            UBLOG(logINFO, "*****************************************");
+/*            UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+            UBLOG(logINFO, "*****************************************");  */   
+         }
+
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+
+         //////////////////////////////////////////////////////////////////////////
+         // refine
+         //////////////////////////////////////////////////////////////////////////
+         //GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.6/*0.55*/));
+
+         //GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.49
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.53));
+
+         //GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.9
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         //GbCuboid3DPtr wallsX1X2maxRef1(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.95
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         //if (refineLevel > 0)
+         //{
+
+         //   RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+         //   refineHelper.addGbObject(wallsX1X2minRef3, refineLevel-1);
+         //   refineHelper.addGbObject(wallsX1X2minRef4, refineLevel);
+         //   refineHelper.addGbObject(wallsX1X2maxRef2, refineLevel-1);
+         //   refineHelper.addGbObject(wallsX1X2maxRef1, refineLevel);
+
+         //   refineHelper.refine();
+         //   if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         //}
+
+         ///interactoren
+         //int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+         //D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         ///////würfel unten version ende
+         ////////////////////////////////////////////////////////////////////////////////
+         ////////PM grid
+         //Temporär:
+         //double  H=1.0;
+
+         vector<D3Q27InteractorPtr> D3Q27InteractorPtrarray;
+         ////////////////////////////////////////////////////////////////////////////////
+         double dpCubes=(double)H/20.0;
+         double distanceXY=dpCubes/2.0-coarseNodeDx*0.5;
+         double distanceZ=0;
+   
+         for (int x = 0; x<30; x++)
+            for (int y = 0; y<20; y++)
+               for (int z = 0; z<9; z++)
+               {
+                  double xminCubes = originX1+distanceXY+2.0*dpCubes*x;
+                  double yminCubes = originX2+distanceXY+2.0*dpCubes*y;
+                  double zminCubes = originX3+distanceZ+2.0*dpCubes*z;
+                  double xmaxCubes = xminCubes+dpCubes;
+                  double ymaxCubes = yminCubes+dpCubes;
+                  double zmaxCubes = zminCubes+dpCubes;
+                  GbCuboid3DPtr rectTemp(new GbCuboid3D(xminCubes, yminCubes, zminCubes, xmaxCubes, ymaxCubes, zmaxCubes));
+                  D3Q27BoundaryConditionAdapterPtr cubeBCAdapter(new D3Q27NoSlipBCAdapter());                   
+                  D3Q27InteractorPtr cubeInteractor( new D3Q27Interactor(rectTemp,grid,cubeBCAdapter,Interactor3D::SOLID));
+                  D3Q27InteractorPtrarray.push_back(cubeInteractor); 
+               }
+
+         ////////////////
+         //ende cubes
+         //////////
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(topBCInteractor);
+         intHelper.addInteractor(bottomBCInteractor);
+         for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+         {
+            intHelper.addInteractor(D3Q27InteractorPtrarray[i]);
+         }
+         intHelper.selectBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         if(myid == 0) ppblocks->update(0);
+         if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+         unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+
+         double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+     
+         mu::Parser fctForcingX1;
+         fctForcingX1.SetExpr("Fx1*dx");
+         fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);//9.99685e-7);
+
+         kernel->setForcingX1(fctForcingX1);
+         kernel->setWithForcing(true); 
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+         //////////////////////////////////////////
+         intHelper.setBC();
+
+         for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+         {
+            grid->addAndInitInteractor( D3Q27InteractorPtrarray[i] ); 
+            char numstr[21];
+            sprintf(numstr, "%f", (double)i);
+            std::string pathObstCube = pathname+"/geo/obstBCCuboid"+ numstr;
+            if(myid == 0) GbSystem3D::writeGeoObject(D3Q27InteractorPtrarray[i]->getGbObject3D().get(),
+               /* rectTemp.get(),*/ pathObstCube, WbWriterVtkXmlASCII::getInstance());
+         }
+
+
+         ppblocks.reset();
+
+         //inflow
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("uLB*0.9"); 
+         inflowProfile.DefineConst("uLB",uLB);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nuLB,rhoLB);
+         initVisitor.setVx1(inflowProfile);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter,true));
+
+         ppgeo->update(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+
+      }
+            else
+            {
+               //set forcing
+               mu::Parser fctForcingX1, fctForcingX2, fctForcingX3;
+               fctForcingX1.SetExpr("Fx1*dx");
+               fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);
+               fctForcingX2.SetExpr("0.0");
+               fctForcingX3.SetExpr("0.0");
+               SetForcingBlockVisitor forcingVisitor(fctForcingX1, fctForcingX2, fctForcingX3);
+               grid->accept(forcingVisitor);
+
+               //set connectors
+               D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+               D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+               grid->accept( setConnsVisitor );
+               if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      }
+
+
+      UbSchedulerPtr visSch(new UbScheduler());
+      visSch->addSchedule(100,100,1000);
+      visSch->addSchedule(1000,1000,10000);
+      visSch->addSchedule(10000,10000,100000);
+      //visSch->addSchedule(20000,20000,800000);
+      //visSch->addSchedule(50,350000,350500);
+      //visSch->addSchedule(50,420000,420500);
+      //visSch->addSchedule(50000,420500,10000000);
+      //visSch->addSchedule(2250,140000,450001);
+      //UbSchedulerPtr resSch(new UbScheduler());
+      //resSch->addSchedule(20000,20,10000000);
+      //UbSchedulerPtr resSchRMS(new UbScheduler());
+      //resSchRMS->addSchedule(40000,420000,10000000);
+      //UbSchedulerPtr resSchMeans(new UbScheduler());
+      //resSchMeans->addSchedule(40000,0,10000000);
+      //UbSchedulerPtr stepAvSch(new UbScheduler());
+      //stepAvSch->addSchedule(20,0,10000000);
+      //AverageValuesPostprocessor Avpp(grid, pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), 
+      //                                visSch/*wann wird rausgeschrieben*/, stepAvSch/*wann wird gemittelt*/, resSchMeans, resSchRMS/*wann wird resettet*/);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+
+      UbSchedulerPtr AdjForcSch(new UbScheduler());
+      AdjForcSch->addSchedule(100,100,20000000);
+      //D3Q27IntegrateValuesHelperPtr IntValHelp(new D3Q27IntegrateValuesHelper(grid, comm, 
+      //   originX1, originX2, kanalhoeheSI*0.55/*0.501*/, 
+      //   nx[0]*blockLengthx1, nx[1]*blockLengthx2, kanalhoeheSI*0.999));
+      D3Q27IntegrateValuesHelperPtr IntValHelp(new D3Q27IntegrateValuesHelper(grid, comm, 
+         originX1, originX2, g_maxX3*0.55/*0.501*/, 
+         g_maxX1, g_maxX2, g_maxX3*0.999));
+
+      double vxZiel=uLB;
+      //D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel*0.6, comm);//da am 11.3.2013 velo um 1/0.6 zu hoch
+      D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel, comm);//dies sollte zu Re=5500 fuehren..
+
+      UbSchedulerPtr visQSch(new UbScheduler());
+      visQSch->addSchedule(10,90100,90130);
+      QCriterionPostprocessor QKritPtr(grid,pathname+"/steps/Qq",WbWriterVtkXmlBinary::getInstance(),visQSch, comm);
+
+      //mu::Parser decrViscFunc;
+      //decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");
+      //decrViscFunc.DefineConst("nue0", nuLB);
+      //decrViscFunc.DefineConst("c0", 0.1);
+      //UbSchedulerPtr DecrViscSch(new UbScheduler());
+      //DecrViscSch->addSchedule(10,10,1000);
+      //DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch,&decrViscFunc, comm);
+
+      cout << "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe()<<endl;
+
+      double endTime = 2000000;//20000001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/bKanalAv/CMakeLists.txt b/source/Applications/bKanalAv/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5ea13434aa29131f70b73a83f385085e5995e85f
--- /dev/null
+++ b/source/Applications/bKanalAv/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bKanalAv)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bKanalAv BINARY)
diff --git a/source/Applications/bKanalAv/bKanal.cpp b/source/Applications/bKanalAv/bKanal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..28f3456abe6d47603ee857e2d64e7fd8940c0ce3
--- /dev/null
+++ b/source/Applications/bKanalAv/bKanal.cpp
@@ -0,0 +1,738 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <sys/types.h> //mkdir rights
+#include <sys/stat.h> //mkdir
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      UBLOG(logINFO,"Testcase BreugemChannel");
+      string pathname; 
+      string pathnameRestart;
+      string pathGeo;
+      int numOfThreads =1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      UbLog::reportingLevel() = logINFO;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+
+         pathname =        "./";
+         //pathnameRestart = "/gfs1/work/niivfcpu/scratch/kucher/BKanaltest";//BKanaltest0Ref2up0612";//BKanaltest0Ref2up1012Out";
+         //pathname =        "/work/koskuche/SFB880/BKanaltestRe260000Out";
+         //pathnameRestart = "/work/koskuche/SFB880/BKanaltestRe260000";//BKanaltest0Ref2up0612";//BKanaltest0Ref2up1012Out";
+
+   	 //pathGeo = "/home/koskuche/data/plate";
+         numOfThreads = 1;
+         availMem = 64.0e9;
+         logfile = true;
+
+//         if (myid==0) 
+//         {
+//            const char* str = pathname.c_str();
+//#if defined(__unix__)
+//            int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+//#endif 
+//
+//         }
+//
+//         if(myid ==0)
+//         {
+//            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+//         }
+
+
+
+
+      //if(myid ==0 && logfile)
+      //{
+      UbLog::output_policy::setStream(logFilename.str());
+      //}
+
+      int baseLevel, refineLevel,nx[3],blocknx[3];
+      double Re,velocity,rhoInit,vx1Init;//,vx2Init,vx3Init;
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      Re            = 5500;// 13286;//13286;//gemessen 18.98 m/s...*5.0 zum  testen ob was passiert
+      velocity      = 0.01;  
+      vx1Init       = 0.01;  
+      rhoInit       = 0.0;
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+
+      int H=200;//200;//392;
+
+      //  nx[0]      =8;//ok mit 8// (int)(3.0*(double)H/8.0/8.0);//2;// (int)(0.3*(double)H/6.0/4.0);//das "/4" hier ist wegen der verfeinerung da! //länge
+      //  nx[1]      =8;//ok mit 8// (int)(2.0*(double)H/8.0/8.0);//2;// (int)(0.2*(double)H/6.0/4.0);//  //breite
+      nx[2]      = (int)(2.0*(double)H/5.0/8.0);// //höhe gebiet
+
+      //(3/2/2)-ratio:
+      nx[1]=nx[2];
+      nx[0]=15;
+
+      blocknx[0] = 15;//10;//5;
+      blocknx[1] = 15;//10;//5;
+      blocknx[2] = 15;//10;//5;
+
+      baseLevel   = 0;
+      refineLevel = 2;//1;////3;//3 soll 1 test;
+
+
+      ///////////////Weltabmessungen:
+      //double kanallaengeSI = ( 2.0*(double)H);
+      // double kanalbreiteSI = ( 1.0*(double)H);
+      double kanalhoeheSI  = ( 2.0*(double)H);
+
+      // double refinewidth1=kanalhoeheSI/10.0;
+
+      double fineNodeDx   = (kanalhoeheSI) / (double)( blocknx[2]*nx[2]*(1<<refineLevel)+1 ); //+1--> gitter liegt jeweils 0.5dx innerhalb
+      double coarseNodeDx = fineNodeDx * (double)(1<<refineLevel);//geowerte
+
+      double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+      double blockLengthx2 = blockLengthx1;
+      double blockLengthx3 = blockLengthx1;
+
+      double originX1 = 0.0;//-50.0*propellerDurchmesser;  //geowerte
+      double originX2 = 0.0;//-0.5*blockLengthx2*nx2;
+      double originX3 = 0.0;// minX3 + 0.5*fineNodeDx;
+
+      double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      bool periodicx1 = true;
+      bool periodicx2 = true;
+      bool periodicx3 = false;
+
+
+      //##########################################################################
+      //## physical parameters
+      //##########################################################################
+      double smagorinskiConstant = 0.18;
+
+
+      double rhoLB         = 0.0;
+
+      double rhoReal       = 1.0;
+      double nueReal  = 1;//0.000016;//0.015;
+
+      double hReal         = blocknx[2]*nx[2];//H*0.9;//0.0105;//<-m     1.05;//Plattendicke in cm(! cm nicht m !)
+      double uReal         = Re*nueReal/hReal;
+
+      //##Machzahl:
+      //#Ma     = uReal/csReal
+      double csReal=343.0;
+      double Ma      = uReal/csReal;//Ma-Real!
+      //double csReal  = uReal/Ma;
+      double hLB     = hReal/coarseNodeDx;
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(hReal, csReal, rhoReal, hLB));
+
+      double uLB           = uReal   * unitConverter->getFactorVelocityWToLb();
+      double nueLB         = nueReal * unitConverter->getFactorViscosityWToLb();
+      double timestep      = unitConverter->getFactorTimeLbToW(coarseNodeDx);
+
+      velocity = uLB;
+      // double viscosity =nueLB*1000.0;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      //UbSchedulerPtr rSch(new UbScheduler(10000,100000,30000000000));//(50000,50000,1000000));
+      //UbSchedulerPtr rSch(new UbScheduler(18000,268250,770000));//(50000,50000,1000000));
+      //RestartPostprocessor rp(grid, rSch, comm, pathnameRestart+"/checkpoints", RestartPostprocessor::BINARY);
+
+      //////////////////////////////////////////////////////////////////////////
+
+      std::string opt;
+
+//      if(cstr!= NULL)
+//         opt = std::string(cstr);
+//
+//      if(/*(cstr== NULL)*/cstr!= NULL)
+//      {
+//         opt = std::string(cstr);
+//
+//         if(myid==0) {
+//            UBLOG(logINFO,"Restart step: " << opt);
+//            UBLOG(logINFO, "Restart=:" << pathnameRestart);
+//         }
+//
+//         grid = rp.restart(UbSystem::stringTo<int>(opt));
+//         rp.reconnect(grid);
+//
+////          mu::Parser fctForcingX1, fctForcingX2, fctForcingX3;
+////          fctForcingX1.SetExpr("Fx1*dx");
+////          fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);
+//// 
+////          SetForcingBlockVisitor forcingVisitor(fctForcingX1, fctForcingX2, fctForcingX3);
+////          grid->accept(forcingVisitor);
+//
+//         //set connectors
+//         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+//         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+//         grid->accept( setConnsVisitor );
+//
+//      }
+//      else
+//      {
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];
+
+         //set grid
+         grid->setDeltaX(coarseNodeDx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         //GenBlocksGridVisitor genBlocks;
+         //genBlocks.addGeoObject(gridCube);
+         //grid->accept(genBlocks);
+
+
+
+         //bottom and top solid bc
+         //iteractors
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         double geoOverlap = coarseNodeDx;
+         GbCuboid3DPtr bottomBCCuboid(new GbCuboid3D(originX1-geoOverlap, originX2-geoOverlap, originX3-geoOverlap, 
+            originX1+geoLength[0]+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(bottomBCCuboid.get(), pathname+"/geo/bottomBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr bottomBCInteractor(new D3Q27Interactor(bottomBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+
+         GbCuboid3DPtr topBCCuboid(new GbCuboid3D(originX1-geoLength[0]-coarseNodeDx, originX2-geoOverlap, originX3+geoLength[2],//-coarseNodeDx*0.5, 
+            originX1+geoLength[0]+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap));
+         if(myid == 0) GbSystem3D::writeGeoObject(topBCCuboid.get(), pathname+"/geo/topBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr topBCInteractor(new D3Q27Interactor(topBCCuboid,grid,bcObst,Interactor3D::SOLID)); 
+         //grid->addAndInitInteractor( bottomBCInteractor ); 
+         // grid->addAndInitInteractor( topBCInteractor ); 
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            ="<<Re);
+            UBLOG(logINFO, "* Ma            ="<<Ma);
+            UBLOG(logINFO, "* uReal         ="<<uReal);
+            UBLOG(logINFO, "* nueReal       ="<<nueReal);
+            UBLOG(logINFO, "* nue           ="<<nueLB);
+            UBLOG(logINFO, "* velocity      ="<<uLB);
+            // UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+            //  UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+            UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+            UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+            UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+            UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+            UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+            UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "*****************************************");
+            UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+            UBLOG(logINFO, "*****************************************");     
+         }
+
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+
+         //////////////////////////////////////////////////////////////////////////
+         // refine
+         //////////////////////////////////////////////////////////////////////////
+         //GbCuboid3DPtr wallsX1X2maxRef1( new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI*0.95
+         //    , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax1(wallsX1X2maxRef1, 0,refineLevel-3);
+         //grid->accept(refineVisitormax1);
+         //
+         //GbCuboid3DPtr wallsX1X2minRef1(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI*0.55
+         //    , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.47));
+         // RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin1(wallsX1X2minRef1, 0,refineLevel-3);
+         // grid->accept(refineVisitormin1);
+
+         //   GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.98));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax2(wallsX1X2maxRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormax2);
+         //   GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.9));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax2(wallsX1X2maxRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormax2);
+
+         // GbCuboid3DPtr wallsX1X2maxRef3(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , kanalhoeheSI
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.9995));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormax3(wallsX1X2maxRef3, 0,refineLevel-1);
+         //grid->accept(refineVisitormax3);
+
+         //         GbCuboid3DPtr wallsX1X2minRefl3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.25));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitorminl3(wallsX1X2minRefl3, 0,refineLevel-3);
+         //grid->accept(refineVisitorminl3);
+         /////würfel unten version
+         //      GbCuboid3DPtr wallsX1X2minRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.2));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin2(wallsX1X2minRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormin2);
+
+         //   GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , kanalhoeheSI*0.04
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.18));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin3(wallsX1X2minRef3, 0,refineLevel-1);
+         //grid->accept(refineVisitormin3);
+
+         //      GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , kanalhoeheSI*0.09
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.16));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel);
+         //grid->accept(refineVisitormin4);
+
+
+
+
+         /////würfel anfang version
+         //       GbCuboid3DPtr wallsX1X2minRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.56));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin2(wallsX1X2minRef2, 0,refineLevel-2);
+         //grid->accept(refineVisitormin2);
+
+         //   GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.55));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin3(wallsX1X2minRef3, 0,refineLevel-2);
+         //grid->accept(refineVisitormin3);
+
+         //      GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.49
+         //   , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.53));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel-1);
+         //grid->accept(refineVisitormin4);
+
+
+         /*           GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX1-3.0*geoOverlap
+         , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.1));
+         RefineCrossAndInsideGbObjectBlockVisitor refineVisitormin4(wallsX1X2minRef4, 0,refineLevel-1);
+         grid->accept(refineVisitormin4);*/
+
+         ////GbCuboid3DPtr refine1PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3
+         ////   , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+         ////RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP1(refine1PlatteCube, baseLevel, refineLevel-6);
+         ////grid->accept(refineAdapterP1);
+
+         //GbCuboid3DPtr refine2PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3*0.5
+         //  , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP2(refine2PlatteCube, baseLevel, refineLevel-5);
+         //grid->accept(refineAdapterP2);
+
+         //GbCuboid3DPtr refine3PlatteCube(new GbCuboid3D(  originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh-H3*0.5
+         //   , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.5));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP3(refine3PlatteCube, baseLevel, refineLevel-4);
+         //grid->accept(refineAdapterP3);
+
+         //GbCuboid3DPtr refine4PlatteCube(new GbCuboid3D(   originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.0
+         //   ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.25));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine4PlatteCube.get(), pathname+"/geo/refine4PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP4(refine4PlatteCube, baseLevel, refineLevel-3);
+         //grid->accept(refineAdapterP4);
+
+         //GbCuboid3DPtr refine5PlatteCube(new GbCuboid3D(   originX1-geoOverlap , originX2-geoOverlap  ,x3minMesh+deltaX3Platte*0.1/* x3minMesh+deltaX3Platte*0.8*/
+         //   ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.00375));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine5PlatteCube.get(), pathname+"/geo/refine5PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP5(refine5PlatteCube, baseLevel, refineLevel-2);
+         //grid->accept(refineAdapterP5);
+
+
+         //GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX1-3.0*geoOverlap
+         //	  , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.1));
+
+         GbCuboid3DPtr wallsX1X2minRef3(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX3-3.0*geoOverlap
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.6/*0.55*/));
+
+         GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.49
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.53));
+
+         GbCuboid3DPtr wallsX1X2maxRef2(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.9
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         GbCuboid3DPtr wallsX1X2maxRef1(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  ,kanalhoeheSI*0.95
+            , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoOverlap+geoLength[2]));
+
+         //if (refineLevel > 0)
+         //{
+
+         //   RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+         //   refineHelper.addGbObject(wallsX1X2minRef3, refineLevel-1);
+         //   refineHelper.addGbObject(wallsX1X2minRef4, refineLevel);
+         //   refineHelper.addGbObject(wallsX1X2maxRef2, refineLevel-1);
+         //   refineHelper.addGbObject(wallsX1X2maxRef1, refineLevel);
+
+         //   refineHelper.refine();
+         //   if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         //}
+
+         ///interactoren
+         //int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+         //D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         ///////würfel unten version ende
+         ////////////////////////////////////////////////////////////////////////////////
+         ////////PM grid
+         //Temporär:
+         //double  H=1.0;
+
+         //vector<D3Q27InteractorPtr> D3Q27InteractorPtrarray;
+         
+         double newDx = fineNodeDx;///2.0;
+         int geoNX1=(int)(600.0/newDx)-1; 
+         int geoNX2=(int)(400.0/newDx)-1; 
+         int geoNX3=(int)((398.0+newDx*2)/newDx); 
+         GbVoxelMatrix3D geoMatrix(geoNX1,geoNX2,geoNX3,0);
+         geoMatrix.setVoxelMatrixDelta(newDx, newDx, newDx);
+         double m_minX1 = 0 - newDx/2.0;
+         double m_minX2 = 0 - newDx/2.0;
+         double m_minX3 = 0.666 + newDx/2.0;
+         geoMatrix.setVoxelMatrixMininum(m_minX1, m_minX2, m_minX3);
+
+         //geoMatrix.writeToVTKImageDataASCII(pathname + "/geo/geoMatrix");
+         //return;
+
+         CoordinateTransformation3D trafo(m_minX1, m_minX2, m_minX3, newDx, newDx, newDx);
+
+         ////////////////////////////////////////////////////////////////////////////////
+         double inflowCubeDx = coarseNodeDx;///(double)(1<<inflowCubeLevel);
+         double dpCubes=(double)H/20.0;//100.0; //30zum testen 100real
+         double offsetZgrid=H+0.5*inflowCubeDx;
+         double epschoch1drittel= 0.928318;
+         double abstandIn=2.0*dpCubes;
+         double c1oAbst=1.0/abstandIn;
+         
+         UBLOG(logINFO,"cubes:start");
+         
+         for (int Nflowdir=0;Nflowdir<((nx[0]*blocknx[0]*c1oAbst)*coarseNodeDx); Nflowdir++)
+         {
+            // for (int Nhorizon=((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5-2; Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5-1-1; Nhorizon++)
+            // {
+            //  for (int Nhorizon=0;  Nhorizon<(((nx[2]*blocknx[2]+1)*c1oAbst)*coarseNodeDx)*0.1; Nhorizon++)//Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5; Nhorizon++)
+            for (int Nhorizon=0;  Nhorizon<(((nx[2]*blocknx[2]+1)*c1oAbst)*coarseNodeDx)*0.5-1; Nhorizon++)//Nhorizon<((nx[2]*blocknx[2]*c1oAbst)*coarseNodeDx)*0.5; Nhorizon++)
+
+            {
+               for (int Nspanw=0; Nspanw<((nx[1]*blocknx[1]*c1oAbst)*coarseNodeDx); Nspanw++)
+               {
+                  // stringstream ss;
+                  //     ss<<"cubeH"<<Nflowdir<<"x"<<Nhorizon<<"x"<<Nspanw;
+                  ////     //   //geoOrigin ist Mitte, nicht vordere Ecke -> korrigieren
+                  // int Nflowdir=1;
+                  //int Nhorizon=0;
+                  //int Nspanw=1;
+                  double xminCubes1=originX1+(Nflowdir*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1);
+                  double xmaxCubes1=originX1+(Nflowdir*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1);
+                  double xminCubes=std::max(xminCubes1,2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double xmaxCubes=std::min(xmaxCubes1,originX1+geoLength[0]-coarseNodeDx/pow(2.0,refineLevel));
+                  double yminCubes=std::max(originX2+(Nspanw*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1),2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double ymaxCubes=std::min(originX2+(Nspanw*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx+3.0*coarseNodeDx/pow(2.0,refineLevel-1),originX2+geoLength[1]-coarseNodeDx/pow(2.0,refineLevel));
+                  double zminCubes=std::max(originX3+(Nhorizon*abstandIn)+4.0*coarseNodeDx/pow(2.0,refineLevel-1),2.0*coarseNodeDx/pow(2.0,refineLevel));
+                  double zmaxCubes=std::min(originX3+(Nhorizon*abstandIn)+dpCubes+4.0*coarseNodeDx/pow(2.0,refineLevel-1),originX3+geoLength[2]-coarseNodeDx/pow(2.0,refineLevel));
+                  ////     /*GbCuboid3D  *rectTemp = new GbCuboid3D(originX1+(Nflowdir*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, originX2+(Nspanw*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, originX3+(Nhorizon*abstandIn)-0.5*dpCubes+0.5*inflowCubeDx, 
+                  ////										 originX1+(Nflowdir*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx, originX2+(Nspanw*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx, originX3+(Nhorizon*abstandIn)+0.5*dpCubes+0.5*inflowCubeDx );
+                  ////*/
+                  ////  
+                  //GbCuboid3DPtr rectTemp(new GbCuboid3D(xminCubes, yminCubes, zminCubes, xmaxCubes, ymaxCubes, zmaxCubes));
+
+                  double x1min = trafo.transformForwardToX1Coordinate( xminCubes, yminCubes, zminCubes );
+                  double x2min = trafo.transformForwardToX2Coordinate( xminCubes, yminCubes, zminCubes );
+                  double x3min = trafo.transformForwardToX3Coordinate( xminCubes, yminCubes, zminCubes );
+
+                  int ix1min, ix2min, ix3min; 
+
+                  if (x1min-(int)x1min>.9999999999) ix1min=(int)x1min+1;else ix1min=(int)x1min; 
+                  if (x2min-(int)x2min>.9999999999) ix2min=(int)x2min+1;else ix2min=(int)x2min; 
+                  if (x3min-(int)x3min>.9999999999) ix3min=(int)x3min+1;else ix3min=(int)x3min; 
+
+                  double x1max = trafo.transformForwardToX1Coordinate( xmaxCubes, ymaxCubes, zmaxCubes );
+                  double x2max = trafo.transformForwardToX2Coordinate( xmaxCubes, ymaxCubes, zmaxCubes );
+                  double x3max = trafo.transformForwardToX3Coordinate( xmaxCubes, ymaxCubes, zmaxCubes );
+
+                  int ix1max, ix2max, ix3max; 
+
+                  if (x1max-(int)x1max>.9999999999) ix1max=(int)x1max+1;else ix1max=(int)x1max; 
+                  if (x2max-(int)x2max>.9999999999) ix2max=(int)x2max+1;else ix2max=(int)x2max; 
+                  if (x3max-(int)x3max>.9999999999) ix3max=(int)x3max+1;else ix3max=(int)x3max; 
+
+                  for (int z = ix3min+1; z <= ix3max; z++)
+                     for (int y = ix2min+1; y <= ix2max; y++)
+                        for (int x = ix1min+1; x <= ix1max; x++)
+                  {
+                     geoMatrix(x,y,z)=GbVoxelMatrix3D::SOLID;
+                  }
+
+
+                  ////
+                  //     ostringstream ostrcubes;
+                  //	 ostrcubes<<pathname <<"/cubeH"<<Nflowdir<<"x"<<Nhorizon<<"x"<<Nspanw;
+                  ////       
+                  ////   
+                  //// // GbSystem3D::writeGeoObject(rectTemp,outpath+cubeschar,WbWriterAvsASCII::getInstance());
+                  ////  GbSystem3D::writeGeoObject(rectTemp,ostrcubes.str(),WbWriterAvsASCII::getInstance()); //??
+                  //        ostrcubes.str("");
+                  //         ostrcubes.clear();
+
+                  ////  boost::shared_ptr<D3Q19AMRInteractor> interactorTemp( new D3Q19AMRInteractor( rectTemp,new D3Q19NoSlipBCAdapter(),AMR3DInteractor::SOLID,ss.str()) );
+                  //  //  interactorService.addInteractor(interactorTemp);
+                  //D3Q27BoundaryConditionAdapterPtr cubeBCAdapter(new D3Q27NoSlipBCAdapter());                   //D3Q27DensityBCAdapter(rhoInit));
+                  //D3Q27InteractorPtr cubeInteractor( new D3Q27Interactor(rectTemp,grid,cubeBCAdapter,Interactor3D::SOLID));
+                  //D3Q27InteractorPtrarray.push_back(cubeInteractor);  
+
+
+               }
+            }}
+         ////////////////
+         //ende cubes
+         //////////
+         UBLOG(logINFO,"cubes:end");
+
+         UBLOG(logINFO,"write geo matrix:start");
+         //geoMatrix.writeToLegacyVTKBinary(pathname + "/geo/geoMatrix");
+         geoMatrix.writeToVTKImageDataASCII(pathname + "/geo/geoMatrix");
+         UBLOG(logINFO,"write geo matrix:end");
+
+         ////////////////////////////////////////////
+      //   //METIS
+      //   MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+      //   grid->accept( metisVisitor );
+
+
+      //   ////////////////////////////////////////////
+      //   /////delete solid blocks
+      //   if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+      //   SolidBlocksHelper sd(grid, comm);
+
+      //   sd.addInteractor(topBCInteractor);
+      //   sd.addInteractor(bottomBCInteractor);
+      //   for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+      //   {
+      //      sd.addInteractor(D3Q27InteractorPtrarray[i]);
+      //   }
+      //   sd.deleteSolidBlocks();
+      //   if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+      //   //////////////////////////////////////
+      //   grid->accept( metisVisitor );
+
+      //   sd.setTransBlocks(); 
+
+
+      //   unsigned long nob = grid->getNumberOfBlocks();
+      //   unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+      //   unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+
+      //   double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+      //   double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      //   if(myid == 0)
+      //   {
+      //      UBLOG(logINFO,"Number of blocks = " << nob);
+      //      UBLOG(logINFO,"Number of nodes  = " << nod);
+      //      UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+      //      UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+      //      UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      //   }
+
+      //   LBMKernel3DPtr kernel;
+      //   kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+      //   // LBMKernel3DPtr kernel(new LBMKernelETD3Q27CascadedTI(blocknx[0], blocknx[1], blocknx[2]));
+      //   //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx[0], blocknx[1], blocknx[2],1));
+      //   BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      //   kernel->setBCProcessor(bcProc);
+      //   //	  //scheint neuerdings fuer absturz zu sorgen:
+      //   mu::Parser fctForcingX1;
+      //   fctForcingX1.SetExpr("Fx1*dx");
+      //   fctForcingX1.DefineConst("Fx1", 0.6*5.0e-6);//9.99685e-7);
+
+      //   kernel->setForcingX1(fctForcingX1);
+      //   kernel->setWithForcing(true); 
+
+      //   SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+
+      //   grid->accept(kernelVisitor);
+
+      //   //////////////////////////////////
+      //   //undef nodes
+      //   if (refineLevel > 0)
+      //   {
+      //      D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+      //      grid->accept(undefNodesVisitor);
+      //   }
+      //   //////////////////////////////////////////
+
+      //   grid->addAndInitInteractor( bottomBCInteractor ); 
+      //   grid->addAndInitInteractor( topBCInteractor );
+      //   for(size_t i=0; i<D3Q27InteractorPtrarray.size(); ++i)
+      //   {
+      //      grid->addAndInitInteractor( D3Q27InteractorPtrarray[i] ); 
+      //      char numstr[21];
+      //      sprintf(numstr, "%f", (double)i);
+      //      std::string pathObstCube = pathname+"/geo/obstBCCuboid"+ numstr;
+      //      if(myid == 0) GbSystem3D::writeGeoObject(D3Q27InteractorPtrarray[i]->getGbObject3D().get(),
+      //         /* rectTemp.get(),*/ pathObstCube, WbWriterVtkXmlASCII::getInstance());
+      //   }
+
+
+      //   UbTimer timer;
+      //   timer.start();
+      //   grid->accept( metisVisitor );
+
+      //   if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+      //   BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+      //   if(myid == 0) ppblocks->update(0);
+      //   if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+
+      //   if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+      //   grid->accept( metisVisitor );
+      //   if(myid == 0) ppblocks->update(1);
+      //   ppblocks.reset();
+      //   if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+      //   //inflow
+      //   double uLB2=uLB;
+      //   double raiseVelSteps = 0;
+      //   vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+      //   mu::Parser inflowProfile;
+      //   inflowProfile.SetExpr("uLB*0.9"); 
+
+      //   inflowProfile.DefineConst("uLB",uLB2);
+      //   velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+
+      //   //set connectors
+      //   D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      //   D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      //   grid->accept( setConnsVisitor );
+
+      //   //domain decomposition
+
+      //   //initialization of decompositions
+      //   D3Q27ETInitDistributionsBlockVisitor initVisitor( nueLB,rhoInit);
+      //   initVisitor.setVx1(inflowProfile);
+      //   grid->accept(initVisitor);
+
+      //   //Postrozess
+      //   //LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      //   UbSchedulerPtr geoSch(new UbScheduler(1));
+      //   D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+      //      new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), 
+      //      unitConverter, comm, true));
+
+
+
+      //   grid->doPostProcess(0);
+      //   ppgeo.reset();
+      //   geoSch.reset();
+
+      //   if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+
+      //}
+
+
+
+      //UbSchedulerPtr visSch(new UbScheduler());
+      ////visSch->addSchedule(100,1,1000);
+      ////visSch->addSchedule(1000,1000,10000);
+      ////visSch->addSchedule(10000,10000,100000);
+      ////visSch->addSchedule(20000,20000,800000);
+      ////visSch->addSchedule(50,350000,350500);
+      ////visSch->addSchedule(50,420000,420500);
+      ////visSch->addSchedule(50000,420500,10000000);
+      //visSch->addSchedule(2250,268250,592250);
+      //UbSchedulerPtr resSch(new UbScheduler());
+      //resSch->addSchedule(20000,20,10000000);
+      //// AverageValuesPostprocessor       Avpp(grid,  pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/,resSch/*wann wird resettet*/,comm);
+      //UbSchedulerPtr resSchRMS(new UbScheduler());
+      //resSchRMS->addSchedule(40000,420000,10000000);
+      //UbSchedulerPtr resSchMeans(new UbScheduler());
+      //resSchMeans->addSchedule(40000,0,10000000);
+      //UbSchedulerPtr stepAvSch(new UbScheduler());
+      //int averageInterval=20;
+      //stepAvSch->addSchedule(averageInterval,0,10000000);
+
+      //double restart=10000; //??????????
+      //AverageValuesPostprocessor       Avpp(grid,  pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), stepAvSch/*wann wird gemittelt*/, averageInterval,visSch/*wann wird rausgeschrieben*/,resSchMeans,resSchRMS/*wann wird resettet*/,comm,restart);
+
+
+      //D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), unitConverter, comm);
+
+      //UbSchedulerPtr nupsSch(new UbScheduler(10, 90050, 90080));
+      //NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+
+      //UbSchedulerPtr AdjForcSch(new UbScheduler());
+      //AdjForcSch->addSchedule(100,20,20000000);
+      //D3Q27IntegrateValuesHelperPtr IntValHelp(new D3Q27IntegrateValuesHelper(grid, comm, 
+      //   originX1, originX2, kanalhoeheSI*0.55/*0.501*/, 
+      //   nx[0]*blockLengthx1, nx[1]*blockLengthx2, kanalhoeheSI*0.999));
+
+      //double vxZiel=uLB;
+      ////D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel*0.6, comm);//da am 11.3.2013 velo um 1/0.6 zu hoch
+      //D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch,IntValHelp, vxZiel, comm);//dies sollte zu Re=5500 fuehren..
+
+      //UbSchedulerPtr visQSch(new UbScheduler());
+      //visQSch->addSchedule(10,90100,90130);
+      //QKritPostprocessor QKritPtr(grid,pathname+"/steps/Qq",WbWriterVtkXmlBinary::getInstance(),visQSch, comm);
+
+      //mu::Parser decrViscFunc;
+      //decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");
+      //decrViscFunc.DefineConst("nue0", nueLB);
+      //decrViscFunc.DefineConst("c0", 0.1);
+      //UbSchedulerPtr DecrViscSch(new UbScheduler());
+      //DecrViscSch->addSchedule(10,10,1000);
+      //DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch,&decrViscFunc, comm);
+
+      //cout << "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem()<<endl;
+      //cout << "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed()<<endl;
+      //cout << "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe()<<endl;
+
+      //double endTime = 520000;//20000001;
+      //CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      //if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      //calculation->calculate();
+      //if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/bananas/CMakeLists.txt b/source/Applications/bananas/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..54ddbbc6cb16197abdc19b7787b21092a4a12593
--- /dev/null
+++ b/source/Applications/bananas/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bananas)
+
+INCLUDE(${SOURCE_ROOT}/core/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES core)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bananas BINARY)
diff --git a/source/Applications/bananas/bananas.cpp b/source/Applications/bananas/bananas.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9e6744f42318af1cda99edd8ee2e3fdfcd62578b
--- /dev/null
+++ b/source/Applications/bananas/bananas.cpp
@@ -0,0 +1,457 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include <numerics/geometry3d/GbSphere3D.h>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "SyncBcBlockVisitor.h"
+#include "numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h"
+#include "numerics/geometry3d/GbTriFaceMesh3D.h"
+#include "D3Q27TriFaceMeshInteractor.h"
+#include "basics/utilities/UbFileOutputASCII.h"
+#include "basics/utilities/UbFileInputASCII.h"
+#include "basics/utilities/UbFileInputBinary.h"
+#include "basics/container/CbArray3D.h"
+#include "numerics/geometry3d/GbVoxelMatrix3D.h"
+
+#define CONVEXHULL
+
+using namespace std;
+
+const int FLUID = 1;
+const int SOLID = 15;
+
+//////////////////////////////////////////////////////////////////////////
+void writeMatrixToVtkImageFile(const std::string& fileName, const CbArray3D <int>& geoMatrix,
+                               double itsDeltaXWorld, double orgX1, double orgX2, double orgX3)
+{
+   UbFileOutputASCII out(fileName);
+
+   int NX1 = (int)geoMatrix.getNX1();	
+   int NX2 = (int)geoMatrix.getNX2();	
+   int NX3 = (int)geoMatrix.getNX3();
+   int nn = NX1*NX2*NX3;
+   out.writeLine("# vtk DataFile Version 3.0");
+   out.writeLine(fileName);
+   out.writeLine("ASCII");
+   out.writeLine("DATASET STRUCTURED_POINTS");
+   out.writeString("DIMENSIONS");
+   out.writeInteger(NX1);
+   out.writeInteger(NX2);
+   out.writeInteger(NX3);
+   out.writeLine();
+   out.writeString("ORIGIN");
+   out.writeDouble(orgX1);
+   out.writeDouble(orgX2);
+   out.writeDouble(orgX3);
+   out.writeLine();
+   out.writeString("SPACING");
+   out.writeDouble(itsDeltaXWorld);
+   out.writeDouble(itsDeltaXWorld);
+   out.writeDouble(itsDeltaXWorld);
+   out.writeLine();
+   out.writeString("POINT_DATA");
+   out.writeInteger(nn);
+   out.writeLine();
+   out.writeLine("SCALARS Geo integer");
+   out.writeLine("LOOKUP_TABLE default");
+
+   for(int k=0 ; k<NX3 ; k++){
+      for(int j=0 ; j<NX2 ; j++){
+         for(int i=0 ; i<NX1 ; i++){
+            out.writeInteger( geoMatrix(i,j,k) );
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void readDimensionsFromFldFile(const std::string& fileName, int& d1, int& d2, int& d3)
+{
+   UbFileInputASCII in(fileName);
+   // read grid nx3
+   int dim   = in.readIntegerAfterString("ndim=");
+
+   if (dim != 3) throw UbException(UB_EXARGS,"readGeoMatrixFromFldFile() - Wrong number of dimensions.");
+
+   d1 = in.readIntegerAfterString("dim1=");
+   d2 = in.readIntegerAfterString("dim2=");
+   d3 = in.readIntegerAfterString("dim3=");
+}
+//////////////////////////////////////////////////////////////////////////
+void readGeoMatrixFromFldFile(const std::string& fileName, GbVoxelMatrix3DPtr geoMatrix)
+{
+   UbFileInputASCII in(fileName);
+   // read grid nx3
+   int dim   = in.readIntegerAfterString("ndim=");
+
+   if (dim != 3) throw UbException(UB_EXARGS,"readGeoMatrixFromFldFile() - Wrong number of dimensions.");
+
+   int sizeX = in.readIntegerAfterString("dim1=");
+   int sizeY = in.readIntegerAfterString("dim2=");
+   int sizeZ = in.readIntegerAfterString("dim3=");
+
+   std::string binFileName = in.readStringAfterString("variable 1 file=");
+
+   //separate name from path
+   std::string path = fileName.substr( 0, fileName.find_last_of('//')+1 );
+
+   binFileName = path.append(binFileName);
+
+   UbFileInputBinary binIn(binFileName);
+
+   for (int i=0; i<2048; i++) 
+   {
+      binIn.readChar();
+   }
+
+   int x, y, z, val;
+
+   for(z=0; z<sizeZ; z++)
+   {
+      for(y=0; y<sizeY; y++)
+      {
+         for(x=0; x<sizeX; x++)
+         {
+            val = binIn.readChar();
+
+            if(x!=0 && x!=sizeX-1 && 
+               y!=0 && y!=sizeY-1 &&
+               z!=0 && z!=sizeZ-1   )
+            {
+               if(val == 0)
+               {
+                   (*geoMatrix)(x,y,z) = GbVoxelMatrix3D::SOLID;
+               }
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void discretizeGeoObject(GbObject3DPtr geoObject, CbArray3D<int>& geoMatrix, double delta, double orgX1, double orgX2, double orgX3)
+{
+   int nx1 = (int)geoMatrix.getNX1();
+   int nx2 = (int)geoMatrix.getNX2();
+   int nx3 = (int)geoMatrix.getNX3();
+
+   for(int k=0 ; k<nx3 ; k++)
+   {
+      for(int j=0 ; j<nx2 ; j++)
+      {
+         for(int i=0 ; i<nx1 ; i++)
+         {
+            double x = orgX1 + i*delta;
+            double y = orgX2 + j*delta;
+            double z = orgX3 + k*delta;
+            if(geoObject->isPointInGbObject3D(x, y, z)) geoMatrix(i,j,k) = SOLID;
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void writeGbVoxelMatrix3DtoVtuXmlASCII(const std::string& fileName, GbVoxelMatrix3DPtr voxelMatrix, 
+                                       double worldDeltaX1, double worldDeltaX2, double worldDeltaX3,
+                                       int nx1, int nx2, int nx3)
+{
+   std::vector< UbTupleFloat3 > nodes;
+   std::vector<std::string > datanames;
+   std::vector<std::vector<double > > nodedata;
+   
+   datanames.resize(0);
+   datanames.push_back("Solid");
+   nodes.resize(0);
+   nodedata.resize(datanames.size());
+
+   double orgX1 = voxelMatrix->getX1Minimum();
+   double orgX2 = voxelMatrix->getX2Minimum();
+   double orgX3 = voxelMatrix->getX3Minimum();
+
+   int index = 0;
+   double x1KO,x2KO,x3KO;
+   
+      for (int x3=0; x3<nx3;x3++){
+         for (int x2=0; x2<nx2;x2++){
+            for(int x1=0; x1<nx1;x1++)
+            {
+                  x1KO = orgX1 + worldDeltaX1*(double)x1;
+                  x2KO = orgX2 + worldDeltaX2*(double)x2;
+                  x3KO = orgX3 + worldDeltaX3*(double)x3;
+                  nodes.push_back( makeUbTuple(float(x1KO), float(x2KO), float(x3KO)) );
+                  nodedata[0].push_back((*voxelMatrix)(x1,x2,x3));
+            }
+         }
+      }
+   WbWriterVtkXmlASCII::getInstance()->writeNodesWithNodeData(fileName, nodes,  datanames, nodedata); 
+}
+//////////////////////////////////////////////////////////////////////////
+void writeGbVoxelMatrix3DtoLegacyVTK(const std::string& fileName, GbVoxelMatrix3DPtr voxelMatrix,
+                                       double worldDeltaX1, double worldDeltaX2, double worldDeltaX3,
+                                       int nx1, int nx2, int nx3)
+{
+   UbFileOutputASCII out(fileName);
+
+   int nn = nx1*nx2*nx3;
+   out.writeLine("# vtk DataFile Version 3.0");
+   out.writeLine(fileName);
+   out.writeLine("ASCII");
+   out.writeLine("DATASET STRUCTURED_POINTS");
+   out.writeString("DIMENSIONS");
+   out.writeInteger(nx1);
+   out.writeInteger(nx2);
+   out.writeInteger(nx3);
+   out.writeLine();
+   out.writeString("ORIGIN");
+   out.writeDouble(voxelMatrix->getX1Minimum());
+   out.writeDouble(voxelMatrix->getX2Minimum());
+   out.writeDouble(voxelMatrix->getX3Minimum());
+   out.writeLine();
+   out.writeString("SPACING");
+   out.writeDouble(worldDeltaX1);
+   out.writeDouble(worldDeltaX2);
+   out.writeDouble(worldDeltaX3);
+   out.writeLine();
+   out.writeString("POINT_DATA");
+   out.writeInteger(nn);
+   out.writeLine();
+   out.writeLine("SCALARS Geo integer");
+   out.writeLine("LOOKUP_TABLE default");
+
+   for(int k=0 ; k<nx3 ; k++){
+      for(int j=0 ; j<nx2 ; j++){
+         for(int i=0 ; i<nx1 ; i++){
+            out.writeInteger( (int)(*voxelMatrix)(i,j,k) );
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void run(const char *cstr)
+{
+   try
+   {
+      //string pathname = "c:/temp/bananas/out";
+      //string pathnameGeo = "c:/temp/bananas/geo";
+
+      std::string opt;
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+      else
+      {
+         UBLOG(logINFO,"no option: x, y or z");
+         return;
+      }
+      
+      string pathnameGeo = "/home/koskuche/data/bananas";
+      string pathname;
+
+      if(opt == "z") pathname = "/work/koskuche/scratch/bananas/setupZ/out";
+
+      if(opt == "x") pathname = "/work/koskuche/scratch/bananas/setupX/out";
+
+      if(opt == "y") pathname = "/work/koskuche/scratch/bananas/setupY/out";
+
+      CommunicatorPtr comm(new MPICommunicator());
+     
+      //////////////////////////////////////////////////////////////////////////
+      // Geometries
+      //////////////////////////////////////////////////////////////////////////
+      //bananas box geometry
+      UBLOG(logINFO,"Start read bananas box geometry");
+      GbTriFaceMesh3DPtr bananaBox (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathnameGeo+"/Banana_boxD.stl","banana_box"));
+      UBLOG(logINFO,"Stop read bananas box geometry");
+      bananaBox->rotate(90.0, 0.0, 0.0); //around Z
+
+      double b_minX1 = bananaBox->getX1Minimum();
+      double b_minX2 = bananaBox->getX2Minimum();
+      double b_minX3 = bananaBox->getX3Minimum();
+
+      double b_maxX1 = bananaBox->getX1Maximum();
+      double b_maxX2 = bananaBox->getX2Maximum();
+      double b_maxX3 = bananaBox->getX3Maximum();
+
+      if(opt == "x") bananaBox->rotate(0.0, 0.0, -90.0); //around X
+      
+      if(opt == "y") bananaBox->rotate(0.0, -90.0, 0.0); //around Y
+
+      UBLOG(logINFO,"Start write bananas box geometry");
+      GbSystem3D::writeGeoObject(bananaBox.get(), pathname+"/banana_box", WbWriterVtkXmlASCII::getInstance());
+      UBLOG(logINFO,"Stop write bananas box geometry");
+
+      //distances for bounding box
+      double dist_z = 0.12;
+      double dist_x = 0.26;
+      double dist_y = 0.195;
+
+      double g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3;
+
+      //bounding box of simulation
+      //setup1 - z
+      if(opt == "z")
+      {
+         g_minX1 = bananaBox->getX1Minimum();
+         g_minX2 = bananaBox->getX2Minimum();
+         g_minX3 = bananaBox->getX3Minimum()-dist_z;
+
+         g_maxX1 = bananaBox->getX1Maximum();
+         g_maxX2 = bananaBox->getX2Maximum();
+         g_maxX3 = bananaBox->getX3Maximum()+dist_z*2.0;
+      }
+
+      //setup2 - x
+      if(opt == "x")
+      {
+         g_minX1 = bananaBox->getX1Minimum();
+         g_minX2 = bananaBox->getX2Minimum();
+         g_minX3 = bananaBox->getX3Minimum()-dist_x;
+
+         g_maxX1 = bananaBox->getX1Maximum();
+         g_maxX2 = bananaBox->getX2Maximum();
+         g_maxX3 = bananaBox->getX3Maximum()+dist_x*2.0;
+      }
+
+      //setup3 - y
+      if(opt == "y")
+      {
+         g_minX1 = bananaBox->getX1Minimum();
+         g_minX2 = bananaBox->getX2Minimum();
+         g_minX3 = bananaBox->getX3Minimum()-dist_y;
+
+         g_maxX1 = bananaBox->getX1Maximum();
+         g_maxX2 = bananaBox->getX2Maximum();
+         g_maxX3 = bananaBox->getX3Maximum()+dist_y*2.0;
+      }
+
+      const double gridOriginX1 = g_minX1;
+      const double gridOriginX2 = g_minX2;
+      const double gridOriginX3 = g_minX3;
+
+      //int gridNX1 = 170;
+      //int gridNX2 = 226;
+      //int gridNX3 = 104;
+
+      const double dx = 2.20183486239e-3; //blockLentghX1/static_cast<double>(blocknx1);
+
+      UBLOG(logINFO,"DeltaX = " << dx);
+
+      CbArray3D<int> grid(int((g_maxX1-g_minX1)/dx)+1, int((g_maxX2-g_minX2)/dx)+1, int((g_maxX3-g_minX3)/dx)+1, FLUID);
+
+      UBLOG(logINFO,"Start write geo matrix empty");
+      writeMatrixToVtkImageFile(pathname + "/geo_matrix_empty.vtk", grid, dx, gridOriginX1, gridOriginX2, gridOriginX3);
+      UBLOG(logINFO,"Stop write geo matrix empty");
+
+#ifdef BANANAS
+      //reed bananas
+      UBLOG(logINFO,"Start read bananas geometry");
+      int d1, d2, d3;
+      readDimensionsFromFldFile(pathnameGeo + "/BANANA_8binn_Binear_A.fld", d1, d2, d3);
+      UBLOG(logINFO,"Dimensions of bananas geometry: " << d1 << ", " << d2 << ", " << d3);
+      GbVoxelMatrix3DPtr bananas(new GbVoxelMatrix3D(d1, d2, d3, float(GbVoxelMatrix3D::FLUID))); 
+      readGeoMatrixFromFldFile(pathnameGeo + "/BANANA_8binn_Binear_A.fld", bananas);
+      UBLOG(logINFO,"Stop read bananas geometry");
+      double bananasDx1 = (b_maxX1 - b_minX1) / float(d1);
+      double bananasDx2 = (b_maxX2 - b_minX2) / float(d2);
+      double bananasDx3 = (b_maxX3 - b_minX3) / float(d3);
+      bananas->setVoxelMatrixDelta(float(bananasDx1), float(bananasDx2), float(bananasDx3));
+      bananas->setCenterCoordinates(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid());
+      bananas->setVoxelMatrixMininum(float(b_minX1), float(b_minX2), float(b_minX3));
+
+      bananas->rotate90aroundX();
+      bananas->rotate90aroundY();
+      //bananas->rotate90aroundX();
+
+      UBLOG(logINFO,"Start write bananas geometry");
+      bananas->writeToLegacyVTK(pathname + "/bananas.vtk");
+      UBLOG(logINFO,"Stop write bananas geometry");
+#endif
+
+#ifdef CONVEXHULL
+      UBLOG(logINFO,"Start read bananas box geometry");
+      GbTriFaceMesh3DPtr bananaHull (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathnameGeo+"/convexhullASCII.stl","banana_hull"));
+      UBLOG(logINFO,"Stop read bananas box geometry");
+      bananaHull->translate(0.0, 0.0, 5.0*dx);
+      if(opt == "x") bananaHull->rotateAroundPoint(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid(), 0.0, 0.0, -90.0); //around X
+      if(opt == "y") bananaHull->rotateAroundPoint(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid(), 0.0, -90.0, 0.0); //around Y
+      UBLOG(logINFO,"Start write banana hull geometry");
+      GbSystem3D::writeGeoObject(bananaHull.get(), pathname+"/banana_hull", WbWriterVtkXmlASCII::getInstance());
+      UBLOG(logINFO,"Stop write banana hull geometry");
+#endif
+      ////////////////////////////////////////
+      //return;
+      /////////////////////////////////////////
+
+      UBLOG(logINFO,"Start discretization of banana box");
+      discretizeGeoObject(bananaBox, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3);
+      UBLOG(logINFO,"Stop discretization of banana box");
+
+#ifdef BANANAS
+      UBLOG(logINFO,"Start discretization of bananas");
+      discretizeGeoObject(bananas, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3);
+      UBLOG(logINFO,"Stop discretization of bananas");
+#endif
+
+#ifdef CONVEXHULL
+      UBLOG(logINFO,"Start discretization of banana hull");
+      discretizeGeoObject(bananaHull, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3);
+      UBLOG(logINFO,"Stop discretization of banana hull");
+#endif
+
+      UBLOG(logINFO,"Start write geo matrix");
+      writeMatrixToVtkImageFile(pathname + "/geo_matrix.vtk", grid, dx, gridOriginX1, gridOriginX2, gridOriginX3);
+      UBLOG(logINFO,"Stop write geo matrix");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/bananas2/CMakeLists.txt b/source/Applications/bananas2/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c2c655e8053b47e1537a70bd50b27b49d540ba8e
--- /dev/null
+++ b/source/Applications/bananas2/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bananas2)
+
+INCLUDE(${SOURCE_ROOT}/core/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES core)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bananas2 BINARY)
diff --git a/source/Applications/bananas2/bananas2.cpp b/source/Applications/bananas2/bananas2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..01a969315c78d2da7418565761f71fe5c75311a3
--- /dev/null
+++ b/source/Applications/bananas2/bananas2.cpp
@@ -0,0 +1,633 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include <numerics/geometry3d/GbSphere3D.h>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "SyncBcBlockVisitor.h"
+#include "numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h"
+#include "numerics/geometry3d/GbTriFaceMesh3D.h"
+#include "D3Q27TriFaceMeshInteractor.h"
+#include "basics/utilities/UbFileOutputASCII.h"
+#include "basics/utilities/UbFileInputASCII.h"
+#include "basics/utilities/UbFileInputBinary.h"
+#include "basics/container/CbArray3D.h"
+#include "numerics/geometry3d/GbVoxelMatrix3D.h"
+
+
+/* 
+ *  The first 3 bits contain node type (fluid, inlet, etc.).
+ *  The remaining 5 bits contain the unique geometry number 
+ *  in case of solid nodes.
+ *
+ *  0 0 0 0 0 | 0 0 0
+ */
+#define getGeoType(geo) (geo & 0x7) /*= 00000111*/
+#define getNormal(geo) (geo >> 3)
+#define setGeoType(dest, geo_type) dest = (dest & 0xF8) + geo_type
+#define setGeoNormal(dest, geo_id) dest = (geo_id << 3) + getGeoType(dest)
+
+#define GEO_INVALID 0
+#define GEO_FLUID 1
+#define GEO_INLET 2
+#define GEO_HULL 3           //hull
+#define GEO_FLUID_IN_HULL 4  //fluid inside hull
+#define GEO_BANANAS 5        //bananas    
+#define GEO_BOX 6            //box
+
+#define NORMAL_POS_X1 1
+#define NORMAL_NEG_X1 2
+
+#define NORMAL_POS_X2 3
+#define NORMAL_NEG_X2 4
+
+#define NORMAL_POS_X3 5
+#define NORMAL_NEG_X3 6
+
+#define CONVEXHULL
+
+using namespace std;
+
+typedef CbArray3D<int> VoxelMatrix;
+
+//index             0   1   2   3   4   5  6   7   8    9  10  11  12  13  14  15  16  17  18
+//f:                E,  W,  N,  S,  T,  B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, ZERO
+const int EX1[] = { 1, -1,  0,  0,  0,  0,  1, -1,  1, -1,  1, -1,  1, -1,  0,  0,  0,  0,  0 };
+const int EX2[] = { 0,  0,  1, -1,  0,  0,  1, -1, -1,  1,  0,  0,  0,  0,  1, -1,  1, -1,  0 };
+const int EX3[] = { 0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  1, -1, -1,  1,  1, -1, -1,  1,  0 };
+
+//////////////////////////////////////////////////////////////////////////
+void writeMatrixToVtkImageFile(const std::string& fileName, const VoxelMatrix& geoMatrix,
+                               double itsDeltaXWorld, double orgX1, double orgX2, double orgX3)
+{
+   UbFileOutputASCII out(fileName);
+
+   int NX1 = (int)geoMatrix.getNX1();	
+   int NX2 = (int)geoMatrix.getNX2();	
+   int NX3 = (int)geoMatrix.getNX3();
+   int nn = NX1*NX2*NX3;
+   out.writeLine("# vtk DataFile Version 3.0");
+   out.writeLine(fileName);
+   out.writeLine("ASCII");
+   out.writeLine("DATASET STRUCTURED_POINTS");
+   out.writeString("DIMENSIONS");
+   out.writeInteger(NX1);
+   out.writeInteger(NX2);
+   out.writeInteger(NX3);
+   out.writeLine();
+   out.writeString("ORIGIN");
+   out.writeDouble(orgX1);
+   out.writeDouble(orgX2);
+   out.writeDouble(orgX3);
+   out.writeLine();
+   out.writeString("SPACING");
+   out.writeDouble(itsDeltaXWorld);
+   out.writeDouble(itsDeltaXWorld);
+   out.writeDouble(itsDeltaXWorld);
+   out.writeLine();
+   out.writeString("POINT_DATA");
+   out.writeInteger(nn);
+   out.writeLine();
+   out.writeLine("SCALARS Geo integer");
+   out.writeLine("LOOKUP_TABLE default");
+
+   for(int k=0 ; k<NX3 ; k++){
+      for(int j=0 ; j<NX2 ; j++){
+         for(int i=0 ; i<NX1 ; i++){
+            out.writeInteger( geoMatrix(i,j,k) );
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void readDimensionsFromFldFile(const std::string& fileName, int& d1, int& d2, int& d3)
+{
+   UbFileInputASCII in(fileName);
+   // read grid nx3
+   int dim   = in.readIntegerAfterString("ndim=");
+
+   if (dim != 3) throw UbException(UB_EXARGS,"readGeoMatrixFromFldFile() - Wrong number of dimensions.");
+
+   d1 = in.readIntegerAfterString("dim1=");
+   d2 = in.readIntegerAfterString("dim2=");
+   d3 = in.readIntegerAfterString("dim3=");
+}
+//////////////////////////////////////////////////////////////////////////
+void readGeoMatrixFromFldFile(const std::string& fileName, GbVoxelMatrix3DPtr geoMatrix)
+{
+   UbFileInputASCII in(fileName);
+   // read grid nx3
+   int dim   = in.readIntegerAfterString("ndim=");
+
+   if (dim != 3) throw UbException(UB_EXARGS,"readGeoMatrixFromFldFile() - Wrong number of dimensions.");
+
+   int sizeX = in.readIntegerAfterString("dim1=");
+   int sizeY = in.readIntegerAfterString("dim2=");
+   int sizeZ = in.readIntegerAfterString("dim3=");
+
+   std::string binFileName = in.readStringAfterString("variable 1 file=");
+
+   //separate name from path
+   std::string path = fileName.substr( 0, fileName.find_last_of('//')+1 );
+
+   binFileName = path.append(binFileName);
+
+   UbFileInputBinary binIn(binFileName);
+
+   for (int i=0; i<2048; i++) 
+   {
+      binIn.readChar();
+   }
+
+   int x, y, z, val;
+
+   for(z=0; z<sizeZ; z++)
+   {
+      for(y=0; y<sizeY; y++)
+      {
+         for(x=0; x<sizeX; x++)
+         {
+            val = binIn.readChar();
+
+            if(x!=0 && x!=sizeX-1 && 
+               y!=0 && y!=sizeY-1 &&
+               z!=0 && z!=sizeZ-1   )
+            {
+               if(val == 0)
+               {
+                   (*geoMatrix)(x,y,z) = GbVoxelMatrix3D::SOLID;
+               }
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void discretizeGeoObject(GbObject3DPtr geoObject, VoxelMatrix& geoMatrix, double delta, 
+                         double orgX1, double orgX2, double orgX3, 
+                         int inValue, int outValue, bool bothSides,
+                         bool overwriteIn, bool overwriteOut,
+                         int noInValue, int noOutValue)
+{
+   int nx1 = (int)geoMatrix.getNX1();
+   int nx2 = (int)geoMatrix.getNX2();
+   int nx3 = (int)geoMatrix.getNX3();
+
+   for(int k=0 ; k<nx3 ; k++)
+   {
+      for(int j=0 ; j<nx2 ; j++)
+      {
+         for(int i=0 ; i<nx1 ; i++)
+         {
+            double x = orgX1 + i*delta;
+            double y = orgX2 + j*delta;
+            double z = orgX3 + k*delta;
+
+            int temp = 0;
+            int gm = geoMatrix(i,j,k);
+
+            if(geoObject->isPointInGbObject3D(x, y, z))  
+            {
+               setGeoType(temp, inValue);
+               if (overwriteIn)
+               {
+                  geoMatrix(i,j,k) = temp;
+               }
+               else
+               {
+                  if(gm != noInValue) 
+                  {
+                     geoMatrix(i,j,k) = temp;
+                  }
+               }
+            }
+            else if(bothSides)
+            {
+               setGeoType(temp, outValue);
+               if (overwriteOut)
+               {
+                  geoMatrix(i,j,k) = temp;
+               }
+               else
+               {
+                  if(gm != noOutValue) 
+                  {
+                     geoMatrix(i,j,k) = temp;
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+bool hasNeighbor(VoxelMatrix& geoMatrix, int x1, int x2, int x3)
+{
+   bool result = false;
+   for( int dir = 0; dir < 18; dir++)
+   {
+      int temp = geoMatrix(x1+EX1[dir], x2+EX2[dir], x3+EX3[dir]);
+      if(temp == GEO_BANANAS || temp == GEO_FLUID_IN_HULL)
+      {
+         result = true;
+         break;
+      }
+   }
+   return result;
+}
+//////////////////////////////////////////////////////////////////////////
+void createHull(VoxelMatrix& geoMatrix)
+{
+   int nx1 = (int)geoMatrix.getNX1();
+   int nx2 = (int)geoMatrix.getNX2();
+   int nx3 = (int)geoMatrix.getNX3();
+
+   for(int k=1 ; k<nx3-1 ; k++)
+   {
+      for(int j=1 ; j<nx2-1 ; j++)
+      {
+         for(int i=1 ; i<nx1-1 ; i++)
+         {
+            int val = geoMatrix(i,j,k);
+            if(val == GEO_FLUID)
+            {
+               if(hasNeighbor(geoMatrix, i, j, k))
+               {
+                  int temp = 0;
+                  setGeoType(temp, GEO_HULL);
+                  geoMatrix(i,j,k) = temp;
+               }
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void writeGbVoxelMatrix3DtoVtuXmlASCII(const std::string& fileName, GbVoxelMatrix3DPtr voxelMatrix, 
+                                       double worldDeltaX1, double worldDeltaX2, double worldDeltaX3,
+                                       int nx1, int nx2, int nx3)
+{
+   std::vector< UbTupleFloat3 > nodes;
+   std::vector<std::string > datanames;
+   std::vector<std::vector<double > > nodedata;
+   
+   datanames.resize(0);
+   datanames.push_back("Solid");
+   nodes.resize(0);
+   nodedata.resize(datanames.size());
+
+   double orgX1 = voxelMatrix->getX1Minimum();
+   double orgX2 = voxelMatrix->getX2Minimum();
+   double orgX3 = voxelMatrix->getX3Minimum();
+
+   int index = 0;
+   double x1KO,x2KO,x3KO;
+   
+      for (int x3=0; x3<nx3;x3++){
+         for (int x2=0; x2<nx2;x2++){
+            for(int x1=0; x1<nx1;x1++)
+            {
+                  x1KO = orgX1 + worldDeltaX1*(double)x1;
+                  x2KO = orgX2 + worldDeltaX2*(double)x2;
+                  x3KO = orgX3 + worldDeltaX3*(double)x3;
+                  nodes.push_back( makeUbTuple(float(x1KO), float(x2KO), float(x3KO)) );
+                  nodedata[0].push_back((*voxelMatrix)(x1,x2,x3));
+            }
+         }
+      }
+   WbWriterVtkXmlASCII::getInstance()->writeNodesWithNodeData(fileName, nodes,  datanames, nodedata); 
+}
+//////////////////////////////////////////////////////////////////////////
+void writeGbVoxelMatrix3DtoLegacyVTK(const std::string& fileName, GbVoxelMatrix3DPtr voxelMatrix,
+                                       double worldDeltaX1, double worldDeltaX2, double worldDeltaX3,
+                                       int nx1, int nx2, int nx3)
+{
+   UbFileOutputASCII out(fileName);
+
+   int nn = nx1*nx2*nx3;
+   out.writeLine("# vtk DataFile Version 3.0");
+   out.writeLine(fileName);
+   out.writeLine("ASCII");
+   out.writeLine("DATASET STRUCTURED_POINTS");
+   out.writeString("DIMENSIONS");
+   out.writeInteger(nx1);
+   out.writeInteger(nx2);
+   out.writeInteger(nx3);
+   out.writeLine();
+   out.writeString("ORIGIN");
+   out.writeDouble(voxelMatrix->getX1Minimum());
+   out.writeDouble(voxelMatrix->getX2Minimum());
+   out.writeDouble(voxelMatrix->getX3Minimum());
+   out.writeLine();
+   out.writeString("SPACING");
+   out.writeDouble(worldDeltaX1);
+   out.writeDouble(worldDeltaX2);
+   out.writeDouble(worldDeltaX3);
+   out.writeLine();
+   out.writeString("POINT_DATA");
+   out.writeInteger(nn);
+   out.writeLine();
+   out.writeLine("SCALARS Geo integer");
+   out.writeLine("LOOKUP_TABLE default");
+
+   for(int k=0 ; k<nx3 ; k++){
+      for(int j=0 ; j<nx2 ; j++){
+         for(int i=0 ; i<nx1 ; i++){
+            out.writeInteger( (int)(*voxelMatrix)(i,j,k) );
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void setNormalsOnBoundary(int minX1, int minX2, int minX3, int maxX1, int maxX2, int maxX3, VoxelMatrix& matrix, int dir)
+{
+   for (int ix3 = minX3; ix3 <= maxX3; ix3++)
+      for (int ix2 = minX2; ix2 <= maxX2; ix2++)
+         for (int ix1 = minX1; ix1 <= maxX1; ix1++)
+         {
+
+            int temp = 0;
+            temp = getGeoType(matrix(ix1, ix2, ix3));
+            setGeoNormal(temp, dir);
+            matrix(ix1, ix2, ix3) = temp;
+         }
+}
+//////////////////////////////////////////////////////////////////////////
+void run(const char *cstr)
+{
+   try
+   {
+      std::string opt;
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+      else
+      {
+         UBLOG(logINFO,"no option: x, y or z");
+         return;
+      }
+
+      string pathnameGeo = "/home/koskuche/data/bananas";
+      string pathname;
+
+      if(opt == "z") pathname = "/work/koskuche/scratch/bananas2/setupZ";
+
+      if(opt == "x") pathname = "/work/koskuche/scratch/bananas2/setupX";
+
+      if(opt == "y") pathname = "/work/koskuche/scratch/bananas2/setupY";
+
+      CommunicatorPtr comm(new MPICommunicator());
+     
+      //////////////////////////////////////////////////////////////////////////
+      // Geometries
+      //////////////////////////////////////////////////////////////////////////
+      //bananas box geometry
+      UBLOG(logINFO,"Start read bananas box geometry");
+      GbTriFaceMesh3DPtr bananaBox (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathnameGeo+"/Banana_boxD.stl","banana_box"));
+      UBLOG(logINFO,"Stop read bananas box geometry");
+      bananaBox->rotate(90.0, 0.0, 0.0); //around Z
+
+      double b_minX1 = bananaBox->getX1Minimum();
+      double b_minX2 = bananaBox->getX2Minimum();
+      double b_minX3 = bananaBox->getX3Minimum();
+
+      double b_maxX1 = bananaBox->getX1Maximum();
+      double b_maxX2 = bananaBox->getX2Maximum();
+      double b_maxX3 = bananaBox->getX3Maximum();
+
+      if(opt == "x") bananaBox->rotate(0.0, 0.0, -90.0); //around X
+
+      if(opt == "y") bananaBox->rotate(0.0, -90.0, 0.0); //around Y
+
+      //after rotation for setup 2-3
+      double bb_minX1 = bananaBox->getX1Minimum();
+      double bb_minX2 = bananaBox->getX2Minimum();
+      double bb_minX3 = bananaBox->getX3Minimum();
+
+      double bb_maxX1 = bananaBox->getX1Maximum();
+      double bb_maxX2 = bananaBox->getX2Maximum();
+      double bb_maxX3 = bananaBox->getX3Maximum();
+
+      UBLOG(logINFO,"Start write bananas box geometry");
+      GbSystem3D::writeGeoObject(bananaBox.get(), pathname+"/banana_box", WbWriterVtkXmlASCII::getInstance());
+      UBLOG(logINFO,"Stop write bananas box geometry");
+
+      //distances for bounding box
+      double dist_z = 0.022;
+      double site   = 0.011;
+
+      //bounding box of simulation
+      double g_minX1 = bananaBox->getX1Minimum()-site;
+      double g_minX2 = bananaBox->getX2Minimum()-site;
+      double g_minX3 = bananaBox->getX3Minimum()-dist_z*2.0;
+
+      double g_maxX1 = bananaBox->getX1Maximum()+site;
+      double g_maxX2 = bananaBox->getX2Maximum()+site;
+      double g_maxX3 = bananaBox->getX3Maximum()+dist_z*2.0;
+
+      const double gridOriginX1 = g_minX1;
+      const double gridOriginX2 = g_minX2;
+      const double gridOriginX3 = g_minX3;
+
+      const double dx = 2.20183486239e-3;
+      UBLOG(logINFO,"DeltaX = " << dx);
+
+      GbCuboid3DPtr addWall1 (new GbCuboid3D(g_minX1, g_minX2, bb_minX3, bb_minX1, g_maxX2, bb_minX3+2*dx));
+      GbSystem3D::writeGeoObject(addWall1.get(), pathname+"/addWall1", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWall2 (new GbCuboid3D(bb_maxX1, g_minX2, bb_minX3, g_maxX1, g_maxX2, bb_minX3+2*dx));
+      GbSystem3D::writeGeoObject(addWall2.get(), pathname+"/addWall2", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWall3 (new GbCuboid3D(g_minX1, g_minX2, bb_minX3, g_maxX1, bb_minX2, bb_minX3+2*dx));
+      GbSystem3D::writeGeoObject(addWall3.get(), pathname+"/addWall3", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWall4 (new GbCuboid3D(g_minX1, bb_maxX2, bb_minX3, g_maxX1, g_maxX2, bb_minX3+2*dx));
+      GbSystem3D::writeGeoObject(addWall4.get(), pathname+"/addWall4", WbWriterVtkXmlASCII::getInstance());
+
+      VoxelMatrix grid(int((g_maxX1-g_minX1)/dx)+1, int((g_maxX2-g_minX2)/dx)+1, int((g_maxX3-g_minX3)/dx)+1, GEO_FLUID);
+
+      UBLOG(logINFO,"Start write geo matrix empty");
+      writeMatrixToVtkImageFile(pathname + "/geo_matrix_empty.vtk", grid, dx, gridOriginX1, gridOriginX2, gridOriginX3);
+      UBLOG(logINFO,"Stop write geo matrix empty");
+
+#ifdef CONVEXHULL
+      UBLOG(logINFO,"Start read bananas box geometry");
+      GbTriFaceMesh3DPtr bananasHull (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathnameGeo+"/convexhullASCII.stl","banana_hull"));
+      UBLOG(logINFO,"Stop read bananas box geometry");
+      double tr1 = bananasHull->getX3Minimum() - bananaBox->getX3Minimum();
+      bananasHull->translate(0.0, 0.0, 5.0*dx);
+#endif
+
+      //reed bananas
+      UBLOG(logINFO,"Start read bananas geometry");
+      int d1, d2, d3;
+      readDimensionsFromFldFile(pathnameGeo + "/BANANA_8binn_Binear_A.fld", d1, d2, d3);
+      UBLOG(logINFO,"Dimensions of bananas geometry: " << d1 << ", " << d2 << ", " << d3);
+      GbVoxelMatrix3DPtr bananas(new GbVoxelMatrix3D(d1, d2, d3, float(GbVoxelMatrix3D::FLUID))); 
+      readGeoMatrixFromFldFile(pathnameGeo + "/BANANA_8binn_Binear_A.fld", bananas);
+      UBLOG(logINFO,"Stop read bananas geometry");
+      double bananasDx1 = (b_maxX1 - b_minX1) / float(d1);
+      double bananasDx2 = (b_maxX2 - b_minX2) / float(d2);
+      double bananasDx3 = (b_maxX3 - b_minX3) / float(d3);
+      bananas->setVoxelMatrixDelta(float(bananasDx1), float(bananasDx2), float(bananasDx3));
+      bananas->setCenterCoordinates(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid());
+      bananas->setVoxelMatrixMininum(float(b_minX1), float(b_minX2), float(b_minX3));
+      
+      bananas->rotate90aroundY();
+      bananas->rotate90aroundY();
+      bananas->rotate90aroundZ();
+      bananas->rotate90aroundZ();
+      
+#ifdef CONVEXHULL
+      std::cout << "translate bananas: " <<bananasHull->getX3Minimum() - bananas->getX3Minimum() - tr1<<"\n";
+      bananas->translate(0.0, 0.0, bananasHull->getX3Minimum() - bananas->getX3Minimum() - tr1);
+      if(opt == "x") bananasHull->rotateAroundPoint(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid(), 0.0, 0.0, -90.0); //around X
+      if(opt == "y") bananasHull->rotateAroundPoint(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid(), 0.0, -90.0, 0.0); //around Y
+      UBLOG(logINFO,"Start write banana hull geometry");
+      GbSystem3D::writeGeoObject(bananasHull.get(), pathname+"/banana_hull", WbWriterVtkXmlASCII::getInstance());
+      UBLOG(logINFO,"Stop write banana hull geometry");
+#endif
+      
+      if(opt == "x")
+      {
+         bananas->rotate90aroundX(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid());
+         bananas->rotate90aroundX(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid());
+         bananas->rotate90aroundX(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid());
+      }
+      else if(opt == "y")
+      {
+         bananas->rotate90aroundY(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid());
+         bananas->rotate90aroundY(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid());
+         bananas->rotate90aroundY(bananaBox->getX1Centroid(), bananaBox->getX2Centroid(), bananaBox->getX3Centroid());
+      }
+
+      UBLOG(logINFO,"Start write bananas geometry");
+      bananas->writeToLegacyVTK(pathname + "/bananas.vtk");
+      UBLOG(logINFO,"Stop write bananas geometry");
+
+#ifdef BANANAS
+      UBLOG(logINFO,"Start discretization of banana box");
+      discretizeGeoObject(bananaBox, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_BOX);
+      UBLOG(logINFO,"Stop discretization of banana box");
+      UBLOG(logINFO,"Start discretization of bananas");
+      discretizeGeoObject(bananas, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_BANANAS);
+      UBLOG(logINFO,"Stop discretization of bananas");
+#endif
+
+#ifdef CONVEXHULL
+      UBLOG(logINFO,"Start discretization of bananas");
+      discretizeGeoObject(bananas, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_BANANAS, GEO_FLUID, false, true, true, GEO_INVALID, GEO_INVALID);
+      UBLOG(logINFO,"Stop discretization of bananas");
+      UBLOG(logINFO,"Start discretization of hull");
+      discretizeGeoObject(bananasHull, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_FLUID_IN_HULL, GEO_FLUID, true, false, true, GEO_BANANAS, GEO_INVALID);
+      UBLOG(logINFO,"Stop discretization of hull");
+      UBLOG(logINFO,"Start creation of hull film");
+      createHull(grid);
+      UBLOG(logINFO,"Stop creation of hull film");
+      UBLOG(logINFO,"Start discretization of banana box");
+      discretizeGeoObject(bananaBox, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_BOX, GEO_FLUID, false, true, true, GEO_INVALID, GEO_INVALID);
+      UBLOG(logINFO,"Stop discretization of banana box");
+#endif
+
+      UBLOG(logINFO,"Start discretization of add walls");
+      discretizeGeoObject(addWall1, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_BOX, GEO_FLUID, false, true, true, GEO_INVALID, GEO_INVALID);
+      discretizeGeoObject(addWall2, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_BOX, GEO_FLUID, false, true, true, GEO_INVALID, GEO_INVALID);
+      discretizeGeoObject(addWall3, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_BOX, GEO_FLUID, false, true, true, GEO_INVALID, GEO_INVALID);
+      discretizeGeoObject(addWall4, grid, dx, gridOriginX1, gridOriginX2, gridOriginX3, GEO_BOX, GEO_FLUID, false, true, true, GEO_INVALID, GEO_INVALID);
+      UBLOG(logINFO,"Stop discretization of add walls");
+
+      UBLOG(logINFO,"Start set normals");
+      int boxNX1 = int(bananaBox->getLengthX1() / dx);
+      int boxNX2 = int(bananaBox->getLengthX2() / dx);
+      int boxNX3 = int(bananaBox->getLengthX3() / dx);
+
+      int minX1 = int((bb_minX1 - gridOriginX1) / dx)+1;
+      int minX2 = int((bb_minX2 - gridOriginX2) / dx)+1;
+      int minX3 = int((bb_minX3 - gridOriginX3) / dx)+1;
+
+      int maxX1 = minX1 + boxNX1;
+      int maxX2 = minX2 + boxNX2;
+      int maxX3 = minX3 + boxNX3;
+
+      UBLOG(logINFO,"minX1="<<minX1<<",minX2= "<<minX2<<",minX3="<<minX3);
+      UBLOG(logINFO,"maxX1="<<maxX1<<",maxX2= "<<maxX2<<",maxX3="<<maxX3);
+
+
+      for (int ix3 = 0; ix3 < grid.getNX3(); ix3++)
+         for (int ix2 = 0; ix2 < grid.getNX2(); ix2++)
+            for (int ix1 = 0; ix1 < grid.getNX1(); ix1++)
+            {
+               int temp = grid(ix1, ix2, ix3);
+               setGeoNormal(temp, 0);
+               grid(ix1, ix2, ix3) = temp;
+            }
+
+
+      setNormalsOnBoundary(minX1, minX2, minX3, minX1, maxX2, maxX3, grid, NORMAL_NEG_X1);
+      setNormalsOnBoundary(maxX1, minX2, minX3, maxX1, maxX2, maxX3, grid, NORMAL_POS_X1);
+      setNormalsOnBoundary(minX1, minX2, minX3, maxX1, minX2, maxX3, grid, NORMAL_NEG_X2);
+      setNormalsOnBoundary(minX1, maxX2, minX3, maxX1, maxX2, maxX3, grid, NORMAL_POS_X2);
+      setNormalsOnBoundary(minX1, minX2, minX3, maxX1, maxX2, minX3, grid, NORMAL_NEG_X3);
+      setNormalsOnBoundary(minX1, minX2, maxX3, maxX1, maxX2, maxX3, grid, NORMAL_POS_X3);
+      UBLOG(logINFO,"Stop set normals");
+
+
+      UBLOG(logINFO,"Start write geo matrix");
+      writeMatrixToVtkImageFile(pathname + "/geo_matrix.vtk", grid, dx, gridOriginX1, gridOriginX2, gridOriginX3);
+      UBLOG(logINFO,"Stop write geo matrix");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/band/CMakeLists.txt b/source/Applications/band/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d8eeb0e810acde26f45352d4e7d8e066a4427de7
--- /dev/null
+++ b/source/Applications/band/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(band)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(band BINARY)
diff --git a/source/Applications/band/band.cpp b/source/Applications/band/band.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4424b62595741c9479cff83eea138a7cbcbbb290
--- /dev/null
+++ b/source/Applications/band/band.cpp
@@ -0,0 +1,582 @@
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+void run(const char *cstr)
+{
+   try
+   {
+      string pathname; 
+      string pathGeo;
+      string pathLog;
+      int numOfThreads = 1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      //UbLog::reportingLevel() = logDEBUG5;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr);
+
+      if(machine == "my") 
+      {
+         pathname = "d:/temp/band";
+         pathGeo = "d:/Data/plate";
+         pathLog = "d:/temp/band";
+         numOfThreads = 6;
+         logfile = false;
+         availMem = 16.0e9;
+      }
+      else if(machine == "Ludwig")      
+      {
+         pathname = "/work/koskuche/SFB880/band";
+         pathGeo = "/home/koskuche/data/plate";
+         pathLog = "/work/koskuche/SFB880/band";
+         numOfThreads = 1;
+         availMem = 12.0e9;
+         logfile = true;
+      }
+      else if(machine == "Hermit")      
+      {
+         //Hermit
+         pathname = "/univ_1/ws1/ws/xrmkuchr-plate3-0";
+         pathGeo = "/zhome/academic/HLRS/xrm/xrmkuchr/data/plate";
+         pathLog = "/zhome/academic/HLRS/xrm/xrmkuchr/work/plate";
+         numOfThreads = 16;
+         availMem = 2.0e9;
+         logfile = true;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+#if defined(__unix__)
+      if (myid==0) 
+      {
+         const char* str = pathLog.c_str();
+         int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      }
+#endif 
+
+      if(myid == 0 && logfile)
+      {
+         logFilename <<  pathLog + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      if(myid==0) UBLOG(logINFO,"Testcase band");
+
+      //string PlatteFilename = pathGeo + "/Platte4mesh_1.8mmProbendicke22.stl";
+      //string PlatteFilename = pathGeo + "/platte_raw.stl";
+      //string PlatteFilename = pathGeo + "/plate.stl";
+      string PlatteFilename = pathGeo + "/Platte_bearbeitet2.stl";
+
+      string ZckbndFilename = pathGeo + "/2zackenbaender0.stl";
+
+      ///////////////Knotenabmessungen:
+      int nx[3], blocknx[3];
+      nx[0]      = 10;//240;//120;//60;//86;//43;//65;//50;  //länge
+      nx[1]      = 1;//2;//6;///1;//5;// //breite
+      nx[2]      = 2;//64;//32;//18;//5;//15;//15; //höhe gebiet
+      blocknx[0] = 10;//10;//6;
+      blocknx[1] = 10;//10;//6;
+      blocknx[2] = 10;//10;//6;
+
+      int baseLevel   = 0;
+      int refineLevel = 0;
+
+      double H = 0.6; // Kanalhöhe [mm]
+      //double cdx = H/blocknx[2];
+      double cdx = 0.0390625;
+      double fdx = cdx/double(1<<refineLevel);
+
+      //double h = 200.0; // gewünschte Plattenhöhe in Gitterpunkten
+      //double fdx = plate->getLengthX3()/h;
+      //double cdx = fdx*double(1<<refineLevel);
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      double Re            = 680; 
+      double rhoLB         = 0.0;
+      double uLB           = 0.1; 
+      double lReal         = 0.6; //Zackenhöhe in mm
+      double nuLB          = (uLB*(lReal/cdx))/Re;
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(10,10,10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+
+         if(myid==0) UBLOG(logINFO,"Neustart..");
+
+         //////////////////////////////////////////////////////////////////////////
+         //Platte
+         GbTriFaceMesh3DPtr plate (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(PlatteFilename,"Netz"));
+         //plate->rotate(180.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+         //plate->rotate(90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+         if(myid == 0) GbSystem3D::writeGeoObject( plate.get(), pathname+"/geo/platte", WbWriterVtkXmlBinary::getInstance() );
+         //////////////////////////////////////////////////////////////////////////
+         // Zackenband
+         //////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr meshBand1 (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand"));
+         meshBand1->translate(-995, -203, -20.35);
+         //meshBand1->scale(1.0, 1.0, 2.0);
+         meshBand1->rotate(0.0, -0.5, 0.0);
+         if(myid == 0) GbSystem3D::writeGeoObject( meshBand1.get(), pathname+"/geo/Band1", WbWriterVtkXmlASCII::getInstance() );
+         //// Zackenband2
+         //GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand2"));
+         //meshBand2->translate(-995, -208, -20.35); 
+         //meshBand2->rotate(0.0, -0.5, 0.0);
+         //if(myid == 0) GbSystem3D::writeGeoObject( meshBand2.get(), pathname+"/geo/Band2", WbWriterVtkXmlASCII::getInstance() );
+
+         //GbTriFaceMesh3DPtr meshBand1 (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand"));
+         //meshBand1->translate(-496, -700, -20.106);
+         //if(myid == 0) GbSystem3D::writeGeoObject( meshBand1.get(), pathname+"/geo/Band1", WbWriterVtkXmlASCII::getInstance() );
+         // Zackenband2
+         //GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand2"));
+         //meshBand2->translate(-496, -705, -20.106); 
+         //if(myid == 0) GbSystem3D::writeGeoObject( meshBand2.get(), pathname+"/geo/Band2", WbWriterVtkXmlASCII::getInstance() );
+         // Zackenband3
+         //GbTriFaceMesh3DPtr meshBand3(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand3"));
+         //meshBand3->translate(-496, -700, -19.806); 
+         //if(myid == 0) GbSystem3D::writeGeoObject( meshBand3.get(), pathname+"/geo/Band3", WbWriterVtkXmlASCII::getInstance() );
+         //// Zackenband4
+         //GbTriFaceMesh3DPtr meshBand4(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand4"));
+         //meshBand4->translate(-496, -705, -19.806); 
+         //if(myid == 0) GbSystem3D::writeGeoObject( meshBand4.get(), pathname+"/geo/Band4", WbWriterVtkXmlASCII::getInstance() );
+         //////////////////////////////////////////////////////////////////////////
+
+
+         string pmFilename  = pathGeo + "/CT-2014-039.raw";
+         int pmNX1=1333;  //abmessung einzelbild in x-richtung
+         int pmNX2=463; //abmessung einzelbild in y richtung
+         int pmNX3=1333; //anzahl der bilder
+         float lthreshold = 27686.97;
+         float uthreshold = 65535.0;
+
+         GbVoxelMatrix3DPtr pmMesh(new GbVoxelMatrix3D(pmNX1,pmNX2,pmNX3,0,lthreshold,uthreshold));
+         pmMesh->readMatrixFromRawFile<unsigned short>(pmFilename, GbVoxelMatrix3D::LittleEndian);
+
+         double scaleFactor = 0.001;
+         double delta = 3.75*scaleFactor;
+         pmMesh->setVoxelMatrixDelta(delta, delta, delta);
+         pmMesh->rotate90aroundX(); 
+         pmMesh->rotate90aroundX();
+         pmMesh->rotate90aroundX();
+
+         GbCuboid3DPtr inlayBox(new GbCuboid3D(pmMesh->getX1Minimum(), pmMesh->getX2Minimum(), pmMesh->getX3Minimum(), 
+                                pmMesh->getX1Maximum(), pmMesh->getX2Maximum(), pmMesh->getX3Maximum()));
+         if(myid == 0) GbSystem3D::writeGeoObject(inlayBox.get(), pathname+"/geo/inlay", WbWriterVtkXmlASCII::getInstance());
+
+
+         double blockLengthx1 = blocknx[0]*cdx; //geowerte
+         double blockLengthx2 = blockLengthx1;
+         double blockLengthx3 = blockLengthx1;
+
+         double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+         //double originX1 = plate->getX1Maximum()-30.0;//meshBand1->getX1Minimum()-10.0;
+         //double originX2 = plate->getX2Minimum()+191.0;
+         //double originX3 = plate->getX3Maximum()-1.7;//meshBand1->getX3Minimum();//-2.0;
+         double originX1 = pmMesh->getX1Minimum()-5.0;//meshBand1->getX1Minimum()-10.0;
+         double originX2 = pmMesh->getX2Minimum()-1.0;
+         double originX3 = pmMesh->getX3Minimum()-5.0;//meshBand1->getX3Minimum();//-2.0;
+
+
+         bool periodicx1 = false;
+         bool periodicx2 = true;
+         bool periodicx3 = false;
+
+         //bounding box
+         double g_minX1 = originX1-cdx;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         //double g_maxX1 = originX1+20.0;//meshBand1->getX1Maximum()+40.0;
+         //double g_maxX2 = originX2+5.0;//meshBand1->getX2Minimum()-0.6;
+         //double g_maxX3 = plate->getX3Maximum()+7.0;//meshBand1->getX3Maximum()+10.0;
+
+         double g_maxX1 = pmMesh->getX1Maximum()+5.0-cdx;
+         double g_maxX2 = pmMesh->getX2Maximum()+1.0;
+         double g_maxX3 = pmMesh->getX3Maximum()+5.0;
+
+
+         //set grid
+         grid->setDeltaX(cdx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         //gridCube->setCenterCoordinates(gridCube->getX1Centroid(),meshBand1->getX2Centroid(),gridCube->getX3Centroid());
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            ="<<Re);
+            UBLOG(logINFO, "* nuLB          ="<<nuLB);
+            UBLOG(logINFO, "* uLB           ="<<uLB);
+            UBLOG(logINFO, "* cdx           ="<<cdx);
+            UBLOG(logINFO, "* fdx           ="<<fdx);
+            UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x1Periodic    ="<<periodicx1);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "* number of levels  ="<<refineLevel+1);
+            UBLOG(logINFO, "* path          ="<<pathname);
+
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* number of threads    ="<<numOfThreads);
+            UBLOG(logINFO, "* number of processes  ="<<comm->getNumberOfProcesses());
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "*****************************************");     
+         }
+         //////////////////////////////////////////////////////////////////////////
+
+
+         //////////////////////////////////////////////////////////////////////////
+         //refinement
+         GbCuboid3DPtr refinePlatteBox(new GbCuboid3D(plate->getX1Minimum(), plate->getX2Minimum(), plate->getX3Minimum()+(plate->getX3Maximum()-plate->getX3Minimum())/2.0, 
+            plate->getX1Maximum(), plate->getX2Maximum(), plate->getX3Maximum()));
+         if(myid == 0) GbSystem3D::writeGeoObject( refinePlatteBox.get(), pathname+"/geo/refinePlatteBox", WbWriterVtkXmlASCII::getInstance() );
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refinePlatteBox, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         /////////////////////////////////////////////////
+         ///interactoren
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         D3Q27TriFaceMeshInteractorPtr triPlateInteractor( new D3Q27TriFaceMeshInteractor(plate, grid, bcObst,Interactor3D::SOLID));
+         D3Q27TriFaceMeshInteractorPtr triBand1Interactor( new D3Q27TriFaceMeshInteractor( meshBand1, grid, bcObst,Interactor3D::SOLID, Interactor3D::POINTS) );
+         //D3Q27TriFaceMeshInteractorPtr triBand2Interactor( new D3Q27TriFaceMeshInteractor( meshBand2, grid, bcObst,Interactor3D::SOLID, Interactor3D::POINTS) );
+         //D3Q27TriFaceMeshInteractorPtr triBand3Interactor( new D3Q27TriFaceMeshInteractor( meshBand3, grid, bcObst,Interactor3D::SOLID, Interactor3D::POINTS) );
+         //D3Q27TriFaceMeshInteractorPtr triBand4Interactor( new D3Q27TriFaceMeshInteractor( meshBand4, grid, bcObst,Interactor3D::SOLID, Interactor3D::POINTS) );
+
+         //walls
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(g_minX1-blockLengthx1-cdx, g_minX2-blockLengthx1, g_minX3-blockLengthx1, g_maxX1+blockLengthx1-cdx, g_maxX2+blockLengthx1, g_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(g_minX1-blockLengthx1-cdx, g_minX2-blockLengthx1, g_maxX3, g_maxX1+blockLengthx1-cdx, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //walls
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr noSlip(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27InteractorPtr addWallZminExInt(new D3Q27Interactor(addWallZmin, grid, noSlip,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxExInt(new D3Q27Interactor(addWallZmax, grid, noSlip,Interactor3D::SOLID));
+
+         D3Q27BoundaryConditionAdapterPtr slip(new D3Q27SlipBCAdapter(bbOption));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, slip,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, slip,Interactor3D::SOLID));
+
+         //porouse medium
+         int bbOptionPM = 2; //quadratic bounce back with for thin walls
+         D3Q27BoundaryConditionAdapterPtr noSlipPM(new D3Q27NoSlipBCAdapter(bbOptionPM));
+         D3Q27InteractorPtr pmMeshInt(new D3Q27Interactor(pmMesh, grid, noSlipPM,Interactor3D::SOLID));
+         
+         //inflow
+         GbCuboid3DPtr velBCCuboid(new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_minX3-blockLengthx1, 
+            g_minX1, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1));
+         if(myid == 0) GbSystem3D::writeGeoObject(velBCCuboid.get(), pathname+"/geo/velBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(velBCCuboid,grid,Interactor3D::SOLID)); 
+
+         //inflow
+         double raiseVelSteps = 0;
+         vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("uLB"); 
+         inflowProfile.DefineConst("uLB",uLB);
+         velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (velcX1BCs,dummy,dummy));
+         velBCInteractor->addBCAdapter(velBCAdapter);
+
+         //outflow
+         GbCuboid3DPtr densCuboid(new GbCuboid3D(g_maxX1, g_minX2-blockLengthx1, g_minX3-blockLengthx1, 
+            g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1 ));
+         if(myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname+"/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr densInteractor( new D3Q27Interactor(densCuboid,grid,denBCAdapter,Interactor3D::SOLID) );
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));	
+
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         //intHelper.addInteractor(triPlateInteractor);
+         //intHelper.addInteractor(triBand1Interactor);
+         //intHelper.addInteractor(triBand2Interactor);
+         //intHelper.addInteractor(triBand3Interactor);
+         //intHelper.addInteractor(triBand4Interactor);
+         //intHelper.addInteractor(addWallZminExInt);
+         //intHelper.addInteractor(addWallZmaxExInt);
+         intHelper.addInteractor(pmMeshInt);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallZmaxInt);
+         intHelper.addInteractor(densInteractor);
+         intHelper.addInteractor(velBCInteractor);
+         intHelper.selectBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+
+         //domain decomposition for threads
+         if(numOfThreads > 1)
+         {
+            PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+            grid->accept(pqPartVisitor);
+         }
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Write blocks - start");
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            ppblocks->update(0);
+            UBLOG(logINFO,"Write blocks - end");
+         }
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+         unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+
+         double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+            UBLOG(logINFO,"Available memory per node/8.0 = " << (availMem/8.0) << " bytes");
+         }
+
+         //////////////////////////////////////////
+         //set connectors
+         UBLOG(logINFO,"set connectors - start");
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         UBLOG(logINFO,"set connectors - end");
+
+         ////////////////////////////
+         LBMKernel3DPtr kernel;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+         //with sponge layer
+         //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+         int sizeSP=4;
+         mu::Parser spongeLayer;
+         spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+         spongeLayer.DefineConst("sizeX", nx[0]*blocknx[0]);
+         spongeLayer.DefineConst("sizeSP", sizeSP*blocknx[0]);
+         kernel->setWithSpongeLayer(true);
+         kernel->setSpongeLayer(spongeLayer);
+
+         //BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+         kernel->setBCProcessor(bcProc);
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+
+         intHelper.setBC();
+
+         //////////////////////////////////////////////////////////////////////////
+         ////porous inlay
+         //string pmFilename  = pathGeo + "/CT-2014-039.raw";
+         //int pmNX1=1333;  //abmessung einzelbild in x-richtung
+         //int pmNX2=463; //abmessung einzelbild in y richtung
+         //int pmNX3=1333; //anzahl der bilder
+         //float lthreshold = 27686.97;
+         //float uthreshold = 65535.0;
+
+         //GbVoxelMatrix3DPtr pmMesh(new GbVoxelMatrix3D(pmNX1,pmNX2,pmNX3,0,lthreshold,uthreshold));
+         //pmMesh->readMatrixFromRawFile<unsigned short>(pmFilename);
+
+         //double scaleFactor = 0.001;
+         //double delta = 3.75*scaleFactor;
+         //pmMesh->setVoxelMatrixDelta(delta, delta, delta);
+         //pmMesh->rotate90aroundX(); 
+         //pmMesh->rotate90aroundX();
+         //pmMesh->rotate90aroundX();
+
+         //double inlayXmin = 995.0;
+         //double inlayYmin = 180.0;
+         //double inlayZmin = 8.73;
+
+         //GbCuboid3DPtr inlayBox(new GbCuboid3D(inlayXmin, inlayYmin, inlayZmin, inlayXmin+(double)75, inlayYmin+(double)35, inlayZmin));
+         //if(myid == 0) GbSystem3D::writeGeoObject(inlayBox.get(), pathname+"/geo/inlay"+UbSystem::toString(i), WbWriterVtkXmlASCII::getInstance());
+         //D3Q27InteractorPtr inlayBoxInt = D3Q27InteractorPtr ( new D3Q27Interactor(inlayBox, grid, bcObst,Interactor3D::SOLID));
+         //SetSolidOrTransBlockVisitor v(inlayBoxInt, SetSolidOrTransBlockVisitor::SOLID);
+         //grid->accept(v);
+         //SetSolidOrTransBlockVisitor v(inlayBoxInt, SetSolidOrTransBlockVisitor::TRANS);
+         //grid->accept(v);
+
+         //vector<Block3DPtr> inlayBlocks;
+         //vector<Block3DPtr>& sb = inlayBoxInt->getSolidBlockSet();
+         //inlayBlocks.insert(inlayBlocks.end(), sb.begin(), sb.end());
+         //vector<Block3DPtr>& tb = inlayBoxInt->getTransBlockSet();
+         //inlayBlocks.insert(inlayBlocks.end(), tb.begin(), tb.end());
+
+
+         //int i = 0;
+         //for (int y = 0; y<=35; y+=5)
+         //   for (int x = 0; x<=75; x+=5)
+         //   {
+         //      UBLOG(logINFO,"inlay # "<<i);
+         //      GbVoxelMatrix3DPtr pmM = GbVoxelMatrix3DPtr(pmMesh->clone());
+         //      pmM->setVoxelMatrixDelta(delta, delta, delta);
+         //      pmM->setVoxelMatrixMininum(inlayXmin-(double)x, inlayYmin+(double)y, inlayZmin);
+         //      D3Q27InteractorPtr inlayInt = D3Q27InteractorPtr ( new D3Q27Interactor(pmM, grid, bcObst,Interactor3D::SOLID));
+         //      SetSolidOrTransBlockVisitor v(inlayInt, SetSolidOrTransBlockVisitor::TRANS);
+         //      grid->accept(v);
+         //      inlayInt->initInteractor();
+
+         //      GbCuboid3DPtr inlayBox(new GbCuboid3D(pmM->getX1Minimum(),pmM->getX2Minimum(),pmM->getX3Minimum(),pmM->getX1Maximum(),pmM->getX2Maximum(),pmM->getX3Maximum()));
+         //      if(myid == 0) GbSystem3D::writeGeoObject(inlayBox.get(), pathname+"/geo/inlay"+UbSystem::toString(i), WbWriterVtkXmlASCII::getInstance());
+         //      D3Q27InteractorPtr inlayBoxInt = D3Q27InteractorPtr ( new D3Q27Interactor(inlayBox, grid, bcObst,Interactor3D::SOLID));
+         //      SetSolidOrTransBlockVisitor v1(inlayBoxInt, SetSolidOrTransBlockVisitor::SOLID);
+         //      grid->accept(v1);
+         //      SetSolidOrTransBlockVisitor v2(inlayBoxInt, SetSolidOrTransBlockVisitor::TRANS);
+         //      grid->accept(v2);
+
+         //      vector<Block3DPtr> inlayBlocks;
+         //      vector<Block3DPtr>& sb = inlayBoxInt->getSolidBlockSet();
+         //      //UBLOG(logINFO, "sb.size = "<<sb.size());
+         //      inlayBlocks.insert(inlayBlocks.end(), sb.begin(), sb.end());
+         //      vector<Block3DPtr>& tb = inlayBoxInt->getTransBlockSet();
+         //      //UBLOG(logINFO, "tb.size = "<<tb.size());
+         //      inlayBlocks.insert(inlayBlocks.end(), tb.begin(), tb.end());
+
+         //      //UBLOG(logINFO, "inlayBlocks.size = "<<inlayBlocks.size());
+
+         //      BOOST_FOREACH(Block3DPtr block, inlayBlocks)
+         //      {
+         //         block->setActive(true);
+         //         inlayInt->setDifferencesToGbObject3D(block);
+         //      }
+         //      i++;
+         //   }
+         //////////////////////////////////////////////////////////////////////
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nuLB,rhoLB);
+         initVisitor.setVx1(uLB);
+         grid->accept(initVisitor);
+
+         //Postprozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+      }
+      else
+      {
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      }
+      UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(1,0,3);
+      //visSch->addSchedule(100,100,1000);
+      //visSch->addSchedule(1000,1000,5000);
+      //visSch->addSchedule(5000,5000,100000);
+      //visSch->addSchedule(100000,100000,10000000);
+
+      visSch->addSchedule(100,100,10000000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      double endTime = 10000000;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   if (argc == 1)
+   {
+      cout<<"Command line argument isn't specified!"<<endl;
+      cout<<"plate2 <machine name>"<<endl;
+      return 1;
+   }
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/bbone/CMakeLists.txt b/source/Applications/bbone/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..607daeb54917ea99811cf3c25082b151ec4567a8
--- /dev/null
+++ b/source/Applications/bbone/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bbone)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bbone BINARY)
diff --git a/source/Applications/bbone/bbone.cpp b/source/Applications/bbone/bbone.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5f24304eac06d9b6976ebcb65f76606d7b178940
--- /dev/null
+++ b/source/Applications/bbone/bbone.cpp
@@ -0,0 +1,427 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void sbonepd(string configname)
+{
+   try
+   {
+      Configuration   config;
+      config.load(configname);
+
+      string          pathname          = config.getString("pathname");
+      string          pathGeo           = config.getString("pathGeo");
+      int             numOfThreads      = config.getInt("numOfThreads");
+      string          sampleFilename    = config.getString("sampleFilename");
+      int             pmNX1             = config.getInt("pmNX1");
+      int             pmNX2             = config.getInt("pmNX2");
+      int             pmNX3             = config.getInt("pmNX3");
+      double          lthreshold        = config.getDouble("lthreshold");
+      double          uthreshold        = config.getDouble("uthreshold");
+      double          dp_real           = config.getDouble("dp_real");
+      string          timeSeriesFile    = config.getString("timeSeriesFile");
+      double          restartStep       = config.getDouble("restartStep");
+      double          restartStepStart  = config.getDouble("restartStepStart");
+      double          endTime           = config.getDouble("endTime");
+      double          outTime           = config.getDouble("outTime");
+      double          availMem          = config.getDouble("availMem");
+      double          timeSeriesOutTime = config.getDouble("timeSeriesOutTime");
+      bool            logToFile         = config.getBool("logToFile");
+      double          deltaT            = config.getDouble("deltaT");
+      
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if (logToFile)
+      {
+#if defined(__unix__)
+         if (myid == 0)
+         {
+            const char* str = pathname.c_str();
+            int status = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+         }
+#endif 
+
+         if (myid == 0)
+         {
+            stringstream logFilename;
+            logFilename << pathname + "/logfile" + UbSystem::toString(UbSystem::getTimeStamp()) + ".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+
+
+
+      if (myid == 0) UBLOG(logINFO, "Testcase big bone");
+
+      Grid3DPtr grid(new Grid3D(comm));
+      double deltaVoxel = 11.658e-6;
+
+      double dx = deltaVoxel;
+
+      const int blocknx1 = 64;
+      const int blocknx2 = 64;
+      const int blocknx3 = 64;
+
+      LBMReal rho_LB = 0.0;
+      //nueWasser = 1e-6 m^2/s
+      double nu_real = 1e-6;
+      LBMReal dt = deltaT; //1e-5; // s (frei gewählt)
+      //dx - frei gewählt
+      //
+      LBMReal nu_LB = nu_real / (dx*dx / dt);
+
+
+      //dp = 50000 Pa - 0 Pa = 50000 Pa
+      //rho wasser = 1000 kg*m^-3
+      double rho_real = 1000;
+      //dp/rho = 50000/1000 = 50 m^2/s^2
+      double dp_div_rho_real = dp_real / rho_real;
+
+      double dp_LB = dp_div_rho_real / ((dx / dt)*(dx / dt));
+
+      double rhoLBinflow;
+      rhoLBinflow = dp_LB*3.0;
+     
+      double deltax = dx;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      double coord[6];
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(restartStep, restartStepStart));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+         if (myid == 0) UBLOG(logINFO, "Neustart..");
+
+         string boneFilename = pathGeo + sampleFilename;
+
+         //int pmNX1 = 1164;  //abmessung einzelbild in x-richtung
+         //int pmNX2 = 972; //abmessung einzelbild in y richtung
+         //int pmNX3 = 900; //anzahl der bilder
+         ////int pmNX3 = 10; //anzahl der bilder
+         //float lthreshold = 109.0;
+         //float uthreshold = 255.0;
+
+         GbVoxelMatrix3DPtr bone(new GbVoxelMatrix3D(pmNX1, pmNX2, pmNX3, 0, lthreshold, uthreshold));
+         bone->readMatrixFromRawFile<unsigned char>(boneFilename, GbVoxelMatrix3D::BigEndian);
+         bone->setVoxelMatrixDelta(deltaVoxel, deltaVoxel, deltaVoxel);
+         bone->setVoxelMatrixMininum(0.0, 0.0, 0.0);
+
+         if (myid == 0) bone->writeToVTKImageDataASCII(pathname + "/geo/bone");
+
+         ///////////////////////////////////////////////////////
+
+         ////////////////////////////////////////////////////////////////////////
+
+         double offset = 0.5e-3;
+         //bounding box
+         double g_minX1 = bone->getX1Minimum();
+         double g_minX2 = bone->getX2Minimum();
+         double g_minX3 = bone->getX3Minimum() - offset;
+
+         double g_maxX1 = bone->getX1Maximum();
+         double g_maxX2 = bone->getX2Maximum();
+         double g_maxX3 = bone->getX3Maximum() + offset;
+
+         double blockLength = (double)blocknx1*deltax;
+
+         grid->setPeriodicX1(false);
+         grid->setPeriodicX2(false);
+         grid->setPeriodicX3(false);
+         grid->setDeltaX(deltax);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Parameters:");
+            UBLOG(logINFO, "rho_LB = " << rho_LB);
+            UBLOG(logINFO, "nu_LB = " << nu_LB);
+            UBLOG(logINFO, "dp_LB = " << dp_LB);
+            UBLOG(logINFO, "dx = " << dx << " m");
+            UBLOG(logINFO, "dt = " << dt << " s");
+            UBLOG(logINFO, "rho_real = " << rho_real << " kg*m^-3");
+            UBLOG(logINFO, "nu_real = " << nu_real << " m^2/s");
+            UBLOG(logINFO, "dp_real = " << dp_real << " Pa");
+
+            UBLOG(logINFO, "number of levels = " << refineLevel + 1);
+            UBLOG(logINFO, "numOfThreads = " << numOfThreads);
+            UBLOG(logINFO, "path = " << pathname);
+            UBLOG(logINFO, "Preprozess - start");
+         }
+
+         //cylinder
+         double radius = 0.0036;
+         double cx1 = 0.007;
+         double cx2 = 0.0046;
+
+         GbObject3DPtr cylinder(new GbCylinder3D(cx1, cx2, g_minX3 - offset, cx1, cx2, g_maxX3 + offset, radius));
+         GbSystem3D::writeGeoObject(cylinder.get(), pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow(new GbCuboid3D(g_minX1 - blockLength, g_minX2 - blockLength, g_minX3 - blockLength, g_maxX1 + blockLength, g_maxX2 + blockLength, g_minX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname + "/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow(new GbCuboid3D(g_minX1 - blockLength, g_minX2 - blockLength, g_maxX3, g_maxX1 + blockLength, g_maxX2 + blockLength, g_maxX3 + blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname + "/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+         //bone interactor
+         int bcOptionBone = 1; //0=simple Bounce Back, 1=quadr. BB, 2=thin wall
+         D3Q27BoundaryConditionAdapterPtr bcBone(new D3Q27NoSlipBCAdapter(bcOptionBone));
+         D3Q27InteractorPtr boneInt(new D3Q27Interactor(bone, grid, bcBone, Interactor3D::SOLID));
+
+         //wall interactors
+         int bcOptionWall = 1; //0=simple Bounce Back, 1=quadr. BB, 2=thin wall
+         D3Q27BoundaryConditionAdapterPtr bcWall(new D3Q27NoSlipBCAdapter(bcOptionWall));
+         D3Q27InteractorPtr cylInt(new D3Q27Interactor(cylinder, grid, bcWall, Interactor3D::INVERSESOLID));
+
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterInflow(new D3Q27DensityBCAdapter(rhoLBinflow));
+         denBCAdapterInflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoInflow, grid, denBCAdapterInflow, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterOutflow(new D3Q27DensityBCAdapter(rho_LB));
+         denBCAdapterOutflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoOutflow, grid, denBCAdapterOutflow, Interactor3D::SOLID));
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::BSW));
+         ////////////////////////////////////////////
+         //Zoltan
+         //Grid3DVisitorPtr zoltanVisitor(new ZoltanPartitioningGridVisitor(comm, D3Q27System::BSW, 1));
+         //////////////////////////////////////////////////////////////////////////
+         /////delete solid blocks
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(boneInt);
+         intHelper.addInteractor(cylInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - end");
+         //////////////////////////////////////
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nod = nob * (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nodg = nob * (blocknx1 + gl) * (blocknx2 + gl) * (blocknx3 + gl);
+         double needMemAll = double(nodg*(27 * sizeof(double) + sizeof(int) + sizeof(float) * 4));
+         double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Number of blocks = " << nob);
+            UBLOG(logINFO, "Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for (int level = minInitLevel; level <= maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO, "Number of blocks for level " << level << " = " << nobl);
+               UBLOG(logINFO, "Number of nodes for level " << level << " = " << nobl*nodb);
+            }
+            UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+            UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+            UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         //BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         BoundaryConditionPtr densityBC(new NonEqDensityBoundaryCondition());
+         BoundaryConditionPtr noSlipBC(new NoSlipBoundaryCondition());
+         bcProc->addBC(densityBC);
+         bcProc->addBC(noSlipBC);
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nu_LB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         //BC
+         intHelper.setBC();
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         //Press*1.6e8+(14.76-coordsX)/3.5*5000
+         //initialization of distributions
+         mu::Parser fct;
+         fct.SetExpr("(x3max-x3)/l*dp*3.0");
+         fct.DefineConst("dp", dp_LB);
+         fct.DefineConst("x3max", g_maxX3);
+         fct.DefineConst("l", g_maxX3-g_minX3);
+
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nu_LB, rho_LB);
+         initVisitor.setRho(fct);
+         //initVisitor.setVx1(fct);
+         //initVisitor.setVx1(0.0);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+
+         coord[0] = bone->getX1Minimum();
+         coord[1] = bone->getX2Minimum();
+         coord[2] = bone->getX3Minimum();//cylinder->getX3Centroid();
+         coord[3] = bone->getX1Maximum();
+         coord[4] = bone->getX2Maximum();
+         coord[5] = bone->getX3Maximum(); //cylinder->getX3Centroid();
+
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "w");
+         fprintf(pFile, "%g\n", coord[0]);
+         fprintf(pFile, "%g\n", coord[1]);
+         fprintf(pFile, "%g\n", coord[2]);
+         fprintf(pFile, "%g\n", coord[3]);
+         fprintf(pFile, "%g\n", coord[4]);
+         fprintf(pFile, "%g\n", coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+         grid->addInteractor(inflowInt);
+         if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+      }
+      else
+      {
+         Grid3D::Interactor3DSet interactors = grid->getInteractors();
+         interactors[0]->setGrid3D(grid);
+         boost::dynamic_pointer_cast<D3Q27Interactor>(interactors[0])->deleteBCAdapter();
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterFront(new D3Q27DensityBCAdapter(rhoLBinflow));
+         boost::dynamic_pointer_cast<D3Q27Interactor>(interactors[0])->addBCAdapter(denBCAdapterFront);
+         interactors[0]->updateInteractor();
+
+         UBLOG(logINFO, "rhoLBinflow = "<<rhoLBinflow);
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "r");
+         fscanf(pFile, "%lg\n", &coord[0]);
+         fscanf(pFile, "%lg\n", &coord[1]);
+         fscanf(pFile, "%lg\n", &coord[2]);
+         fscanf(pFile, "%lg\n", &coord[3]);
+         fscanf(pFile, "%lg\n", &coord[4]);
+         fscanf(pFile, "%lg\n", &coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+      }
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      //stepSch->addSchedule(10, 10, 10);
+      //stepSch->addSchedule(100, 100, 100);
+      //stepSch->addSchedule(1000, 1000, 1000);
+      //stepSch->addSchedule(100, 1500, 2000);
+      //stepSch->addSchedule(10000, 10000, 10000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+      double dxd2 = deltax / 2.0;
+      D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, coord[0], coord[1], coord[2] - dxd2*10.0,
+         coord[3], coord[4], coord[2] - dxd2*10.0 - 2.0*dxd2));
+      D3Q27IntegrateValuesHelperPtr ih2(new D3Q27IntegrateValuesHelper(grid, comm, coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]));
+      D3Q27IntegrateValuesHelperPtr ih3(new D3Q27IntegrateValuesHelper(grid, comm, coord[0], coord[1], coord[5] + dxd2*10.0,
+         coord[3], coord[4], coord[5] + dxd2*10.0 + 2.0*dxd2));
+
+      if (myid == 0) GbSystem3D::writeGeoObject(ih1->getBoundingBox().get(), pathname + "/geo/ih1", WbWriterVtkXmlBinary::getInstance());
+      if (myid == 0) GbSystem3D::writeGeoObject(ih2->getBoundingBox().get(), pathname + "/geo/ih2", WbWriterVtkXmlBinary::getInstance());
+      if (myid == 0) GbSystem3D::writeGeoObject(ih3->getBoundingBox().get(), pathname + "/geo/ih3", WbWriterVtkXmlBinary::getInstance());
+
+      UbSchedulerPtr stepMV(new UbScheduler(timeSeriesOutTime));
+
+      TimeseriesPostprocessor tsp1(grid, stepMV, ih1, pathname+timeSeriesFile+"_1", comm);
+      TimeseriesPostprocessor tsp2(grid, stepMV, ih2, pathname+timeSeriesFile+"_2", comm);
+      TimeseriesPostprocessor tsp3(grid, stepMV, ih3, pathname+timeSeriesFile+"_3", comm);
+
+      if (myid == 0)
+      {
+         UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepMV));
+      if (myid == 0) UBLOG(logINFO, "Simulation-start");
+      calculation->calculate();
+      if (myid == 0) UBLOG(logINFO, "Simulation-end");
+   }
+   catch (exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch (string& s)
+   {
+      cerr << s << endl;
+   }
+   catch (...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+
+   if (argv != NULL)
+   {
+      if (argv[1] != NULL)
+         sbonepd(string(argv[1]));
+   }
+
+   return 0;
+}
diff --git a/source/Applications/bbone/configBombadilBone.txt b/source/Applications/bbone/configBombadilBone.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b5fa00058f05e277ea2418d9c33890129bec18ce
--- /dev/null
+++ b/source/Applications/bbone/configBombadilBone.txt
@@ -0,0 +1,46 @@
+#
+#Simulation parameters for determitatoin of permeability
+#SBP120
+
+pathname = d:/temp/bbone2
+pathGeo = d:/Data/Bone/BigBone
+numOfThreads = 4
+availMem = 3e9
+logToFile = false
+
+#porous media
+#rawFile = false
+sampleFilename = /cyl_bone2.raw
+
+#diminsions [voxel]
+pmNX1 = 1164
+pmNX2 = 972
+pmNX3 = 900
+
+#threshold
+lthreshold = 109
+uthreshold = 255
+
+#diminsions [m]
+#pmL1 = 1.87e-3
+#pmL2 = 1.87e-3
+#pmL3 = 1.87e-3
+
+#grid
+#blocknx = 30
+#nx3 = 5
+#blocknx = 50
+#nx3 = 10
+#spongeLayer=true
+
+#physic
+dp_real = 1
+
+timeSeriesFile = /timeseries/bone1
+timeSeriesOutTime = 10
+
+restartStep = 20000
+restartStepStart=20000
+
+endTime = 60000
+outTime = 100
diff --git a/source/Applications/bbone/configLudwigBone.cfg b/source/Applications/bbone/configLudwigBone.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..7ce59bfdbef2929d9e9bef8e8fbcf0c831a4a9fc
--- /dev/null
+++ b/source/Applications/bbone/configLudwigBone.cfg
@@ -0,0 +1,33 @@
+#
+#Simulation parameters for determitatoin of permeability
+#SBP120
+
+pathname = /hpc3lustre/work/koskuche/Bone/BigBone2
+pathGeo = /hpc3lustre/work/koskuche/Bone/data/bbone
+numOfThreads = 4
+availMem = 11e9
+logToFile = true
+
+#porous media
+sampleFilename = /cyl_bone2.raw
+
+#diminsions [voxel]
+pmNX1 = 1164
+pmNX2 = 972
+pmNX3 = 900
+
+#threshold
+lthreshold = 109
+uthreshold = 255
+
+#physic
+dp_real = 1
+
+timeSeriesFile = /timeseries/bone1
+timeSeriesOutTime = 10
+
+restartStep = 20000
+restartStepStart=20000
+
+endTime = 60000
+outTime = 10000
diff --git a/source/Applications/block_test/CMakeLists.txt b/source/Applications/block_test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..81b15cecd490f9f39a455956c8db9b1af7631dfc
--- /dev/null
+++ b/source/Applications/block_test/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(block_test)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(block_test BINARY)
diff --git a/source/Applications/block_test/block_test.cpp b/source/Applications/block_test/block_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..92f3ff2bb2506324caeae7ae5d6243ea56b9a98b
--- /dev/null
+++ b/source/Applications/block_test/block_test.cpp
@@ -0,0 +1,20 @@
+#include "block_test_incompressible.hpp"
+
+int main(int argc, char* argv[])
+{
+
+   if ( argv != NULL )
+   {
+      if (argc > 1)
+      {
+         block_test_incompressible(argv[1], argv[2]);
+      }
+      else
+      {
+         cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+      }
+   }
+
+   return 0;
+}
+
diff --git a/source/Applications/block_test/block_test_all.hpp b/source/Applications/block_test/block_test_all.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c51e77b162017322623eeca0e467f6eb482ed3d1
--- /dev/null
+++ b/source/Applications/block_test/block_test_all.hpp
@@ -0,0 +1,397 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "D3Q27PressureDifferencePostprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "RestartPostprocessor.h"
+#include "SolidBlocksHelper.h"
+#include "NUPSCounterPostprocessor.h"
+#include "BlocksPostprocessor.h"
+#include "LBMKernelETD3Q27BGK.h"
+#include "EmergencyExitPostprocessor.h"
+#include "D3Q27ForcesPostprocessor.h"
+#include "ConfigFileReader.h"
+#include "MemoryUtil.h"
+#include "LBMKernelETD3Q27CCLB.h"
+
+
+using namespace std;
+
+
+void block_test_all(const char *cstr)
+{
+   try
+   {
+      ConfigFileReader cf(cstr);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname = cf.getValue("path"); 
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+      double availMem = 0;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         //pathname = "c:/temp/block_test";
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         //pathname = "/work/koskuche/scratch/block_test";
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = 1;
+
+      const int blocknx1 = UbSystem::stringTo<int>(cf.getValue("blocknx1")); //16;
+      const int blocknx2 = UbSystem::stringTo<int>(cf.getValue("blocknx2"));//16;
+      const int blocknx3 = UbSystem::stringTo<int>(cf.getValue("blocknx3"));//16;
+
+      const int gridNx1 = UbSystem::stringTo<int>(cf.getValue("gridNx1"));//3;
+      const int gridNx2 = UbSystem::stringTo<int>(cf.getValue("gridNx2"));//3;
+      const int gridNx3 = UbSystem::stringTo<int>(cf.getValue("gridNx3"));//3;
+
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3, H;
+      L2 = L3 = H = gridNx2*blocknx1;
+
+      LBMReal radius = 3;
+      LBMReal uLB = 0.05;
+      LBMReal Re = 300.0;
+      LBMReal rhoLB = 1.0;
+      LBMReal l = L2 / dx;
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = UbSystem::stringTo<int>(cf.getValue("refineLevel"));
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(L1*0.5, L2*0.5, 0, L1*0.5, L2*0.5, L3, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27InteractorPtr cylinderInt;
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = dx;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      double blockLength = blocknx1*dx;
+
+      //refinement area
+      double off = 1;
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-off, cylinder->getX2Minimum()-off, cylinder->getX3Minimum(), 
+         cylinder->getX1Maximum()+off, cylinder->getX2Maximum()+off, cylinder->getX3Maximum()));
+
+      Grid3DPtr grid(new Grid3D(blocknx1, blocknx2, blocknx3, gridNx1, gridNx2, gridNx3));
+
+
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"Parameters:");
+         UBLOG(logINFO,"L = " << L2/dx );
+         UBLOG(logINFO,"v = " << uLB );
+         UBLOG(logINFO,"rho = " << rhoLB );
+         UBLOG(logINFO,"nue = " << nueLB );
+         UBLOG(logINFO,"Re = " << Re );
+         UBLOG(logINFO,"dx = " << dx );
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+         UBLOG(logINFO,"Preprozess - start");
+      }
+
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+      //walls
+      GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+      //inflow
+      GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      //outflow
+      GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+      if (refineLevel > 0)
+      {
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+         RefineCrossAndInsideGbObjectBlockVisitor refVisitor(refineCube, baseLevel, refineLevel-1);
+         grid->accept(refVisitor);
+
+         RatioBlockVisitor ratioVisitor(refineLevel);
+         grid->accept(ratioVisitor);
+
+         RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+         grid->accept(ratioSmoothVisitor);
+
+         OverlapBlockVisitor overlapVisitor(refineLevel);
+         grid->accept(overlapVisitor);
+
+         std::vector<int> dirs;
+         D3Q27System::getLBMDirections(dirs);
+         SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+         grid->accept(interDirsVisitor);
+         if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      }
+
+      MetisPartitioningGridVisitor metisVisitor(numOfThreads, D3Q27System::B, comm, true);
+      grid->accept( metisVisitor );
+
+      SolidBlocksHelper sd(grid, comm);
+
+      int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+      cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+      //walls
+      D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+      mu::Parser fct;
+      fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+      fct.DefineConst("U", uLB);
+      fct.DefineConst("H", H);
+
+      //inflow
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+      velBCAdapter->setSecondaryBcOption(2);
+      D3Q27BoundaryConditionAdapterPtr denBCAdapterFront(new D3Q27DensityBCAdapter(rhoLB));
+      denBCAdapterFront->setSecondaryBcOption(1);
+      D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+      //D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, bcObst, Interactor3D::SOLID));
+
+      //outflow
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+      denBCAdapter->setSecondaryBcOption(1);
+      D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+      //D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, bcObst,Interactor3D::SOLID));
+
+      //sd.addInteractor(cylinderInt);
+      sd.addInteractor(addWallYminInt);
+      sd.addInteractor(addWallZminInt);
+      sd.addInteractor(addWallYmaxInt);
+      sd.addInteractor(addWallZmaxInt);
+      sd.addInteractor(inflowInt);
+      sd.addInteractor(outflowInt);
+
+      sd.deleteSolidBlocks();
+
+      grid->accept( metisVisitor );
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition for threads
+      //PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      //grid->accept(pqPartVisitor);
+
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nodb = (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nod = nob * (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+      double needMemAll  = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         int minInitLevel = grid->getCoarsestInitializedLevel();
+         int maxInitLevel = grid->getFinestInitializedLevel();
+         for(int level = minInitLevel; level<=maxInitLevel; level++)
+         {
+            int nobl = grid->getNumberOfBlocks(level);
+            UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nob);
+            UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nob*nodb);
+         }
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      int kernelType = UbSystem::stringTo<int>(cf.getValue("kernel"));
+      LBMKernel3DPtr kernel;
+      if (kernelType == 0)
+      {
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+      }
+      else if (kernelType == 1)
+      {
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+      }
+      else if (kernelType == 2)
+      {
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3));
+      }
+
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      if (refineLevel > 0)
+      {
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+      //walls
+      grid->addAndInitInteractor(addWallYminInt);
+      grid->addAndInitInteractor(addWallZminInt);
+      grid->addAndInitInteractor(addWallYmaxInt);
+      grid->addAndInitInteractor(addWallZmaxInt);
+
+      //obstacle
+      //grid->addAndInitInteractor(cylinderInt);
+
+      //inflow
+      grid->addAndInitInteractor(inflowInt);
+
+      //outflow
+      grid->addAndInitInteractor(outflowInt);
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+      //initVisitor.setVx1(fct);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+      ppgeo->update(0);
+      ppgeo.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 1.0;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      //UbSchedulerPtr stepSch(new UbScheduler());
+      //stepSch->addSchedule(10, 100, 1000);
+      //nodeSch->addSchedule(1000, 1000, 10000);
+      //nodeSch->addSchedule(10000, 10000, 50000);
+      //stepSch->addSchedule(100, 100, 1000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      UbSchedulerPtr visSch(new UbScheduler());
+      //UbSchedulerPtr visSch(stepSch);
+      double endTime = UbSystem::stringTo<int>(cf.getValue("endTime"));//10001.0;
+
+      //cout << "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem()<<endl;
+      //cout << "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed()<<endl;
+      //cout << "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe()<<endl;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
\ No newline at end of file
diff --git a/source/Applications/block_test/block_test_incompressible.hpp b/source/Applications/block_test/block_test_incompressible.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..eaa6c1b78838a64416465e2ceabc55a1e1bb4ceb
--- /dev/null
+++ b/source/Applications/block_test/block_test_incompressible.hpp
@@ -0,0 +1,522 @@
+#include <iostream>
+#include <string>
+
+#include <boost/pointer_cast.hpp>
+
+#include "vfluids.h"
+
+using namespace std;
+
+#include <omp.h>
+
+void block_test_incompressible(const char *cstr1, const char *cstr2)
+{
+
+   try
+   {
+
+      //Sleep(30000);
+
+      ConfigFileReader cf(cstr1);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname = cf.getValue("path"); 
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         //pathname = "c:/temp/block_test";
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         //pathname = "/work/koskuche/scratch/block_test";
+         availMem = 12.0e9;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+
+      //if(myid ==0)
+      //{
+      //   UbLog::reportingLevel() = logDEBUG5;
+      //   stringstream logFilename;
+      //   logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+      //   UbLog::output_policy::setStream(logFilename.str());
+      //}
+
+      double dx = 1.0;
+
+      const int blocknx1 = UbSystem::stringTo<int>(cf.getValue("blocknx1")); //16;
+      const int blocknx2 = UbSystem::stringTo<int>(cf.getValue("blocknx2"));//16;
+      const int blocknx3 = UbSystem::stringTo<int>(cf.getValue("blocknx3"));//16;
+
+      const int gridNx1 = UbSystem::stringTo<int>(cf.getValue("gridNx1"));//3;
+      const int gridNx2 = UbSystem::stringTo<int>(cf.getValue("gridNx2"));//3;
+      const int gridNx3 = UbSystem::stringTo<int>(cf.getValue("gridNx3"));//3;
+
+
+      double L1 = gridNx1*blocknx1*dx;
+      double L2, L3, H;
+      L2 = L3 = H = gridNx2*blocknx1*dx;
+
+      LBMReal radius = 3.0*dx;
+      LBMReal uLB = 0.01;
+      LBMReal Re = 0.5;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+      LBMReal nuLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+      //LBMReal nueLB = 0.005842;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = UbSystem::stringTo<int>(cf.getValue("refineLevel"));
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = 0.0;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      double blockLength = blocknx1*dx;
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(L1*0.5-2*blockLength, L2*0.5+dx, -1.0*dx, L1*0.5-2*blockLength, L2*0.5+dx, L3+1.0*dx, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27InteractorPtr cylinderInt;
+      D3Q27InteractorPtr addWallZminInt;
+
+      //refinement area
+      double off = dx;
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-off, cylinder->getX2Minimum()-off, cylinder->getX3Minimum(), 
+         cylinder->getX1Maximum()+off, cylinder->getX2Maximum()+off, cylinder->getX3Maximum()));
+
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance()); 
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+      //Grid3DPtr grid(new Grid3D(comm, blocknx1, blocknx2, blocknx3, gridNx1, gridNx2, gridNx3));
+      //grid->setPeriodicX1(true);
+      //grid->setPeriodicX2(true);
+      //grid->setPeriodicX3(true);
+
+      double outTime = 1.0;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      //PostprocessorPtr pp; //(new D3Q27MacroscopicQuantitiesPostprocessor(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlASCII::getInstance(), conv, comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(1000,10,10000));
+      //RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         //rp->addPostprocessor(pp);
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"Parameters:");
+            UBLOG(logINFO,"L = " << L2/dx );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nuLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+            UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+blockLength, d_minX2, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+blockLength, d_maxX2+blockLength, d_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-blockLength, d_maxX2, d_minX3-blockLength, d_maxX1+blockLength, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_maxX3, d_maxX1+blockLength, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-blockLength, d_minX2-blockLength, d_minX3-blockLength, d_minX1, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-blockLength, d_minX3-blockLength, d_maxX1+blockLength, d_maxX2+blockLength, d_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         //GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2-2*dx, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         //if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         //GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3-2*dx, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         //if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         ////inflow
+         //GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1+2*dx, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         //if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         ////outflow
+         //GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1-2*dx, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         //if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineCube, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+
+         int bbOptionC = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObstC(new D3Q27NoSlipBCAdapter(bbOptionC));
+         cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObstC,Interactor3D::SOLID));
+
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         addWallZminInt = D3Q27InteractorPtr(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+         mu::Parser fct;
+         //fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+         //fct.SetExpr("-4*U*(x2^2-H*x2)/H^2");
+         //fct.DefineConst("U", 3/2*uLB);
+         //fct.DefineConst("H", H);
+
+         fct.SetExpr("U");
+         fct.DefineConst("U", uLB);
+
+         //inflow
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         //double dp_Ph=0.1*10000.0;//
+         //double dp_lb=dp_Ph*0.001*(nueLB*dx)*(nueLB*dx);//nue_ph=10e-6
+         //if(myid == 0) UBLOG(logINFO,"dp_lb = " << dp_lb );
+         //D3Q27BoundaryConditionAdapterPtr denBCAdapterFront(new D3Q27DensityBCAdapter(3.0*(dp_lb-rhoLB)));
+         //denBCAdapterFront->setSecondaryBcOption(0);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+         //D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, denBCAdapterFront, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(0);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+         //D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, bcObst,Interactor3D::SOLID));
+
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(cylinderInt);
+         intHelper.addInteractor(addWallYminInt);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallYmaxInt);
+         intHelper.addInteractor(addWallZmaxInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1) * (blocknx2) * (blocknx3);
+         unsigned long nod = nob * (blocknx1) * (blocknx2) * (blocknx3);
+         unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+         double needMemAll  = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for(int level = minInitLevel; level<=maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nob);
+               UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nob*nodb);
+            }
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         //int kernelType = UbSystem::stringTo<int>(cf.getValue("kernel"));
+         LBMKernel3DPtr kernel;
+         //if (kernelType == 0)
+         //{
+         //   rhoLB = 1.0;
+         //   kernel = LBMKernel3DPtr(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+         //}
+         //else if (kernelType == 1)
+         //{
+         //   rhoLB = 1.0;
+         //   kernel = LBMKernel3DPtr(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+         //}
+         //else if (kernelType == 2)
+         //{
+            rhoLB = 0.0;
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+            //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+            //int nx[4];
+            //nx[0]=gridNx1*blocknx1*(1<<refineLevel);
+            //nx[1]=gridNx2*blocknx2*(1<<refineLevel);
+            //nx[2]=gridNx3*blocknx3*(1<<refineLevel);
+            //nx[3]=refineLevel+1;
+            //EsoTwistD3Q27SparseData::setSize(nx);
+            //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBSparse(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLBSparse::NORMAL));
+            //kernel = LBMKernel3DPtr(new LBMKernelESD3Q27CCLB(blocknx1, blocknx2, blocknx3, grid));
+            //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBex(blocknx1, blocknx2, blocknx3, 0, grid));
+         //}
+
+         //int sizeSP=2;
+         //mu::Parser spongeLayer;
+         //spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+         //spongeLayer.DefineConst("sizeX", gridNx1*blocknx1);
+         //spongeLayer.DefineConst("sizeSP", sizeSP*blocknx1);
+         //kernel->setWithSpongeLayer(true);
+         //kernel->setSpongeLayer(spongeLayer);
+
+
+
+         //mu::Parser fctForcingX1;
+         //fctForcingX1.SetExpr("Fx1");
+         //fctForcingX1.DefineConst("Fx1", 9.99685e-7);
+
+         //kernel->setForcingX1(fctForcingX1);
+         //kernel->setWithForcing(true);
+         //
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         //BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+
+         grid->accept(kernelVisitor);
+
+         //////////////////////////////////////////////////////////////////////////
+         //Experemintel
+         //////////////////////////////////////////////////////////////////////////
+         //int minInitLevel = grid->getCoarsestInitializedLevel();
+
+         //for(int level = minInitLevel; level<=maxInitLevel; level++)
+         //{
+         //   vector<Block3DPtr> blockVector;
+         //   grid->getBlocks(level, blockVector);
+         //   BOOST_FOREACH(Block3DPtr block, blockVector)
+         //   {
+         //      if (block)
+         //      {
+         //         boost::dynamic_pointer_cast<LBMKernelESD3Q27CCLB>(block->getKernel())->initNeighbours();
+         //      }
+         //   }
+         //}
+         //////////////////////////////////////////////////////////////////////////
+
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //UbSchedulerPtr geoSch(new UbScheduler(1));
+         //D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         // new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+         //ppgeo->update(0);
+         //ppgeo.reset();
+
+         //return;
+
+         intHelper.setBC();
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nuLB, rhoLB);
+         //initVisitor.setVx1(fct);
+         //initVisitor.setNu(nueLB);
+         //initVisitor.setVx1(0.01);
+         //initVisitor.setVx2(0.02);
+         //initVisitor.setVx3(0.03);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         //UbSchedulerPtr geoSch(new UbScheduler(1));
+         //D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         //   new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+         //ppgeo->update(0);
+         //ppgeo.reset();
+
+         {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            //D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+            D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+               new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+            //grid->addObserver(ppgeo);
+            grid->doPostProcess(0);
+            //grid->notifyObservers(0);
+            //grid->removeObserver(ppgeo);
+         }
+
+         //grid->notifyObservers(0);
+
+         //UbSchedulerPtr stepSch(new UbScheduler(outTime));
+         //D3Q27MacroscopicQuantitiesPostprocessorPtr pp(new D3Q27MacroscopicQuantitiesPostprocessor(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlASCII::getInstance(), conv));
+         //rp->addPostprocessor(pp);
+
+         //for (int i=0; i < 10; i++)
+         //{
+         //   grid->doPostProcess(i);
+         //}
+
+         //return;
+
+         //UbSchedulerPtr rs(new UbScheduler(3));
+         //D3Q27ShearStressPostprocessorPtr shsPp(new D3Q27ShearStressPostprocessor(grid,pathname + "/shs/shs", WbWriterVtkXmlASCII::getInstance(), stepSch, rs));
+         //shsPp->addInteractor(boost::dynamic_pointer_cast<D3Q27Interactor>(addWallZminInt));
+         //rp->addPostprocessor(shsPp);
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+
+      else
+      {
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      }
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      //UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(1,1,3);
+      //visSch->addSchedule(100,100,1000);
+      //visSch->addSchedule(1000,1000,5000);
+      //visSch->addSchedule(5000,5000,100000);
+      //visSch->addSchedule(100000,100000,10000000);
+
+      
+      D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, gridCube->getX1Minimum(), gridCube->getX2Minimum(), gridCube->getX3Minimum(), 
+         gridCube->getX1Maximum(), gridCube->getX2Maximum(), gridCube->getX3Maximum()));
+      if (myid == 0) GbSystem3D::writeGeoObject(ih1->getBoundingBox().get(), pathname + "/geo/ih1", WbWriterVtkXmlBinary::getInstance());
+
+      double factorp = 1; // dp_real / dp_LB;
+      double factorv = 1;// dx / dt;
+      UbSchedulerPtr stepMV(new UbScheduler(500));
+
+      TimeseriesPostprocessor tsp(grid, stepMV, ih1, pathname+cf.getValue("timeSeriesOut"), comm);
+
+      UbSchedulerPtr visSch(stepSch);
+
+      //UbSchedulerPtr avSch(new UbScheduler());
+      //avSch->addSchedule(100,100,10000);
+      //
+      //double startStep = 32000;
+      //UbSchedulerPtr resSchRMS(new UbScheduler());
+      //resSchRMS->addSchedule(100000, startStep, 10000000);
+      //UbSchedulerPtr resSchMeans(new UbScheduler());
+      //resSchMeans->addSchedule(100000, startStep, 10000000);
+      //UbSchedulerPtr stepAvSch(new UbScheduler());
+      //int averageInterval=100;
+      //stepAvSch->addSchedule(averageInterval,0,10000000);
+
+      //AverageValuesPostprocessor Avpp(grid, pathname, WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/, stepAvSch/*wann wird gemittelt*/, resSchMeans,resSchRMS/*wann wird resettet*/);
+
+      UbSchedulerPtr emSch(new UbScheduler(100));
+      //EmergencyExitPostprocessor empr(grid, emSch, pathname, RestartPostprocessorPtr(&rp), comm);
+
+      //rp->addPostprocessor(avPp);
+
+      //D3Q27ShearStressPostprocessor shs(grid,pathname, WbWriterVtkXmlASCII::getInstance(), stepSch, resSchMeans);
+      //shs.addInteractor(boost::dynamic_pointer_cast<D3Q27Interactor>(addWallZminInt));
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlASCII::getInstance(), conv);
+
+      //UbSchedulerPtr visSch(new UbScheduler(1));
+
+      double endTime = UbSystem::stringTo<int>(cf.getValue("endTime"));//10001.0;
+
+      cout << "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe()<<endl;
+
+      //#pragma omp parallel num_threads(4)
+      //      {
+      //         int i = omp_get_thread_num();
+      //         printf_s("Hello from thread %d\n", i);
+      //      }
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+
+
diff --git a/source/Applications/block_test/block_test_periodic.hpp b/source/Applications/block_test/block_test_periodic.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ab6d2ad4145b00f94ce41434328479d12b29980e
--- /dev/null
+++ b/source/Applications/block_test/block_test_periodic.hpp
@@ -0,0 +1,430 @@
+#include <iostream>
+#include <string>
+
+#include "vfluids.h"
+
+using namespace std;
+
+
+void block_test_periodic(const char *cstr1, const char *cstr2)
+{
+   try
+   {
+      ConfigFileReader cf(cstr1);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname = cf.getValue("path"); 
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+      double availMem = 0;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         //pathname = "c:/temp/block_test";
+         availMem = 3.0e9;
+      }
+      else if(machine == "HICEGATE0")      
+      {
+         //pathname = "/work/koskuche/scratch/block_test";
+         availMem = 6.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = 1;
+
+      const int blocknx1 = UbSystem::stringTo<int>(cf.getValue("blocknx1")); //16;
+      const int blocknx2 = UbSystem::stringTo<int>(cf.getValue("blocknx2"));//16;
+      const int blocknx3 = UbSystem::stringTo<int>(cf.getValue("blocknx3"));//16;
+
+      const int gridNx1 = UbSystem::stringTo<int>(cf.getValue("gridNx1"));//3;
+      const int gridNx2 = UbSystem::stringTo<int>(cf.getValue("gridNx2"));//3;
+      const int gridNx3 = UbSystem::stringTo<int>(cf.getValue("gridNx3"));//3;
+
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3, H;
+      L2 = L3 = H = gridNx2*blocknx1;
+
+      LBMReal radius = 3;
+      LBMReal uLB = 0.05;
+      LBMReal Re = 20.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+      //LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+      LBMReal nueLB = 0.05842;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = UbSystem::stringTo<int>(cf.getValue("refineLevel"));
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(L1*0.5, L2*0.5, 0, L1*0.5, L2*0.5, L3, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27InteractorPtr cylinderInt;
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = dx;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      double blockLength = blocknx1*dx;
+
+      //refinement area
+      double off = 1;
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-off, cylinder->getX2Minimum()-off, cylinder->getX3Minimum(), 
+         cylinder->getX1Maximum()+off, cylinder->getX2Maximum()+off, cylinder->getX3Maximum()));
+
+      Grid3DPtr grid(new Grid3D(comm, blocknx1, blocknx2, blocknx3, gridNx1, gridNx2, gridNx3));
+      grid->setPeriodicX1(true);
+      grid->setPeriodicX2(true);
+      grid->setPeriodicX3(true);
+
+      UbSchedulerPtr rSch(new UbScheduler());
+      rSch->addSchedule(5000, 5000, 5000);
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::TXT));
+
+      std::string opt;
+
+      if(cstr2!= NULL)
+         opt = std::string(cstr2);
+
+      if/*(cstr== NULL)*/(cstr2!= NULL)
+      {
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+
+         SetForcingBlockVisitor forcingVisitor(0.0, 0.0, 0.0);
+         grid->accept(forcingVisitor);
+
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+      }
+      else
+{
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"Parameters:");
+         UBLOG(logINFO,"L = " << L2/dx );
+         UBLOG(logINFO,"v = " << uLB );
+         UBLOG(logINFO,"rho = " << rhoLB );
+         UBLOG(logINFO,"nue = " << nueLB );
+         UBLOG(logINFO,"Re = " << Re );
+         UBLOG(logINFO,"dx = " << dx );
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"number of threads = " << numOfThreads );
+         UBLOG(logINFO,"number of processes = " << comm->getNumberOfProcesses() );
+         UBLOG(logINFO,"Preprocess - start");
+      }
+
+      //if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+      //walls
+      GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+      //if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+      //inflow
+      GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      //outflow
+      GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+      //GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2-2*dx, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+      //GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3-2*dx, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+      ////inflow
+      //GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1+2*dx, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      ////outflow
+      //GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1-2*dx, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      //if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+//      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+      if (refineLevel > 0)
+      {
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+         RefineCrossAndInsideGbObjectBlockVisitor refVisitor(refineCube, refineLevel);
+         grid->accept(refVisitor);
+
+         RatioBlockVisitor ratioVisitor(refineLevel);
+         grid->accept(ratioVisitor);
+
+         RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+         grid->accept(ratioSmoothVisitor);
+
+         OverlapBlockVisitor overlapVisitor(refineLevel);
+         grid->accept(overlapVisitor);
+
+         std::vector<int> dirs;
+         D3Q27System::getLBMDirections(dirs);
+         SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+         grid->accept(interDirsVisitor);
+         if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      }
+
+      MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+      grid->accept( metisVisitor );
+
+      SolidBlocksHelper sd(grid, comm);
+
+      int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+      cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+      //walls
+      D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+      mu::Parser fct;
+      fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+      fct.DefineConst("U", uLB);
+      fct.DefineConst("H", H);
+      fct.SetExpr("U");
+
+      //inflow
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+      velBCAdapter->setSecondaryBcOption(2);
+      //D3Q27BoundaryConditionAdapterPtr denBCAdapterFront(new D3Q27DensityBCAdapter(rhoLB));
+      //denBCAdapterFront->setSecondaryBcOption(1);
+      D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+      //D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, bcObst, Interactor3D::SOLID));
+
+      //outflow
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+      denBCAdapter->setSecondaryBcOption(1);
+      D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+      //D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, bcObst,Interactor3D::SOLID));
+
+      //sd.addInteractor(cylinderInt);
+      //sd.addInteractor(addWallYminInt);
+      //sd.addInteractor(addWallZminInt);
+      //sd.addInteractor(addWallYmaxInt);
+      //sd.addInteractor(addWallZmaxInt);
+      //sd.addInteractor(inflowInt);
+      //sd.addInteractor(outflowInt);
+
+      //sd.deleteSolidBlocks();
+
+      grid->accept( metisVisitor );
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition for threads
+      //PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      //grid->accept(pqPartVisitor);
+
+//      ppblocks->update(0);
+//      ppblocks.reset();
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nodb = (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nod = nob * (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+      double needMemAll  = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         int minInitLevel = grid->getCoarsestInitializedLevel();
+         int maxInitLevel = grid->getFinestInitializedLevel();
+         for(int level = minInitLevel; level<=maxInitLevel; level++)
+         {
+            int nobl = grid->getNumberOfBlocks(level);
+            UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nob);
+            UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nob*nodb);
+         }
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      int kernelType = UbSystem::stringTo<int>(cf.getValue("kernel"));
+      LBMKernel3DPtr kernel;
+      if (kernelType == 0)
+      {
+         rhoLB = 1.0;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+      }
+      else if (kernelType == 1)
+      {
+         rhoLB = 1.0;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+      }
+      else if (kernelType == 2)
+      {
+         rhoLB = 0.0;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, 0));
+         //kernel = LBMKernel3DPtr(new LBMKernelESD3Q27CCLB(blocknx1, blocknx2, blocknx3, grid));
+         //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBex(blocknx1, blocknx2, blocknx3, 0, grid));
+      }
+
+      //mu::Parser fctForcingX1;
+      //fctForcingX1.SetExpr("Fx1");
+      //fctForcingX1.DefineConst("Fx1", 9.99685e-7);
+
+      //kernel->setForcingX1(fctForcingX1);
+      //kernel->setWithForcing(true);
+      //
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      //////////////////////////////////////////////////////////////////////////
+      //Experemintel
+      //////////////////////////////////////////////////////////////////////////
+      //int minInitLevel = grid->getCoarsestInitializedLevel();
+      //int maxInitLevel = grid->getFinestInitializedLevel();
+
+      //for(int level = minInitLevel; level<=maxInitLevel; level++)
+      //{
+      //   vector<Block3DPtr> blockVector;
+      //   grid->getBlocks(level, blockVector);
+      //   BOOST_FOREACH(Block3DPtr block, blockVector)
+      //   {
+      //      if (block)
+      //      {
+      //         boost::dynamic_pointer_cast<LBMKernelESD3Q27CCLB>(block->getKernel())->initNeighbours();
+      //      }
+      //   }
+      //}
+      //////////////////////////////////////////////////////////////////////////
+
+
+      if (refineLevel > 0)
+      {
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+      //walls
+      //grid->addAndInitInteractor(addWallYminInt);
+      //grid->addAndInitInteractor(addWallZminInt);
+      //grid->addAndInitInteractor(addWallYmaxInt);
+      //grid->addAndInitInteractor(addWallZmaxInt);
+
+
+      //addWallYminInt->updateInteractor(0);
+
+      //obstacle
+      //grid->addAndInitInteractor(cylinderInt);
+
+      //inflow
+      //grid->addAndInitInteractor(inflowInt);
+
+      //outflow
+      //grid->addAndInitInteractor(outflowInt);
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB);
+      initVisitor.setVx1(0.0);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      //UbSchedulerPtr geoSch(new UbScheduler(1));
+      //D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         //new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+      //ppgeo->update(0);
+      //ppgeo.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprocess - end"); 
+}
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 500.0;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      //UbSchedulerPtr stepSch(new UbScheduler());
+      //stepSch->addSchedule(10, 100, 1000);
+      //nodeSch->addSchedule(1000, 1000, 10000);
+      //nodeSch->addSchedule(10000, 10000, 50000);
+      //stepSch->addSchedule(100, 100, 1000);
+
+      //D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlASCII::getInstance(), conv, comm);
+
+      UbSchedulerPtr visSch(new UbScheduler());
+      //UbSchedulerPtr visSch(stepSch);
+      double endTime = UbSystem::stringTo<int>(cf.getValue("endTime"));//10001.0;
+
+      //cout << "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem()<<endl;
+      //cout << "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed()<<endl;
+      //cout << "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe()<<endl;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+ 
+
diff --git a/source/Applications/block_test/config.txt b/source/Applications/block_test/config.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6551aad25ba6d6e1d38e533077a414cb81047138
--- /dev/null
+++ b/source/Applications/block_test/config.txt
@@ -0,0 +1,20 @@
+#number of threads
+numOfThreads = 3
+
+#block dimensions
+blocknx1 = 8
+blocknx2 = 8
+blocknx3 = 8
+
+#grid dimensions
+gridNx1 = 8
+gridNx2 = 4
+gridNx3 = 4
+
+#grid refinement
+refineLevel = 0
+
+path = "/work/koskuche/scratch/block_test"
+
+#BGK=0, CLB=1, CCLB=2
+kernel = 0
\ No newline at end of file
diff --git a/source/Applications/bond_benchmark/CMakeLists.txt b/source/Applications/bond_benchmark/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a059287d53b6ba3b66e0fa446f7f9c0a5f4367ca
--- /dev/null
+++ b/source/Applications/bond_benchmark/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bond_b)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bond_b BINARY)
diff --git a/source/Applications/bond_benchmark/bonb_b_chanel.cpp b/source/Applications/bond_benchmark/bonb_b_chanel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3753ebea683a520dfd34fd2a78f392f169442214
--- /dev/null
+++ b/source/Applications/bond_benchmark/bonb_b_chanel.cpp
@@ -0,0 +1,335 @@
+
+#include <vfluids.h>
+
+#include "fbond.h"
+#include "Version.h"
+
+
+using namespace std;
+
+
+//////////////////////////////////////////////////////////////////////////
+void chanel(const char *cstr)
+{
+   try
+   {
+      ConfigFileReader cf(cstr);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+      double availMem = 0;
+
+      CommunicatorPtr comm;
+
+      string comm_type = cf.getValue("comm");
+      if(comm_type == "MPI")
+         comm = MPICommunicator::getInstance();
+      else if(comm_type == "BOND")
+         comm = BondCommunicator::getInstance();
+      
+      int myid = comm->getProcessID();
+      int mybundle = comm->getBundleID();
+      int root = comm->getRoot();
+
+      //UbLog::reportingLevel() = logDEBUG5;
+      
+      
+      pathname = cf.getValue("path");
+
+      if(machine == "BOMBADIL") 
+      {
+         //pathname = "c:/temp/bond_test";
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         //pathname = "/work/koskuche/scratch/bond_test";
+         availMem = 1.5e9;
+
+         if(myid==root && mybundle==root)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(mybundle)+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      
+      double dx = 1;
+
+      const int blocknx1 = UbSystem::stringTo<int>(cf.getValue("blocknx1")); //16;
+      const int blocknx2 = UbSystem::stringTo<int>(cf.getValue("blocknx2"));//16;
+      const int blocknx3 = UbSystem::stringTo<int>(cf.getValue("blocknx3"));//16;
+
+      const int gridNx1 = UbSystem::stringTo<int>(cf.getValue("gridNx1"));//3;
+      const int gridNx2 = UbSystem::stringTo<int>(cf.getValue("gridNx2"));//3;
+      const int gridNx3 = UbSystem::stringTo<int>(cf.getValue("gridNx3"));//3;
+
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3, H;
+      L2 = L3 = H = gridNx2*blocknx1;
+
+      LBMReal radius = 7;
+      LBMReal uLB = 0.05;
+      LBMReal Re = 300.0;
+      LBMReal rhoLB = 1.0;
+      LBMReal l = L2 / dx;
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = UbSystem::stringTo<int>(cf.getValue("refineLevel"));
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(L1*0.5, L2*0.5, 0, L1*0.5, L2*0.5, L3, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27InteractorPtr cylinderInt;
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = dx;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      double blockLength = blocknx1*dx;
+
+      //refinement area
+      double off = 1;
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-off, cylinder->getX2Minimum()-off, cylinder->getX3Minimum(), 
+         cylinder->getX1Maximum()+off, cylinder->getX2Maximum()+off, cylinder->getX3Maximum()));
+
+      Grid3DPtr grid(new Grid3D(comm, blocknx1, blocknx2, blocknx3, gridNx1, gridNx2, gridNx3));
+
+
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"Parameters:");
+         UBLOG(logINFO,"L = " << L2/dx );
+         UBLOG(logINFO,"v = " << uLB );
+         UBLOG(logINFO,"rho = " << rhoLB );
+         UBLOG(logINFO,"nue = " << nueLB );
+         UBLOG(logINFO,"Re = " << Re );
+         UBLOG(logINFO,"dx = " << dx );
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+         UBLOG(logINFO,"Preprozess - start");
+      }
+
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+      //walls
+      GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+      //inflow
+      GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      //outflow
+      GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+      if (refineLevel > 0)
+      {
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+         RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+         refineHelper.addGbObject(refineCube, 1);
+         refineHelper.refine();
+         if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      }
+
+      
+      if(comm_type == "MPI")
+      {
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+         grid->accept( metisVisitor );
+      }
+      else if(comm_type == "BOND")
+      {
+         MetisPartitioningWithBundlesGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+         grid->accept( metisVisitor );
+      }
+      
+      int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+      cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+      //walls
+      D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+      mu::Parser fct;
+      fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+      fct.DefineConst("U", uLB);
+      fct.DefineConst("H", H);
+
+      //inflow
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+      velBCAdapter->setSecondaryBcOption(2);
+      D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+      //outflow
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+      D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+
+      if(comm_type == "MPI")
+      {
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+      }
+      else if(comm_type == "BOND")
+      {
+         D3Q27BondSetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+      }
+
+      //domain decomposition for threads
+      //PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      //grid->accept(pqPartVisitor);
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+      double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+      LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+      //option = 0 - ohne param., option = 1 - mit param.
+      //int option = 0;
+      //LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, option));
+
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      if (refineLevel > 0)
+      {
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+      //walls
+      grid->addAndInitInteractor(addWallYminInt);
+      grid->addAndInitInteractor(addWallZminInt);
+      grid->addAndInitInteractor(addWallYmaxInt);
+      grid->addAndInitInteractor(addWallZmaxInt);
+
+      //obstacle
+      //grid->addAndInitInteractor(cylinderInt);
+
+      //inflow
+      grid->addAndInitInteractor(inflowInt);
+
+      //outflow
+      grid->addAndInitInteractor(outflowInt);
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+      //initVisitor.setVx1(fct);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, true));
+      ppgeo->update(0);
+      ppgeo.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+
+            //double outTime = 100.0;
+      UbSchedulerPtr stepSch(new UbScheduler());
+      //stepSch->addSchedule(10, 0, 1000);
+      //nodeSch->addSchedule(1000, 1000, 10000);
+      //nodeSch->addSchedule(10000, 10000, 50000);
+      //nodeSch->addSchedule(100, 100, 10000);
+
+      //D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      double step = UbSystem::stringTo<double>(cf.getValue("step"));
+      double begin = UbSystem::stringTo<double>(cf.getValue("begin"));
+      double end = UbSystem::stringTo<double>(cf.getValue("end"));
+      
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      UbSchedulerPtr visSch(new UbScheduler(10.0));
+      double endTime = UbSystem::stringTo<double>(cf.getValue("endTime"));;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch));
+      //if(myid == 0) 
+      UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      //if(myid == 0) 
+      UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
\ No newline at end of file
diff --git a/source/Applications/bond_benchmark/bond_b.cpp b/source/Applications/bond_benchmark/bond_b.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e85f9347796f3a0223f45d851bef28c91913fcaa
--- /dev/null
+++ b/source/Applications/bond_benchmark/bond_b.cpp
@@ -0,0 +1,337 @@
+#ifdef VF_BOND
+
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+#include "fbond.h"
+#include "Version.h"
+
+#include <stdlib.h>
+
+using namespace std;
+
+
+//////////////////////////////////////////////////////////////////////////
+void periodic(const char *cstr1, const char *cstr2)
+{
+   try
+   {
+      //Sleep(10000);
+      ConfigFileReader cf(cstr1);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+      double availMem = 0;
+
+      CommunicatorPtr comm;
+
+      string comm_type = cf.getValue("comm");
+      if(comm_type == "MPI")
+         comm = MPICommunicator::getInstance();
+      else if(comm_type == "BOND")
+         comm = BondCommunicator::getInstance();
+
+      int myid = comm->getProcessID();
+      int mybundle = comm->getBundleID();
+      int root = comm->getRoot();
+
+      UbLog::reportingLevel() = logDEBUG5;
+      system("hostname");
+      
+////////////////////////////////////////////// 
+//       char hostname[1024];
+//       hostname[1023] = '\0';
+//       gethostname(hostname, 1023);
+//       puts(hostname);
+//       UBLOG(logINFO,"hostname = " << string(hostname) );
+//////////////////////////////////////////////      
+
+      pathname = cf.getValue("path");
+
+      if(machine == "BOMBADIL") 
+      {
+         //pathname = "c:/temp/bond_test";
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         //pathname = "/work/koskuche/scratch/bond_test";
+         availMem = 1.5e9;
+
+         if(myid==root /*&& mybundle==root*/)
+         {
+            //UBLOG(logINFO,"bundle = " << mybundle);
+            //UBLOG(logINFO,"process ID = " << myid);
+            stringstream logFilename;
+            //logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(mybundle)+"_"+UbSystem::toString(myid)+"_"+comm_type+".txt";
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(comm->getNumberOfProcesses())+"p_"+comm_type+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+            //UbLog::reportingLevel() = logDEBUG5;
+         }
+      }
+      else if(machine == "HICEGATE0")      
+      {
+         //pathname = "/work/koskuche/scratch/block_test";
+         availMem = 6.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      } 
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      //UBLOG(logINFO,"bundle = " << mybundle);
+      //UBLOG(logINFO,"process ID = " << myid);
+
+      double dx = 1;
+
+      const int blocknx1 = UbSystem::stringTo<int>(cf.getValue("blocknx1")); //16;
+      const int blocknx2 = UbSystem::stringTo<int>(cf.getValue("blocknx2"));//16;
+      const int blocknx3 = UbSystem::stringTo<int>(cf.getValue("blocknx3"));//16;
+
+      const int gridNx1 = UbSystem::stringTo<int>(cf.getValue("gridNx1"));//3;
+      const int gridNx2 = UbSystem::stringTo<int>(cf.getValue("gridNx2"));//3;
+      const int gridNx3 = UbSystem::stringTo<int>(cf.getValue("gridNx3"));//3;
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3, H;
+      L2 = L3 = H = gridNx2*blocknx1;
+
+      LBMReal uLB = 0.05;
+      LBMReal Re = 20.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal nueLB = 0.05842;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = UbSystem::stringTo<int>(cf.getValue("refineLevel"));
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = dx;
+
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      double blockLength = blocknx1*dx;
+
+      //refinement area
+      //double off = 1;
+      //GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-off, cylinder->getX2Minimum()-off, cylinder->getX3Minimum(), 
+      //   cylinder->getX1Maximum()+off, cylinder->getX2Maximum()+off, cylinder->getX3Maximum()));
+
+      Grid3DPtr grid(new Grid3D(comm, blocknx1, blocknx2, blocknx3, gridNx1, gridNx2, gridNx3));
+      grid->setPeriodicX1(true);
+      grid->setPeriodicX2(true);
+      grid->setPeriodicX3(true);
+
+
+      if(myid ==0)
+      {
+         //UBLOG(logINFO,"bundle = " << mybundle);
+         //UBLOG(logINFO,"process ID = " << myid);
+         UBLOG(logINFO,"Parameters:");
+         UBLOG(logINFO,"Communicator =  " << comm_type);
+         UBLOG(logINFO,"Grid size =  " << gridNx1);
+         UBLOG(logINFO,"L = " << L1 );
+         UBLOG(logINFO,"v = " << uLB );
+         UBLOG(logINFO,"rho = " << rhoLB );
+         UBLOG(logINFO,"nue = " << nueLB );
+         UBLOG(logINFO,"Re = " << Re );
+         UBLOG(logINFO,"dx = " << dx );
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"number of threads = " << numOfThreads );
+         UBLOG(logINFO,"number of processes = " << comm->getNumberOfProcesses() );
+         UBLOG(logINFO,"Preprocess - start");
+      }
+
+
+      //if (refineLevel > 0)
+      //{
+      //   if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+      //   RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+      //   refineHelper.addGbObject(refineCube, 1);
+      //   refineHelper.refine();
+      //   if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      //}
+
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+
+      if(comm_type == "MPI")
+      {
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+         grid->accept( metisVisitor );
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+      }
+      else if(comm_type == "BOND")
+      {
+         //MetisPartitioningWithBundlesGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+	 MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+         grid->accept( metisVisitor );
+         D3Q27BondSetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         setConnsVisitor.activate();
+      }
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+
+      unsigned long nod = nob * (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+      double needMemAll  = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         int minInitLevel = grid->getCoarsestInitializedLevel();
+         int maxInitLevel = grid->getFinestInitializedLevel();
+         unsigned long nodb = (blocknx1) * (blocknx2) * (blocknx3);
+         for(int level = minInitLevel; level<=maxInitLevel; level++)
+         {
+            unsigned long nobl = grid->getNumberOfBlocks(level);
+            UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nobl);
+            UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nobl*nodb);
+         }
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      LBMKernel3DPtr kernel;
+      rhoLB = 0.0;
+      kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      //if (refineLevel > 0)
+      //{
+      //   D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+      //   grid->accept(undefNodesVisitor);
+      //}
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+      initVisitor.setVx1(0.0);
+      grid->accept(initVisitor);
+
+      if(myid == 0) UBLOG(logINFO,"Preprocess - end"); 
+      
+      UbSchedulerPtr stepSch(new UbScheduler());
+      
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      UbSchedulerPtr visSch(new UbScheduler());
+      double endTime = UbSystem::stringTo<int>(cf.getValue("endTime"));//10001.0;
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"//////////////////////////////////////////////////////////////////////////");
+         UBLOG(logINFO,"System information:");
+         UBLOG(logINFO,"Total Physical Memory (RAM): " << Utilities::getTotalPhysMem()/1073741824.0<< " GB");
+         UBLOG(logINFO,"Physical Memory currently used: " << Utilities::getPhysMemUsed()/1073741824.0<<" GB");
+         UBLOG(logINFO,"Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe()/1073741824.0<<" GB");
+         UBLOG(logINFO,"//////////////////////////////////////////////////////////////////////////");
+      }
+
+      CalculationManagerPtr calculation;
+      if(comm_type == "MPI")
+         calculation = CalculationManagerPtr(new CalculationManager(grid, numOfThreads, endTime, stepSch, CalculationManager::MPI));
+      else if(comm_type == "BOND")
+         calculation = CalculationManagerPtr(new CalculationManager(grid, numOfThreads, endTime, stepSch, CalculationManager::MPI));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   int returnval = 0;
+   try
+   {
+      if ( argv != NULL )
+      {
+         if (argc > 1)
+         {
+            //chanel(argv[1]);
+            periodic(argv[1], argv[2]);
+         }
+         else
+         {
+            cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+         }
+      }
+   }
+   catch(std::runtime_error& e)
+   {
+      std::cerr<<"\nRUNTIME ERROR: "<<e.what()<<"\n"<<std::endl;
+   }
+   catch(...)
+   {
+      std::cerr<<"unknown error"<<std::endl;
+   }
+   return returnval;
+}
+
+#endif
+
+
+
+
+
+
+
+
+
diff --git a/source/Applications/bond_benchmark/bond_b_test.cpp b/source/Applications/bond_benchmark/bond_b_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ad0b60c37d84ef7038fd0c016ba6fd8146bc504
--- /dev/null
+++ b/source/Applications/bond_benchmark/bond_b_test.cpp
@@ -0,0 +1,103 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+#include "fbond.h"
+#include "Version.h"
+
+
+using namespace std;
+
+
+int agent_main();
+
+int main(int argc, char* argv[])
+{
+   int returnval = 0;
+   try
+   {
+      bond::init();
+      returnval = agent_main();
+      bond::finalize();
+   }
+   catch(std::runtime_error& e)
+   {
+      std::cerr<<"\nRUNTIME ERROR: "<<e.what()<<"\n"<<std::endl;
+   }
+   catch(...)
+   {
+      std::cerr<<"unknown error"<<std::endl;
+   }
+   return returnval;
+}
+
+
+int agent_main()
+{
+   cout<<"\n=== bond lib info:\n"<<bond::Version::info()<<"\n===\n\n";
+
+   string pathname = "/work/koskuche/scratch/bond_benchmark";
+
+   // try to work around a bug in mpich (at least mpich2-1.4.1p1 and mpich2-1.5a1)
+   int _mpiInitialized = (int)false;
+   MPI_Initialized(&_mpiInitialized);
+   if(!_mpiInitialized)
+   {
+      MPI_Init(0, 0);	
+      _mpiInitialized = true;
+   }
+
+   int mpi_rank;
+   MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
+   int mpi_size;
+   MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
+   cout<<"I am process "<<bond::processID()<<" of "<<bond::processCount()
+      <<", bundle ID "<<bond::bundleID()<<" of "<<bond::bundleCount()
+      <<", MPI rank "<<mpi_rank<<" of "<<mpi_size<<"\n";
+
+   stringstream logFilename;
+   logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(bond::bundleID())+".txt";
+   UbLog::output_policy::setStream(logFilename.str());
+
+   vector<double> data(42);
+   data[0] = 123.1;
+   data[data.size()-1] = -999.1;  
+
+   vector<double> data2(42);
+   data2[0] = 123.2;
+   data2[data2.size()-1] = -999.2;     
+
+   std::tr1::shared_ptr<bond::FutureReceive> receiveRequest[8];
+   int id = bond::processID();
+
+   UBLOG(logINFO, "I am process "<<bond::processID()<<" of "<<bond::processCount()
+      <<", bundle ID "<<bond::bundleID()<<" of "<<bond::bundleCount()
+      <<", MPI rank "<<mpi_rank<<" of "<<mpi_size);
+
+   for(int i = 0; i < 8; i++)
+   {
+      UBLOG(logINFO, "bond::receiveFuture:start "<< i);
+      if(i == id) continue;
+      receiveRequest[i] = bond::receiveFuture(&data[0], data.size(), MPI_DOUBLE, i, 0);  
+      UBLOG(logINFO, "bond::receiveFuture:end "<< i);
+   }
+
+   for(int i = 0; i < 8; i++)
+   {
+      UBLOG(logINFO, "bond::sendComplete:start "<< i);
+      if(i == id) continue;
+      bond::sendComplete(&data2[0], data2.size(), MPI_DOUBLE, i, 0); 
+      UBLOG(logINFO, "bond::sendComplete:end "<<i);
+   }
+
+   for(int i = 0; i < 8; i++)
+   {
+      UBLOG(logINFO, "receiveRequest->complete:start "<<i);
+      if(i == id) continue;
+      receiveRequest[i]->complete();  
+      UBLOG(logINFO, "receiveRequest->complete:end "<<i);
+   }
+
+   return 0;
+}
diff --git a/source/Applications/bond_benchmark/config.txt b/source/Applications/bond_benchmark/config.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7c83ead3a3acec963e60fa429e713b09ec865fda
--- /dev/null
+++ b/source/Applications/bond_benchmark/config.txt
@@ -0,0 +1,31 @@
+#number of threads
+numOfThreads = 1
+
+#block dimesions
+blocknx1 = 8
+blocknx2 = 8
+blocknx3 = 8
+
+#grid dimensions
+gridNx1 = 20
+#100
+gridNx2 = 6
+#20
+gridNx3 = 6
+#20
+
+#grid refinement
+refineLevel = 0
+
+#communication
+comm=MPI
+#comm=BOND
+
+#simulation
+path = /work/koskuche/scratch/bond_b
+endTime = 101
+
+#NUPS count scheduler
+step  = 10
+begin = 20
+end   = 100
diff --git a/source/Applications/bond_test/CMakeLists.txt b/source/Applications/bond_test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a13830a0264757027227dc484337e75e4e2ee13c
--- /dev/null
+++ b/source/Applications/bond_test/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bond_test)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bond_test BINARY)
diff --git a/source/Applications/bond_test/bond_test.cpp b/source/Applications/bond_test/bond_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6511603e0108cc4b77409e1b1394692750c9349b
--- /dev/null
+++ b/source/Applications/bond_test/bond_test.cpp
@@ -0,0 +1,500 @@
+#ifdef VF_BOND
+
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+#include "fbond.h"
+#include "Version.h"
+
+
+using namespace std;
+
+int agent_main();
+void simulation(const char *cstr);
+
+int main(int argc, char* argv[])
+{
+   int returnval = 0;
+   try
+   {
+      bond::init();
+      returnval = agent_main();
+      bond::finalize();
+
+      //CommunicatorPtr comm(new BondCommunicator());
+      //cout<<"Bundle ID = "<<comm->getBundleID()<<", MPI rank = "<<comm->getProcessID()<<", root = "<<comm->getRoot()<<endl;
+
+      //if ( argv != NULL )
+      //{
+      //   if (argc > 1)
+      //   {
+      //      simulation(argv[1]);
+      //   }
+      //   else
+      //   {
+      //      cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+      //   }
+      //}
+   }
+   catch(std::runtime_error& e)
+   {
+      std::cerr<<"\nRUNTIME ERROR: "<<e.what()<<"\n"<<std::endl;
+   }
+   catch(...)
+   {
+      std::cerr<<"unknown error"<<std::endl;
+   }
+   return returnval;
+}
+
+
+int agent_main()
+{
+   cout<<"\n=== bond lib info:\n"<<bond::Version::info()<<"\n===\n\n";
+
+   // try to work around a bug in mpich (at least mpich2-1.4.1p1 and mpich2-1.5a1)
+   int _mpiInitialized = (int)false;
+   MPI_Initialized(&_mpiInitialized);
+   if(!_mpiInitialized)
+      MPI_Init(0, 0);	
+
+   int mpi_rank;
+   MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
+   int mpi_size;
+   MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
+   cout<<"I am process "<<bond::processID()<<" of "<<bond::processCount()
+      <<", bundle ID "<<bond::bundleID()<<" of "<<bond::bundleCount()
+      <<", MPI rank "<<mpi_rank<<" of "<<mpi_size<<"\n";
+
+   if(bond::processID() == 0)
+   {
+      try
+      {
+         Sleep(10000);
+         // send
+         vector<double> data(42);
+         data[0] = 123.1;
+         data[data.size()-1] = -999.1;
+
+         int dst_rank = 1;
+         int msg_tag = 42;
+         cout<<"["<<bond::processID()<<"] nonblocking send ... "<<data[0]<<"..."<<data[data.size()-1]<<"\n";
+         std::tr1::shared_ptr<bond::FutureSend> fus = bond::sendFuture(&data[0], data.size(), MPI_DOUBLE, dst_rank, msg_tag);
+
+         vector<double> data2(42);
+         data2[0] = 123.2;
+         data2[data2.size()-1] = -999.2;
+         cout<<"["<<bond::processID()<<"] blocking send ... "<<data2[0]<<"..."<<data2[data.size()-1]<<"\n";
+         bond::sendComplete(&data2[0], data2.size(), MPI_DOUBLE, dst_rank, msg_tag);
+
+         //Sleep(10000);
+
+         fus->complete();
+      }
+      catch(std::runtime_error& e)
+      {
+         std::cerr<<"\nSEND ERROR: "<<e.what()<<"\n"<<std::endl;
+      }
+   }
+   else
+   {
+      try
+      {
+         // receive
+         vector<double> data(42);
+         int src_rank = 0;
+         cout<<"["<<bond::processID()<<"] nonblocking receive ...\n";
+         int msg_tag = 42;
+         std::tr1::shared_ptr<bond::FutureReceive> fur = bond::receiveFuture(&data[0], data.size(), MPI_DOUBLE, src_rank, msg_tag);
+
+
+         //Sleep(10000);
+
+         cout<<"["<<bond::processID()<<"] blocking receive ...\n";
+         vector<double> data2(42);
+         bond::receiveComplete(&data2[0], data2.size(), MPI_DOUBLE, src_rank, msg_tag);
+         cout<<"received blocking "<<data2[0]<<"..."<<data2[data.size()-1]<<"\n";
+
+         
+
+         fur->complete();
+         cout<<"received nonblocking "<<data[0]<<"..."<<data[data.size()-1]<<"\n";
+      }
+      catch(std::runtime_error& e)
+      {
+         std::cerr<<"\nRECEIVE ERROR: "<<e.what()<<"\n"<<std::endl;
+      }
+   }
+
+   cout<<"process "<<bond::processID()<<" done\n";
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+void simulation(const char *cstr)
+{
+   try
+   {
+      ConfigFileReader cf(cstr);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      //UbLog::reportingLevel() = logDEBUG5;
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname = cf.getValue("path"); 
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+      double availMem = 0;
+
+      CommunicatorPtr comm;
+      string comm_type = cf.getValue("comm");
+      if(comm_type == "MPI")
+         comm = MPICommunicator::getInstance();
+      else if(comm_type == "BOND")
+         comm = BondCommunicator::getInstance();
+
+      int myid = comm->getProcessID();
+      int mybundle = comm->getBundleID();
+      int root = comm->getRoot();
+
+      //UbLog::reportingLevel() = logDEBUG5;
+
+      if(machine == "BOMBADIL") 
+      {
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         availMem = 12.0e9;
+
+         if(myid==root && mybundle==root)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx = 1;
+
+      const int blocknx1 = UbSystem::stringTo<int>(cf.getValue("blocknx1")); //16;
+      const int blocknx2 = UbSystem::stringTo<int>(cf.getValue("blocknx2"));//16;
+      const int blocknx3 = UbSystem::stringTo<int>(cf.getValue("blocknx3"));//16;
+
+      const int gridNx1 = UbSystem::stringTo<int>(cf.getValue("gridNx1"));//3;
+      const int gridNx2 = UbSystem::stringTo<int>(cf.getValue("gridNx2"));//3;
+      const int gridNx3 = UbSystem::stringTo<int>(cf.getValue("gridNx3"));//3;
+
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3, H;
+      L2 = L3 = H = gridNx2*blocknx1;
+
+      LBMReal radius = 7;
+      LBMReal uLB = 0.05;
+      LBMReal Re = 300.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = UbSystem::stringTo<int>(cf.getValue("refineLevel"));
+
+      //obstacle
+      GbObject3DPtr cylinder(new GbCylinder3D(L1*0.5, L2*0.5, 0, L1*0.5, L2*0.5, L3, radius));
+      GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27InteractorPtr cylinderInt;
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = dx;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      double blockLength = blocknx1*dx;
+
+      //refinement area
+      double off = 1;
+      GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-off, cylinder->getX2Minimum()-off, cylinder->getX3Minimum(), 
+         cylinder->getX1Maximum()+off, cylinder->getX2Maximum()+off, cylinder->getX3Maximum()));
+
+      Grid3DPtr grid(new Grid3D(comm, blocknx1, blocknx2, blocknx3, gridNx1, gridNx2, gridNx3));
+
+      //grid->setPeriodicX1(true);
+      //grid->setPeriodicX2(true);
+      //grid->setPeriodicX3(true);
+
+
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"Parameters:");
+         UBLOG(logINFO,"L = " << L2/dx );
+         UBLOG(logINFO,"v = " << uLB );
+         UBLOG(logINFO,"rho = " << rhoLB );
+         UBLOG(logINFO,"nue = " << nueLB );
+         UBLOG(logINFO,"Re = " << Re );
+         UBLOG(logINFO,"dx = " << dx );
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+         UBLOG(logINFO,"Preprozess - start");
+      }
+
+      if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+      //walls
+      GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+      //inflow
+      GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      //outflow
+      GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+      if (refineLevel > 0)
+      {
+         if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+         RefineCrossAndInsideGbObjectBlockVisitor refVisitor(refineCube, refineLevel);
+         grid->accept(refVisitor);
+
+         RatioBlockVisitor ratioVisitor(refineLevel);
+         grid->accept(ratioVisitor);
+
+         RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+         grid->accept(ratioSmoothVisitor);
+
+         OverlapBlockVisitor overlapVisitor(refineLevel);
+         grid->accept(overlapVisitor);
+
+         std::vector<int> dirs;
+         D3Q27System::getLBMDirections(dirs);
+         SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+         grid->accept(interDirsVisitor);
+         if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      }
+
+
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+
+      if(comm_type == "MPI")
+      {
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+         grid->accept( metisVisitor );
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+      }
+      else if(comm_type == "BOND")
+      {
+         MetisPartitioningWithBundlesGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B, true, numOfThreads);
+         grid->accept( metisVisitor );
+         D3Q27BondSetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         setConnsVisitor.activate();
+      }
+      
+      int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+      cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+      //walls
+      D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+      mu::Parser fct;
+      fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+      fct.DefineConst("U", uLB);
+      fct.DefineConst("H", H);
+
+      //inflow
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+      velBCAdapter->setSecondaryBcOption(2);
+      D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+      //outflow
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+      D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+      //SolidBlocksHelper sd(grid, comm);
+      //sd.addInteractor(cylinderInt);
+      //sd.addInteractor(addWallYminInt);
+      //sd.addInteractor(addWallZminInt);
+      //sd.addInteractor(addWallYmaxInt);
+      //sd.addInteractor(addWallZmaxInt);
+      //sd.addInteractor(inflowInt);
+      //sd.addInteractor(outflowInt);
+
+      //sd.deleteSolidBlocks();
+
+      //grid->accept( metisVisitor );
+
+      //grid->getBlock(0)->setBundle(0);
+      //grid->getBlock(0)->setRank(0);
+      //grid->getBlock(1)->setBundle(1);
+      //grid->getBlock(1)->setRank(1);
+      //grid->getBlock(2)->setBundle(0);
+      //grid->getBlock(2)->setRank(0);
+      //grid->getBlock(3)->setBundle(1);
+      //grid->getBlock(3)->setRank(1);
+      //grid->getBlock(4)->setBundle(0);
+      //grid->getBlock(4)->setRank(0);
+      //grid->getBlock(5)->setBundle(1);
+      //grid->getBlock(5)->setRank(1);
+      //grid->getBlock(6)->setBundle(1);
+      //grid->getBlock(6)->setRank(1);
+      //grid->getBlock(7)->setBundle(0);
+      //grid->getBlock(7)->setRank(0);
+
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+      double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+      //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+      //option = 0 - ohne param., option = 1 - mit param.
+      int option = 0;
+      LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      if (refineLevel > 0)
+      {
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+      //walls
+      grid->addAndInitInteractor(addWallYminInt);
+      grid->addAndInitInteractor(addWallZminInt);
+      grid->addAndInitInteractor(addWallYmaxInt);
+      grid->addAndInitInteractor(addWallZmaxInt);
+
+      //obstacle
+      //grid->addAndInitInteractor(cylinderInt);
+
+      //inflow
+      grid->addAndInitInteractor(inflowInt);
+
+      //outflow
+      grid->addAndInitInteractor(outflowInt);
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+      initVisitor.setVx1(fct);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, true));
+      ppgeo->update(0);
+      ppgeo.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+
+            //double outTime = 100.0;
+      UbSchedulerPtr stepSch(new UbScheduler());
+      stepSch->addSchedule(100, 0, 1000);
+      //nodeSch->addSchedule(1000, 1000, 10000);
+      //nodeSch->addSchedule(10000, 10000, 50000);
+      //nodeSch->addSchedule(100, 100, 10000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      UbSchedulerPtr visSch(new UbScheduler(10.0));
+      double endTime = UbSystem::stringTo<int>(cf.getValue("endTime"));
+      //CalculatorPtr calc = CalculatorPtr(new FETOLCalculator());
+      //CalculatorPtr calc = CalculatorPtr(new Calculator());
+      //CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch, calc));
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch));
+      //if(myid == 0) 
+      UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      //if(myid == 0) 
+      UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/Applications/bond_test/start.bat b/source/Applications/bond_test/start.bat
new file mode 100644
index 0000000000000000000000000000000000000000..ec3fc5640dfcec57412401946ef92a85c9366fec
--- /dev/null
+++ b/source/Applications/bond_test/start.bat
@@ -0,0 +1,6 @@
+@echo off
+set FETOL_BUNDLE_INFO_PATH=c:\Projects\FETOL\dev\bond_config\YAML_Bond_ConfigFile.yaml
+set FETOL_CLASSPATH=c:\Projects\FETOL\dev\fetol_bond\fetol_bond.jar
+
+set FETOL_BUNDLE_ID=%1
+call %2
\ No newline at end of file
diff --git a/source/Applications/bone/CMakeLists.txt b/source/Applications/bone/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f03f31b3b06d73c6708883c25ab3db36dc4bb058
--- /dev/null
+++ b/source/Applications/bone/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(bone)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(bone BINARY)
diff --git a/source/Applications/bone/bone.cpp b/source/Applications/bone/bone.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a45ece43199d1d8713a7881b952d06de993240ed
--- /dev/null
+++ b/source/Applications/bone/bone.cpp
@@ -0,0 +1,568 @@
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+void run(const char *cstr1, const char *cstr2)
+{
+   try
+   {
+      string pathname; 
+      string pathGeo;
+      string pathLog;
+      int numOfThreads = 1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr1);
+
+      if(machine == "my") 
+      {
+         pathname = "d:/temp/bone";
+         pathGeo = "d:/Data/Bone/BigBone";
+         pathLog = "d:/temp/bone";
+         numOfThreads = 4;
+         logfile = false;
+         availMem = 15.0e9;
+      }
+      else if(machine == "Ludwig")      
+      {
+         pathname = "/work/koskuche/SFB880/plate2Con";
+         pathGeo = "/home/koskuche/data/plate";
+         pathLog = pathname;
+         numOfThreads = 8;
+         availMem = 12.0e9;///8*numOfThreads;
+         logfile = true;
+      }
+      else if(machine == "HLRS")      
+      {
+         pathname = "/univ_1/ws1/ws/xrmkuchr-plate3-0";
+         pathGeo = "/zhome/academic/HLRS/xrm/xrmkuchr/data/plate";
+         pathLog = "/zhome/academic/HLRS/xrm/xrmkuchr/work/plate";
+         numOfThreads = 16;
+         availMem = 2.0e9;
+         logfile = true;
+      }
+      else if(machine == "HLRN")      
+      {
+         pathname = "/gfs1/work/niivfcpu/scratch/plateEx";
+         pathGeo = "/gfs1/work/niivfcpu/data/plate";
+         pathLog = pathname;
+         numOfThreads = 24;
+         availMem = 64.0e9/24.0*numOfThreads;
+         logfile = true;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+#if defined(__unix__)
+      if (myid==0) 
+      {
+         const char* str = pathLog.c_str();
+         int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      }
+#endif 
+
+      if(myid == 0 && logfile)
+      {
+         //UbLog::reportingLevel() = logDEBUG5;
+         logFilename <<  pathLog + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      if(myid==0) UBLOG(logINFO,"Testcase bone");
+
+      string boneFilename = pathGeo + "/bone.raw";
+      
+      int pmNX1=1800;  //abmessung einzelbild in x-richtung
+      int pmNX2=972; //abmessung einzelbild in y richtung
+      int pmNX3=1164; //anzahl der bilder
+      float lthreshold = 27756.0;
+      float uthreshold = 65535.0;
+
+      GbVoxelMatrix3DPtr pmMesh(new GbVoxelMatrix3D(pmNX1,pmNX2,pmNX3,0,lthreshold,uthreshold));
+      pmMesh->readMatrixFromRawFile<unsigned short>(boneFilename, GbVoxelMatrix3D::BigEndian);
+
+      double scaleFactor = 0.001;
+      double delta = 11.0*scaleFactor;
+      pmMesh->setVoxelMatrixDelta(delta, delta, delta);
+
+      pmMesh->setVoxelMatrixMininum(0.0, 0.0, 0.0);
+      if(myid == 0) pmMesh->writeToLegacyVTKBinary(pathname+"/geo/bone");
+
+      ///////////////////////////////////////////////////////
+      return;
+
+
+      /////////////////Knotenabmessungen:
+      //int nx[3], blocknx[3];
+      //nx[0]      = 90;//240;//120;//60;//86;//43;//65;//50;  //länge
+      //nx[1]      = 2;//2;//6;///1;//5;// //breite
+      //nx[2]      = 30;//64;//32;//18;//5;//15;//15; //höhe gebiet
+      //blocknx[0] = 16;//10;//6;
+      //blocknx[1] = 16;//10;//6;
+      //blocknx[2] = 16;//10;//6;
+
+      //int baseLevel   = 0;
+      //int refineLevel = 4;
+
+      //double H = 600.0; // Kanalhöhe [mm]
+      //double cdx = H/(double)(nx[2]*blocknx[2]);
+      //double fdx = cdx/double(1<<refineLevel);
+
+      ////double h = 200.0; // gewünschte Plattenhöhe in Gitterpunkten
+      ////double fdx = plate->getLengthX3()/h;
+      ////double cdx = fdx*double(1<<refineLevel);
+
+      //LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      ////////////////////////////////////////////////////////////////////////////
+      ////physik
+      ////////////////////////////////////////////////////////////////////////////
+      //double Re            = 1133333.3333333335; 
+      //double rhoLB         = 0.0;
+      //double uLB           = 0.1; 
+      //double lReal         = 1000; //Plattenlänge in mm
+      //double nuLB          = (uLB*(lReal/cdx))/Re;
+
+      //int sizeSP=4;
+      //mu::Parser spongeLayer;
+      //spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+      //spongeLayer.DefineConst("sizeX", nx[0]*blocknx[0]);
+      //spongeLayer.DefineConst("sizeSP", sizeSP*blocknx[0]);
+
+      //Grid3DPtr grid(new Grid3D(comm));
+
+      ////////////////////////////////////////////////////////////////////////////
+      ////restart
+      //UbSchedulerPtr rSch(new UbScheduler(1000,1000,10000000));
+      //RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      ////////////////////////////////////////////////////////////////////////////
+
+      //if (grid->getTimeStep() == 0)
+      //{
+
+      //   if(myid==0) UBLOG(logINFO,"Neustart..");
+
+      //   //////////////////////////////////////////////////////////////////////////
+      //   //Platte
+      //   GbTriFaceMesh3DPtr plate (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(PlatteFilename,"Netz"));
+      //   plate->rotate(90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+      //   if(myid == 0) GbSystem3D::writeGeoObject( plate.get(), pathname+"/geo/platte", WbWriterVtkXmlBinary::getInstance() );
+      //   //////////////////////////////////////////////////////////////////////////
+      //   // Zackenband
+      //   //////////////////////////////////////////////////////////////////////////
+      //   GbTriFaceMesh3DPtr meshBand1 (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand"));
+      //   meshBand1->translate(-495, -700, -19.94);
+      //   if(myid == 0) GbSystem3D::writeGeoObject( meshBand1.get(), pathname+"/geo/Band1", WbWriterVtkXmlASCII::getInstance() );
+      //   // Zackenband2
+      //   GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand2"));
+      //   meshBand2->translate(-495, -705, -19.94); 
+      //   if(myid == 0) GbSystem3D::writeGeoObject( meshBand2.get(), pathname+"/geo/Band2", WbWriterVtkXmlASCII::getInstance() );
+      //   // Zackenband3
+      //   GbTriFaceMesh3DPtr meshBand3(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand3"));
+      //   meshBand3->translate(-495, -700, -19.64); 
+      //   if(myid == 0) GbSystem3D::writeGeoObject( meshBand3.get(), pathname+"/geo/Band3", WbWriterVtkXmlASCII::getInstance() );
+      //   // Zackenband4
+      //   GbTriFaceMesh3DPtr meshBand4(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand4"));
+      //   meshBand4->translate(-495, -705, -19.64); 
+      //   if(myid == 0) GbSystem3D::writeGeoObject( meshBand4.get(), pathname+"/geo/Band4", WbWriterVtkXmlASCII::getInstance() );
+      //   //////////////////////////////////////////////////////////////////////////
+
+      //   double blockLengthx1 = blocknx[0]*cdx; //geowerte
+      //   double blockLengthx2 = blockLengthx1;
+      //   double blockLengthx3 = blockLengthx1;
+
+      //   double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      //   double originX1 = plate->getX1Minimum()-plate->getLengthX1()/4.0;
+      //   double originX2 = plate->getX2Minimum();
+      //   double originX3 = plate->getX3Minimum()-299.5;
+
+
+      //   bool periodicx1 = false;
+      //   bool periodicx2 = true;
+      //   bool periodicx3 = true;
+
+      //   //bounding box
+      //   double g_minX1 = originX1;
+      //   double g_minX2 = originX2;
+      //   double g_minX3 = originX3;
+
+      //   double g_maxX1 = originX1 + geoLength[0];
+      //   double g_maxX2 = originX2 + geoLength[1];
+      //   double g_maxX3 = originX3 + geoLength[2];;
+
+
+      //   //set grid
+      //   grid->setDeltaX(cdx);
+      //   grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+      //   grid->setPeriodicX1(periodicx1);
+      //   grid->setPeriodicX2(periodicx2);
+      //   grid->setPeriodicX3(periodicx3);
+
+      //   GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      //   gridCube->setCenterCoordinates(gridCube->getX1Centroid(),meshBand1->getX2Centroid(),gridCube->getX3Centroid());
+      //   if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+      //   originX2 = gridCube->getX2Minimum();
+      //   g_minX2 = originX2;
+      //   g_maxX2 = originX2 + geoLength[1];
+
+      //   GenBlocksGridVisitor genBlocks(gridCube);
+      //   grid->accept(genBlocks);
+
+      //   //////////////////////////////////////////////////////////////////////////
+      //   if(myid == 0)
+      //   {
+      //      UBLOG(logINFO, "*****************************************");
+      //      UBLOG(logINFO, "* Parameters                            *");
+      //      UBLOG(logINFO, "* Re            ="<<Re);
+      //      UBLOG(logINFO, "* nuLB          ="<<nuLB);
+      //      UBLOG(logINFO, "* uLB           ="<<uLB);
+      //      UBLOG(logINFO, "* cdx           ="<<cdx);
+      //      UBLOG(logINFO, "* fdx           ="<<fdx);
+      //      double Hzb = 0.6/fdx;
+      //      UBLOG(logINFO, "* Height of Zackenband ="<<Hzb);
+      //      UBLOG(logINFO, "* Re on Zackenband ="<<(uLB*Hzb)/(nuLB*double(1<<refineLevel)));
+      //      UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+      //      UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+      //      UBLOG(logINFO, "* x1Periodic    ="<<periodicx1);
+      //      UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+      //      UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+      //      UBLOG(logINFO, "* number of levels  ="<<refineLevel+1);
+      //      UBLOG(logINFO, "* path          ="<<pathname);
+
+      //      UBLOG(logINFO, "*****************************************");
+      //      UBLOG(logINFO, "* number of threads    ="<<numOfThreads);
+      //      UBLOG(logINFO, "* number of processes  ="<<comm->getNumberOfProcesses());
+      //      UBLOG(logINFO, "*****************************************");
+      //      UBLOG(logINFO, "*****************************************");     
+      //   }
+      //   //////////////////////////////////////////////////////////////////////////
+
+
+      //   //////////////////////////////////////////////////////////////////////////
+      //   //refinement
+      //   GbCuboid3DPtr refinePlatteBox(new GbCuboid3D(plate->getX1Minimum(), plate->getX2Minimum(), plate->getX3Minimum()+(plate->getX3Maximum()-plate->getX3Minimum())/2.0, 
+      //      plate->getX1Maximum()+40.0, plate->getX2Maximum(), plate->getX3Maximum()));
+      //   if(myid == 0) GbSystem3D::writeGeoObject( refinePlatteBox.get(), pathname+"/geo/refinePlatteBox", WbWriterVtkXmlASCII::getInstance() );
+
+      //   if (refineLevel > 0)
+      //   {
+      //      if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+      //      RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+      //      refineHelper.addGbObject(refinePlatteBox, refineLevel);
+      //      refineHelper.refine();
+      //      if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      //   }
+
+      //   /////////////////////////////////////////////////
+      //   ///interactoren
+      //   int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+      //   D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+      //   D3Q27TriFaceMeshInteractorPtr triPlateInteractor( new D3Q27TriFaceMeshInteractor(plate, grid, bcObst,Interactor3D::SOLID));
+      //   D3Q27TriFaceMeshInteractorPtr triBand1Interactor( new D3Q27TriFaceMeshInteractor( meshBand1, grid, bcObst,Interactor3D::SOLID, Interactor3D::EDGES) );
+      //   D3Q27TriFaceMeshInteractorPtr triBand2Interactor( new D3Q27TriFaceMeshInteractor( meshBand2, grid, bcObst,Interactor3D::SOLID, Interactor3D::EDGES) );
+      //   D3Q27TriFaceMeshInteractorPtr triBand3Interactor( new D3Q27TriFaceMeshInteractor( meshBand3, grid, bcObst,Interactor3D::SOLID, Interactor3D::EDGES) );
+      //   D3Q27TriFaceMeshInteractorPtr triBand4Interactor( new D3Q27TriFaceMeshInteractor( meshBand4, grid, bcObst,Interactor3D::SOLID, Interactor3D::EDGES) );
+
+      //   //inflow
+      //   GbCuboid3DPtr velBCCuboid(new GbCuboid3D(originX1-blockLengthx1, originX2-blockLengthx1, originX3-blockLengthx1, 
+      //      originX1, originX2+geoLength[1]+blockLengthx1, originX3+geoLength[2]+blockLengthx1));
+      //   if(myid == 0) GbSystem3D::writeGeoObject(velBCCuboid.get(), pathname+"/geo/velBCCuboid", WbWriterVtkXmlASCII::getInstance());
+      //   D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(velBCCuboid,grid,Interactor3D::SOLID)); 
+
+      //   //inflow
+      //   double raiseVelSteps = 0;
+      //   vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+      //   mu::Parser inflowProfile;
+      //   inflowProfile.SetExpr("uLB"); 
+      //   inflowProfile.DefineConst("uLB",uLB);
+      //   velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+      //   D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (velcX1BCs,dummy,dummy));
+      //   velBCInteractor->addBCAdapter(velBCAdapter);
+
+      //   //outflow
+      //   GbCuboid3DPtr densCuboid(new GbCuboid3D(originX1+geoLength[0], originX2-blockLengthx1, originX3-blockLengthx1, 
+      //      originX1+geoLength[0]+blockLengthx1, originX2+geoLength[1]+blockLengthx1, originX3+geoLength[2]+blockLengthx1 ));
+      //   if(myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname+"/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+      //   D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+      //   D3Q27InteractorPtr densInteractor( new D3Q27Interactor(densCuboid,grid,denBCAdapter,Interactor3D::SOLID) );
+
+      //   ////////////////////////////////////////////
+      //   //METIS
+      //   Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));	
+
+      //   ////////////////////////////////////////////
+      //   /////delete solid blocks
+      //   if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+      //   InteractorsHelper intHelper(grid, metisVisitor);
+      //   intHelper.addInteractor(triPlateInteractor);
+      //   intHelper.addInteractor(triBand1Interactor);
+      //   intHelper.addInteractor(triBand2Interactor);
+      //   intHelper.addInteractor(triBand3Interactor);
+      //   intHelper.addInteractor(triBand4Interactor);
+      //   intHelper.addInteractor(densInteractor);
+      //   intHelper.addInteractor(velBCInteractor);
+      //   intHelper.selectBlocks();
+      //   if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+      //   //////////////////////////////////////
+
+      //   //domain decomposition for threads
+      //   if(numOfThreads > 1)
+      //   {
+      //      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      //      grid->accept(pqPartVisitor);
+      //   }
+
+      //   if(myid == 0)
+      //   {
+      //      UBLOG(logINFO,"Write blocks - start");
+      //      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+      //      ppblocks->update(0);
+      //      UBLOG(logINFO,"Write blocks - end");
+      //   }
+
+      //   unsigned long nob = grid->getNumberOfBlocks();
+      //   unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+      //   unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+      //   unsigned long nodb = (blocknx[0]) * (blocknx[1]) * (blocknx[2]);
+
+      //   double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+      //   double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+      //   
+      //   double nup = 0; 
+
+      //   if(myid == 0)
+      //   {
+      //      UBLOG(logINFO,"Number of blocks = " << nob);
+      //      UBLOG(logINFO,"Number of nodes  = " << nod);
+      //      int minInitLevel = grid->getCoarsestInitializedLevel();
+      //      int maxInitLevel = grid->getFinestInitializedLevel();
+      //      for(int level = minInitLevel; level<=maxInitLevel; level++)
+      //      {
+      //         int nobl = grid->getNumberOfBlocks(level);
+      //         UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nobl);
+      //         UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nobl*nodb);
+      //         nup += nobl*nodb*double(1<<level); 
+      //      }
+      //      UBLOG(logINFO,"Hypothetically time for calculation step for 120 nodes  = " << nup/6.0e5/(120*8)  << " s");
+      //      UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+      //      UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+      //      UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      //      UBLOG(logINFO,"Available memory per node/8.0 = " << (availMem/8.0) << " bytes");
+      //   }
+
+      //   //////////////////////////////////////////
+      //   //set connectors
+      //   if(myid == 0) UBLOG(logINFO,"set connectors - start");
+      //   D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      //   D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+      //   grid->accept( setConnsVisitor );
+      //   if(myid == 0) UBLOG(logINFO,"set connectors - end");
+
+      //   ////////////////////////////
+      //   LBMKernel3DPtr kernel;
+      //   //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+      //   //with sponge layer
+      //   kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+      //   kernel->setWithSpongeLayer(true);
+      //   kernel->setSpongeLayer(spongeLayer);
+
+      //   BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      //   kernel->setBCProcessor(bcProc);
+      //   SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+      //   grid->accept(kernelVisitor);
+      //   //////////////////////////////////
+      //   //undef nodes
+      //   if (refineLevel > 0)
+      //   {
+      //      D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+      //      grid->accept(undefNodesVisitor);
+      //   }
+
+
+      //   intHelper.setBC();
+
+      //   //initialization of decompositions
+      //   D3Q27ETInitDistributionsBlockVisitor initVisitor( nuLB,rhoLB);
+      //   initVisitor.setVx1(uLB);
+      //   grid->accept(initVisitor);
+
+      //   //Postprozess
+      //   UbSchedulerPtr geoSch(new UbScheduler(1));
+      //   D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+      //      new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), 
+      //      unitConverter, true));
+      //   ppgeo->update(0);
+      //   ppgeo.reset();
+      //   geoSch.reset();
+
+      //   if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+      //}
+      //else
+      //{
+      //   //domain decomposition for threads
+      //   if(numOfThreads > 1)
+      //   {
+      //      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      //      grid->accept(pqPartVisitor);
+      //   }
+      //   //set connectors
+      //   //grid->setPeriodicX3(false);
+      //   D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      //   D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+      //   grid->accept( setConnsVisitor );
+      //   SetSpongeLayerBlockVisitor ssp(spongeLayer);
+      //   grid->accept(ssp);
+
+      //   //////////////////////////////////////////////////////////////////////////
+      //   //////////////////////////////////////////////////////////////////////////
+      //   //Platte
+      //   GbTriFaceMesh3DPtr plate (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(PlatteFilename,"Netz"));
+      //   plate->rotate(90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+      //   if(myid == 0) GbSystem3D::writeGeoObject( plate.get(), pathname+"/geo/platte", WbWriterVtkXmlBinary::getInstance() );
+      //   //////////////////////////////////////////////////////////////////////////
+      //   //////////////////////////////////////////////////////////////////////////
+      //   // Zackenband
+      //   //////////////////////////////////////////////////////////////////////////
+      //   GbTriFaceMesh3DPtr meshBand1 (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand"));
+      //   meshBand1->translate(-495, -700, -19.94);
+      //   if(myid == 0) GbSystem3D::writeGeoObject( meshBand1.get(), pathname+"/geo/Band1", WbWriterVtkXmlASCII::getInstance() );
+
+      //   double blockLengthx1 = blocknx[0]*cdx; //geowerte
+      //   double blockLengthx2 = blockLengthx1;
+      //   double blockLengthx3 = blockLengthx1;
+
+      //   double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      //   double originX1 = plate->getX1Minimum()-plate->getLengthX1()/4.0;
+      //   double originX2 = plate->getX2Minimum();
+      //   double originX3 = plate->getX3Minimum()-299.5;
+
+      //   //bounding box
+      //   double g_minX1 = originX1;
+      //   double g_minX2 = originX2;
+      //   double g_minX3 = originX3;
+
+      //   double g_maxX1 = originX1 + geoLength[0];
+      //   double g_maxX2 = originX2 + geoLength[1];
+      //   double g_maxX3 = originX3 + geoLength[2];;
+
+      //   GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      //   gridCube->setCenterCoordinates(gridCube->getX1Centroid(),meshBand1->getX2Centroid(),gridCube->getX3Centroid());
+      //   if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+      //   originX2 = gridCube->getX2Minimum();
+      //   g_minX2 = originX2;
+      //   g_maxX2 = originX2 + geoLength[1];
+      //   //walls
+      //   GbCuboid3DPtr addWallZmin (new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_minX3-blockLengthx1, g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_minX3));
+      //   if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+      //   GbCuboid3DPtr addWallZmax (new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_maxX3, g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1));
+      //   if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+      //   //walls
+      //   int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB        
+      //   D3Q27BoundaryConditionAdapterPtr slip(new D3Q27SlipBCAdapter(bbOption));
+      //   D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, slip,Interactor3D::SOLID));
+      //   D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, slip,Interactor3D::SOLID));
+
+      //   SetSolidOrTransBlockVisitor v1(addWallZminInt, SetSolidOrTransBlockVisitor::TRANS);
+      //   grid->accept(v1);
+      //   addWallZminInt->initInteractor();
+      //   SetSolidOrTransBlockVisitor v2(addWallZmaxInt, SetSolidOrTransBlockVisitor::TRANS);
+      //   grid->accept(v2);        
+      //   addWallZmaxInt->initInteractor();
+
+      //   UbSchedulerPtr geoSch(new UbScheduler(1));
+      //   D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+      //      new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), 
+      //      unitConverter, true));
+      //   ppgeo->update(0);
+      //   ppgeo.reset();
+      //   geoSch.reset();
+      //   //////////////////////////////////////////////////////////////////////////
+
+      //   if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      //}
+      //UbSchedulerPtr visSch(new UbScheduler());
+      ////visSch->addSchedule(1,0,3);
+      ////visSch->addSchedule(100,100,1000);
+      ////visSch->addSchedule(1000,1000,5000);
+      ////visSch->addSchedule(5000,5000,100000);
+      ////visSch->addSchedule(100000,100000,10000000);
+
+      //visSch->addSchedule(1000,1000,10000000);
+
+      //D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      //UbSchedulerPtr resSchRMS(new UbScheduler());
+      //resSchRMS->addSchedule(1000000,93000,10000000);
+      //UbSchedulerPtr resSchMeans(new UbScheduler());
+      //resSchMeans->addSchedule(1000000,93000,10000000);
+      //UbSchedulerPtr stepAvSch(new UbScheduler());
+      //int averageInterval=100;
+      //stepAvSch->addSchedule(averageInterval,0,10000000);
+      //AverageValuesPostprocessor Avpp(grid, pathname, WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/, stepAvSch/*wann wird gemittelt*/, resSchMeans,resSchRMS/*wann wird resettet*/);
+
+      //UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      //nupsSch->addSchedule(500,500,1e6);
+      //NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      //UbSchedulerPtr emSch(new UbScheduler(10));
+      //EmergencyExitPostprocessor empr(grid, emSch, pathname, RestartPostprocessorPtr(&rp), comm);
+
+      //if(myid == 0)
+      //{
+      //   UBLOG(logINFO,"PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem());
+      //   UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed());
+      //   UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe());
+      //}
+
+      //string lastStep = string(cstr2);
+      //double endTime = UbSystem::stringTo<double>(lastStep);
+      //CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      //if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      //calculation->calculate();
+      //if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   if (argc == 1)
+   {
+      cout<<"Command line argument isn't specified!"<<endl;
+      cout<<"plate2 <machine name>"<<endl;
+      return 1;
+   }
+   run(argv[1], argv[2]);
+
+   return 0;
+}
+
diff --git a/source/Applications/fetol_demo/CMakeLists.txt b/source/Applications/fetol_demo/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..878ba5dceb5e2f800426c374f745b138aaf8dc04
--- /dev/null
+++ b/source/Applications/fetol_demo/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(fetol_demo)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids ${FETOL_RELEASE_LIBRARY})
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(fetol_demo BINARY)
diff --git a/source/Applications/fetol_demo/fetol_demo.cpp b/source/Applications/fetol_demo/fetol_demo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b3a103805a3a2a0e02deb45d5c768c833002bcf4
--- /dev/null
+++ b/source/Applications/fetol_demo/fetol_demo.cpp
@@ -0,0 +1,306 @@
+#include <vfluids.h>
+
+#include <fbond.h>
+#include <Version.h>
+
+#include <JM.h>
+
+using namespace std;
+
+using namespace fetol;
+
+////////////////////////////////////////////////////////////////////////
+void chanel(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      UBLOG(logINFO,"Communicator-init::strat");
+      CommunicatorPtr comm = FETOLCommunicator::getInstance();
+      UBLOG(logINFO,"Communicator-init::end");
+
+      int myid = comm->getProcessID();
+      int mybundle = comm->getBundleID();
+      int root = comm->getRoot();
+      int myrank = boost::dynamic_pointer_cast<FETOLCommunicator>(comm)->getMPIRank();
+
+      UBLOG(logINFO,"myid = " << myid );
+      UBLOG(logINFO,"mybundle = " << mybundle );
+      UBLOG(logINFO,"myrank = " << myrank );
+
+      JM::init(mybundle, myrank);
+
+      //UbLog::reportingLevel() = logDEBUG5;
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/fetol_demo";
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         //pathname = "/work/koskuche/scratch/fetol_demo";
+
+         pathname = string(cstr);
+         availMem = 1.5e9;
+
+        if(myid==root && mybundle==root)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/log/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      double dx = 1;
+
+      const int blocknx1 = 40;
+      const int blocknx2 = 40;
+      const int blocknx3 = 40;
+
+      const int gridNx1 = 4;
+      const int gridNx2 = 2;
+      const int gridNx3 = 2;
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3, H;
+      L2 = H = gridNx2*blocknx1;
+      L3 = gridNx3*blocknx1;
+
+      LBMReal radius = 7;
+      LBMReal uLB = 0.1;
+      LBMReal Re = 3000.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+      LBMReal nueLB = (uLB*2.0*radius)/Re;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+      //UBLOG(logINFO,"Restart:start");
+      UbSchedulerPtr restartSch(new UbScheduler(1000, 1000, 100000));
+      RestartPostprocessor rp(grid, restartSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+      grid = rp.restart(-1);
+      //UBLOG(logINFO,"Restart:end");
+
+      if (grid->getTimeStep() == 0)
+      {
+
+         const int baseLevel = 0;
+         const int refineLevel = 0;
+
+         //obstacle
+         GbObject3DPtr sphere(new GbSphere3D(L1/4.0, L2*0.5, L3*0.5, radius));
+         GbSystem3D::writeGeoObject(sphere.get(),pathname + "/geo/sphere", WbWriterVtkXmlBinary::getInstance());
+
+         D3Q27InteractorPtr sphereInt;
+
+         //bounding box
+         double d_minX1 = 0.0;
+         double d_minX2 = 0.0;
+         double d_minX3 = 0.0;
+
+         double d_maxX1 = L1;
+         double d_maxX2 = L2;
+         double d_maxX3 = L3;
+
+         double blockLength = blocknx1*dx;
+
+         GbObject3DPtr gridCube(new GbCuboid3D(d_minX1, d_minX2, d_minX3, d_maxX1, d_maxX2, d_maxX3));
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance()); 
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"Parameters:");
+            UBLOG(logINFO,"L = " << L2/dx );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+            UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+         //sphere
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         sphereInt = D3Q27InteractorPtr ( new D3Q27Interactor(sphere, grid, bcObst,Interactor3D::SOLID));
+
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+         mu::Parser fct;
+         fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+         fct.DefineConst("U", uLB);
+         fct.DefineConst("H", H);
+
+         //inflow
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(sphereInt);
+         intHelper.addInteractor(addWallYminInt);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallYmaxInt);
+         intHelper.addInteractor(addWallZmaxInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         FETOLSetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         intHelper.setBC();
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+         initVisitor.setVx1(fct);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+      else
+      {
+         UBLOG(logINFO,"SetConnectors - start, id="<<myid);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         FETOLSetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         
+         UBLOG(logINFO,"SetConnectors - end, id="<<myid); 
+      }
+
+      UbSchedulerPtr stepSch(new UbScheduler());
+      stepSch->addSchedule(1000, 0, 1000000);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv);
+
+      //UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      //NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double endTime = 100000;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch, CalculationManager::FETOL));
+      
+      if(myid == 0) 
+         UBLOG(logINFO,"Simulation-start");
+      
+      calculation->calculate();
+      
+      if(myid == 0) 
+         UBLOG(logINFO,"Simulation-end");
+
+      JM::finalize();
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   if ( argv != NULL )
+   {
+      if (argc > 1)
+      {
+         chanel(argv[1]);
+      }
+      else
+      {
+         cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+      }
+   }
+}
+
diff --git a/source/Applications/greenvortex/CMakeLists.txt b/source/Applications/greenvortex/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2715bc92017327fd1354dc5d4e54241d55cf5324
--- /dev/null
+++ b/source/Applications/greenvortex/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(greenvortex)
+
+INCLUDE(${SOURCE_ROOT}/core/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES core)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(greenvortex BINARY)
diff --git a/source/Applications/greenvortex/greenvortex.cpp b/source/Applications/greenvortex/greenvortex.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e9b1327e4451ea03e9cb7afd85110096eed1d6d4
--- /dev/null
+++ b/source/Applications/greenvortex/greenvortex.cpp
@@ -0,0 +1,211 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include <numerics/geometry3d/GbSphere3D.h>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "D3Q27PathLinePostprocessor.h"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "BlocksPostprocessor.h"
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string pathname = "c:/temp/greenvortex/out";
+
+      int numOfThreads = 3;
+
+      const int blocknx1 = 5;
+      const int blocknx2 = 5;
+      const int blocknx3 = 5;
+
+      const int baseLevel = 0;
+      const int refineLevel = 1;
+
+      const double blockLentghX1 = 1.0;
+      const double blockLentghX2 = 1.0;
+      const double blockLentghX3 = 1.0;
+
+      const double gridOriginX1 = 0.0;
+      const double gridOriginX2 = 0.0;
+      const double gridOriginX3 = 0.0;
+
+      double L1 = 5.0;
+      double L2 = 5.0;
+      double L3 = 5.0;
+
+      const double dx = blockLentghX1/static_cast<double>(blocknx1);
+
+      CommunicatorPtr comm(new MPICommunicator());
+
+      LBMReal uLB = 0.01;
+      LBMReal Re = 20.0;
+      LBMReal rhoLB = 1.0;
+      LBMReal l = blockLentghX2 / dx;
+      LBMReal nueLB = (uLB*l)/Re;
+
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+      param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+      param->setRho(rhoLB);
+      param->setVelocityX(uLB);
+      param->setViscosity(nueLB);
+
+      Grid3DPtr grid(new Grid3D());
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+      grid->setPeriodicX1(true);
+      grid->setPeriodicX2(false);
+      grid->setPeriodicX3(false);
+
+
+      GbObject3DPtr gridCube(new GbCuboid3D(0.0, 0.0, 0.0, L1, L2, L3));
+      GenBlocksGridVisitor genBlocks;
+      genBlocks.addGeoObject(gridCube);
+      grid->accept(genBlocks);
+
+      LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+
+      mu::Parser fctForcingX1, fctForcingX2;
+      fctForcingX1.SetExpr("2.0*rho* (4.0*PI*PI/(L1/dx)/(L2/dx))*( nue*vlb*sin(x1*2.0*PI/(L1/dx))*cos(x2*2.0*PI/(L2/dx)))");
+      fctForcingX2.SetExpr("-2.0*rho*(4.0*PI*PI/(L1/dx)/(L2/dx))*( nue*vlb*cos(x1*2.0*PI/(L1/dx))*sin(x2*2.0*PI/(L2/dx)))");
+
+      fctForcingX1.DefineConst("L1"     , static_cast<double>(L1*blocknx1));
+      fctForcingX1.DefineConst("L2"     , static_cast<double>(L2*blocknx2));
+      fctForcingX1.DefineConst("PI"     , PI);
+      fctForcingX1.DefineConst("rho"    , rhoLB);
+      fctForcingX1.DefineConst("vlb"    , uLB);
+
+      fctForcingX2.DefineConst("L1"     , static_cast<double>(L1*blocknx1));
+      fctForcingX2.DefineConst("L2"     , static_cast<double>(L2*blocknx2));
+      fctForcingX2.DefineConst("PI"     , PI);
+      fctForcingX2.DefineConst("rho"    , rhoLB);
+      fctForcingX2.DefineConst("vlb"    , uLB);
+
+      kernel->setForcingX1(fctForcingX1);
+      kernel->setForcingX2(fctForcingX2);
+
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB);
+      grid->accept(kernelVisitor);
+
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+
+      mu::Parser fct,fct2,fct3;
+      fct.SetExpr(" vLB*sin( ( (x1)*2.0*PI/ L1))*cos( (x2)*2.0*PI/L2)");
+      fct.DefineConst("L1"     , L1);
+      fct.DefineConst("L2"     , L2);
+      fct.DefineConst("vLB"  , uLB);
+      fct.DefineConst("PI"  , PI);
+      initVisitor.setVx1(fct);
+
+      fct2.SetExpr(" -vLB*cos( ( (x1)*2.0*PI/ L1))*sin( (x2)*2.0*PI/L2)");
+      fct2.DefineConst("L1"     , L1);
+      fct2.DefineConst("L2"     , L2);
+      fct2.DefineConst("vLB"  , uLB           );
+      fct2.DefineConst("PI"  , PI);
+      initVisitor.setVx2(fct2);
+
+      initVisitor.setVx3(0.0);
+
+      fct3.SetExpr(" 1.0+(vLB*vLB)*3.0/4.0*(cos((x1)*4.0*PI/L1)+cos((x2)*4.0*PI/L2))");
+      fct3.DefineConst("L1"     , L1);
+      fct3.DefineConst("L2"     , L2);
+      fct3.DefineConst("vLB"  , uLB           );
+      fct3.DefineConst("PI"  , PI);
+      initVisitor.setRho(fct3);
+
+      grid->accept(initVisitor);
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      {
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid, geoSch, pathname + "/nodes_geo", WbWriterVtkXmlBinary::getInstance(), conv, comm, true);
+         grid->doPostProcess(0);
+      }
+      double outTime = 1000.0;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      //////////////////////////////////////////////////////////////////////////
+      //PathLine
+      UbSchedulerPtr plSch(new UbScheduler(1000, 1000));
+      D3Q27PathLinePostprocessor pathLine(grid, pathname + "/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm, 4.2, 4.2, 4.2, nueLB, iProcessor);
+      //////////////////////////////////////////////////////////////////////////
+
+      //////////////////////////////////////////////////////////////////////////
+      //Simulation
+      //////////////////////////////////////////////////////////////////////////
+      double endTime = 10000.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/gridRf/CMakeLists.txt b/source/Applications/gridRf/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d67a3834a408228619d509d1053d7b8db05c6793
--- /dev/null
+++ b/source/Applications/gridRf/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(gridRf)
+
+INCLUDE(${SOURCE_ROOT}/core/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES core)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(gridRf BINARY)
diff --git a/source/Applications/gridRf/gridRf.cpp b/source/Applications/gridRf/gridRf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a406609e9f970632eb0e906b47c5c23c93275ebc
--- /dev/null
+++ b/source/Applications/gridRf/gridRf.cpp
@@ -0,0 +1,253 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include <numerics/geometry3d/GbSphere3D.h>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "BlocksPostprocessor.h"
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string pathname = "c:/temp/bFluid/out";
+
+      int numOfThreads = 3;
+
+      const int blocknx1 = 5;
+      const int blocknx2 = 5;
+      const int blocknx3 = 5;
+
+      const int baseLevel = 0;
+      const int refineLevel = 1;
+
+      const double blockLentghX1 = 1.0;
+      const double blockLentghX2 = 1.0;
+      const double blockLentghX3 = 1.0;
+
+      const double gridOriginX1 = 0.0;
+      const double gridOriginX2 = 0.0;
+      const double gridOriginX3 = 0.0;
+
+      double L1 = 7.0;
+      double L2 = 7.0;
+      double L3 = 7.0;
+
+      const double dx = blockLentghX1/static_cast<double>(blocknx1);
+
+      CommunicatorPtr comm(new MPICommunicator());
+
+      LBMReal uLB = 0.01;
+      LBMReal Re = 20.0;
+      LBMReal rhoLB = 1.0;
+      LBMReal l = blockLentghX2 / dx;
+      LBMReal nueLB = (uLB*l)/Re;
+
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+      param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+      param->setRho(rhoLB);
+      param->setVelocityX(uLB);
+      param->setViscosity(nueLB);
+
+      Grid3DPtr grid(new Grid3D());
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+      grid->setPeriodicX1(true);
+      grid->setPeriodicX2(false);
+      grid->setPeriodicX3(false);
+
+      
+      GbObject3DPtr gridCube(new GbCuboid3D(0.0, 0.0, 0.0, L1, L2, L3));
+      GbObject3DPtr geoObject2(new GbCuboid3D(0.0, 0.0+dx, 0.0+dx, L1, L2-dx, L3-dx));
+      //GbObject3DPtr geoObject1(new GbCylinder3D(0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 3.0));
+      GenBlocksGridVisitor genBlocks;
+      genBlocks.addGeoObject(gridCube);
+      //genBlocks.addGeoObject(geoObject2);
+      grid->accept(genBlocks);
+
+      GbObject3DPtr refineCube(new  GbCuboid3D(2.2, 2.2, 2.2, 3.8, 3.8, 3.8));
+      //GbObject3DPtr refineCube(new  GbCuboid3D(1.5, 1.5, 1.5, 3.5, 3.5, 3.5));
+      GbSphere3DPtr refineSphere(new GbSphere3D(3.5, 3.5, 3.5, 0.5));
+
+      RefineCrossAndInsideGbObjectBlockVisitor refVisitor(refineCube, baseLevel, refineLevel-1);
+      grid->accept(refVisitor);
+
+      //RefineInterGbObjectsVisitor refVisitor(refineSphere, refineCube, baseLevel, refineLevel-1);
+      //grid->accept(refVisitor);
+
+      RatioBlockVisitor ratioVisitor(refineLevel);
+      grid->accept(ratioVisitor);
+
+      RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+      grid->accept(ratioSmoothVisitor);
+
+
+      OverlapBlockVisitor overlapVisitor(refineLevel);
+      grid->accept(overlapVisitor);
+
+      GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geoC", WbWriterVtkXmlASCII::getInstance());
+      GbSystem3D::writeGeoObject(refineSphere.get(),pathname + "/geoS", WbWriterVtkXmlASCII::getInstance());
+
+      LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+
+      mu::Parser fctForcingX1, fctForcingX2;
+      //fctForcingX1.SetExpr("2.0*rho* (4.0*PI*PI/(L1/dx)/(L2/dx))*( nue*vlb*sin(x1*2.0*PI/(L1/dx))*cos(x2*2.0*PI/(L2/dx)))");
+      //fctForcingX2.SetExpr("-2.0*rho*(4.0*PI*PI/(L1/dx)/(L2/dx))*( nue*vlb*cos(x1*2.0*PI/(L1/dx))*sin(x2*2.0*PI/(L2/dx)))");
+
+      fctForcingX1.SetExpr("2.0*rho* (4.0*PI*PI/(L1/dx)/(L2/dx))*nue*vlb");
+
+      fctForcingX1.DefineConst("L1"     , static_cast<double>(L1*blocknx1));
+      fctForcingX1.DefineConst("L2"     , static_cast<double>(L2*blocknx2));
+      fctForcingX1.DefineConst("PI"     , PI);
+      fctForcingX1.DefineConst("rho"    , rhoLB);
+      //fctForcingX1.DefineConst("nuelb"  , nueLB);
+      fctForcingX1.DefineConst("vlb"    , uLB);
+
+      fctForcingX2.DefineConst("L1"     , static_cast<double>(L1*blocknx1));
+      fctForcingX2.DefineConst("L2"     , static_cast<double>(L2*blocknx2));
+      fctForcingX2.DefineConst("PI"     , PI);
+      fctForcingX2.DefineConst("rho"    , rhoLB);
+      //fctForcingX2.DefineConst("nuelb"  , nueLB);
+      fctForcingX2.DefineConst("vlb"    , uLB);
+
+      kernel->setForcingX1(fctForcingX1);
+      kernel->setForcingX2(0.0);
+
+
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      //MetisPartitioningGridVisitor metisVisitor(numOfThreads, D3Q27System::B, comm, true);
+      //grid->accept( metisVisitor );
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB);
+      grid->accept(kernelVisitor);
+
+      std::vector<int> dirs;
+      D3Q27System::getLBMDirections(dirs);
+      SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+      grid->accept(interDirsVisitor);
+
+      D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+      grid->accept(undefNodesVisitor);
+
+      int bbOption = 0; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr bc(new D3Q27NoSlipBCAdapter(bbOption));
+      D3Q27InteractorPtr chanel( new D3Q27Interactor(geoObject2, grid, bc,Interactor3D::INVERSESOLID));
+      grid->addAndInitInteractor(chanel);
+
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+
+      mu::Parser fct,fct2,fct3;
+      fct.SetExpr(" vLB*sin( ( (x1)*2.0*PI/ L1))*cos( (x2)*2.0*PI/L2)");
+      fct.DefineConst("L1"     , L1);
+      fct.DefineConst("L2"     , L2);
+      fct.DefineConst("vLB"  , uLB);
+      fct.DefineConst("PI"  , PI);
+      //initVisitor.setVx1(fct);
+      initVisitor.setVx1(0.0);
+
+      fct2.SetExpr(" -vLB*cos( ( (x1)*2.0*PI/ L1))*sin( (x2)*2.0*PI/L2)");
+      fct2.DefineConst("L1"     , L1);
+      fct2.DefineConst("L2"     , L2);
+      fct2.DefineConst("vLB"  , uLB           );
+      fct2.DefineConst("PI"  , PI);
+      //initVisitor.setVx2(fct2);
+      initVisitor.setVx2(0.0);
+
+      initVisitor.setVx3(0.0);
+
+      fct3.SetExpr(" 1.0+(vLB*vLB)*3.0/4.0*(cos((x1)*4.0*PI/L1)+cos((x2)*4.0*PI/L2))");
+      fct3.DefineConst("L1"     , L1);
+      fct3.DefineConst("L2"     , L2);
+      fct3.DefineConst("vLB"  , uLB           );
+      fct3.DefineConst("PI"  , PI);
+      //initVisitor.setRho(fct3);
+      initVisitor.setRho(1.0);
+
+      grid->accept(initVisitor);
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      {
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid, geoSch, pathname + "/nodes_geo", WbWriterVtkXmlBinary::getInstance(), conv, comm, true);
+         grid->doPostProcess(0);
+      }
+      double outTime = 1000.0;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      //grid->doPostProcess(0);
+
+      double endTime = 10000.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+     
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/insitu_demo/CMakeLists.txt b/source/Applications/insitu_demo/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5ecce347855a9dd8f0502e273683ce72bef62124
--- /dev/null
+++ b/source/Applications/insitu_demo/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(insitu_demo)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids ${FETOL_RELEASE_LIBRARY})
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(insitu_demo BINARY)
diff --git a/source/Applications/insitu_demo/config.txt b/source/Applications/insitu_demo/config.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f927708298e2a148da60a827d6960aeec17865bd
--- /dev/null
+++ b/source/Applications/insitu_demo/config.txt
@@ -0,0 +1,24 @@
+#Ordner für Simulationsergebnisse
+path=d:/temp/insitu_demo
+
+#Verfügbare Arbeitsspeicher in Byte
+memory=12e9
+
+#Pfad zum Metafile
+metafile=d:/Data/insituDemo/metafile.csv
+
+#Ausgabezeitschritt
+outstep=1
+
+#maximale Anzahl Simulationszeitschritte
+endstep=10000
+
+#Blockauflösung in Knoten
+blocknx1=8
+blocknx2=8
+blocknx3=8
+
+#Gitterauflösung in Blöcken
+gridnx1=10
+gridnx2=5
+gridnx3=5
\ No newline at end of file
diff --git a/source/Applications/insitu_demo/insitu_demo.cpp b/source/Applications/insitu_demo/insitu_demo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dc6d0381ab02780c6698ad06d95791552fef844d
--- /dev/null
+++ b/source/Applications/insitu_demo/insitu_demo.cpp
@@ -0,0 +1,329 @@
+#include <vfluids.h>
+
+using namespace std;
+
+
+////////////////////////////////////////////////////////////////////////
+void chanel(const char *cstr1)
+{
+   try
+   {
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      int numOfThreads = 6;
+      double availMem = 0;
+
+      //CommunicatorPtr comm = FETOLCommunicator::getInstance();
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+
+      int myid = comm->getProcessID();
+      int mybundle = comm->getBundleID();
+      int root = comm->getRoot();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/insitu_demo";
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/fetol_demo";
+         availMem = 1.5e9;
+
+         if(myid==root && mybundle==root)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(mybundle)+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      ConfigFileReader cf(cstr1);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+
+      pathname = cf.getValue("path");
+      availMem = UbSystem::stringTo<double>(cf.getValue("memory"));
+      string metafile = cf.getValue("metafile");
+      double outstep = UbSystem::stringTo<double>(cf.getValue("outstep"));
+      double endstep = UbSystem::stringTo<double>(cf.getValue("endstep"));
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      double dx = 1;
+
+      const int blocknx1 = UbSystem::stringTo<int>(cf.getValue("blocknx1")); //16;
+      const int blocknx2 = UbSystem::stringTo<int>(cf.getValue("blocknx2"));//16;
+      const int blocknx3 = UbSystem::stringTo<int>(cf.getValue("blocknx3"));//16;
+
+      const int gridNx1 = UbSystem::stringTo<int>(cf.getValue("gridnx1"));//3;
+      const int gridNx2 = UbSystem::stringTo<int>(cf.getValue("gridnx2"));//3;
+      const int gridNx3 = UbSystem::stringTo<int>(cf.getValue("gridnx3"));//3;
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3, H;
+      L2 = H = gridNx2*blocknx1;
+      L3 = gridNx3*blocknx1;
+
+      LBMReal radius = 7;
+      LBMReal uLB = 0.01;
+      LBMReal Re = 3000.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+      LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+      //UbSchedulerPtr restartSch(new UbScheduler(10000, 10000, 100000));
+      //RestartPostprocessor rp(grid, restartSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+      //grid = rp.restart(-1);
+
+      if (grid->getTimeStep() == 0)
+      {
+
+         const int baseLevel = 0;
+         const int refineLevel = 0;
+
+         //obstacle
+         GbObject3DPtr cylinder(new GbCylinder3D(L1*0.5, L2*0.5, 0, L1*0.5, L2*0.5, L3, radius));
+         GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+         D3Q27InteractorPtr cylinderInt;
+
+         //bounding box
+         double d_minX1 = 0.0;
+         double d_minX2 = 0.0;
+         double d_minX3 = 0.0;
+
+         double d_maxX1 = L1;
+         double d_maxX2 = L2;
+         double d_maxX3 = L3;
+
+
+         double blockLength = blocknx1*dx;
+
+         //refinement area
+         double off = 1;
+         GbObject3DPtr refineCube(new  GbCuboid3D(cylinder->getX1Minimum()-off, cylinder->getX2Minimum()-off, cylinder->getX3Minimum(), 
+            cylinder->getX1Maximum()+off, cylinder->getX2Maximum()+off, cylinder->getX3Maximum()));
+
+         GbObject3DPtr gridCube(new GbCuboid3D(d_minX1, d_minX2, d_minX3, d_maxX1, d_maxX2, d_maxX3));
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance()); 
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"Parameters:");
+            UBLOG(logINFO,"L = " << L2/dx );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+            UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineCube, 1);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+
+         mu::Parser fct;
+         fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+         fct.DefineConst("U", uLB);
+         fct.DefineConst("H", H);
+
+         //inflow
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+         InteractorsHelper intHelper(grid, metisVisitor);
+         //intHelper.addInteractor(cylinderInt);
+         intHelper.addInteractor(addWallYminInt);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallYmaxInt);
+         intHelper.addInteractor(addWallZmaxInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         //FETOLSetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+         //option = 0 - ohne param., option = 1 - mit param.
+         //int option = 0;
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         intHelper.setBC();
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+         //initVisitor.setVx1(fct);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+      else
+      {
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+      }
+
+      UbSchedulerPtr stepSch(new UbScheduler(outstep));
+      //D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv);
+
+      InSituVTKPostprocessor isp(grid, stepSch, metafile, conv);
+      //isp.update(0);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endstep, stepSch));
+      
+      if(myid == 0) 
+         UBLOG(logINFO,"Simulation-start");
+      
+      calculation->calculate();
+      
+      if(myid == 0) 
+         UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   if ( argv != NULL )
+   {
+      if (argc > 1)
+      {
+            chanel(argv[1]);
+      }
+      else
+      {
+         cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+      }
+   }
+
+   return 0;
+}
+
diff --git a/source/Applications/insitu_demoserver/CMakeLists.txt b/source/Applications/insitu_demoserver/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f88611140ac6498dd878f3074bdf35e23e3dcc67
--- /dev/null
+++ b/source/Applications/insitu_demoserver/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(insitu_demoserver)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids ${FETOL_RELEASE_LIBRARY})
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(insitu_demoserver BINARY)
diff --git a/source/Applications/insitu_demoserver/insitu_demoserver.cpp b/source/Applications/insitu_demoserver/insitu_demoserver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3f9d3912bc8525d6280360be4ab8eed19332e74
--- /dev/null
+++ b/source/Applications/insitu_demoserver/insitu_demoserver.cpp
@@ -0,0 +1,229 @@
+#define vtkRenderingCore_AUTOINIT 4(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingFreeTypeOpenGL,vtkRenderingOpenGL)
+#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL)
+
+#include "vtkActor.h"
+#include "vtkContourFilter.h"
+#include "vtkDataSetMapper.h"
+#include "vtkDebugLeaks.h"
+#include "vtkDoubleArray.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkRectilinearGrid.h"
+#include "vtkRegressionTestImage.h"
+#include "vtkRenderWindow.h"
+#include "vtkOpenGLRenderer.h"
+#include "vtkSocketCommunicator.h"
+#include "vtkSocketController.h"
+#include "vtkStructuredGrid.h"
+#include "vtkImageData.h"
+#include "vtkUnstructuredGrid.h"
+#include "vtkCamera.h"
+#include "vtkImageActor.h"
+#include <vtkXMLUnstructuredGridWriter.h>
+#include "vtkRenderWindowInteractor.h"
+#include "vtkOpenGLActor.h"
+#include "vtkSmartPointer.h"
+#include "vtkInteractorStyleTrackballCamera.h"
+#include <vtkProperty.h>
+#include <vtkPointData.h>
+#include <vtkPlane.h>
+#include <vtkCutter.h>
+
+#include <boost/thread.hpp>
+
+#define VTK_CREATE(type, name) \
+   vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+
+
+static const int scMsgLength = 10;
+
+static void CleanUp(vtkSmartPointer<vtkSocketCommunicator> vtkNotUsed(comm),
+                    vtkSmartPointer<vtkSocketController> vtkNotUsed(contr))
+{
+   // This will close the connection as well as delete
+   // the communicator
+   // Deleting no longer necessary with smart pointers.
+   //   comm->Delete();
+   //   contr->Delete();
+}
+
+using namespace std;
+
+vtkSmartPointer<vtkSocketController> contr;
+vtkSmartPointer<vtkSocketCommunicator> comm;
+
+void receive(vtkSmartPointer<vtkUnstructuredGrid> ugrid, vtkSmartPointer<vtkDataSetMapper> umapper, vtkSmartPointer<vtkRenderWindow> renWin)
+{
+   int step;
+   while (true)
+   {
+      if (!comm->Receive(&step, 1, 1, 11))
+      {
+         cerr << "Server error: Error receiving data." << endl;
+         CleanUp(comm, contr);
+         return;
+      }
+
+      cout << "step: "<<step<<"\n";
+
+      if (!comm->Receive(ugrid, 1, 9))
+      {
+         cerr << "Client error: Error receiving data." << endl;
+         CleanUp(comm, contr);
+         return;
+      }
+      double range[2];
+      ugrid->GetPointData()->GetArray("Vx")->GetRange(range);
+      umapper->SetScalarRange(range);
+      umapper->Update();
+      //renWin->Render();
+   }
+}
+
+////////////////////////////////////////////////////////////////////////
+void server()
+{
+   try
+   {
+      contr = vtkSmartPointer<vtkSocketController>::New();
+      contr->Initialize();
+
+      comm = vtkSmartPointer<vtkSocketCommunicator>::New();
+
+      string hostname = "localhost";
+      int port=11111;
+
+      // Establish connection
+      if (!comm->WaitForConnection(port))
+      {
+         cerr << "Server error: Wait timed out or could not initialize socket." << endl;
+         return;
+      }
+
+      // Test receiving vtkDataObject
+      VTK_CREATE(vtkUnstructuredGrid, ugrid);
+
+      int step;
+
+      if (!comm->Receive(&step, 1, 1, 11))
+      {
+         cerr << "Server error: Error receiving data." << endl;
+         CleanUp(comm, contr);
+         return;
+      }
+
+      cout << "step: "<<step<<"\n";
+
+      if (!comm->Receive(ugrid, 1, 9))
+      {
+         cerr << "Client error: Error receiving data." << endl;
+         CleanUp(comm, contr);
+         return;
+      }
+
+      vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer = vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
+      writer->SetInput(ugrid);
+      writer->SetFileName("test.vtu");
+      writer->SetDataModeToAscii();
+      writer->Update();
+
+      //vtkPlane
+      vtkSmartPointer<vtkPlane> plane = vtkPlane::New();
+      plane->SetNormal(0.0, 1.0, 0.0);
+      plane->SetOrigin(40, 19.5, 19.5);
+
+      //Cut
+      vtkSmartPointer<vtkCutter> planeCut = vtkCutter::New();
+      planeCut->SetInput(ugrid);
+      planeCut->SetCutFunction(plane);
+      planeCut->Update();
+
+      VTK_CREATE(vtkDataSetMapper, umapper);
+      //umapper->SetInput(planeCut->GetOutput());
+      umapper->SetInput(ugrid);
+
+      umapper->SetScalarModeToUsePointFieldData();
+      umapper->SetColorModeToMapScalars();
+      umapper->ScalarVisibilityOn();
+      double range[2];
+      //planeCut->GetOutput()->GetPointData()->GetArray("Vx")->GetRange(range);
+      ugrid->GetPointData()->GetArray("Vx")->GetRange(range);
+      umapper->SetScalarRange(range);
+      umapper->SelectColorArray("Vx");
+
+      VTK_CREATE(vtkActor, uactor);
+      uactor->SetMapper(umapper);
+
+      VTK_CREATE(vtkRenderer, ren);
+      ren->AddActor(uactor);
+      ren->SetBackground( 0.1, 0.2, 0.4 );
+
+      VTK_CREATE(vtkRenderWindow, renWin);
+      renWin->SetSize(1024,800);
+      renWin->AddRenderer(ren);
+
+      //while (true)
+      //{
+      //   if (!comm->Receive(&step, 1, 1, 11))
+      //   {
+      //      cerr << "Server error: Error receiving data." << endl;
+      //      CleanUp(comm, contr);
+      //      return;
+      //   }
+
+      //   cout << "step: "<<step<<"\n";
+
+      //   if (!comm->Receive(ugrid, 1, 9))
+      //   {
+      //      cerr << "Client error: Error receiving data." << endl;
+      //      CleanUp(comm, contr);
+      //      return;
+      //   }
+
+      //   //writer->Update();
+      //   
+      //   planeCut->Update();
+      //   planeCut->GetOutput()->GetPointData()->GetArray("Vx")->GetRange(range);
+      //   umapper->SetScalarRange(range);
+      //   umapper->Update();
+      //   renWin->Render();
+      //}
+
+      boost::thread t(boost::bind( &receive, ugrid, umapper,renWin));
+
+      vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
+      iren->SetRenderWindow(renWin);
+
+      vtkInteractorStyleTrackballCamera *style = vtkInteractorStyleTrackballCamera::New();
+      iren->SetInteractorStyle(style);
+
+      iren->Initialize();
+      iren->Start();
+
+      iren->Delete();
+      style->Delete();
+
+      CleanUp(comm, contr);
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   server();
+}
+
diff --git a/source/Applications/micropart/CMakeLists.txt b/source/Applications/micropart/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..15e818a09c9634878780600a3def0002c70d675c
--- /dev/null
+++ b/source/Applications/micropart/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(micropart)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(mcpart BINARY)
diff --git a/source/Applications/micropart/mcpart.cpp b/source/Applications/micropart/mcpart.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3089a6e4311fd1ecee37e52a2eae4dc5fa5c3fa0
--- /dev/null
+++ b/source/Applications/micropart/mcpart.cpp
@@ -0,0 +1,14 @@
+#include "micropartTestQs3.hpp"
+//#include "micropartSetup1.hpp"
+//#include "micropartSetup2.hpp"
+//#include "orifice.hpp"
+
+int main(int argc, char* argv[])
+{
+   micropartTestQs3(argv[1]);
+   //runSetup1(argv[1]);
+   //runSetup2(argv[1]);
+   //orifice(argv[1]);
+   return 0;
+}
+
diff --git a/source/Applications/micropart/micropartSetup1.hpp b/source/Applications/micropart/micropartSetup1.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..79fe30059a596f9a9600c4eb45eddd248bb35a62
--- /dev/null
+++ b/source/Applications/micropart/micropartSetup1.hpp
@@ -0,0 +1,451 @@
+#include <iostream>
+#include <string>
+#include <map>
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include "numerics/geometry3d/GbSphere3D.h"
+#include "BlocksPostprocessor.h"
+#include "Grid3D.h"
+#include "Patch3D.h"
+#include "Patch3DSystem.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "LBMKernelETD3Q27BGK.h"
+#include "CalculationManager.h" 
+#include "D3Q27SetConnectorsBlockVisitor.h" 
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "Communicator.h"
+#include "MPICommunicator.h"
+#include "SimpleGeometricPartitioner.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27TriFaceMeshInteractor.h"
+#include "ConfigFileReader.h"
+#include "StringUtil.hpp"
+#include "D3Q27PressureDifferencePostprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "LBMUnitConverter.h"
+#include "NUPSCounterPostprocessor.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "GenBlocksGridVisitor.h"
+#include "D3Q27PathLinePostprocessor.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+   //
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h"
+#include "numerics/geometry3d/GbTriFaceMesh3D.h"
+#include "D3Q27System.h"
+#include <basics/transmitter/TbTransmitterMpiPool.h>
+#include "MathUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "SolidBlocksHelper.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "RestartPostprocessor.h"
+#include "LBMKernelETD3Q27CCLB.h"
+#include "D3Q27IncompressibleOffsetInterpolationProcessor.h"
+
+using namespace std;
+
+void runSetup1(const char *cstr)
+{
+   try
+   {
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+      int numprocs = comm->getNumberOfProcesses();
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      double availMem = 0;
+      string geoFile;
+      int numOfThreads = 1;
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "c:/temp/micropart";
+         availMem = 3.0e9;
+         //geoFile = "c:/Data/micropart/DK19_7_02_Martin.stl";
+         //geoFile = "c:/Data/micropart/ktoolcav.stl";
+         //geoFile = "c:/Data/micropart/boxN.stl";
+         //geoFile = "c:/Data/bananas/Banana_boxD.stl";
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/micropart_s1";
+         //pathname = "/work/koskuche/scratch/micropart2";
+         availMem = 12.0e9;
+         geoFile = "/home/koskuche/data/micropart/DK19_7_02_Martin.stl";
+
+         numOfThreads = 1;
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      UbLog::reportingLevel() = logINFO;
+      //UbLog::reportingLevel() = logDEBUG1;
+
+      int nodePerBlockX1 = 8; //Anzahl an Knoten pro Block
+      int nodePerBlockX2 = 8;//(int)16;
+      int nodePerBlockX3 = 8;//(int)16;
+
+      double bH = nodePerBlockX1;    //gewuenschte Rand- und Blockbreite
+
+      //Simulation Parameters
+
+      double sf = 1.0;
+      double endTime = 160001*sf;
+      //length [m]
+      double lSI = 0.067;
+      //length [LB]
+      double lLB = 30;
+
+      double dx = 0.0134;//lSI/lLB;
+
+      double left_offset = 0.5;
+      double right_offset  = 0.5;//2*0.5
+      double front_offset = 0.15;
+      double back_offset  = 0.15;
+      double top_offset = 0.0;
+      double bottom_offset  = 0.07;
+
+      LBMReal vLB = 0.016103/sf;
+      LBMReal Re;
+      LBMReal rhoLB = 0.0;
+      LBMReal nueLB = 0.0000249/sf;//(vLB*lLB)/Re;
+      Re = (vLB*(0.303/dx))/nueLB;
+      const int baseLevel = 0;
+      const int refineLevel = 5;
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      //////////////////////////////////////////////////////////////////////////
+      GbObject3DPtr refineCube1(new  GbCuboid3D(-0.2222890,-0.52993, -0.141754, 0.578916113,0.6089970,0.0446053));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube1.get(), pathname+"/geo/refineCube1", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube2(new  GbCuboid3D(-0.16,-0.05, -0.141754, 0.2,0.05,0.0446053));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube2.get(), pathname+"/geo/refineCube2", WbWriterVtkXmlASCII::getInstance());
+      //////////////////////////////////////////////////////////////////////////
+
+      Grid3DPtr grid(new Grid3D());
+
+      UbSchedulerPtr rSch(new UbScheduler());
+      rSch->addSchedule(20000, 20000, endTime-1);
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         rp->reconnect();
+
+         if(myid ==0) UBLOG(logINFO,"TimeStep = " <<grid->getTimeStep());
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         //PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         //grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " <<lLB );
+            UBLOG(logINFO,"v = " <<vLB );
+            UBLOG(logINFO,"rho = " <<rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+
+         ////////////////////////////////////////////////////////////////////////
+         //Grid
+         //////////////////////////////////////////////////////////////////////////
+         grid->setDeltaX(dx);
+         grid->setBlockNX(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2);
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Geometrie
+         ////////////////////////////////////////////////////////////////////////////
+         //GbTriFaceMesh3DPtr geo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+
+         //if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo", WbWriterVtkXmlASCII::getInstance());
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Randgeometrien erstellen
+         ////////////////////////////////////////////////////////////////////////////
+         
+         GbCuboid3DPtr plate1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -1.515e-1, -6.831e-2, 7.5, 1.515e-1, 0.0 ));
+
+         GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+         GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+         GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -1.0e-1, 7.5, 2.515e-1, -6.831e-2 ));
+         GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -0.0000001, 7.5, 2.515e-1, 1.0e-1 ));
+         //GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -7.5, 1.515e-1, -6.831e-2, 7.5, 2.515e-1, 0.0  ));
+         GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -7.5, 1.515e-1, -9.831e-2, 7.5, 2.515e-1, 0.06  ));
+         GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, 0.0, 7.5, -1.515e-1, -1.0e-1 ));
+
+         GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -8.0, -1.0, -1.0, -7.5, 1.0, 1.0 ));
+         GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 7.5, -1.0, -1.0, 8.0, 1.0, 1.0 ));
+
+         if(myid == 0)
+         {
+            GbSystem3D::writeGeoObject(plate2.get(),pathname+"/geo/plate2", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate3.get(),pathname+"/geo/plate3", WbWriterVtkXmlASCII::getInstance());
+
+            GbSystem3D::writeGeoObject(plate1_1.get(),pathname+"/geo/plate1_1", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate1_2.get(),pathname+"/geo/plate1_2", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate1_3.get(),pathname+"/geo/plate1_3", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate1_4.get(),pathname+"/geo/plate1_4", WbWriterVtkXmlASCII::getInstance());
+
+            GbSystem3D::writeGeoObject(inflow.get(),pathname+"/geo/inflow", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(outflow.get(),pathname+"/geo/outflow", WbWriterVtkXmlASCII::getInstance());
+         }
+
+         double shiftForMG=grid->getDeltaX(refineLevel)*nodePerBlockX1 / 3.0*1.5;
+
+         GbObject3DPtr gridCube(new GbCuboid3D(plate1->getX1Minimum()-shiftForMG, plate1->getX2Minimum()-shiftForMG, plate1->getX3Minimum()-shiftForMG,
+                                                plate1->getX1Maximum()+shiftForMG, 
+                                                plate1->getX2Maximum()+shiftForMG, 
+                                                plate1->getX3Maximum()+shiftForMG));
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectBlockVisitor refVisitor1(refineCube1, baseLevel, refineLevel-3);
+            grid->accept(refVisitor1);
+
+            RefineCrossAndInsideGbObjectBlockVisitor refVisitor2(refineCube2, baseLevel, refineLevel-1);
+            grid->accept(refVisitor2);
+
+            RatioBlockVisitor ratioVisitor(refineLevel);
+            grid->accept(ratioVisitor);
+
+            RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            grid->accept(ratioSmoothVisitor);
+
+            OverlapBlockVisitor overlapVisitor(refineLevel);
+            grid->accept(overlapVisitor);
+
+            std::vector<int> dirs;
+            D3Q27System::getLBMDirections(dirs);
+            SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            grid->accept(interDirsVisitor);
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //INTERAKTOREN SETZEN (=Randbedingungen)
+         //////////////////////////////////////////////////////////////////////////
+         //oben/unten = Haftrand
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         //D3Q27TriFaceMeshInteractorPtr geoInt = D3Q27TriFaceMeshInteractorPtr( new D3Q27TriFaceMeshInteractor(geo, grid, D3Q27BoundaryConditionAdapterPtr(new D3Q27NoSlipBCAdapter(bbOption)),Interactor3D::SOLID));
+         //geoInt->setUseHalfSpaceCheck(true);
+         //geoInt->setRegardPointInObjectTest(true);
+
+         //D3Q27InteractorPtr plate1Int(new D3Q27Interactor(plate1, grid, bcObst,Interactor3D::INVERSESOLID));
+         D3Q27InteractorPtr plate2Int(new D3Q27Interactor(plate2, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr plate3Int(new D3Q27Interactor(plate3, grid, bcObst,Interactor3D::SOLID));
+
+         D3Q27InteractorPtr plate1_1Int(new D3Q27Interactor(plate1_1, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr plate1_2Int(new D3Q27Interactor(plate1_2, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr plate1_3Int(new D3Q27Interactor(plate1_3, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr plate1_4Int(new D3Q27Interactor(plate1_4, grid, bcObst,Interactor3D::SOLID));
+
+         //links: geschwindigkeits-einfluss
+         //Velocity-BC
+         //////////////////////////////////////////////////////////////////////////
+         mu::Parser fct;
+         fct.DefineConst("vx1"  , vLB*9.0/4.0);
+         fct = Utilities::getDuctParaboloidX(plate1->getX2Centroid(), plate1->getX2Maximum() - plate1->getX2Minimum(), plate1->getX3Centroid(), plate1->getX3Minimum() - plate1->getX3Maximum(), vLB*9.0/4.0);
+         //fct.SetExpr("vx1");
+         //////////////////////////////////////////////////////////////////////////
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+        // velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         //rechts: druckrand
+         //Density-BC
+         //fuer Kompressibles Modell  rho = 1.0
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(1);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(outflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         //MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelIntersected, D3Q27System::B, true, numOfThreads);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+         //sd.addInteractor(geoInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+         sd.addInteractor(plate1_1Int);
+         sd.addInteractor(plate1_2Int);
+         sd.addInteractor(plate1_3Int);
+         sd.addInteractor(plate1_4Int);
+         sd.addInteractor(plate2Int);
+         sd.addInteractor(plate3Int);
+         sd.deleteSolidBlocks();     
+
+         grid->accept( metisVisitor );
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod_temp = nob * (nodePerBlockX1+gl) * (nodePerBlockX2+gl) * (nodePerBlockX3+gl);
+         unsigned long nod = nob * (nodePerBlockX1) * (nodePerBlockX2) * (nodePerBlockX3);
+         double needMemAll  = double(nod_temp*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }  
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+         //option = 0 - ohne param., option = 1 - mit param.
+         int option = 0;
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2, option));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //canal
+         //grid->addAndInitInteractor(geoInt);
+         grid->addAndInitInteractor(plate1_1Int);
+         grid->addAndInitInteractor(plate1_2Int);
+         grid->addAndInitInteractor(plate1_3Int);
+         grid->addAndInitInteractor(plate1_4Int);
+         grid->addAndInitInteractor(plate2Int);
+         grid->addAndInitInteractor(plate3Int);
+
+         //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+
+         //////////////////////////////////////////////////////////////////////////
+         //connectoren setzen:
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         //////////////////////////////////////////////////////////////////////////
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+         //////////////////////////////////////////////////////////////////////////
+         //Stroemungsfeld initialisieren
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB); //1.0
+         //initVisitor.setVx1(0.0); 
+         grid->accept(initVisitor);
+
+         //if(myid == 0)
+         //{
+         //   //Abstände "q" als Linien rausschreiben
+         //   std::vector< UbTupleFloat3 > nodes;
+         //   std::vector< UbTupleInt2 >   lines;
+         //   geoInt->addQsLineSet(nodes, lines);
+         //   WbWriterVtkXmlBinary::getInstance()->writeLines(pathname+"/grid/qs",nodes,lines);
+         //}
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");
+
+      }
+      //////////////////////////////////////////////////////////////////////////
+      //Set Postprozessors
+      //////////////////////////////////////////////////////////////////////////
+      {
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+         grid->doPostProcess(0);
+      }
+
+      UbSchedulerPtr nupsSch(new UbScheduler(1, 5, 10));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 2000;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      stepSch->addSchedule(100, 100, 100);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid,stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv,  comm);
+      //////////////////////////////////////////////////////////////////////////
+      //PathLine
+      //UbSchedulerPtr plSch(new UbScheduler(10, 1500));
+      //D3Q27PathLinePostprocessor pathLine(grid, pathname + "/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm, -0.3285474538, 0.09692341,-0.0376166666, nueLB, iProcessor);
+      //////////////////////////////////////////////////////////////////////////
+      //Simulation
+      //////////////////////////////////////////////////////////////////////////
+
+      UbSchedulerPtr visSch(stepSch);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
diff --git a/source/Applications/micropart/micropartSetup2.hpp b/source/Applications/micropart/micropartSetup2.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e2ee2d18c6eea114bdbd9e161d9e8628b5ef42aa
--- /dev/null
+++ b/source/Applications/micropart/micropartSetup2.hpp
@@ -0,0 +1,444 @@
+#include <iostream>
+#include <string>
+#include <map>
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include "numerics/geometry3d/GbSphere3D.h"
+#include "BlocksPostprocessor.h"
+#include "Grid3D.h"
+#include "Patch3D.h"
+#include "Patch3DSystem.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "LBMKernelETD3Q27BGK.h"
+#include "CalculationManager.h" 
+#include "D3Q27SetConnectorsBlockVisitor.h" 
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "Communicator.h"
+#include "MPICommunicator.h"
+#include "SimpleGeometricPartitioner.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27TriFaceMeshInteractor.h"
+#include "ConfigFileReader.h"
+#include "StringUtil.hpp"
+#include "D3Q27PressureDifferencePostprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "LBMUnitConverter.h"
+#include "NUPSCounterPostprocessor.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "GenBlocksGridVisitor.h"
+#include "D3Q27PathLinePostprocessor.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+   //
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h"
+#include "numerics/geometry3d/GbTriFaceMesh3D.h"
+#include "D3Q27System.h"
+#include <basics/transmitter/TbTransmitterMpiPool.h>
+#include "MathUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "SolidBlocksHelper.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "RestartPostprocessor.h"
+#include "D3Q27IncompressibleOffsetInterpolationProcessor.h"
+#include "LBMKernelETD3Q27CCLB.h"
+
+using namespace std;
+
+void runSetup2(const char *cstr)
+{
+   try
+   {
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+      int numprocs = comm->getNumberOfProcesses();
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      double availMem = 0;
+      string geoFile;
+      int numOfThreads = 1;
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "c:/temp/micropart";
+         availMem = 3.0e9;
+         //geoFile = "c:/Data/micropart/DK19_7_02_Martin.stl";
+         //geoFile = "c:/Data/micropart/ktoolcav.stl";
+         //geoFile = "c:/Data/micropart/boxN.stl";
+         //geoFile = "c:/Data/bananas/Banana_boxD.stl";
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/micropart2";
+         availMem = 12.0e9;
+         //geoFile = "/home/koskuche/data/micropart/DK19_7_02_Martin.stl";
+
+         numOfThreads = 1;
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      UbLog::reportingLevel() = logINFO;
+      //UbLog::reportingLevel() = logDEBUG1;
+
+      int nodePerBlockX1 = 16; //Anzahl an Knoten pro Block
+      int nodePerBlockX2 = 16;//(int)16;
+      int nodePerBlockX3 = 16;//(int)16;
+
+      double bH = nodePerBlockX1;    //gewuenschte Rand- und Blockbreite
+
+      //Simulation Parameters
+
+      //length [m]
+      double lSI = 0.067;
+      //length [LB]
+      double lLB = 30;
+
+      double dx = 0.0134*0.5;//lSI/lLB;
+
+      double left_offset = 0.5;
+      double right_offset  = 0.5;//2*0.5
+      double front_offset = 0.15;
+      double back_offset  = 0.15;
+      double top_offset = 0.0;
+      double bottom_offset  = 0.07;
+
+      LBMReal vLB = 0.016103;
+      LBMReal Re;
+      LBMReal rhoLB = 0.0;
+      LBMReal nueLB = 0.0000249*2.0;//(vLB*lLB)/Re;
+      Re = (vLB*(0.303/dx))/nueLB;
+      const int baseLevel = 0;
+      const int refineLevel = 5;
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      //////////////////////////////////////////////////////////////////////////
+      GbObject3DPtr refineCube1(new  GbCuboid3D(-0.2222890,-0.52993, -0.141754, 0.578916113,0.6089970,0.0446053));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube1.get(), pathname+"/geo/refineCube1", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube2(new  GbCuboid3D(-0.16,-0.05, -0.141754, 0.2,0.05,0.0446053));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube2.get(), pathname+"/geo/refineCube2", WbWriterVtkXmlASCII::getInstance());
+      //////////////////////////////////////////////////////////////////////////
+
+      Grid3DPtr grid(new Grid3D());
+
+      UbSchedulerPtr rSch(new UbScheduler(1000, 1000));
+      //RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         //grid = rp->restart(UbSystem::stringTo<int>(opt));
+         //rp->reconnect();
+         grid->setTimeStep(UbSystem::stringTo<int>(opt));
+
+         if(myid ==0) UBLOG(logINFO,"TimeStep = " <<grid->getTimeStep());
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " <<lLB );
+            UBLOG(logINFO,"v = " <<vLB );
+            UBLOG(logINFO,"rho = " <<rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+
+         ////////////////////////////////////////////////////////////////////////
+         //Grid
+         //////////////////////////////////////////////////////////////////////////
+         grid->setDeltaX(dx);
+         grid->setBlockNX(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2);
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Geometrie
+         ////////////////////////////////////////////////////////////////////////////
+         //GbTriFaceMesh3DPtr geo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+
+         //if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo", WbWriterVtkXmlASCII::getInstance());
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Randgeometrien erstellen
+         ////////////////////////////////////////////////////////////////////////////
+         double shiftForMG=grid->getDeltaX(refineLevel)*nodePerBlockX1 / 3.0*2.0;
+         GbCuboid3DPtr plate1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -1.515e-1, -6.831e-2, 7.5, 1.515e-1, 0.0 ));
+
+         GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+         GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+         GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -1.0e-1, 7.5, 2.515e-1, -6.831e-2 ));
+         GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -0.0000001, 7.5, 2.515e-1, 1.0e-1 ));
+         GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -7.5, 1.515e-1, -6.831e-2, 7.5, 2.515e-1, 0.0  ));
+         GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, 0.0, 7.5, -1.515e-1, -1.0e-1 ));
+
+         GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -8.0, -1.0, -1.0, -7.5, 1.0, 1.0 ));
+         GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 7.5, -1.0, -1.0, 8.0, 1.0, 1.0 ));
+
+         if(myid == 0)
+         {
+            GbSystem3D::writeGeoObject(plate1.get(),pathname+"/geo/plate1", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate2.get(),pathname+"/geo/plate2", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate3.get(),pathname+"/geo/plate3", WbWriterVtkXmlASCII::getInstance());
+
+            GbSystem3D::writeGeoObject(plate1_1.get(),pathname+"/geo/plate1_1", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate1_2.get(),pathname+"/geo/plate1_2", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate1_3.get(),pathname+"/geo/plate1_3", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(plate1_4.get(),pathname+"/geo/plate1_4", WbWriterVtkXmlASCII::getInstance());
+
+            GbSystem3D::writeGeoObject(inflow.get(),pathname+"/geo/inflow", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(outflow.get(),pathname+"/geo/outflow", WbWriterVtkXmlASCII::getInstance());
+         }
+
+         GbObject3DPtr gridCube(new GbCuboid3D(plate1->getX1Minimum()-shiftForMG, plate1->getX2Minimum()-shiftForMG, plate1->getX3Minimum()-shiftForMG,
+                                                plate1->getX1Maximum()+shiftForMG, 
+                                                plate1->getX2Maximum()+shiftForMG, 
+                                                plate1->getX3Maximum()+shiftForMG));
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectBlockVisitor refVisitor1(refineCube1, baseLevel, refineLevel-3);
+            grid->accept(refVisitor1);
+
+            RefineCrossAndInsideGbObjectBlockVisitor refVisitor2(refineCube2, baseLevel, refineLevel-1);
+            grid->accept(refVisitor2);
+
+            RatioBlockVisitor ratioVisitor(refineLevel);
+            grid->accept(ratioVisitor);
+
+            RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            grid->accept(ratioSmoothVisitor);
+
+            OverlapBlockVisitor overlapVisitor(refineLevel);
+            grid->accept(overlapVisitor);
+
+            std::vector<int> dirs;
+            D3Q27System::getLBMDirections(dirs);
+            SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            grid->accept(interDirsVisitor);
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //INTERAKTOREN SETZEN (=Randbedingungen)
+         //////////////////////////////////////////////////////////////////////////
+         //oben/unten = Haftrand
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         //D3Q27TriFaceMeshInteractorPtr geoInt = D3Q27TriFaceMeshInteractorPtr( new D3Q27TriFaceMeshInteractor(geo, grid, D3Q27BoundaryConditionAdapterPtr(new D3Q27NoSlipBCAdapter(bbOption)),Interactor3D::SOLID));
+         //geoInt->setUseHalfSpaceCheck(true);
+         //geoInt->setRegardPointInObjectTest(true);
+
+         //D3Q27InteractorPtr plate1Int(new D3Q27Interactor(plate1, grid, bcObst,Interactor3D::INVERSESOLID));
+         D3Q27InteractorPtr plate2Int(new D3Q27Interactor(plate2, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr plate3Int(new D3Q27Interactor(plate3, grid, bcObst,Interactor3D::SOLID));
+
+         D3Q27InteractorPtr plate1_1Int(new D3Q27Interactor(plate1_1, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr plate1_2Int(new D3Q27Interactor(plate1_2, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr plate1_3Int(new D3Q27Interactor(plate1_3, grid, bcObst,Interactor3D::SOLID));
+         D3Q27InteractorPtr plate1_4Int(new D3Q27Interactor(plate1_4, grid, bcObst,Interactor3D::SOLID));
+
+         //links: geschwindigkeits-einfluss
+         //Velocity-BC
+         //////////////////////////////////////////////////////////////////////////
+         mu::Parser fct;
+         fct.DefineConst("vx1"  , vLB*9.0/4.0 );
+         fct = Utilities::getDuctParaboloidX(plate1->getX2Centroid(), plate1->getX2Maximum() - plate1->getX2Minimum(), plate1->getX3Centroid(), plate1->getX3Minimum() - plate1->getX3Maximum(), vLB*9.0/4.0);
+         //fct.SetExpr("vx1");
+         //////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         //rechts: druckrand
+         //Density-BC
+         //fuer Kompressibles Modell  rho = 1.0
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(1);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(outflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+         //sd.addInteractor(geoInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+         sd.addInteractor(plate1_1Int);
+         sd.addInteractor(plate1_2Int);
+         sd.addInteractor(plate1_3Int);
+         sd.addInteractor(plate1_4Int);
+         sd.addInteractor(plate2Int);
+         sd.addInteractor(plate3Int);
+         sd.deleteSolidBlocks();     
+
+         grid->accept( metisVisitor );
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod_temp = nob * (nodePerBlockX1+gl) * (nodePerBlockX2+gl) * (nodePerBlockX3+gl);
+         unsigned long nod = nob * (nodePerBlockX1) * (nodePerBlockX2) * (nodePerBlockX3);
+         double needMemAll  = double(nod_temp*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }  
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //canal
+         //grid->addAndInitInteractor(geoInt);
+         grid->addAndInitInteractor(plate1_1Int);
+         grid->addAndInitInteractor(plate1_2Int);
+         grid->addAndInitInteractor(plate1_3Int);
+         grid->addAndInitInteractor(plate1_4Int);
+         grid->addAndInitInteractor(plate2Int);
+         grid->addAndInitInteractor(plate3Int);
+
+         //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+
+         //////////////////////////////////////////////////////////////////////////
+         //connectoren setzen:
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         //////////////////////////////////////////////////////////////////////////
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+         //////////////////////////////////////////////////////////////////////////
+         //Stroemungsfeld initialisieren
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB); //1.0
+         //initVisitor.setVx1(0.0); 
+         grid->accept(initVisitor);
+
+         //if(myid == 0)
+         //{
+         //   //Abstände "q" als Linien rausschreiben
+         //   std::vector< UbTupleFloat3 > nodes;
+         //   std::vector< UbTupleInt2 >   lines;
+         //   geoInt->addQsLineSet(nodes, lines);
+         //   WbWriterVtkXmlBinary::getInstance()->writeLines(pathname+"/grid/qs",nodes,lines);
+         //}
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");
+
+      }
+      //////////////////////////////////////////////////////////////////////////
+      //Set Postprozessors
+      //////////////////////////////////////////////////////////////////////////
+      {
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+         grid->doPostProcess(0);
+      }
+
+      UbSchedulerPtr nupsSch(new UbScheduler(1, 5, 10));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 2000;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid,stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv,  comm);
+      //////////////////////////////////////////////////////////////////////////
+      //PathLine
+      //UbSchedulerPtr plSch(new UbScheduler(10, 1500));
+      //D3Q27PathLinePostprocessor pathLine(grid, pathname + "/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm, -0.3285474538, 0.09692341,-0.0376166666, nueLB, iProcessor);
+      //////////////////////////////////////////////////////////////////////////
+      //Simulation
+      //////////////////////////////////////////////////////////////////////////
+      double endTime = 1000000;
+      UbSchedulerPtr visSch(stepSch);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
diff --git a/source/Applications/micropart/micropartTestQs.hpp b/source/Applications/micropart/micropartTestQs.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..895e1759239be41dbe1b0b5e433aaee98c6eb200
--- /dev/null
+++ b/source/Applications/micropart/micropartTestQs.hpp
@@ -0,0 +1,380 @@
+#include <iostream>
+#include <string>
+#include <map>
+#include <vfluids.h>
+
+
+using namespace std;
+
+void micropartTestQs(const char *cstr)
+{
+   try
+   {
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+      int numprocs = comm->getNumberOfProcesses();
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      double availMem = 0;
+      string geoFile;
+      int numOfThreads = 3;
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "c:/temp/micropart";
+         availMem = 3.0e9;
+         //geoFile = "c:/Data/micropart/DK19_7_02_Martin.stl";
+         geoFile = "d:/Data/micropart/E0019B_mit_Radien.stl";
+         //geoFile = "c:/Data/micropart/boxN.stl";
+         //geoFile = "c:/Data/bananas/Banana_boxD.stl";
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/micropart3";
+         //pathname = "/work/koskuche/scratch/micropart2";
+         availMem = 12.0e9;
+         geoFile = "/home/koskuche/data/micropart/E0019B_mit_Radien_Inv_new_Box.stl";
+
+         numOfThreads = 8;
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      UbLog::reportingLevel() = logINFO;
+      //UbLog::reportingLevel() = logDEBUG1;
+
+      int nodePerBlockX1 = 8; //Anzahl an Knoten pro Block
+      int nodePerBlockX2 = 8;//(int)16;
+      int nodePerBlockX3 = 8;//(int)16;
+
+      double bH = nodePerBlockX1;    //gewuenschte Rand- und Blockbreite
+
+      //Simulation Parameters
+
+      //length [m]
+      double lSI = 0.067;
+      //length [LB]
+      double lLB = 30;
+
+      double dx = 5;//0.0134;//lSI/lLB;
+
+      double left_offset = 0.5;
+      double right_offset  = 0.5;//2*0.5
+      double front_offset = 0.15;
+      double back_offset  = 0.15;
+      double top_offset = 0.0;
+      double bottom_offset  = 0.07;
+
+      LBMReal vLB = 0.016103;
+      LBMReal Re;
+      LBMReal rhoLB = 0.0;
+      LBMReal nueLB = 0.0000249;//(vLB*lLB)/Re;
+      Re = (vLB*(0.303/dx))/nueLB;
+      const int baseLevel = 0;
+      const int refineLevel = 2;
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      double ft=1000.0;
+      //////////////////////////////////////////////////////////////////////////
+      GbObject3DPtr refineCube1(new  GbCuboid3D(-0.2222890*ft,-0.52993*ft, -0.141754*ft, /*0.578916113*ft*/275.0,0.6089970*ft,0.0446053*ft));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube1.get(), pathname+"/geo/refineCube1", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube2(new  GbCuboid3D(-0.16*ft-10.0,-0.05*ft, -0.141754*ft, 0.2*ft+10.0,0.05*ft,0.0446053*ft));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube2.get(), pathname+"/geo/refineCube2", WbWriterVtkXmlASCII::getInstance());
+      //////////////////////////////////////////////////////////////////////////
+
+      Grid3DPtr grid(new Grid3D());
+
+      UbSchedulerPtr rSch(new UbScheduler(1000, 1000));
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         rp->reconnect(grid);
+         grid->setTimeStep(UbSystem::stringTo<int>(opt));
+
+         if(myid ==0) UBLOG(logINFO,"TimeStep = " <<grid->getTimeStep());
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " <<lLB );
+            UBLOG(logINFO,"v = " <<vLB );
+            UBLOG(logINFO,"rho = " <<rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+
+         ////////////////////////////////////////////////////////////////////////
+         //Grid
+         //////////////////////////////////////////////////////////////////////////
+         grid->setDeltaX(dx);
+         grid->setBlockNX(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2);
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Geometrie
+         ////////////////////////////////////////////////////////////////////////////
+         UBLOG(logINFO,"Read geometry: start");
+         GbTriFaceMesh3DPtr geo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+         UBLOG(logINFO,"Read geometry: end");
+         if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo", WbWriterVtkXmlASCII::getInstance());
+
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Randgeometrien erstellen
+         ////////////////////////////////////////////////////////////////////////////
+         double shiftForMG=grid->getDeltaX(refineLevel)*nodePerBlockX1 / 3.0*2.0;
+
+         GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D(geo->getX1Minimum()+9100.0,  geo->getX2Minimum()-200.0, geo->getX3Minimum()-200.0,
+                                                               geo->getX1Minimum()+10000.0, geo->getX2Maximum()+200.0, geo->getX3Maximum()+200.0));
+         GbCuboid3DPtr outflow  = GbCuboid3DPtr( new GbCuboid3D(geo->getX1Maximum()-10000.0,  geo->getX2Minimum()-200.0, geo->getX3Minimum()-200.0,
+                                                                geo->getX1Maximum()-9100.0, geo->getX2Maximum()+200.0, geo->getX3Maximum()+200.0));
+
+         if(myid == 0)
+         {
+            GbSystem3D::writeGeoObject(inflow.get(),pathname+"/geo/inflow", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(outflow.get(),pathname+"/geo/outflow", WbWriterVtkXmlASCII::getInstance());
+         }
+
+         //GbObject3DPtr gridCube(new GbCuboid3D(geo->getX1Minimum()-(double)nodePerBlockX1*dx, geo->getX2Minimum()-(double)nodePerBlockX1*dx, geo->getX3Minimum()-(double)nodePerBlockX1*dx,
+         //   geo->getX1Maximum()+(double)nodePerBlockX1*dx, 
+         //   geo->getX2Maximum()+(double)nodePerBlockX1*dx, 
+         //   geo->getX3Maximum()+(double)nodePerBlockX1*dx));
+
+
+         shiftForMG=0.0;
+         GbObject3DPtr gridCube(new GbCuboid3D(geo->getX1Minimum()+10000.0, geo->getX2Minimum()-shiftForMG, -0.141754*ft/2.0/*geo->getX3Minimum()-shiftForMG*/,
+            geo->getX1Maximum()-10000.0, 
+            geo->getX2Maximum()+shiftForMG, 
+            geo->getX3Maximum()+shiftForMG));
+
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(),pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            //RefineCrossAndInsideGbObjectBlockVisitor refVisitor1(refineCube1, baseLevel, refineLevel-3);
+            //grid->accept(refVisitor1);
+
+            RefineCrossAndInsideGbObjectBlockVisitor refVisitor2(refineCube1, refineLevel);
+            grid->accept(refVisitor2);
+
+            RatioBlockVisitor ratioVisitor(refineLevel);
+            grid->accept(ratioVisitor);
+
+            RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            grid->accept(ratioSmoothVisitor);
+
+            OverlapBlockVisitor overlapVisitor(refineLevel);
+            grid->accept(overlapVisitor);
+
+            std::vector<int> dirs;
+            D3Q27System::getLBMDirections(dirs);
+            SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            grid->accept(interDirsVisitor);
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //INTERAKTOREN SETZEN (=Randbedingungen)
+         //////////////////////////////////////////////////////////////////////////
+         //oben/unten = Haftrand
+         int bbOption = 2; //0=simple Bounce Back, 1=quadr. BB, 2=quadr. BB 2nd choice 
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27TriFaceMeshInteractorPtr geoInt = D3Q27TriFaceMeshInteractorPtr( new D3Q27TriFaceMeshInteractor(geo, grid, D3Q27BoundaryConditionAdapterPtr(new D3Q27NoSlipBCAdapter(bbOption)),Interactor3D::INVERSESOLID));
+         geoInt->setUseHalfSpaceCheck(true);
+         geoInt->setRegardPointInObjectTest(true);
+
+         //links: geschwindigkeits-einfluss
+         //Velocity-BC
+         //////////////////////////////////////////////////////////////////////////
+         mu::Parser fct;
+         fct.DefineConst("vx1"  , vLB           );
+         //fct = MathUtil::getDuctParaboloidX(plate1->getX2Centroid(), plate1->getX2Maximum() - plate1->getX2Minimum(), plate1->getX3Centroid(), plate1->getX3Minimum() - plate1->getX3Maximum(), vLB*9.0/4.0);
+         fct.SetExpr("vx1");
+         //////////////////////////////////////////////////////////////////////////
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(2);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, velBCAdapter, Interactor3D::SOLID));
+         //D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, bcObst, Interactor3D::SOLID));
+
+         //rechts: druckrand
+         //Density-BC
+         //fuer Kompressibles Modell  rho = 1.0
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(outflow, grid, D3Q27BoundaryConditionAdapterPtr(new D3Q27DensityBCAdapter(rhoLB)),Interactor3D::SOLID));
+         //D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(outflow, grid, bcObst,Interactor3D::SOLID));
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+         sd.addInteractor(geoInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+         sd.deleteSolidBlocks();     
+
+         grid->accept( metisVisitor );
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         UBLOG(logINFO,grid->getBlock(10,12,0,1)->toString());
+         vector<Block3DPtr> blocks;
+         //grid->getNeighborBlocksForDirection(D3Q27System::W,10,12,0,1,3,blocks);
+         grid->getNeighborBlocksForDirection(D3Q27System::E,4,6,0,0,2,blocks);
+         BOOST_FOREACH(Block3DPtr b, blocks)
+            UBLOG(logINFO, b->toString());
+
+
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod_temp = nob * (nodePerBlockX1+gl) * (nodePerBlockX2+gl) * (nodePerBlockX3+gl);
+         unsigned long nod = nob * (nodePerBlockX1) * (nodePerBlockX2) * (nodePerBlockX3);
+         double needMemAll  = double(nod_temp*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }  
+
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2, true));
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2,0));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //canal
+         grid->addAndInitInteractor(geoInt);
+
+         //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+
+         //////////////////////////////////////////////////////////////////////////
+         //connectoren setzen:
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         //////////////////////////////////////////////////////////////////////////
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+         //////////////////////////////////////////////////////////////////////////
+         //Stroemungsfeld initialisieren
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB); //1.0
+         //initVisitor.setVx1(0.0); 
+         grid->accept(initVisitor);
+
+         if(myid == 0)
+         {
+            //Abstände "q" als Linien rausschreiben
+            std::vector< UbTupleFloat3 > nodes;
+            std::vector< UbTupleInt2 >   lines;
+            geoInt->addQsLineSet(nodes, lines);
+            WbWriterVtkXmlBinary::getInstance()->writeLines(pathname+"/grid/qs",nodes,lines);
+         }
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");
+
+      }
+      //////////////////////////////////////////////////////////////////////////
+      //Set Postprozessors
+      //////////////////////////////////////////////////////////////////////////
+      {
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+         grid->doPostProcess(0);
+      }
+
+
+      UbSchedulerPtr nupsSch(new UbScheduler(1, 5, 10));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 100;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      //visSch->addSchedule(20, 1010, 1100);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid,visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv,  comm);
+      //////////////////////////////////////////////////////////////////////////
+      //PathLine
+      //UbSchedulerPtr plSch(new UbScheduler(10, 1500));
+      //D3Q27PathLinePostprocessor pathLine(grid, pathname + "/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm, -0.3285474538, 0.09692341,-0.0376166666, nueLB, iProcessor);
+      //////////////////////////////////////////////////////////////////////////
+      //Simulation
+      //////////////////////////////////////////////////////////////////////////
+      double endTime = 1000;
+      UbSchedulerPtr visSch1(new UbScheduler(1));
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
diff --git a/source/Applications/micropart/micropartTestQs2.hpp b/source/Applications/micropart/micropartTestQs2.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..bcaa75a458fb0cdf3126d8bce7a72d853dd0bc21
--- /dev/null
+++ b/source/Applications/micropart/micropartTestQs2.hpp
@@ -0,0 +1,592 @@
+#include <iostream>
+#include <string>
+#include <map>
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include "numerics/geometry3d/GbSphere3D.h"
+#include "BlocksPostprocessor.h"
+#include "Grid3D.h"
+#include "Patch3D.h"
+#include "Patch3DSystem.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "LBMKernelETD3Q27BGK.h"
+#include "CalculationManager.h" 
+#include "D3Q27SetConnectorsBlockVisitor.h" 
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "Communicator.h"
+#include "MPICommunicator.h"
+#include "SimpleGeometricPartitioner.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27TriFaceMeshInteractor.h"
+#include "ConfigFileReader.h"
+#include "StringUtil.hpp"
+#include "D3Q27PressureDifferencePostprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "LBMUnitConverter.h"
+#include "NUPSCounterPostprocessor.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "GenBlocksGridVisitor.h"
+#include "D3Q27PathLinePostprocessorMcpart.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+   //
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h"
+#include "numerics/geometry3d/GbTriFaceMesh3D.h"
+#include "D3Q27System.h"
+#include <basics/transmitter/TbTransmitterMpiPool.h>
+#include "MathUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "SolidBlocksHelper.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "RestartPostprocessor.h"
+#include "D3Q27IncompressibleOffsetInterpolationProcessor.h"
+#include "LBMKernelETD3Q27CCLB.h"
+#include "AverageValuesPostprocessor.h"
+#include <vfluids.h>
+using namespace std;
+
+void micropartTestQs2(const char *cstr)
+{
+   try
+   {
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+      int numprocs = comm->getNumberOfProcesses();
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      double availMem = 0;
+      string geoFile;
+      int numOfThreads = 1;
+
+      if(machine == "EHSAN1491") 
+      {
+         pathname = "/work/ehsan/micropart";
+         availMem = 3.0e9;
+		  int numOfThreads = 1;
+         //geoFile = "c:/Data/micropart/DK19_7_02_Martin.stl";
+         //geoFile = "c:/Data/micropart/ktoolcav.stl";
+         //geoFile = "c:/Data/micropart/boxN.stl";
+        geoFile = "C:/Users/ehsan/Desktop/meshparticles/E0019B_mit_Radien.stl";
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/mcpart/out";
+         availMem = 12.0e9/8.0;
+		  geoFile = "/work/ehsan/data/E0019B_mit_Radien.stl";
+         //geoFile = "/home/koskuche/data/micropart/DK19_7_02_Martin.stl";
+
+         numOfThreads = 1;
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      UbLog::reportingLevel() = logINFO;
+      //UbLog::reportingLevel() = logDEBUG1;
+
+      int nodePerBlockX1 =16; //Anzahl an Knoten pro Block
+      int nodePerBlockX2 =16;//(int)16;
+      int nodePerBlockX3 =8;//8; //(int)16;
+
+      double bH = nodePerBlockX1;    //gewuenschte Rand- und Blockbreite
+
+      //Simulation Parameters
+      const int baseLevel = 0;
+      const int refineLevel =4;
+      //length [m]
+      double lSI = 219;//223.2;
+      //length [LB]
+      double lLB = 30;
+
+      double dx =lSI/lLB;
+
+      double left_offset = 10700;//*0.5;
+      double right_offset  = 107000;//0.5;//2*0.5
+      double front_offset = 750;//0.15;
+      double back_offset  = 750;//0.15;
+      double top_offset = 250;//0.0;
+      double bottom_offset  =750;// 70;//0.07;
+	  
+	   LBMReal vLB =0.00016103/5.0*sqrt(2.0);//0.00016103;
+       LBMReal Re;
+       LBMReal rhoLB = 0.0;
+       LBMReal nueLB = 0.0000249;//(vLB*lLB)/Re;
+       Re = (vLB*(500/dx))/nueLB;
+       double dp_Ph=200.0*100000;//
+	   double dp_lb=dp_Ph*0.001*(nueLB*dx)*(nueLB*dx);//nue_ph=10e-6 and dx is in micrometer
+      // LBMReal nueLB = 0.000016103;
+      // LBMReal Re=15000;
+      // LBMReal rhoLB = 0.0;
+      // LBMReal vLB =nueLB*Re/(500.0/dx);
+     // // Re = (vLB*(0.303/dx))/nueLB;
+	   // //Re = (vLB*lLB)/nueLB;
+	  
+      // LBMReal rhoWord = 1e-15;//kg/micrometre^3;//1000.0;
+	  // LBMReal nueRE = 1e6;//micromter^2/s;//0.000001;
+	  // LBMReal  vWorld=300*1e6;//micrometer/s;//nueRE*Re/ (lSI*4.0/9.0);
+	  LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      //conv->init(lSI*1e-6,30000,rhoWord,vWorld,lLB,1.0/*rhoLB*/,vLB);
+      
+	 
+ //////////////////////////////////////////////////////////////////////////
+      GbObject3DPtr refineCube1(new  GbCuboid3D(-500.0+5.0/*-354.0*/,-957.0/*-280.0*/,-684.0/* -72.0*/, 4100/*370.0*/,957.0/*354.0*/,70.0));//-530.0,-280.0, -72.0, 530.0,354.0,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube1.get(), pathname+"/geo/refineCube1", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube2(new  GbCuboid3D(-230.0,-90.0, -684.0/*-72.0*/, 600,100.0,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube2.get(), pathname+"/geo/refineCube2", WbWriterVtkXmlASCII::getInstance());
+	  
+	   GbObject3DPtr refineCube3(new  GbCuboid3D(-350.0,-957.0/*-120.0*/,-684.0/*-684.0*//* -72.0*/, 1700,957.0/*120.0*/,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube3.get(), pathname+"/geo/refineCube3", WbWriterVtkXmlASCII::getInstance());
+	  
+	   GbObject3DPtr refineCube4(new  GbCuboid3D(-170.0,-60.0, -684.0/*-72.0*/, 200,60.0,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube4.get(), pathname+"/geo/refineCube4", WbWriterVtkXmlASCII::getInstance());
+	  
+	   GbObject3DPtr refineCubeInlet(new  GbCuboid3D(-10600.0,-600.0, -600.0/*-72.0*/, -9000,600.0,60.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCubeInlet.get(), pathname+"/geo/refineCubeInlet", WbWriterVtkXmlASCII::getInstance());
+	  
+	  GbObject3DPtr refineCubeOutlet(new  GbCuboid3D(9000,-600.0, -600.0/*-72.0*/,10550.0 ,600.0,60.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCubeOutlet.get(), pathname+"/geo/refineCubeOutlet", WbWriterVtkXmlASCII::getInstance());
+      //////////////////////////////////////////////////////////////////////////
+      D3Q27TriFaceMeshInteractorPtr geoInt;
+	  /////////////////
+      //Grid3DPtr grid(new Grid3D());
+        Grid3DPtr grid(new Grid3D(comm));
+
+      UbSchedulerPtr rSch(new UbScheduler());
+      rSch->addSchedule(100, 200, 20000);
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         rp->reconnect(grid);
+
+         // SetForcingBlockVisitor forcingVisitor(0.0, 0.0, 0.0);
+         // grid->accept(forcingVisitor);
+
+         //D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+		  if(myid==0) UBLOG(logINFO,"Restart finish: " << opt);
+	 
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " <<lLB );
+            UBLOG(logINFO,"v = " <<vLB );
+            UBLOG(logINFO,"rho = " <<rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+			UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Re = " << Re );
+			 UBLOG(logINFO,"dp_lb = " << dp_lb );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+
+         ////////////////////////////////////////////////////////////////////////
+         //Grid
+         //////////////////////////////////////////////////////////////////////////
+         grid->setDeltaX(dx);
+         grid->setBlockNX(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3);
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Geometrie
+         ////////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr geo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+
+         if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo", WbWriterVtkXmlASCII::getInstance());
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Randgeometrien erstellen
+         ////////////////////////////////////////////////////////////////////////////
+         double shiftForMG=grid->getDeltaX(refineLevel)*nodePerBlockX1 / 3.0*2.0;
+          GbCuboid3DPtr plate1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -1.515e-1, -6.831e-2, 7.5, 1.515e-1, 0.0 ));
+
+           GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+           GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+          // GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -1.0e-1, 7.5, 2.515e-1, -6.831e-2 ));
+          // GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -0.0000001, 7.5, 2.515e-1, 1.0e-1 ));
+          // GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -7.5, 1.515e-1, -6.831e-2, 7.5, 2.515e-1, 0.0  ));
+          // GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, 0.0, 7.5, -1.515e-1, -1.0e-1 ));
+
+          // GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -8.0, -1.0, -1.0, -7.5, 1.0, 1.0 ));
+          // GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 7.5, -1.0, -1.0, 8.0, 1.0, 1.0 ));
+		  
+		   // GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+          // GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+          // GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, back_offset, -bottom_offset-bH*dx, right_offset+bH*dx, back_offset+bH*dx, top_offset+bH*dx ));
+          // GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, -bottom_offset-bH*dx, right_offset+bH*dx, -front_offset, top_offset+bH*dx ));
+          // GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, top_offset, right_offset+bH*dx, back_offset+bH*dx, top_offset+bH*dx+2.0*dx ));
+          // GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, -bottom_offset-bH*dx, right_offset+bH*dx, back_offset+bH*dx, -bottom_offset ));
+
+          //GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-5*bH*dx, -front_offset-5*bH*dx, -bottom_offset-5*bH*dx, -left_offset, back_offset+5*bH*dx, top_offset+5*bH*dx ));
+          //GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( right_offset, -front_offset-5*bH*dx, -bottom_offset-5*bH*dx, right_offset+5.0*bH*dx, back_offset+5*bH*dx, top_offset+5*bH*dx ));
+		  GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -11000.0,-600.0, -600.0, -9000.0, 600.0, -500 ));
+		  GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 9000,-600.0, -600.0, 11000.0, 600.0, -500));
+
+
+		   GbObject3DPtr gridCube(new GbCuboid3D(-10700.0/*inflow->getX1Maximum()-4.0*dx/*.5*shiftForMG*/,-550.0/*-270*/ , -550.0/*-70*/,
+                                                10700.0/*outflow->getX1Minimum()+4.0*dx/*.5*shiftForMG*/, 
+                                                550.0/*270*/, 
+                                                23.0/*10.0*/));
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+		  
+         if(myid == 0)
+         {
+            GbSystem3D::writeGeoObject(gridCube.get(),pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+            //GbSystem3D::writeGeoObject(plate2.get(),pathname+"/geo/plate2", WbWriterVtkXmlASCII::getInstance());
+            //GbSystem3D::writeGeoObject(plate3.get(),pathname+"/geo/plate3", WbWriterVtkXmlASCII::getInstance());
+
+            // GbSystem3D::writeGeoObject(plate1_1.get(),pathname+"/geo/plate1_1", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_2.get(),pathname+"/geo/plate1_2", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_3.get(),pathname+"/geo/plate1_3", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_4.get(),pathname+"/geo/plate1_4", WbWriterVtkXmlASCII::getInstance());
+
+            GbSystem3D::writeGeoObject(inflow.get(),pathname+"/geo/inflow", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(outflow.get(),pathname+"/geo/outflow", WbWriterVtkXmlASCII::getInstance());
+         }
+   
+
+         if (refineLevel > 0)
+         {
+		  if(myid == 0) UBLOG(logINFO,"Refinement - start");   
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineCube1, 1);
+            refineHelper.addGbObject(refineCube3, 2);
+			 refineHelper.addGbObject(refineCube2, 3);
+			 refineHelper.addGbObject(refineCube4, 4);
+			 
+			 refineHelper.addGbObject(refineCubeInlet, 1);
+			 refineHelper.addGbObject(refineCubeOutlet, 1);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");   
+		 
+		 
+           // RefineCrossAndInsideGbObjectBlockVisitor refVisitor1(refineCube1, refineLevel-4);
+            // grid->accept(refVisitor1);
+
+			// RefineCrossAndInsideGbObjectBlockVisitor refVisitor3(refineCube3, refineLevel-3);
+            // grid->accept(refVisitor3);
+
+            // RefineCrossAndInsideGbObjectBlockVisitor refVisitor2(refineCube2, refineLevel-2);
+            // grid->accept(refVisitor2);
+			
+			 // RefineCrossAndInsideGbObjectBlockVisitor refVisitor4(refineCube4, refineLevel-1);
+            // grid->accept(refVisitor4);
+
+            // RatioBlockVisitor ratioVisitor(refineLevel);
+            // grid->accept(ratioVisitor);
+
+            // RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            // grid->accept(ratioSmoothVisitor);
+
+            // OverlapBlockVisitor overlapVisitor(refineLevel);
+            // grid->accept(overlapVisitor);
+
+            // std::vector<int> dirs;
+            // D3Q27System::getLBMDirections(dirs);
+            // SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            // grid->accept(interDirsVisitor);
+            // if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //INTERAKTOREN SETZEN (=Randbedingungen)
+         //////////////////////////////////////////////////////////////////////////
+         //oben/unten = Haftrand
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         geoInt = D3Q27TriFaceMeshInteractorPtr( new D3Q27TriFaceMeshInteractor(geo, grid, D3Q27BoundaryConditionAdapterPtr(new D3Q27NoSlipBCAdapter(bbOption)),Interactor3D::INVERSESOLID, Interactor3D::SIMPLE));
+	     geoInt->setUseHalfSpaceCheck(true);
+         geoInt->setRegardPointInObjectTest(true);
+         if(myid == 0) UBLOG(logINFO,"stl - end"); 
+         //D3Q27InteractorPtr plate1Int(new D3Q27Interactor(plate1, grid, bcObst,Interactor3D::INVERSESOLID));
+         // D3Q27InteractorPtr plate2Int(new D3Q27Interactor(plate2, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate3Int(new D3Q27Interactor(plate3, grid, bcObst,Interactor3D::SOLID));
+
+         // D3Q27InteractorPtr plate1_1Int(new D3Q27Interactor(plate1_1, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_2Int(new D3Q27Interactor(plate1_2, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_3Int(new D3Q27Interactor(plate1_3, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_4Int(new D3Q27Interactor(plate1_4, grid, bcObst,Interactor3D::SOLID));
+
+         //links: geschwindigkeits-einfluss
+         //Velocity-BC
+         //////////////////////////////////////////////////////////////////////////
+         mu::Parser fct;
+         fct.DefineConst("vx1"  , vLB*9.0/4.0 );
+         //fct = MathUtil::getDuctParaboloidX(0, 250*2.0, -51.08/2, 51.08, vLB*9.0/4.0);
+         fct.SetExpr("vx1");
+         //////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////////
+            // D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter (false, false ,true ,fct, 0, D3Q27BCFunction::INFCONST));
+            // velBCAdapter->setSecondaryBcOption(2);
+            // D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+		 D3Q27BoundaryConditionAdapterPtr denBCAdapterInlet(new D3Q27DensityBCAdapter(3.0*(dp_lb-rhoLB)));
+        denBCAdapterInlet->setSecondaryBcOption(1);
+        D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, denBCAdapterInlet,Interactor3D::SOLID));
+		 
+         //rechts: druckrand
+         //Density-BC
+         //fuer Kompressibles Modell  rho = 1.0
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(1);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(outflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+         
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         if(myid == 0) ppblocks->update(0);
+         
+         SolidBlocksHelper sd(grid, comm);
+         sd.addInteractor(geoInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+         // sd.addInteractor(plate1_1Int);
+         // sd.addInteractor(plate1_2Int);
+         // sd.addInteractor(plate1_3Int);
+         // sd.addInteractor(plate1_4Int);
+         // sd.addInteractor(plate2Int);
+         // sd.addInteractor(plate3Int);
+		   if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         sd.deleteSolidBlocks();     
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         grid->accept( metisVisitor );
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__);
+
+         sd.setTransBlocks();
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__);
+         //BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         if(myid == 0) ppblocks->update(1);
+         if(myid == 0) ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod_temp = nob * (nodePerBlockX1+gl) * (nodePerBlockX2+gl) * (nodePerBlockX3+gl);
+         unsigned long nod = nob * (nodePerBlockX1) * (nodePerBlockX2) * (nodePerBlockX3);
+         double needMemAll  = double(nod_temp*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }  
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+
+		  int option = 0;
+		 LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3,option));
+
+		 
+		 
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+		 
+		  if(myid == 0) UBLOG(logINFO,"intractor - start"); 
+          //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+         //canal
+         grid->addAndInitInteractor(geoInt);
+         // grid->addAndInitInteractor(plate1_1Int);
+         // grid->addAndInitInteractor(plate1_2Int);
+         // grid->addAndInitInteractor(plate1_3Int);
+         // grid->addAndInitInteractor(plate1_4Int);
+         // grid->addAndInitInteractor(plate2Int);
+         // grid->addAndInitInteractor(plate3Int);
+
+       
+
+         //////////////////////////////////////////////////////////////////////////
+         //connectoren setzen:
+
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         //////////////////////////////////////////////////////////////////////////	 
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+			 
+         //////////////////////////////////////////////////////////////////////////     
+	   //Stroemungsfeld initialisieren
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB); //1.0
+         initVisitor.setVx1(0); 
+         grid->accept(initVisitor);
+
+         if(myid == 0)
+         {
+            //Abstände "q" als Linien rausschreiben
+            std::vector< UbTupleFloat3 > nodes;
+            std::vector< UbTupleInt2 >   lines;
+            geoInt->addQsLineSet(nodes, lines);
+            WbWriterVtkXmlBinary::getInstance()->writeLines(pathname+"/grid/qs",nodes,lines);
+         }
+
+          if(myid == 0) UBLOG(logINFO,"Preprozess - end");
+		 
+		 	  ////////////////////////
+           //Set Postprozessors
+           //////////////////////////////////////////////////////////////////////////
+           {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+            grid->doPostProcess(0);
+           }
+	    
+
+      }
+
+      //////////////////////////////////////////////////////////////////////////
+	   // UbSchedulerPtr visSchAv(new UbScheduler());
+		UbSchedulerPtr visSchAv(new UbScheduler(100,100));
+      // visSchAv->addSchedule(100,10,1000);
+      // UbSchedulerPtr resSchAv(new UbScheduler());
+	   UbSchedulerPtr resSchAv(new UbScheduler(100,100));
+      // resSchAv->addSchedule(20,20,1000);
+      AverageValuesPostprocessor       Avpp(grid,  pathname + "/Turbulence/stepAV", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm);
+	  
+	   D3Q27ShearStressPostprocessor  shear(grid,  pathname + "/shear/step", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm,iProcessor); 
+	   //D3Q27ShearStressPostprocessor  shear(grid,  pathname + "/shear/step", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm);
+	   shear.addInteractor(geoInt);
+	   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	  
+
+      UbSchedulerPtr nupsSch(new UbScheduler(1, 5, 10));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 100.0;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid,stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv,  comm);
+      //////////////////////////////////////////////////////////////////////////
+      //PathLine
+       UbSchedulerPtr plSch(new UbScheduler(5000, 5000));
+      const int numberofparticle=20;
+	
+	  std::vector<UbTupleDouble3 > potisions;
+	  double randomx[numberofparticle];
+	  double randomy[numberofparticle];
+	  double randomz[numberofparticle];
+	  double lowestx,highestx,lowesty,highesty,lowestz,highestz;
+	  if(myid==0)
+	  {
+		  for(int i = 0; i < numberofparticle; i++)
+		  {
+			  double random; 
+	        lowestx =-10300.0;  lowesty =-230;          lowestz =-250;
+	        highestx=-9792.0;  highesty=-330;          highestz=-250; 
+		  
+	      double rangex=(highestx-lowestx),rangey=(highesty-lowesty),rangez=(highestz-lowestz);	
+           randomx[i] = lowestx+(rangex*rand()/(RAND_MAX + 1.0));
+		   randomy[i] = lowesty+(rangey*rand()/(RAND_MAX + 1.0));
+	       randomz[i] = lowestz+(rangez*rand()/(RAND_MAX + 1.0));
+		  //val<1>(potisions[i])= 0.506983973456;
+		  //val<2>(potisions[i]) = lowesty+(rangey*rand()/(RAND_MAX + 1.0));
+		   //val<3>(potisions[i]) = lowestz+(rangez*rand()/(RAND_MAX + 1.0));
+		  }
+		  for (int i=0;i<comm->getNumberOfProcesses();i++)
+		  {
+			  if (i!=0)
+			  {
+			      MPI_Send(randomx,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+				  MPI_Send(randomy,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+				  MPI_Send(randomz,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+			  }
+		  }
+	  }
+	  if (myid!=0)
+	  {
+		  MPI_Status status; 
+		  MPI_Recv(randomx,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+		  MPI_Recv(randomy,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+		  MPI_Recv(randomz,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+	  }
+	  for(int i = 0; i < numberofparticle; i++)
+	  {	
+		  potisions.push_back( makeUbTuple(randomx[i],randomy[i],randomz[i]) );
+		  //val<1>(potisions[i])= 0.506983973456;
+		  //val<2>(potisions[i]) = randomy[i];
+		  //val<3>(potisions[i]) = randomz[i];
+	  }
+	 //  UBLOG(logINFO,"Rank="<<myid<<" positions  = " <<val<1>(potisions)<< " "<<val<2>(potisions)<<" "<< val<3>(potisions));
+	 // D3Q27InterpolationProcessorPtr iProcessor2;
+     // D3Q27PathLinePostprocessorMcpart pathLine(grid, pathname + "/pathLine/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm,potisions, nueLB, iProcessor);
+      //////////////////////////////////////////////////////////////////////////
+      //Simulation
+      //////////////////////////////////////////////////////////////////////////
+
+	  double endTime = 1000.0;
+      UbSchedulerPtr visSch(stepSch);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
diff --git a/source/Applications/micropart/micropartTestQs3.hpp b/source/Applications/micropart/micropartTestQs3.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9bf5aaa9ea3bdb5d81dd4e1a2f45540ff572bff2
--- /dev/null
+++ b/source/Applications/micropart/micropartTestQs3.hpp
@@ -0,0 +1,560 @@
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <vfluids.h>
+using namespace std;
+
+void micropartTestQs3(const char *cstr)
+{
+   try
+   {
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+      int numprocs = comm->getNumberOfProcesses();
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      double availMem = 0;
+      string geoFile;
+      int numOfThreads = 1;
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/micropart";
+         availMem = 1.0e9;
+         int numOfThreads = 1;
+         geoFile = "d:/Data/micropart/E0019B_mit_Radien.stl";
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         // pathname = "/work/koskuche/scratch/mcpart/out";
+         pathname = "/work/ehsan/orifice";
+         availMem = 12.0e9;
+         geoFile = "d:/Data/micropart/E0019B_mit_Radien.stl";
+         //geoFile = "/home/koskuche/data/micropart/DK19_7_02_Martin.stl";
+
+         numOfThreads = 1;
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      UbLog::reportingLevel() = logINFO;
+      //UbLog::reportingLevel() = logDEBUG1;
+
+      int nodePerBlockX1 =16; //Anzahl an Knoten pro Block
+      int nodePerBlockX2 =16;//(int)16;
+      int nodePerBlockX3 =16;//8; //(int)16;
+
+      double bH = nodePerBlockX1;    //gewuenschte Rand- und Blockbreite
+
+
+      //Simulation Parameters
+      const int baseLevel = 0;
+      const int refineLevel = 5;
+      //length [m]
+      double lSI =217.35;// 216.75;//223.2;
+      //length [LB]
+      double lLB = 30;
+
+      double dx =10;//lSI/lLB;
+
+      double left_offset = 10700;//*0.5;
+      double right_offset  = 107000;//0.5;//2*0.5
+      double front_offset = 750;//0.15;
+      double back_offset  = 750;//0.15;
+      double top_offset = 250;//0.0;
+      double bottom_offset  =750;// 70;//0.07;
+
+      LBMReal vLB =0.00016103/5.0*sqrt(2.0);//0.00016103;
+      LBMReal Re;
+      LBMReal rhoLB = 0.0;
+      LBMReal nueLB = 0.0000249;//(vLB*lLB)/Re;
+      Re = (vLB*(500/dx))/nueLB;
+      double dp_Ph=200.0*100000;//
+      //double dp_lb=dp_Ph*0.001*(nueLB)*(nueLB);//nue_ph=10e-6 and dx is in micrometer
+      LBMReal nue_Ph = 1e-6;//
+      double dt=/*(nue_Ph/nueLB)*/(nueLB/nue_Ph)*(dx*1e-6)*(dx*1e-6);//dt=nu_lb/nu_ph*dx*dx;//nue_ph=10e-6;dx is in micrometer;
+      double dp_lb=dp_Ph/1000*(dt*dt)/((dx*1e-6)*(dx*1e-6));//dp_lb=dp_ph/rho_ph*dt*dt/dx/dx
+      // LBMReal nueLB = 0.000016103;
+      // LBMReal Re=15000;
+      // LBMReal rhoLB = 0.0;
+      // LBMReal vLB =nueLB*Re/(500.0/dx);
+      // // Re = (vLB*(0.303/dx))/nueLB;
+      // //Re = (vLB*lLB)/nueLB;
+
+      // LBMReal rhoWord = 1e-15;//kg/micrometre^3;//1000.0;
+      // LBMReal nueRE = 1e6;//micromter^2/s;//0.000001;
+      // LBMReal  vWorld=300*1e6;//micrometer/s;//nueRE*Re/ (lSI*4.0/9.0);
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      //conv->init(lSI*1e-6,30000,rhoWord,vWorld,lLB,1.0/*rhoLB*/,vLB); 
+
+      //////////////////////////////////////////////////////////////////////////
+      GbObject3DPtr refineCube1(new  GbCuboid3D(-500.0+5.0/*-354.0*/,-957.0/*-280.0*/,-684.0/* -72.0*/, 4100/*370.0*/,957.0/*354.0*/,70.0));//-530.0,-280.0, -72.0, 530.0,354.0,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube1.get(), pathname+"/geo/refineCube1", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube2(new  GbCuboid3D(-280.0,-957.0/*-120.0*/,-684.0/*-684.0*//* -72.0*/, 500,957.0/*120.0*/,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube2.get(), pathname+"/geo/refineCube2", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube3(new  GbCuboid3D(-350.0,-957.0/*-120.0*/,-684.0/*-684.0*//* -72.0*/, 1700,957.0/*120.0*/,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube3.get(), pathname+"/geo/refineCube3", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube4(new  GbCuboid3D(-230.0,-150.0/*-120.0*/,-684.0, 225,150,957.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube4.get(), pathname+"/geo/refineCube4", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube5up(new  GbCuboid3D(-147.0,-50,-5.0, 0.0,50.0,957.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube5up.get(), pathname+"/geo/refineCube5up", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube5down(new  GbCuboid3D(-147.0,-50,-46.0, 0,50,-957.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube5down.get(), pathname+"/geo/refineCube5down", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCubeInlet(new  GbCuboid3D(-10600.0,-600.0, -600.0/*-72.0*/, -8000,600.0,60.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCubeInlet.get(), pathname+"/geo/refineCubeInlet", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCubeOutlet(new  GbCuboid3D(8000,-600.0, -600.0/*-72.0*/,10550.0 ,600.0,60.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCubeOutlet.get(), pathname+"/geo/refineCubeOutlet", WbWriterVtkXmlASCII::getInstance());
+      //////////////////////////////////////////////////////////////////////////
+      D3Q27TriFaceMeshInteractorPtr geoInt;
+      /////////////////
+      //Grid3DPtr grid(new Grid3D());
+      Grid3DPtr grid(new Grid3D(comm));
+
+      UbSchedulerPtr rSch(new UbScheduler());
+      rSch->addSchedule(50000, 50000, 1000000000);
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         rp->reconnect(grid);
+
+         // SetForcingBlockVisitor forcingVisitor(0.0, 0.0, 0.0);
+         // grid->accept(forcingVisitor);
+
+         //D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         if(myid==0) UBLOG(logINFO,"Restart finish: " << opt);
+
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " <<lLB );
+            UBLOG(logINFO,"v = " <<vLB );
+            UBLOG(logINFO,"rho = " <<rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dt = " << dt );
+            UBLOG(logINFO,"dp_lb = " << dp_lb );
+            UBLOG(logINFO,"refineLevel = " << refineLevel );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+
+         ////////////////////////////////////////////////////////////////////////
+         //Grid
+         //////////////////////////////////////////////////////////////////////////
+         grid->setDeltaX(dx);
+         grid->setBlockNX(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3);
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Geometrie
+         ////////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr geo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+
+         if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo", WbWriterVtkXmlASCII::getInstance());
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Randgeometrien erstellen
+         ////////////////////////////////////////////////////////////////////////////
+         double shiftForMG=grid->getDeltaX(refineLevel)*nodePerBlockX1 / 3.0*2.0;
+         GbCuboid3DPtr plate1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -1.515e-1, -6.831e-2, 7.5, 1.515e-1, 0.0 ));
+
+         GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+         GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+         // GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -1.0e-1, 7.5, 2.515e-1, -6.831e-2 ));
+         // GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -0.0000001, 7.5, 2.515e-1, 1.0e-1 ));
+         // GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -7.5, 1.515e-1, -6.831e-2, 7.5, 2.515e-1, 0.0  ));
+         // GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, 0.0, 7.5, -1.515e-1, -1.0e-1 ));
+
+         // GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -8.0, -1.0, -1.0, -7.5, 1.0, 1.0 ));
+         // GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 7.5, -1.0, -1.0, 8.0, 1.0, 1.0 ));
+
+         // GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+         // GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+         // GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, back_offset, -bottom_offset-bH*dx, right_offset+bH*dx, back_offset+bH*dx, top_offset+bH*dx ));
+         // GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, -bottom_offset-bH*dx, right_offset+bH*dx, -front_offset, top_offset+bH*dx ));
+         // GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, top_offset, right_offset+bH*dx, back_offset+bH*dx, top_offset+bH*dx+2.0*dx ));
+         // GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, -bottom_offset-bH*dx, right_offset+bH*dx, back_offset+bH*dx, -bottom_offset ));
+
+         //GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-5*bH*dx, -front_offset-5*bH*dx, -bottom_offset-5*bH*dx, -left_offset, back_offset+5*bH*dx, top_offset+5*bH*dx ));
+         //GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( right_offset, -front_offset-5*bH*dx, -bottom_offset-5*bH*dx, right_offset+5.0*bH*dx, back_offset+5*bH*dx, top_offset+5*bH*dx ));
+
+         //GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -11000.0,-600.0, -600.0, -9000.0, 600.0, -500 ));
+         //GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 9000,-600.0, -600.0, 11000.0, 600.0, -500));
+
+         GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -11000.0,-600.0, -600.0, -9000.0, 600.0, -480 ));
+         GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 9000,-600.0, -600.0, 11000.0, 600.0, -480));
+         GbObject3DPtr gridCube(new GbCuboid3D(-1.05e4, -500-140.0, -480.0-25.54, 1.05e4, 500.0, 0.0));
+
+
+
+         //GbObject3DPtr gridCube(new GbCuboid3D(-10700.0/*inflow->getX1Maximum()-4.0*dx/*.5*shiftForMG*/,-550.0/*-270*/ , -550.0/*-70*/,
+         //                                             10700.0/*outflow->getX1Minimum()+4.0*dx/*.5*shiftForMG*/, 
+         //                                             550.0/*270*/, 
+         //                                             23.0/*10.0*/));
+
+
+
+         //GbObject3DPtr gridCube(new GbCuboid3D(-1.05e4, -500.0, -500.0-0.54, 1.05e4, 500.0, 0.0-0.54));
+         //GbObject3DPtr gridCube(new GbCuboid3D(-1.05e4, -500.0, -500.0, 1.05e4, 500.0, 0.0));
+
+         //double difX1 = geo->getX1Centroid() - gridCube->getX1Centroid();
+         //double difX2 = geo->getX2Centroid() - gridCube->getX2Centroid();
+         //double difX3 = geo->getX3Centroid() - gridCube->getX3Centroid();
+
+         ////GbObject3DPtr gridCubeCor(new GbCuboid3D(-1.05e4+difX1, -500.0+difX2, -500.0-0.54, 1.05e4+difX1, 500.0+difX2, 0.0-0.54));
+         //GbObject3DPtr gridCubeCor(new GbCuboid3D(-1.05e4+difX1, -500.0+difX2, -500.0+difX3, 1.05e4+difX1, 500.0+difX2, 0.0+difX3));
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         if(myid == 0)
+         {
+            GbSystem3D::writeGeoObject(gridCube.get(),pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(gridCube.get(),pathname+"/geo/gridCubeCor", WbWriterVtkXmlASCII::getInstance());
+            //GbSystem3D::writeGeoObject(plate2.get(),pathname+"/geo/plate2", WbWriterVtkXmlASCII::getInstance());
+            //GbSystem3D::writeGeoObject(plate3.get(),pathname+"/geo/plate3", WbWriterVtkXmlASCII::getInstance());
+
+            // GbSystem3D::writeGeoObject(plate1_1.get(),pathname+"/geo/plate1_1", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_2.get(),pathname+"/geo/plate1_2", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_3.get(),pathname+"/geo/plate1_3", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_4.get(),pathname+"/geo/plate1_4", WbWriterVtkXmlASCII::getInstance());
+
+            GbSystem3D::writeGeoObject(inflow.get(),pathname+"/geo/inflow", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(outflow.get(),pathname+"/geo/outflow", WbWriterVtkXmlASCII::getInstance());
+         }
+
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");   
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineCube1, 1);
+            refineHelper.addGbObject(refineCube3, 2);
+            refineHelper.addGbObject(refineCube2, 3);
+            refineHelper.addGbObject(refineCube4, 4);
+
+            refineHelper.addGbObject(refineCube5up, 5);
+            refineHelper.addGbObject(refineCube5down, 5);
+
+            refineHelper.addGbObject(refineCubeInlet, 1);
+            refineHelper.addGbObject(refineCubeOutlet, 1);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");   
+
+
+            // RefineCrossAndInsideGbObjectBlockVisitor refVisitor1(refineCube1, refineLevel-4);
+            // grid->accept(refVisitor1);
+
+            // RefineCrossAndInsideGbObjectBlockVisitor refVisitor3(refineCube3, refineLevel-3);
+            // grid->accept(refVisitor3);
+
+            // RefineCrossAndInsideGbObjectBlockVisitor refVisitor2(refineCube2, refineLevel-2);
+            // grid->accept(refVisitor2);
+
+            // RefineCrossAndInsideGbObjectBlockVisitor refVisitor4(refineCube4, refineLevel-1);
+            // grid->accept(refVisitor4);
+
+            // RatioBlockVisitor ratioVisitor(refineLevel);
+            // grid->accept(ratioVisitor);
+
+            // RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            // grid->accept(ratioSmoothVisitor);
+
+            // OverlapBlockVisitor overlapVisitor(refineLevel);
+            // grid->accept(overlapVisitor);
+
+            // std::vector<int> dirs;
+            // D3Q27System::getLBMDirections(dirs);
+            // SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            // grid->accept(interDirsVisitor);
+            // if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //INTERAKTOREN SETZEN (=Randbedingungen)
+         //////////////////////////////////////////////////////////////////////////
+         //oben/unten = Haftrand
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         geoInt = D3Q27TriFaceMeshInteractorPtr( new D3Q27TriFaceMeshInteractor(geo, grid, D3Q27BoundaryConditionAdapterPtr(new D3Q27NoSlipBCAdapter(bbOption)),Interactor3D::INVERSESOLID, Interactor3D::SIMPLE));
+         geoInt->setUseHalfSpaceCheck(true);
+         geoInt->setRegardPointInObjectTest(true);
+         if(myid == 0) UBLOG(logINFO,"stl - end"); 
+         //D3Q27InteractorPtr plate1Int(new D3Q27Interactor(plate1, grid, bcObst,Interactor3D::INVERSESOLID));
+         // D3Q27InteractorPtr plate2Int(new D3Q27Interactor(plate2, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate3Int(new D3Q27Interactor(plate3, grid, bcObst,Interactor3D::SOLID));
+
+         // D3Q27InteractorPtr plate1_1Int(new D3Q27Interactor(plate1_1, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_2Int(new D3Q27Interactor(plate1_2, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_3Int(new D3Q27Interactor(plate1_3, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_4Int(new D3Q27Interactor(plate1_4, grid, bcObst,Interactor3D::SOLID));
+
+         //links: geschwindigkeits-einfluss
+         //Velocity-BC
+         //////////////////////////////////////////////////////////////////////////
+         mu::Parser fct;
+         fct.DefineConst("vx1"  , vLB*9.0/4.0 );
+         //fct = MathUtil::getDuctParaboloidX(0, 250*2.0, -51.08/2, 51.08, vLB*9.0/4.0);
+         fct.SetExpr("vx1");
+         //////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////////
+         // D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter (false, false ,true ,fct, 0, D3Q27BCFunction::INFCONST));
+         // velBCAdapter->setSecondaryBcOption(2);
+         // D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterInlet(new D3Q27DensityBCAdapter(3.0*(dp_lb-rhoLB)));
+         denBCAdapterInlet->setSecondaryBcOption(1);
+         D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, denBCAdapterInlet,Interactor3D::SOLID));
+
+         //rechts: druckrand
+         //Density-BC
+         //fuer Kompressibles Modell  rho = 1.0
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(1);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(outflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+         SolidBlocksHelper sd(grid, comm);
+         sd.addInteractor(geoInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+         // sd.addInteractor(plate1_1Int);
+         // sd.addInteractor(plate1_2Int);
+         // sd.addInteractor(plate1_3Int);
+         // sd.addInteractor(plate1_4Int);
+         // sd.addInteractor(plate2Int);
+         // sd.addInteractor(plate3Int);
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         sd.deleteSolidBlocks();  
+
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         grid->accept( metisVisitor );
+         sd.setTransBlocks();		 
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod_temp = nob * (nodePerBlockX1+gl) * (nodePerBlockX2+gl) * (nodePerBlockX3+gl);
+         unsigned long nod = nob * (nodePerBlockX1) * (nodePerBlockX2) * (nodePerBlockX3);
+         double needMemAll  = double(nod_temp*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }  
+
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3,LBMKernelETD3Q27CCLB::MAGIC));
+
+
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         if(myid == 0) UBLOG(logINFO,"intractor - start"); 
+         //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+         //canal
+         grid->addAndInitInteractor(geoInt);
+         // grid->addAndInitInteractor(plate1_1Int);
+         // grid->addAndInitInteractor(plate1_2Int);
+         // grid->addAndInitInteractor(plate1_3Int);
+         // grid->addAndInitInteractor(plate1_4Int);
+         // grid->addAndInitInteractor(plate2Int);
+         // grid->addAndInitInteractor(plate3Int);
+
+
+         if(myid == 0) UBLOG(logINFO,"intractor - end");
+         //////////////////////////////////////////////////////////////////////////
+         //connectoren setzen:
+
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         //////////////////////////////////////////////////////////////////////////	 
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         //////////////////////////////////////////////////////////////////////////     
+         //Stroemungsfeld initialisieren
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB); //1.0
+         initVisitor.setVx1(0); 
+         grid->accept(initVisitor);
+
+         // if(myid == 0)
+         // {
+         // //Abstände "q" als Linien rausschreiben
+         // std::vector< UbTupleFloat3 > nodes;
+         // std::vector< UbTupleInt2 >   lines;
+         // geoInt->addQsLineSet(nodes, lines);
+         // WbWriterVtkXmlBinary::getInstance()->writeLines(pathname+"/grid/qs",nodes,lines);
+         // }
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");
+
+         ////////////////////////
+         //Set Postprozessors
+         //////////////////////////////////////////////////////////////////////////
+         {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+            //grid->doPostProcess(0);
+            grid->notifyObservers(0);
+         }
+
+
+      }
+
+      //////////////////////////////////////////////////////////////////////////
+      // UbSchedulerPtr visSchAv(new UbScheduler());
+      UbSchedulerPtr visSchAv(new UbScheduler(100000,350000));
+      // visSchAv->addSchedule(100,10,1000);
+      // UbSchedulerPtr resSchAv(new UbScheduler());
+      UbSchedulerPtr resSchAv(new UbScheduler(100,10000000000));
+      // resSchAv->addSchedule(20,20,1000);
+      AverageValuesPostprocessor       Avpp(grid,  pathname + "/Turbulence/stepAV", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm);
+
+      D3Q27ShearStressPostprocessor  shear(grid,  pathname + "/shear/step", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/); 
+      // D3Q27ShearStressPostprocessor  shear(grid,  pathname + "/shear/step", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm);
+      shear.addInteractor(geoInt);
+      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+      UbSchedulerPtr nupsSch(new UbScheduler(1, 5, 10));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 10000.0;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid,stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv,  comm);
+      //////////////////////////////////////////////////////////////////////////
+      //PathLine
+      UbSchedulerPtr plSch(new UbScheduler(5000, 5000));
+      const int numberofparticle=20;
+
+      std::vector<UbTupleDouble3 > potisions;
+      double randomx[numberofparticle];
+      double randomy[numberofparticle];
+      double randomz[numberofparticle];
+      double lowestx,highestx,lowesty,highesty,lowestz,highestz;
+      if(myid==0)
+      {
+         for(int i = 0; i < numberofparticle; i++)
+         {
+            double random; 
+            lowestx =-10300.0;  lowesty =-230;          lowestz =-250;
+            highestx=-9792.0;  highesty=-330;          highestz=-250; 
+
+            double rangex=(highestx-lowestx),rangey=(highesty-lowesty),rangez=(highestz-lowestz);	
+            randomx[i] = lowestx+(rangex*rand()/(RAND_MAX + 1.0));
+            randomy[i] = lowesty+(rangey*rand()/(RAND_MAX + 1.0));
+            randomz[i] = lowestz+(rangez*rand()/(RAND_MAX + 1.0));
+            //val<1>(potisions[i])= 0.506983973456;
+            //val<2>(potisions[i]) = lowesty+(rangey*rand()/(RAND_MAX + 1.0));
+            //val<3>(potisions[i]) = lowestz+(rangez*rand()/(RAND_MAX + 1.0));
+         }
+         for (int i=0;i<comm->getNumberOfProcesses();i++)
+         {
+            if (i!=0)
+            {
+               MPI_Send(randomx,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+               MPI_Send(randomy,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+               MPI_Send(randomz,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+            }
+         }
+      }
+      if (myid!=0)
+      {
+         MPI_Status status; 
+         MPI_Recv(randomx,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+         MPI_Recv(randomy,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+         MPI_Recv(randomz,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+      }
+      for(int i = 0; i < numberofparticle; i++)
+      {	
+         potisions.push_back( makeUbTuple(randomx[i],randomy[i],randomz[i]) );
+         //val<1>(potisions[i])= 0.506983973456;
+         //val<2>(potisions[i]) = randomy[i];
+         //val<3>(potisions[i]) = randomz[i];
+      }
+      //  UBLOG(logINFO,"Rank="<<myid<<" positions  = " <<val<1>(potisions)<< " "<<val<2>(potisions)<<" "<< val<3>(potisions));
+      // D3Q27InterpolationProcessorPtr iProcessor2;
+      // D3Q27PathLinePostprocessorMcpart pathLine(grid, pathname + "/pathLine/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm,potisions, nueLB, iProcessor);
+      //////////////////////////////////////////////////////////////////////////
+      //Simulation
+      //////////////////////////////////////////////////////////////////////////
+      return;
+
+      double endTime = 1000000000.0;
+      UbSchedulerPtr visSch(stepSch);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
diff --git a/source/Applications/micropart/miro.txt b/source/Applications/micropart/miro.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7ed704098a74d3ea0db5fea3a9cf21810bcbeb8e
--- /dev/null
+++ b/source/Applications/micropart/miro.txt
@@ -0,0 +1,585 @@
+#include <iostream>
+#include <string>
+#include <map>
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include "numerics/geometry3d/GbSphere3D.h"
+#include "BlocksPostprocessor.h"
+#include "Grid3D.h"
+#include "Patch3D.h"
+#include "Patch3DSystem.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "LBMKernelETD3Q27BGK.h"
+#include "CalculationManager.h" 
+#include "D3Q27SetConnectorsBlockVisitor.h" 
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "Communicator.h"
+#include "MPICommunicator.h"
+#include "SimpleGeometricPartitioner.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27TriFaceMeshInteractor.h"
+#include "ConfigFileReader.h"
+#include "StringUtil.hpp"
+#include "D3Q27PressureDifferencePostprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "LBMUnitConverter.h"
+#include "NUPSCounterPostprocessor.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "GenBlocksGridVisitor.h"
+#include "D3Q27PathLinePostprocessorMcpart.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+   //
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h"
+#include "numerics/geometry3d/GbTriFaceMesh3D.h"
+#include "D3Q27System.h"
+#include <basics/transmitter/TbTransmitterMpiPool.h>
+#include "MathUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "SolidBlocksHelper.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "RestartPostprocessor.h"
+#include "D3Q27IncompressibleOffsetInterpolationProcessor.h"
+#include "LBMKernelETD3Q27CCLB.h"
+#include "AverageValuesPostprocessor.h"
+#include <vfluids.h>
+using namespace std;
+
+void micropartTestQs2(const char *cstr)
+{
+   try
+   {
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+      int numprocs = comm->getNumberOfProcesses();
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      double availMem = 0;
+      string geoFile;
+      int numOfThreads = 1;
+
+      if(machine == "EHSAN1491") 
+      {
+         pathname = "/work/ehsan/micropart";
+         availMem = 3.0e9;
+		  int numOfThreads = 1;
+         //geoFile = "c:/Data/micropart/DK19_7_02_Martin.stl";
+         //geoFile = "c:/Data/micropart/ktoolcav.stl";
+         //geoFile = "c:/Data/micropart/boxN.stl";
+        geoFile = "C:/Users/ehsan/Desktop/meshparticles/E0019B_mit_Radien.stl";
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/ehsan/micropart";
+         availMem = 12.0e9;
+		  geoFile = "/work/ehsan/data/E0019B_mit_Radien.stl";
+         //geoFile = "/home/koskuche/data/micropart/DK19_7_02_Martin.stl";
+
+         numOfThreads = 1;
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      UbLog::reportingLevel() = logINFO;
+      //UbLog::reportingLevel() = logDEBUG1;
+
+      int nodePerBlockX1 =16; //Anzahl an Knoten pro Block
+      int nodePerBlockX2 =16;//(int)16;
+      int nodePerBlockX3 =8;//8; //(int)16;
+
+      double bH = nodePerBlockX1;    //gewuenschte Rand- und Blockbreite
+
+      //Simulation Parameters
+      const int baseLevel = 0;
+      const int refineLevel =4;
+      //length [m]
+      double lSI = 219;//223.2;
+      //length [LB]
+      double lLB = 30;
+
+      double dx =lSI/lLB;
+
+      double left_offset = 10700;//*0.5;
+      double right_offset  = 107000;//0.5;//2*0.5
+      double front_offset = 750;//0.15;
+      double back_offset  = 750;//0.15;
+      double top_offset = 250;//0.0;
+      double bottom_offset  =750;// 70;//0.07;
+	  
+	   LBMReal vLB =0.00016103/5.0*sqrt(2.0);//0.00016103;
+       LBMReal Re;
+       LBMReal rhoLB = 0.0;
+       LBMReal nueLB = 0.0000249;//(vLB*lLB)/Re;
+       Re = (vLB*(500/dx))/nueLB;
+       double dp_Ph=200.0*100000;//
+	   double dp_lb=dp_Ph*0.001*(nueLB*dx)*(nueLB*dx);//nue_ph=10e-6 and dx is in micrometer
+      // LBMReal nueLB = 0.000016103;
+      // LBMReal Re=15000;
+      // LBMReal rhoLB = 0.0;
+      // LBMReal vLB =nueLB*Re/(500.0/dx);
+     // // Re = (vLB*(0.303/dx))/nueLB;
+	   // //Re = (vLB*lLB)/nueLB;
+	  
+      // LBMReal rhoWord = 1e-15;//kg/micrometre^3;//1000.0;
+	  // LBMReal nueRE = 1e6;//micromter^2/s;//0.000001;
+	  // LBMReal  vWorld=300*1e6;//micrometer/s;//nueRE*Re/ (lSI*4.0/9.0);
+	  LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      //conv->init(lSI*1e-6,30000,rhoWord,vWorld,lLB,1.0/*rhoLB*/,vLB);
+      
+	 
+ //////////////////////////////////////////////////////////////////////////
+      GbObject3DPtr refineCube1(new  GbCuboid3D(-500.0+5.0/*-354.0*/,-957.0/*-280.0*/,-684.0/* -72.0*/, 4100/*370.0*/,957.0/*354.0*/,70.0));//-530.0,-280.0, -72.0, 530.0,354.0,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube1.get(), pathname+"/geo/refineCube1", WbWriterVtkXmlASCII::getInstance());
+
+      GbObject3DPtr refineCube2(new  GbCuboid3D(-230.0,-90.0, -684.0/*-72.0*/, 600,100.0,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube2.get(), pathname+"/geo/refineCube2", WbWriterVtkXmlASCII::getInstance());
+	  
+	   GbObject3DPtr refineCube3(new  GbCuboid3D(-350.0,-957.0/*-120.0*/,-684.0/*-684.0*//* -72.0*/, 1700,957.0/*120.0*/,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube3.get(), pathname+"/geo/refineCube3", WbWriterVtkXmlASCII::getInstance());
+	  
+	   GbObject3DPtr refineCube4(new  GbCuboid3D(-170.0,-60.0, -684.0/*-72.0*/, 200,60.0,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube4.get(), pathname+"/geo/refineCube4", WbWriterVtkXmlASCII::getInstance());
+	  
+	   GbObject3DPtr refineCubeInlet(new  GbCuboid3D(-10600.0,-600.0, -600.0/*-72.0*/, -9000,600.0,60.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCubeInlet.get(), pathname+"/geo/refineCubeInlet", WbWriterVtkXmlASCII::getInstance());
+	  
+	  GbObject3DPtr refineCubeOutlet(new  GbCuboid3D(9000,-600.0, -600.0/*-72.0*/,10550.0 ,600.0,60.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCubeOutlet.get(), pathname+"/geo/refineCubeOutlet", WbWriterVtkXmlASCII::getInstance());
+      //////////////////////////////////////////////////////////////////////////
+      D3Q27TriFaceMeshInteractorPtr geoInt;
+	  /////////////////
+      //Grid3DPtr grid(new Grid3D());
+        Grid3DPtr grid(new Grid3D(comm));
+
+      UbSchedulerPtr rSch(new UbScheduler());
+      rSch->addSchedule(100, 200, 20000);
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         rp->reconnect(grid);
+
+         // SetForcingBlockVisitor forcingVisitor(0.0, 0.0, 0.0);
+         // grid->accept(forcingVisitor);
+
+         //D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+		  if(myid==0) UBLOG(logINFO,"Restart finish: " << opt);
+	 
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " <<lLB );
+            UBLOG(logINFO,"v = " <<vLB );
+            UBLOG(logINFO,"rho = " <<rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+			UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Re = " << Re );
+			 UBLOG(logINFO,"dp_lb = " << dp_lb );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+
+         ////////////////////////////////////////////////////////////////////////
+         //Grid
+         //////////////////////////////////////////////////////////////////////////
+         grid->setDeltaX(dx);
+         grid->setBlockNX(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3);
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Geometrie
+         ////////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr geo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+
+         if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo", WbWriterVtkXmlASCII::getInstance());
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Randgeometrien erstellen
+         ////////////////////////////////////////////////////////////////////////////
+         double shiftForMG=grid->getDeltaX(refineLevel)*nodePerBlockX1 / 3.0*2.0;
+          GbCuboid3DPtr plate1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -1.515e-1, -6.831e-2, 7.5, 1.515e-1, 0.0 ));
+
+           GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+           GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+          // GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -1.0e-1, 7.5, 2.515e-1, -6.831e-2 ));
+          // GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -0.0000001, 7.5, 2.515e-1, 1.0e-1 ));
+          // GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -7.5, 1.515e-1, -6.831e-2, 7.5, 2.515e-1, 0.0  ));
+          // GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, 0.0, 7.5, -1.515e-1, -1.0e-1 ));
+
+          // GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -8.0, -1.0, -1.0, -7.5, 1.0, 1.0 ));
+          // GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 7.5, -1.0, -1.0, 8.0, 1.0, 1.0 ));
+		  
+		   // GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+          // GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+          // GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, back_offset, -bottom_offset-bH*dx, right_offset+bH*dx, back_offset+bH*dx, top_offset+bH*dx ));
+          // GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, -bottom_offset-bH*dx, right_offset+bH*dx, -front_offset, top_offset+bH*dx ));
+          // GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, top_offset, right_offset+bH*dx, back_offset+bH*dx, top_offset+bH*dx+2.0*dx ));
+          // GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, -bottom_offset-bH*dx, right_offset+bH*dx, back_offset+bH*dx, -bottom_offset ));
+
+          //GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-5*bH*dx, -front_offset-5*bH*dx, -bottom_offset-5*bH*dx, -left_offset, back_offset+5*bH*dx, top_offset+5*bH*dx ));
+          //GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( right_offset, -front_offset-5*bH*dx, -bottom_offset-5*bH*dx, right_offset+5.0*bH*dx, back_offset+5*bH*dx, top_offset+5*bH*dx ));
+		  GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -11000.0,-600.0, -600.0, -9000.0, 600.0, -500 ));
+		  GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 9000,-600.0, -600.0, 11000.0, 600.0, -500));
+
+
+		   GbObject3DPtr gridCube(new GbCuboid3D(-10700.0/*inflow->getX1Maximum()-4.0*dx/*.5*shiftForMG*/,-550.0/*-270*/ , -550.0/*-70*/,
+                                                10700.0/*outflow->getX1Minimum()+4.0*dx/*.5*shiftForMG*/, 
+                                                550.0/*270*/, 
+                                                23.0/*10.0*/));
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+		  
+         if(myid == 0)
+         {
+            GbSystem3D::writeGeoObject(gridCube.get(),pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+            //GbSystem3D::writeGeoObject(plate2.get(),pathname+"/geo/plate2", WbWriterVtkXmlASCII::getInstance());
+            //GbSystem3D::writeGeoObject(plate3.get(),pathname+"/geo/plate3", WbWriterVtkXmlASCII::getInstance());
+
+            // GbSystem3D::writeGeoObject(plate1_1.get(),pathname+"/geo/plate1_1", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_2.get(),pathname+"/geo/plate1_2", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_3.get(),pathname+"/geo/plate1_3", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_4.get(),pathname+"/geo/plate1_4", WbWriterVtkXmlASCII::getInstance());
+
+            GbSystem3D::writeGeoObject(inflow.get(),pathname+"/geo/inflow", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(outflow.get(),pathname+"/geo/outflow", WbWriterVtkXmlASCII::getInstance());
+         }
+   
+
+         if (refineLevel > 0)
+         {
+		  if(myid == 0) UBLOG(logINFO,"Refinement - start");   
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineCube1, 1);
+            refineHelper.addGbObject(refineCube3, 2);
+			 refineHelper.addGbObject(refineCube2, 3);
+			 refineHelper.addGbObject(refineCube4, 4);
+			 
+			 refineHelper.addGbObject(refineCubeInlet, 1);
+			 refineHelper.addGbObject(refineCubeOutlet, 1);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");   
+		 
+		 
+           // RefineCrossAndInsideGbObjectBlockVisitor refVisitor1(refineCube1, refineLevel-4);
+            // grid->accept(refVisitor1);
+
+			// RefineCrossAndInsideGbObjectBlockVisitor refVisitor3(refineCube3, refineLevel-3);
+            // grid->accept(refVisitor3);
+
+            // RefineCrossAndInsideGbObjectBlockVisitor refVisitor2(refineCube2, refineLevel-2);
+            // grid->accept(refVisitor2);
+			
+			 // RefineCrossAndInsideGbObjectBlockVisitor refVisitor4(refineCube4, refineLevel-1);
+            // grid->accept(refVisitor4);
+
+            // RatioBlockVisitor ratioVisitor(refineLevel);
+            // grid->accept(ratioVisitor);
+
+            // RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            // grid->accept(ratioSmoothVisitor);
+
+            // OverlapBlockVisitor overlapVisitor(refineLevel);
+            // grid->accept(overlapVisitor);
+
+            // std::vector<int> dirs;
+            // D3Q27System::getLBMDirections(dirs);
+            // SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            // grid->accept(interDirsVisitor);
+            // if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //INTERAKTOREN SETZEN (=Randbedingungen)
+         //////////////////////////////////////////////////////////////////////////
+         //oben/unten = Haftrand
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         geoInt = D3Q27TriFaceMeshInteractorPtr( new D3Q27TriFaceMeshInteractor(geo, grid, D3Q27BoundaryConditionAdapterPtr(new D3Q27NoSlipBCAdapter(bbOption)),Interactor3D::INVERSESOLID, Interactor3D::SIMPLE));
+	     geoInt->setUseHalfSpaceCheck(true);
+         geoInt->setRegardPointInObjectTest(true);
+         if(myid == 0) UBLOG(logINFO,"stl - end"); 
+         //D3Q27InteractorPtr plate1Int(new D3Q27Interactor(plate1, grid, bcObst,Interactor3D::INVERSESOLID));
+         // D3Q27InteractorPtr plate2Int(new D3Q27Interactor(plate2, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate3Int(new D3Q27Interactor(plate3, grid, bcObst,Interactor3D::SOLID));
+
+         // D3Q27InteractorPtr plate1_1Int(new D3Q27Interactor(plate1_1, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_2Int(new D3Q27Interactor(plate1_2, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_3Int(new D3Q27Interactor(plate1_3, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_4Int(new D3Q27Interactor(plate1_4, grid, bcObst,Interactor3D::SOLID));
+
+         //links: geschwindigkeits-einfluss
+         //Velocity-BC
+         //////////////////////////////////////////////////////////////////////////
+         mu::Parser fct;
+         fct.DefineConst("vx1"  , vLB*9.0/4.0 );
+         //fct = MathUtil::getDuctParaboloidX(0, 250*2.0, -51.08/2, 51.08, vLB*9.0/4.0);
+         fct.SetExpr("vx1");
+         //////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////////
+            // D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter (false, false ,true ,fct, 0, D3Q27BCFunction::INFCONST));
+            // velBCAdapter->setSecondaryBcOption(2);
+            // D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+		 D3Q27BoundaryConditionAdapterPtr denBCAdapterInlet(new D3Q27DensityBCAdapter(3.0*(dp_lb-rhoLB)));
+        denBCAdapterInlet->setSecondaryBcOption(1);
+        D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, denBCAdapterInlet,Interactor3D::SOLID));
+		 
+         //rechts: druckrand
+         //Density-BC
+         //fuer Kompressibles Modell  rho = 1.0
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(1);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(outflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+         SolidBlocksHelper sd(grid, comm);
+         sd.addInteractor(geoInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+         // sd.addInteractor(plate1_1Int);
+         // sd.addInteractor(plate1_2Int);
+         // sd.addInteractor(plate1_3Int);
+         // sd.addInteractor(plate1_4Int);
+         // sd.addInteractor(plate2Int);
+         // sd.addInteractor(plate3Int);
+		 if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         sd.deleteSolidBlocks();     
+ if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         grid->accept( metisVisitor );
+if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod_temp = nob * (nodePerBlockX1+gl) * (nodePerBlockX2+gl) * (nodePerBlockX3+gl);
+         unsigned long nod = nob * (nodePerBlockX1) * (nodePerBlockX2) * (nodePerBlockX3);
+         double needMemAll  = double(nod_temp*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }  
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+
+		  int option = 0;
+		 LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3,option));
+
+		 
+		 
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+		 
+		  if(myid == 0) UBLOG(logINFO,"intractor - start"); 
+          //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+         //canal
+         grid->addAndInitInteractor(geoInt);
+         // grid->addAndInitInteractor(plate1_1Int);
+         // grid->addAndInitInteractor(plate1_2Int);
+         // grid->addAndInitInteractor(plate1_3Int);
+         // grid->addAndInitInteractor(plate1_4Int);
+         // grid->addAndInitInteractor(plate2Int);
+         // grid->addAndInitInteractor(plate3Int);
+
+       
+
+         //////////////////////////////////////////////////////////////////////////
+         //connectoren setzen:
+
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         //////////////////////////////////////////////////////////////////////////	 
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+			 
+         //////////////////////////////////////////////////////////////////////////     
+	   //Stroemungsfeld initialisieren
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB); //1.0
+         initVisitor.setVx1(0); 
+         grid->accept(initVisitor);
+
+         if(myid == 0)
+         {
+            //Abstände "q" als Linien rausschreiben
+            std::vector< UbTupleFloat3 > nodes;
+            std::vector< UbTupleInt2 >   lines;
+            geoInt->addQsLineSet(nodes, lines);
+            WbWriterVtkXmlBinary::getInstance()->writeLines(pathname+"/grid/qs",nodes,lines);
+         }
+
+          if(myid == 0) UBLOG(logINFO,"Preprozess - end");
+		 
+		 	  ////////////////////////
+           //Set Postprozessors
+           //////////////////////////////////////////////////////////////////////////
+           {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+            grid->doPostProcess(0);
+           }
+	    
+
+      }
+
+      //////////////////////////////////////////////////////////////////////////
+	   // UbSchedulerPtr visSchAv(new UbScheduler());
+		UbSchedulerPtr visSchAv(new UbScheduler(100,100));
+      // visSchAv->addSchedule(100,10,1000);
+      // UbSchedulerPtr resSchAv(new UbScheduler());
+	   UbSchedulerPtr resSchAv(new UbScheduler(100,100));
+      // resSchAv->addSchedule(20,20,1000);
+      AverageValuesPostprocessor       Avpp(grid,  pathname + "/Turbulence/stepAV", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm);
+	  
+	 D3Q27ShearStressPostprocessor  shear(grid,  pathname + "/shear/step", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm,iProcessor); 
+	 // D3Q27ShearStressPostprocessor  shear(grid,  pathname + "/shear/step", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm);
+	  shear.addInteractor(geoInt);
+	   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	  
+
+      UbSchedulerPtr nupsSch(new UbScheduler(1, 5, 10));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 100.0;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid,stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv,  comm);
+      //////////////////////////////////////////////////////////////////////////
+      //PathLine
+       UbSchedulerPtr plSch(new UbScheduler(5000, 5000));
+      const int numberofparticle=20;
+	
+	  std::vector<UbTupleDouble3 > potisions;
+	  double randomx[numberofparticle];
+	  double randomy[numberofparticle];
+	  double randomz[numberofparticle];
+	  double lowestx,highestx,lowesty,highesty,lowestz,highestz;
+	  if(myid==0)
+	  {
+		  for(int i = 0; i < numberofparticle; i++)
+		  {
+			  double random; 
+	        lowestx =-10300.0;  lowesty =-230;          lowestz =-250;
+	        highestx=-9792.0;  highesty=-330;          highestz=-250; 
+		  
+	      double rangex=(highestx-lowestx),rangey=(highesty-lowesty),rangez=(highestz-lowestz);	
+           randomx[i] = lowestx+(rangex*rand()/(RAND_MAX + 1.0));
+		   randomy[i] = lowesty+(rangey*rand()/(RAND_MAX + 1.0));
+	       randomz[i] = lowestz+(rangez*rand()/(RAND_MAX + 1.0));
+		  //val<1>(potisions[i])= 0.506983973456;
+		  //val<2>(potisions[i]) = lowesty+(rangey*rand()/(RAND_MAX + 1.0));
+		   //val<3>(potisions[i]) = lowestz+(rangez*rand()/(RAND_MAX + 1.0));
+		  }
+		  for (int i=0;i<comm->getNumberOfProcesses();i++)
+		  {
+			  if (i!=0)
+			  {
+			      MPI_Send(randomx,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+				  MPI_Send(randomy,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+				  MPI_Send(randomz,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+			  }
+		  }
+	  }
+	  if (myid!=0)
+	  {
+		  MPI_Status status; 
+		  MPI_Recv(randomx,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+		  MPI_Recv(randomy,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+		  MPI_Recv(randomz,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+	  }
+	  for(int i = 0; i < numberofparticle; i++)
+	  {	
+		  potisions.push_back( makeUbTuple(randomx[i],randomy[i],randomz[i]) );
+		  //val<1>(potisions[i])= 0.506983973456;
+		  //val<2>(potisions[i]) = randomy[i];
+		  //val<3>(potisions[i]) = randomz[i];
+	  }
+	 //  UBLOG(logINFO,"Rank="<<myid<<" positions  = " <<val<1>(potisions)<< " "<<val<2>(potisions)<<" "<< val<3>(potisions));
+	 // D3Q27InterpolationProcessorPtr iProcessor2;
+     // D3Q27PathLinePostprocessorMcpart pathLine(grid, pathname + "/pathLine/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm,potisions, nueLB, iProcessor);
+      //////////////////////////////////////////////////////////////////////////
+      //Simulation
+      //////////////////////////////////////////////////////////////////////////
+
+	  double endTime = 1000.0;
+      UbSchedulerPtr visSch(stepSch);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
diff --git a/source/Applications/micropart/orifice.hpp b/source/Applications/micropart/orifice.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2cba0511e7a7e62ca25e1315b3d0f24908a06004
--- /dev/null
+++ b/source/Applications/micropart/orifice.hpp
@@ -0,0 +1,542 @@
+#include <vfluids.h>
+using namespace std;
+
+void orifice(const char *cstr)
+{
+   try
+   {
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+      int numprocs = comm->getNumberOfProcesses();
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      double availMem = 0;
+      string geoFile;
+      int numOfThreads = 1;
+
+      if(machine == "BOMBADIL") 
+      {
+    //     pathname = "/work/ehsan/orifice";
+		 pathname = "d:/temp/orifice";
+         availMem = 6.0e9;
+		  int numOfThreads = 1;
+         //geoFile = "c:/Data/micropart/DK19_7_02_Martin.stl";
+         //geoFile = "c:/Data/micropart/ktoolcav.stl";
+         //geoFile = "c:/Data/micropart/boxN.stl";
+        geoFile = "d:/Data/Ehsan/orifice.stl";
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+        // pathname = "/work/koskuche/scratch/mcpart/out";
+		  pathname = "/work/ehsan/orifice";
+         availMem = 12.0e9;
+		  geoFile = "/work/ehsan/data/orifice.stl";
+         //geoFile = "/home/koskuche/data/micropart/DK19_7_02_Martin.stl";
+
+         numOfThreads = 1;
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      UbLog::reportingLevel() = logINFO;
+      //UbLog::reportingLevel() = logDEBUG1;
+
+      int nodePerBlockX1 =8; //Anzahl an Knoten pro Block
+      int nodePerBlockX2 =8;//(int)16;
+      int nodePerBlockX3 =8;//8; //(int)16;
+
+      double bH = nodePerBlockX1;    //gewuenschte Rand- und Blockbreite
+
+      //Simulation Parameters
+      const int baseLevel = 0;
+      const int refineLevel =1;
+      //length [m]
+      double lSI = 1.55;//223.2;
+      //length [LB]
+      double lLB = 15;
+
+	  
+      double dx =lSI/lLB *2;
+
+      double left_offset = 0;//*0.5;
+      double right_offset  = 159;//0.5;//2*0.5
+      double front_offset = 750;//0.15;
+      double back_offset  = 750;//0.15;
+      double top_offset = 250;//0.0;
+      double bottom_offset  =750;// 70;//0.07;
+	  
+	   LBMReal vLB =0.00016103/5.0*sqrt(2.0);//0.00016103;
+       LBMReal Re;
+       LBMReal rhoLB = 0.0;
+       LBMReal nueLB = 0.0000249;//(vLB*lLB)/Re;
+       Re = (vLB*(500/dx))/nueLB;
+       double dp_Ph=200.0*100000;//
+	   double dp_lb=dp_Ph*0.001*(nueLB*dx)*(nueLB*dx);//nue_ph=10e-6 and dx is in micrometer
+      // LBMReal nueLB = 0.000016103;
+      // LBMReal Re=15000;
+      // LBMReal rhoLB = 0.0;
+      // LBMReal vLB =nueLB*Re/(500.0/dx);
+     // // Re = (vLB*(0.303/dx))/nueLB;
+	   // //Re = (vLB*lLB)/nueLB;
+	  
+      // LBMReal rhoWord = 1e-15;//kg/micrometre^3;//1000.0;
+	  // LBMReal nueRE = 1e6;//micromter^2/s;//0.000001;
+	  // LBMReal  vWorld=300*1e6;//micrometer/s;//nueRE*Re/ (lSI*4.0/9.0);
+	  LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      //conv->init(lSI*1e-6,30000,rhoWord,vWorld,lLB,1.0/*rhoLB*/,vLB);
+      
+	 
+ //////////////////////////////////////////////////////////////////////////
+      GbObject3DPtr refineCube1(new  GbCuboid3D(78.0,-1.0,-1.0, 81/*370.0*/,20.0/*354.0*/,20.0));//-530.0,-280.0, -72.0, 530.0,354.0,70.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(refineCube1.get(), pathname+"/geo/refineCube1", WbWriterVtkXmlASCII::getInstance());
+
+   //   GbObject3DPtr refineCube2(new  GbCuboid3D(-230.0,-90.0, -684.0/*-72.0*/, 600,100.0,70.0));
+   //   if(myid == 0) GbSystem3D::writeGeoObject(refineCube2.get(), pathname+"/geo/refineCube2", WbWriterVtkXmlASCII::getInstance());
+	  //
+	  // GbObject3DPtr refineCube3(new  GbCuboid3D(-350.0,-957.0/*-120.0*/,-684.0/*-684.0*//* -72.0*/, 1700,957.0/*120.0*/,70.0));
+   //   if(myid == 0) GbSystem3D::writeGeoObject(refineCube3.get(), pathname+"/geo/refineCube3", WbWriterVtkXmlASCII::getInstance());
+	  //
+	  // GbObject3DPtr refineCube4(new  GbCuboid3D(-170.0,-60.0, -684.0/*-72.0*/, 200,60.0,70.0));
+   //   if(myid == 0) GbSystem3D::writeGeoObject(refineCube4.get(), pathname+"/geo/refineCube4", WbWriterVtkXmlASCII::getInstance());
+	  //
+	  // GbObject3DPtr refineCubeInlet(new  GbCuboid3D(-10600.0,-600.0, -600.0/*-72.0*/, -9000,600.0,60.0));
+   //   if(myid == 0) GbSystem3D::writeGeoObject(refineCubeInlet.get(), pathname+"/geo/refineCubeInlet", WbWriterVtkXmlASCII::getInstance());
+	  //
+	  //GbObject3DPtr refineCubeOutlet(new  GbCuboid3D(9000,-600.0, -600.0/*-72.0*/,10550.0 ,600.0,60.0));
+   //   if(myid == 0) GbSystem3D::writeGeoObject(refineCubeOutlet.get(), pathname+"/geo/refineCubeOutlet", WbWriterVtkXmlASCII::getInstance());
+      //////////////////////////////////////////////////////////////////////////
+      D3Q27TriFaceMeshInteractorPtr geoInt;
+	  /////////////////
+      //Grid3DPtr grid(new Grid3D());
+        Grid3DPtr grid(new Grid3D(comm));
+
+      UbSchedulerPtr rSch(new UbScheduler());
+      rSch->addSchedule(100, 200, 20000);
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      std::string opt;
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         rp->reconnect(grid);
+
+         // SetForcingBlockVisitor forcingVisitor(0.0, 0.0, 0.0);
+         // grid->accept(forcingVisitor);
+
+         //D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+		  if(myid==0) UBLOG(logINFO,"Restart finish: " << opt);
+	 
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " <<lLB );
+            UBLOG(logINFO,"v = " <<vLB );
+            UBLOG(logINFO,"rho = " <<rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+			UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"Re = " << Re );
+			 UBLOG(logINFO,"dp_lb = " << dp_lb );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+
+         ////////////////////////////////////////////////////////////////////////
+         //Grid
+         //////////////////////////////////////////////////////////////////////////
+         grid->setDeltaX(dx);
+         grid->setBlockNX(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3);
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Geometrie
+         ////////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr geo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(geoFile,"geo"));
+
+         if(myid == 0) GbSystem3D::writeGeoObject(geo.get(), pathname+"/geo/geo", WbWriterVtkXmlASCII::getInstance());
+
+         ////////////////////////////////////////////////////////////////////////////
+         //// Randgeometrien erstellen
+         ////////////////////////////////////////////////////////////////////////////
+         double shiftForMG=grid->getDeltaX(refineLevel)*nodePerBlockX1 / 3.0*2.0;
+          GbCuboid3DPtr plate1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -1.515e-1, -6.831e-2, 7.5, 1.515e-1, 0.0 ));
+
+           GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+           GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+          // GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -1.0e-1, 7.5, 2.515e-1, -6.831e-2 ));
+          // GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, -0.0000001, 7.5, 2.515e-1, 1.0e-1 ));
+          // GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -7.5, 1.515e-1, -6.831e-2, 7.5, 2.515e-1, 0.0  ));
+          // GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -7.5, -2.515e-1, 0.0, 7.5, -1.515e-1, -1.0e-1 ));
+
+          // GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -8.0, -1.0, -1.0, -7.5, 1.0, 1.0 ));
+          // GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 7.5, -1.0, -1.0, 8.0, 1.0, 1.0 ));
+		  
+		   // GbCuboid3DPtr plate2  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, -16.51e-1, -16.831e-2, 1.5e-1, -1.6e-2, 1.0 ));
+          // GbCuboid3DPtr plate3  = GbCuboid3DPtr( new GbCuboid3D( -1.5e-1, 1.6e-2, -16.831e-2, 1.5e-1, 16.515e-1, 1.0 ));
+
+          // GbCuboid3DPtr plate1_1  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, back_offset, -bottom_offset-bH*dx, right_offset+bH*dx, back_offset+bH*dx, top_offset+bH*dx ));
+          // GbCuboid3DPtr plate1_2  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, -bottom_offset-bH*dx, right_offset+bH*dx, -front_offset, top_offset+bH*dx ));
+          // GbCuboid3DPtr plate1_3  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, top_offset, right_offset+bH*dx, back_offset+bH*dx, top_offset+bH*dx+2.0*dx ));
+          // GbCuboid3DPtr plate1_4  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-bH*dx, -front_offset-bH*dx, -bottom_offset-bH*dx, right_offset+bH*dx, back_offset+bH*dx, -bottom_offset ));
+
+          //GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -left_offset-5*bH*dx, -front_offset-5*bH*dx, -bottom_offset-5*bH*dx, -left_offset, back_offset+5*bH*dx, top_offset+5*bH*dx ));
+          //GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( right_offset, -front_offset-5*bH*dx, -bottom_offset-5*bH*dx, right_offset+5.0*bH*dx, back_offset+5*bH*dx, top_offset+5*bH*dx ));
+		  GbCuboid3DPtr inflow  = GbCuboid3DPtr( new GbCuboid3D( -5.0,-1.5, -1.5, 1.5, 20.0, 20.0 ));
+		  GbCuboid3DPtr outflow = GbCuboid3DPtr( new GbCuboid3D( 157.50,-1.5, -1.5, 160.5, 20.0, 20.0));
+
+
+		   GbObject3DPtr gridCube(new GbCuboid3D(inflow->getX1Maximum()-4.0*dx,inflow->getX2Minimum()-4.0*dx ,inflow->getX3Minimum()-4.0*dx,
+			   outflow->getX1Minimum()-4.0*dx,outflow->getX2Maximum()-4.0*dx ,outflow->getX3Maximum()-4.0*dx
+                                               ));
+
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+		  
+         if(myid == 0)
+         {
+            GbSystem3D::writeGeoObject(gridCube.get(),pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+            //GbSystem3D::writeGeoObject(plate2.get(),pathname+"/geo/plate2", WbWriterVtkXmlASCII::getInstance());
+            //GbSystem3D::writeGeoObject(plate3.get(),pathname+"/geo/plate3", WbWriterVtkXmlASCII::getInstance());
+
+            // GbSystem3D::writeGeoObject(plate1_1.get(),pathname+"/geo/plate1_1", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_2.get(),pathname+"/geo/plate1_2", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_3.get(),pathname+"/geo/plate1_3", WbWriterVtkXmlASCII::getInstance());
+            // GbSystem3D::writeGeoObject(plate1_4.get(),pathname+"/geo/plate1_4", WbWriterVtkXmlASCII::getInstance());
+
+            GbSystem3D::writeGeoObject(inflow.get(),pathname+"/geo/inflow", WbWriterVtkXmlASCII::getInstance());
+            GbSystem3D::writeGeoObject(outflow.get(),pathname+"/geo/outflow", WbWriterVtkXmlASCII::getInstance());
+         }
+   
+
+         if (refineLevel > 0)
+         {
+		  if(myid == 0) UBLOG(logINFO,"Refinement - start");   
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineCube1, refineLevel);
+    //        refineHelper.addGbObject(refineCube3, 2);
+			 //refineHelper.addGbObject(refineCube2, 3);
+			 //refineHelper.addGbObject(refineCube4, 4);
+			 //
+			 //refineHelper.addGbObject(refineCubeInlet, 1);
+			 //refineHelper.addGbObject(refineCubeOutlet, 1);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");   
+		 
+		 
+           // RefineCrossAndInsideGbObjectBlockVisitor refVisitor1(refineCube1, refineLevel-4);
+            // grid->accept(refVisitor1);
+
+			// RefineCrossAndInsideGbObjectBlockVisitor refVisitor3(refineCube3, refineLevel-3);
+            // grid->accept(refVisitor3);
+
+            // RefineCrossAndInsideGbObjectBlockVisitor refVisitor2(refineCube2, refineLevel-2);
+            // grid->accept(refVisitor2);
+			
+			 // RefineCrossAndInsideGbObjectBlockVisitor refVisitor4(refineCube4, refineLevel-1);
+            // grid->accept(refVisitor4);
+
+            // RatioBlockVisitor ratioVisitor(refineLevel);
+            // grid->accept(ratioVisitor);
+
+            // RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+            // grid->accept(ratioSmoothVisitor);
+
+            // OverlapBlockVisitor overlapVisitor(refineLevel);
+            // grid->accept(overlapVisitor);
+
+            // std::vector<int> dirs;
+            // D3Q27System::getLBMDirections(dirs);
+            // SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+            // grid->accept(interDirsVisitor);
+            // if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //INTERAKTOREN SETZEN (=Randbedingungen)
+         //////////////////////////////////////////////////////////////////////////
+         //oben/unten = Haftrand
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+         geoInt = D3Q27TriFaceMeshInteractorPtr( new D3Q27TriFaceMeshInteractor(geo, grid, D3Q27BoundaryConditionAdapterPtr(new D3Q27NoSlipBCAdapter(bbOption)),Interactor3D::INVERSESOLID, Interactor3D::SIMPLE));
+	     geoInt->setUseHalfSpaceCheck(true);
+         geoInt->setRegardPointInObjectTest(true);
+         if(myid == 0) UBLOG(logINFO,"stl - end"); 
+         //D3Q27InteractorPtr plate1Int(new D3Q27Interactor(plate1, grid, bcObst,Interactor3D::INVERSESOLID));
+         // D3Q27InteractorPtr plate2Int(new D3Q27Interactor(plate2, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate3Int(new D3Q27Interactor(plate3, grid, bcObst,Interactor3D::SOLID));
+
+         // D3Q27InteractorPtr plate1_1Int(new D3Q27Interactor(plate1_1, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_2Int(new D3Q27Interactor(plate1_2, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_3Int(new D3Q27Interactor(plate1_3, grid, bcObst,Interactor3D::SOLID));
+         // D3Q27InteractorPtr plate1_4Int(new D3Q27Interactor(plate1_4, grid, bcObst,Interactor3D::SOLID));
+
+         //links: geschwindigkeits-einfluss
+         //Velocity-BC
+         //////////////////////////////////////////////////////////////////////////
+         mu::Parser fct;
+         fct.DefineConst("vx1"  , vLB*9.0/4.0 );
+         //fct = MathUtil::getDuctParaboloidX(0, 250*2.0, -51.08/2, 51.08, vLB*9.0/4.0);
+         fct.SetExpr("vx1");
+         //////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////////
+             D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter (false, false ,true ,fct, 0, D3Q27BCFunction::INFCONST));
+    //     D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter (false, false ,true ,fct,fct,fct, 0, D3Q27BCFunction::INFCONST));
+			 // velBCAdapter->setSecondaryBcOption(2);
+            // D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+		 D3Q27BoundaryConditionAdapterPtr denBCAdapterInlet(new D3Q27DensityBCAdapter(3.0*(dp_lb-rhoLB)));
+        denBCAdapterInlet->setSecondaryBcOption(1);
+        D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr( new D3Q27Interactor(inflow, grid, denBCAdapterInlet,Interactor3D::SOLID));
+		 
+         //rechts: druckrand
+         //Density-BC
+         //fuer Kompressibles Modell  rho = 1.0
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         denBCAdapter->setSecondaryBcOption(1);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(outflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+         
+      //   BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+        // if(myid == 0) ppblocks->update(0);
+         
+         SolidBlocksHelper sd(grid, comm);
+         sd.addInteractor(geoInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+         // sd.addInteractor(plate1_1Int);
+         // sd.addInteractor(plate1_2Int);
+         // sd.addInteractor(plate1_3Int);
+         // sd.addInteractor(plate1_4Int);
+         // sd.addInteractor(plate2Int);
+         // sd.addInteractor(plate3Int);
+		   if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         sd.deleteSolidBlocks();     
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         grid->accept( metisVisitor );
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__);
+
+         sd.setTransBlocks();
+         if(myid == 0) UBLOG(logINFO,"line"<<__LINE__);
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         if(myid == 0) ppblocks->update(0);
+         if(myid == 0) ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod_temp = nob * (nodePerBlockX1+gl) * (nodePerBlockX2+gl) * (nodePerBlockX3+gl);
+         unsigned long nod = nob * (nodePerBlockX1) * (nodePerBlockX2) * (nodePerBlockX3);
+         double needMemAll  = double(nod_temp*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }  
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX2));
+
+		
+		  int option = 0;
+		// LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3,option));
+		  LBMKernel3DPtr kernel;
+		kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3, LBMKernelETD3Q27CCLB::MAGIC));
+		//  
+		// kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(nodePerBlockX1, nodePerBlockX2, nodePerBlockX3, 1));
+		 
+		 
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+		 
+		  if(myid == 0) UBLOG(logINFO,"intractor - start"); 
+          //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+         //canal
+         grid->addAndInitInteractor(geoInt);
+         // grid->addAndInitInteractor(plate1_1Int);
+         // grid->addAndInitInteractor(plate1_2Int);
+         // grid->addAndInitInteractor(plate1_3Int);
+         // grid->addAndInitInteractor(plate1_4Int);
+         // grid->addAndInitInteractor(plate2Int);
+         // grid->addAndInitInteractor(plate3Int);
+
+       
+
+         //////////////////////////////////////////////////////////////////////////
+         //connectoren setzen:
+
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         //////////////////////////////////////////////////////////////////////////	 
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+			 
+         //////////////////////////////////////////////////////////////////////////     
+	   //Stroemungsfeld initialisieren
+         //////////////////////////////////////////////////////////////////////////
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB); //1.0
+         initVisitor.setVx1(0); 
+		   initVisitor.setVx1(0); 
+
+         grid->accept(initVisitor);
+
+         if(myid == 0)
+         {
+            //Abstände "q" als Linien rausschreiben
+            std::vector< UbTupleFloat3 > nodes;
+            std::vector< UbTupleInt2 >   lines;
+            geoInt->addQsLineSet(nodes, lines);
+            WbWriterVtkXmlBinary::getInstance()->writeLines(pathname+"/grid/qs",nodes,lines);
+         }
+
+          if(myid == 0) UBLOG(logINFO,"Preprozess - end");
+		 
+		 	  ////////////////////////
+           //Set Postprozessors
+           //////////////////////////////////////////////////////////////////////////
+           {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            D3Q27MacroscopicQuantitiesPostprocessor ppgeo(grid,geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv,  comm, true);
+            grid->doPostProcess(0);
+           }
+	    
+
+      }
+
+      //////////////////////////////////////////////////////////////////////////
+	   // UbSchedulerPtr visSchAv(new UbScheduler());
+		UbSchedulerPtr visSchAv(new UbScheduler(100,100));
+      // visSchAv->addSchedule(100,10,1000);
+      // UbSchedulerPtr resSchAv(new UbScheduler());
+	   UbSchedulerPtr resSchAv(new UbScheduler(100,100));
+      // resSchAv->addSchedule(20,20,1000);
+      AverageValuesPostprocessor       Avpp(grid,  pathname + "/Turbulence/stepAV", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm);
+	  
+	   D3Q27ShearStressPostprocessor  shear(grid,  pathname + "/shear/step", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm,iProcessor); 
+	   //D3Q27ShearStressPostprocessor  shear(grid,  pathname + "/shear/step", WbWriterVtkXmlBinary::getInstance(), visSchAv/*wann wird rausgeschrieben*/,resSchAv/*wann wird resettet*/,comm);
+	   shear.addInteractor(geoInt);
+	   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	  
+
+      UbSchedulerPtr nupsSch(new UbScheduler(1, 5, 10));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double outTime = 100.0;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid,stepSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv,  comm);
+      //////////////////////////////////////////////////////////////////////////
+      //PathLine
+       UbSchedulerPtr plSch(new UbScheduler(5000, 5000));
+      const int numberofparticle=20;
+	
+	  std::vector<UbTupleDouble3 > potisions;
+	  double randomx[numberofparticle];
+	  double randomy[numberofparticle];
+	  double randomz[numberofparticle];
+	  double lowestx,highestx,lowesty,highesty,lowestz,highestz;
+	  if(myid==0)
+	  {
+		  for(int i = 0; i < numberofparticle; i++)
+		  {
+			  double random; 
+	        lowestx =-10300.0;  lowesty =-230;          lowestz =-250;
+	        highestx=-9792.0;  highesty=-330;          highestz=-250; 
+		  
+	      double rangex=(highestx-lowestx),rangey=(highesty-lowesty),rangez=(highestz-lowestz);	
+           randomx[i] = lowestx+(rangex*rand()/(RAND_MAX + 1.0));
+		   randomy[i] = lowesty+(rangey*rand()/(RAND_MAX + 1.0));
+	       randomz[i] = lowestz+(rangez*rand()/(RAND_MAX + 1.0));
+		  //val<1>(potisions[i])= 0.506983973456;
+		  //val<2>(potisions[i]) = lowesty+(rangey*rand()/(RAND_MAX + 1.0));
+		   //val<3>(potisions[i]) = lowestz+(rangez*rand()/(RAND_MAX + 1.0));
+		  }
+		  for (int i=0;i<comm->getNumberOfProcesses();i++)
+		  {
+			  if (i!=0)
+			  {
+			      MPI_Send(randomx,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+				  MPI_Send(randomy,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+				  MPI_Send(randomz,numberofparticle, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+			  }
+		  }
+	  }
+	  if (myid!=0)
+	  {
+		  MPI_Status status; 
+		  MPI_Recv(randomx,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+		  MPI_Recv(randomy,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+		  MPI_Recv(randomz,numberofparticle, MPI_DOUBLE_PRECISION,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+	  }
+	  for(int i = 0; i < numberofparticle; i++)
+	  {	
+		  potisions.push_back( makeUbTuple(randomx[i],randomy[i],randomz[i]) );
+		  //val<1>(potisions[i])= 0.506983973456;
+		  //val<2>(potisions[i]) = randomy[i];
+		  //val<3>(potisions[i]) = randomz[i];
+	  }
+	 //  UBLOG(logINFO,"Rank="<<myid<<" positions  = " <<val<1>(potisions)<< " "<<val<2>(potisions)<<" "<< val<3>(potisions));
+	 // D3Q27InterpolationProcessorPtr iProcessor2;
+     // D3Q27PathLinePostprocessorMcpart pathLine(grid, pathname + "/pathLine/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm,potisions, nueLB, iProcessor);
+      //////////////////////////////////////////////////////////////////////////
+      //Simulation
+      //////////////////////////////////////////////////////////////////////////
+
+	  double endTime = 1000.0;
+      UbSchedulerPtr visSch(stepSch);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
\ No newline at end of file
diff --git a/source/Applications/micropart/setup.txt b/source/Applications/micropart/setup.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d0e1e18ff1c94ed14246706de31dd59f3fdc7f14
--- /dev/null
+++ b/source/Applications/micropart/setup.txt
@@ -0,0 +1,5 @@
+pathname = "/work/koskuche/scratch/micropart2";
+blocknx = 16
+double dx = 0.0134*0.5;
+LBMReal nueLB = 0.0000249*2.0;
+double outTime = 2000;
\ No newline at end of file
diff --git a/source/Applications/mpi_benchmark/CMakeLists.txt b/source/Applications/mpi_benchmark/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7869ef7ee5cbb89cda184225b1b2005fbec727ea
--- /dev/null
+++ b/source/Applications/mpi_benchmark/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(sscaling)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(sscaling BINARY)
diff --git a/source/Applications/mpi_benchmark/sscaling.cpp b/source/Applications/mpi_benchmark/sscaling.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7780ad75a6a50af98647dafb0148e820731ab73c
--- /dev/null
+++ b/source/Applications/mpi_benchmark/sscaling.cpp
@@ -0,0 +1,207 @@
+#include <iostream>
+#include <string>
+
+#include "vfluids.h"
+
+using namespace std;
+
+int main(int argc, char* argv[])
+{
+   //// Initialize the MPI environment
+   //MPI_Init(NULL, NULL);
+
+   //// Get the number of processes
+   //int world_size;
+   //MPI_Comm_size(MPI_COMM_WORLD, &world_size);
+
+   //// Get the rank of the process
+   //int world_rank;
+   //MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
+
+   //// Get the name of the processor
+   //char processor_name[MPI_MAX_PROCESSOR_NAME];
+   //int name_len;
+   //MPI_Get_processor_name(processor_name, &name_len);
+
+   //// Print off a hello world message
+   //printf("Hello world from processor %s, rank %d"
+   //   " out of %d processors\n",
+   //   processor_name, world_rank, world_size);
+
+   //// Finalize the MPI environment.
+   //MPI_Finalize();
+
+   //Sleep(30000);
+
+   CommunicatorPtr comm = MPICommunicator::getInstance();
+   int myid = comm->getProcessID();
+   
+   // Get the name of the processor
+   char machinename[MPI_MAX_PROCESSOR_NAME];
+   int name_len;
+   MPI_Get_processor_name(machinename, &name_len);
+
+   try
+   {
+      double availMem = 1.2e9;
+      int numOfThreads = 1;
+
+      //UbLog::reportingLevel() = UbLog::logLevelFromString("DEBUG5");
+
+      stringstream logFilename;
+      logFilename <<  "logfile_"+UbSystem::toString(machinename)+"_PID_"+UbSystem::toString(myid)+".txt";
+      UbLog::output_policy::setStream(logFilename.str());
+
+      UBLOG(logINFO, "MPI benchmark");
+      UBLOG(logINFO, "1. PID = " << myid << " host name: " << machinename);
+      UBLOG(logINFO, "1. PID = " << myid << " Number of processes = " << comm->getNumberOfProcesses());
+      UBLOG(logINFO, "1. PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem()/1073741824.0<< " GB");
+      UBLOG(logINFO, "1. PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed()/1073741824.0<< " GB");
+      UBLOG(logINFO, "1. PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe()/1073741824.0<< " GB");
+
+      double dx = 1;
+
+      const int blocknx1 = 64;
+      const int blocknx2 = 64;
+      const int blocknx3 = 64;
+
+      int gs = 60; // 30;
+      const int gridNx1 = gs; // *comm->getNumberOfProcesses();
+      const int gridNx2 = gs;
+      const int gridNx3 = gs;
+
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3, H;
+      L2 = L3 = H = gridNx2*blocknx1;
+
+      LBMReal uLB = 0.05;
+      LBMReal Re = 20.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+
+      LBMReal nueLB = 0.05842;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      double blockLength = blocknx1*dx;
+
+      Grid3DPtr grid(new Grid3D(comm, blocknx1, blocknx2, blocknx3, gridNx1, gridNx2, gridNx3));
+      grid->setPeriodicX1(true);
+      grid->setPeriodicX2(true);
+      grid->setPeriodicX3(true);
+
+      UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////");
+      UBLOG(logINFO, "2. PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem()/1073741824.0<< " GB");
+      UBLOG(logINFO, "2. PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed()/1073741824.0<< " GB");
+      UBLOG(logINFO, "2. PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe()/1073741824.0<< " GB");
+      UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////");
+
+      UBLOG(logINFO, "MetisPartitioningGridVisitor:start");
+      MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::BSW);
+      grid->accept(metisVisitor);
+      UBLOG(logINFO, "MetisPartitioningGridVisitor:end");
+
+      //set connectors
+      UBLOG(logINFO, "D3Q27SetConnectorsBlockVisitor:start");
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept(setConnsVisitor);
+      UBLOG(logINFO, "D3Q27SetConnectorsBlockVisitor:end");
+
+      //domain decomposition for threads
+      UBLOG(logINFO, "PQueuePartitioningGridVisitor:start");
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+      UBLOG(logINFO, "PQueuePartitioningGridVisitor:end");
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), ".", WbWriterVtkXmlBinary::getInstance(), comm));
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nodb = (blocknx1)* (blocknx2)* (blocknx3);
+      unsigned long nod = nob * (blocknx1)* (blocknx2)* (blocknx3);
+      unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+      double needMemAll = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+
+      UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////");
+      UBLOG(logINFO, "Setup information:");
+      UBLOG(logINFO, "Number of blocks = " << nob);
+      UBLOG(logINFO, "Number of nodes  = " << nod);
+      int minInitLevel = grid->getCoarsestInitializedLevel();
+      int maxInitLevel = grid->getFinestInitializedLevel();
+      for (int level = minInitLevel; level<=maxInitLevel; level++)
+      {
+         int nobl = grid->getNumberOfBlocks(level);
+         UBLOG(logINFO, "Number of blocks for level " << level <<" = " << nob);
+         UBLOG(logINFO, "Number of nodes for level " << level <<" = " << nob*nodb);
+      }
+      UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////");
+      UBLOG(logINFO, "Necessary memory  = " << needMemAll/1073741824.0  << " GB");
+      UBLOG(logINFO, "Necessary memory per process = " << needMem/1073741824.0  << " GB");
+      UBLOG(logINFO, "Available memory per process = " << availMem/1073741824.0 << " GB");
+      UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////");
+
+
+      LBMKernel3DPtr kernel;
+      kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+      //rhoLB = 1.0;
+      //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+      initVisitor.setVx1(0.0);
+      grid->accept(initVisitor);
+
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      UbSchedulerPtr visSch(new UbScheduler(500, 500));
+
+      double endTime = 100;
+
+      UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////");
+      UBLOG(logINFO, "System information:");
+      UBLOG(logINFO, "Total Physical Memory (RAM): " << Utilities::getTotalPhysMem()/1073741824.0<< " GB");
+      UBLOG(logINFO, "Physical Memory currently used: " << Utilities::getPhysMemUsed()/1073741824.0<<" GB");
+      UBLOG(logINFO, "Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe()/1073741824.0<<" GB");
+      UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////");
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      UBLOG(logINFO, "Simulation-start");
+      calculation->calculate();
+      UBLOG(logINFO, "Simulation-end");
+   }
+   catch (std::exception& e)
+   {
+      cerr << "PID = " << myid << " host name: " << machinename << endl << flush;
+      cerr << e.what() << endl << flush<<
+         boost::current_exception_diagnostic_information();
+   }
+   catch (std::string& s)
+   {
+      cerr << s << endl<<boost::current_exception_diagnostic_information();
+   }
+   catch (...)
+   {
+      cerr << "unknown exception" << endl<<
+         boost::current_exception_diagnostic_information();
+   }
+
+   return 0;
+}
+
+
+
diff --git a/source/Applications/musis/CMakeLists.txt b/source/Applications/musis/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ed82e04c1f63994b4eaf6b18ba2964da0bfdf071
--- /dev/null
+++ b/source/Applications/musis/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(musis)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(musis BINARY)
diff --git a/source/Applications/musis/config.txt b/source/Applications/musis/config.txt
new file mode 100644
index 0000000000000000000000000000000000000000..023b077a150c7535b7afc3a9e09e359b87bea218
--- /dev/null
+++ b/source/Applications/musis/config.txt
@@ -0,0 +1,46 @@
+#number of threads
+numOfThreads = 1
+
+#block dimensions
+blocknx1 = 12
+blocknx2 = 12
+blocknx3 = 12
+
+#grid refinement
+refineLevel = 2
+numBaseBlock_L1 = 1
+
+#physical length
+L1 = 0.07
+L2 = 0.07
+L3 = 0.4169
+
+#material parameter
+nueLB = 0.0016666666667
+
+#Forcing
+ForcingX1 = 1.0e-7
+
+path = "J:/TBL/scratch/C100_DrySampleTest/"
+
+# musis sample
+geoFile = "J:/TBL/TBL_Sw_Geos/C100/C100MulTest.geo.00000000.raw"
+geoDimX1 = 78
+geoDimX2 = 78
+geoDimX3 = 45
+
+#paraview visualization
+outTime = 1.0
+endTime = 7.0
+
+#retart parameters
+restartDump = 3.0
+
+#data measurement
+calcBegin = 500.0
+calcEnd	 = 1000.0
+calcIntervall = 50.0
+
+
+#BGK=0, CLB=1, CCLB=2
+kernel = 2
\ No newline at end of file
diff --git a/source/Applications/musis/musis.cpp b/source/Applications/musis/musis.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..09bb95f862c8df85a389975838032fac417d7f0d
--- /dev/null
+++ b/source/Applications/musis/musis.cpp
@@ -0,0 +1,474 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr1, const char *cstr2)
+{
+   
+   try
+   {
+      ConfigFileReader cf(cstr1);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname = cf.getValue("path"); 
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+      double availMem = 0;
+      string geoFile;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+
+      int d1, d2, d3; // for reading musis sample 
+
+      if(machine == "BOMBADIL") 
+      //if(machine == "YWANG")
+      {
+         //pathname = "J:/TBL/scratch/C100_DrySampleTest/";
+         //geoFile  = "J:/TBL/TBL_Sw_Geos/CS518/TBL_CS518_MulSim02.geo.00000000.raw";
+         pathname = cf.getValue("path"); 
+         geoFile  = cf.getValue("geoFile"); 
+         numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+         
+         availMem = 3.0e9;
+         d1 = UbSystem::stringTo<int>(cf.getValue("geoDimX1"));;
+         d2 = UbSystem::stringTo<int>(cf.getValue("geoDimX2"));;
+         d3 = UbSystem::stringTo<int>(cf.getValue("geoDimX3"));;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         //pathname = "/hpc3lustre/work/wang/TBL/scratch/CS518_DrySampleTest/";
+         //geoFile = "/hpc3lustre/work/wang/TBL/TBL_Sw_Geos/CS518.X2Y2Z1/TBL_CS518_MulSim02.geo.00030000.raw";
+         //numOfThreads = 1;
+         pathname = cf.getValue("path"); 
+         geoFile  = cf.getValue("geoFile"); 
+         numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfThreads"));
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+         d1 = UbSystem::stringTo<int>(cf.getValue("geoDimX1"));;
+         d2 = UbSystem::stringTo<int>(cf.getValue("geoDimX2"));;
+         d3 = UbSystem::stringTo<int>(cf.getValue("geoDimX3"));;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+      
+      const int baseLevel = 0;
+      const int refineLevel = UbSystem::stringTo<int>(cf.getValue("refineLevel"));//2;
+      const int blocknx1    = UbSystem::stringTo<int>(cf.getValue("blocknx1"));//12; 
+      const int blocknx2    = UbSystem::stringTo<int>(cf.getValue("blocknx1"));//12;
+      const int blocknx3    = UbSystem::stringTo<int>(cf.getValue("blocknx1"));//12;
+
+      const int numBaseBlockL1 = UbSystem::stringTo<int>(cf.getValue("numBaseBlock_L1"));//1;
+      ////////////////////////////////////////////////////////////////////////////
+      //// Geometrie
+      ////////////////////////////////////////////////////////////////////////////
+      double L1 = UbSystem::stringTo<double>(cf.getValue("L1"));//0.07; //m
+      double L2 = UbSystem::stringTo<double>(cf.getValue("L2"));//0.07; //m
+      double L3 = UbSystem::stringTo<double>(cf.getValue("L3"));//0.0379 + 0.379; //m
+      double dx = L1/(blocknx1*numBaseBlockL1)/(pow(2.0,refineLevel)); //0.0379/272.0; //m
+
+      LBMReal rhoReal = 1.0; //kg/m^3
+      LBMReal uReal = 5.0;  //m/s
+      LBMReal uLB = 0.1;
+      LBMReal nueLB = UbSystem::stringTo<double>(cf.getValue("nueLB"));//0.00166666666667;
+      LBMReal Re = 0.0;
+      LBMReal rhoLB = 0.0;
+
+      //LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter(1.0, 1/sqrt(3.0)*(uReal/uLB), 1.0, 1.0/dx, dx*dx*dx));
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double offs = 0.0;
+
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+
+      double blockLength = blocknx1 * dx;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setPeriodicX1(true);
+      grid->setPeriodicX2(true);
+      grid->setPeriodicX3(false);
+      grid->setDeltaX(pow(2.0,refineLevel)*dx); // for coarse
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+      double restartDump = UbSystem::stringTo<double>(cf.getValue("restartDump"));
+      UbSchedulerPtr rSch(new UbScheduler(restartDump));
+      RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+      //UbSchedulerPtr emSch(new UbScheduler(1000, 1000));
+      //EmergencyExitPostprocessor em(grid, emSch, pathname+"/checkpoints/emex.txt", rp, comm);
+
+      std::string opt;
+      if(cstr2!= NULL)
+         opt = std::string(cstr2);
+
+      LBMKernel3DPtr kernel;
+      double ForcingX1 = UbSystem::stringTo<double>(cf.getValue("ForcingX1"));
+
+      mu::Parser fctForcingX1;
+      mu::Parser fctForcingX2;
+      mu::Parser fctForcingX3;
+
+      fctForcingX2.SetExpr("0.0");
+      fctForcingX3.SetExpr("0.0");
+      fctForcingX1.SetExpr("c3*(tanh(c1*(x3-c2))+c4)*Fx1*dx");
+      //fctForcingX1.SetExpr("Fx1*dx");
+      fctForcingX1.DefineConst("Fx1", ForcingX1);
+      fctForcingX1.DefineConst("c1", 0.5);       // incline
+      double ForcingLevel = 0.039/dx;
+      fctForcingX1.DefineConst("c2", ForcingLevel); // forcing switch level
+      fctForcingX1.DefineConst("c3", 0.5); // const always
+      fctForcingX1.DefineConst("c4", 1.0); // const always
+      if(myid == 0) UBLOG(logINFO,"Forcing Level = " << ForcingLevel );
+
+      if(cstr2!= NULL)
+      {
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+         grid = rp->restart(UbSystem::stringTo<int>(opt));
+         //rp->reconnect(grid);
+
+         //Forcing setzen falls nötig
+         SetForcingBlockVisitor forcingVisitor(fctForcingX1,fctForcingX2,fctForcingX3);
+         grid->accept(forcingVisitor); 
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         ////domain decomposition //useful if pro mpi processor contains more than 1 thread 
+         //PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         //grid->accept(pqPartVisitor);
+
+         //int option = 0;
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, option));
+
+
+        
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " << L1/dx );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            //UBLOG(logINFO,conv->toString() );
+            UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+            UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         // read musis geometry 
+         //if(myid ==0) UBLOG(logINFO,"Read geometry: start");
+         //GbVoxelMatrix3DPtr vmatrix(new GbVoxelMatrix3D(d1, d2, d3, float(GbVoxelMatrix3D::FLUID),8.0,8.0)); 
+
+         //vmatrix->readMatrixFromRawFile<char>(geoFile);
+         //if(myid ==0) UBLOG(logINFO,"Read geometry: end");
+
+         //vmatrix->setVoxelMatrixDelta(L1/(d1-1),L1/(d1-1),L1/(d1-1));
+
+         //if(myid ==0) UBLOG(logINFO,"Write geometry: start");
+         //if(myid == 0) vmatrix->writeToLegacyVTK(pathname+"/geo/geo");
+         //if(myid ==0) UBLOG(logINFO,"Write geometry: end");
+         
+         // domain
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+
+         //refinement area
+         GbObject3DPtr refineCube1(new  GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3+8.0*0.0379));
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube1.get(),pathname + "/geo/refineCube1", WbWriterVtkXmlBinary::getInstance());
+         GbObject3DPtr refineCube2(new  GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3+4.0*0.0379));
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube2.get(),pathname + "/geo/refineCube2", WbWriterVtkXmlBinary::getInstance());
+
+         // walls
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+         
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");   
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineCube1, refineLevel-1);
+            refineHelper.addGbObject(refineCube2, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");   
+         }
+         
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bc_noslip(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27BoundaryConditionAdapterPtr bc_slip(new D3Q27SlipBCAdapter(bbOption));
+         // porous geometry
+         //D3Q27InteractorPtr geoInt = D3Q27InteractorPtr ( new D3Q27Interactor(vmatrix, grid, bc_noslip,Interactor3D::SOLID));
+
+         //mu::Parser fct; 
+         //fct.DefineConst("U", uLB);//Vx
+         //fct.SetExpr("U"); 
+         
+         //D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST)); 
+
+         //walls
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bc_noslip,Interactor3D::SOLID));
+         ////up velocity
+         //D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, velBCAdapter,Interactor3D::SOLID)); 
+         //up slip
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bc_slip  ,Interactor3D::SOLID));
+         
+         //sd.addInteractor(geoInt);
+         sd.addInteractor(addWallZminInt);
+         sd.addInteractor(addWallZmaxInt);
+      
+         sd.deleteSolidBlocks();
+
+         grid->accept( metisVisitor );
+
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1) * (blocknx2) * (blocknx3);
+         unsigned long nod = nob * (blocknx1) * (blocknx2) * (blocknx3);
+         unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for(int level = minInitLevel; level<=maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nobl);
+               UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nobl*nodb);
+            }
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+
+         }            
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+         //option = 0 - ohne param., option = 1 - mit param.
+         //int option = 0;
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, option));
+         
+
+         int kernelType = UbSystem::stringTo<int>(cf.getValue("kernel"));
+         LBMKernel3DPtr kernel;
+         if (kernelType == 0)
+         {
+            rhoLB = 1.0;
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+         }
+         else if (kernelType == 1)
+         {
+            rhoLB = 1.0;
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+         }
+         else if (kernelType == 2)
+         {
+            rhoLB = 0.0;
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, 0));
+            //kernel = LBMKernel3DPtr(new LBMKernelESD3Q27CCLB(blocknx1, blocknx2, blocknx3, grid));
+            //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBex(blocknx1, blocknx2, blocknx3, 0, grid));
+         }
+         
+         kernel->setForcingX1(fctForcingX1);
+         kernel->setForcingX2(fctForcingX2);
+         kernel->setForcingX3(fctForcingX3);
+         kernel->setWithForcing(true);
+         
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         mu::Parser fctnueLB;
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+      //   //walls
+         grid->addAndInitInteractor(addWallZminInt);
+         grid->addAndInitInteractor(addWallZmaxInt);
+         // porous geometry
+         //grid->addAndInitInteractor(geoInt);
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB);
+         //initVisitor.setVx1(0.0);
+         grid->accept(initVisitor);
+
+         ////Postrozess - Measurement
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         //if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+      
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double calcBegin = UbSystem::stringTo<double>(cf.getValue("calcBegin"));//0.07; //m
+      double calcEnd = UbSystem::stringTo<double>(cf.getValue("calcEnd"));//0.07; //m
+      double calcIntervall = UbSystem::stringTo<double>(cf.getValue("calcIntervall"));//0.0379 + 0.379; //m
+      
+      /*UbSchedulerPtr TBL_Sch(new UbScheduler(calcIntervall,calcBegin,calcEnd));
+      UbSchedulerPtr TBL_rSch(new UbScheduler(100000));
+      TurbulentStrengthSurfaceRoughnessPostprocessor TBLpp(grid,pathname +"/results/TBL", TBL_Sch,TBL_rSch,comm);
+      */
+
+      double outTime = UbSystem::stringTo<double>(cf.getValue("outTime"));
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname + "/steps/step", WbWriterVtkXmlASCII::getInstance(), conv, comm);
+
+      double fdx = grid->getDeltaX(grid->getFinestInitializedLevel());
+
+      //D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+      //   g_minX1, g_minX2, g_minX3, 
+      //   g_minX1+1.0*fdx, g_maxX2, g_maxX3));
+      ////if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      //D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+      //   g_maxX1-1.0*fdx, g_minX2, g_minX3, 
+      //   g_maxX1, g_maxX2, g_maxX3));
+      ////if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      //LBMReal rhoReal = rhoLB;
+      //LBMReal uReal = uLB; 
+      //D3Q27PressureDifferencePostprocessor rhopp(grid, stepSch, pathname + "/results/rho_diff.txt", h1, h2, rhoReal, uReal, uLB, comm);
+
+      //UbSchedulerPtr resSch(new UbScheduler(1000,10000,10000));
+      //UbSchedulerPtr visSch(new UbScheduler(1,0,1));         
+      //AverageValuesPostprocessor TBLpp(grid, pathname + "/results/AvVelocity", WbWriterVtkXmlBinary::getInstance(), visSch, resSch, comm); 
+
+
+      double endTime = UbSystem::stringTo<double>(cf.getValue("endTime"));;//10001.0;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+      //
+      //double point1[3] = {0.45, 0.20, 0.205};
+      //double point2[3] = {0.55, 0.20, 0.205};
+      //D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+      //   point1[0]-1.0*fdx, point1[1]-1.0*fdx, point1[2]-1.0*fdx, 
+      //   point1[0], point1[1], point1[2]));
+      //if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      //D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+      //   point2[0], point2[1]-1.0*fdx, point2[2]-1.0*fdx, 
+      //   point2[0]+1.0*fdx, point2[1], point2[2]));
+      //if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      ////D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, conv, comm);
+      //D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, rhoReal, uReal, uLB, comm);
+      //
+      //double area = 2.0*radius*H;
+      //double v    = 4.0*uLB/9.0;
+      //D3Q27ForcesPostprocessor fp(grid, visSch, pathname + "/results/forces.txt", comm, rhoLB, v, area, D3Q27ForcesPostprocessor::X, D3Q27ForcesPostprocessor::Y);
+      //fp.addInteractor(cylinderInt);
+      //
+      //UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 40));
+      //NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      //double endTime = 40001.0;
+      //CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      //if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      //calculation->calculate();
+      //if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+   if ( argv != NULL )
+   {
+      if (argc > 1)
+      {
+         run(argv[1], argv[2]);
+      }
+      else
+      {
+         cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+      }
+   }
+
+   return 0;
+ 
+}
+
+
+
+
diff --git a/source/Applications/pChannel/CMakeLists.txt b/source/Applications/pChannel/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..81ea739ecd58e2b018caa808bac8d8bc6909dfbb
--- /dev/null
+++ b/source/Applications/pChannel/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(pchannel)
+
+INCLUDE(${SOURCE_ROOT}/IncludsList.cmake) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES VirtualFluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(pchannel BINARY)
diff --git a/source/Applications/pChannel/configBombadilpChannel.cfg b/source/Applications/pChannel/configBombadilpChannel.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..f4dff5a18d62f83d0d60e2bde37796bb3fa2ead6
--- /dev/null
+++ b/source/Applications/pChannel/configBombadilpChannel.cfg
@@ -0,0 +1,93 @@
+#
+#Simulation parameters for porous channel
+#
+
+pathname = d:/temp/pChannel
+pathGeo = d:/Projects/SFB880/GeometrienPoroeseMedien/PA80-110
+numOfThreads = 4
+availMem = 4e9
+logToFile = false
+
+#porous media
+#rawFile = false
+sampleFilename = PA80-110_275x267x254_1mm.vti  
+#writeSample = true
+
+rawFile = false
+#sampleFilename = PA80-110_1096x1327x1265.raw
+#sampleFilename = PA80-110_1096x1327x423.vti
+#sampleFilename = PA80-110_1096x1327x216.vti  
+#sampleFilename = PA80-110_1096x1327x303.vti  
+writeSample = false
+
+#diminsions [voxel]
+pmNX = 275 267 254
+#pmNX = 1096  1327  1265
+#pmNX = 1096 1327 216
+
+#threshold
+lthreshold = 29041
+uthreshold = 65535
+
+#deltas
+voxelDeltaX = 3.6496350365e-6 3.76789751319e-6 3.95256916996e-6
+
+#diminsions [m]
+#pmL = 7.299270073e-4 7.53579502638e-4 7.90513833992e-4
+
+#grid
+# deltax = 0.0000144
+# blocknx = 32 20 20
+
+#diminsions [m]
+#pmL = 4e-3 5e-3 5e-3
+#pmL = 4e-3 5e-3 1.67e-3
+#pmL = 4e-3 5e-3 0.85e-3
+
+#letzte
+#pmL = 4e-3 5e-3 1.19e-3
+
+#pmL = 4e-3 0.5e-3 1e-3
+
+pmL = 1e-3 1e-3 1e-3
+
+#grid
+refineLevel = 1
+#refineLevel = 1
+#refineLevel = 0 
+#deltaXfine  = 3.6496350365e-5
+deltaXfine  = 20e-6
+# x10
+#deltaXfine  = 1.4598540146e-5# x4
+#3deltaXfine = 3.6496350365e-6
+#deltaXfine = 3.95e-6
+#deltaXfine = 8.0e-6
+blocknx = 10 10 10
+#blocknx = 32 40 20
+lengthFactor = 4
+thinWall = true
+forcing = 1e-6
+changeQs = false
+
+channelHigh = 0.002
+
+#DLR-F15
+#channelHigh = 0.017
+#NACA 0012
+#channelHigh = 0.008
+ 
+#channelHigh = 0.005
+ 
+#physic
+# for DLRF-15 Re = 102000/2
+Re = 51000
+#real velocity is 54.95 m/s
+u_LB = 0.1
+
+restartStep = 200000
+restartStepStart=200000
+
+endTime = 200000
+outTime = 1000
+ 
+
diff --git a/source/Applications/pChannel/configHLRNpChannel.cfg b/source/Applications/pChannel/configHLRNpChannel.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..1f5ee170c92212eb947dab3c675a9c6909bf6370
--- /dev/null
+++ b/source/Applications/pChannel/configHLRNpChannel.cfg
@@ -0,0 +1,54 @@
+#
+#Simulation parameters for porous channel
+#
+
+pathname = /gfs2/work/niikonst/scratch/pChannel2
+pathGeo = /gfs1/work/niikonst/data/materials
+numOfThreads = 24
+availMem = 128e9
+logToFile = true
+
+#porous media
+rawFile = false
+#sampleFilename = /PA80-110_1096x1327x1265.raw  
+sampleFilename = PA80-110_1096x1327x303.vti  
+writeSample = false
+
+#diminsions [voxel]
+#pmNX = 1096  1327  1265
+pmNX = 1096  1327  303
+
+#threshold
+lthreshold = 29041
+uthreshold = 65535
+
+#deltas
+voxelDeltaX = 3.6496350365e-6 3.76789751319e-6 3.95256916996e-6
+
+#diminsions [m]
+#pmL = 4e-3 5e-3 5e-3
+pmL = 4e-3 5e-3 1.19e-3
+
+#grid
+refineLevel = 2
+deltaXfine = 8.0e-6
+blocknx = 32 40 20
+lengthFactor = 2
+thinWall = true
+
+#DLR-F15
+channelHigh = 0.017
+
+#physic
+# for DLRF-15 Re = 102000/2
+Re = 51000
+#real velocity is 54.95 m/s
+u_LB = 0.1
+
+restartStep = 10000
+restartStepStart=10000
+
+endTime = 80000
+outTime = 10000
+
+
diff --git a/source/Applications/pChannel/configLudwigpChannel.cfg b/source/Applications/pChannel/configLudwigpChannel.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..784c4a65cdf3e6c790aa989bfbc4f405292016b8
--- /dev/null
+++ b/source/Applications/pChannel/configLudwigpChannel.cfg
@@ -0,0 +1,53 @@
+#
+#Simulation parameters for porous channel
+#
+
+pathname = /hpc3lustre/work/koskuche/SFB880/pChannel
+pathGeo = /hpc3lustre/work/koskuche/SFB880/Materials/PA80-110
+numOfThreads = 8
+availMem = 11e9
+logToFile = true
+
+#porous media
+rawFile = false
+#sampleFilename = /PA80-110_1096x1327x1265.raw  
+sampleFilename = PA80-110_1096x1327x303.vti  
+writeSample = false
+
+#diminsions [voxel]
+#pmNX = 1096  1327  1265
+pmNX = 1096  1327  303
+
+#threshold
+lthreshold = 29041
+uthreshold = 65535
+
+#deltas
+voxelDeltaX = 3.6496350365e-6 3.76789751319e-6 3.95256916996e-6
+
+#diminsions [m]
+#pmL = 4e-3 5e-3 5e-3
+pmL = 4e-3 5e-3 1.19e-3
+
+#grid
+refineLevel = 2
+deltaXfine = 8.0e-6
+blocknx = 32 40 20
+lengthFactor = 2
+thinWall = true
+
+#DLR-F15
+channelHigh = 0.017
+
+#physic
+# for DLRF-15 Re = 102000/2
+Re = 51000
+#real velocity is 54.95 m/s
+u_LB = 0.1
+
+restartStep = 10000
+restartStepStart=10000
+
+endTime = 80000
+outTime = 10000
+
diff --git a/source/Applications/pChannel/pChannel.cpp b/source/Applications/pChannel/pChannel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..69b7392ee95123813e8cefa82f633bed6e92f37e
--- /dev/null
+++ b/source/Applications/pChannel/pChannel.cpp
@@ -0,0 +1,571 @@
+#include <iostream>
+#include <string>
+#include "VirtualFluids.h"
+
+
+
+//#include <thread>
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////
+void run(string configname)
+{
+   try
+   {
+      ConfigurationFile   config;
+      config.load(configname);
+
+      string          pathname          = config.getString("pathname");
+      string          pathGeo           = config.getString("pathGeo");
+      int             numOfThreads      = config.getInt("numOfThreads");
+      string          sampleFilename    = config.getString("sampleFilename");
+      vector<int>     pmNX              = config.getVector<int>("pmNX");
+      double          lthreshold        = config.getDouble("lthreshold");
+      double          uthreshold        = config.getDouble("uthreshold");
+      vector<float>   voxelDeltaX       = config.getVector<float>("voxelDeltaX");
+      vector<int>     blocknx           = config.getVector<int>("blocknx");
+      double          u_LB              = config.getDouble("u_LB");
+      double          restartStep       = config.getDouble("restartStep");
+      double          restartStepStart  = config.getDouble("restartStepStart");
+      double          endTime           = config.getDouble("endTime");
+      double          outTime           = config.getDouble("outTime");
+      double          availMem          = config.getDouble("availMem");
+      bool            rawFile           = config.getBool("rawFile");
+      bool            logToFile         = config.getBool("logToFile");
+      bool            writeSample       = config.getBool("writeSample");
+      vector<double>  pmL               = config.getVector<double>("pmL");
+      double          deltaXfine        = config.getDouble("deltaXfine");
+      int             refineLevel       = config.getInt("refineLevel");
+      bool            thinWall          = config.getBool("thinWall");
+      double          Re                = config.getDouble("Re");
+      double          channelHigh       = config.getDouble("channelHigh");
+      double          lengthFactor      = config.getDouble("lengthFactor");
+      double          forcing           = config.getDouble("forcing");
+      bool            changeQs          = config.getBool("changeQs"); 
+      double          timeAvStart       = config.getDouble("timeAvStart");
+      double          timeAvStop        = config.getDouble("timeAvStop");
+
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if (logToFile)
+      {
+#if defined(__unix__)
+         if (myid == 0)
+         {
+            const char* str = pathname.c_str();
+            mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+         }
+#endif 
+
+         if (myid == 0)
+         {
+            stringstream logFilename;
+            logFilename << pathname + "/logfile" + UbSystem::toString(UbSystem::getTimeStamp()) + ".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+
+      //Sleep(30000);
+
+      if (myid == 0) UBLOG(logINFO, "Testcase porous channel");
+
+      LBMReal rho_LB = 0.0;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      double deltaXcoarse = deltaXfine*(double)(1<<refineLevel);
+
+      double coord[6];
+      bool restart;
+
+      vector<double> origin(3);
+      origin[0] = 0;
+      origin[1] = 0;
+      origin[2] = 0;
+
+      //real velocity is 49.63 m/s
+      double nu_LB;
+
+      BoundaryConditionProcessorPtr bcProcessor(new BoundaryConditionProcessor());
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(restartStep, restartStepStart));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::TXT);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+         if (myid == 0) UBLOG(logINFO, "new start...");
+         restart = false;
+
+         double offsetMinX3 = pmL[2];
+         
+         double offsetMaxX1 = pmL[0]*lengthFactor;
+         double offsetMaxX2 = pmL[1]*2.0;
+         double offsetMaxX3 = pmL[2] + channelHigh; //DLR-F15  //pmL[2]*2.0;
+
+         //bounding box
+         double g_minX1 = origin[0];
+         double g_minX2 = origin[1];
+         double g_minX3 = origin[2];
+
+         double g_maxX1 = origin[0] + offsetMaxX1;
+         double g_maxX2 = origin[1] + offsetMaxX2;
+         double g_maxX3 = origin[2] + offsetMaxX3;
+//////////////////////////////////////////////////////////////////////////
+         double nx1_temp = floor((g_maxX1-g_minX1) /(deltaXcoarse*(double)blocknx[0]));
+
+         deltaXcoarse = (g_maxX1-g_minX1) /(nx1_temp*(double)blocknx[0]);
+
+         g_maxX1 -= 0.5* deltaXcoarse;
+//////////////////////////////////////////////////////////////////////////
+         double blockLength = (double)blocknx[0]*deltaXcoarse;
+
+         grid->setPeriodicX1(true);
+         grid->setPeriodicX2(true);
+         grid->setPeriodicX3(false);
+         grid->setDeltaX(deltaXcoarse);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+         double channel_high = channelHigh; // g_maxX3-g_minX3;
+         double channel_high_LB = channel_high/deltaXcoarse;
+//////////////////////////////////////////////////////////////////////////
+         //nu_LB = 0.005;
+         nu_LB = (u_LB*channel_high_LB)/Re;
+//////////////////////////////////////////////////////////////////////////
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Parameters:");
+            UBLOG(logINFO, "Re = " << Re);
+            UBLOG(logINFO, "u_LB = " << u_LB);
+            UBLOG(logINFO, "rho_LB = " << rho_LB);
+            UBLOG(logINFO, "nu_LB = " << nu_LB);
+            UBLOG(logINFO, "dx coarse = " << deltaXcoarse << " m");
+            UBLOG(logINFO, "dx fine = " << grid->getDeltaX(refineLevel) << " m");
+            UBLOG(logINFO, "number of levels = " << refineLevel + 1);
+            UBLOG(logINFO, "number of processes = " << comm->getNumberOfProcesses());
+            UBLOG(logINFO, "number of threads = " << numOfThreads);
+            UBLOG(logINFO, "path = " << pathname);
+            UBLOG(logINFO, "Preprocess - start");
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //refinement
+         double blockLengthX3Fine = grid->getDeltaX(refineLevel) * blocknx[2];
+
+         GbCuboid3DPtr refineBoxTop(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3-blockLengthX3Fine, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(refineBoxTop.get(), pathname + "/geo/refineBoxTop", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr refineBoxBottom(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3+offsetMinX3+blockLengthX3Fine));
+         //GbCuboid3DPtr refineBoxBottom(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLengthX3Fine, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3+blockLengthX3Fine));
+         if (myid == 0) GbSystem3D::writeGeoObject(refineBoxBottom.get(), pathname + "/geo/refineBoxBottom", WbWriterVtkXmlASCII::getInstance());
+
+         if (refineLevel > 0)
+         {
+            if (myid == 0) UBLOG(logINFO, "Refinement - start");
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineBoxTop, refineLevel);
+            refineHelper.addGbObject(refineBoxBottom, refineLevel);
+            refineHelper.refine();
+            if (myid == 0) UBLOG(logINFO, "Refinement - end");
+         }
+         //////////////////////////////////////////////////////////////////////////
+
+         //walls
+         GbCuboid3DPtr addWallZmin(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+
+         //wall interactors
+         int bbOption = 1;
+         D3Q27BoundaryConditionAdapterPtr bcNoSlip(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcNoSlip, Interactor3D::SOLID));
+
+		 ////////////////////////////////////////////////
+		 //TEST
+		 //GbObject3DPtr testCube(new GbCuboid3D(g_minX1 + 2.0 * blockLength, g_minX2 + 2.0 * blockLength, g_minX3 + 5.0 * blockLength, 
+			// g_minX1 + 3.0 * blockLength, g_minX2 + 3.0 * blockLength, g_minX3 + 6.0 * blockLength));
+		 //if (myid == 0) GbSystem3D::writeGeoObject(testCube.get(), pathname + "/geo/testCube", WbWriterVtkXmlBinary::getInstance());
+		 //D3Q27InteractorPtr testCubeInt(new D3Q27Interactor(testCube, grid, bcNoSlip, Interactor3D::SOLID));
+		 ///////////////////////////////////////////////
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::BSW, MetisPartitioner::KWAY));
+         ////////////////////////////////////////////
+         //Zoltan
+         //Grid3DVisitorPtr zoltanVisitor(new ZoltanPartitioningGridVisitor(comm, D3Q27System::BSW, 1));
+         //grid->accept(zoltanVisitor);
+         /////delete solid blocks
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallZmaxInt);
+		 //////////////////////////////////////////////////////////////////////////
+		 //TEST
+		 //intHelper.addInteractor(testCubeInt);
+         //////////////////////////////////////////////////////////////////////////
+		 intHelper.selectBlocks();
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - end");
+         //////////////////////////////////////
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long long numberOfBlocks = (unsigned long long)grid->getNumberOfBlocks();
+         int ghostLayer = 3;
+         unsigned long long numberOfNodesPerBlock = (unsigned long long)(blocknx[0])* (unsigned long long)(blocknx[1])* (unsigned long long)(blocknx[2]);
+         unsigned long long numberOfNodes = numberOfBlocks * numberOfNodesPerBlock;
+         unsigned long long numberOfNodesPerBlockWithGhostLayer = numberOfBlocks * (blocknx[0] + ghostLayer) * (blocknx[1] + ghostLayer) * (blocknx[2] + ghostLayer);
+         double needMemAll = double(numberOfNodesPerBlockWithGhostLayer*(27 * sizeof(double) + sizeof(int) + sizeof(float) * 4));
+         double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Number of blocks = " << numberOfBlocks);
+            UBLOG(logINFO, "Number of nodes  = " << numberOfNodes);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for (int level = minInitLevel; level <= maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO, "Number of blocks for level " << level << " = " << nobl);
+               UBLOG(logINFO, "Number of nodes for level " << level << " = " << nobl*numberOfNodesPerBlock);
+            }
+            UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+            UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+            UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+         mu::Parser fctForcingX1;
+         fctForcingX1.SetExpr("Fx1");
+         fctForcingX1.DefineConst("Fx1", 1.0e-6);
+
+         kernel->setWithForcing(true);
+
+         BCProcessorPtr bcProc;
+         BoundaryConditionPtr noSlipBC;
+
+         if (thinWall)
+         {
+            bcProc = BCProcessorPtr(new D3Q27ETForThinWallBCProcessor());
+            noSlipBC = BoundaryConditionPtr(new ThinWallNoSlipBoundaryCondition());
+         }
+         else
+         {
+            bcProc = BCProcessorPtr(new D3Q27ETBCProcessor());
+            noSlipBC = BoundaryConditionPtr(new NoSlipBoundaryCondition());
+         }
+
+         bcProc->addBC(noSlipBC);
+
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nu_LB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         //////////////////////////////////
+         //undef nodes for refinement
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+
+         //BC
+         intHelper.setBC();
+
+         ////porous media
+         {
+            string samplePathname = pathGeo + "/" + sampleFilename;
+
+            GbVoxelMatrix3DPtr sample(new GbVoxelMatrix3D(pmNX[0], pmNX[1], pmNX[2], 0, lthreshold, uthreshold));
+            if (rawFile)
+            {
+               sample->readBufferedMatrixFromRawFile<unsigned short>(samplePathname, GbVoxelMatrix3D::BigEndian);
+            }
+            else
+            {
+               sample->readMatrixFromVtiASCIIFile(samplePathname);
+            }
+
+            sample->setVoxelMatrixDelta(voxelDeltaX[0], voxelDeltaX[1], voxelDeltaX[2]);
+            sample->setVoxelMatrixMininum(origin[0], origin[1], origin[2]);
+
+            int bounceBackOption = 1;
+            bool vxFile = false;
+            int i = 0;
+            for (int x = 0; x < lengthFactor; x+=2)
+            {
+               double offset = pmL[0] * (double)x;
+               //sample 0
+               if (myid == 0) UBLOG(logINFO, "sample # " << i);
+               sample->setVoxelMatrixMininum(origin[0]+offset, origin[1], origin[2]);
+               Utilities::voxelMatrixDiscretisation(sample, pathname, myid, i, grid, bounceBackOption, vxFile);
+               i++;
+
+               if (myid == 0)
+               {
+                  UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+                  UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+                  UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+               }
+
+               //sample 1
+               if (myid == 0) UBLOG(logINFO, "sample # " << i);
+               sample->setVoxelMatrixMininum(origin[0]+pmL[0]+offset, origin[1], origin[2]);
+               sample->mirrorX();
+               Utilities::voxelMatrixDiscretisation(sample, pathname, myid, i, grid, bounceBackOption, vxFile);
+               i++;
+
+               if (myid == 0)
+               {
+                  UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+                  UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+                  UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+               }
+
+               //sample 2
+               if (myid == 0) UBLOG(logINFO, "sample # " << i);
+               sample->setVoxelMatrixMininum(origin[0]+pmL[0]+offset, origin[1]+pmL[1], origin[2]);
+               sample->mirrorY();
+               Utilities::voxelMatrixDiscretisation(sample, pathname, myid, i, grid, bounceBackOption, vxFile);
+               i++;
+
+               if (myid == 0)
+               {
+                  UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+                  UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+                  UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+               }
+
+               //sample 3
+               if (myid == 0) UBLOG(logINFO, "sample # " << i);
+               sample->setVoxelMatrixMininum(origin[0]+offset, origin[1]+pmL[1], origin[2]);
+               sample->mirrorX();
+               Utilities::voxelMatrixDiscretisation(sample, pathname, myid, i, grid, bounceBackOption, vxFile);
+               sample->mirrorY();
+               i++;
+            }
+
+         }
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("x3 < h ? 0.0 : uLB+1*x1-1*x2");
+		   //inflowProfile.SetExpr("uLB+1*x1-1*x2");
+         //inflowProfile.SetExpr("uLB");
+         inflowProfile.DefineConst("uLB", u_LB);
+         inflowProfile.DefineConst("h", pmL[2]);
+
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nu_LB, rho_LB);
+         initVisitor.setVx1(inflowProfile);
+         //initVisitor.setVx1(u_LB);
+         grid->accept(initVisitor);
+
+         ////set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         coord[0] = g_minX1;
+         coord[1] = g_minX2;
+         coord[2] = g_minX3;
+         coord[3] = g_maxX1;
+         coord[4] = g_maxX2;
+         coord[5] = g_maxX3;
+
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "w");
+         fprintf(pFile, "%g\n", deltaXcoarse);
+         fprintf(pFile, "%g\n", nu_LB);
+         fprintf(pFile, "%g\n", coord[0]);
+         fprintf(pFile, "%g\n", coord[1]);
+         fprintf(pFile, "%g\n", coord[2]);
+         fprintf(pFile, "%g\n", coord[3]);
+         fprintf(pFile, "%g\n", coord[4]);
+         fprintf(pFile, "%g\n", coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+         if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+      }
+      else
+      {
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "r");
+         fscanf(pFile, "%lg\n", &deltaXcoarse);
+         fscanf(pFile, "%lg\n", &nu_LB);
+         fscanf(pFile, "%lg\n", &coord[0]);
+         fscanf(pFile, "%lg\n", &coord[1]);
+         fscanf(pFile, "%lg\n", &coord[2]);
+         fscanf(pFile, "%lg\n", &coord[3]);
+         fscanf(pFile, "%lg\n", &coord[4]);
+         fscanf(pFile, "%lg\n", &coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Parameters:");
+            UBLOG(logINFO, "Re = " << Re);
+            UBLOG(logINFO, "u_LB = " << u_LB);
+            UBLOG(logINFO, "rho_LB = " << rho_LB);
+            UBLOG(logINFO, "nu_LB = " << nu_LB);
+            UBLOG(logINFO, "dx coarse = " << deltaXcoarse << " m");
+            UBLOG(logINFO, "dx fine = " << grid->getDeltaX(refineLevel) << " m");
+            UBLOG(logINFO, "number of levels = " << refineLevel + 1);
+            UBLOG(logINFO, "numOfThreads = " << numOfThreads);
+            UBLOG(logINFO, "path = " << pathname);
+         }
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         restart = true;
+
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+      }
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+
+      //D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+      double startStep = grid->getTimeStep();
+
+      //UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(40000,40000,40000000);
+      //UbSchedulerPtr resSchRMS(new UbScheduler());
+      //resSchRMS->addSchedule(40000, startStep, 40000000);
+      //UbSchedulerPtr resSchMeans(new UbScheduler());
+      //resSchMeans->addSchedule(40000, startStep, 40000000);
+      //UbSchedulerPtr stepAvSch(new UbScheduler());
+      //stepAvSch->addSchedule(100, 0, 10000000);
+      //AverageValuesPostprocessor Avpp(grid, pathname, WbWriterVtkXmlBinary::getInstance(),
+      //   stepSch/*wann wird rausgeschrieben*/, stepAvSch/*wann wird gemittelt*/, resSchMeans, resSchRMS/*wann wird resettet*/, restart);
+
+
+      UbSchedulerPtr AdjForcSch(new UbScheduler());
+      AdjForcSch->addSchedule(100, 0, 10000000);
+      D3Q27IntegrateValuesHelperPtr intValHelp(new D3Q27IntegrateValuesHelper(grid, comm,
+         coord[0], coord[1], coord[2],
+         coord[3], coord[4], coord[5]));
+      if (myid == 0) GbSystem3D::writeGeoObject(intValHelp->getBoundingBox().get(), pathname + "/geo/IntValHelp", WbWriterVtkXmlBinary::getInstance());
+
+      double vxTarget=u_LB;
+      D3Q27AdjustForcingPostprocessor AdjForcPPPtr(grid, AdjForcSch, pathname, intValHelp, vxTarget, forcing, comm);
+
+      //mu::Parser decrViscFunc;
+      //decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");
+      //decrViscFunc.DefineConst("nue0", nu_LB*4.0);
+      //decrViscFunc.DefineConst("c0", 0.1);
+      //UbSchedulerPtr DecrViscSch(new UbScheduler());
+      //DecrViscSch->addSchedule(10, 0, 1000);
+      //DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch, &decrViscFunc, comm);
+
+	  //if (changeQs)
+	  //{
+		 // double z1 = pmL[2];
+		 // D3Q27IntegrateValuesHelperPtr intValHelp2(new D3Q27IntegrateValuesHelper(grid, comm,
+			//  coord[0], coord[1], z1 - deltaXfine,
+			//  coord[3], coord[4], z1 + deltaXfine));
+		 // if (myid == 0) GbSystem3D::writeGeoObject(intValHelp2->getBoundingBox().get(), pathname + "/geo/intValHelp2", WbWriterVtkXmlBinary::getInstance());
+		 // Utilities::ChangeRandomQs(intValHelp2);
+	  //}
+
+
+      //UbSchedulerPtr tavSch(new UbScheduler(1, timeAvStart, timeAvStop));
+      //TimeAveragedValuesPostprocessor tav(grid, pathname, WbWriterVtkXmlBinary::getInstance(), tavSch, 
+      //   TimeAveragedValuesPostprocessor::Velocity|TimeAveragedValuesPostprocessor::Fluctuations|TimeAveragedValuesPostprocessor::Triplecorrelations);
+      
+      UbSchedulerPtr catalystSch(new UbScheduler(1));
+      InSituCatalystPostprocessor catalyst(grid, catalystSch, "pchannel.py");
+
+      if (myid == 0)
+      {
+         UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch));
+      if (myid == 0) UBLOG(logINFO, "Simulation-start");
+      calculation->calculate();
+      if (myid == 0) UBLOG(logINFO, "Simulation-end");
+   }
+   catch (exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch (string& s)
+   {
+      cerr << s << endl;
+   }
+   catch (...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+
+   if (argv != NULL)
+   {
+      if (argv[1] != NULL)
+      {
+         run(string(argv[1]));
+      }
+      else
+      {
+         cout << "Configuration file is missing!" << endl;
+      }
+   }
+
+   return 0;
+}
diff --git a/source/Applications/pChannel/pchannel.py b/source/Applications/pChannel/pchannel.py
new file mode 100644
index 0000000000000000000000000000000000000000..6a58fd005cdc695c6b016ccc1726cf187912ae2b
--- /dev/null
+++ b/source/Applications/pChannel/pchannel.py
@@ -0,0 +1,85 @@
+try: paraview.simple
+except: from paraview.simple import *
+
+from paraview import coprocessing
+
+
+#--------------------------------------------------------------
+# Code generated from cpstate.py to create the CoProcessor.
+
+
+# ----------------------- CoProcessor definition -----------------------
+
+def CreateCoProcessor():
+  def _CreatePipeline(coprocessor, datadescription):
+    class Pipeline:
+      filename_3_pvtu = coprocessor.CreateProducer( datadescription, "input" )
+
+      #~ Slice1 = Slice( guiName="Slice1", Crinkleslice=0, SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane" )
+      #~ Slice1.SliceType.Offset = 0.0
+      #~ Slice1.SliceType.Origin = [34.5, 32.45, 27.95]
+      #~ Slice1.SliceType.Normal = [1.0, 0.0, 0.0]
+#~ 
+      #~ ParallelPolyDataWriter1 = coprocessor.CreateWriter( XMLPPolyDataWriter, "slice_%t.pvtp", 10 )
+
+      SetActiveSource(filename_3_pvtu)
+      #~ ParallelUnstructuredGridWriter1 = coprocessor.CreateWriter( XMLPUnstructuredGridWriter, "fullgrid_%t.pvtu", 100 )
+
+    return Pipeline()
+
+  class CoProcessor(coprocessing.CoProcessor):
+    def CreatePipeline(self, datadescription):
+      self.Pipeline = _CreatePipeline(self, datadescription)
+
+  coprocessor = CoProcessor()
+  freqs = {'input': [10, 100]}
+  coprocessor.SetUpdateFrequencies(freqs)
+  return coprocessor
+
+#--------------------------------------------------------------
+# Global variables that will hold the pipeline for each timestep
+# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
+# It will be automatically setup when coprocessor.UpdateProducers() is called the
+# first time.
+coprocessor = CreateCoProcessor()
+
+#--------------------------------------------------------------
+# Enable Live-Visualizaton with ParaView
+coprocessor.EnableLiveVisualization(True)
+
+
+# ---------------------- Data Selection method ----------------------
+
+def RequestDataDescription(datadescription):
+    "Callback to populate the request for current timestep"
+    global coprocessor
+    if datadescription.GetForceOutput() == True:
+        # We are just going to request all fields and meshes from the simulation
+        # code/adaptor.
+        for i in range(datadescription.GetNumberOfInputDescriptions()):
+            datadescription.GetInputDescription(i).AllFieldsOn()
+            datadescription.GetInputDescription(i).GenerateMeshOn()
+        return
+
+    # setup requests for all inputs based on the requirements of the
+    # pipeline.
+    coprocessor.LoadRequestedData(datadescription)
+
+# ------------------------ Processing method ------------------------
+
+def DoCoProcessing(datadescription):
+    "Callback to do co-processing for current timestep"
+    global coprocessor
+
+    # Update the coprocessor by providing it the newly generated simulation data.
+    # If the pipeline hasn't been setup yet, this will setup the pipeline.
+    coprocessor.UpdateProducers(datadescription)
+
+    # Write output data, if appropriate.
+    coprocessor.WriteData(datadescription);
+
+    # Write image capture (Last arg: rescale lookup table), if appropriate.
+    coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
+
+    # Live Visualization, if enabled.
+    coprocessor.DoLiveVisualization(datadescription, "localhost", 22222)
diff --git a/source/Applications/pDisk/CMakeLists.txt b/source/Applications/pDisk/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..75a6476e7d052d3d0a3ccc561a4d775395012cfb
--- /dev/null
+++ b/source/Applications/pDisk/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(pDisk)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(pdisk BINARY)
diff --git a/source/Applications/pDisk/configBombadilPdisk.cfg b/source/Applications/pDisk/configBombadilPdisk.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..a600e4cddd3e0f5375cc80be8fc8ac579c8e7900
--- /dev/null
+++ b/source/Applications/pDisk/configBombadilPdisk.cfg
@@ -0,0 +1,36 @@
+#
+#Simulation parameters for porous disk
+#
+
+pathname = d:/temp/pDisk
+pathGeo = d:/Data/PorousDisk
+numOfThreads = 1
+availMem = 3e9
+logToFile = false
+
+#geometry
+diskFilename = PorousDiskDR.stl 
+mastFilename = Mast.stl
+
+#grid
+fineNodeDx = 10  # 0.3 / 0.2
+blocknx = 16 16 16
+refineLevel = 2
+geoLength = 5000 2000 2000
+
+#physic
+Re = 6.66e4
+u_LB = 0.01
+rho_LB = 0.0
+
+#averaging
+restart = false
+averaging = false
+
+restartStep = 20000
+restartStepStart=20000
+
+endTime = 60000
+outTime = 100
+
+
diff --git a/source/Applications/pDisk/configHlrnPorousDisk.cfg b/source/Applications/pDisk/configHlrnPorousDisk.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..d3cfec356c0ed0adf157cf800678e02eed48e640
--- /dev/null
+++ b/source/Applications/pDisk/configHlrnPorousDisk.cfg
@@ -0,0 +1,36 @@
+#
+#Simulation parameters for porous disk
+#
+
+pathname = /gfs1/work/niikonst/scratch/pDisk
+pathGeo = /gfs1/work/niikonst/data/PorousDisk
+numOfThreads = 24
+availMem = 128e9
+logToFile = true
+
+#geometry
+diskFilename = PorousDiskD2.stl 
+mastFilename = Mast.stl
+
+#grid
+fineNodeDx = 1.9  
+blocknx = 16 16 16
+refineLevel = 4
+geoLength = 5000 2000 2000
+
+#physic
+Re = 6.66e4
+u_LB = 0.01
+rho_LB = 0.0
+
+#averaging
+restart = false
+averaging = false
+
+restartStep = 10000
+restartStepStart=10000
+
+outTime = 10000
+
+endTime = 100000
+
diff --git a/source/Applications/pDisk/pdisk.cpp b/source/Applications/pDisk/pdisk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e86cab201d3043328e004af3f41b47cc7677cbf6
--- /dev/null
+++ b/source/Applications/pDisk/pdisk.cpp
@@ -0,0 +1,427 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(string configname)
+{
+   try
+   {
+      Configuration   config;
+      config.load(configname);
+
+      string          pathname          = config.getString("pathname");
+      string          pathGeo           = config.getString("pathGeo");
+      int             numOfThreads      = config.getInt("numOfThreads");
+      string          diskFilename      = config.getString("diskFilename");
+      string          mastFilename      = config.getString("mastFilename");
+      vector<int>     blocknx           = config.getVector<int>("blocknx");
+      double          restartStep       = config.getDouble("restartStep");
+      double          restartStepStart  = config.getDouble("restartStepStart");
+      double          endTime           = config.getDouble("endTime");
+      double          outTime           = config.getDouble("outTime");
+      double          availMem          = config.getDouble("availMem");
+      bool            logToFile         = config.getBool("logToFile");
+      vector<double>  geoLength         = config.getVector<double>("geoLength");
+      int             refineLevel       = config.getInt("refineLevel");
+      double          Re                = config.getDouble("Re");
+      double          u_LB              = config.getDouble("u_LB");
+      double          rho_LB            = config.getDouble("rho_LB");
+      double          fineNodeDx        = config.getDouble("fineNodeDx");
+      bool            restart           = config.getBool("restart");
+      bool            averaging         = config.getBool("averaging");
+
+      //UbLog::reportingLevel() = logDEBUG5;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+
+#if defined(__unix__)
+      if (myid==0) 
+      {
+         const char* str = pathname.c_str();
+         int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      }
+#endif 
+
+      if(myid == 0 && logToFile)
+      {
+         stringstream logFilename;
+         logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      if(myid==0) UBLOG(logINFO,"Test case: porous disk");
+
+      int baseLevel = 0;
+
+      double coarseNodeDx = fineNodeDx * (double)(1<<refineLevel);//geowerte
+
+      double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+      double blockLengthx2 = blockLengthx1;
+      double blockLengthx3 = blockLengthx1;
+
+      bool periodicx1 = false;
+      bool periodicx2 = true;
+      bool periodicx3 = false;
+
+      int sizeSP= (int)(500.0/coarseNodeDx); //500 mm sponge layer
+      mu::Parser spongeLayer;
+      spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dt ? (sizeX-x1)/sizeSP/2.0 + 0.5 : 1.0");
+      spongeLayer.DefineConst("sizeX", 5000.0/coarseNodeDx);
+      spongeLayer.DefineConst("sizeSP", sizeSP);
+
+      //##########################################################################
+      //## physical parameters
+      //##########################################################################
+      double nu_LB = (u_LB*(geoLength[2]/coarseNodeDx))/Re;
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+      
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(restartStep, restartStepStart));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      
+
+      if (grid->getTimeStep() == 0)
+      {
+         if (myid==0) UBLOG(logINFO, "new start..");
+
+         if (myid==0) UBLOG(logINFO, "load geometry start");
+         GbTriFaceMesh3DPtr geoMast(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathGeo+"/"+mastFilename, "mast"));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoMast.get(), pathname + "/geo/geoMast", WbWriterVtkXmlBinary::getInstance());
+
+         GbTriFaceMesh3DPtr geoDisk(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathGeo+"/"+diskFilename, "disk"));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoDisk.get(), pathname + "/geo/geoDisk", WbWriterVtkXmlBinary::getInstance());
+         if (myid==0) UBLOG(logINFO, "load geometry end");
+
+         //bounding box
+         double g_minX1 = geoMast->getX1Centroid() - 2000.0;
+         double g_minX2 = geoMast->getX2Centroid() - 1000.0;
+         double g_minX3 = geoMast->getX3Minimum();
+
+         double g_maxX1 = g_minX1 + geoLength[0];
+         double g_maxX2 = g_minX2 + geoLength[1];
+         double g_maxX3 = g_minX3 + geoLength[2];
+
+         double nx1_temp = floor((g_maxX2-g_minX2) /(coarseNodeDx*(double)blocknx[1]));
+
+         coarseNodeDx = (g_maxX2-g_minX2) /(nx1_temp*(double)blocknx[1]);
+
+         fineNodeDx = coarseNodeDx / (double)(1<<refineLevel);
+
+         //set grid
+         grid->setDeltaX(coarseNodeDx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         //////////////////////////////////////////////////////////////////////////
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re                = "<<Re);
+            UBLOG(logINFO, "* nu_LB             = "<<nu_LB);
+            UBLOG(logINFO, "* u_LB              = "<<u_LB);
+            UBLOG(logINFO, "* cdx               = "<<coarseNodeDx<<" mm");
+            UBLOG(logINFO, "* fdx               = "<<fineNodeDx<<" mm");
+            UBLOG(logINFO, "* nx1/2/3           = "<<grid->getNX1()<<"/"<<grid->getNX2()<<"/"<<grid->getNX3());
+            UBLOG(logINFO, "* blocknx1/2/3      = "<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x1Periodic        = "<<periodicx1);
+            UBLOG(logINFO, "* x2Periodic        = "<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic        = "<<periodicx3);
+            UBLOG(logINFO, "* number of levels  = "<<refineLevel+1);
+            UBLOG(logINFO, "* path              = "<<pathname);
+
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* number of threads    = "<<numOfThreads);
+            UBLOG(logINFO, "* number of processes  = "<<comm->getNumberOfProcesses());
+            UBLOG(logINFO, "*****************************************");
+            //UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+            //UBLOG(logINFO, "*****************************************");     
+         }
+
+         ////walls
+         GbCuboid3DPtr addWallYmin(new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_minX3-blockLengthx1, g_maxX1+blockLengthx1, g_minX2, g_maxX3+blockLengthx1));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax(new GbCuboid3D(g_minX1-blockLengthx1, g_maxX2, g_minX3-blockLengthx1, g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin(new GbCuboid3D(g_minX1 - blockLengthx1, g_minX2 - blockLengthx1, g_minX3 - blockLengthx1, g_maxX1 + blockLengthx1, g_maxX2 + blockLengthx1, g_minX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname + "/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax(new GbCuboid3D(g_minX1 - blockLengthx1, g_minX2 - blockLengthx1, g_maxX3, g_maxX1 + blockLengthx1, g_maxX2 + blockLengthx1, g_maxX3 + blockLengthx1));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname + "/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcNoSlip(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27BoundaryConditionAdapterPtr bcSlip(new D3Q27SlipBCAdapter());
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcSlip, Interactor3D::SOLID));
+
+         D3Q27TriFaceMeshInteractorPtr mastInt(new D3Q27TriFaceMeshInteractor(geoMast, grid, bcNoSlip, Interactor3D::SOLID, Interactor3D::POINTS));
+         D3Q27TriFaceMeshInteractorPtr diskInt(new D3Q27TriFaceMeshInteractor(geoDisk, grid, bcNoSlip, Interactor3D::SOLID, Interactor3D::POINTS));
+
+         //inflow
+         GbCuboid3DPtr geoInflow(new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_minX3-blockLengthx1, g_minX1, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname + "/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr inflowInt(new D3Q27Interactor(geoInflow, grid, Interactor3D::SOLID));
+
+         //inflow
+         mu::Parser inflowProfile;
+         //inflowProfile.SetExpr("u_ref*(((x3+Z_ref)/Z_ref)^a)");
+         inflowProfile.SetExpr("u_ref");
+         inflowProfile.DefineConst("u_ref", u_LB);
+         inflowProfile.DefineConst("Z_ref", 300.0);
+         inflowProfile.DefineConst("a", 0.143);
+
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter = D3Q27BoundaryConditionAdapterPtr(new D3Q27VelocityBCAdapter(true, false, false, inflowProfile, 0, D3Q27BCFunction::INFCONST));
+         inflowInt->addBCAdapter(velBCAdapter);
+
+         //outflow
+         GbCuboid3DPtr geoOutflow(new GbCuboid3D(g_maxX1, g_minX2-blockLengthx1, g_minX3-blockLengthx1, g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname + "/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rho_LB));
+         D3Q27InteractorPtr outflowInt(new D3Q27Interactor(geoOutflow, grid, denBCAdapter, Interactor3D::SOLID));
+
+         {
+            if (myid == 0) UBLOG(logINFO, "Write blocks - start"); 
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            if (myid == 0)
+               ppblocks->update(0);
+            if (myid == 0) UBLOG(logINFO, "Write blocks - end"); 
+         }
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));	
+        
+         //////////////////////////////////////////////////////////////////////////
+         //refinement
+         double diameter = geoDisk->getLengthX2();
+         GbCuboid3DPtr refineDiskBox(new GbCuboid3D(geoDisk->getX1Centroid()-0.2*diameter, geoDisk->getX2Centroid()-0.6*diameter, geoDisk->getX3Minimum()-diameter, 
+            geoDisk->getX1Centroid() + 1.0*diameter, geoDisk->getX2Centroid()+0.6*diameter, geoDisk->getX3Maximum() + 0.05*diameter));
+         if (myid == 0) GbSystem3D::writeGeoObject(refineDiskBox.get(), pathname + "/geo/refineDiskBox", WbWriterVtkXmlASCII::getInstance());
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refineDiskBox, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         {
+            if (myid == 0) UBLOG(logINFO, "Write blocks - start");
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            if (myid == 0)
+               ppblocks->update(1);
+            if (myid == 0) UBLOG(logINFO, "Write blocks - end");
+         }
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(mastInt);
+         intHelper.addInteractor(diskInt);
+         //intHelper.addInteractor(addWallYminInt);
+         //intHelper.addInteractor(addWallYmaxInt);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallZmaxInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.selectBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx[0])* (blocknx[1])* (blocknx[2]);
+         unsigned long nod = nob * (blocknx[0])* (blocknx[1])* (blocknx[2]);
+         unsigned long nodg = nob * (blocknx[0] + gl) * (blocknx[1] + gl) * (blocknx[2] + gl);
+         double needMemAll = double(nodg*(27 * sizeof(double) + sizeof(int) + sizeof(float) * 4));
+         double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Number of blocks = " << nob);
+            UBLOG(logINFO, "Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for (int level = minInitLevel; level <= maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO, "Number of blocks for level " << level << " = " << nobl);
+               UBLOG(logINFO, "Number of nodes for level " << level << " = " << nobl*nodb);
+            }
+            UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+            UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+            UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+         }
+
+         ////////////////////////////
+         LBMKernel3DPtr kernel;
+         //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+         //with sponge layer
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+         kernel->setWithSpongeLayer(true);
+         kernel->setSpongeLayer(spongeLayer);
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         BoundaryConditionPtr densityBC(new NonEqDensityBoundaryCondition());
+         BoundaryConditionPtr noSlipBC(new NoSlipBoundaryCondition());
+         BoundaryConditionPtr velocityBC(new VelocityBoundaryCondition());
+         BoundaryConditionPtr slipBC(new SlipBoundaryCondition());
+
+         bcProc->addBC(densityBC);
+         bcProc->addBC(noSlipBC);
+         bcProc->addBC(velocityBC);
+         bcProc->addBC(slipBC);
+         kernel->setBCProcessor(bcProc);
+         SetKernelBlockVisitor kernelVisitor(kernel, nu_LB, availMem, needMem);
+         grid->accept(kernelVisitor);
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+         //////////////////////////////////////////
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         intHelper.setBC();
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nu_LB,rho_LB);
+         //initVisitor.setVx1(inflowProfile);
+         initVisitor.setVx1(u_LB);
+         grid->accept(initVisitor);
+
+         //Postprozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+      }
+      else
+      {
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept( setConnsVisitor );
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+         //SetSpongeLayerBlockVisitor ssp(spongeLayer);
+         //grid->accept(ssp);
+         if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      }
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+
+      double startStep = 80000;
+
+      if (averaging)
+      {
+         UbSchedulerPtr resSchRMS(new UbScheduler());
+         resSchRMS->addSchedule(100000, 80000, 10000000);
+         UbSchedulerPtr resSchMeans(new UbScheduler());
+         resSchMeans->addSchedule(100000, 80000, 10000000);
+         UbSchedulerPtr stepAvSch(new UbScheduler());
+         int averageInterval=100;
+         stepAvSch->addSchedule(averageInterval, 0, 10000000);
+
+         AverageValuesPostprocessor Avpp(grid, pathname, WbWriterVtkXmlBinary::getInstance(),
+            visSch/*wann wird rausgeschrieben*/, stepAvSch/*wann wird gemittelt*/, resSchMeans, resSchRMS/*wann wird resettet*/, restart);
+      }
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      nupsSch->addSchedule(1000, 1000, 1000000000);
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      //double endTime = 80001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   if (argv != NULL)
+   {
+      if (argv[1] != NULL)
+      {
+         run(string(argv[1]));
+      }
+      else
+      {
+         cout << "Configuration file is missing!" << endl;
+      }
+   }
+
+   return 0;
+}
+
diff --git a/source/Applications/perm/CMakeLists.txt b/source/Applications/perm/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0b2bc6bc918de538a7006aedcb21550b3cd2c2a7
--- /dev/null
+++ b/source/Applications/perm/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(perm)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(perm BINARY)
diff --git a/source/Applications/perm/config.txt b/source/Applications/perm/config.txt
new file mode 100644
index 0000000000000000000000000000000000000000..30d0cb452adb24805fdabb7e24105ad1c029c8e4
--- /dev/null
+++ b/source/Applications/perm/config.txt
@@ -0,0 +1,41 @@
+pathname = /gfs1/work/niikonst/scratch/permAlu
+pathGeo = /gfs1/work/niikonst/data/materials
+numOfTreads = 24
+
+#poroeses Medium
+
+sampleFilename = alu_80-110.vti
+
+#Diminsion in Voxel
+pmNX1 = 1096
+pmNX2 = 1327
+pmNX3 = 1265
+
+#Threshold
+lthreshold = 29041
+uthreshold = 65535
+
+#Diminsion in m
+pmL1 = 4e-3
+pmL2 = 5e-3
+pmL3 = 5e-3
+
+dp_LB = 0.01
+
+#for Re=2
+nu_LB = 0.02
+
+#for Re=100
+#nu_LB = 0.0004
+
+#nu -= nuFactor*simNumber
+#coefficient for nu (0.02-0.0004)/10
+nuFactor = 0.00196
+#simulation number
+simNumber = 1
+
+restartStep = 20000
+#immer 40000 pro Job
+endTime = 140000
+outTime = 20000
+nupsStep = 10 80010 80100
\ No newline at end of file
diff --git a/source/Applications/perm/configBombadil.txt b/source/Applications/perm/configBombadil.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4f5a8115b0c56f4dc6afc658192fb948d0c66a55
--- /dev/null
+++ b/source/Applications/perm/configBombadil.txt
@@ -0,0 +1,34 @@
+pathname = d:/temp/perm2
+pathGeo = d:/Projects/SFB880/GeometrienPoroeseMedien/Alu_80-110
+numOfTreads = 4
+
+#poroeses Medium
+
+sampleFilename = /alu_80-110.vti
+
+#Diminsion in Voxel
+pmNX1 = 200
+pmNX2 = 200
+pmNX3 = 200
+
+#Threshold
+lthreshold = 29041
+uthreshold = 65535
+
+#Diminsion in m
+pmL1 = 0.726e-3
+pmL2 = 0.75e-3
+pmL3 = 0.786e-3
+
+#dp_LB = 1e-9
+dp_LB = 1e-1
+nu_LB = 2e-5
+
+timeSeriesOut = /timeseries/simAlu80_5
+
+restartStep = 300
+restartStepStart = 300
+#immer 40000 pro Job
+endTime = 140000
+outTime = 10
+nupsStep = 10 80010 80100
\ No newline at end of file
diff --git a/source/Applications/perm/configBombadil2.txt b/source/Applications/perm/configBombadil2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..64bb2fb7f902d0849b478c41fa49f258fdc9995a
--- /dev/null
+++ b/source/Applications/perm/configBombadil2.txt
@@ -0,0 +1,36 @@
+pathname = d:/temp/perm
+pathGeo = d:/Projects/SFB880/GeometrienPoroeseMedien/Alu_80-110
+numOfTreads = 4
+
+#poroeses Medium
+
+sampleFilename = /alu_80-110.vti
+
+#Diminsion in Voxel
+pmNX1 = 200
+pmNX2 = 200
+pmNX3 = 200
+
+#Threshold
+lthreshold = 29041
+uthreshold = 65535
+
+#Diminsion in m
+pmL1 = 0.726e-3
+pmL2 = 0.75e-3
+pmL3 = 0.786e-3
+
+dp_LB = 0.001
+#nu_LB = 0.168666666667
+#nu_LB = 0.168666666667e-1
+#nu_LB = 0.168666666667e-2
+#nu_LB = 0.168666666667e-3
+nu_LB = 0.168666666667e-4
+
+timeSeriesOut = /timeseries/simAlu80_5
+
+restartStep = 20000
+#immer 40000 pro Job
+endTime = 140000
+outTime = 1000
+nupsStep = 10 80010 80100
\ No newline at end of file
diff --git a/source/Applications/perm/configBombadilSBP120s.txt b/source/Applications/perm/configBombadilSBP120s.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de8aa0694ea499ff23cb17048d5d4b47fa2c5202
--- /dev/null
+++ b/source/Applications/perm/configBombadilSBP120s.txt
@@ -0,0 +1,42 @@
+#
+#Simulation parameters for determitatoin of permeability
+#SBP120
+
+pathname = d:/temp/perm
+pathGeo = d:/Projects/SFB880/GeometrienPoroeseMedien/SBP120
+numOfThreads = 4
+availMem = 1.2e9
+
+#porous media
+rawFile = false
+sampleFilename = /SPB120s_center_closed.vti
+
+#diminsions [voxel]
+pmNX1 = 680
+pmNX2 = 689
+pmNX3 = 787
+
+#threshold
+lthreshold = 1
+uthreshold = 1
+
+#diminsions [m]
+pmL1 = 2.55e-3
+pmL2 = 2.55000278e-3
+pmL3 = 2.95125e-3
+
+#grid
+blocknx = 10
+nx3 = 10
+
+#physic
+dp_LB = 0.001
+nu_LB = 0.01
+
+timeSeriesOut = /timeseries/simSBP120_1
+
+restartStep = 20000
+restartStepStart=20000
+
+endTime = 140000
+outTime = 1000
diff --git a/source/Applications/perm/configBombadilSBP120s500.txt b/source/Applications/perm/configBombadilSBP120s500.txt
new file mode 100644
index 0000000000000000000000000000000000000000..89e60d9a17fe690a17cccb1c7df8ec213fa795d4
--- /dev/null
+++ b/source/Applications/perm/configBombadilSBP120s500.txt
@@ -0,0 +1,50 @@
+#
+#Simulation parameters for determitatoin of permeability
+#SBP120
+
+pathname = d:/temp/perm
+pathGeo = d:/Projects/SFB880/GeometrienPoroeseMedien/SBP120
+numOfThreads = 4
+availMem = 3e9
+logToFile = false
+
+#porous media
+rawFile = false
+sampleFilename = /SBP120s500_center_closed.vti
+
+#diminsions [voxel]
+pmNX1 = 500
+pmNX2 = 500
+pmNX3 = 500
+
+#threshold
+#lthreshold = 38370
+#uthreshold = 65535
+lthreshold = 1
+uthreshold = 1
+
+
+#diminsions [m]
+pmL1 = 1.87e-3
+pmL2 = 1.87e-3
+pmL3 = 1.87e-3
+
+#grid
+#blocknx = 30
+#nx3 = 5
+blocknx = 50
+nx3 = 10
+spongeLayer=true
+
+#physic
+dp_LB = 1e-7
+nu_LB = 0.01
+
+timeSeriesFile = /timeseries/simSBP120_1
+timeSeriesOutTime = 10
+
+restartStep = 20000
+restartStepStart=20000
+
+endTime = 60000
+outTime = 100
diff --git a/source/Applications/perm/configHlrnAlu.txt b/source/Applications/perm/configHlrnAlu.txt
new file mode 100644
index 0000000000000000000000000000000000000000..101c741be225b854e162c2b8f4b85f7f64885d56
--- /dev/null
+++ b/source/Applications/perm/configHlrnAlu.txt
@@ -0,0 +1,34 @@
+pathname = /gfs1/work/niikonst/scratch/permAlu80
+pathGeo = /gfs1/work/niikonst/data/materials
+
+numOfTreads = 1
+
+#poroeses Medium
+
+sampleFilename = /alu_80-110.vti
+
+#Diminsion in Voxel
+pmNX1 = 200
+pmNX2 = 200
+pmNX3 = 200
+
+#Threshold
+lthreshold = 29041
+uthreshold = 65535
+
+#Diminsion in m
+pmL1 = 0.726e-3
+pmL2 = 0.75e-3
+pmL3 = 0.786e-3
+
+dp_LB = 0.001
+nu_LB = 0.15
+
+timeSeriesOut = /timeseries/simAlu80_1
+
+restartStep = 20
+#immer 40000 pro Job
+#endTime = 140000
+endTime = 60
+outTime = 10
+nupsStep = 10 80010 80100
\ No newline at end of file
diff --git a/source/Applications/perm/config_HLRS_SBP120.cfg b/source/Applications/perm/config_HLRS_SBP120.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..54ceee42016bd06904a472fedccb35c68bbb06be
--- /dev/null
+++ b/source/Applications/perm/config_HLRS_SBP120.cfg
@@ -0,0 +1,43 @@
+#HLRS
+#Simulation parameters for determitatoin of permeability
+#SBP120
+
+pathname = /univ_1/ws1/ws/xrmkuchr-perm-0/SBP120
+pathGeo = /univ_1/ws1/ws/xrmkuchr-perm-0/SBP120/Data
+numOfThreads = 24
+availMem = 128e9
+logToFile = true
+#porous media
+rawFile = false
+sampleFilename = /Sinterbronze_SBP120_1358x1376x1572.raw
+
+#diminsions [voxel]
+pmNX1 = 1358
+pmNX2 = 1376
+pmNX3 = 1572
+
+#threshold
+lthreshold = 38370
+uthreshold = 65535
+
+#diminsions [m]
+pmL1 = 5092499.73e-9
+pmL2 = 5159999.85e-9
+pmL3 = 5894999.98e-9
+
+#grid
+blocknx = 64
+nx3 = 22
+
+#physic
+dp_LB = 1e-7
+nu_LB = 0.01
+
+timeSeriesFile = /timeseries/simSBP120_1
+timeSeriesOutTime = 100
+
+restartStep = 1000
+restartStepStart=1000
+
+endTime = 2000
+outTime = 1000
diff --git a/source/Applications/perm/perm.cpp b/source/Applications/perm/perm.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2222a77c06952e7d2d9a6f4f3756314550d98d3b
--- /dev/null
+++ b/source/Applications/perm/perm.cpp
@@ -0,0 +1,633 @@
+#include <iostream>
+#include <string>
+#include <vfluids.h>
+
+using namespace std;
+
+void changeDP()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void perm(const char *configname)
+{
+   try
+   {
+      Configuration   config;
+      config.load((string)configname);
+
+      string          pathname = config.getString("pathname");
+      string          pathGeo = config.getString("pathGeo");
+      int             numOfThreads = config.getInt("numOfThreads");
+      string          sampleFilename = config.getString("sampleFilename");
+      int             pmNX1 = config.getInt("pmNX1");
+      int             pmNX2 = config.getInt("pmNX2");
+      int             pmNX3 = config.getInt("pmNX3");
+      double          lthreshold = config.getDouble("lthreshold");
+      double          uthreshold = config.getDouble("uthreshold");
+      double          pmL1 = config.getDouble("pmL1");
+      double          pmL2 = config.getDouble("pmL2");
+      double          pmL3 = config.getDouble("pmL3");
+      int             blocknx = config.getInt("blocknx");
+      double          nx3 = config.getDouble("nx3");
+      double          dp_LB = config.getDouble("dp_LB");
+      double          nu_LB = config.getDouble("nu_LB");
+      string          timeSeriesFile = config.getString("timeSeriesFile");
+      double          restartStep = config.getDouble("restartStep");
+      double          restartStepStart = config.getDouble("restartStepStart");
+      double          endTime = config.getDouble("endTime");
+      double          outTime = config.getDouble("outTime");
+      double          availMem = config.getDouble("availMem");
+      bool            rawFile = config.getBool("rawFile");
+      double          timeSeriesOutTime = config.getDouble("timeSeriesOutTime");
+      bool            logToFile = config.getBool("logToFile");
+      bool            spongeLayer = config.getBool("spongeLayer");
+
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if (logToFile)
+      {
+#if defined(__unix__)
+         if (myid == 0)
+         {
+            const char* str = pathname.c_str();
+            int status = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+         }
+#endif 
+
+         if (myid == 0)
+         {
+            stringstream logFilename;
+            logFilename << pathname + "/logfile" + UbSystem::toString(UbSystem::getTimeStamp()) + ".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+
+      //Sleep(30000);
+
+      if (myid == 0) UBLOG(logINFO, "Testcase permeability");
+
+      string machinename = UbSystem::getMachineName();
+      UBLOG(logINFO, "PID = " << myid << " Hostname: " << machinename);
+      UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+      UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+      UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+
+      int blocknx1 = blocknx;
+      int blocknx2 = blocknx;
+      int blocknx3 = blocknx;
+
+      LBMReal rho_LB = 0.0;
+
+      //Re = (Lp*u)/nu, Lp - size of pore, u - volume-avaraged velocity, nu - viscositi
+      //double Re = UbSystem::stringTo<double>(cf.getValue("Re")); 
+      //LBMReal nu_LB = UbSystem::stringTo<double>(cf.getValue("nu_LB"));
+      //double nuFactor = UbSystem::stringTo<double>(cf.getValue("nuFactor"));
+      //double simNumber = UbSystem::stringTo<double>(cf.getValue("simNumber"));
+      //nu_LB -= nuFactor*simNumber;
+      //double Lp = 90e-6; //m
+
+
+      //dp/dx ~ u for laminar flow
+      //double dp_LB = UbSystem::stringTo<double>(cf.getValue("dp_LB"));
+      double rhoLBinflow = dp_LB*3.0;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      //double nx3 = 10.0; //number of blocks for z
+      double coord[6];
+      double deltax;
+
+
+      ///close void space
+      //////////////////////////////////////////////////////////////////////////
+      //{
+      //   string samplePathname = pathGeo + sampleFilename;
+
+      //   double deltaVoxelX1 = pmL1/(double)pmNX1;
+      //   double deltaVoxelX2 = pmL2/(double)pmNX2;
+      //   double deltaVoxelX3 = pmL3/(double)pmNX3;
+
+      //   GbVoxelMatrix3DPtr sample(new GbVoxelMatrix3D(pmNX1, pmNX2, pmNX3, 0, lthreshold, uthreshold));
+      //   if (rawFile)
+      //   {
+      //      sample->readMatrixFromRawFile<unsigned short>(samplePathname, GbVoxelMatrix3D::BigEndian);
+      //   }
+      //   else
+      //   {
+      //      sample->readMatrixFromVtiASCIIFile(samplePathname);
+      //   }
+
+      //   sample->setVoxelMatrixDelta((float)deltaVoxelX1, (float)deltaVoxelX2, (float)deltaVoxelX3);
+      //   sample->setVoxelMatrixMininum(0.0, 0.0, 0.0);
+
+      //   if (myid == 0) sample->writeToVTKImageDataASCII(pathname + "/geo/sampleOpen");
+      //   sample->calculateNumberOfSolidAndFluid();
+      //   if (myid == 0)  UBLOG(logINFO, "number of solid = "<<sample->getNumberOfSolid());
+      //   if (myid == 0)  UBLOG(logINFO, "number of fluid = "<<sample->getNumberOfFluid());
+
+      //   sample->setClosedVoidSpaceToSolid();
+
+      //   if (myid == 0) sample->writeToVTKImageDataASCII(pathname + "/geo/sampleClosed");
+
+      //   sample->calculateNumberOfSolidAndFluid();
+      //   if (myid == 0)  UBLOG(logINFO, "number of solid = "<<sample->getNumberOfSolid());
+      //   if (myid == 0)  UBLOG(logINFO, "number of fluid = "<<sample->getNumberOfFluid());
+
+      //   UBLOG(logINFO, "Finish!");
+      //   return;
+      //}
+      //////////////////////////////////////////////////////////////////////////
+
+      BoundaryConditionProcessorPtr bcProcessor(new BoundaryConditionProcessor());
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      //double restartStep = UbSystem::stringTo<double>(cf.getValue("restartStep"));
+      //double restartStepStart = UbSystem::stringTo<double>(cf.getValue("restartStepStart"));
+      UbSchedulerPtr rSch(new UbScheduler(restartStep, restartStepStart));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //int restartS = UbSystem::stringTo<int>(cf.getValue("restartS"));
+      //RestartPostprocessor rp(grid, rSch, comm, pathname, restartS, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+         if (myid == 0) UBLOG(logINFO, "new start..");
+
+         UBLOG(logINFO, "new start PID = " << myid << " Hostname: " << machinename);
+         UBLOG(logINFO, "new start PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO, "new start PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO, "new start PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+
+         string samplePathname = pathGeo + sampleFilename;
+
+         double deltaVoxelX1 = pmL1/(double)pmNX1;
+         double deltaVoxelX2 = pmL2/(double)pmNX2;
+         double deltaVoxelX3 = pmL3/(double)pmNX3;
+
+         GbVoxelMatrix3DPtr sample(new GbVoxelMatrix3D(pmNX1, pmNX2, pmNX3, 0, lthreshold, uthreshold));
+         if (rawFile)
+         {
+            sample->readMatrixFromRawFile<unsigned short>(samplePathname, GbVoxelMatrix3D::BigEndian);
+         }
+         else
+         {
+            sample->readMatrixFromVtiASCIIFile(samplePathname);
+         }
+
+         sample->setVoxelMatrixDelta((float)deltaVoxelX1, (float)deltaVoxelX2, (float)deltaVoxelX3);
+         sample->setVoxelMatrixMininum(0.0, 0.0, 0.0);
+         //sample->rotate90aroundZ();
+
+         if (myid == 0) sample->writeToVTKImageDataASCII(pathname + "/geo/sample");
+
+         ///////////////////////////////////////////////////////
+
+         ////////////////////////////////////////////////////////////////////////
+
+         double offset1 = sample->getLengthX1()/10.0;
+         double offset2 = 2.0*offset1;
+         //bounding box
+         double g_minX1 = sample->getX1Minimum() - offset1;
+         double g_minX2 = sample->getX2Minimum();
+         double g_minX3 = sample->getX3Minimum();
+
+         double g_maxX1 = sample->getX1Maximum() + offset2;
+         double g_maxX2 = sample->getX2Maximum();
+         double g_maxX3 = sample->getX3Maximum();
+
+         //double g_minX1 = 0;
+         //double g_minX2 = 0;
+         //double g_minX3 = 0;
+
+         //double g_maxX1 = 1e-3;
+         //double g_maxX2 = 1e-3;
+         //double g_maxX3 = 1e-3;
+
+         deltax = (g_maxX3-g_minX3) /(nx3*blocknx3);
+
+
+         //double Lp_LB = Lp/deltax;
+         //double nu_LB = (Lp_LB*u_LB)/Re;
+
+         double blockLength = (double)blocknx1*deltax;
+
+         grid->setPeriodicX1(false);
+         grid->setPeriodicX2(false);
+         grid->setPeriodicX3(false);
+         grid->setDeltaX(deltax);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Parameters:");
+            UBLOG(logINFO, "rho_LB = " << rho_LB);
+            UBLOG(logINFO, "nu_LB = " << nu_LB);
+            UBLOG(logINFO, "dp_LB = " << dp_LB);
+            UBLOG(logINFO, "dx = " << deltax << " m");
+            //UBLOG(logINFO, "Lp = " << Lp << " m");
+
+            UBLOG(logINFO, "number of levels = " << refineLevel + 1);
+            UBLOG(logINFO, "numOfThreads = " << numOfThreads);
+            UBLOG(logINFO, "path = " << pathname);
+            UBLOG(logINFO, "Preprozess - start");
+         }
+
+         //walls
+         GbCuboid3DPtr addWallYmin(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_minX2, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax(new GbCuboid3D(g_minX1-blockLength, g_maxX2, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+
+         //inflow
+         GbCuboid3DPtr geoInflow(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_minX1, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname + "/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow(new GbCuboid3D(g_maxX1, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname + "/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+         //bone interactor
+         int bcOptionNoSlip = 1; //0=simple Bounce Back, 1=quadr. BB, 2=thin wall
+         D3Q27BoundaryConditionAdapterPtr bcNoSlip(new D3Q27NoSlipBCAdapter(bcOptionNoSlip));
+         D3Q27InteractorPtr sampleInt(new D3Q27Interactor(sample, grid, bcNoSlip, Interactor3D::SOLID));
+
+         //wall interactors
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcNoSlip, Interactor3D::SOLID));
+
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterInflow(new D3Q27DensityBCAdapter(rhoLBinflow));
+         denBCAdapterInflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoInflow, grid, denBCAdapterInflow, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterOutflow(new D3Q27DensityBCAdapter(rho_LB));
+         denBCAdapterOutflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoOutflow, grid, denBCAdapterOutflow, Interactor3D::SOLID));
+
+         
+         UBLOG(logINFO, "PID = " << myid << " Hostname: " << machinename);
+         UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+
+         ////////////////////////////////////////////
+         //METIS
+         //Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::BSW, MetisPartitioner::RECURSIVE));
+         ////////////////////////////////////////////
+         //Zoltan
+         Grid3DVisitorPtr zoltanVisitor(new ZoltanPartitioningGridVisitor(comm, D3Q27System::BSW, 1));
+         grid->accept(zoltanVisitor);
+         /////delete solid blocks
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, zoltanVisitor);
+         intHelper.addInteractor(addWallYminInt);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallYmaxInt);
+         intHelper.addInteractor(addWallZmaxInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.addInteractor(sampleInt);
+         intHelper.selectBlocks();
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - end");
+         //////////////////////////////////////
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nod = nob * (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nodg = nob * (blocknx1 + gl) * (blocknx2 + gl) * (blocknx3 + gl);
+         double needMemAll = double(nodg*(27 * sizeof(double) + sizeof(int) + sizeof(float) * 4));
+         double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Number of blocks = " << nob);
+            UBLOG(logINFO, "Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for (int level = minInitLevel; level <= maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO, "Number of blocks for level " << level << " = " << nobl);
+               UBLOG(logINFO, "Number of nodes for level " << level << " = " << nobl*nodb);
+            }
+            UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+            UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+            UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel;
+
+         if (spongeLayer)
+         {
+            //with sponge layer
+            double sizeSP = 1;
+            mu::Parser spongeLayer;
+            spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+            spongeLayer.DefineConst("sizeX", grid->getNX1()*blocknx1);
+            spongeLayer.DefineConst("sizeSP", sizeSP*blocknx1);
+
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+            kernel->setWithSpongeLayer(true);
+            kernel->setSpongeLayer(spongeLayer);
+         }
+         else
+         {
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+         }
+
+
+         //mu::Parser fctForcingX3;
+         //fctForcingX3.SetExpr("Fx3");
+         //fctForcingX3.DefineConst("Fx3", forcing);
+
+         //kernel->setForcingX3(fctForcingX3);
+         //kernel->setWithForcing(true);
+
+         //BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         
+         BoundaryConditionPtr densityBC(new NonEqDensityBoundaryCondition());
+         //BoundaryConditionPtr noSlipBC(new HighViscosityNoSlipBoundaryCondition());
+         BoundaryConditionPtr noSlipBC(new NoSlipBoundaryCondition());
+
+         bcProc->addBC(densityBC);
+         bcProc->addBC(noSlipBC);
+
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nu_LB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+
+         //BC
+         intHelper.setBC();
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         //Press*1.6e8+(14.76-coordsX)/3.5*5000
+         //initialization of distributions
+         mu::Parser fct;
+         fct.SetExpr("(x1max-x1)/l*dp*3.0");
+         fct.DefineConst("dp", dp_LB);
+         fct.DefineConst("x1max", g_maxX1);
+         fct.DefineConst("l", g_maxX1-g_minX1);
+
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nu_LB, rho_LB);
+         initVisitor.setRho(fct);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         coord[0] = sample->getX1Minimum();
+         coord[1] = sample->getX2Minimum();
+         coord[2] = sample->getX3Minimum();
+         coord[3] = sample->getX1Maximum();
+         coord[4] = sample->getX2Maximum();
+         coord[5] = sample->getX3Maximum();
+
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "w");
+         fprintf(pFile, "%g\n", deltax);
+         fprintf(pFile, "%g\n", coord[0]);
+         fprintf(pFile, "%g\n", coord[1]);
+         fprintf(pFile, "%g\n", coord[2]);
+         fprintf(pFile, "%g\n", coord[3]);
+         fprintf(pFile, "%g\n", coord[4]);
+         fprintf(pFile, "%g\n", coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+         grid->addInteractor(inflowInt);
+         //grid->addInteractor(outflowInt);
+
+         if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+      }
+      else
+      {
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "r");
+         fscanf(pFile, "%lg\n", &deltax);
+         fscanf(pFile, "%lg\n", &coord[0]);
+         fscanf(pFile, "%lg\n", &coord[1]);
+         fscanf(pFile, "%lg\n", &coord[2]);
+         fscanf(pFile, "%lg\n", &coord[3]);
+         fscanf(pFile, "%lg\n", &coord[4]);
+         fscanf(pFile, "%lg\n", &coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+         //new nu
+         //ViscosityBlockVisitor nuVisitor(nu_LB);
+         //grid->accept(nuVisitor);
+
+         Grid3D::Interactor3DSet interactors = grid->getInteractors();
+         interactors[0]->setGrid3D(grid);
+         boost::dynamic_pointer_cast<D3Q27Interactor>(interactors[0])->deleteBCAdapter();
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterFront(new D3Q27DensityBCAdapter(rhoLBinflow));
+         boost::dynamic_pointer_cast<D3Q27Interactor>(interactors[0])->addBCAdapter(denBCAdapterFront);
+         interactors[0]->updateInteractor();
+
+
+         //if (StringUtil::toBool(cf.getValue("changeKernel")))
+         //{
+         //   if (myid == 0)
+         //   {
+         //      UBLOG(logINFO, "chahge to LBMKernelETD3Q27CCLBWithSpongeLayer");
+         //   }
+         //   double sizeSP = 5e-4;
+         //   mu::Parser spongeLayer;
+         //   spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+         //   spongeLayer.DefineConst("sizeX", grid->getNX1()*blocknx1);
+         //   spongeLayer.DefineConst("sizeSP", sizeSP/deltax);
+
+         //   //with sponge layer
+         //   LBMKernel3DPtr kernel;
+         //   kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+         //   kernel->setWithSpongeLayer(true);
+         //   kernel->setSpongeLayer(spongeLayer);
+
+         //   BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         //   kernel->setBCProcessor(bcProc);
+         //   SetKernelBlockVisitor kernelVisitor(kernel, nu_LB, 1, 0,SetKernelBlockVisitor::Change);
+         //   grid->accept(kernelVisitor);
+         //}
+
+         //SetSpongeLayerBlockVisitor ssp(spongeLayer);
+         //grid->accept(ssp);
+
+         //ChangeBoundaryDensityBlockVisitor(0.03, rhoLBinflow);
+
+         if (myid == 0)
+         {
+	         UBLOG(logINFO, "Parameters:");
+	         UBLOG(logINFO, "rho_LB = " << rho_LB);
+	         UBLOG(logINFO, "nu_LB = " << nu_LB);
+	         UBLOG(logINFO, "dp_LB = " << dp_LB);
+	         UBLOG(logINFO, "dx = " << deltax << " m");
+	         //UBLOG(logINFO, "Lp = " << Lp << " m");
+         }
+
+         //new dp
+         //Grid3D::Interactor3DSet interactors = grid->getInteractors();
+         //interactors[0]->setGrid3D(grid);
+         //boost::dynamic_pointer_cast<D3Q27Interactor>(interactors[0])->deleteBCAdapter();
+         //D3Q27BoundaryConditionAdapterPtr denBCAdapterFront(new D3Q27DensityBCAdapter(rhoLBinflow));
+         //boost::dynamic_pointer_cast<D3Q27Interactor>(interactors[0])->addBCAdapter(denBCAdapterFront);
+         //interactors[0]->updateInteractor();
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+      }
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      //vector<double> nupsStep = StringUtil::toVector<double>(cf.getValue("nupsStep"));
+      //nupsSch->addSchedule(nupsStep[0], nupsStep[1], nupsStep[2]);
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      //double outTime = UbSystem::stringTo<double>(cf.getValue("outTime"));
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      //stepSch->addSchedule(10, 10, 10);
+      //stepSch->addSchedule(100, 100, 100);
+      //stepSch->addSchedule(1000, 1000, 1000);
+      //stepSch->addSchedule(100, 1500, 2000);
+      //stepSch->addSchedule(10000, 10000, 10000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+      deltax = grid->getDeltaX(baseLevel);
+      double dxd2 = deltax / 2.0;
+
+      D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, coord[0] - dxd2*10.0, coord[1] - dxd2, coord[2] - dxd2,
+         coord[0] - dxd2*10.0 - 2.0*dxd2, coord[4] + dxd2, coord[5] + dxd2));
+
+      //D3Q27IntegrateValuesHelperPtr ih2(new D3Q27IntegrateValuesHelper(grid, comm, coord[3]/2.0, coord[1] - dxd2, coord[2] - dxd2,
+      //   coord[3]/2.0 + 2.0*dxd2, coord[4] + dxd2, coord[5] + dxd2));
+      D3Q27IntegrateValuesHelperPtr ih2(new D3Q27IntegrateValuesHelper(grid, comm, coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]));
+
+      D3Q27IntegrateValuesHelperPtr ih3(new D3Q27IntegrateValuesHelper(grid, comm, coord[3] + dxd2*10.0, coord[1] - dxd2, coord[2] - dxd2,
+         coord[3] + dxd2*10.0 + 2.0*dxd2, coord[4] + dxd2, coord[5] + dxd2));
+
+      //D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]));
+      if (myid == 0) GbSystem3D::writeGeoObject(ih1->getBoundingBox().get(), pathname + "/geo/ih1", WbWriterVtkXmlBinary::getInstance());
+      if (myid == 0) GbSystem3D::writeGeoObject(ih2->getBoundingBox().get(), pathname + "/geo/ih2", WbWriterVtkXmlBinary::getInstance());
+      if (myid == 0) GbSystem3D::writeGeoObject(ih3->getBoundingBox().get(), pathname + "/geo/ih3", WbWriterVtkXmlBinary::getInstance());
+
+      double factorp = 1; // dp_real / dp_LB;
+      double factorv = 1;// dx / dt;
+      UbSchedulerPtr stepMV(new UbScheduler(timeSeriesOutTime));
+      
+      TimeseriesPostprocessor tsp1(grid, stepMV, ih1, pathname+timeSeriesFile+"_1", comm);
+      TimeseriesPostprocessor tsp2(grid, stepMV, ih2, pathname+timeSeriesFile+"_2", comm);
+      TimeseriesPostprocessor tsp3(grid, stepMV, ih3, pathname+timeSeriesFile+"_3", comm);
+      //D3Q27MeanValuesPostprocessor mvp1(grid, stepMV, pathname + "/mv/mv1.txt", comm, ih1, factorp, factorv);
+
+
+      //D3Q27IntegrateValuesHelperPtr ih2(new D3Q27IntegrateValuesHelper(grid, comm, g_maxX1-2.0*deltax, g_minX2, g_minX3,
+      //   g_maxX1 - deltax, g_maxX2, g_maxX3));
+      //if (myid == 0) GbSystem3D::writeGeoObject(ih2->getBoundingBox().get(), pathname + "/geo/ih2", WbWriterVtkXmlBinary::getInstance());
+
+      //D3Q27MeanValuesPostprocessor mvp2(grid, stepSch, pathname + "/mv/mv2.txt", comm, ih2, factorp, factorv);
+
+      if (myid == 0)
+      {
+         UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      //double endTime = UbSystem::stringTo<double>(cf.getValue("endTime")); //100001;//10001.0;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepMV, bcProcessor/*, CalculationManager::PrePost*/));
+      if (myid == 0) UBLOG(logINFO, "Simulation-start");
+      calculation->calculate();
+      if (myid == 0) UBLOG(logINFO, "Simulation-end");
+   }
+   catch (exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch (string& s)
+   {
+      cerr << s << endl;
+   }
+   catch (...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+
+   if (argv != NULL)
+   {
+      if (argv[1] != NULL)
+      {
+         perm(argv[1]);
+      }
+      else
+      {
+         cout << "Configuration file is missing!" << endl;
+      }
+   }
+
+   return 0;
+}
diff --git a/source/Applications/perm/perm.cpp_s b/source/Applications/perm/perm.cpp_s
new file mode 100644
index 0000000000000000000000000000000000000000..799c6d50c7d22b2c12347773da3144890f5049ec
--- /dev/null
+++ b/source/Applications/perm/perm.cpp_s
@@ -0,0 +1,442 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void perm(const char *configname)
+{
+   try
+   {
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname, pathGeo;
+      int numOfThreads;
+      double availMem;
+
+      ConfigFileReader cf(configname);
+      if (!cf.read())
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if (machine == "BOMBADIL")
+      {
+         numOfThreads = 4;
+         pathname = "d:/temp/perm";
+         pathGeo = "d:/Projects/SFB880/GeometrienPoroeseMedien/Allu_80-110";
+         availMem = 15.0e9;
+      }
+      else //if (machine == "M01" || machine == "M02")
+      {
+         numOfThreads = UbSystem::stringTo<int>(cf.getValue("numOfTreads"));
+         pathname = cf.getValue("pathname");
+         pathGeo = cf.getValue("pathGeo");
+         availMem = 12.0e9;
+
+#if defined(__unix__)
+         if (myid == 0)
+         {
+            const char* str = pathname.c_str();
+            int status = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+         }
+#endif 
+
+         if (myid == 0)
+         {
+            stringstream logFilename;
+            logFilename << pathname + "/logfile" + UbSystem::toString(UbSystem::getTimeStamp()) + ".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      //else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+
+
+      if (myid == 0) UBLOG(logINFO, "Testcase permebility");
+
+      Grid3DPtr grid(new Grid3D(comm));
+  
+      const int blocknx1 = 64;
+      const int blocknx2 = 64;
+      const int blocknx3 = 64;
+
+      LBMReal rho_LB = 0.0;
+
+      //Re = (Lp*u)/nu, Lp - size of pore, u - volume-avaraged velocity, nu - viscositi
+      double Re = 1.0;
+      double u_LB = 0.01;
+
+      //dp/dx ~ u for laminar flow
+      double dp_LB = 0.0001;
+      double rhoLBinflow = dp_LB*3.0;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      double nx3 = 3.0; //number of blocks for z
+      double deltax;
+      double coord[6];
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(50000, 50000, 10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+         if (myid == 0) UBLOG(logINFO, "Neustart..");
+
+         string sampleFilename = pathGeo + "/alu_80-110.vti";
+
+         int pmNX1 = 200;  //abmessung einzelbild in x-richtung
+         int pmNX2 = 200; //abmessung einzelbild in y richtung
+         int pmNX3 = 200; //anzahl der bilder
+
+         float lthreshold = 29041.0;
+         float uthreshold = 65535.0;
+         double deltaVoxelX1 = 4e-3/1096.0;
+         double deltaVoxelX2 = 5e-3/1327.0;
+         double deltaVoxelX3 = 5e-3/1265.0;
+
+
+         GbVoxelMatrix3DPtr sample(new GbVoxelMatrix3D(pmNX1, pmNX2, pmNX3, 0, lthreshold, uthreshold));
+         //sample->readMatrixFromRawFile<unsigned char>(sampleFilename, GbVoxelMatrix3D::BigEndian);
+         sample->readMatrixFromVtiASCIIFile(sampleFilename);
+         sample->setVoxelMatrixDelta(deltaVoxelX1, deltaVoxelX2, deltaVoxelX3);
+         sample->setVoxelMatrixMininum(0.0, 0.0, 0.0);
+
+         if (myid == 0) sample->writeToVTKImageDataASCII(pathname + "/geo/sample");
+
+         ///////////////////////////////////////////////////////
+
+         ////////////////////////////////////////////////////////////////////////
+
+         double offset = 0.2e-3; //0.5e-3;
+         //bounding box
+         double g_minX1 = sample->getX1Minimum() - offset;
+         double g_minX2 = sample->getX2Minimum();
+         double g_minX3 = sample->getX3Minimum();
+
+         double g_maxX1 = sample->getX1Maximum() + offset;
+         double g_maxX2 = sample->getX2Maximum();
+         double g_maxX3 = sample->getX3Maximum();
+
+         deltax = (g_maxX3-g_minX3) /(nx3*blocknx3);
+
+         double Lp = 90e-6/deltax;
+         double nu_LB = (Lp*u_LB)/Re;
+
+
+         double blockLength = (double)blocknx1*deltax;
+
+         grid->setPeriodicX1(false);
+         grid->setPeriodicX2(false);
+         grid->setPeriodicX3(false);
+         grid->setDeltaX(deltax);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Parameters:");
+            //UBLOG(logINFO, "with forcing = " << with_forcing);
+            UBLOG(logINFO, "rho_LB = " << rho_LB);
+            UBLOG(logINFO, "nu_LB = " << nu_LB);
+            UBLOG(logINFO, "dp_LB = " << dp_LB);
+            UBLOG(logINFO, "u_LB = " << u_LB);
+            //UBLOG(logINFO, "forcing = " << forcing);
+            UBLOG(logINFO, "dx = " << deltax << " m");
+            //UBLOG(logINFO, "dt = " << dt << " s");
+            //UBLOG(logINFO, "rho_real = " << rho_real << " kg*m^-3");
+            //UBLOG(logINFO, "nu_real = " << nu_real << " m^2/s");
+            //UBLOG(logINFO, "dp_real = " << dp_real << " Pa");
+
+            UBLOG(logINFO, "number of levels = " << refineLevel + 1);
+            UBLOG(logINFO, "numOfThreads = " << numOfThreads);
+            UBLOG(logINFO, "path = " << pathname);
+            UBLOG(logINFO, "Preprozess - start");
+         }
+
+         //walls
+         GbCuboid3DPtr addWallYmin(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_minX2, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax(new GbCuboid3D(g_minX1-blockLength, g_maxX2, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+
+         //inflow
+         GbCuboid3DPtr geoInflow(new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_minX1, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname + "/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow(new GbCuboid3D(g_maxX1, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+         if (myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname + "/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+         //bone interactor
+         int bcOptionNoSlip = 1; //0=simple Bounce Back, 1=quadr. BB, 2=thin wall
+         D3Q27BoundaryConditionAdapterPtr bcNoSlip(new D3Q27NoSlipBCAdapter(bcOptionNoSlip));
+         D3Q27InteractorPtr sampleInt(new D3Q27Interactor(sample, grid, bcNoSlip, Interactor3D::SOLID));
+
+         //wall interactors
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcNoSlip, Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcNoSlip, Interactor3D::SOLID));
+
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterInflow(new D3Q27DensityBCAdapter(rhoLBinflow));
+         denBCAdapterInflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoInflow, grid, denBCAdapterInflow, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterOutflow(new D3Q27DensityBCAdapter(rho_LB));
+         denBCAdapterOutflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoOutflow, grid, denBCAdapterOutflow, Interactor3D::SOLID));
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::BSW));
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(sampleInt);
+         intHelper.addInteractor(addWallYminInt);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallYmaxInt);
+         intHelper.addInteractor(addWallZmaxInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+         if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - end");
+         //////////////////////////////////////
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nodb = (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nod = nob * (blocknx1)* (blocknx2)* (blocknx3);
+         unsigned long nodg = nob * (blocknx1 + gl) * (blocknx2 + gl) * (blocknx3 + gl);
+         double needMemAll = double(nodg*(27 * sizeof(double) + sizeof(int) + sizeof(float) * 4));
+         double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Number of blocks = " << nob);
+            UBLOG(logINFO, "Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for (int level = minInitLevel; level <= maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO, "Number of blocks for level " << level << " = " << nobl);
+               UBLOG(logINFO, "Number of nodes for level " << level << " = " << nobl*nodb);
+            }
+            UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+            UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+            UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+         }
+
+         LBMKernel3DPtr kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         //mu::Parser fctForcingX3;
+         //fctForcingX3.SetExpr("Fx3");
+         //fctForcingX3.DefineConst("Fx3", forcing);
+
+         //kernel->setForcingX3(fctForcingX3);
+         //kernel->setWithForcing(true);
+
+         //BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nu_LB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+
+         //BC
+         intHelper.setBC();
+
+         //Press*1.6e8+(14.76-coordsX)/3.5*5000
+         //initialization of distributions
+         //mu::Parser fct;
+         //fct.SetExpr("(x1max-x1)/l*dp*3.0");
+         //fct.DefineConst("dp", dp_LB);
+         //fct.DefineConst("x3max", g_maxX3);
+         //fct.DefineConst("l", g_maxX3-g_minX3);
+
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nu_LB, rho_LB);
+         //initVisitor.setRho(fct);
+         //initVisitor.setVx1(fct);
+         initVisitor.setVx1(0);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         coord[0] = sample->getX1Minimum();
+         coord[1] = sample->getX2Minimum();
+         coord[2] = sample->getX3Minimum();
+         coord[3] = sample->getX1Maximum();
+         coord[4] = sample->getX2Maximum();
+         coord[5] = sample->getX3Maximum();
+
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "w");
+         fprintf(pFile, "%f\n", deltax);
+         fprintf(pFile, "%f\n", coord[0]);
+         fprintf(pFile, "%f\n", coord[1]);
+         fprintf(pFile, "%f\n", coord[2]);
+         fprintf(pFile, "%f\n", coord[3]);
+         fprintf(pFile, "%f\n", coord[4]);
+         fprintf(pFile, "%f\n", coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+
+         if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+      }
+      else
+      {
+         ////////////////////////////////////////////////////////
+         FILE * pFile;
+         string str = pathname + "/checkpoints/coord.txt";
+         pFile = fopen(str.c_str(), "r");
+         fscanf(pFile, "%f\n", &deltax);
+         fscanf(pFile, "%f\n", &coord[0]);
+         fscanf(pFile, "%f\n", &coord[1]);
+         fscanf(pFile, "%f\n", &coord[2]);
+         fscanf(pFile, "%f\n", &coord[3]);
+         fscanf(pFile, "%f\n", &coord[4]);
+         fscanf(pFile, "%f\n", &coord[5]);
+         fclose(pFile);
+         ////////////////////////////////////////////////////////
+
+         double Lp = 0.35e-3/deltax;
+         double nu_LB = (Lp*u_LB)/Re;
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+         grid->accept(setConnsVisitor);
+
+
+
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+      }
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      double outTime = 30000;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      stepSch->addSchedule(10, 10, 10);
+      stepSch->addSchedule(100, 100, 100);
+      stepSch->addSchedule(1000, 1000, 1000);
+      stepSch->addSchedule(100, 1500, 2000);
+      stepSch->addSchedule(10000, 10000, 10000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+      double dxd2 = deltax / 2.0;
+      //D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, coord[0] - dxd2, coord[1] - dxd2, coord[2] - dxd2,
+      //   coord[3] + dxd2, coord[4] + dxd2, coord[5] + dxd2));
+      //if (myid == 0) GbSystem3D::writeGeoObject(ih1->getBoundingBox().get(), pathname + "/geo/ih1", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, coord[3] + dxd2, coord[1] - dxd2, coord[2] - dxd2,
+         coord[3] + 2.0*dxd2, coord[4] + dxd2, coord[5] + dxd2));
+      if (myid == 0) GbSystem3D::writeGeoObject(ih1->getBoundingBox().get(), pathname + "/geo/ih1", WbWriterVtkXmlBinary::getInstance());
+
+      double factorp = 1; // dp_real / dp_LB;
+      double factorv = 1;// dx / dt;
+      UbSchedulerPtr stepMV(new UbScheduler(1));
+      D3Q27MeanValuesPostprocessor mvp1(grid, stepMV, pathname + "/mv/mv1.txt", comm, ih1, factorp, factorv);
+
+
+      //D3Q27IntegrateValuesHelperPtr ih2(new D3Q27IntegrateValuesHelper(grid, comm, g_maxX1-2.0*deltax, g_minX2, g_minX3,
+      //   g_maxX1 - deltax, g_maxX2, g_maxX3));
+      //if (myid == 0) GbSystem3D::writeGeoObject(ih2->getBoundingBox().get(), pathname + "/geo/ih2", WbWriterVtkXmlBinary::getInstance());
+
+      //D3Q27MeanValuesPostprocessor mvp2(grid, stepSch, pathname + "/mv/mv2.txt", comm, ih2, factorp, factorv);
+
+      if (myid == 0)
+      {
+         UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe());
+      }
+
+      double endTime = UbSystem::stringTo<double>(cf.getValue("endTime")); //100001;//10001.0;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepMV));
+      if (myid == 0) UBLOG(logINFO, "Simulation-start");
+      calculation->calculate();
+      if (myid == 0) UBLOG(logINFO, "Simulation-end");
+   }
+   catch (exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch (string& s)
+   {
+      cerr << s << endl;
+   }
+   catch (...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+
+   if (argv != NULL)
+   {
+      perm(argv[1]);
+   }
+
+   return 0;
+}
diff --git a/source/Applications/plate/CMakeLists.txt b/source/Applications/plate/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e239e51050d988321fbdd347bd1d89722c788d2a
--- /dev/null
+++ b/source/Applications/plate/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(plate)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(plate BINARY)
diff --git a/source/Applications/plate/plate.cpp b/source/Applications/plate/plate.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cb851e89625c1033fd58460070b5c35b5d923692
--- /dev/null
+++ b/source/Applications/plate/plate.cpp
@@ -0,0 +1,652 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr, double endTime)
+{
+   try
+   {
+      string pathname; 
+      string pathGeo;
+      string pathLog;
+      string PlatteFilename;
+      string ZckbndFilename;
+      int numOfThreads = 1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      //UbLog::reportingLevel() = logDEBUG5;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr);
+
+      if(machine == "my") 
+      {
+         pathname = "d:/temp/plate";
+         pathGeo = "d:/Data/plate";
+         pathLog = "d:/temp/plate";
+         numOfThreads = 6;
+         logfile = false;
+         availMem = 15.0e9;
+      }
+      else if(machine == "Ludwig")      
+      {
+         pathname = "/work/koskuche/SFB880/plateR1e06";
+         pathGeo = "/home/koskuche/data/plate";
+         pathLog = "/work/koskuche/SFB880/plateR1e06";
+         numOfThreads = 1;
+         availMem = 1.0e9;
+         logfile = true;
+      }
+      else if(machine == "Hermit")      
+      {
+         //Hermit
+         pathname = "/univ_1/ws1/ws/xrmkuchr-plate3-0";
+         pathGeo = "/zhome/academic/HLRS/xrm/xrmkuchr/data/plate";
+         pathLog = "/zhome/academic/HLRS/xrm/xrmkuchr/work/plate";
+         numOfThreads = 16;
+         availMem = 2.0e9;
+         logfile = true;
+      }
+      else if(machine == "HLRN")      
+      {
+         //Hermit
+         pathname = "/gfs1/work/niivfcpu/scratch/plate";
+         pathGeo = "/gfs1/work/niivfcpu/data/plate";
+         pathLog = "/gfs1/work/niivfcpu/scratch/plate";
+         numOfThreads = 24;
+         availMem = 12.0e9;
+         logfile = true;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+#if defined(__unix__)
+      if (myid==0) 
+      {
+         const char* str = pathLog.c_str();
+         int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      }
+#endif 
+
+      if(myid == 0 && logfile)
+      {
+         logFilename <<  pathLog + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+      }
+
+      if(myid ==0 && logfile)
+      {
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      if(myid==0) UBLOG(logINFO,"Testcase plate");
+
+      PlatteFilename = pathGeo + "/platte_raw.stl"; 
+      ZckbndFilename= pathGeo + "/2zackenbaender0.stl";
+
+      int baseLevel, refineLevel,nx[3],blocknx[3];
+      double Re,velocity,rhoInit,vx1Init;
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      Re            = 1e6; //11900;// 13286;//13286;//gemessen 18.98 m/s...*spaeter koorestur michael moessner 17m/s
+      velocity      = 0.1;  
+      vx1Init       = 0.1;  
+      rhoInit       = 0.0;
+
+      //int H=200;//200;//392;
+      ///////////////Knotenabmessungen:
+      nx[0]      = 50;//240;//120;//60;//86;//43;//65;//50;  //länge
+      nx[1]      = 1;//2;//6;///1;//5;// //breite
+      nx[2]      = 16;//64;//32;//18;//5;//15;//15; //höhe gebiet
+      blocknx[0] = 25;//10;//6;
+      blocknx[1] = 25;//10;//6;
+      blocknx[2] = 25;//10;//6;
+
+      baseLevel   = 0;
+      refineLevel = 4;
+
+      ///////////////Weltabmessungen:
+      double kanalhoeheSI  = 60.0/100.0;//60.0/100.0;//cm, Kanalhöhe
+      double kanalbreiteSI = kanalhoeheSI*((double)nx[1])/((double)nx[2]);//=kanalhöhe*nx1/nx2//1.65/100.0;//13.2/100.0;////40.0/100.0; //cm, Kanalbreite //13.2 zeilbreite
+      double kanallaengeSI = kanalhoeheSI*((double)nx[0])/((double)nx[2]);//80.0/100.0;//cm, Kanallänge, ist nicht angegeben
+
+      // double refinewidth1=kanalhoeheSI/10.0;
+
+
+      double fineNodeDx   = (kanalhoeheSI) / (double)( blocknx[2]*nx[2]*(1<<refineLevel)+1 ); //+1--> gitter liegt jeweils 0.5dx innerhalb
+      //double fineNodeDx   = hReal/100.0;
+      double coarseNodeDx = fineNodeDx * (double)(1<<refineLevel);//geowerte
+
+      double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+      double blockLengthx2 = blockLengthx1;
+      double blockLengthx3 = blockLengthx1;
+
+      double originX1 = 0.0;//-50.0*propellerDurchmesser;  //geowerte
+      double originX2 = 0.0;//-0.5*blockLengthx2*nx2;
+      double originX3 = 0.0;// minX3 + 0.5*fineNodeDx;
+
+      double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      //position vorderkante cube
+      double originBridgeX1 = 20.0/100.0; //cm, geraten
+      double originBridgeX2 = 0.0;//0.5*params.nx[1]*blockLengthx2-0.5*H-fineNodeDx;
+      double originBridgeX3 = kanalhoeheSI*0.5;//H*0.0-fineNodeDx; //boden
+
+      bool periodicx1 = false;
+      bool periodicx2 = true;
+      bool periodicx3 = true;
+
+      //##########################################################################
+      //## physical parameters
+      //##########################################################################
+      double rhoLB         = rhoInit;
+      double rhoReal       = 1.0;
+      double nuReal  = 0.000015;//0.015;
+
+      double hReal         = 0.0105;//<-m     1.05;//Plattendicke in cm(! cm nicht m !)
+      double uReal         = 15;//m/s   //Re*nueReal/hReal;
+      double lReal         = 1; //m Plattenlänge
+
+      //##Machzahl:
+      //#Ma     = uReal/csReal
+      double Ma      = 0.05;//0.0553;//Ma-Real!
+      double csReal  = 343; //uReal/Ma;
+      double hLB     = hReal/coarseNodeDx;
+
+      //LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(hReal, csReal, rhoReal, hLB));
+      //LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(hReal, LBMUnitConverter::AIR_20C, hLB));
+      
+
+      double uLB           = 0.1; //uReal   * unitConverter->getFactorVelocityWToLb();
+      //double nuLB         = nueReal * unitConverter->getFactorViscosityWToLb();
+      double nuLB         = (uLB*(lReal/coarseNodeDx))/Re;
+      //double timestep      = unitConverter->getFactorTimeLbToW(coarseNodeDx);
+
+      
+      //LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(0, uReal, uLB, nuReal, nuLB));
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+      
+      velocity = uLB;
+      double viscosity = nuLB;
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(10000,10000,10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      int sizeSP=4;
+      mu::Parser spongeLayer;
+      //spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+      spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-x1)/sizeSP/2.0 + 0.5 : 1.0");
+      spongeLayer.DefineConst("sizeX", nx[0]*blocknx[0]);
+      spongeLayer.DefineConst("sizeSP", sizeSP*blocknx[0]);
+
+      if (grid->getTimeStep() == 0)
+      {
+         if(myid==0) UBLOG(logINFO,"Neustart..");
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];
+
+         //set grid
+         grid->setDeltaX(coarseNodeDx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         /////////////////////////////////////////////////
+         //interactoren definieren
+         double geoOverlap = 3.0*coarseNodeDx;
+
+         //inflow
+         GbCuboid3DPtr velBCCuboid(new GbCuboid3D(originX1-geoOverlap, originX2-geoOverlap, originX3-geoOverlap, 
+            originX1/*+coarseNodeDx*/, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap));
+         if(myid == 0) GbSystem3D::writeGeoObject(velBCCuboid.get(), pathname+"/geo/velBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(velBCCuboid,grid,Interactor3D::SOLID)); 
+
+         //inflow
+         double uLB2=uLB*0.96*1.02;//*0.5;
+         double raiseVelSteps = 0;
+         vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("uLB"); 
+
+         inflowProfile.DefineConst("uLB",uLB);
+         velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (velcX1BCs,dummy,dummy));
+         velBCInteractor->addBCAdapter(velBCAdapter);
+
+         //outflow
+         GbCuboid3DPtr densCuboid(new GbCuboid3D(originX1+geoLength[0], originX2-geoOverlap, originX3-geoOverlap, 
+            originX1+geoLength[0]+geoOverlap, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap ));
+         if(myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname+"/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoInit));
+         D3Q27InteractorPtr densInteractor( new D3Q27Interactor(densCuboid,grid,denBCAdapter,Interactor3D::SOLID) );
+
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            ="<<Re);
+            UBLOG(logINFO, "* Ma            ="<<Ma);
+            UBLOG(logINFO, "* uReal         ="<<uReal);
+            UBLOG(logINFO, "* nueReal       ="<<nuReal);
+            UBLOG(logINFO, "* nueLB         ="<<nuLB);
+            UBLOG(logINFO, "* uLB           ="<<uLB);
+            UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+            UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+            UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+            UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+            UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+            UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x1Periodic    ="<<periodicx1);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "* number of levels  ="<<refineLevel+1);
+            UBLOG(logINFO, "* path          ="<<pathname);
+
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* number of threads    ="<<numOfThreads);
+            UBLOG(logINFO, "* number of processes  ="<<comm->getNumberOfProcesses());
+            UBLOG(logINFO, "*****************************************");
+            //UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+            UBLOG(logINFO, "*****************************************");     
+         }
+         //////////////////////////////////////////////////////////////////////////
+         //Platte
+         GbTriFaceMesh3DPtr mesh (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(PlatteFilename,"Netz"));
+
+         double x1minMesh = mesh->getX1Minimum(); double x1maxMesh = mesh->getX1Maximum();
+         double x2minMesh = mesh->getX2Minimum(); double x2maxMesh = mesh->getX2Maximum();
+         double x3minMesh = mesh->getX3Minimum(); double x3maxMesh = mesh->getX3Maximum();
+
+         double drehpunktX=x1minMesh+(x1maxMesh-x1minMesh)*0.5;//triFaceMeshS->getX1Centroid();
+         double drehpunktZ=x3minMesh+(x3maxMesh-x3minMesh)*0.5;//triFaceMeshS->getX3Centroid();
+         double drehpunktY=x2minMesh+(x2maxMesh-x2minMesh)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+         mesh->rotate(90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+
+         x1minMesh = mesh->getX1Minimum();  x1maxMesh = mesh->getX1Maximum();
+         x2minMesh = mesh->getX2Minimum();  x2maxMesh = mesh->getX2Maximum();
+         x3minMesh = mesh->getX3Minimum();  x3maxMesh = mesh->getX3Maximum();
+
+         drehpunktX=x1minMesh+(x1maxMesh-x1minMesh)*0.5;//triFaceMeshS->getX1Centroid();
+         drehpunktZ=x3minMesh+(x3maxMesh-x3minMesh)*0.5;//triFaceMeshS->getX3Centroid();
+         drehpunktY=x2minMesh+(x2maxMesh-x2minMesh)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+         double H3=1.05/100.0;//cm, Plattendicke
+         double scaleB=H3/(x3maxMesh-x3minMesh);
+         double scaleX2=(geoLength[2]+2.0*coarseNodeDx)/(x2minMesh-x2maxMesh);
+
+         mesh->scale(scaleB,scaleB,scaleB);
+         x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+         x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+         x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+         double offsetXBridge=originBridgeX1;//originBridgeX1;
+         double offsetYBridge=originBridgeX2;//originBridgeX2;
+         double offsetZBridge=originBridgeX3;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+         //mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh-0.5*offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge); 
+         mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh+offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge-(x3maxMesh-x3minMesh)*0.5/*-hReal*2.0*/); 
+
+         x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+         x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+         x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+
+         if(myid == 0) GbSystem3D::writeGeoObject( mesh.get(), pathname+"/geo/platte", WbWriterVtkXmlBinary::getInstance() );
+
+         //////////////////////////////////////////////////////////////////////////
+         // Zackenband
+         //////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr meshBand (GbTriFaceMesh3DCreator::readMeshFromFile(ZckbndFilename, "NetzBand"));
+         meshBand->deleteRedundantNodes();
+
+         double x1minMeshB = meshBand->getX1Minimum(); double x1maxMeshB = meshBand->getX1Maximum();
+         double x2minMeshB = meshBand->getX2Minimum(); double x2maxMeshB = meshBand->getX2Maximum();
+         double x3minMeshB = meshBand->getX3Minimum(); double x3maxMeshB = meshBand->getX3Maximum();
+
+         x1minMeshB = meshBand->getX1Minimum();  x1maxMeshB = meshBand->getX1Maximum();
+         x2minMeshB = meshBand->getX2Minimum();  x2maxMeshB = meshBand->getX2Maximum();
+         x3minMeshB = meshBand->getX3Minimum();  x3maxMeshB = meshBand->getX3Maximum();
+
+         double H1B=1.05/100.0;//*2.0;//0.05;//cm, Banddicke..nachschauen!!!
+         double scaleBand=H1B/(x1maxMeshB-x1minMeshB);//H3B/(x3maxMeshB-x3minMeshB);
+
+         meshBand->scale(scaleBand,scaleBand,scaleBand);
+         x1minMeshB = meshBand->getX1Minimum(); x1maxMeshB = meshBand->getX1Maximum();
+         x2minMeshB = meshBand->getX2Minimum(); x2maxMeshB = meshBand->getX2Maximum();
+         x3minMeshB = meshBand->getX3Minimum(); x3maxMeshB = meshBand->getX3Maximum();
+         double dBandX=0.5/100.0;//1.29; //15mm-2.1mm Absand von Bandvorderkante
+         double dBandY=0.0/100.0;
+         double dBandZ=0.223/100.0;//0.344;//....
+         double offsetXBridgeB=x1minMesh+dBandX;//originBridgeX1+dBandX;//originBridgeX1;
+         double offsetYBridgeB=originBridgeX2+dBandY;//originBridgeX2;
+         double offsetZBridgeB=originBridgeX3+dBandZ;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+         meshBand->translate(-x1minMeshB+offsetXBridgeB, -x2minMeshB+offsetYBridgeB-coarseNodeDx, -x3minMeshB+offsetZBridgeB);//-(x3maxMeshB-x3minMeshB)*0.5); 
+
+         x1minMeshB = meshBand->getX1Minimum(); x1maxMeshB = meshBand->getX1Maximum();
+         x2minMeshB = meshBand->getX2Minimum(); x2maxMeshB = meshBand->getX2Maximum();
+         x3minMeshB = meshBand->getX3Minimum(); x3maxMeshB = meshBand->getX3Maximum();
+
+         GbSystem3D::writeGeoObject( meshBand.get(), pathname+"/geo/Band", WbWriterVtkXmlASCII::getInstance() );
+
+         /////////////////Band2
+         GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::readMeshFromFile(ZckbndFilename, "NetzBand2"));
+         meshBand->deleteRedundantNodes();
+
+         double x1minMeshB2 = meshBand2->getX1Minimum(); double x1maxMeshB2 = meshBand2->getX1Maximum();
+         double x2minMeshB2 = meshBand2->getX2Minimum(); double x2maxMeshB2 = meshBand2->getX2Maximum();
+         double x3minMeshB2 = meshBand2->getX3Minimum(); double x3maxMeshB2 = meshBand2->getX3Maximum();
+
+         x1minMeshB2 = meshBand2->getX1Minimum();  x1maxMeshB2 = meshBand2->getX1Maximum();
+         x2minMeshB2 = meshBand2->getX2Minimum();  x2maxMeshB2 = meshBand2->getX2Maximum();
+         x3minMeshB2 = meshBand2->getX3Minimum();  x3maxMeshB2 = meshBand2->getX3Maximum();
+
+         double H1B2=1.05/100.0;//0.05;//cm, Banddicke..nachschauen!!!
+         double scaleBand2=H1B2/(x1maxMeshB2-x1minMeshB2);//*3.0;//H3B/(x3maxMeshB-x3minMeshB);
+
+         meshBand2->scale(scaleBand2,scaleBand2,scaleBand2);
+         x1minMeshB2 = meshBand2->getX1Minimum(); x1maxMeshB2 = meshBand2->getX1Maximum();
+         x2minMeshB2 = meshBand2->getX2Minimum(); x2maxMeshB2 = meshBand2->getX2Maximum();
+         x3minMeshB2 = meshBand2->getX3Minimum(); x3maxMeshB2 = meshBand2->getX3Maximum();
+         double dBandX2=0.5/100.0;//1.29;
+         double dBandY2=0.5/100.0;
+         double dBandZ2=0.223/100.0;//0.344;//...
+         double offsetXBridgeB2=x1minMesh+dBandX2;//originBridgeX1;
+         double offsetYBridgeB2=originBridgeX2+dBandY2;//originBridgeX2;
+         double offsetZBridgeB2=originBridgeX3+dBandZ2;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+         meshBand2->translate(-x1minMeshB2+offsetXBridgeB2, -x2minMeshB2+offsetYBridgeB2-coarseNodeDx, -x3minMeshB2+offsetZBridgeB2);//-(x3maxMeshB2-x3minMeshB2)*0.5); 
+
+         x1minMeshB2 = meshBand2->getX1Minimum(); x1maxMeshB2 = meshBand2->getX1Maximum();
+         x2minMeshB2 = meshBand2->getX2Minimum(); x2maxMeshB2 = meshBand2->getX2Maximum();
+         x3minMeshB2 = meshBand2->getX3Minimum(); x3maxMeshB2 = meshBand2->getX3Maximum();
+
+         if(myid == 0) GbSystem3D::writeGeoObject( meshBand2.get(), pathname+"/geo/Band2", WbWriterVtkXmlASCII::getInstance() );
+         //////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////////
+         // refine
+         //////////////////////////////////////////////////////////////////////////
+
+         ///////////platte ausmessen:
+         x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+         x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+         x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+         double deltaX3Platte=(x3maxMesh-x3minMesh);
+
+         GbCuboid3DPtr refine2PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3*0.5
+            , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine2PlatteCube.get(), pathname+"/geo/refine2PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP2(refine2PlatteCube, baseLevel, refineLevel-5);
+         //grid->accept(refineAdapterP2);
+
+         GbCuboid3DPtr refine3PlatteCube(new GbCuboid3D(   x1minMesh+H3*2.0  , originX2-geoOverlap  , x3minMesh+H3*0.8
+            , x1maxMesh-H3*0.2, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.1));
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP3(refine3PlatteCube, baseLevel, refineLevel-4);
+         //grid->accept(refineAdapterP3);
+
+         GbCuboid3DPtr refine4PlatteCube(new GbCuboid3D(   x1minMesh-H3*2.0  , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.04
+            ,  x1maxMesh+H3*2.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.25));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine4PlatteCube.get(), pathname+"/geo/refine4PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP4(refine4PlatteCube, baseLevel, refineLevel-3);
+         //grid->accept(refineAdapterP4);
+
+         GbCuboid3DPtr refine5PlatteCube(new GbCuboid3D(   originX1-geoOverlap , originX2-geoOverlap  ,x3minMesh-deltaX3Platte/*x3minMesh+deltaX3Platte*0.8*//* x3minMesh+deltaX3Platte*0.8*/
+            ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine5PlatteCube.get(), pathname+"/geo/refine5PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP5(refine5PlatteCube, baseLevel, refineLevel-2);
+         //grid->accept(refineAdapterP5);
+
+         GbCuboid3DPtr refine6PlatteCube(new GbCuboid3D(   originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-deltaX3Platte*3.0/*x3minMesh+deltaX3Platte*0.9*/
+            ,  x1maxMesh+H3*7.0, originX2+geoOverlap+geoLength[1], x3maxMesh+deltaX3Platte*3.0));
+         //if(myid == 0) GbSystem3D::writeGeoObject(refine6PlatteCube.get(), pathname+"/geo/refine6PlatteCube", WbWriterVtkXmlASCII::getInstance());
+         //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP6(refine6PlatteCube, baseLevel, refineLevel-1);
+         //grid->accept(refineAdapterP6);
+
+         //GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX1-3.0*geoOverlap
+         //  , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.1));
+
+
+         GbCuboid3DPtr refinePlatteBox(new GbCuboid3D(mesh->getX1Minimum(), mesh->getX2Minimum(), mesh->getX3Minimum()+(mesh->getX3Maximum()-mesh->getX3Minimum())/2.0, 
+                                                      mesh->getX1Maximum(), mesh->getX2Maximum(), mesh->getX3Maximum()));
+         if(myid == 0) GbSystem3D::writeGeoObject( refinePlatteBox.get(), pathname+"/geo/refinePlatteBox", WbWriterVtkXmlASCII::getInstance() );
+
+         /////////////////////////////////////////////////
+         ///interactoren
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         D3Q27TriFaceMeshInteractorPtr triPlateInteractor( new D3Q27TriFaceMeshInteractor(mesh, grid, bcObst,Interactor3D::SOLID));
+         D3Q27TriFaceMeshInteractorPtr triBandInteractor( new D3Q27TriFaceMeshInteractor( meshBand, grid, bcObst,Interactor3D::SOLID) );
+         D3Q27TriFaceMeshInteractorPtr triBand2Interactor( new D3Q27TriFaceMeshInteractor( meshBand2, grid, bcObst,Interactor3D::SOLID) );
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));	
+        
+         //////////////////////////////////////////////////////////////////////////
+         //refinement
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            //refineHelper.addGbObject( refine6PlatteCube, refineLevel-3);
+            //refineHelper.addGbObject( refine5PlatteCube, refineLevel-2);
+            //refineHelper.addGbObject( refine4PlatteCube, refineLevel-1);
+            //refineHelper.addGbObject( refine3PlatteCube, refineLevel);
+            refineHelper.addGbObject(refinePlatteBox, refineLevel);
+            refineHelper.refine();
+
+            //RefineAroundGbObjectHelper refineHelper(grid, refineLevel, boost::dynamic_pointer_cast<D3Q27TriFaceMeshInteractor>(triPlateInteractor), 0.0, hReal/4.0);
+            //refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //BlocksPostprocessorPtr ppblocks1(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         ////if(myid == 0) 
+         //ppblocks1->update(0);
+
+         //return;
+
+         //GbCuboid3DPtr testBox(new GbCuboid3D(0.2, -1, 0.1, 1.6, 0.04, 0.5));
+         //if(myid == 0) GbSystem3D::writeGeoObject(testBox.get(), pathname+"/geo/testBox", WbWriterVtkXmlASCII::getInstance());
+         //D3Q27InteractorPtr testBoxInt(new D3Q27Interactor(testBox, grid, bcObst,Interactor3D::SOLID));
+
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(triPlateInteractor);
+         intHelper.addInteractor(triBandInteractor);
+         intHelper.addInteractor(triBand2Interactor);
+         //intHelper.addInteractor(testBoxInt);
+         intHelper.addInteractor(densInteractor);
+         intHelper.addInteractor(velBCInteractor);
+         intHelper.selectBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+
+         if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+         if(myid == 0) 
+            ppblocks->update(0);
+         if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+         
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+         unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+
+         double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+            UBLOG(logINFO,"Available memory per node/8.0 = " << (availMem/8.0) << " bytes");
+         }
+         ////////////////////////////
+         LBMKernel3DPtr kernel;
+         //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+         //with sponge layer
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+         kernel->setWithSpongeLayer(true);
+         kernel->setSpongeLayer(spongeLayer);
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+         //////////////////////////////////////////
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         intHelper.setBC();
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nuLB,rhoInit);
+         initVisitor.setVx1(vx1Init);
+         grid->accept(initVisitor);
+
+         //Postprozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter, true));
+         ppgeo->update(0);
+         //grid->doPostProcess(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+         
+         //return;
+      }
+      else
+      {
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         SetSpongeLayerBlockVisitor ssp(spongeLayer);
+         grid->accept(ssp);
+         if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      }
+      UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(1,0,3);
+      //visSch->addSchedule(100,100,1000);
+      //visSch->addSchedule(1000,1000,5000);
+      //visSch->addSchedule(5000,5000,100000);
+      //visSch->addSchedule(100000,100000,10000000);
+
+      visSch->addSchedule(10000,10000,10000000);
+      //visSch->addSchedule(100,100,100000000);
+
+      //UbSchedulerPtr resSchRMS(new UbScheduler());
+      //resSchRMS->addSchedule(100000,0,10000000);
+      //UbSchedulerPtr resSchMeans(new UbScheduler());
+      //resSchMeans->addSchedule(100000,0,10000000);
+      //UbSchedulerPtr stepAvSch(new UbScheduler());
+      //int averageInterval=1000;
+      //stepAvSch->addSchedule(averageInterval,0,10000000);
+
+      //AverageValuesPostprocessor Avpp(grid, pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/, stepAvSch/*wann wird gemittelt*/, resSchMeans,resSchRMS/*wann wird resettet*/);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      nupsSch->addSchedule(1000, 1000, 1000000000);
+      NUPSCounterPostprocessor npr(grid, nupsSch, comm);
+
+      //mu::Parser decrViscFunc;
+      //decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");
+      //decrViscFunc.DefineConst("nue0", nueLB);
+      //decrViscFunc.DefineConst("c0", 0.1);
+      //UbSchedulerPtr DecrViscSch(new UbScheduler());
+      //DecrViscSch->addSchedule(10,10,5000);
+      //DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch,&decrViscFunc, comm);
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      //double endTime = 80001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1], UbSystem::stringTo<double>(argv[2]));
+
+   return 0;
+}
+
diff --git a/source/Applications/plate/plate.cpp.ludwig10092013 b/source/Applications/plate/plate.cpp.ludwig10092013
new file mode 100644
index 0000000000000000000000000000000000000000..852eed72bc66eef1d56d70edea8ad5c7033e7b2c
--- /dev/null
+++ b/source/Applications/plate/plate.cpp.ludwig10092013
@@ -0,0 +1,626 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+	  UBLOG(logINFO,"Testcase plate");
+      string pathname; 
+      string pathGeo;
+	  string BrueckeFilename;
+	  string ZckbndFilename;
+      int numOfThreads =1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      UbLog::reportingLevel() = logDEBUG;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+      
+      if(machine == "PIPPINNEU") 
+      {
+
+		  pathname = "f:/temp/plateBfluid";
+		  pathGeo = "e:/geometriedatenstls";
+         numOfThreads = 1;
+         logfile = false;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+		  pathname = "/work/sonjaOutputs/plateBfluidNeud";
+		  pathGeo = "/home/sonuphof/Stl-Zeichnungen";
+         numOfThreads = 1;
+         availMem = 12.0e9;
+         logfile = true;
+
+         //if(myid ==0)
+         //{
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         //}
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+	  BrueckeFilename = pathGeo + "/platte_raw.stl"; 
+	  ZckbndFilename= pathGeo + "/2zackenbaender0.stl";
+
+      //if(myid ==0 && logfile)
+      //{
+         UbLog::output_policy::setStream(logFilename.str());
+      //}
+
+      int baseLevel, refineLevel,nx[3],blocknx[3];
+      double Re,velocity,rhoInit,vx1Init;//,vx2Init,vx3Init;
+
+	  //////////////////////////////////////////////////////////////////////////
+	  //physik
+	  //////////////////////////////////////////////////////////////////////////
+	  Re            = 11900;// 13286;//13286;//gemessen 18.98 m/s...*5.0 zum  testen ob was passiert
+	  velocity      = 0.01;  
+	  vx1Init       = 0.01;  
+	  rhoInit       = 1.0;
+	  SimulationParametersPtr param = SimulationParameters::getInstanz();
+	  param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+
+	  int H=200;//200;//392;
+	  ///////////////Knotenabmessungen:
+	  nx[0]      = 120;//60;//86;//43;//65;//50;  //länge
+	  nx[1]      = 3;//6;///1;//5;// //breite
+	  nx[2]      = 32;//18;//5;//15;//15; //höhe gebiet
+	  blocknx[0] = 9;
+	  blocknx[1] = 9;
+	  blocknx[2] = 9;
+
+	  baseLevel   = 0;
+	  refineLevel = 2;//1;//5;
+
+
+
+	  ///////////////Weltabmessungen:
+	  double kanalhoeheSI  = 60.0/100.0;//60.0/100.0;//cm, Kanalhöhe
+	  double kanalbreiteSI = kanalhoeheSI*120.0/2.0;//=kanalhöhe*nx1/nx2//1.65/100.0;//13.2/100.0;////40.0/100.0; //cm, Kanalbreite //13.2 zeilbreite
+	  double kanallaengeSI = kanalhoeheSI*120.0/32.0;//80.0/100.0;//cm, Kanallänge, ist nicht angegeben
+
+	  // double refinewidth1=kanalhoeheSI/10.0;
+
+	  double fineNodeDx   = (kanalhoeheSI) / (double)( blocknx[2]*nx[2]*(1<<refineLevel)+1 ); //+1--> gitter liegt jeweils 0.5dx innerhalb
+	  double coarseNodeDx = fineNodeDx * (double)(1<<refineLevel);//geowerte
+
+	  double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+	  double blockLengthx2 = blockLengthx1;
+	  double blockLengthx3 = blockLengthx1;
+
+	  double originX1 = 0.0;//-50.0*propellerDurchmesser;  //geowerte
+	  double originX2 = 0.0;//-0.5*blockLengthx2*nx2;
+	  double originX3 = 0.0;// minX3 + 0.5*fineNodeDx;
+
+	  double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+	  //position vorderkante cube
+	  double originBridgeX1 = 20.0/100.0; //cm, geraten
+	  double originBridgeX2 = 0.0;//0.5*params.nx[1]*blockLengthx2-0.5*H-fineNodeDx;
+	  double originBridgeX3 = kanalhoeheSI*0.5;//H*0.0-fineNodeDx; //boden
+
+	  bool periodicx1 = false;
+	  bool periodicx2 = true;
+	  bool periodicx3 = true;
+
+	  //##########################################################################
+	  //## physical parameters
+	  //##########################################################################
+
+	  double smagorinskiConstant = 0.18;
+
+
+	  double rhoLB         = 1.0;
+	  double rhoReal       = 1.0;
+	  double nueReal  = 0.000015;//0.015;
+
+	  double hReal         = 0.0105;//<-m     1.05;//Plattendicke in cm(! cm nicht m !)
+	  double uReal         = Re*nueReal/hReal;
+
+	  //##Machzahl:
+	  //#Ma     = uReal/csReal
+	  double Ma      = 0.05;//0.0553;//Ma-Real!
+	  double csReal  = uReal/Ma;
+	  double hLB     = hReal/coarseNodeDx;
+
+	  LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(hReal, csReal, rhoReal, hLB));
+
+	  double uLB           = uReal   * unitConverter->getFactorVelocityWToLb();
+	  double nueLB         = nueReal * unitConverter->getFactorViscosityWToLb();
+	  double timestep      = unitConverter->getFactorTimeLbToW(coarseNodeDx);
+
+	  velocity = uLB;
+	  double viscosity = nueLB;
+
+	  //////////////////////////////////////////////////////////////////////////
+	  Grid3DPtr grid(new Grid3D(comm));
+	  UbSchedulerPtr rSch(new UbScheduler(5000,5000,1000000));
+	  RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if(/*(cstr== NULL)*/cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         grid = rp.restart(UbSystem::stringTo<int>(opt));
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         //PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         //grid->accept(pqPartVisitor);
+      }
+      else
+      {
+      //bounding box
+      double g_minX1 = originX1;
+      double g_minX2 = originX2;
+      double g_minX3 = originX3;
+
+      double g_maxX1 = originX1 + geoLength[0];
+      double g_maxX2 = originX2 + geoLength[1];
+      double g_maxX3 = originX3 + geoLength[2];
+
+      //set grid
+      grid->setDeltaX(coarseNodeDx);
+      grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+      grid->setPeriodicX1(periodicx1);
+      grid->setPeriodicX2(periodicx2);
+      grid->setPeriodicX3(periodicx3);
+	  
+      
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+      GenBlocksGridVisitor genBlocks;
+      genBlocks.addGeoObject(gridCube);
+      grid->accept(genBlocks);
+
+
+	  /////////////////////////////////////////////////7
+	  //interactoren definieren
+
+
+
+	  double geoOverlap = 3.0*coarseNodeDx;
+
+	  //inflow
+      GbCuboid3DPtr velBCCuboid(new GbCuboid3D(originX1-geoOverlap, originX2-geoOverlap, originX3-geoOverlap, 
+         originX1/*+coarseNodeDx*/, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap));
+      if(myid == 0) GbSystem3D::writeGeoObject(velBCCuboid.get(), pathname+"/geo/velBCCuboid", WbWriterVtkXmlASCII::getInstance());
+      D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(velBCCuboid,grid,Interactor3D::SOLID)); 
+
+	   //inflow
+      double uLB2=uLB*0.96*1.02;//*0.5;
+      double raiseVelSteps = 0;
+      vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+      mu::Parser inflowProfile;
+      inflowProfile.SetExpr("uLB"); 
+
+      inflowProfile.DefineConst("uLB",uLB2);
+      velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+      
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (velcX1BCs,dummy,dummy));
+      velBCInteractor->addBCAdapter(velBCAdapter);
+
+	  //outflow
+	  GbCuboid3DPtr densCuboid(new GbCuboid3D(originX1+geoLength[0]-coarseNodeDx, originX2-geoOverlap, originX3-geoOverlap, 
+		  originX1+geoLength[0]+geoOverlap, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap ));
+	  if(myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname+"/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+	  D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoInit));
+	  D3Q27InteractorPtr densInteractor( new D3Q27Interactor(densCuboid,grid,denBCAdapter,Interactor3D::SOLID) );
+      
+      //////////////////////////////////////////////////////////////////////////
+      if(myid == 0)
+      {
+         UBLOG(logINFO, "*****************************************");
+         UBLOG(logINFO, "* Parameters                            *");
+         UBLOG(logINFO, "* Re            ="<<Re);
+         UBLOG(logINFO, "* Ma            ="<<Ma);
+         UBLOG(logINFO, "* uReal         ="<<uReal);
+         UBLOG(logINFO, "* nueReal       ="<<nueReal);
+         UBLOG(logINFO, "* nue           ="<<nueLB);
+         UBLOG(logINFO, "* velocity      ="<<uLB);
+        // UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+       //  UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+         UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+         UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+         UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+         UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+         UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+         UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+         UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+         UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+         UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+         UBLOG(logINFO, "*****************************************");
+         UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+         UBLOG(logINFO, "*****************************************");     
+      }
+	  //////////////////////////////////////////////////////////////////////////
+	  //platte
+	  GbTriFaceMesh3DPtr mesh (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(BrueckeFilename,"Netz"));
+
+	  double x1minMesh = mesh->getX1Minimum(); double x1maxMesh = mesh->getX1Maximum();
+	  double x2minMesh = mesh->getX2Minimum(); double x2maxMesh = mesh->getX2Maximum();
+	  double x3minMesh = mesh->getX3Minimum(); double x3maxMesh = mesh->getX3Maximum();
+
+	  double drehpunktX=x1minMesh+(x1maxMesh-x1minMesh)*0.5;//triFaceMeshS->getX1Centroid();
+	  double drehpunktZ=x3minMesh+(x3maxMesh-x3minMesh)*0.5;//triFaceMeshS->getX3Centroid();
+	  double drehpunktY=x2minMesh+(x2maxMesh-x2minMesh)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+	  mesh->rotate(90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+
+	  x1minMesh = mesh->getX1Minimum();  x1maxMesh = mesh->getX1Maximum();
+	  x2minMesh = mesh->getX2Minimum();  x2maxMesh = mesh->getX2Maximum();
+	  x3minMesh = mesh->getX3Minimum();  x3maxMesh = mesh->getX3Maximum();
+
+	  drehpunktX=x1minMesh+(x1maxMesh-x1minMesh)*0.5;//triFaceMeshS->getX1Centroid();
+	  drehpunktZ=x3minMesh+(x3maxMesh-x3minMesh)*0.5;//triFaceMeshS->getX3Centroid();
+	  drehpunktY=x2minMesh+(x2maxMesh-x2minMesh)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+	  double H3=1.05/100.0;//cm, Plattendicke
+	  double scaleB=H3/(x3maxMesh-x3minMesh);
+	  double scaleX2=(geoLength[2]+2.0*coarseNodeDx)/(x2minMesh-x2maxMesh);
+
+	  mesh->scale(scaleB,scaleB,scaleB);
+	  x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+	  x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+	  x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+	  double offsetXBridge=originBridgeX1;//originBridgeX1;
+	  double offsetYBridge=originBridgeX2;//originBridgeX2;
+	  double offsetZBridge=originBridgeX3;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+	  //mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh-0.5*offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge); 
+	  mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh+offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge-(x3maxMesh-x3minMesh)*0.5); 
+
+	  x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+	  x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+	  x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+
+	  if(myid == 0) GbSystem3D::writeGeoObject( mesh.get(), pathname+"/geo/platte", WbWriterVtkXmlBinary::getInstance() );
+
+	  //////////////////////////////////////////////////////////////////////////
+	  // Zackenband
+	  //////////////////////////////////////////////////////////////////////////
+	  GbTriFaceMesh3DPtr meshBand (GbTriFaceMesh3DCreator::readMeshFromFile(ZckbndFilename, "NetzBand"));
+	  meshBand->deleteRedundantNodes();
+
+	  double x1minMeshB = meshBand->getX1Minimum(); double x1maxMeshB = meshBand->getX1Maximum();
+	  double x2minMeshB = meshBand->getX2Minimum(); double x2maxMeshB = meshBand->getX2Maximum();
+	  double x3minMeshB = meshBand->getX3Minimum(); double x3maxMeshB = meshBand->getX3Maximum();
+
+	  x1minMeshB = meshBand->getX1Minimum();  x1maxMeshB = meshBand->getX1Maximum();
+	  x2minMeshB = meshBand->getX2Minimum();  x2maxMeshB = meshBand->getX2Maximum();
+	  x3minMeshB = meshBand->getX3Minimum();  x3maxMeshB = meshBand->getX3Maximum();
+
+	  double H1B=1.5/100.0;//0.05;//cm, Banddicke..nachschauen!!!
+	  double scaleBand=H1B/(x1maxMeshB-x1minMeshB);//H3B/(x3maxMeshB-x3minMeshB);
+
+	  meshBand->scale(scaleBand,scaleBand,scaleBand);
+	  x1minMeshB = meshBand->getX1Minimum(); x1maxMeshB = meshBand->getX1Maximum();
+	  x2minMeshB = meshBand->getX2Minimum(); x2maxMeshB = meshBand->getX2Maximum();
+	  x3minMeshB = meshBand->getX3Minimum(); x3maxMeshB = meshBand->getX3Maximum();
+	  double dBandX=0.5/100.0;//1.29; //15mm-2.1mm Absand von Bandvorderkante
+	  double dBandY=0.0/100.0;
+	  double dBandZ=0.223/100.0;//0.344;//....
+	  double offsetXBridgeB=x1minMesh+dBandX;//originBridgeX1+dBandX;//originBridgeX1;
+	  double offsetYBridgeB=originBridgeX2+dBandY;//originBridgeX2;
+	  double offsetZBridgeB=originBridgeX3+dBandZ;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+	  meshBand->translate(-x1minMeshB+offsetXBridgeB, -x2minMeshB+offsetYBridgeB-coarseNodeDx, -x3minMeshB+offsetZBridgeB);//-(x3maxMeshB-x3minMeshB)*0.5); 
+
+	  x1minMeshB = meshBand->getX1Minimum(); x1maxMeshB = meshBand->getX1Maximum();
+	  x2minMeshB = meshBand->getX2Minimum(); x2maxMeshB = meshBand->getX2Maximum();
+	  x3minMeshB = meshBand->getX3Minimum(); x3maxMeshB = meshBand->getX3Maximum();
+
+	  GbSystem3D::writeGeoObject( meshBand.get(), pathname+"/geo/Band", WbWriterVtkXmlASCII::getInstance() );
+
+	  /////////////////Band2
+	  GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::readMeshFromFile(ZckbndFilename, "NetzBand2"));
+	  meshBand->deleteRedundantNodes();
+
+	  double x1minMeshB2 = meshBand2->getX1Minimum(); double x1maxMeshB2 = meshBand2->getX1Maximum();
+	  double x2minMeshB2 = meshBand2->getX2Minimum(); double x2maxMeshB2 = meshBand2->getX2Maximum();
+	  double x3minMeshB2 = meshBand2->getX3Minimum(); double x3maxMeshB2 = meshBand2->getX3Maximum();
+
+	  x1minMeshB2 = meshBand2->getX1Minimum();  x1maxMeshB2 = meshBand2->getX1Maximum();
+	  x2minMeshB2 = meshBand2->getX2Minimum();  x2maxMeshB2 = meshBand2->getX2Maximum();
+	  x3minMeshB2 = meshBand2->getX3Minimum();  x3maxMeshB2 = meshBand2->getX3Maximum();
+
+	  double H1B2=1.5/100.0;//0.05;//cm, Banddicke..nachschauen!!!
+	  double scaleBand2=H1B2/(x1maxMeshB2-x1minMeshB2);//H3B/(x3maxMeshB-x3minMeshB);
+
+	  meshBand2->scale(scaleBand2,scaleBand2,scaleBand2);
+	  x1minMeshB2 = meshBand2->getX1Minimum(); x1maxMeshB2 = meshBand2->getX1Maximum();
+	  x2minMeshB2 = meshBand2->getX2Minimum(); x2maxMeshB2 = meshBand2->getX2Maximum();
+	  x3minMeshB2 = meshBand2->getX3Minimum(); x3maxMeshB2 = meshBand2->getX3Maximum();
+	  double dBandX2=0.5/100.0;//1.29;
+	  double dBandY2=0.5/100.0;
+	  double dBandZ2=0.223/100.0;//0.344;//...
+	  double offsetXBridgeB2=x1minMesh+dBandX2;//originBridgeX1;
+	  double offsetYBridgeB2=originBridgeX2+dBandY2;//originBridgeX2;
+	  double offsetZBridgeB2=originBridgeX3+dBandZ2;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+	  meshBand2->translate(-x1minMeshB2+offsetXBridgeB2, -x2minMeshB2+offsetYBridgeB2-coarseNodeDx, -x3minMeshB2+offsetZBridgeB2);//-(x3maxMeshB2-x3minMeshB2)*0.5); 
+
+	  x1minMeshB2 = meshBand2->getX1Minimum(); x1maxMeshB2 = meshBand2->getX1Maximum();
+	  x2minMeshB2 = meshBand2->getX2Minimum(); x2maxMeshB2 = meshBand2->getX2Maximum();
+	  x3minMeshB2 = meshBand2->getX3Minimum(); x3maxMeshB2 = meshBand2->getX3Maximum();
+
+	  if(myid == 0) GbSystem3D::writeGeoObject( meshBand2.get(), pathname+"/geo/Band2", WbWriterVtkXmlASCII::getInstance() );
+	  //////////////////////////////////////////////////////////////////////////
+      if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+
+      //////////////////////////////////////////////////////////////////////////
+      // refine
+      //////////////////////////////////////////////////////////////////////////
+
+	  ///////////platte ausmessen:
+	  x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+	  x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+	  x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+	  double deltaX3Platte=(x3maxMesh-x3minMesh);
+
+
+	 // GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+	 // if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+
+
+
+	  //GbCuboid3DPtr refine2PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3*0.5
+	  //  , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+	  //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP2(refine2PlatteCube, baseLevel, refineLevel-5);
+	  //grid->accept(refineAdapterP2);
+
+	  GbCuboid3DPtr refine3PlatteCube(new GbCuboid3D(   x1minMesh+H3*2.0  , originX2-geoOverlap  , x3minMesh+H3*0.8
+	     , x1maxMesh-H3*0.2, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.1));
+	  //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP3(refine3PlatteCube, baseLevel, refineLevel-4);
+	  //grid->accept(refineAdapterP3);
+
+	  GbCuboid3DPtr refine4PlatteCube(new GbCuboid3D(   x1minMesh-H3*2.0  , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.04
+	     ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.25));
+	  //if(myid == 0) GbSystem3D::writeGeoObject(refine4PlatteCube.get(), pathname+"/geo/refine4PlatteCube", WbWriterVtkXmlASCII::getInstance());
+	  //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP4(refine4PlatteCube, baseLevel, refineLevel-3);
+	  //grid->accept(refineAdapterP4);
+
+	  GbCuboid3DPtr refine5PlatteCube(new GbCuboid3D(   originX1-geoOverlap , originX2-geoOverlap  ,x3minMesh-deltaX3Platte/*x3minMesh+deltaX3Platte*0.8*//* x3minMesh+deltaX3Platte*0.8*/
+	     ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+	  //if(myid == 0) GbSystem3D::writeGeoObject(refine5PlatteCube.get(), pathname+"/geo/refine5PlatteCube", WbWriterVtkXmlASCII::getInstance());
+	  //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP5(refine5PlatteCube, baseLevel, refineLevel-2);
+	  //grid->accept(refineAdapterP5);
+
+	  GbCuboid3DPtr refine6PlatteCube(new GbCuboid3D(   originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-deltaX3Platte*3.0/*x3minMesh+deltaX3Platte*0.9*/
+		  ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+deltaX3Platte*3.0));
+	  if(myid == 0) GbSystem3D::writeGeoObject(refine6PlatteCube.get(), pathname+"/geo/refine6PlatteCube", WbWriterVtkXmlASCII::getInstance());
+	  //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP6(refine6PlatteCube, baseLevel, refineLevel-1);
+	  //grid->accept(refineAdapterP6);
+
+	  //GbCuboid3DPtr wallsX1X2minRef4(new GbCuboid3D(  originX1-3.0*geoOverlap   , originX2-3.0*geoOverlap  , originX1-3.0*geoOverlap
+		//  , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], kanalhoeheSI*0.1));
+
+
+
+	  if (refineLevel > 0)
+	  {
+		 
+		  RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+		  refineHelper.addGbObject( refine6PlatteCube, refineLevel-1);
+                refineHelper.addGbObject( refine5PlatteCube, refineLevel);
+                //refineHelper.addGbObject( refine4PlatteCube, refineLevel);
+		  //refineHelper.addGbObject( refine3PlatteCube, refineLevel);
+		  refineHelper.refine();
+		  if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+	  }
+
+
+
+      if(myid == 0) UBLOG(logINFO,"Refinement - end");
+	  ////////////////////////////////////////////
+	  //METIS
+	  MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+	  grid->accept( metisVisitor );
+	  /////////////////////////////////////////////////
+	  ///interactoren
+	  int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+	  D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+
+	  D3Q27TriFaceMeshInteractorPtr triBridgeInteractor( new D3Q27TriFaceMeshInteractor(mesh, grid, bcObst,Interactor3D::SOLID));
+	  //sd.addInteractor(triBridgeInteractor);
+
+	  D3Q27TriFaceMeshInteractorPtr triBandInteractor( new D3Q27TriFaceMeshInteractor( meshBand, grid, bcObst,Interactor3D::SOLID) );
+
+	  D3Q27TriFaceMeshInteractorPtr triBand2Interactor( new D3Q27TriFaceMeshInteractor( meshBand2, grid, bcObst,Interactor3D::SOLID) );
+
+	
+	  ////////////////////////////////////////////
+	  /////delete solid blocks
+	  if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+	  SolidBlocksHelper sd(grid, comm);
+
+	  sd.addInteractor(triBridgeInteractor);
+	  sd.addInteractor(triBandInteractor);
+	  sd.addInteractor(triBand2Interactor);
+	  sd.addInteractor(densInteractor);
+	  sd.addInteractor(velBCInteractor);
+	  sd.deleteSolidBlocks();
+	  if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+
+
+
+	  //////////////////////////////////////
+
+     
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+      unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+      
+      double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+	  UBLOG(logINFO,"Available memory per node/8.0 = " << (availMem/8.0) << " bytes");
+      }
+	  ////////////////////////////
+	  grid->accept( metisVisitor );
+	  /////kernel
+      //LBMKernel3DPtr kernel(new LBMKernelETD3Q27CascadedTI(blocknx[0], blocknx[1], blocknx[2]));
+	LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2],0)); 
+//	LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK (blocknx[0], blocknx[1], blocknx[2],1));
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+	 
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+	  
+      grid->accept(kernelVisitor);
+	  //////////////////////////////////
+	  //undef nodes
+	  if (refineLevel > 0)
+	  {
+		  D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+		  grid->accept(undefNodesVisitor);
+	  }
+	  //////////////////////////////////////////
+	  grid->addAndInitInteractor(triBridgeInteractor);
+	  grid->addAndInitInteractor(triBandInteractor);
+	  grid->addAndInitInteractor(triBand2Interactor);
+	  grid->addAndInitInteractor( densInteractor ); 
+	  grid->addAndInitInteractor( velBCInteractor );
+
+	    UbTimer timer;
+   timer.start();
+ 
+   grid->accept( metisVisitor );
+
+   if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+   BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+   if(myid == 0) ppblocks->update(0);
+   if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+	      
+
+   if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+   grid->accept( metisVisitor );
+   if(myid == 0) ppblocks->update(1);
+   ppblocks.reset();
+   if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+  
+
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition
+      //PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      //grid->accept(pqPartVisitor);
+
+      //initialization of decompositions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+      initVisitor.setVx1(inflowProfile);
+      grid->accept(initVisitor);
+
+      //Postprozess
+	
+      
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+           new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), 
+                                                       unitConverter, comm, true));
+	  									
+
+      grid->doPostProcess(0);
+      ppgeo.reset();
+      geoSch.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+
+}
+      
+
+
+      UbSchedulerPtr visSch(new UbScheduler());
+visSch->addSchedule(1,1,3);
+      visSch->addSchedule(100,100,1000);
+ //     visSch->addSchedule(1000,1000,100000);
+ //     visSch->addSchedule(100000,100000,1000000);
+	//  //TurbulenceIntensityPostprocessor tipp(grid,  pathname + "/steps/stepTI", WbWriterVtkXmlBinary::getInstance(), visSch, comm);
+	  UbSchedulerPtr resSch(new UbScheduler());
+      resSch->addSchedule(0,20,1000);
+	  AverageValuesPostprocessor       Avpp(grid,  pathname + "/steps/stepAV", WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/,resSch/*wann wird resettet*/,comm);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), unitConverter, comm);// unitConverter, comm);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+	  //}
+	  mu::Parser decrViscFunc;
+      decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");
+      decrViscFunc.DefineConst("nue0", nueLB);
+	  decrViscFunc.DefineConst("c0", 0.1);
+	  UbSchedulerPtr DecrViscSch(new UbScheduler());
+      DecrViscSch->addSchedule(10,10,1000);
+	  DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch,&decrViscFunc, comm);
+
+      cout << "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe()<<endl;
+
+      double endTime = 200001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/plate/plate.old b/source/Applications/plate/plate.old
new file mode 100644
index 0000000000000000000000000000000000000000..f3d3be2d1db3823e4776da6bfcd410a11d8b9d95
--- /dev/null
+++ b/source/Applications/plate/plate.old
@@ -0,0 +1,615 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include <numerics/geometry3d/GbSphere3D.h>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "SyncBcBlockVisitor.h"
+#include "numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h"
+#include "numerics/geometry3d/GbTriFaceMesh3D.h"
+#include "D3Q27TriFaceMeshInteractor.h"
+#include "MathUtil.hpp"
+#include "SolidBlocksHelper.h"
+#include "LBMKernelETD3Q27CascadedTI.h"
+#include "TurbulenceIntensityPostprocessor.h"
+#include "RestartPostprocessor.h"
+#include "BlocksPostprocessor.h"
+#include "NUPSCounterPostprocessor.h"
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string BrueckeFilename;
+      string ZckbndFilename;
+      string pathname; 
+      string pathGeo;
+      int numOfThreads =1;
+      bool logfile = false;
+      double availMem = 0;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+      
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "c:/temp/plate";
+         pathGeo = "c:/Data/plate";
+         numOfThreads = 1;
+         logfile = false;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/plate";
+         pathGeo = "/home/koskuche/data/plate";
+         numOfThreads = 8;
+         availMem = 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      BrueckeFilename = pathGeo + "/platte_raw.stl"; 
+      ZckbndFilename= pathGeo + "/2zackenbaender0.stl";
+      
+
+
+      if(myid ==0 && logfile)
+      {
+         stringstream logFilename;
+         logFilename <<  pathname + "/logfile.log";
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      int baseLevel, refineLevel,nx[3],blocknx[3];
+      double Re,velocity,rhoInit,vx1Init;//,vx2Init,vx3Init;
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      Re            = 11900;// 13286;//13286;//gemessen 18.98 m/s...*5.0 zum  testen ob was passiert
+      velocity      = 0.01;  
+      vx1Init       = 0.01;  
+      rhoInit       = 1.0;
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+      param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+
+      ///////////////Knotenabmessungen:
+      //int KnotenCubeCoarse=40;
+      nx[0]      = 120;//60;//86;//43;//65;//50;  //länge
+      nx[1]      = 1;//6;///1;//5;// //breite
+      nx[2]      = 32;//18;//5;//15;//15; //höhe gebiet
+      blocknx[0] = 15;
+      blocknx[1] = 15;
+      blocknx[2] = 15;
+
+      baseLevel   = 0;
+      refineLevel = 4;
+
+      int inflowCubeLevel = 1;
+      int bottomLevel     = 1;
+
+      ///////////////Weltabmessungen:
+      double kanalhoeheSI  = 60.0/100.0;//60.0/100.0;//cm, Kanalhöhe
+      double kanalbreiteSI = 9.9/100.0;//1.65/100.0;//13.2/100.0;////40.0/100.0; //cm, Kanalbreite //13.2 zeilbreite
+      double kanallaengeSI = kanalhoeheSI*30.0/18.0;//80.0/100.0;//cm, Kanallänge, ist nicht angegeben
+
+      // double refinewidth1=kanalhoeheSI/10.0;
+
+      double fineNodeDx   = (kanalhoeheSI) / (double)( blocknx[2]*nx[2]*(1<<refineLevel)+1 ); //+1--> gitter liegt jeweils 0.5dx innerhalb
+      double coarseNodeDx = fineNodeDx * (double)(1<<refineLevel);//geowerte
+
+      double blockLengthx1 = blocknx[0]*coarseNodeDx; //geowerte
+      double blockLengthx2 = blockLengthx1;
+      double blockLengthx3 = blockLengthx1;
+
+      double originX1 = 0.0;//-50.0*propellerDurchmesser;  //geowerte
+      double originX2 = 0.0;//-0.5*blockLengthx2*nx2;
+      double originX3 = 0.0;// minX3 + 0.5*fineNodeDx;
+
+      double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+      //position vorderkante cube
+      double originBridgeX1 = 20.0/100.0; //cm, geraten
+      double originBridgeX2 = 0.0;//0.5*params.nx[1]*blockLengthx2-0.5*H-fineNodeDx;
+      double originBridgeX3 = kanalhoeheSI*0.5;//H*0.0-fineNodeDx; //boden
+
+      bool periodicx1 = false;
+      bool periodicx2 = true;
+      bool periodicx3 = true;
+
+      //##########################################################################
+      //## physical parameters
+      //##########################################################################
+      double smagorinskiConstant = 0.18;
+
+
+      double rhoLB         = 1.0;
+      double rhoReal       = 1.0;
+      double nueReal  = 0.000015;//0.015;
+
+      double hReal         = 0.0105;//<-m     1.05;//Plattendicke in cm(! cm nicht m !)
+      double uReal         = Re*nueReal/hReal;
+
+      //##Machzahl:
+      //#Ma     = uReal/csReal
+      double Ma      = 0.05;//0.0553;//Ma-Real!
+      double csReal  = uReal/Ma;
+      double hLB     = hReal/coarseNodeDx;
+
+      LBMUnitConverter unitConverter(hReal, csReal, rhoReal, hLB);
+
+      double uLB           = uReal   * unitConverter.getFactorVelocityWToLb();
+      double nueLB         = nueReal * unitConverter.getFactorViscosityWToLb();
+
+      velocity = uLB;
+      double viscosity = nueLB;
+
+      Grid3DPtr grid(new Grid3D());
+      UbSchedulerPtr rSch(new UbScheduler(5000,5000,1000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+
+      //////////////////////////////////////////////////////////////////////////
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if(/*(cstr== NULL)*/cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         grid = rp.restart(UbSystem::stringTo<int>(opt));
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+      //bounding box
+      double g_minX1 = originX1;
+      double g_minX2 = originX2;
+      double g_minX3 = originX3;
+
+      double g_maxX1 = originX1 + geoLength[0];
+      double g_maxX2 = originX2 + geoLength[1];
+      double g_maxX3 = originX3 + geoLength[2];
+
+      //set grid
+      grid->setDeltaX(coarseNodeDx);
+      grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+      grid->setPeriodicX1(periodicx1);
+      grid->setPeriodicX2(periodicx2);
+      grid->setPeriodicX3(periodicx3);
+
+      
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+      GenBlocksGridVisitor genBlocks;
+      genBlocks.addGeoObject(gridCube);
+      grid->accept(genBlocks);
+
+      //////////////////////////////////////////////////////////////////////////
+      //platte
+      GbTriFaceMesh3DPtr mesh (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(BrueckeFilename,"Netz"));
+
+      double x1minMesh = mesh->getX1Minimum(); double x1maxMesh = mesh->getX1Maximum();
+      double x2minMesh = mesh->getX2Minimum(); double x2maxMesh = mesh->getX2Maximum();
+      double x3minMesh = mesh->getX3Minimum(); double x3maxMesh = mesh->getX3Maximum();
+
+      double drehpunktX=x1minMesh+(x1maxMesh-x1minMesh)*0.5;//triFaceMeshS->getX1Centroid();
+      double drehpunktZ=x3minMesh+(x3maxMesh-x3minMesh)*0.5;//triFaceMeshS->getX3Centroid();
+      double drehpunktY=x2minMesh+(x2maxMesh-x2minMesh)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+      mesh->rotate(90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+
+      x1minMesh = mesh->getX1Minimum();  x1maxMesh = mesh->getX1Maximum();
+      x2minMesh = mesh->getX2Minimum();  x2maxMesh = mesh->getX2Maximum();
+      x3minMesh = mesh->getX3Minimum();  x3maxMesh = mesh->getX3Maximum();
+
+      drehpunktX=x1minMesh+(x1maxMesh-x1minMesh)*0.5;//triFaceMeshS->getX1Centroid();
+      drehpunktZ=x3minMesh+(x3maxMesh-x3minMesh)*0.5;//triFaceMeshS->getX3Centroid();
+      drehpunktY=x2minMesh+(x2maxMesh-x2minMesh)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+      double H3=1.05/100.0;//cm, Plattendicke
+      double scaleB=H3/(x3maxMesh-x3minMesh);
+      double scaleX2=(geoLength[2]+2.0*coarseNodeDx)/(x2minMesh-x2maxMesh);
+
+      mesh->scale(scaleB,scaleB,scaleB);
+      x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+      x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+      x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+      double offsetXBridge=originBridgeX1;//originBridgeX1;
+      double offsetYBridge=originBridgeX2;//originBridgeX2;
+      double offsetZBridge=originBridgeX3;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+      //mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh-0.5*offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge); 
+      mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh+offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge-(x3maxMesh-x3minMesh)*0.5); 
+
+      x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+      x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+      x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+
+      if(myid == 0) GbSystem3D::writeGeoObject( mesh.get(), pathname+"/geo/platte", WbWriterVtkXmlBinary::getInstance() );
+
+      //////////////////////////////////////////////////////////////////////////
+      // Zackenband
+      //////////////////////////////////////////////////////////////////////////
+      GbTriFaceMesh3DPtr meshBand (GbTriFaceMesh3DCreator::readMeshFromFile(ZckbndFilename, "NetzBand"));
+      meshBand->deleteRedundantNodes();
+
+      double x1minMeshB = meshBand->getX1Minimum(); double x1maxMeshB = meshBand->getX1Maximum();
+      double x2minMeshB = meshBand->getX2Minimum(); double x2maxMeshB = meshBand->getX2Maximum();
+      double x3minMeshB = meshBand->getX3Minimum(); double x3maxMeshB = meshBand->getX3Maximum();
+
+      x1minMeshB = meshBand->getX1Minimum();  x1maxMeshB = meshBand->getX1Maximum();
+      x2minMeshB = meshBand->getX2Minimum();  x2maxMeshB = meshBand->getX2Maximum();
+      x3minMeshB = meshBand->getX3Minimum();  x3maxMeshB = meshBand->getX3Maximum();
+
+      double H1B=1.5/100.0;//0.05;//cm, Banddicke..nachschauen!!!
+      double scaleBand=H1B/(x1maxMeshB-x1minMeshB);//H3B/(x3maxMeshB-x3minMeshB);
+
+      meshBand->scale(scaleBand,scaleBand,scaleBand);
+      x1minMeshB = meshBand->getX1Minimum(); x1maxMeshB = meshBand->getX1Maximum();
+      x2minMeshB = meshBand->getX2Minimum(); x2maxMeshB = meshBand->getX2Maximum();
+      x3minMeshB = meshBand->getX3Minimum(); x3maxMeshB = meshBand->getX3Maximum();
+      double dBandX=0.5/100.0;//1.29; //15mm-2.1mm Absand von Bandvorderkante
+      double dBandY=0.0/100.0;
+      double dBandZ=0.223/100.0;//0.344;//....
+      double offsetXBridgeB=x1minMesh+dBandX;//originBridgeX1+dBandX;//originBridgeX1;
+      double offsetYBridgeB=originBridgeX2+dBandY;//originBridgeX2;
+      double offsetZBridgeB=originBridgeX3+dBandZ;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+      meshBand->translate(-x1minMeshB+offsetXBridgeB, -x2minMeshB+offsetYBridgeB-coarseNodeDx, -x3minMeshB+offsetZBridgeB);//-(x3maxMeshB-x3minMeshB)*0.5); 
+
+      x1minMeshB = meshBand->getX1Minimum(); x1maxMeshB = meshBand->getX1Maximum();
+      x2minMeshB = meshBand->getX2Minimum(); x2maxMeshB = meshBand->getX2Maximum();
+      x3minMeshB = meshBand->getX3Minimum(); x3maxMeshB = meshBand->getX3Maximum();
+
+      GbSystem3D::writeGeoObject( meshBand.get(), pathname+"/geo/Band", WbWriterVtkXmlASCII::getInstance() );
+
+      /////////////////Band2
+      GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::readMeshFromFile(ZckbndFilename, "NetzBand2"));
+      meshBand->deleteRedundantNodes();
+
+      double x1minMeshB2 = meshBand2->getX1Minimum(); double x1maxMeshB2 = meshBand2->getX1Maximum();
+      double x2minMeshB2 = meshBand2->getX2Minimum(); double x2maxMeshB2 = meshBand2->getX2Maximum();
+      double x3minMeshB2 = meshBand2->getX3Minimum(); double x3maxMeshB2 = meshBand2->getX3Maximum();
+
+      x1minMeshB2 = meshBand2->getX1Minimum();  x1maxMeshB2 = meshBand2->getX1Maximum();
+      x2minMeshB2 = meshBand2->getX2Minimum();  x2maxMeshB2 = meshBand2->getX2Maximum();
+      x3minMeshB2 = meshBand2->getX3Minimum();  x3maxMeshB2 = meshBand2->getX3Maximum();
+
+      double H1B2=1.5/100.0;//0.05;//cm, Banddicke..nachschauen!!!
+      double scaleBand2=H1B2/(x1maxMeshB2-x1minMeshB2);//H3B/(x3maxMeshB-x3minMeshB);
+
+      meshBand2->scale(scaleBand2,scaleBand2,scaleBand2);
+      x1minMeshB2 = meshBand2->getX1Minimum(); x1maxMeshB2 = meshBand2->getX1Maximum();
+      x2minMeshB2 = meshBand2->getX2Minimum(); x2maxMeshB2 = meshBand2->getX2Maximum();
+      x3minMeshB2 = meshBand2->getX3Minimum(); x3maxMeshB2 = meshBand2->getX3Maximum();
+      double dBandX2=0.5/100.0;//1.29;
+      double dBandY2=0.5/100.0;
+      double dBandZ2=0.223/100.0;//0.344;//...
+      double offsetXBridgeB2=x1minMesh+dBandX2;//originBridgeX1;
+      double offsetYBridgeB2=originBridgeX2+dBandY2;//originBridgeX2;
+      double offsetZBridgeB2=originBridgeX3+dBandZ2;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+      meshBand2->translate(-x1minMeshB2+offsetXBridgeB2, -x2minMeshB2+offsetYBridgeB2-coarseNodeDx, -x3minMeshB2+offsetZBridgeB2);//-(x3maxMeshB2-x3minMeshB2)*0.5); 
+
+      x1minMeshB2 = meshBand2->getX1Minimum(); x1maxMeshB2 = meshBand2->getX1Maximum();
+      x2minMeshB2 = meshBand2->getX2Minimum(); x2maxMeshB2 = meshBand2->getX2Maximum();
+      x3minMeshB2 = meshBand2->getX3Minimum(); x3maxMeshB2 = meshBand2->getX3Maximum();
+
+      if(myid == 0) GbSystem3D::writeGeoObject( meshBand2.get(), pathname+"/geo/Band2", WbWriterVtkXmlASCII::getInstance() );
+      //////////////////////////////////////////////////////////////////////////
+      if(myid == 0) 
+      {
+         UBLOG(logINFO, "*****************************************");
+         UBLOG(logINFO, "* Parameters                            *");
+         UBLOG(logINFO, "* Re            ="<<Re);
+         UBLOG(logINFO, "* Ma            ="<<Ma);
+         UBLOG(logINFO, "* uReal         ="<<uReal);
+         UBLOG(logINFO, "* nueReal       ="<<nueReal);
+         UBLOG(logINFO, "* nue           ="<<nueLB);
+         UBLOG(logINFO, "* velocity      ="<<uLB);
+         UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+         UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+         UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+         //UBLOG(logINFO, "* dxInflow-Cube ="<<velBCCuboid->getX1Maximum()-mesh->getX1Minimum());
+         UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+         UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+         //UBLOG(logINFO, "* inflowProfile ="<<inflowProfile.GetExpr());
+         UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+         UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+         //UBLOG(logINFO, "* raiseVelSteps ="<<raiseVelSteps);
+         UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+         UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+         UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+         UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+         UBLOG(logINFO, "*****************************************");
+         UBLOGML(logINFO, "UnitConverter:"<<unitConverter.toString());
+         UBLOG(logINFO, "*****************************************");     
+      }
+      if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+      double geoOverlap = 3.0*coarseNodeDx;
+      //////////////////////////////////////////////////////////////////////////
+      // refine
+      //////////////////////////////////////////////////////////////////////////
+      ///////////platte ausmessen:
+      x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+      x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+      x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+      double deltaX3Platte=(x3maxMesh-x3minMesh);
+
+
+      //GbCuboid3DPtr refine1PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3
+      //   , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+      //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP1(refine1PlatteCube, baseLevel, refineLevel-6);
+      //grid->accept(refineAdapterP1);
+
+      // GbCuboid3DPtr refine2PlatteCube(new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3*0.5
+        // , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3));
+      // RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP2(refine2PlatteCube, baseLevel, refineLevel-5);
+      // grid->accept(refineAdapterP2);
+
+      GbCuboid3DPtr refine3PlatteCube(new GbCuboid3D(  originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh-H3*0.5
+         , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.5));
+      RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP3(refine3PlatteCube, baseLevel, refineLevel-4);
+      grid->accept(refineAdapterP3);
+
+      GbCuboid3DPtr refine4PlatteCube(new GbCuboid3D(   originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.0
+         ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.25));
+      if(myid == 0) GbSystem3D::writeGeoObject(refine4PlatteCube.get(), pathname+"/geo/refine4PlatteCube", WbWriterVtkXmlASCII::getInstance());
+      RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP4(refine4PlatteCube, baseLevel, refineLevel-3);
+      grid->accept(refineAdapterP4);
+
+      GbCuboid3DPtr refine5PlatteCube(new GbCuboid3D(   originX1-geoOverlap , originX2-geoOverlap  ,x3minMesh+deltaX3Platte*0.1/* x3minMesh+deltaX3Platte*0.8*/
+         ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.00375));
+      if(myid == 0) GbSystem3D::writeGeoObject(refine5PlatteCube.get(), pathname+"/geo/refine5PlatteCube", WbWriterVtkXmlASCII::getInstance());
+      RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP5(refine5PlatteCube, baseLevel, refineLevel-2);
+      grid->accept(refineAdapterP5);
+
+      GbCuboid3DPtr refine6PlatteCube(new GbCuboid3D(   originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-deltaX3Platte*0.1/*x3minMesh+deltaX3Platte*0.9*/
+         ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+deltaX3Platte*0.9));
+      if(myid == 0) GbSystem3D::writeGeoObject(refine6PlatteCube.get(), pathname+"/geo/refine6PlatteCube", WbWriterVtkXmlASCII::getInstance());
+      RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP6(refine6PlatteCube, baseLevel, refineLevel-1);
+      grid->accept(refineAdapterP6);
+
+      //GbCuboid3DPtr refine7PlatteCube(new GbCuboid3D(originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-deltaX3Platte*0.3, 
+      //                                               meshBand->getX1Maximum()+meshBand->getLengthX1()*3.0, originX2+geoOverlap+geoLength[1], x3maxMesh));
+      //if(myid == 0) GbSystem3D::writeGeoObject(refine7PlatteCube.get(), pathname+"/geo/refine7PlatteCube", WbWriterVtkXmlASCII::getInstance());
+      //RefineCrossAndInsideGbObjectBlockVisitor refineAdapterP7(refine7PlatteCube, baseLevel, refineLevel-1);
+      //grid->accept(refineAdapterP7);
+
+      RatioBlockVisitor ratioVisitor(refineLevel);
+      grid->accept(ratioVisitor);
+      RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+      grid->accept(ratioSmoothVisitor);
+      OverlapBlockVisitor overlapVisitor(refineLevel);
+      grid->accept(overlapVisitor);
+      std::vector<int> dirs;
+      D3Q27System::getLBMDirections(dirs);
+      SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+      grid->accept(interDirsVisitor);
+
+      if(myid == 0) UBLOG(logINFO,"Refinement - end");
+
+      if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+      if(myid == 0) ppblocks->update(0);
+      //ppblocks.reset();
+      if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+      
+      MetisPartitioningGridVisitor metisVisitor(numOfThreads, D3Q27System::B, comm, false);
+      grid->accept( metisVisitor );
+
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+      SolidBlocksHelper sd(grid, comm);
+
+      //iteractors
+      int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+
+      D3Q27TriFaceMeshInteractorPtr triBridgeInteractor( new D3Q27TriFaceMeshInteractor(mesh, grid, bcObst,Interactor3D::SOLID));
+      sd.addInteractor(triBridgeInteractor);
+
+      D3Q27TriFaceMeshInteractorPtr triBandInteractor( new D3Q27TriFaceMeshInteractor( meshBand, grid, bcObst,Interactor3D::SOLID) );
+
+      D3Q27TriFaceMeshInteractorPtr triBand2Interactor( new D3Q27TriFaceMeshInteractor( meshBand2, grid, bcObst,Interactor3D::SOLID) );
+
+      sd.deleteSolidBlocks();
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	      
+      
+      if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+      grid->accept( metisVisitor );
+      //BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+      if(myid == 0) ppblocks->update(0);
+      ppblocks.reset();
+      if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+      
+      double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int))*2);
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }
+
+      LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx[0], blocknx[1], blocknx[2]));
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      if (refineLevel > 0)
+      {
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+      //discretization
+      grid->addAndInitInteractor(triBridgeInteractor);
+      grid->addAndInitInteractor(triBandInteractor);
+      grid->addAndInitInteractor(triBand2Interactor);
+
+      //outflow
+      GbCuboid3DPtr densCuboid(new GbCuboid3D(originX1+geoLength[0]-coarseNodeDx, originX2-geoOverlap, originX3-geoOverlap, 
+                                              originX1+geoLength[0]+geoOverlap, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap ));
+      if(myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname+"/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoInit));
+      D3Q27InteractorPtr densInteractor( new D3Q27Interactor(densCuboid,grid,denBCAdapter,Interactor3D::SOLID) );
+      grid->addAndInitInteractor( densInteractor ); 
+
+      //inflow
+      double uLB2=uLB*0.96*1.02;//*0.5;
+      double raiseVelSteps = 0;
+      vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+      mu::Parser inflowProfile;
+      inflowProfile.SetExpr("uLB"); 
+
+      inflowProfile.DefineConst("uLB",uLB2);
+      velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+      GbCuboid3DPtr velBCCuboid(new GbCuboid3D(originX1-geoOverlap, originX2-geoOverlap, originX3-geoOverlap, 
+                                               originX1+coarseNodeDx, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap));
+      if(myid == 0) GbSystem3D::writeGeoObject(velBCCuboid.get(), pathname+"/geo/velBCCuboid", WbWriterVtkXmlASCII::getInstance());
+
+      D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(velBCCuboid,grid,Interactor3D::SOLID)); 
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (velcX1BCs,dummy,dummy));
+      velBCInteractor->addBCAdapter(velBCAdapter);
+      grid->addAndInitInteractor( velBCInteractor ); 
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+
+      //initialization of decompositions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+      initVisitor.setVx1(inflowProfile);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+           new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), 
+                                                       conv, comm, true));
+      grid->doPostProcess(0);
+      ppgeo.reset();
+      geoSch.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end");    
+      
+      if(myid == 0) 
+      {
+         UBLOG(logINFO, "* dxInflow-Cube ="<<velBCCuboid->getX1Maximum()-mesh->getX1Minimum());
+         UBLOG(logINFO, "* inflowProfile ="<<inflowProfile.GetExpr());
+         UBLOG(logINFO, "* raiseVelSteps ="<<raiseVelSteps);
+      }
+}
+      
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      double outTime = 1000;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      visSch->addSchedule(1000,1000,10000);
+      visSch->addSchedule(10000,10000,100000);
+      visSch->addSchedule(100000,100000,1000000);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double endTime = 1000001;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/plate/sonjas_org.cpp.vf b/source/Applications/plate/sonjas_org.cpp.vf
new file mode 100644
index 0000000000000000000000000000000000000000..8f590605aed93606c716ef4c9276b3c96b66e5c0
--- /dev/null
+++ b/source/Applications/plate/sonjas_org.cpp.vf
@@ -0,0 +1,678 @@
+
+
+..damit wir gleich damit anfangen können. So sieht das Setup aus.
+Sonja
+
+
+SpD3Q19Plattenanstroemung.hpp
+
+#include <topology/amr3d/blockadaptation/AMR3DCrossAndInsideGbObject3DAdapter.h>
+//AMR3DCrossAndInsideGbObject3DAdapter
+#include <topology/amr3d/lbmd3q19/utils/D3Q19MetisTools.h>
+//#include <topology/amr3d/lbmd3q19/turbulenceWale/gridadaptation/TwD3Q19SpongeLayerAdapter.h>
+#include <topology/amr3d/lbmd3q19/gridadaptation/D3Q19GridInformationGridAdapter.h>
+#include <topology/amr3d/lbmd3q19/gridadaptation/D3Q19SetConnectorsGridAdapter.h>
+#include <topology/amr3d/lbmd3q19/gridadaptation/D3Q19InitDistributionsGridAdapter.h>
+#include <topology/amr3d/gridadaptation/AMR3DGridLevelPartitionMetisAdapter.h>
+#include <topology/amr3d/gridadaptation/AMR3DGridPartitionOneDirectionAdapter.h>
+#include <topology/amr3d/lbmd3q19/bcadapter/D3Q19DensityLodiBCAdapter.h>
+#include <topology/amr3d/lbmd3q19/singlephase/gridadaptation/SpD3Q19SpongeLayerAdapter.h>
+#include <topology/amr3d/lbmd3q19/gridadaptation/D3Q19InitDistributionsGridAdapter.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+#include <topology/amr3d/lbmd3q19/interactor/D3Q19AMRTriFaceMeshInteractor.h>
+#include <topology/amr3d/lbmd3q19/services/adapter/D3Q19ClientGridWriteInteractorNodeFiles.h>
+#include <topology/amr3d/lbmd3q19/gridadaptation/D3Q19ChangeSlipToNoSlipGridAdapter.h> 
+
+using namespace std;
+
+void SpD3Q19MasterTestcases::start( RcfClient<IRcfIpService>& ipService, 
+                                   RcfClient<IRcfD3Q19TopologyService>& topoService, 
+                                   RcfClient<IRcfD3Q19AMRInteractorService>& interactorService, 
+                                   RcfClient<IRcfD3Q19CalculationManager>& calculationManager,
+                                   std::vector< RcfClient<IRcfD3Q19CalcService> >& calcServices,
+                                   std::string inputfile )
+{
+   using namespace std;
+   UBLOG(logERROR,"Testcase GBBridge_Sonja "); 
+
+   string outpath = UbStaticPathMap::getPath(UbStaticPathMap::GLOBAL);
+
+   SpD3Q19TestCaseParameters params;
+   bool useLODI;
+   bool initWithLogProfile;
+   //////////////////////////////////////////////////////////////////////////
+   // Params
+   //////////////////////////////////////////////////////////////////////////
+   // if( inputfile.empty() )
+   // {
+   params.calcSteps          = 300000;
+   params.threadedClientCall = true;
+
+   //params.distributedDumpScheduler = UbScheduler(5000, 0);
+   params.distributedDumpScheduler.addSchedule(UbSchedule(100,0,100));
+   params.distributedDumpScheduler.addSchedule(UbSchedule(100,100,6000));
+   params.distributedDumpScheduler.addSchedule(UbSchedule(1000,6000,10000));
+   params.distributedDumpScheduler.addSchedule(UbSchedule(5000,10000,Ub::inf));
+
+   //params.schedulers.calcForces    = UbScheduler(10,0);
+   //params.schedulers.writeForces   = UbScheduler(500,500);
+   params.schedulers.resetAverage  = UbScheduler(50000,50000);
+   params.schedulers.serialization = UbScheduler(20000,20000);
+
+   //Schnickschnack(  so lassen, da geht es im Wesentlichen um Kommunikationsdetails)
+   params.connsTransAttr.setRemoteProtocol(D3Q19ConnectorTransmitterAttributes::MPI_PROTOCOL);
+   params.connsTransAttr.setOptionDirectConnectors(true);
+   params.connsTransAttr.setOptionTwoVectorsForLocalVectors(false);
+   params.connsTransAttr.setOptionConsForNotActiveBlocks(true);
+   params.connsTransAttr.setOptionRemoteBlockedSend(false);
+   params.connsTransAttr.setOptionRemoteBlockedReceive(true);
+   params.connsTransAttr.setOptionRemotePool(true);
+   params.connsTransAttr.setOptionStlVecForSameLevelCons(false);
+   params.connsTransAttr.setOptionStlVecForScaleCons(false);
+
+#ifndef CAB_MPI
+   if(params.connsTransAttr.getRemoteProtocol() == D3Q19ConnectorTransmitterAttributes::MPI_PROTOCOL) 
+      throw UbException(UB_EXARGS,"MPI Transmitter not available for this compilation without /DCAB_MPI");
+#endif
+
+   string machine = QUOTEME(CAB_MACHINE);
+   string BrueckeFilename;
+   string ZckbndFilename;
+   if(machine == "ARAGORN")     {  BrueckeFilename = "f:/data/bruecke/platte_raw.stl"; ZckbndFilename="f:/data/bruecke/zweiPlatten0.stl";}
+   else if(machine == "LUDWIG") {  BrueckeFilename = "/hpc3lustre/home/sonuphof/Stl-Zeichnungen/platte_raw.stl"; ZckbndFilename="/hpc3lustre/home/sonuphof/Stl-Zeichnungen/2zackenbaender0.stl";}
+   else if(machine == "PIPPIN") {  BrueckeFilename = "C:/platteD291009/sonja2/svn_uphoff/Daten/SFB880/platte-cad/platte_raw.stl"; ZckbndFilename="C:/platteD291009/sonja2/svn_uphoff/Daten/SFB880/platte-cad/2zackenbaender0.stl";}
+   else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+
+   //////////////////////////////////////////////////////////////////////////
+   //physik
+   //////////////////////////////////////////////////////////////////////////
+   params.Re            = 11900;// 13286;//13286;//gemessen 18.98 m/s...*5.0 zum  testen ob was passiert
+   params.velocity      = 0.01;  
+   params.vx1Init       = 0.01;  
+   params.rhoInit       = 0.0;
+   initWithLogProfile   = true;
+   useLODI              = false;
+
+   params.collModel = D3Q19System::INCOMPGLBEJTLESMODEL;
+   ///////////////Knotenabmessungen:
+   //int KnotenCubeCoarse=40;
+   params.nx[0]      = 120;//60;//86;//43;//65;//50;  //länge
+   params.nx[1]      = 6;///1;//5;// //breite
+   params.nx[2]      = 32;//18;//5;//15;//15; //höhe gebiet
+   params.blocknx[0] = 10;
+   params.blocknx[1] = 10;
+   params.blocknx[2] = 10;
+
+   params.baseLevel   = 0;
+   params.refineLevel = 3;
+
+   int inflowCubeLevel = 1;
+   int bottomLevel     = 1;
+
+   ///////////////Weltabmessungen:
+   double kanalhoeheSI  = 60.0/100.0;//60.0/100.0;//cm, Kanalhöhe
+   double kanalbreiteSI = 9.9/100.0;//1.65/100.0;//13.2/100.0;////40.0/100.0; //cm, Kanalbreite //13.2 zeilbreite
+   double kanallaengeSI = kanalhoeheSI*30.0/18.0;//80.0/100.0;//cm, Kanallänge, ist nicht angegeben
+
+   // double refinewidth1=kanalhoeheSI/10.0;
+
+   double fineNodeDx   = (kanalhoeheSI) / (double)( params.blocknx[2]*params.nx[2]*(1<<params.refineLevel)+1 ); //+1--> gitter liegt jeweils 0.5dx innerhalb
+   double coarseNodeDx = fineNodeDx * (double)(1<<params.refineLevel);//geowerte
+
+   double blockLengthx1 = params.blocknx[0]*coarseNodeDx; //geowerte
+   double blockLengthx2 = blockLengthx1;
+   double blockLengthx3 = blockLengthx1;
+
+   double originX1 = 0.0;//-50.0*propellerDurchmesser;  //geowerte
+   double originX2 = 0.0;//-0.5*blockLengthx2*nx2;
+   double originX3 = 0.0;// minX3 + 0.5*fineNodeDx;
+
+   double geoLength[]   = {  params.nx[0]*blockLengthx1, params.nx[1]*blockLengthx2, params.nx[2]*blockLengthx3}; 
+
+   //position vorderkante cube
+   double originBridgeX1 = 20.0/100.0; //cm, geraten
+   double originBridgeX2 = 0.0;//0.5*params.nx[1]*blockLengthx2-0.5*H-fineNodeDx;
+   double originBridgeX3 = kanalhoeheSI*0.5;//H*0.0-fineNodeDx; //boden
+
+   bool periodicx1 = false;
+   bool periodicx2 = true;
+   bool periodicx3 = false;
+
+#ifndef CAB_MPI
+   if(params.connsTransAttr.getRemoteProtocol() == D3Q19ConnectorTransmitterAttributes::MPI_PROTOCOL) 
+      throw UbException("LbD3Q19MasterTestcases::startChannelFlow - MPI Transmitter not available for this compilation without /DCAB_MPI");
+#endif
+
+   //weitere parameter
+   double raiseVelSteps                  = 0;
+   double startViscosity                 = 1.0/3.0;
+   int    decreaseViscositySteps         = 6000;
+   int    decreaseViscosityStepForHalVis = (int)(1.0/8.0*decreaseViscositySteps);
+
+   if( D3Q19System::isCompModel(params.collModel) ) params.rhoInit = 1.0;
+   //////////////////////////////////////////////////////////////////////////
+   //grid initialization
+   //////////////////////////////////////////////////////////////////////////
+   UBLOG2(logINFO, std::cout, "grid initialization...");
+
+   CoordinateTransformation3D* trafo = new CoordinateTransformation3D(originX1,originX2, originX3, blockLengthx1, blockLengthx2, blockLengthx3);
+   vector< boost::shared_ptr<AMR3DGridAdaptationCriterion> > adapter;
+   UBLOG(logINFO,"set periodic")
+   adapter.push_back( boost::shared_ptr<AMR3DGridAdaptationCriterion>(new AMR3DSetPeriodicAdapter(periodicx1, params.nx[0], periodicx2, params.nx[1], periodicx3, params.nx[2])) );
+      UBLOG(logINFO,"construct block grid")
+   topoService.constructBlockGrid("MyGrid", UbTupleInt6(params.nx[0],params.nx[1],params.nx[2],params.blocknx[0],params.blocknx[1],params.blocknx[2]), params.baseLevel, UbPointerWrapper<CoordinateTransformation3D>(trafo),adapter );
+
+   UBLOG2(logINFO, std::cout, "grid initialization... done");
+
+   //##########################################################################
+
+   double geoOverlap = 3.0*coarseNodeDx;
+
+   //////////////////////////////////////////////////////////////////////////////
+
+   GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::readMeshFromFile(BrueckeFilename, "Netz");
+    mesh->deleteRedundantNodes();
+
+     double x1minMesh = mesh->getX1Minimum(); double x1maxMesh = mesh->getX1Maximum();
+   double x2minMesh = mesh->getX2Minimum(); double x2maxMesh = mesh->getX2Maximum();
+   double x3minMesh = mesh->getX3Minimum(); double x3maxMesh = mesh->getX3Maximum();
+
+   double drehpunktX=x1minMesh+(x1maxMesh-x1minMesh)*0.5;//triFaceMeshS->getX1Centroid();
+   double drehpunktZ=x3minMesh+(x3maxMesh-x3minMesh)*0.5;//triFaceMeshS->getX3Centroid();
+   double drehpunktY=x2minMesh+(x2maxMesh-x2minMesh)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+     mesh->rotateAroundPoint(drehpunktZ,drehpunktX,drehpunktY,90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+
+   x1minMesh = mesh->getX1Minimum();  x1maxMesh = mesh->getX1Maximum();
+   x2minMesh = mesh->getX2Minimum();  x2maxMesh = mesh->getX2Maximum();
+   x3minMesh = mesh->getX3Minimum();  x3maxMesh = mesh->getX3Maximum();
+
+   drehpunktX=x1minMesh+(x1maxMesh-x1minMesh)*0.5;//triFaceMeshS->getX1Centroid();
+   drehpunktZ=x3minMesh+(x3maxMesh-x3minMesh)*0.5;//triFaceMeshS->getX3Centroid();
+   drehpunktY=x2minMesh+(x2maxMesh-x2minMesh)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+   double H3=1.05/100.0;//cm, Plattendicke
+   double scaleB=H3/(x3maxMesh-x3minMesh);
+   double scaleX2=(geoLength[2]+2.0*coarseNodeDx)/(x2minMesh-x2maxMesh);
+
+   mesh->scale(scaleB,scaleB,scaleB);
+   x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+   x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+   x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+   double offsetXBridge=originBridgeX1;//originBridgeX1;
+   double offsetYBridge=originBridgeX2;//originBridgeX2;
+   double offsetZBridge=originBridgeX3;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+   //mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh-0.5*offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge); 
+   mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh+offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge-(x3maxMesh-x3minMesh)*0.5); 
+
+   x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+   x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+   x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+
+   GbSystem3D::writeGeoObject( mesh, UbStaticPathMap::getPath(UbStaticPathMap::GLOBAL)+"/platte", WbWriterVtkXmlBinary::getInstance() );
+
+   //GbTriFaceMesh3D* Bruecke = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(BrueckeFilename         ,"Bruecke");
+   // Bruecke->setPointInObjectTest(GbTriFaceMesh3D::RAYCROSSING);//, HALFSPACE, MEGARAY, SEGURA, GELLER)
+   //D3Q19AMRTriFaceMeshInteractor* triInteractor = new D3Q19AMRTriFaceMeshInteractor(mesh, grid,new D3Q19NoSlipBCAdapter, AMR3DInteractor::SOLID);
+   boost::shared_ptr<D3Q19AMRTriFaceMeshInteractor> triBridgeInteractor( new D3Q19AMRTriFaceMeshInteractor( mesh,new D3Q19NoSlipBCAdapter,AMR3DInteractor::SOLID,"bridge") );
+
+   //grid->addAndInitInteractor(triInteractor);
+   interactorService.addInteractor(triBridgeInteractor);
+
+     //////////////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////////
+   // Zackenband
+   //////////////////////////////////////////////////////////////////////////
+     GbTriFaceMesh3D* meshBand = GbTriFaceMesh3DCreator::readMeshFromFile(ZckbndFilename, "NetzBand");
+    meshBand->deleteRedundantNodes();
+
+   double x1minMeshB = meshBand->getX1Minimum(); double x1maxMeshB = meshBand->getX1Maximum();
+   double x2minMeshB = meshBand->getX2Minimum(); double x2maxMeshB = meshBand->getX2Maximum();
+   double x3minMeshB = meshBand->getX3Minimum(); double x3maxMeshB = meshBand->getX3Maximum();
+
+   //double drehpunktXB=x1minMeshB+(x1maxMeshB-x1minMeshB)*0.5;//triFaceMeshS->getX1Centroid();
+   //double drehpunktZB=x3minMeshB+(x3maxMeshB-x3minMeshB)*0.5;//triFaceMeshS->getX3Centroid();
+   //double drehpunktYB=x2minMeshB+(x2maxMeshB-x2minMeshB)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+    // meshBand->rotateAroundPoint(drehpunktZB,drehpunktXB,drehpunktYB,90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+
+   x1minMeshB = meshBand->getX1Minimum();  x1maxMeshB = meshBand->getX1Maximum();
+   x2minMeshB = meshBand->getX2Minimum();  x2maxMeshB = meshBand->getX2Maximum();
+   x3minMeshB = meshBand->getX3Minimum();  x3maxMeshB = meshBand->getX3Maximum();
+
+   //drehpunktXB=x1minMeshB+(x1maxMeshB-x1minMeshB)*0.5;//triFaceMeshS->getX1Centroid();
+   //drehpunktZB=x3minMeshB+(x3maxMeshB-x3minMeshB)*0.5;//triFaceMeshS->getX3Centroid();
+   //drehpunktYB=x2minMeshB+(x2maxMeshB-x2minMeshB)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+   double H1B=1.5/100.0;//0.05;//cm, Banddicke..nachschauen!!!
+   double scaleBand=H1B/(x1maxMeshB-x1minMeshB);//H3B/(x3maxMeshB-x3minMeshB);
+ //  double scaleX2B=(geoLength[2]+2.0*coarseNodeDx)/(x2minMeshB-x2maxMeshB);
+
+   meshBand->scale(scaleBand,scaleBand,scaleBand);
+   x1minMeshB = meshBand->getX1Minimum(); x1maxMeshB = meshBand->getX1Maximum();
+   x2minMeshB = meshBand->getX2Minimum(); x2maxMeshB = meshBand->getX2Maximum();
+   x3minMeshB = meshBand->getX3Minimum(); x3maxMeshB = meshBand->getX3Maximum();
+   double dBandX=0.5/100.0;//1.29; //15mm-2.1mm Absand von Bandvorderkante
+   double dBandY=0.0/100.0;
+   double dBandZ=0.223/100.0;//0.344;//....
+   double offsetXBridgeB=x1minMesh+dBandX;//originBridgeX1+dBandX;//originBridgeX1;
+   double offsetYBridgeB=originBridgeX2+dBandY;//originBridgeX2;
+   double offsetZBridgeB=originBridgeX3+dBandZ;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+   //mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh-0.5*offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge); 
+   meshBand->translate(-x1minMeshB+offsetXBridgeB, -x2minMeshB+offsetYBridgeB-coarseNodeDx, -x3minMeshB+offsetZBridgeB);//-(x3maxMeshB-x3minMeshB)*0.5); 
+
+   x1minMeshB = meshBand->getX1Minimum(); x1maxMeshB = meshBand->getX1Maximum();
+   x2minMeshB = meshBand->getX2Minimum(); x2maxMeshB = meshBand->getX2Maximum();
+   x3minMeshB = meshBand->getX3Minimum(); x3maxMeshB = meshBand->getX3Maximum();
+
+   GbSystem3D::writeGeoObject( meshBand, UbStaticPathMap::getPath(UbStaticPathMap::GLOBAL)+"/Band", WbWriterVtkXmlBinary::getInstance() );
+
+   //GbTriFaceMesh3D* Bruecke = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(BrueckeFilename         ,"Bruecke");
+   // Bruecke->setPointInObjectTest(GbTriFaceMesh3D::RAYCROSSING);//, HALFSPACE, MEGARAY, SEGURA, GELLER)
+   //D3Q19AMRTriFaceMeshInteractor* triInteractor = new D3Q19AMRTriFaceMeshInteractor(mesh, grid,new D3Q19NoSlipBCAdapter, AMR3DInteractor::SOLID);
+   boost::shared_ptr<D3Q19AMRTriFaceMeshInteractor> triBandInteractor( new D3Q19AMRTriFaceMeshInteractor( meshBand,new D3Q19NoSlipBCAdapter,AMR3DInteractor::SOLID,"band") );
+   interactorService.addInteractor(triBandInteractor);
+    /////////////////Band2
+
+
+      GbTriFaceMesh3D* meshBand2 = GbTriFaceMesh3DCreator::readMeshFromFile(ZckbndFilename, "NetzBand2");
+    meshBand->deleteRedundantNodes();
+
+   double x1minMeshB2 = meshBand2->getX1Minimum(); double x1maxMeshB2 = meshBand2->getX1Maximum();
+   double x2minMeshB2 = meshBand2->getX2Minimum(); double x2maxMeshB2 = meshBand2->getX2Maximum();
+   double x3minMeshB2 = meshBand2->getX3Minimum(); double x3maxMeshB2 = meshBand2->getX3Maximum();
+
+   //double drehpunktXB2=x1minMeshB2+(x1maxMeshB2-x1minMeshB2)*0.5;//triFaceMeshS->getX1Centroid();
+   //double drehpunktZB2=x3minMeshB2+(x3maxMeshB2-x3minMeshB2)*0.5;//triFaceMeshS->getX3Centroid();
+   //double drehpunktYB2=x2minMeshB2+(x2maxMeshB2-x2minMeshB2)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+//     meshBand2->rotateAroundPoint(drehpunktZB2,drehpunktXB2,drehpunktYB2,90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+
+   x1minMeshB2 = meshBand2->getX1Minimum();  x1maxMeshB2 = meshBand2->getX1Maximum();
+   x2minMeshB2 = meshBand2->getX2Minimum();  x2maxMeshB2 = meshBand2->getX2Maximum();
+   x3minMeshB2 = meshBand2->getX3Minimum();  x3maxMeshB2 = meshBand2->getX3Maximum();
+
+   //drehpunktXB2=x1minMeshB2+(x1maxMeshB2-x1minMeshB2)*0.5;//triFaceMeshS->getX1Centroid();
+   //drehpunktZB2=x3minMeshB2+(x3maxMeshB2-x3minMeshB2)*0.5;//triFaceMeshS->getX3Centroid();
+   //drehpunktYB2=x2minMeshB2+(x2maxMeshB2-x2minMeshB2)*0.5;// seedX2-0.5*nodeDelta;//+nx2*deltaX2+0.5*deltaX2;
+
+   double H1B2=1.5/100.0;//0.05;//cm, Banddicke..nachschauen!!!
+   double scaleBand2=H1B2/(x1maxMeshB2-x1minMeshB2);//H3B/(x3maxMeshB-x3minMeshB);
+
+   meshBand2->scale(scaleBand2,scaleBand2,scaleBand2);
+   x1minMeshB2 = meshBand2->getX1Minimum(); x1maxMeshB2 = meshBand2->getX1Maximum();
+   x2minMeshB2 = meshBand2->getX2Minimum(); x2maxMeshB2 = meshBand2->getX2Maximum();
+   x3minMeshB2 = meshBand2->getX3Minimum(); x3maxMeshB2 = meshBand2->getX3Maximum();
+   double dBandX2=0.5/100.0;//1.29;
+   double dBandY2=0.5/100.0;
+   double dBandZ2=0.223/100.0;//0.344;//...
+   double offsetXBridgeB2=x1minMesh+dBandX2;//originBridgeX1;
+   double offsetYBridgeB2=originBridgeX2+dBandY2;//originBridgeX2;
+   double offsetZBridgeB2=originBridgeX3+dBandZ2;//originBridgeX3;//-0.5*(x3minMesh-x3maxMesh);
+   //mesh->translate(-x1minMesh+offsetXBridge, -x2minMesh-0.5*offsetYBridge-coarseNodeDx, -x3minMesh+offsetZBridge); 
+   meshBand2->translate(-x1minMeshB2+offsetXBridgeB2, -x2minMeshB2+offsetYBridgeB2-coarseNodeDx, -x3minMeshB2+offsetZBridgeB2);//-(x3maxMeshB2-x3minMeshB2)*0.5); 
+
+   x1minMeshB2 = meshBand2->getX1Minimum(); x1maxMeshB2 = meshBand2->getX1Maximum();
+   x2minMeshB2 = meshBand2->getX2Minimum(); x2maxMeshB2 = meshBand2->getX2Maximum();
+   x3minMeshB2 = meshBand2->getX3Minimum(); x3maxMeshB2 = meshBand2->getX3Maximum();
+
+   GbSystem3D::writeGeoObject( meshBand2, UbStaticPathMap::getPath(UbStaticPathMap::GLOBAL)+"/Band2", WbWriterVtkXmlBinary::getInstance() );
+
+   //GbTriFaceMesh3D* Bruecke = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(BrueckeFilename         ,"Bruecke");
+   // Bruecke->setPointInObjectTest(GbTriFaceMesh3D::RAYCROSSING);//, HALFSPACE, MEGARAY, SEGURA, GELLER)
+   //D3Q19AMRTriFaceMeshInteractor* triInteractor = new D3Q19AMRTriFaceMeshInteractor(mesh, grid,new D3Q19NoSlipBCAdapter, AMR3DInteractor::SOLID);
+   boost::shared_ptr<D3Q19AMRTriFaceMeshInteractor> triBand2Interactor( new D3Q19AMRTriFaceMeshInteractor( meshBand2,new D3Q19NoSlipBCAdapter,AMR3DInteractor::SOLID,"band2") );
+    interactorService.addInteractor(triBand2Interactor);
+   
+   //////////////////////////////////////////////////////////////////////////
+   // refine
+   //////////////////////////////////////////////////////////////////////////
+                        
+
+
+   
+
+
+
+   ///////////platte ausmessen:
+   x1minMesh = mesh->getX1Minimum(); x1maxMesh = mesh->getX1Maximum();
+   x2minMesh = mesh->getX2Minimum(); x2maxMesh = mesh->getX2Maximum();
+   x3minMesh = mesh->getX3Minimum(); x3maxMesh = mesh->getX3Maximum();
+  double deltaX3Platte=(x3maxMesh-x3minMesh);
+
+
+      GbCuboid3D* refine1PlatteCube = new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3
+      , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3);
+   boost::shared_ptr<AMR3DBlockAdaptationCriterion> refineAdapterP1(new AMR3DCrossAndInsideGbObject3DAdapter(refine1PlatteCube,0,params.refineLevel-6));
+   topoService.adaptGridByBlockCriterion(refineAdapterP1);
+
+        GbCuboid3D* refine2PlatteCube = new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh-H3*0.5
+      , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3);
+   boost::shared_ptr<AMR3DBlockAdaptationCriterion> refineAdapterP2(new AMR3DCrossAndInsideGbObject3DAdapter(refine2PlatteCube,0,params.refineLevel-5));
+   topoService.adaptGridByBlockCriterion(refineAdapterP2);
+
+        GbCuboid3D* refine3PlatteCube = new GbCuboid3D(  originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh-H3*0.5
+      , x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.5);
+   boost::shared_ptr<AMR3DBlockAdaptationCriterion> refineAdapterP3(new AMR3DCrossAndInsideGbObject3DAdapter(refine3PlatteCube,0,params.refineLevel-4));   //dieser hier hat eine ecke 
+   topoService.adaptGridByBlockCriterion(refineAdapterP3);
+
+        GbCuboid3D* refine4PlatteCube = new GbCuboid3D(   originX1-geoOverlap  , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.6
+      ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.25);
+   boost::shared_ptr<AMR3DBlockAdaptationCriterion> refineAdapterP4(new AMR3DCrossAndInsideGbObject3DAdapter(refine4PlatteCube,0,params.refineLevel-3));   //weil der hier zu hoch ist
+   topoService.adaptGridByBlockCriterion(refineAdapterP4);
+
+           GbCuboid3D* refine5PlatteCube = new GbCuboid3D(   originX1-geoOverlap , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.8
+      ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+H3*0.00375);
+   boost::shared_ptr<AMR3DBlockAdaptationCriterion> refineAdapterP5(new AMR3DCrossAndInsideGbObject3DAdapter(refine5PlatteCube,0,params.refineLevel-2));
+   topoService.adaptGridByBlockCriterion(refineAdapterP5);
+
+  //            GbCuboid3D* refine6PlatteCube = new GbCuboid3D(   x1minMeshB2+( x1maxMeshB2- x1minMeshB2)*0.8   , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.9
+  //    ,  x1maxMesh+H3*0.075, originX2+geoOverlap+geoLength[1], x3maxMesh+2.0*fineNodeDx);
+  // boost::shared_ptr<AMR3DBlockAdaptationCriterion> refineAdapterP6(new AMR3DCrossAndInsideGbObject3DAdapter(refine6PlatteCube,0,params.refineLevel-1));
+  // topoService.adaptGridByBlockCriterion(refineAdapterP6);
+
+           GbCuboid3D* refine6PlatteCube = new GbCuboid3D(   originX1-geoOverlap   , originX2-geoOverlap  , x3minMesh+deltaX3Platte*0.9
+      ,  x1maxMesh+H3*5.0, originX2+geoOverlap+geoLength[1], x3maxMesh+deltaX3Platte*0.9);
+   boost::shared_ptr<AMR3DBlockAdaptationCriterion> refineAdapterP6(new AMR3DCrossAndInsideGbObject3DAdapter(refine6PlatteCube,0,params.refineLevel-1));
+   topoService.adaptGridByBlockCriterion(refineAdapterP6);
+
+     UBLOG2(logINFO, std::cout, "Refinement..done");
+   //blockverhältnis von 2:1 herstellen:
+   UBLOG(logINFO,"ratio")
+      boost::shared_ptr<AMR3DBlockAdaptationCriterion> ratioAdapter(new AMR3DBlockRatioAdapter(params.refineLevel));
+   topoService.adaptGridByBlockCriterion(ratioAdapter);
+
+
+
+   //////////////////////////////////////////////////////////////////////////
+   //walls                                                                                                   
+   ////////////////////////////////////////////////////////////////////////// 
+   int noSlipSecOpt = 1; //0=2nd order BB 1=simple BB
+   int slipSecOpt   = 1; //0=2nd order BB 1=simple BB
+
+   ////x1x2-walls:                                                                                             
+   GbCuboid3D* wallsX1X2min = new GbCuboid3D(  originX1-geoOverlap   , originX2-geoOverlap  , originX3-geoOverlap
+      , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3-0.5*fineNodeDx);
+   boost::shared_ptr<D3Q19AMRInteractor> wallsX1X2minInteractor( new D3Q19AMRInteractor( wallsX1X2min,new D3Q19SlipBCAdapter(slipSecOpt),AMR3DInteractor::SOLID,"wallsX1X2min") );
+   if(!params.periodic[2]) interactorService.addInteractor( wallsX1X2minInteractor );
+
+   GbCuboid3D* wallsX1X2max = new GbCuboid3D(  originX1-geoOverlap , originX2-geoOverlap , originX3+geoLength[2]+0.5*fineNodeDx            
+      , originX1+geoLength[0]+geoOverlap, originX2+geoOverlap+geoLength[1], originX3+geoLength[2]+geoOverlap); 
+   boost::shared_ptr<D3Q19AMRInteractor> wallsX1X2maxInteractor( new D3Q19AMRInteractor( wallsX1X2max,new D3Q19SlipBCAdapter(slipSecOpt),AMR3DInteractor::SOLID,"wallsX1X2max") ) ;  
+   if(!params.periodic[2]) interactorService.addInteractor( wallsX1X2maxInteractor );
+
+
+  
+
+   //##########################################################################
+   //## physical parameters
+   //##########################################################################
+   double smagorinskiConstant = 0.18;
+
+
+   double rhoLB         = 1.0;
+   double rhoReal       = 1.0;
+   double nueReal  = 0.000015;//0.015;
+
+   double hReal         = 0.0105;//<-m     1.05;//Plattendicke in cm(! cm nicht m !)
+   double uReal         = params.Re*nueReal/hReal;
+
+   //##Machzahl:
+   //#Ma     = uReal/csReal
+   double Ma      = 0.05;//0.0553;//Ma-Real!
+   double csReal  = uReal/Ma;
+   double hLB     = hReal/coarseNodeDx;
+
+   D3Q19UnitConverter unitConverter(hReal, csReal, rhoReal, hLB );
+
+   double uLB           = uReal   * unitConverter.getFactorVelocityWToLb();
+   double nueLB         = nueReal * unitConverter.getFactorViscosityWToLb();
+
+   params.velocity = uLB;
+   double viscosity = nueLB;
+
+   //////////////////////////////////////////////////////////////////////////
+   // BCs
+   //////////////////////////////////////////////////////////////////////////
+   //////////////////////////////////////////////////////////////////////////
+   // inflow
+   //////////////////////////////////////////////////////////////////////////
+
+
+   double uLB2=uLB*0.96*1.02;//*0.5;
+
+   vector<D3Q19BCFunction> velcX1BCs,dummy;
+
+   if(raiseVelSteps>0)
+   {
+      mu::Parser inflowProfile1;
+         inflowProfile1.SetExpr("uLB"); 
+    
+          inflowProfile1.DefineConst("uLB",uLB2);
+   }
+   mu::Parser inflowProfile;
+   inflowProfile.SetExpr("uLB"); 
+
+   inflowProfile.DefineConst("uLB",uLB2);
+   //inflowProfile.DefineConst("xlbnachxworld",xlbnachxworld);
+   velcX1BCs.push_back(D3Q19BCFunction(inflowProfile,raiseVelSteps,D3Q19BCFunction::INFCONST));
+
+
+   GbCuboid3D* velBCCuboid = NULL;
+   velBCCuboid = new GbCuboid3D(  originX1-geoOverlap, originX2-geoOverlap, originX3-geoOverlap
+      , originX1-fineNodeDx, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap);
+
+   boost::shared_ptr< D3Q19AMRInteractor> velBCInteractor(new D3Q19AMRInteractor(velBCCuboid,AMR3DInteractor::SOLID,"velBC")); 
+   velBCInteractor->addBCAdapter(new D3Q19VelocityBCAdapter(velcX1BCs,dummy,dummy) );
+   interactorService.addInteractor( velBCInteractor ); 
+
+
+
+   //////////////////////////////////////////////////////////////////////////
+   // outflow
+   //////////////////////////////////////////////////////////////////////////
+   GbCuboid3D* densCuboid = NULL;
+   densCuboid = new GbCuboid3D(  originX1+geoLength[0]+fineNodeDx, originX2-geoOverlap             , originX3-geoOverlap
+      , originX1+geoLength[0]+geoOverlap, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap );
+
+   if(useLODI)
+   {
+      float LX1 = (float)((densCuboid->getX1Minimum()-velBCCuboid->getX1Maximum())/coarseNodeDx);
+      float LX2 = -1.0f;
+      float LX3 = -1.0f;
+
+      D3Q19DensityLodiBCAdapter* lodiBCadapter = new D3Q19DensityLodiBCAdapter(3,LX1,LX2,LX3,params.rhoInit,params.vx1Init,params.vx2Init,params.vx3Init,params.rhoInit);
+      boost::shared_ptr< D3Q19AMRInteractor> densInteractor(new D3Q19AMRInteractor(densCuboid,lodiBCadapter,AMR3DInteractor::SOLID,"lodiDensBC"));
+      interactorService.addInteractor( densInteractor ); 
+   }
+   else
+   {
+      boost::shared_ptr< D3Q19AMRInteractor> densInteractor( new D3Q19AMRInteractor(densCuboid,new D3Q19DensityBCAdapter(params.rhoInit),AMR3DInteractor::SOLID,"densBC") );
+      interactorService.addInteractor( densInteractor ); 
+   }
+
+   UBLOG(logINFO, "*****************************************");
+   UBLOG(logINFO, "* Parameters                            *");
+   UBLOG(logINFO, "* Re            ="<<params.Re);
+   UBLOG(logINFO, "* Ma            ="<<Ma);
+   UBLOG(logINFO, "* uReal         ="<<uReal);
+   UBLOG(logINFO, "* nueReal       ="<<nueReal);
+   UBLOG(logINFO, "* nue           ="<<nueLB);
+   UBLOG(logINFO, "* velocity      ="<<uLB);
+   UBLOG(logINFO, "* LX1 (world/LB)="<<kanallaengeSI<<"/"<<kanallaengeSI/coarseNodeDx);
+   UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+   UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+   UBLOG(logINFO, "* dxInflow-Cube ="<<velBCCuboid->getX1Maximum()-mesh->getX1Minimum());
+   UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+   UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+  // UBLOG(logINFO, "* H_world       ="<<H);
+  // UBLOG(logINFO, "* H_LB          ="<<H/coarseNodeDx);
+   //UBLOG(logINFO, "* H_log_world   ="<<delta);
+   //UBLOG(logINFO, "* H_log_LB      ="<<delta/baseDX);
+   //UBLOG(logINFO, "* alpha         ="<<alpha);
+   UBLOG(logINFO, "* inflowProfile ="<<inflowProfile.GetExpr());
+   UBLOG(logINFO, "* dx_base       ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+   UBLOG(logINFO, "* dx_refine     ="<<fineNodeDx<<" == "<<fineNodeDx );
+   UBLOG(logINFO, "* collModel     ="<<params.collModel);
+   UBLOG(logINFO, "* raiseVelSteps ="<<raiseVelSteps);
+   UBLOG(logINFO, "* startVis      ="<<startViscosity);
+   UBLOG(logINFO, "* raiseVisSteps ="<<decreaseViscositySteps);
+   UBLOG(logINFO, "* nx1/2/3       ="<<params.nx[0]<<"/"<<params.nx[1]<<"/"<<params.nx[2]);
+   UBLOG(logINFO, "* blocknx1/2/3  ="<<params.blocknx[0]<<"/"<<params.blocknx[1]<<"/"<<params.blocknx[2]);
+   UBLOG(logINFO, "* x3Periodic    ="<<params.periodic[2]);
+   UBLOG(logINFO, "* useDirectConnectors           "<< params.connsTransAttr.useDirectConnectors()        ); 
+   UBLOG(logINFO, "* useSTLVectorForSameLevelCons  "<< params.connsTransAttr.useStlVecForSameLevelCons()  ); 
+   UBLOG(logINFO, "* useSTLVectorForScaleCons      "<< params.connsTransAttr.useStlVecForScaleCons()      ); 
+   UBLOG(logINFO, "* useConsForNotActiveBlocks     "<< params.connsTransAttr.useConsForNotActiveBlocks() ); 
+   UBLOG(logINFO, "* LODI           ="<< (useLODI ? "ON" : "OFF") ); 
+   UBLOG(logINFO, "*****************************************");
+   UBLOGML(logINFO, "UnitConverter:"<<unitConverter.toString());
+   UBLOG(logINFO, "*****************************************");
+
+   //////////////////////////////////////////////////////////////////////////
+   //geo holen und setzen!!!
+   //////////////////////////////////////////////////////////////////////////
+   topoService.getAndAddAndInitInteractors();
+
+   //////////////////////////////////////////////////////////////////////////
+   UBLOG(logINFO, "//////////////////////////////////////////////////////////////////");
+   int nofBlocks = topoService.getNumberOfBlocks(true);
+   UBLOG(logINFO, "//active blocks after interactors: "<<nofBlocks);
+   int nofAllBlocks = topoService.getNumberOfBlocks(false);
+   UBLOG(logINFO, "//total blocks after interactors: "<<nofAllBlocks);
+   UBLOG(logINFO, " -> ~"<<nofBlocks*(params.blocknx[0]+1)*(params.blocknx[1]+1)*(params.blocknx[2]+1)<<" nodes");
+   UBLOG(logINFO, "//////////////////////////////////////////////////////////////////");
+
+   //partitionierung
+   UBLOG2(logINFO,cout, "levelweise METIS SEGMENTIERUNG!!!!")
+      boost::shared_ptr<AMR3DGridAdaptationCriterion> partioningAdapter(new AMR3DGridLevelPartitionMetisAdapter( (int)calcServices.size()
+      , D3Q19MetisAdapterTools::getMetisDirsAndWeights(  params.blocknx[0]
+   , params.blocknx[1]
+   , params.blocknx[2] )
+      , params.connsTransAttr.useConsForNotActiveBlocks()
+      , D3Q19MetisAdapterTools::getD3Q19GetBlockWeightFunctor(false) ) );   ///////hier false auf keine gewichtung - default:doppelte gewichtung für fine
+   //  boost::shared_ptr<AMR3DGridAdaptationCriterion> partioningAdapter(new AMR3DGridPartitionOneDirectionAdapter((int)calcServices.size()) );   
+  // UBLOG2(logINFO,"params.connsTransAttr.useConsForNotActiveBlocks():" ); 
+   //UBLOG2(logINFO,params.connsTransAttr.useConsForNotActiveBlocks() );         
+   topoService.adaptGridByGridCriterion(partioningAdapter);
+   topoService.writeBlocksToAVS(outpath+"/blocksSegments",false);
+   UBLOG2(logINFO,cout, "BlockSegmentsGeschriebe")
+      //clientgrids erzeugen
+      topoService.createClientGridsAndSendBlocksToClients("client",params.connsTransAttr,params.threadedClientCall);
+   UBLOG2(logINFO,cout, "createClientGrids usw")
+
+
+
+      boost::shared_ptr<D3Q19ClientGridWriteInteractorNodeFiles> writeInteractorTransNodesAdapter(new D3Q19ClientGridWriteInteractorNodeFiles("shared",D3Q19ClientGridWriteInteractorNodeFiles::ValueProjOnGeoVertex)); 
+   writeInteractorTransNodesAdapter->setScheduler(UbSchedule(10000));
+   writeInteractorTransNodesAdapter->addInteractorID( triBridgeInteractor ->getName() );
+
+      //physik-daten zuweisen
+      D3Q19GridPhysicsAdapter* physicsAdapter = new D3Q19GridPhysicsAdapter(params.collModel,viscosity,0.0,0.0,0.0);
+   physicsAdapter->setSmagorinskyConstant(smagorinskiConstant);
+   physicsAdapter->setUnitConverter( unitConverter );
+   boost::shared_ptr<AMR3DGridAdaptationCriterion>  physicsAdapterPtr(physicsAdapter);
+
+   //UbPointerWrapper<AMR3DGridAdaptationCriterion>   decreaseViscosityAdapter( new D3Q19GridPhysicsAdapter(decreaseViscositySteps, startViscosity, viscosity, decreaseViscosityStepForHalVis) );
+   boost::shared_ptr<AMR3DGridAdaptationCriterion>  decreaseViscosityAdapter( new D3Q19GridPhysicsAdapter(decreaseViscositySteps, startViscosity, viscosity, decreaseViscosityStepForHalVis) );
+   //boost::shared_ptr<AMR3DBlockAdaptationCriterion> initadapter(new D3Q19InitDistributionsAdapter(params.connsTransAttr.useConsForNotActiveBlocks(), params.collModel, params.rhoInit,(params.vx1Init*0.96),params.vx2Init,params.vx3Init, 0, AMR3DSystem::MAXLEVEL));
+
+   boost::shared_ptr<AMR3DGridAdaptationCriterion> initadapter(new D3Q19InitDistributionsGridAdapter(params.rhoInit,params.vx1Init,params.vx2Init,params.vx3Init));
+   if(initWithLogProfile) 
+   {
+    
+      boost::dynamic_pointer_cast<D3Q19InitDistributionsGridAdapter>(initadapter)->setVx1( inflowProfile );
+   }
+
+
+   boost::shared_ptr<D3Q19ClientGridPostProcessFileAdapter> writeDumpsAdapter(new D3Q19ClientGridPostProcessFileAdapter("shared",true,false));
+   writeDumpsAdapter->setScheduler(params.distributedDumpScheduler);
+   writeDumpsAdapter->setUseFileCounterInsteadTimestepForGlobalPVD(true);
+
+
+   UBLOG(logINFO, "put physicsAdapter to clients");
+   calculationManager.adaptGridByGridCriterionAtClients(physicsAdapterPtr,params.threadedClientCall);
+
+   boost::shared_ptr<AMR3DGridAdaptationCriterion>  hackAdapter(new D3Q19ChangeSlipToNoSlipGridAdapter());
+   UBLOG2(logINFO, std::cout, "add hackAdapter to clients");
+   calculationManager.addTimeDependentGridAdapterAtClients(hackAdapter,params.threadedClientCall);
+   UBLOG2(logINFO, std::cout, "## adapter stuff - start"); 
+
+   UBLOG(logINFO, "getAndAddInteractorsAtClients at clients");
+   calculationManager.getAndAddInteractorsAtClients(params.threadedClientCall);
+
+   UBLOG(logINFO, "put initadapter to clients");
+   calculationManager.adaptGridByGridCriterionAtClients(initadapter,params.threadedClientCall);
+   UBLOG(logINFO, "put setConnectorAdapter to clients");
+   boost::shared_ptr<AMR3DGridAdaptationCriterion>  setConnectorAdapter(new D3Q19SetConnectorsGridAdapter( ) );
+   calculationManager.adaptGridByGridCriterionAtClients(setConnectorAdapter,params.threadedClientCall);
+
+   if(decreaseViscositySteps) calculationManager.addTimeDependentGridAdapterAtClients(decreaseViscosityAdapter,params.threadedClientCall);
+
+   UBLOG(logINFO,"put writeAdapter to calc clients")
+      calculationManager.addClientGridAdapterAtClients(writeDumpsAdapter,params.threadedClientCall);
+   UBLOG(logINFO, "put writeInteractorTransNodesAdapter to clients" )
+      calculationManager.addClientGridAdapterAtClients(writeInteractorTransNodesAdapter, params.threadedClientCall); 
+
+   //remote connetoren
+   UBLOG(logINFO, "setRemoteConnectorsOnCalcServices at clients");
+   topoService.setRemoteConnectorsOnCalcServices(D3Q19System::getAMR3DDirsForD3Q19Dirs(),params.connsTransAttr,params.threadedClientCall);
+
+    UbFileOutputASCII out(UbStaticPathMap::getPath(UbStaticPathMap::GLOBAL)+"/params.txt");
+   if(out.isOpen())
+   {
+      UBLOG(logINFO, "save params to "<<out.getFileName());
+      params.write(&out);
+      out.writeLine();
+      out.writeString("useLodi                  "); out.writeBool(useLODI);             out.writeLine();
+      out.writeString("initWithLogProfile       "); out.writeBool(initWithLogProfile);  out.writeLine();
+      UBLOG(logINFO, " done" )
+   }
+
+
+   //##########################################################################
+   //## spongelayer
+   //##########################################################################
+   UBLOG2(logINFO, std::cout, "##################################################################");
+   UBLOG2(logINFO, std::cout, "## spongelayer - start");
+
+   GbCuboid3D* spongeCubeLeft = new GbCuboid3D( velBCCuboid->getX1Minimum() 
+      , velBCCuboid->getX2Minimum() 
+      , velBCCuboid->getX3Minimum() 
+      , velBCCuboid->getX1Maximum()+(velBCCuboid->getX1Maximum()-velBCCuboid->getX1Minimum() )*0.1-1.0*coarseNodeDx 
+      , velBCCuboid->getX2Maximum() 
+      , velBCCuboid->getX3Maximum() );
+
+   GbSystem3D::writeGeoObject( spongeCubeLeft, UbStaticPathMap::getPath(UbStaticPathMap::GLOBAL)+"/spongeIn", WbWriterVtkXmlBinary::getInstance() );
+   boost::shared_ptr<AMR3DGridAdaptationCriterion>  spongeAdapterLeft( new SpD3Q19SpongeLayerAdapter(spongeCubeLeft, 1./3., nueLB,  SpD3Q19SpongeLayerAdapter::ALTERNATIONX1) );
+   calculationManager.adaptGridByGridCriterionAtClients(spongeAdapterLeft ,params.threadedClientCall);
+
+
+
+   UBLOG2(logINFO, std::cout, "## spongelayerOutflow - start");
+                                                double H=kanallaengeSI/10.0;
+   GbCuboid3D* spongeCubeRight = new GbCuboid3D( originX1+geoLength[0]+fineNodeDx-H 
+      , originX2-geoOverlap             , originX3-geoOverlap
+      , originX1+geoLength[0]+geoOverlap, originX2+geoLength[1]+geoOverlap, originX3+geoLength[2]+geoOverlap   );   
+
+   GbSystem3D::writeGeoObject( spongeCubeRight, UbStaticPathMap::getPath(UbStaticPathMap::GLOBAL)+"/spongeOut", WbWriterVtkXmlBinary::getInstance() );
+   boost::shared_ptr<AMR3DGridAdaptationCriterion>  spongeAdapterRight( new SpD3Q19SpongeLayerAdapter(spongeCubeRight,  nueLB,1./3.,  SpD3Q19SpongeLayerAdapter::ALTERNATIONX1) );
+   calculationManager.adaptGridByGridCriterionAtClients(spongeAdapterRight ,params.threadedClientCall);
+   UBLOG2(logINFO, std::cout, "## spongelayer - end");
+   UBLOG2(logINFO, std::cout, "##################################################################");
+
+
+
+   //GbCuboid3D* densCuboid = NULL;
+   //##########################################################################
+
+   calculationManager.calculate(params.calcSteps, UbStaticPathMap::GLOBAL, params.schedulers);
+
+   UBLOG(logINFO, "warte nun auf ende!!");
+
+}
+
diff --git a/source/Applications/plate2/CMakeLists.txt b/source/Applications/plate2/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8bcfaf01f930a79e4b4bcef994fe79bd45830bb2
--- /dev/null
+++ b/source/Applications/plate2/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(plate2)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(plate2 BINARY)
diff --git a/source/Applications/plate2/plate2.cpp b/source/Applications/plate2/plate2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..adce2d5a178f169b56a49deb4ed26e5939ff1c22
--- /dev/null
+++ b/source/Applications/plate2/plate2.cpp
@@ -0,0 +1,557 @@
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+void run(const char *cstr1, const char *cstr2)
+{
+   try
+   {
+      string pathname; 
+      string pathGeo;
+      string pathLog;
+      int numOfThreads = 1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr1);
+
+      if(machine == "my") 
+      {
+         pathname = "d:/temp/plate2R1e6";
+         pathGeo = "d:/Data/plate";
+         pathLog = "d:/temp/plate2R1e6";
+         numOfThreads = 4;
+         logfile = false;
+         availMem = 15.0e9;
+      }
+      else if(machine == "Ludwig")      
+      {
+         pathname = "/work/koskuche/SFB880/plate2Con";
+         pathGeo = "/home/koskuche/data/plate";
+         pathLog = pathname;
+         numOfThreads = 8;
+         availMem = 12.0e9;///8*numOfThreads;
+         logfile = true;
+      }
+      else if(machine == "HLRS")      
+      {
+         pathname = "/univ_1/ws1/ws/xrmkuchr-plate3-0";
+         pathGeo = "/zhome/academic/HLRS/xrm/xrmkuchr/data/plate";
+         pathLog = "/zhome/academic/HLRS/xrm/xrmkuchr/work/plate";
+         numOfThreads = 16;
+         availMem = 2.0e9;
+         logfile = true;
+      }
+      else if(machine == "HLRN")      
+      {
+         pathname = "/gfs1/work/niivfcpu/scratch/plateEx";
+         pathGeo = "/gfs1/work/niivfcpu/data/plate";
+         pathLog = pathname;
+         numOfThreads = 24;
+         availMem = 64.0e9/24.0*numOfThreads;
+         logfile = true;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+#if defined(__unix__)
+      if (myid==0) 
+      {
+         const char* str = pathLog.c_str();
+         int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      }
+#endif 
+
+      if(myid == 0 && logfile)
+      {
+         //UbLog::reportingLevel() = logDEBUG5;
+         logFilename <<  pathLog + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      if(myid==0) UBLOG(logINFO,"Testcase plate");
+
+      //string PlatteFilename = pathGeo + "/Platte4mesh_1.8mmProbendicke.stl";
+      string PlatteFilename = pathGeo + "/platte_raw.stl";
+
+      string ZckbndFilename = pathGeo + "/2zackenbaender0.stl";
+
+      ///////////////Knotenabmessungen:
+      int nx[3], blocknx[3];
+      nx[0]      = 90;//240;//120;//60;//86;//43;//65;//50;  //länge
+      nx[1]      = 2;//2;//6;///1;//5;// //breite
+      nx[2]      = 30;//64;//32;//18;//5;//15;//15; //höhe gebiet
+      blocknx[0] = 16;//10;//6;
+      blocknx[1] = 16;//10;//6;
+      blocknx[2] = 16;//10;//6;
+
+      int baseLevel   = 0;
+      int refineLevel = 4;
+
+      double H = 600.0; // Kanalhöhe [mm]
+      double cdx = H/(double)(nx[2]*blocknx[2]);
+      double fdx = cdx/double(1<<refineLevel);
+
+      //double h = 200.0; // gewünschte Plattenhöhe in Gitterpunkten
+      //double fdx = plate->getLengthX3()/h;
+      //double cdx = fdx*double(1<<refineLevel);
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      double Re            = 1133333.3333333335; 
+      double rhoLB         = 0.0;
+      double uLB           = 0.1; 
+      double lReal         = 1000; //Plattenlänge in mm
+      double nuLB          = (uLB*(lReal/cdx))/Re;
+
+      int sizeSP=4;
+      mu::Parser spongeLayer;
+      spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+      spongeLayer.DefineConst("sizeX", nx[0]*blocknx[0]);
+      spongeLayer.DefineConst("sizeSP", sizeSP*blocknx[0]);
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(1000,1000,10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+      bool restart;
+
+      if (grid->getTimeStep() == 0)
+      {
+
+         if(myid==0) UBLOG(logINFO,"Neustart..");
+         restart = false;
+         //////////////////////////////////////////////////////////////////////////
+         //Platte
+         GbTriFaceMesh3DPtr plate (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(PlatteFilename,"Netz"));
+         plate->rotate(90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+         if(myid == 0) GbSystem3D::writeGeoObject( plate.get(), pathname+"/geo/platte", WbWriterVtkXmlBinary::getInstance() );
+         //////////////////////////////////////////////////////////////////////////
+         // Zackenband
+         //////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr meshBand1 (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand"));
+         meshBand1->translate(-495, -700, -19.94);
+         if(myid == 0) GbSystem3D::writeGeoObject( meshBand1.get(), pathname+"/geo/Band1", WbWriterVtkXmlASCII::getInstance() );
+         // Zackenband2
+         GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand2"));
+         meshBand2->translate(-495, -705, -19.94); 
+         if(myid == 0) GbSystem3D::writeGeoObject( meshBand2.get(), pathname+"/geo/Band2", WbWriterVtkXmlASCII::getInstance() );
+         // Zackenband3
+         GbTriFaceMesh3DPtr meshBand3(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand3"));
+         meshBand3->translate(-495, -700, -19.64); 
+         if(myid == 0) GbSystem3D::writeGeoObject( meshBand3.get(), pathname+"/geo/Band3", WbWriterVtkXmlASCII::getInstance() );
+         // Zackenband4
+         GbTriFaceMesh3DPtr meshBand4(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand4"));
+         meshBand4->translate(-495, -705, -19.64); 
+         if(myid == 0) GbSystem3D::writeGeoObject( meshBand4.get(), pathname+"/geo/Band4", WbWriterVtkXmlASCII::getInstance() );
+         //////////////////////////////////////////////////////////////////////////
+
+         double blockLengthx1 = blocknx[0]*cdx; //geowerte
+         double blockLengthx2 = blockLengthx1;
+         double blockLengthx3 = blockLengthx1;
+
+         double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+         double originX1 = plate->getX1Minimum()-plate->getLengthX1()/4.0;
+         double originX2 = plate->getX2Minimum();
+         double originX3 = plate->getX3Minimum()-299.5;
+
+
+         bool periodicx1 = false;
+         bool periodicx2 = true;
+         bool periodicx3 = true;
+
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];;
+
+
+         //set grid
+         grid->setDeltaX(cdx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         gridCube->setCenterCoordinates(gridCube->getX1Centroid(),meshBand1->getX2Centroid(),gridCube->getX3Centroid());
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         originX2 = gridCube->getX2Minimum();
+         g_minX2 = originX2;
+         g_maxX2 = originX2 + geoLength[1];
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            ="<<Re);
+            UBLOG(logINFO, "* nuLB          ="<<nuLB);
+            UBLOG(logINFO, "* uLB           ="<<uLB);
+            UBLOG(logINFO, "* cdx           ="<<cdx);
+            UBLOG(logINFO, "* fdx           ="<<fdx);
+            double Hzb = 0.6/fdx;
+            UBLOG(logINFO, "* Height of Zackenband ="<<Hzb);
+            UBLOG(logINFO, "* Re on Zackenband ="<<(uLB*Hzb)/(nuLB*double(1<<refineLevel)));
+            UBLOG(logINFO, "* nx1/2/3       ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x1Periodic    ="<<periodicx1);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "* number of levels  ="<<refineLevel+1);
+            UBLOG(logINFO, "* path          ="<<pathname);
+
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* number of threads    ="<<numOfThreads);
+            UBLOG(logINFO, "* number of processes  ="<<comm->getNumberOfProcesses());
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "*****************************************");     
+         }
+         //////////////////////////////////////////////////////////////////////////
+
+
+         //////////////////////////////////////////////////////////////////////////
+         //refinement
+         GbCuboid3DPtr refinePlatteBox(new GbCuboid3D(plate->getX1Minimum(), plate->getX2Minimum(), plate->getX3Minimum()+(plate->getX3Maximum()-plate->getX3Minimum())/2.0, 
+            plate->getX1Maximum()+40.0, plate->getX2Maximum(), plate->getX3Maximum()));
+         if(myid == 0) GbSystem3D::writeGeoObject( refinePlatteBox.get(), pathname+"/geo/refinePlatteBox", WbWriterVtkXmlASCII::getInstance() );
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            refineHelper.addGbObject(refinePlatteBox, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         /////////////////////////////////////////////////
+         ///interactoren
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+         D3Q27TriFaceMeshInteractorPtr triPlateInteractor( new D3Q27TriFaceMeshInteractor(plate, grid, bcObst,Interactor3D::SOLID));
+         D3Q27TriFaceMeshInteractorPtr triBand1Interactor( new D3Q27TriFaceMeshInteractor( meshBand1, grid, bcObst,Interactor3D::SOLID, Interactor3D::EDGES) );
+         D3Q27TriFaceMeshInteractorPtr triBand2Interactor( new D3Q27TriFaceMeshInteractor( meshBand2, grid, bcObst,Interactor3D::SOLID, Interactor3D::EDGES) );
+         D3Q27TriFaceMeshInteractorPtr triBand3Interactor( new D3Q27TriFaceMeshInteractor( meshBand3, grid, bcObst,Interactor3D::SOLID, Interactor3D::EDGES) );
+         D3Q27TriFaceMeshInteractorPtr triBand4Interactor( new D3Q27TriFaceMeshInteractor( meshBand4, grid, bcObst,Interactor3D::SOLID, Interactor3D::EDGES) );
+
+         //inflow
+         GbCuboid3DPtr velBCCuboid(new GbCuboid3D(originX1-blockLengthx1, originX2-blockLengthx1, originX3-blockLengthx1, 
+            originX1, originX2+geoLength[1]+blockLengthx1, originX3+geoLength[2]+blockLengthx1));
+         if(myid == 0) GbSystem3D::writeGeoObject(velBCCuboid.get(), pathname+"/geo/velBCCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(velBCCuboid,grid,Interactor3D::SOLID)); 
+
+         //inflow
+         double raiseVelSteps = 0;
+         vector<D3Q27BCFunction> velcX1BCs,dummy;
+
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("uLB"); 
+         inflowProfile.DefineConst("uLB",uLB);
+         velcX1BCs.push_back(D3Q27BCFunction(inflowProfile,raiseVelSteps,D3Q27BCFunction::INFCONST));
+
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (velcX1BCs,dummy,dummy));
+         velBCInteractor->addBCAdapter(velBCAdapter);
+
+         //outflow
+         GbCuboid3DPtr densCuboid(new GbCuboid3D(originX1+geoLength[0], originX2-blockLengthx1, originX3-blockLengthx1, 
+            originX1+geoLength[0]+blockLengthx1, originX2+geoLength[1]+blockLengthx1, originX3+geoLength[2]+blockLengthx1 ));
+         if(myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname+"/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr densInteractor( new D3Q27Interactor(densCuboid,grid,denBCAdapter,Interactor3D::SOLID) );
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));	
+
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         intHelper.addInteractor(triPlateInteractor);
+         intHelper.addInteractor(triBand1Interactor);
+         intHelper.addInteractor(triBand2Interactor);
+         intHelper.addInteractor(triBand3Interactor);
+         intHelper.addInteractor(triBand4Interactor);
+         intHelper.addInteractor(densInteractor);
+         intHelper.addInteractor(velBCInteractor);
+         intHelper.selectBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+
+         //domain decomposition for threads
+         if(numOfThreads > 1)
+         {
+            PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+            grid->accept(pqPartVisitor);
+         }
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Write blocks - start");
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            ppblocks->update(0);
+            UBLOG(logINFO,"Write blocks - end");
+         }
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+         unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+         unsigned long nodb = (blocknx[0]) * (blocknx[1]) * (blocknx[2]);
+
+         double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+         
+         double nup = 0; 
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for(int level = minInitLevel; level<=maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nobl);
+               UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nobl*nodb);
+               nup += nobl*nodb*double(1<<level); 
+            }
+            UBLOG(logINFO,"Hypothetically time for calculation step for 120 nodes  = " << nup/6.0e5/(120*8)  << " s");
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+            UBLOG(logINFO,"Available memory per node/8.0 = " << (availMem/8.0) << " bytes");
+         }
+
+         //////////////////////////////////////////
+         //set connectors
+         if(myid == 0) UBLOG(logINFO,"set connectors - start");
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         if(myid == 0) UBLOG(logINFO,"set connectors - end");
+
+         ////////////////////////////
+         LBMKernel3DPtr kernel;
+         //kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+         //with sponge layer
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+         kernel->setWithSpongeLayer(true);
+         kernel->setSpongeLayer(spongeLayer);
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+
+         intHelper.setBC();
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nuLB,rhoLB);
+         initVisitor.setVx1(uLB);
+         grid->accept(initVisitor);
+
+         //Postprozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+      }
+      else
+      {
+         restart = true;
+
+         //domain decomposition for threads
+         if(numOfThreads > 1)
+         {
+            PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+            grid->accept(pqPartVisitor);
+         }
+         //set connectors
+         //grid->setPeriodicX3(false);
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         SetSpongeLayerBlockVisitor ssp(spongeLayer);
+         grid->accept(ssp);
+
+         //////////////////////////////////////////////////////////////////////////
+         //////////////////////////////////////////////////////////////////////////
+         //Platte
+         GbTriFaceMesh3DPtr plate (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(PlatteFilename,"Netz"));
+         plate->rotate(90.0,0.0,0.0);  //TriFacMesh-KO-System anders als LB-KO-System
+         if(myid == 0) GbSystem3D::writeGeoObject( plate.get(), pathname+"/geo/platte", WbWriterVtkXmlBinary::getInstance() );
+         //////////////////////////////////////////////////////////////////////////
+         //////////////////////////////////////////////////////////////////////////
+         // Zackenband
+         //////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr meshBand1 (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand"));
+         meshBand1->translate(-495, -700, -19.94);
+         if(myid == 0) GbSystem3D::writeGeoObject( meshBand1.get(), pathname+"/geo/Band1", WbWriterVtkXmlASCII::getInstance() );
+
+         double blockLengthx1 = blocknx[0]*cdx; //geowerte
+         double blockLengthx2 = blockLengthx1;
+         double blockLengthx3 = blockLengthx1;
+
+         double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3}; 
+
+         double originX1 = plate->getX1Minimum()-plate->getLengthX1()/4.0;
+         double originX2 = plate->getX2Minimum();
+         double originX3 = plate->getX3Minimum()-299.5;
+
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];;
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         gridCube->setCenterCoordinates(gridCube->getX1Centroid(),meshBand1->getX2Centroid(),gridCube->getX3Centroid());
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         originX2 = gridCube->getX2Minimum();
+         g_minX2 = originX2;
+         g_maxX2 = originX2 + geoLength[1];
+         //walls
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_minX3-blockLengthx1, g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(g_minX1-blockLengthx1, g_minX2-blockLengthx1, g_maxX3, g_maxX1+blockLengthx1, g_maxX2+blockLengthx1, g_maxX3+blockLengthx1));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //walls
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB        
+         D3Q27BoundaryConditionAdapterPtr slip(new D3Q27SlipBCAdapter(bbOption));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, slip,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, slip,Interactor3D::SOLID));
+
+         SetSolidOrTransBlockVisitor v1(addWallZminInt, SetSolidOrTransBlockVisitor::TRANS);
+         grid->accept(v1);
+         addWallZminInt->initInteractor();
+         SetSolidOrTransBlockVisitor v2(addWallZmaxInt, SetSolidOrTransBlockVisitor::TRANS);
+         grid->accept(v2);        
+         addWallZmaxInt->initInteractor();
+
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+         geoSch.reset();
+         //////////////////////////////////////////////////////////////////////////
+
+         if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      }
+      UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(1,0,3);
+      //visSch->addSchedule(100,100,1000);
+      //visSch->addSchedule(1000,1000,5000);
+      //visSch->addSchedule(5000,5000,100000);
+      //visSch->addSchedule(100000,100000,10000000);
+
+      visSch->addSchedule(1000,1000,10000000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      double startStep = 88000;
+
+      UbSchedulerPtr resSchRMS(new UbScheduler());
+      resSchRMS->addSchedule(1000000, startStep, 10000000);
+      UbSchedulerPtr resSchMeans(new UbScheduler());
+      resSchMeans->addSchedule(1000000, startStep, 10000000);
+      UbSchedulerPtr stepAvSch(new UbScheduler());
+      int averageInterval=100;
+      stepAvSch->addSchedule(averageInterval,0,10000000);
+      AverageValuesPostprocessor Avpp(grid, pathname, WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/, 
+         stepAvSch/*wann wird gemittelt*/, resSchMeans,resSchRMS/*wann wird resettet*/,restart);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      nupsSch->addSchedule(500,500,1e6);
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      UbSchedulerPtr emSch(new UbScheduler(10));
+      EmergencyExitPostprocessor empr(grid, emSch, pathname, RestartPostprocessorPtr(&rp), comm);
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      string lastStep = string(cstr2);
+      double endTime = UbSystem::stringTo<double>(lastStep);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   if (argc == 1)
+   {
+      cout<<"Command line argument isn't specified!"<<endl;
+      cout<<"plate2 <machine name>"<<endl;
+      return 1;
+   }
+   run(argv[1], argv[2]);
+
+   return 0;
+}
+
diff --git a/source/Applications/pmTortu/CMakeLists.txt b/source/Applications/pmTortu/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..000cf49662caf85298e49d5e4d1ca493984a035e
--- /dev/null
+++ b/source/Applications/pmTortu/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(plate)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(pmTortu BINARY)
diff --git a/source/Applications/pmTortu/pmTortu.cpp b/source/Applications/pmTortu/pmTortu.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ddd039ec87f973720cf6191c23d08b4217658bde
--- /dev/null
+++ b/source/Applications/pmTortu/pmTortu.cpp
@@ -0,0 +1,511 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+using namespace std;
+
+//! \brief  Computes Flow thorugh a porous medium and writespathlines
+//! \details Aim: determine tortuosity. pathlines are later integrated using python-script streamlinesMean.py (needs scipy,numpy)
+//! \details If PM-data is large run on single visulalization node.
+//! \details Created on: 01.07.2013
+//! \author  Sonja Uphoff
+
+void run(const char *cstr)
+{
+   try
+   {
+     string machine = QUOTEME(CAB_MACHINE);
+      UBLOG(logINFO,"Testcase PMTortuosity");
+      string pathname;
+      string stlPath;
+      int numOfThreads =1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      UbLog::reportingLevel() = logDEBUG5; //logINFO;
+
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+
+      if(machine == "PIPPINNEU")
+      {
+
+         pathname = "f:/temp/PMtortu";
+         stlPath = "f:/GeometrienVliese";
+         numOfThreads = 3;
+         logfile = false;
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")
+      {
+         pathname = "/work/sonjaOutputs/PMTortu2metall450";
+         stlPath = "/work/sonjaOutputs";
+         numOfThreads = 4;
+         availMem = 12.0e9;
+         logfile = true;
+
+         //if(myid ==0)
+         //{
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         //}
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+
+
+      //if(myid ==0 && logfile)
+      //{
+         UbLog::output_policy::setStream(logFilename.str());
+      //}
+
+      int baseLevel, refineLevel,nx[3],blocknx[3];
+      double Re,velocity,rhoInit,vx1Init;//,vx2Init,vx3Init;
+
+//////////////////////////////////////////////////////////////////////////
+      //physik
+//////////////////////////////////////////////////////////////////////////
+      Re            = 1;// 13286;//13286;//gemessen 18.98 m/s...*5.0 zum  testen ob was passiert
+      velocity      = 0.01;
+      vx1Init       = 0.01;
+      rhoInit       = 1.0;
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+
+      ///////////////Knotenabmessungen:
+
+    nx[0]=28;
+    nx[1]=27;
+       nx[2]=27;
+    blocknx[0]=10;
+    blocknx[1]=10;
+    blocknx[2]=10;
+
+   baseLevel   = 0;
+   refineLevel = 0;
+
+      bool periodicx1 = false;
+      bool periodicx2 = false;
+      bool periodicx3 = false;
+
+
+
+   double minX1 = 0.0;
+   double maxX1 = 280;
+   double minX2 = 0.0;
+   double maxX2 = 270;
+   double minX3 = 0.0;
+   double maxX3 = 270;
+   double centerX1 = 0.5*(maxX1-minX1);
+   double centerX2 = 0.5*(maxX2-minX2);
+   //double scaleAsphalt = 0.0000625; //10/1600
+   double scalepixeltomm=0.5;
+   double scaleAsphalt = 1.0;
+   minX1 = minX1*scaleAsphalt;
+   minX2 = minX2*scaleAsphalt;
+   minX3 = minX3*scaleAsphalt;
+   maxX1 = maxX1*scaleAsphalt;
+   maxX2 = maxX2*scaleAsphalt;
+   maxX3 = maxX3*scaleAsphalt;
+
+   //vorgabe geom. dx im feinsten = 1 -> abstand der voxel = 1
+   double coarseNodeDx = (maxX2 - minX2) / (double)( blocknx[1]*nx[1] );
+   double fineNodeDx   = coarseNodeDx / (double)(1<<refineLevel);
+
+   double blockLengthx1 = blocknx[0]*coarseNodeDx;
+   double blockLengthx2 = blocknx[1]*coarseNodeDx;
+   double blockLengthx3 = blocknx[2]*coarseNodeDx;
+
+   double originX1 = minX1;
+   double originX2 = minX2;
+   double originX3 = minX3;
+
+   int nx1 = nx[0];
+   int nx2 = nx[1];
+   int nx3 = nx[2];
+   int blocknx1      = blocknx[0];
+   int blocknx2      = blocknx[1];
+   int blocknx3      = blocknx[2];
+
+   double gridOrigin[3] = { originX1, originX2, originX3 };
+
+   //geom. GROBE Blocklaenge
+   double coarseBlockLength[3];
+   coarseBlockLength[0] = blockLengthx1;
+   coarseBlockLength[1] = blockLengthx2;
+   coarseBlockLength[2] = blockLengthx3;
+   double geoLength[]   = {  nx[0]*blockLengthx1, nx[1]*blockLengthx2, nx[2]*blockLengthx3};
+
+//////////////////////////////////////////////////////////////////////////
+   // PM File
+//////////////////////////////////////////////////////////////////////////
+   string pmFilename;
+   pmFilename = stlPath+"/metallrgbx271y271z270.vti";//
+   int pmNX1=270;
+   int pmNX2=271;
+   int pmNX3=270;
+   float threshold = 120.0;
+
+         GbVoxelMatrix3DPtr pmMesh(GbVoxelMatrix3DCreator::getInstance()->createFromVtiASCIIFloatFile(pmFilename,pmNX1,pmNX2,pmNX3,threshold));
+
+pmMesh->translate((maxX1-minX1)*0.05,-(maxX2-minX2)*0.01,-(maxX3-minX3)*0.01);
+   pmMesh->setTransferViaFilename(true, pmFilename);
+
+//##########################################################################
+      //## physical parameters
+//##########################################################################
+
+      double rhoLB         = 1.0;
+      double rhoReal       = 1.0;
+      double nueReal  = 0.16;//0.015;
+
+      double hReal         = maxX1;
+      double uReal         = Re*nueReal/hReal;
+
+      //##Machzahl:
+      //#Ma     = uReal/csReal
+
+      double csReal  = 1.0/sqrt(3.0);
+      double cs_LB=1.0/sqrt(3.0);
+      double Ma      = uReal/csReal;//0.0553;//Ma-Real!
+      double hLB     = hReal;
+
+      //LBMUnitConverter unitConverter(hReal, csReal, rhoReal, hLB);
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter(hReal, csReal, rhoReal, blocknx[0]*nx[0] ));
+
+      double uLB           = uReal   * unitConverter->getFactorVelocityWToLb();
+      double nueLB         = nueReal * unitConverter->getFactorViscosityWToLb();
+
+      double realDeltaT     = (nueLB * hReal *hReal) / (nueReal * blocknx[0]*nx[0] *blocknx[0]*nx[0]);
+
+
+
+      Grid3DPtr grid(new Grid3D());
+      UbSchedulerPtr rSch(new UbScheduler(5000,5000,1000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+
+//////////////////////////////////////////////////////////////////////////
+
+     std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      //bounding box
+      double g_minX1 = originX1;
+      double g_minX2 = originX2;
+      double g_minX3 = originX3;
+
+      double g_maxX1 = originX1 + geoLength[0];
+      double g_maxX2 = originX2 + geoLength[1];
+      double g_maxX3 = originX3 + geoLength[2];
+
+      //set grid
+      grid->setDeltaX(coarseNodeDx);
+      grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+      grid->setPeriodicX1(periodicx1);
+      grid->setPeriodicX2(periodicx2);
+      grid->setPeriodicX3(periodicx3);
+
+
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+      GenBlocksGridVisitor genBlocks;
+      genBlocks.addGeoObject(gridCube);
+      grid->accept(genBlocks);
+
+
+//////////////////////////////////////////////////////////////////////////
+      if(myid == 0)
+      {
+         UBLOG(logINFO, "*****************************************");
+         UBLOG(logINFO, "* Parameters *");
+         UBLOG(logINFO, "* Re            ="<<Re);
+         UBLOG(logINFO, "* Ma            ="<<Ma);
+         UBLOG(logINFO, "* uReal         ="<<uReal);
+         UBLOG(logINFO, "* nueReal       ="<<nueReal);
+         UBLOG(logINFO, "* nue           ="<<nueLB);
+         UBLOG(logINFO, "* velocity      ="<<uLB);
+         UBLOG(logINFO, "* LX1 (world/LB)="<<hReal<<"/"<<hReal/coarseNodeDx);
+      //   UBLOG(logINFO, "* LX2 (world/LB)="<<kanalbreiteSI<<"/"<<kanalbreiteSI/coarseNodeDx);
+      //   UBLOG(logINFO, "* LX3 (world/LB)="<<kanalhoeheSI<<"/"<<kanalhoeheSI/coarseNodeDx);
+         UBLOG(logINFO, "* cdx           ="<<coarseNodeDx);
+         UBLOG(logINFO, "* fdx           ="<<fineNodeDx);
+         UBLOG(logINFO, "* dx_base ="<<coarseNodeDx<<" == "<<coarseNodeDx);
+         UBLOG(logINFO, "* dx_refine ="<<fineNodeDx<<" == "<<fineNodeDx );
+         UBLOG(logINFO, "* nx1/2/3 ="<<nx[0]<<"/"<<nx[1]<<"/"<<nx[2]);
+         UBLOG(logINFO, "* blocknx1/2/3 ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+         UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+         UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+         UBLOG(logINFO, "*****************************************");
+         UBLOGML(logINFO, "UnitConverter:"<<unitConverter->toString());
+         UBLOG(logINFO, "*****************************************");
+      }
+
+
+      RatioBlockVisitor ratioVisitor(refineLevel);
+      grid->accept(ratioVisitor);
+      RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+      grid->accept(ratioSmoothVisitor);
+      OverlapBlockVisitor overlapVisitor(refineLevel);
+      grid->accept(overlapVisitor);
+      std::vector<int> dirs;
+      D3Q27System::getLBMDirections(dirs);
+      SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+      grid->accept(interDirsVisitor);
+
+      if(myid == 0) UBLOG(logINFO,"Refinement - end");
+
+      MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+      grid->accept( metisVisitor );
+
+      if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+      if(myid == 0) ppblocks->update(0);
+      if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+      SolidBlocksHelper sd(grid, comm);
+
+
+      sd.deleteSolidBlocks();
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");
+
+      if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+      grid->accept( metisVisitor );
+      if(myid == 0) ppblocks->update(1);
+      ppblocks.reset();
+      if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+      unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+
+      double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }
+
+      LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx[0], blocknx[1], blocknx[2]));
+
+  //    LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx[0], blocknx[1], blocknx[2],1));
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+
+      grid->accept(kernelVisitor);
+
+
+
+//////////////////////////////////////////////////////////////////////////
+    double geoOverlap = 5*coarseNodeDx;
+
+
+//////////////////////////////////////////////////////////////////////////
+   // Interactoren
+//////////////////////////////////////////////////////////////////////////
+//##########################################################################
+   int noSlipSecOpt = 0; // #0=2nd order BB 1=simple BB
+//##########################################################################
+   int noSlipSecOptAsphalt = 1; // #0=2nd order BB 1=simple BB
+//##########################################################################
+     int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+     D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+   D3Q27InteractorPtr PM1Interactor = D3Q27InteractorPtr ( new D3Q27Interactor(pmMesh, grid, bcObst,Interactor3D::SOLID)); //wo ist bc obst definiert?
+ grid->addAndInitInteractor( PM1Interactor);
+   //UBLOG(logINFO,"SpD3Q19Asphalt - send porous media to D3Q19InteractorService");
+   //UBLOG(logINFO,"SpD3Q19Asphalt - send porous media = "<<pmInteractor->getName()<<" with "<<typeid(*pmInteractor->getGbObject3D()).name()<<" node("<<pmNX1<<"/"<<pmNX2<<"/"<<pmNX3<<")");
+   UbTimer timer;
+   timer.start();
+
+
+   UBLOG(logINFO,"SpD3Q19Asphalt - send porous media to D3Q19InteractorService done in "<<timer.stop());
+
+
+      if (refineLevel > 0)
+      {
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+
+      //initialization of decompositions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+      initVisitor.setVx1(0.0);
+      grid->accept(initVisitor);
+
+
+ //////////////////////////////////////////////////////////////////////////
+   // BCs
+//////////////////////////////////////////////////////////////////////////
+      //Reparatur an den Seiten:
+       UBLOG(logINFO,"inflow")
+           double x3minMesh=0.000;  double x3maxMesh=originX3 + blockLengthx3*nx3 + geoOverlap;
+   GbCuboid3DPtr leftCuboid(new GbCuboid3D( originX1 + blockLengthx1*nx1 - coarseNodeDx,
+                                           originX2 - geoOverlap,
+                                           x3minMesh,
+                                           originX1 + blockLengthx1*nx1 + geoOverlap,
+                                           originX2 + blockLengthx2*nx2 + geoOverlap,
+                                           x3maxMesh));
+   GbCuboid3DPtr rightCuboid(new GbCuboid3D( originX1 - geoOverlap,
+                                           originX2 - geoOverlap,
+                                           x3minMesh,
+                                           originX1 + geoOverlap,
+                                           originX2 + blockLengthx2*nx2 + geoOverlap,
+                                           x3maxMesh));
+   GbCuboid3DPtr northCuboid(new GbCuboid3D( originX1- geoOverlap,
+                                           originX2 + blockLengthx2*nx2 - 0.5*coarseNodeDx,
+                                           x3minMesh,
+                                           originX1 + blockLengthx1*nx1 + geoOverlap,
+                                           originX2 + blockLengthx2*nx2 + geoOverlap,
+                                           x3maxMesh));
+   GbCuboid3DPtr southCuboid(new GbCuboid3D( originX1 - geoOverlap,
+                                           originX2 - geoOverlap,
+                                           x3minMesh,
+                                           originX1 + blockLengthx1*nx1 + geoOverlap,
+                                           originX2 + geoOverlap,
+                                           x3maxMesh));
+
+//////////////////////////////////////////////////////////////////////////
+   // inflow
+//////////////////////////////////////////////////////////////////////////
+   UBLOG(logINFO,"inflow")
+
+   GbCuboid3DPtr densCuboid(new GbCuboid3D(
+                                           originX1 - geoOverlap,
+                                           originX2 - geoOverlap,
+                                           originX3 + blockLengthx3*nx3 - coarseNodeDx,
+                                           originX1 + blockLengthx1*nx1 + geoOverlap,
+                                           originX2 + blockLengthx2*nx2 + geoOverlap,
+                                           originX3 + blockLengthx3*nx3 + geoOverlap));
+
+
+//////////////////////////////////////////////////////////////////////////
+   // bottom/outflow
+//////////////////////////////////////////////////////////////////////////
+      double dRho=0.05;
+      GbCuboid3DPtr densCuboid2(new GbCuboid3D(
+                                                 originX1 - geoOverlap,
+                                                 originX2 - geoOverlap,
+                                                 originX3 - geoOverlap,
+                                                 originX1 + blockLengthx1*nx1 + geoOverlap,
+                                                 originX2 + blockLengthx2*nx2 + geoOverlap,
+minX3+0.5*fineNodeDx   ));
+
+      if(myid == 0) GbSystem3D::writeGeoObject(densCuboid2.get(), pathname+"/geo/densCuboid2", WbWriterVtkXmlASCII::getInstance());
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter2(new D3Q27DensityBCAdapter(rhoInit-dRho));
+      D3Q27InteractorPtr densInteractor2( new D3Q27Interactor(leftCuboid,grid,denBCAdapter2,Interactor3D::SOLID) );
+      grid->addAndInitInteractor( densInteractor2 );
+
+            if(myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname+"/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoInit+dRho));
+      D3Q27InteractorPtr densInteractor( new D3Q27Interactor(rightCuboid,grid,denBCAdapter,Interactor3D::SOLID) );
+      grid->addAndInitInteractor( densInteractor );
+
+   D3Q27InteractorPtr leftInteractor = D3Q27InteractorPtr ( new D3Q27Interactor(densCuboid2, grid, bcObst,Interactor3D::SOLID));
+   grid->addAndInitInteractor( leftInteractor);
+   D3Q27InteractorPtr rightInteractor = D3Q27InteractorPtr ( new D3Q27Interactor(densCuboid, grid, bcObst,Interactor3D::SOLID));
+  grid->addAndInitInteractor(rightInteractor);
+   D3Q27InteractorPtr northInteractor = D3Q27InteractorPtr ( new D3Q27Interactor(northCuboid, grid, bcObst,Interactor3D::SOLID));
+   grid->addAndInitInteractor(northInteractor);
+   D3Q27InteractorPtr southInteractor = D3Q27InteractorPtr ( new D3Q27Interactor(southCuboid, grid, bcObst,Interactor3D::SOLID));
+  grid->addAndInitInteractor(southInteractor);
+
+  if(myid == 0) GbSystem3D::writeGeoObject(northCuboid.get(), pathname+"/geo/north", WbWriterVtkXmlASCII::getInstance());
+if(myid == 0) GbSystem3D::writeGeoObject(southCuboid.get(), pathname+"/geo/south", WbWriterVtkXmlASCII::getInstance());
+if(myid == 0) GbSystem3D::writeGeoObject(rightCuboid.get(), pathname+"/geo/right", WbWriterVtkXmlASCII::getInstance());
+if(myid == 0) GbSystem3D::writeGeoObject(leftCuboid.get(), pathname+"/geo/left", WbWriterVtkXmlASCII::getInstance());
+
+
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+           new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(),
+unitConverter, comm, true));
+
+              double raiseVelSteps = 0;
+
+      grid->doPostProcess(0);
+      ppgeo.reset();
+      geoSch.reset();
+
+     UbSchedulerPtr plSch(new UbScheduler(10, 2));
+      vector<D3Q27PathLinePostprocessorPtr> pathlinepostPParray;
+
+ for (int ppz=0; ppz<27; ppz++)
+      {
+      for (int ppy=0; ppy<27; ppy++)
+      {
+          char numstr[21];
+          sprintf(numstr, "%d", ppy+20*ppz);
+          std::string pathPL = pathname+"/pathline" + numstr+".dat";
+         D3Q27PathLinePostprocessorPtr plptr1( new D3Q27PathLinePostprocessor(grid, pathPL, WbWriterVtkXmlASCII::getInstance(), unitConverter, plSch, comm, 8.0, 6.0+8.0*(double)ppy,5.0+8.0*(double)ppz, nueLB, iProcessor));
+              pathlinepostPParray.push_back(plptr1);//new D3Q27PathLinePostprocessor(grid, pathname + "/pathLine", WbWriterVtkXmlASCII::getInstance(), conv, plSch, comm, 0.01+(double)ppx*0.0001, 0.00001,0.00001, nueLB, iProcessor));
+
+          }
+      }
+
+ UbSchedulerPtr visSch(new UbScheduler());
+      visSch->addSchedule(1,1,10);
+      visSch->addSchedule(10,10,100);
+      visSch->addSchedule(100,100,1000);
+      visSch->addSchedule(1000,1000,100000);
+      visSch->addSchedule(100000,100000,1000000);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), unitConverter, comm);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+//////////////////////////////////////////////////////////////////////////
+
+      cout << "PID = " << myid << " Total Physical Memory (RAM): " << MemoryUtil::getTotalPhysMem()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used: " << MemoryUtil::getPhysMemUsed()<<endl;
+      cout << "PID = " << myid << " Physical Memory currently used by current process: " << MemoryUtil::getPhysMemUsedByMe()<<endl;
+
+      double endTime = 40001;
+      UbSchedulerPtr ghostLSch(new UbScheduler());
+      ghostLSch->addSchedule(1,1,endTime);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, ghostLSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+} 
diff --git a/source/Applications/pmTortu/streamlinesMean.py b/source/Applications/pmTortu/streamlinesMean.py
new file mode 100644
index 0000000000000000000000000000000000000000..47d39b94575168d514e53a282bb068d6eaa6d787
--- /dev/null
+++ b/source/Applications/pmTortu/streamlinesMean.py
@@ -0,0 +1,162 @@
+import os
+import scipy
+import numpy
+import math
+
+#li=[[5,0.005]]
+
+n=409;
+i=0;
+j=0;
+k=0;
+length=[0];
+lengthx=[0];
+lengthT=[0,0,0,0,0];
+lengthxT=[0,0,0,0,0];
+ItortuList=[0];
+outKOx=78.0;#0.105;
+try:
+ for i in range(1,n):
+  length.append(0);
+  lengthx.append(0);
+  #if (i<10):
+  # dateiIn="C:/Users/Sonja/Documents/pathlines3/pathline30"+str(i)+".dat.ascii.vtu"
+  #else:
+  dateiIn="C:/Users/Sonja/Documents/blech2c/pathline"+str(i)+".dat.ascii.vtu"
+  print dateiIn
+  datei = open(dateiIn,"r")
+  j=0; k=0;
+  for line in datei:
+     j=j+1
+     #print line
+ ##   if ((i>6568) and (i<17261)  ):
+     #zuordnung = line.split("  ")
+     #if (j==1): print line
+     if (k==1): ##marker der anfang der koordinaten bezeichnet
+         zuordnung = line.split("  ")
+         #print zuordnung
+         #pointsxyz=zuordnung[7].split(" ")
+         #print pointsxyz
+         t=0;
+         for entry in zuordnung:
+             pointsxyz=entry.split(" ")
+             #print pointsxyz
+             t=t+1;
+             #if (i==1 | i==2):
+             lengthT.append(0);
+             lengthxT.append(0);
+             if (t>7):
+              if (pointsxyz[1]!="\n"):
+               if(float(pointsxyz[1])<outKOx): ##ende messbereich
+                 #print pointsxyz
+                 if (t==8):
+                     xalt=float(pointsxyz[1]);
+                     yalt=float(pointsxyz[2]);
+                     zalt=float(pointsxyz[3]);
+                 xneu=float(pointsxyz[1]);
+                 yneu=float(pointsxyz[2]);
+                 zneu=float(pointsxyz[3]);
+                 if (xalt>20.0):              ##beginn messbereicht
+                  length[i]=length[i]+math.sqrt((xneu-xalt)*(xneu-xalt)+(yneu-yalt)*(yneu-yalt)+(zneu-zalt)*(zneu-zalt));
+                  lengthx[i]=lengthx[i]+(xneu-xalt);
+                  lengthT[t]=lengthT[t]+length[i];
+                  lengthxT[t]=lengthxT[t]+lengthx[i];
+                  #print lengthT[t]
+                  #print xneu
+                  #print lengthx[i]
+                 xalt=xneu; yalt=yneu; zalt=zneu;
+                 
+ 
+         k=2;
+     #if (str(line)=="""            <DataArray type="Float64" NumberOfComponents="3" format="ascii">"""):
+ 
+     if(j==5):
+       print line
+       k=1;
+     #print zuordnung
+     #print zuordnung[0]
+     #print zuordnung[1]
+     #test0=float(zuordnung[0])
+     #test1=float(zuordnung[1])
+     #li.append([test0,test1])
+ ##print float(li[10])/20
+ #print li
+  datei.close();
+ i=0;
+ j=0;
+ length.pop(0);
+ lengthx.pop(0);
+ #print length
+ #print lengthx
+ tortuGes=0;
+ LGes=0.0;
+ LxGes=0.0;
+ fFile = open("f:/temp/pathlinesb2cLength.dat", "w")
+ for entry in length:
+     #print entry;
+     #print lengthx[i];
+     LGes=LGes+length[i];
+     LxGes=LxGes+lengthx[i];
+     ItortuList.append(entry/max(lengthx[i],0.00000001));
+     if (length[i]>2.0):
+      Itortu=entry/lengthx[i]
+      print Itortu
+      j=j+1;
+      tortuGes=tortuGes+Itortu;
+     i=i+1
+     fFile.write(str(i))
+     fFile.write(" ")
+     fFile.write(str(entry))
+     fFile.write(" ")
+     #fFile.write(str(lengthx[i]))
+     #fFile.write(" ")
+     #fFile.write(str(entry/max(lengthx[i],0.00000001)))   
+     fFile.write("\n")
+ tortuGes=tortuGes/j;
+ print "berücksichtigte Stromlinien:" 
+ print j
+ fFile.close();
+ ItortuList.pop(0);
+ print "TortuGes:"
+ print tortuGes;
+ print "Lges:"
+ print LGes;
+ print "Lxges:"
+ print LxGes;
+ print "Lges/LxGes:"
+ print LGes/LxGes;
+ erg=[lengthx,length,ItortuList];
+ #print erg
+ erg=numpy.asarray(erg).T.tolist() #does a list-transpose
+ #print erg
+ erg=sorted(erg);
+ fFile = open("f:/temp/pathlinesb2cLengthSortt1000.dat", "w")
+ i=0;
+ #print erg[1][1]
+ #print erg[0][1]
+ for entry in erg:
+     i=i+1;
+     #print i
+     fFile.write(str(entry[0]))
+     fFile.write(" ")
+     fFile.write(str(entry[1]))
+     fFile.write(" ")
+     fFile.write(" ")
+     fFile.write(str(entry[2]))
+     fFile.write("\n")
+ fFile.close();
+ fFile = open("f:/temp/pathlinesbcbwithTime.dat", "w")
+ i=0;
+ for entry in lengthxT:
+     i=i+1;
+     #print i
+     fFile.write(str(entry))
+     fFile.write(" ")
+     fFile.write(str(lengthT[i]))
+     fFile.write(" ")
+     fFile.write("\n")
+ fFile.close();
+except IOError:
+ datei.close()
+ print "caught error couldnt process datafile"
+ print i
diff --git a/source/Applications/porplate2/CMakeLists.txt b/source/Applications/porplate2/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0c5ab0a066a5d953ca26e58bef628e2d56333454
--- /dev/null
+++ b/source/Applications/porplate2/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(porplate2)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(porplate2 BINARY)
diff --git a/source/Applications/porplate2/porplate.cpp b/source/Applications/porplate2/porplate.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..639dfff35e6ef0aa994c9cece1dab3d32d3dcb45
--- /dev/null
+++ b/source/Applications/porplate2/porplate.cpp
@@ -0,0 +1,1060 @@
+
+
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////
+void inlay(GbVoxelMatrix3DPtr pmMesh, string& pathname, int myid, int i, Grid3DPtr grid)
+{
+   int bbOptionPM = 2; //quadratic bounce back with for thin walls
+   D3Q27BoundaryConditionAdapterPtr noSlipPM(new D3Q27NoSlipBCAdapter(bbOptionPM));
+   D3Q27InteractorPtr inlayInt = D3Q27InteractorPtr(new D3Q27Interactor(pmMesh, grid, noSlipPM, Interactor3D::SOLID));
+
+   GbCuboid3DPtr inlayBox(new GbCuboid3D(pmMesh->getX1Minimum(), pmMesh->getX2Minimum(), pmMesh->getX3Minimum(), pmMesh->getX1Maximum(), pmMesh->getX2Maximum(), pmMesh->getX3Maximum()));
+   if (myid == 0) GbSystem3D::writeGeoObject(inlayBox.get(), pathname + "/geo/inlay" + UbSystem::toString(i), WbWriterVtkXmlASCII::getInstance());
+   D3Q27InteractorPtr inlayBoxInt = D3Q27InteractorPtr(new D3Q27Interactor(inlayBox, grid, noSlipPM, Interactor3D::SOLID));
+   SetSolidOrTransBlockVisitor v1(inlayBoxInt, SetSolidOrTransBlockVisitor::SOLID);
+   grid->accept(v1);
+   SetSolidOrTransBlockVisitor v2(inlayBoxInt, SetSolidOrTransBlockVisitor::TRANS);
+   grid->accept(v2);
+
+   vector<Block3DPtr> inlayBlocks;
+   vector<Block3DPtr>& sb = inlayBoxInt->getSolidBlockSet();
+   if (myid == 0) UBLOG(logINFO, "sb.size = " << sb.size());
+   inlayBlocks.insert(inlayBlocks.end(), sb.begin(), sb.end());
+   vector<Block3DPtr>& tb = inlayBoxInt->getTransBlockSet();
+   if (myid == 0) UBLOG(logINFO, "tb.size = " << tb.size());
+   inlayBlocks.insert(inlayBlocks.end(), tb.begin(), tb.end());
+
+   if (myid == 0) UBLOG(logINFO, "inlayBlocks.size = " << inlayBlocks.size());
+
+   BOOST_FOREACH(Block3DPtr block, inlayBlocks)
+   {
+      block->setActive(true);
+      inlayInt->setDifferencesToGbObject3D(block);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void deleteExistBlocks(Grid3DPtr ngrid, Grid3DPtr ogrid)
+{
+   int minInitLevel = ogrid->getCoarsestInitializedLevel();
+   int maxInitLevel = ogrid->getFinestInitializedLevel();
+
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   blockVector.resize(maxInitLevel + 1);
+
+   std::vector<int> ids;
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      ogrid->getBlocks(level, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         int x1 = block->getX1();
+         int x2 = block->getX2();
+         int x3 = block->getX3();
+         Block3DPtr nblock = ngrid->getBlock(x1, x2, x3, level);
+         if (nblock)
+         {
+            ngrid->deleteBlock(x1, x2, x3, level);
+         }
+         else
+         {
+            ids.push_back(block->getGlobalID());
+         }
+      }
+   }
+
+   ogrid->deleteBlocks(ids);
+}
+//////////////////////////////////////////////////////////////////////////
+void reindexBlocks(Grid3DPtr ngrid)
+{
+   int minInitLevel = ngrid->getCoarsestInitializedLevel();
+   int maxInitLevel = ngrid->getFinestInitializedLevel();
+
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   blockVector.resize(maxInitLevel + 1);
+
+   int maxID = Block3D::getMaxGlobalID();
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      ngrid->getBlocks(level, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         block->setGlobalID(++maxID);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void setInterpolationFlag(Grid3DPtr grid)
+{
+   int minInitLevel = grid->getCoarsestInitializedLevel();
+   int maxInitLevel = grid->getFinestInitializedLevel();
+
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   blockVector.resize(maxInitLevel + 1);
+
+   int maxID = Block3D::getMaxGlobalID();
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      grid->getBlocks(level, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         block->deleteInterpolationFlag();
+      }
+   }
+
+   std::vector<int> dirs;
+
+   for (int i = D3Q27System::E; i <= D3Q27System::TS; i++)
+   {
+      dirs.push_back(i);
+   }
+   SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+   grid->accept(interDirsVisitor);
+}
+//////////////////////////////////////////////////////////////////////////
+void addExistBlocks(Grid3DPtr ngrid, Grid3DPtr ogrid, Grid3DPtr hgrid)
+{
+   int minInitLevel = ngrid->getCoarsestInitializedLevel();
+   int maxInitLevel = ngrid->getFinestInitializedLevel();
+
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   blockVector.resize(maxInitLevel + 1);
+
+   std::vector<Block3DPtr> db;
+
+   //int gridRank = ogrid->getRank();
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      ngrid->getBlocks(level, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         int x1 = block->getX1();
+         int x2 = block->getX2();
+         int x3 = block->getX3();
+         Block3DPtr oblock = ogrid->getBlock(x1, x2, x3, level);
+         if (oblock)
+         {
+            hgrid->addBlock(oblock);
+         }
+
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void moveBlocks(Grid3DPtr ngrid, Grid3DPtr ogrid)
+{
+   int minInitLevel = ngrid->getCoarsestInitializedLevel();
+   int maxInitLevel = ngrid->getFinestInitializedLevel();
+
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   blockVector.resize(maxInitLevel + 1);
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      ngrid->getBlocks(level, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         ogrid->addBlock(block);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void removeUndefNodes(Grid3DPtr grid)
+{
+   int minInitLevel = grid->getCoarsestInitializedLevel();
+   int maxInitLevel = grid->getFinestInitializedLevel();
+
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   blockVector.resize(maxInitLevel + 1);
+
+   int gridRank = grid->getRank();
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         int gl = 0;
+
+         LBMKernel3DPtr kernel = block->getKernel();
+         BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+         int minX1 = gl;
+         int minX2 = gl;
+         int minX3 = gl;
+
+         int maxX1 = static_cast<int>(bcMatrix.getNX1()) - 1 - gl;
+         int maxX2 = static_cast<int>(bcMatrix.getNX2()) - 1 - gl;
+         int maxX3 = static_cast<int>(bcMatrix.getNX3()) - 1 - gl;
+
+         minX1 = gl;
+         minX2 = gl;
+         minX3 = gl;
+
+         maxX1 = static_cast<int>(bcMatrix.getNX1()) - 1 - gl;
+         maxX2 = static_cast<int>(bcMatrix.getNX2()) - 1 - gl;
+         maxX3 = static_cast<int>(bcMatrix.getNX3()) - 1 - gl;
+
+         for (int ix3 = minX3; ix3 <= maxX3; ix3++)
+            for (int ix2 = minX2; ix2 <= maxX2; ix2++)
+               for (int ix1 = minX1; ix1 <= maxX3; ix1++)
+               {
+                  if (bcMatrix.isUndefined(ix1, ix2, ix3)) bcMatrix.setFluid(ix1, ix2, ix3);
+               }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void removeBCInformation(Grid3DPtr grid)
+{
+   int minInitLevel = grid->getCoarsestInitializedLevel();
+   int maxInitLevel = grid->getFinestInitializedLevel();
+
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   blockVector.resize(maxInitLevel + 1);
+
+   int gridRank = grid->getRank();
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         int gl = 0;
+
+         LBMKernel3DPtr kernel = block->getKernel();
+         BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+         int minX1 = gl;
+         int minX2 = gl;
+         int minX3 = gl;
+
+         int maxX1 = static_cast<int>(bcMatrix.getNX1()) - 1 - gl;
+         int maxX2 = static_cast<int>(bcMatrix.getNX2()) - 1 - gl;
+         int maxX3 = static_cast<int>(bcMatrix.getNX3()) - 1 - gl;
+
+         for (int ix3 = minX3; ix3 <= maxX3; ix3++)
+            for (int ix2 = minX2; ix2 <= maxX2; ix2++)
+               for (int ix1 = minX1; ix1 <= maxX3; ix1++)
+               {
+                  bcMatrix.setFluid(ix1, ix2, ix3);
+                  //bcMatrix.setBC(ix1, ix2, ix3, D3Q27BoundaryConditionPtr());
+               }
+
+   //      if (!block->getKernel())
+   //      {
+   //         if (block->getRank() == grid->getRank())
+   //         {
+   //            BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+   //            block->getKernel()->setBCProcessor(bcProc);
+   //         }
+   //      }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void setKernel(Grid3DPtr grid, LBMKernel3DPtr kernel, double nu)
+{
+   int minInitLevel = grid->getCoarsestInitializedLevel();
+   int maxInitLevel = grid->getFinestInitializedLevel();
+
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   blockVector.resize(maxInitLevel + 1);
+
+   int gridRank = grid->getRank();
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         if (!block->getKernel())
+         {
+            if (block->getRank() == grid->getRank())
+            {
+               LBMReal collFactor = LBMSystem::calcCollisionFactor(nu, block->getLevel());
+               kernel->setCollisionFactor(collFactor);
+               kernel->setIndex(block->getX1(), block->getX2(), block->getX3());
+               kernel->setDeltaT(LBMSystem::getDeltaT(block->getLevel()));
+               kernel->setBlock(block);
+               LBMKernel3DPtr newKernel = kernel->clone();
+               block->setKernel(newKernel);
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void run(const char *cstr, bool firststart)
+{
+   try
+   {
+      string pathname;
+      string pathGeo;
+      string pathLog;
+      int numOfThreads = 1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr);
+
+      if (machine == "my")
+      {
+         pathname = "d:/temp/porplate2";
+         pathGeo = "d:/Data/plate";
+         pathLog = pathname;
+         numOfThreads = 1;
+         logfile = false;
+         availMem = 15.0e9;
+      }
+      else if (machine == "Ludwig")
+      {
+         pathname = "/work/koskuche/SFB880/porplate2";
+         pathGeo = "/home/koskuche/data/plate";
+         pathLog = pathname;
+         numOfThreads = 8;
+         availMem = 12.0e9;///8*numOfThreads;
+         logfile = true;
+      }
+      else if (machine == "HLRS")
+      {
+         pathname = "/univ_1/ws1/ws/xrmkuchr-plate3-0";
+         pathGeo = "/zhome/academic/HLRS/xrm/xrmkuchr/data/plate";
+         pathLog = "/zhome/academic/HLRS/xrm/xrmkuchr/work/plate";
+         numOfThreads = 16;
+         availMem = 2.0e9;
+         logfile = true;
+      }
+      else if (machine == "HLRN")
+      {
+         pathname = "/gfs1/work/niivfcpu/scratch/plateEx";
+         pathGeo = "/gfs1/work/niivfcpu/data/plate";
+         pathLog = pathname;
+         numOfThreads = 24;
+         availMem = 64.0e9 / 24.0*numOfThreads;
+         logfile = true;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+#if defined(__unix__)
+      if (myid==0) 
+      {
+         const char* str = pathLog.c_str();
+         int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      }
+#endif 
+
+      if (myid == 0 && logfile)
+      {
+         //UbLog::reportingLevel() = logDEBUG5;
+         logFilename << pathLog + "/logfile" + UbSystem::toString(UbSystem::getTimeStamp()) + "_" + UbSystem::toString(myid) + ".txt";
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      if (myid == 0) UBLOG(logINFO, "Testcase plate");
+
+      string PlatteFilename = pathGeo + "/Platte_bearbeitet2_10cmA.stl";
+
+      string ZckbndFilename = pathGeo + "/2zackenbaender0.stl";
+
+      int ppblockc = 0;
+
+      ///////////////Knotenabmessungen:
+      int nx[3], blocknx[3];
+      nx[0] = 90;//240;//120;//60;//86;//43;//65;//50;  //länge
+      nx[1] = 2;//2;//6;///1;//5;// //breite
+      nx[2] = 30;//64;//32;//18;//5;//15;//15; //höhe gebiet
+      blocknx[0] = 16;//10;//6;
+      blocknx[1] = 16;//10;//6;
+      blocknx[2] = 16;//10;//6;
+
+      int baseLevel = 0;
+      int refineLevel = 5;
+
+      double H = 600.0; // Kanalhöhe [mm]
+      double cdx = H / (double)(nx[2] * blocknx[2]);
+      double fdx = cdx / double(1 << refineLevel);
+
+      //double h = 200.0; // gewünschte Plattenhöhe in Gitterpunkten
+      //double fdx = plate->getLengthX3()/h;
+      //double cdx = fdx*double(1<<refineLevel);
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      //////////////////////////////////////////////////////////////////////////
+      // physik
+      //////////////////////////////////////////////////////////////////////////
+
+      //////////////////////////////////////////////////////////////////////////
+      // Experiment Parametr
+      // Re = 1000000
+      // V = 16.05  # m / s
+      // p = 994.7  #hPa(manuell abgelesen von MUB)
+      // T = 21.78  #°C
+      // Luftfeuchte = 50.5   # %
+      //////////////////////////////////////////////////////////////////////////
+      // Simulation Parametr
+      //////////////////////////////////////////////////////////////////////////
+      double Re = 1e6; // 1133333.3333333335;
+      double rhoLB = 0.0;
+      double uLB = 0.1;
+      double lReal = 1000; //Plattenlänge in mm
+      double nuLB = (uLB*(lReal / cdx)) / Re;
+
+      int sizeSP = 4;
+      mu::Parser spongeLayer;
+      spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dx ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+      spongeLayer.DefineConst("sizeX", nx[0] * blocknx[0]);
+      spongeLayer.DefineConst("sizeSP", sizeSP*blocknx[0]);
+
+      Grid3DPtr ogrid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(1000, 1000, 10000000));
+      rSch->addSchedule(100, 47000, 47100);
+      RestartPostprocessor rp(ogrid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+      bool restart;
+
+      if (firststart)
+      {
+
+         if (myid == 0) UBLOG(logINFO, "Neustart..");
+         restart = false;
+       
+         Grid3DPtr ngrid(new Grid3D(comm));
+         //////////////////////////////////////////////////////////////////////////
+         //Platte
+         GbTriFaceMesh3DPtr plate(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(PlatteFilename, "Netz"));
+         if (myid == 0) GbSystem3D::writeGeoObject(plate.get(), pathname + "/geo/platte", WbWriterVtkXmlBinary::getInstance());
+         //////////////////////////////////////////////////////////////////////////
+         // Zackenband
+         //////////////////////////////////////////////////////////////////////////
+         GbTriFaceMesh3DPtr meshBand1(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand"));
+         meshBand1->translate(5.0, -2.86, -14.717);
+         meshBand1->rotate(0.0, -0.5, 0.0);
+         if (myid == 0) GbSystem3D::writeGeoObject(meshBand1.get(), pathname + "/geo/Band1", WbWriterVtkXmlASCII::getInstance());
+         // Zackenband2
+         GbTriFaceMesh3DPtr meshBand2(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand2"));
+         meshBand2->translate(5.0, -7.86, -14.717);
+         meshBand2->rotate(0.0, -0.5, 0.0);
+         if (myid == 0) GbSystem3D::writeGeoObject(meshBand2.get(), pathname + "/geo/Band2", WbWriterVtkXmlASCII::getInstance());
+         // Zackenband3
+         GbTriFaceMesh3DPtr meshBand3(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand3"));
+         meshBand3->translate(5.0, -2.86, -14.417); //+0.3
+         meshBand3->rotate(0.0, -0.5, 0.0);
+         if (myid == 0) GbSystem3D::writeGeoObject(meshBand3.get(), pathname + "/geo/Band3", WbWriterVtkXmlASCII::getInstance());
+         // Zackenband4
+         GbTriFaceMesh3DPtr meshBand4(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(ZckbndFilename, "NetzBand4"));
+         meshBand4->translate(5.0, -7.86, -14.417);
+         meshBand4->rotate(0.0, -0.5, 0.0);
+         if (myid == 0) GbSystem3D::writeGeoObject(meshBand4.get(), pathname + "/geo/Band4", WbWriterVtkXmlASCII::getInstance());
+         //////////////////////////////////////////////////////////////////////////
+
+         double blockLengthx1 = blocknx[0] * cdx; //geowerte
+         double blockLengthx2 = blockLengthx1;
+         double blockLengthx3 = blockLengthx1;
+
+         double geoLength[] = { nx[0] * blockLengthx1, nx[1] * blockLengthx2, nx[2] * blockLengthx3 };
+
+         double originX1 = plate->getX1Minimum() - plate->getLengthX1() / 4.0;
+         double originX2 = plate->getX2Minimum();
+         double originX3 = plate->getX3Minimum() - 299.5;
+
+
+         bool periodicx1 = false;
+         bool periodicx2 = true;
+         bool periodicx3 = false;
+
+         //bounding box
+         double g_minX1 = originX1;
+         double g_minX2 = originX2;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0];
+         double g_maxX2 = originX2 + geoLength[1];
+         double g_maxX3 = originX3 + geoLength[2];;
+
+
+         //set grid
+         ngrid->setDeltaX(cdx);
+         ngrid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         ngrid->setPeriodicX1(periodicx1);
+         ngrid->setPeriodicX2(periodicx2);
+         ngrid->setPeriodicX3(periodicx3);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         gridCube->setCenterCoordinates(gridCube->getX1Centroid(), meshBand1->getX2Centroid(), gridCube->getX3Centroid());
+         if (myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname + "/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         originX2 = gridCube->getX2Minimum();
+         g_minX2 = originX2;
+         g_maxX2 = originX2 + geoLength[1];
+
+         //Grid3DPtr hgrid(ngrid);
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         ngrid->accept(genBlocks);
+
+         //hgrid->setCoordinateTransformator(ngrid->getCoordinateTransformator());
+
+
+         //////////////////////////////////////////////////////////////////////////
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            UBLOG(logINFO, "* Re            =" << Re);
+            UBLOG(logINFO, "* nuLB          =" << nuLB);
+            UBLOG(logINFO, "* uLB           =" << uLB);
+            UBLOG(logINFO, "* cdx           =" << cdx);
+            UBLOG(logINFO, "* fdx           =" << fdx);
+            double Hzb = 0.6 / fdx;
+            UBLOG(logINFO, "* Height of Zackenband =" << Hzb);
+            UBLOG(logINFO, "* Re on Zackenband =" << (uLB*Hzb) / (nuLB*double(1 << refineLevel)));
+            UBLOG(logINFO, "* nx1/2/3       =" << nx[0] << "/" << nx[1] << "/" << nx[2]);
+            UBLOG(logINFO, "* blocknx1/2/3  =" << blocknx[0] << "/" << blocknx[1] << "/" << blocknx[2]);
+            UBLOG(logINFO, "* x1Periodic    =" << periodicx1);
+            UBLOG(logINFO, "* x2Periodic    =" << periodicx2);
+            UBLOG(logINFO, "* x3Periodic    =" << periodicx3);
+            UBLOG(logINFO, "* number of levels  =" << refineLevel + 1);
+            UBLOG(logINFO, "* path          =" << pathname);
+
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* number of threads    =" << numOfThreads);
+            UBLOG(logINFO, "* number of processes  =" << comm->getNumberOfProcesses());
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "*****************************************");
+         }
+         //////////////////////////////////////////////////////////////////////////
+
+
+         //////////////////////////////////////////////////////////////////////////
+         //refinement
+         GbCuboid3DPtr refinePlatteBox(new GbCuboid3D(plate->getX1Minimum() - 1.0, plate->getX2Minimum(), plate->getX3Minimum() + (plate->getX3Maximum() - plate->getX3Minimum()) / 2.0,
+            plate->getX1Maximum() + 40.0, plate->getX2Maximum(), plate->getX3Maximum() + 2.0));
+         if (myid == 0) GbSystem3D::writeGeoObject(refinePlatteBox.get(), pathname + "/geo/refinePlatteBox", WbWriterVtkXmlASCII::getInstance());
+
+         //inlay patch
+         GbCuboid3DPtr refineInlayBox(new GbCuboid3D(plate->getX1Maximum() - 104.0, plate->getX2Minimum(), plate->getX3Minimum() + (plate->getX3Maximum() - plate->getX3Minimum()) / 2.0,
+            plate->getX1Maximum() + 1.0, plate->getX2Maximum(), plate->getX3Maximum() + 1.0));
+         if (myid == 0) GbSystem3D::writeGeoObject(refineInlayBox.get(), pathname + "/geo/refineInlayBox", WbWriterVtkXmlASCII::getInstance());
+
+         if (refineLevel > 0)
+         {
+            if (myid == 0) UBLOG(logINFO, "Refinement - start");
+            RefineCrossAndInsideGbObjectHelper refineHelper(ngrid, refineLevel);
+            refineHelper.addGbObject(refinePlatteBox, refineLevel - 1);
+            refineHelper.addGbObject(refineInlayBox, refineLevel);
+
+            refineHelper.refine();
+            if (myid == 0) UBLOG(logINFO, "Refinement - end");
+         }
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Write blocks - start");
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(ngrid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            ppblocks->update(ppblockc++);
+            UBLOG(logINFO, "Write blocks - end");
+         }
+
+
+
+         {
+
+            ////walls
+            GbCuboid3DPtr addWallZmin(new GbCuboid3D(g_minX1 - blockLengthx1, g_minX2 - blockLengthx1, g_minX3 - blockLengthx1, g_maxX1 + blockLengthx1, g_maxX2 + blockLengthx1, g_minX3));
+            if (myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname + "/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+            GbCuboid3DPtr addWallZmax(new GbCuboid3D(g_minX1 - blockLengthx1, g_minX2 - blockLengthx1, g_maxX3, g_maxX1 + blockLengthx1, g_maxX2 + blockLengthx1, g_maxX3 + blockLengthx1));
+            if (myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname + "/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+            //walls
+            int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+            D3Q27BoundaryConditionAdapterPtr slip(new D3Q27SlipBCAdapter(bbOption));
+            D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, ngrid, slip, Interactor3D::SOLID));
+            D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, ngrid, slip, Interactor3D::SOLID));
+
+            /////////////////////////////////////////////////
+            ///interactoren
+            int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+            D3Q27BoundaryConditionAdapterPtr noSlip(new D3Q27NoSlipBCAdapter(bbOption1));
+            //D3Q27TriFaceMeshInteractorPtr triPlateInteractor(new D3Q27TriFaceMeshInteractor(plate, ngrid, noSlip, Interactor3D::SOLID, Interactor3D::POINTS));
+            D3Q27TriFaceMeshInteractorPtr triPlateInteractor(new D3Q27TriFaceMeshInteractor(plate, ngrid, noSlip, Interactor3D::SOLID, Interactor3D::SIMPLE));
+            D3Q27TriFaceMeshInteractorPtr triBand1Interactor(new D3Q27TriFaceMeshInteractor(meshBand1, ngrid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand2Interactor(new D3Q27TriFaceMeshInteractor(meshBand2, ngrid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand3Interactor(new D3Q27TriFaceMeshInteractor(meshBand3, ngrid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand4Interactor(new D3Q27TriFaceMeshInteractor(meshBand4, ngrid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+
+            //inflow
+            GbCuboid3DPtr velBCCuboid(new GbCuboid3D(originX1 - blockLengthx1, originX2 - blockLengthx1, originX3 - blockLengthx1,
+               originX1, originX2 + geoLength[1] + blockLengthx1, originX3 + geoLength[2] + blockLengthx1));
+            if (myid == 0) GbSystem3D::writeGeoObject(velBCCuboid.get(), pathname + "/geo/velBCCuboid", WbWriterVtkXmlASCII::getInstance());
+            D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(velBCCuboid, ngrid, Interactor3D::SOLID));
+
+            //inflow
+            double raiseVelSteps = 0;
+            vector<D3Q27BCFunction> velcX1BCs, dummy;
+
+            mu::Parser inflowProfile;
+            inflowProfile.SetExpr("uLB");
+            inflowProfile.DefineConst("uLB", uLB);
+            velcX1BCs.push_back(D3Q27BCFunction(inflowProfile, raiseVelSteps, D3Q27BCFunction::INFCONST));
+
+            D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter(velcX1BCs, dummy, dummy));
+            velBCInteractor->addBCAdapter(velBCAdapter);
+
+            //outflow
+            GbCuboid3DPtr densCuboid(new GbCuboid3D(originX1 + geoLength[0], originX2 - blockLengthx1, originX3 - blockLengthx1,
+               originX1 + geoLength[0] + blockLengthx1, originX2 + geoLength[1] + blockLengthx1, originX3 + geoLength[2] + blockLengthx1));
+            if (myid == 0) GbSystem3D::writeGeoObject(densCuboid.get(), pathname + "/geo/densCuboid", WbWriterVtkXmlASCII::getInstance());
+            D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+            D3Q27InteractorPtr densInteractor(new D3Q27Interactor(densCuboid, ngrid, denBCAdapter, Interactor3D::SOLID));
+
+ 
+            ///////////////////////////////////////////////////
+            if (myid == 0) UBLOG(logINFO, "deleteExistBlocks - start");
+            deleteExistBlocks(ngrid, ogrid);
+            if (myid == 0) UBLOG(logINFO, "deleteExistBlocks - end");
+
+            if (myid == 0)
+            {
+               UBLOG(logINFO, "Write blocks - start");
+               BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(ngrid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+               ppblocks->update(ppblockc++);
+               UBLOG(logINFO, "Write blocks - end");
+            }
+
+            ////////////////////////////////////////////
+            //METIS
+            Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+
+            ////////////////////////////////////////////
+            /////delete solid blocks
+            if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - start");
+            InteractorsHelper intHelper(ngrid, metisVisitor);
+            intHelper.addInteractor(triPlateInteractor);
+            intHelper.addInteractor(triBand1Interactor);
+            intHelper.addInteractor(triBand2Interactor);
+            intHelper.addInteractor(triBand3Interactor);
+            intHelper.addInteractor(triBand4Interactor);
+            intHelper.addInteractor(addWallZminInt);
+            intHelper.addInteractor(addWallZmaxInt);
+            intHelper.addInteractor(densInteractor);
+            intHelper.addInteractor(velBCInteractor);
+            intHelper.selectBlocks();
+            if (myid == 0) UBLOG(logINFO, "deleteSolidBlocks - end");
+            //////////////////////////////////////
+            if (myid == 0)
+            {
+               UBLOG(logINFO, "Write blocks - start");
+               BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(ngrid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+               ppblocks->update(ppblockc++);
+               UBLOG(logINFO, "Write blocks - end");
+            }
+            ////////////////////////////////////////////////////////
+
+            //addExistBlocks(ngrid, ogrid, hgrid);
+
+            ////////////////////////////////////////////////////////
+            unsigned long nob = ogrid->getNumberOfBlocks();
+            unsigned long nod = nob * blocknx[0] * blocknx[1] * blocknx[2];
+            unsigned long nod_real = nob * (blocknx[0] + 3)*(blocknx[1] + 3)*(blocknx[2] + 3);
+            unsigned long nodb = (blocknx[0]) * (blocknx[1]) * (blocknx[2]);
+
+            double needMemAll = double(nod_real*(27 * sizeof(double) + sizeof(int)));
+            double needMem = needMemAll / double(comm->getNumberOfProcesses());
+
+            double nup = 0;
+
+            if (myid == 0)
+            {
+               UBLOG(logINFO, "Number of blocks = " << nob);
+               UBLOG(logINFO, "Number of nodes  = " << nod);
+               int minInitLevel = ngrid->getCoarsestInitializedLevel();
+               int maxInitLevel = ngrid->getFinestInitializedLevel();
+               for (int level = minInitLevel; level <= maxInitLevel; level++)
+               {
+                  int nobl = ngrid->getNumberOfBlocks(level);
+                  UBLOG(logINFO, "Number of blocks for level " << level << " = " << nobl);
+                  UBLOG(logINFO, "Number of nodes for level " << level << " = " << nobl*nodb);
+                  nup += nobl*nodb*double(1 << level);
+               }
+               UBLOG(logINFO, "Hypothetically time for calculation step for 120 nodes  = " << nup / 6.0e5 / (120 * 8) << " s");
+               UBLOG(logINFO, "Necessary memory  = " << needMemAll << " bytes");
+               UBLOG(logINFO, "Necessary memory per process = " << needMem << " bytes");
+               UBLOG(logINFO, "Available memory per process = " << availMem << " bytes");
+               UBLOG(logINFO, "Available memory per node/8.0 = " << (availMem / 8.0) << " bytes");
+            }
+
+
+            //deleteNotExistBlocks(ngrid, ogrid);
+
+            //deleteExistBlocks(ngrid, ogrid);
+
+            //set kernel for new blocks
+            //////////////////////////////
+            LBMKernel3DPtr kernel;
+            //with sponge layer
+            kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLBWithSpongeLayer(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+            kernel->setWithSpongeLayer(true);
+            kernel->setSpongeLayer(spongeLayer);
+
+            BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+            kernel->setBCProcessor(bcProc);
+
+            //setKernel(ogrid, kernel, nuLB);
+
+            SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+            ngrid->accept(kernelVisitor);
+            //////////////////////////////////
+
+            //initialization of decompositions
+            D3Q27ETInitDistributionsBlockVisitor initVisitor(nuLB, rhoLB);
+            //double aVuLB = 0.1;
+            initVisitor.setVx1(uLB);
+            ngrid->accept(initVisitor);
+
+            int maxblock = Block3D::getMaxGlobalID();
+            if (myid == 0) UBLOG(logINFO, "maxblock = " << maxblock);
+
+            reindexBlocks(ngrid);
+
+            moveBlocks(ngrid, ogrid);
+
+            setInterpolationFlag(ogrid);
+
+            removeBCInformation(ogrid);
+
+            //set connectors
+            D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+            D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+            ogrid->accept(setConnsVisitor);
+
+            ////////////////////////////////////
+            ////undef nodes
+            if (refineLevel > 0)
+            {
+               D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+               ogrid->accept(undefNodesVisitor);
+            }
+
+
+            D3Q27InteractorPtr addWallZminInt1(new D3Q27Interactor(addWallZmin, ogrid, slip, Interactor3D::SOLID));
+            D3Q27InteractorPtr addWallZmaxInt1(new D3Q27Interactor(addWallZmax, ogrid, slip, Interactor3D::SOLID));
+            D3Q27TriFaceMeshInteractorPtr triPlateInteractor1(new D3Q27TriFaceMeshInteractor(plate, ogrid, noSlip, Interactor3D::SOLID, Interactor3D::SIMPLE));
+            D3Q27TriFaceMeshInteractorPtr triBand1Interactor1(new D3Q27TriFaceMeshInteractor(meshBand1, ogrid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand2Interactor1(new D3Q27TriFaceMeshInteractor(meshBand2, ogrid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand3Interactor1(new D3Q27TriFaceMeshInteractor(meshBand3, ogrid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27TriFaceMeshInteractorPtr triBand4Interactor1(new D3Q27TriFaceMeshInteractor(meshBand4, ogrid, noSlip, Interactor3D::SOLID, Interactor3D::EDGES));
+            D3Q27InteractorPtr velBCInteractor1(new D3Q27Interactor(velBCCuboid, ogrid, Interactor3D::SOLID));
+            velBCInteractor1->addBCAdapter(velBCAdapter);
+            D3Q27InteractorPtr densInteractor1(new D3Q27Interactor(densCuboid, ogrid, denBCAdapter, Interactor3D::SOLID));
+
+            {SetSolidOrTransBlockVisitor v2(addWallZminInt1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+            {SetSolidOrTransBlockVisitor v2(addWallZmaxInt1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+            {SetSolidOrTransBlockVisitor v2(triPlateInteractor1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+            {SetSolidOrTransBlockVisitor v2(triBand1Interactor1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+            {SetSolidOrTransBlockVisitor v2(triBand2Interactor1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+            {SetSolidOrTransBlockVisitor v2(triBand3Interactor1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+            {SetSolidOrTransBlockVisitor v2(triBand4Interactor1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+            {SetSolidOrTransBlockVisitor v2(velBCInteractor1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+            {SetSolidOrTransBlockVisitor v2(densInteractor1, SetSolidOrTransBlockVisitor::TRANS);
+            ogrid->accept(v2); }
+
+            addWallZminInt1->initInteractor();
+            addWallZmaxInt1->initInteractor();
+            triPlateInteractor1->initInteractor();
+            triBand1Interactor1->initInteractor();
+            triBand2Interactor1->initInteractor();
+            triBand3Interactor1->initInteractor();
+            triBand4Interactor1->initInteractor();
+            velBCInteractor1->initInteractor();
+            densInteractor1->initInteractor();
+
+
+            //intHelper.setBC();
+         }
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Write blocks - start");
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(ogrid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            ppblocks->update(ppblockc++);
+            UBLOG(logINFO, "Write blocks - end");
+         }
+
+         {
+            UbSchedulerPtr geoSch(new UbScheduler(1));
+            D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+               new D3Q27MacroscopicQuantitiesPostprocessor(ogrid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(),
+               unitConverter, true));
+            ppgeo->update(0);
+            ppgeo.reset();
+            geoSch.reset();
+         }
+
+         //////////////////////////////////////////////////////////////////////////
+         //porous inlay
+         {
+            string pmFilename = pathGeo + "/CT-2014-039.raw";
+            int pmNX1 = 1333;  //abmessung einzelbild in x-richtung
+            int pmNX2 = 463; //abmessung einzelbild in y richtung
+            int pmNX3 = 1333; //anzahl der bilder
+            float lthreshold = 27686.97;
+            float uthreshold = 65535.0;
+
+            GbVoxelMatrix3DPtr pmMesh(new GbVoxelMatrix3D(pmNX1, pmNX2, pmNX3, 0, lthreshold, uthreshold));
+            pmMesh->readMatrixFromRawFile<unsigned short>(pmFilename, GbVoxelMatrix3D::LittleEndian);
+
+            double scaleFactor = 0.001;
+            double delta = 3.75*scaleFactor;
+            pmMesh->setVoxelMatrixDelta(delta, delta, delta);
+            pmMesh->rotate90aroundX();
+            pmMesh->rotate90aroundX();
+            pmMesh->rotate90aroundX();
+
+            double inlayXmin = plate->getX1Maximum() - 5.0;//995.0;
+            double inlayYmin = gridCube->getX2Minimum();//180.0;
+            double inlayZmin = 8.84 + fdx;//8.73;
+
+            //pmMesh->setVoxelMatrixMininum(inlayXmin, inlayYmin, inlayZmin);
+            //if(myid == 0) pmMesh->writeToLegacyVTKBinary(pathname+"/geo/pmMesh");
+
+            int i = 0;
+            for (int y = 0; y < 40; y += 10)
+               for (int x = 0; x < 100; x += 10)
+               {
+                  if (myid == 0) UBLOG(logINFO, "inlay # " << i);
+                  pmMesh->setVoxelMatrixMininum(inlayXmin - (double)x, inlayYmin + (double)y, inlayZmin);
+                  inlay(pmMesh, pathname, myid, i, ogrid);
+                  i++;
+
+                  if (myid == 0) UBLOG(logINFO, "inlay # " << i);
+                  pmMesh->setVoxelMatrixMininum(inlayXmin - (double)(x + 5), inlayYmin + (double)y, inlayZmin);
+                  pmMesh->mirrorX();
+                  inlay(pmMesh, pathname, myid, i, ogrid);
+                  i++;
+
+                  if (myid == 0) UBLOG(logINFO, "inlay # " << i);
+                  pmMesh->setVoxelMatrixMininum(inlayXmin - (double)(x + 5), inlayYmin + (double)(y + 5), inlayZmin);
+                  pmMesh->mirrorY();
+                  inlay(pmMesh, pathname, myid, i, ogrid);
+                  i++;
+
+                  if (myid == 0) UBLOG(logINFO, "inlay # " << i);
+                  pmMesh->setVoxelMatrixMininum(inlayXmin - (double)x, inlayYmin + (double)(y + 5), inlayZmin);
+                  pmMesh->mirrorX();
+                  inlay(pmMesh, pathname, myid, i, ogrid);
+                  pmMesh->mirrorY();
+                  i++;
+               }
+
+            if (myid == 0)
+            {
+               UBLOG(logINFO, "mit VoxelMatrix");
+               UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+               UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+               UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+            }
+         }
+         //////////////////////////////////////////////////////////////////////////
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Write blocks - start");
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(ogrid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            ppblocks->update(ppblockc++);
+            UBLOG(logINFO, "Write blocks - end");
+         }
+
+         ////initialization of decompositions
+         //D3Q27ETInitDistributionsBlockVisitor initVisitor(nuLB, rhoLB);
+         ////initVisitor.setVx1(uLB);
+         //hgrid->accept(initVisitor);
+
+         
+         //Postprozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(ogrid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(),
+            unitConverter, true));
+         ppgeo->update(1);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if (myid == 0)
+         {
+            UBLOG(logINFO, "Write blocks - start");
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(ogrid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            ppblocks->update(ppblockc++);
+            UBLOG(logINFO, "Write blocks - end");
+         }
+
+
+         //domain decomposition for threads
+         if (numOfThreads > 1)
+         {
+            PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+            ogrid->accept(pqPartVisitor);
+         }
+
+         SetSpongeLayerBlockVisitor ssp(spongeLayer);
+         ogrid->accept(ssp);
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+
+         if (myid == 0) UBLOG(logINFO, "Preprozess - end");
+      }
+      else
+      {
+         restart = true;
+
+         ////////////////////////////////////////////////////////////////////////////
+         //change viscosity
+         //Re = 1e6;
+         //nuLB = (uLB*(lReal / cdx)) / Re;
+         //if (myid == 0) UBLOG(logINFO, "nuLB =" << nuLB);
+
+         //int gridRank = grid->getRank();
+         //int minInitLevel = grid->getCoarsestInitializedLevel();
+         //int maxInitLevel = grid->getFinestInitializedLevel();
+
+         //std::vector<std::vector<Block3DPtr> > blockVector;
+         //blockVector.resize(maxInitLevel + 1);
+
+         //for (int level = minInitLevel; level <= maxInitLevel; level++)
+         //{
+         //   grid->getBlocks(level, gridRank, true, blockVector[level]);
+
+         //   BOOST_FOREACH(Block3DPtr block, blockVector[level])
+         //   {
+         //      LBMReal collFactor = LBMSystem::calcCollisionFactor(nuLB, block->getLevel());
+         //      block->getKernel()->setCollisionFactor(collFactor);
+         //   }
+         //}
+         ////////////////////////////////////////////////////////////////////////////
+
+         //domain decomposition for threads
+         if (numOfThreads > 1)
+         {
+            PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+            ogrid->accept(pqPartVisitor);
+         }
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         ogrid->accept(setConnsVisitor);
+         SetSpongeLayerBlockVisitor ssp(spongeLayer);
+         ogrid->accept(ssp);
+         if (myid == 0) UBLOG(logINFO, "Restart - end");
+      }
+      UbSchedulerPtr visSch(new UbScheduler());
+      //visSch->addSchedule(1,0,10);
+      visSch->addSchedule(100, 100, 1000);
+      //visSch->addSchedule(1000,1000,5000);
+      //visSch->addSchedule(5000,5000,100000);
+      //visSch->addSchedule(100000,100000,10000000);
+
+      visSch->addSchedule(1000, 1000, 10000000);
+      visSch->addSchedule(1, 47100, 47100);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(ogrid, visSch, pathname, WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      double startStep = 47000;
+      double startStep2= 47500;
+
+      if(ogrid->getTimeStep() >= startStep2) startStep = startStep2;
+
+      UbSchedulerPtr resSchRMS(new UbScheduler());
+      resSchRMS->addSchedule(1000000, startStep, 10000000);
+      resSchRMS->addSchedule(1000000, startStep2, 10000000);
+      UbSchedulerPtr resSchMeans(new UbScheduler());
+      resSchMeans->addSchedule(1000000, startStep, 10000000);
+      resSchMeans->addSchedule(1000000, startStep2, 10000000);
+      UbSchedulerPtr stepAvSch(new UbScheduler());
+      int averageInterval = 100;
+
+      stepAvSch->addSchedule(averageInterval, 0, 10000000);
+      AverageValuesPostprocessor Avpp(ogrid, pathname, WbWriterVtkXmlBinary::getInstance(), visSch/*wann wird rausgeschrieben*/,
+         stepAvSch/*wann wird gemittelt*/, resSchMeans, resSchRMS/*wann wird resettet*/, restart);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      nupsSch->addSchedule(500, 500, 1e6);
+      NUPSCounterPostprocessor npr(ogrid, nupsSch, numOfThreads, comm);
+
+      UbSchedulerPtr emSch(new UbScheduler(10));
+      EmergencyExitPostprocessor empr(ogrid, emSch, pathname, RestartPostprocessorPtr(&rp), comm);
+
+      if (myid == 0)
+      {
+         UBLOG(logINFO, "PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO, "PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      double endTime = 100000001;
+      CalculationManagerPtr calculation(new CalculationManager(ogrid, numOfThreads, endTime, visSch));
+      if (myid == 0) UBLOG(logINFO, "Simulation-start");
+      calculation->calculate();
+      if (myid == 0) UBLOG(logINFO, "Simulation-end");
+   }
+   catch (std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch (std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch (...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   if (argc == 1)
+   {
+      cout << "Command line argument isn't specified!" << endl;
+      cout << "plate2 <machine name>" << endl;
+      return 1;
+   }
+   run(argv[1], true);
+
+   return 0;
+}
+
diff --git a/source/Applications/reefer/CMakeLists.txt b/source/Applications/reefer/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..116a067c86dfc847d74034b01ee30ccfff55225f
--- /dev/null
+++ b/source/Applications/reefer/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(reefer)
+
+INCLUDE(${SOURCE_ROOT}/core/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES core)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(reefer BINARY)
diff --git a/source/Applications/reefer/reefer.cpp b/source/Applications/reefer/reefer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..74bfc3d2d600be085faffc73cd68eca8d09fc698
--- /dev/null
+++ b/source/Applications/reefer/reefer.cpp
@@ -0,0 +1,489 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include <numerics/geometry3d/GbSphere3D.h>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "SyncBcBlockVisitor.h"
+#include "numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h"
+#include "numerics/geometry3d/GbTriFaceMesh3D.h"
+#include "D3Q27TriFaceMeshInteractor.h"
+#include "MathUtil.hpp"
+#include "SolidBlocksHelper.h"
+#include "LBMKernelETD3Q27CascadedTI.h"
+#include "TurbulenceIntensityPostprocessor.h"
+#include "RestartPostprocessor.h"
+
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   try
+   {
+      string pathname = "c:/temp/reefer/out";
+      string pathGeo = "c:/Data/reefer";
+
+      //string pathname = "/work/koskuche/scratch/reefer2/out";
+      //string pathGeo = "/home/koskuche/data/reefer/new";
+
+      //string pathname = "/home/kucher/temp/reefer/out";
+      //string pathGeo = "/home/kucher/data/reefer/new";
+
+      int numOfThreads = 2;
+      
+      CommunicatorPtr comm(new MPICommunicator());
+      int myid = comm->getProcessID();
+
+      //if(myid ==0)
+      //{
+      //   stringstream logFilename;
+      //   logFilename <<  "/work/koskuche/scratch/reefer2/logfile.log";
+      //   UbLog::output_policy::setStream(logFilename.str());
+      //}
+
+      //const double dx = 13.6;
+      const double dx = 2.0;
+      double refLentgthWorld = dx/1000.0; //from mm to m
+      double refLentgthLB = 1.0;
+      LBMUnitConverterPtr uconv = LBMUnitConverterPtr(new LBMUnitConverter(refLentgthWorld, LBMUnitConverter::AIR_20C, refLentgthLB));
+      LBMReal uSI = 10;//m/s
+      LBMReal uLB = uSI * uconv->getFactorVelocityWToLb();
+      LBMReal rhoLB = 1.0;
+      LBMReal nueSI = 1.5e-5;
+      LBMReal nueLB = nueSI * uconv->getFactorViscosityWToLb();//(uLB*l)/Re;
+
+      Grid3DPtr grid(new Grid3D());
+      UbSchedulerPtr rSch(new UbScheduler(1500,5000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY);
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         grid = rp.restart(UbSystem::stringTo<int>(opt));
+
+         LBMReal nueLB = 1.5e-3;
+         
+         SimulationParametersPtr param = SimulationParameters::getInstanz();
+         param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+      //////////////////////////////////////////////////////////////////////////
+      // Geometries
+      //////////////////////////////////////////////////////////////////////////
+      //container
+      GbTriFaceMesh3DPtr geoContainer (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathGeo +"/Containerascii.stl","geoContainer"));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoContainer.get(), pathname+"/geo/geoContainer", WbWriterVtkXmlASCII::getInstance());
+      //cargo
+      //GbTriFaceMesh3DPtr geoCargo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathGeo + "/Kisten_fuer_Palettenascii.stl","geoCargo"));
+      GbTriFaceMesh3DPtr geoCargo (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathGeo + "/Kistenascii.stl","geoCargo"));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoCargo.get(), pathname+"/geo/geoCargo", WbWriterVtkXmlASCII::getInstance());
+      //palette
+      //GbTriFaceMesh3DPtr geoPalette (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathGeo + "/Palettenascii.stl","geoPalette"));
+      //if(myid == 0) GbSystem3D::writeGeoObject(geoPalette.get(), pathname+"/geoPalette", WbWriterVtkXmlASCII::getInstance());
+      //reefer
+      GbTriFaceMesh3DPtr geoBlower (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathGeo + "/Solidblockascii.stl","geoReefer"));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoBlower.get(), pathname+"/geo/geoBlower", WbWriterVtkXmlASCII::getInstance());
+      //T floor
+      GbTriFaceMesh3DPtr geoTFloor (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(pathGeo + "/T-Floorascii.stl","geoTFloor"));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoTFloor.get(), pathname+"/geo/geoTFloor", WbWriterVtkXmlASCII::getInstance());
+
+      //bounding box
+      double g_minX1 = geoContainer->getX1Minimum();
+      double g_minX2 = geoContainer->getX2Minimum();
+      double g_minX3 = geoContainer->getX3Minimum();
+
+      double g_maxX1 = geoContainer->getX1Maximum();
+      double g_maxX2 = geoContainer->getX2Maximum();
+      double g_maxX3 = geoContainer->getX3Maximum();
+
+      const int nodesPerBlock = 10;
+      //const double dx = 1.7;
+      //const double dx = 13.6;
+      const double blockLength = double(nodesPerBlock)*dx;
+
+      const double gridOriginX1 = g_minX1;
+      const double gridOriginX2 = g_minX2;
+      const double gridOriginX3 = g_minX3;
+
+      //add wall X
+      GbCuboid3DPtr addWallXmax (new GbCuboid3D(g_maxX1, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+      //GbCuboid3DPtr addWallXmax (new GbCuboid3D(geoBlower->getX1Maximum()+geoBlower->getLengthX1(), g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallXmax.get(), pathname+"/geo/addWallXmax", WbWriterVtkXmlASCII::getInstance());
+      //add wall Y
+      GbCuboid3DPtr addWallYmax (new GbCuboid3D(g_minX1-blockLength, geoBlower->getX2Maximum(), g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+      //add wall Z
+      GbCuboid3DPtr addWallZmax (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+      //add wall X
+      GbCuboid3DPtr addWallXmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, geoBlower->getX1Minimum(), g_maxX2+blockLength, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallXmin.get(), pathname+"/geo/addWallXmin", WbWriterVtkXmlASCII::getInstance());
+      //add wall Y
+      GbCuboid3DPtr addWallYmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, geoBlower->getX2Minimum(), g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+      //add wall Z
+      GbCuboid3DPtr addWallZmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, geoTFloor->getX3Minimum()));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+      //add wall for blower
+      GbCuboid3DPtr addWallBlower (new GbCuboid3D(geoBlower->getX1Minimum()-3.0*blockLength, geoBlower->getX2Minimum()-3.0*blockLength, geoBlower->getX3Minimum()+4.0*dx, 
+                                                  geoBlower->getX1Maximum(), geoBlower->getX2Maximum()+3.0*blockLength, geoBlower->getX3Maximum()-4.0*dx));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallBlower.get(), pathname+"/geo/addWallBlower", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallBlowerXmin (new GbCuboid3D(geoBlower->getX1Minimum(), geoBlower->getX2Minimum(), geoBlower->getX3Minimum(), 
+                                       geoBlower->getX1Minimum()+2.0*dx, geoBlower->getX2Maximum(), geoBlower->getX3Maximum()));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallBlowerXmin.get(), pathname+"/geo/addWallBlowerXmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallBlowerXmax (new GbCuboid3D(geoBlower->getX1Maximum()-2.0*dx, geoBlower->getX2Minimum(), geoBlower->getX3Minimum(), 
+                                                      geoBlower->getX1Maximum(), geoBlower->getX2Maximum(), geoBlower->getX3Maximum()));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallBlowerXmax.get(), pathname+"/geo/addWallBlowerXmax", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallBlowerYmin (new GbCuboid3D(geoBlower->getX1Minimum(), geoBlower->getX2Minimum(), geoBlower->getX3Minimum(), 
+                                                      geoBlower->getX1Maximum(), geoBlower->getX2Minimum()+2.0*dx, geoBlower->getX3Maximum()));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallBlowerYmin.get(), pathname+"/geo/addWallBlowerYmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallBlowerYmax (new GbCuboid3D(geoBlower->getX1Minimum()-2.0*dx, geoBlower->getX2Maximum()-2.0*dx, geoBlower->getX3Minimum(), 
+                                                      geoBlower->getX1Maximum(), geoBlower->getX2Maximum(), geoBlower->getX3Maximum()));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallBlowerYmax.get(), pathname+"/geo/addWallBlowerYmax", WbWriterVtkXmlASCII::getInstance());
+
+      //inflow
+      GbCuboid3DPtr geoInflow (new GbCuboid3D(geoBlower->getX1Minimum()+dx, geoBlower->getX2Minimum()+dx, geoBlower->getX3Minimum()+2.0*dx, 
+                                              geoBlower->getX1Maximum()-dx, geoBlower->getX2Maximum()-dx, geoBlower->getX3Minimum()+4.0*dx));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      //outflow
+      GbCuboid3DPtr geoOutflow (new GbCuboid3D(geoBlower->getX1Minimum()+2.0*dx, geoBlower->getX2Minimum()+2.0*dx, geoBlower->getX3Maximum()-4.0*dx, 
+                                               geoBlower->getX1Maximum()-2.0*dx, geoBlower->getX2Maximum()-2.0*dx, geoBlower->getX3Maximum()-2.0*dx));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+      //simulation parameters
+      double lSI = g_maxX2 - g_minX2;
+      double lLB = lSI / dx;
+      //double refLentgthWorld = blockLength/1000.0; //from mm to m
+      //double refLentgthLB = double(nodesPerBlock);
+      //LBMUnitConverterPtr uconv = LBMUnitConverterPtr(new LBMUnitConverter(refLentgthWorld, LBMUnitConverter::AIR_20C, refLentgthLB));
+      //LBMReal uSI = 10;//m/s
+      //LBMReal uLB = uSI * uconv->getFactorVelocityWToLb();
+      //LBMReal rhoLB = 1.0;
+      //LBMReal nueSI = 1.5e-5;
+      //LBMReal nueLB = nueSI * uconv->getFactorViscosityWToLb();//(uLB*l)/Re;
+      //LBMReal nueLB = 1.5e-3;
+      LBMReal Re = (uLB*(420/dx))/nueLB;
+
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"grid = " <<int((g_maxX1 - g_minX1)/dx)<<"x"<<int((g_maxX2 - g_minX2)/dx) << "x"<<int((g_maxX3 - g_minX3)/dx));
+         UBLOG(logINFO,"dx = " << dx);
+         UBLOG(logINFO,"nodes per block = " << nodesPerBlock);
+         UBLOG(logINFO,"block length = " << blockLength << "mm");
+         UBLOG(logINFO,"v = " << uLB );
+         UBLOG(logINFO,"rho = " << rhoLB );
+         UBLOG(logINFO,"nue = " << nueLB );
+         UBLOG(logINFO,"Re = " << Re );
+         UBLOG(logINFO,"Preprozess - start");
+      }
+
+      SimulationParametersPtr param = SimulationParameters::getInstanz();
+      param->setCollisionModelType(SimulationParameters::COMPRESSIBLE);
+      param->setRho(rhoLB);
+      param->setVelocityX(uLB);
+      param->setViscosity(nueLB);
+      
+      //set grid
+      //Grid3DPtr grid(new Grid3D());
+      grid->setDeltaX(dx);
+      grid->setBlockNX(nodesPerBlock, nodesPerBlock, nodesPerBlock);
+      
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+      GenBlocksGridVisitor genBlocks;
+      genBlocks.addGeoObject(gridCube);
+      grid->accept(genBlocks);
+
+      MetisPartitioningGridVisitor metisVisitor(numOfThreads, D3Q27System::B, comm, false);
+      grid->accept( metisVisitor );
+
+      SolidBlocksHelper sd(grid, comm);
+
+      //iteractors
+      int bbOption1 = 0; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption1));
+
+      D3Q27TriFaceMeshInteractorPtr cargoInt( new D3Q27TriFaceMeshInteractor(geoCargo, grid, bcObst,Interactor3D::SOLID));
+      sd.addInteractor(cargoInt);
+
+      D3Q27InteractorPtr addWallBlowerInt(new D3Q27Interactor(addWallBlower, grid, bcObst,Interactor3D::SOLID));
+
+      sd.addInteractor(addWallBlowerInt);
+
+      //D3Q27TriFaceMeshInteractorPtr paletteInt( new D3Q27TriFaceMeshInteractor(geoPalette, grid, bcObst,Interactor3D::SOLID));
+      //sd.addInteractor(paletteInt);
+
+      D3Q27InteractorPtr addWallXmaxInt(new D3Q27Interactor(addWallXmax, grid, bcObst,Interactor3D::SOLID));
+      sd.addInteractor(addWallXmaxInt);
+
+      D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst,Interactor3D::SOLID));
+      sd.addInteractor(addWallYmaxInt);
+
+      D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst,Interactor3D::SOLID));
+      sd.addInteractor(addWallZmaxInt);
+
+      D3Q27InteractorPtr addWallXminInt(new D3Q27Interactor(addWallXmin, grid, bcObst,Interactor3D::SOLID));
+      sd.addInteractor(addWallXminInt);
+
+      D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst,Interactor3D::SOLID));
+      sd.addInteractor(addWallYminInt);
+
+      D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst,Interactor3D::SOLID));
+      sd.addInteractor(addWallZminInt);
+
+      sd.deleteSolidBlocks();
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	      
+      
+      if (refineLevel > 0)
+      {
+         GbObject3DPtr refineCube1(new  GbCuboid3D(geoTFloor->getX1Minimum(), geoTFloor->getX2Minimum(), geoTFloor->getX3Minimum(), 
+            geoTFloor->getX1Maximum(), geoTFloor->getX2Maximum(), geoTFloor->getX3Maximum()));
+         GbSystem3D::writeGeoObject(refineCube1.get(),pathname + "/refineCube", WbWriterVtkXmlASCII::getInstance());
+
+         RefineCrossAndInsideGbObjectBlockVisitor refVisitor(refineCube1, baseLevel, refineLevel-1);
+         grid->accept(refVisitor);
+
+         RatioBlockVisitor ratioVisitor(refineLevel);
+         grid->accept(ratioVisitor);
+
+         RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+         grid->accept(ratioSmoothVisitor);
+
+         OverlapBlockVisitor overlapVisitor(refineLevel);
+         grid->accept(overlapVisitor);
+      }
+
+      if(myid == 0) UBLOG(logINFO,"Write blocks - start");
+      grid->accept( metisVisitor );
+      if(myid == 0) grid->writeBlocks(pathname + "/blocks" + StringUtil::toString(myid), 0, WbWriterVtkXmlASCII::getInstance(), false);
+      if(myid == 0) UBLOG(logINFO,"Write blocks - end");
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      unsigned long nod = nob * nodesPerBlock * nodesPerBlock *nodesPerBlock;
+      double availMem = 6.0e9;
+      double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int))*2);
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }
+
+      //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(nodesPerBlock, nodesPerBlock, nodesPerBlock));
+      LBMKernel3DPtr kernel(new LBMKernelETD3Q27CascadedTI(nodesPerBlock, nodesPerBlock, nodesPerBlock));
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      //SetKernelBlockVisitor kernelVisitor(kernel, nueLB);
+      grid->accept(kernelVisitor);
+
+      if (refineLevel > 0)
+      {
+         std::vector<int> dirs;
+         D3Q27System::getLBMDirections(dirs);
+         SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+         grid->accept(interDirsVisitor);
+
+         D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+         grid->accept(undefNodesVisitor);
+      }
+
+      //discretization
+      //D3Q27TriFaceMeshInteractorPtr containerInt( new D3Q27TriFaceMeshInteractor(geoContainer, grid, bcObst,Interactor3D::SOLID));
+      //grid->addAndInitInteractor(containerInt);
+
+      D3Q27TriFaceMeshInteractorPtr tFloorInt( new D3Q27TriFaceMeshInteractor(geoTFloor, grid, bcObst,Interactor3D::SOLID));
+      grid->addAndInitInteractor(tFloorInt);
+
+      grid->addAndInitInteractor(addWallBlowerInt);
+      //grid->addAndInitInteractor(blowerInt);
+      grid->addAndInitInteractor(cargoInt);
+      //grid->addAndInitInteractor(paletteInt);
+      grid->addAndInitInteractor(addWallXmaxInt);
+      grid->addAndInitInteractor(addWallYmaxInt);
+      grid->addAndInitInteractor(addWallZmaxInt);
+      grid->addAndInitInteractor(addWallXminInt);
+      grid->addAndInitInteractor(addWallYminInt);
+      grid->addAndInitInteractor(addWallZminInt);
+
+      D3Q27InteractorPtr addWallBlowerXminInt(new D3Q27Interactor(addWallBlowerXmin, grid, bcObst,Interactor3D::SOLID));
+      grid->addAndInitInteractor(addWallBlowerXminInt);
+      
+      D3Q27InteractorPtr addWallBlowerXmaxInt(new D3Q27Interactor(addWallBlowerXmax, grid, bcObst,Interactor3D::SOLID));
+      grid->addAndInitInteractor(addWallBlowerXmaxInt);
+      
+      D3Q27InteractorPtr addWallBlowerYminInt(new D3Q27Interactor(addWallBlowerYmin, grid, bcObst,Interactor3D::SOLID));
+      grid->addAndInitInteractor(addWallBlowerYminInt);
+      
+      D3Q27InteractorPtr addWallBlowerYmaxInt(new D3Q27Interactor(addWallBlowerYmax, grid, bcObst,Interactor3D::SOLID));
+      grid->addAndInitInteractor(addWallBlowerYmaxInt);
+
+      //outflow
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+      D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+      grid->addAndInitInteractor(outflowInt);
+
+      //inflow
+      double Cx = geoInflow->getX1Centroid();
+      double Hx = geoInflow->getLengthX1();
+      double Cy = geoInflow->getX2Centroid();
+      double Hy = geoInflow->getLengthX2();
+      mu::Parser fct = MathUtil::getDuctParaboloidZ(Cx,Hx,Cy,Hy,-uLB);
+      //mu::Parser fct;
+      //fct.SetExpr("vx3");
+      //fct.DefineConst("vx3", uLB);
+
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (false, false ,true ,fct, 0, D3Q27BCFunction::INFCONST));
+      velBCAdapter->setSecondaryBcOption(2);
+      D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+      grid->addAndInitInteractor(inflowInt);
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+
+      //initialization of decompositions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(1.0);
+      grid->accept(initVisitor);
+
+
+      //Postrozess
+      //if(myid == 0) grid->writeBlocks(pathname + "/blocks" + StringUtil::toString(myid), 0, WbWriterVtkXmlASCII::getInstance(), false);
+
+      //std::vector< UbTupleFloat3 > nodes;
+      //std::vector< UbTupleInt2 >   lines;
+      //sphereInt->addQsLineSet(nodes, lines);
+      //WbWriterVtkXmlBinary::getInstance()->writeLines(pathname+"/qs",nodes,lines);
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+           new D3Q27MacroscopicQuantitiesPostprocessor(grid, pathname + "/geo/nodes_geo", WbWriterVtkXmlBinary::getInstance(), 
+                                                       conv, geoSch, comm, true));
+      grid->doPostProcess(0);
+      ppgeo.reset();
+      geoSch.reset();
+      
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+
+}
+      
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+      //double outTime = 50000;
+      double outTime = 500;
+      UbSchedulerPtr visSch(new UbScheduler());
+      visSch->addSchedule(1000,1000,10000);
+      visSch->addSchedule(10000,10000,100000);
+      visSch->addSchedule(100000,100000,1000000);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, pathname + "/mq/nodes", WbWriterVtkXmlBinary::getInstance(), conv, visSch, comm);
+
+      //turbulence intensity postprocessor
+      UbSchedulerPtr tiSch(new UbScheduler());
+      tiSch->addSchedule(1000, 5000, 5000);
+      tiSch->addSchedule(10000, 50000, 50000);
+      tiSch->addSchedule(100000, 500000, 500000);
+      TurbulenceIntensityPostprocessor vp(grid, pathname + "/ti/TI", WbWriterVtkXmlBinary::getInstance(), tiSch, comm);
+
+      double endTime = 1000001;
+      //double endTime = 1001.0;
+      UbSchedulerPtr upSch(new UbScheduler(1));
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, upSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/sbone/CMakeLists.txt b/source/Applications/sbone/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..883dab362fb5313d52af2ed81c0e9f15e6580a0c
--- /dev/null
+++ b/source/Applications/sbone/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(sbone)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(sbone BINARY)
diff --git a/source/Applications/sbone/sbone.cpp b/source/Applications/sbone/sbone.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2d404cee86f0e2dd895655c3c82397ad52a4ab33
--- /dev/null
+++ b/source/Applications/sbone/sbone.cpp
@@ -0,0 +1,421 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+
+using namespace std;
+
+
+void sbonepd(const char *configname)
+{
+   try
+   {
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname, pathGeo; 
+      int numOfThreads;
+      double availMem;
+
+      ConfigFileReader cf(configname);
+      if (!cf.read())
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         numOfThreads = 4;
+         pathname = "d:/temp/sbone2";
+         pathGeo = "d:/Data/Bone/SmallBone";
+         availMem = 3.0e9;
+      }
+      else if(machine == "M01" || machine == "M02")      
+      {
+         numOfThreads = 8;
+         pathname = cf.getValue("pathname"); //"/work/koskuche/Bone/SmallBone";
+         pathGeo = cf.getValue("pathGeo"); //"/home/koskuche/data/Bone/SmallBone/vti";
+         availMem = 1.0e9;
+
+#if defined(__unix__)
+         if (myid == 0)
+         {
+            const char* str = pathname.c_str();
+            int status = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+         }
+#endif 
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      if(myid==0) UBLOG(logINFO,"Testcase small bone");
+
+      //string boneFileName = pathGeo + "/sbone.stl";
+      string boneFileName = pathGeo + "/boneimage.vti";
+
+      double dx = 3.5e-3/175.0;
+
+      const int blocknx1 = 16;
+      const int blocknx2 = 16;
+      const int blocknx3 = 16;
+
+      LBMReal rho_LB = 0.0;
+      //nueWasser = 1e-6 m^2/s
+      double nu_real = 1e-6;
+      LBMReal dt = 5e-8; // s (frei gewählt)
+      //dx - frei gewählt
+      //
+      LBMReal nu_LB = nu_real/(dx*dx/dt);
+
+
+      //dp = 50000 Pa - 0 Pa = 50000 Pa
+      double dp_real = UbSystem::stringTo<double>(cf.getValue("pressure")); //5000;
+      //rho wasser = 1000 kg*m^-3
+      double rho_real = 1000;
+      //dp/rho = 50000/1000 = 50 m^2/s^2
+      double dp_div_rho_real = dp_real/rho_real;
+
+      double dp_LB = dp_div_rho_real/((dx/dt)*(dx/dt));
+
+      bool with_forcing = false;
+
+      double rhoLBinflow;
+      if (with_forcing)
+      {
+         rhoLBinflow = 0.0;
+      } 
+      else
+      {
+         rhoLBinflow = dp_LB*3.0;
+      }
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+
+      //////////////////////////////////////////////////////////////////////////
+      //bone STL
+      //GbTriFaceMesh3DPtr bone (GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(boneFileName,"Netz"));
+      //if(myid == 0) GbSystem3D::writeGeoObject( bone.get(), pathname+"/geo/bone", WbWriterVtkXmlBinary::getInstance() );
+
+      string boneFilename = pathGeo + "/boneimage.vti";
+
+      int pmNX1=151;  //abmessung einzelbild in x-richtung
+      int pmNX2=101; //abmessung einzelbild in y richtung
+      int pmNX3=101; //anzahl der bilder
+      float lthreshold = 1.0;
+      float uthreshold = 255.0;
+
+      GbVoxelMatrix3DPtr bone(new GbVoxelMatrix3D(pmNX1,pmNX2,pmNX3,0,lthreshold,uthreshold));
+      bone->readMatrixFromVtiASCIIFile(boneFilename);
+      bone->setVoxelMatrixMininum(11.5, 8.01, 5.01);
+
+      double deltax = dx*1e3;
+      double deltaVoxel = 11e-3;
+      bone->setVoxelMatrixDelta(deltaVoxel, deltaVoxel, deltaVoxel);
+      bone->setLbGridDx(deltax);
+
+      if(myid == 0) bone->writeToLegacyVTKBinary(pathname+"/geo/bone");
+
+      //bounding box
+      double g_minX1 = bone->getX1Minimum()-0.25;
+      double g_minX2 = bone->getX2Minimum()-0.25;
+      double g_minX3 = bone->getX3Minimum()-0.25;
+
+      double g_maxX1 = bone->getX1Maximum()+0.25;
+      double g_maxX2 = bone->getX2Maximum()+0.25;
+      double g_maxX3 = bone->getX3Maximum()+0.25;
+
+      double blockLength = (double)blocknx1*deltax;
+
+      //double h = g_maxX2/2.0;
+      //double dpLB = (rhoLBinflow - rhoLB)/3.0;
+
+      //
+      //double dex = g_maxX1+1.0;
+      //double Umax = (1.0/(2.0*nueLB))*(dpLB/dex)*(h*h);
+
+      //double Re = (4*h*Umax)/(3*nueLB);
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setPeriodicX1(false);
+      grid->setPeriodicX2(false);
+      grid->setPeriodicX3(false);
+      grid->setDeltaX(deltax);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());      
+
+
+      GenBlocksGridVisitor genBlocks(gridCube);
+      grid->accept(genBlocks);
+
+      double forcing = 0;
+      if (with_forcing)
+      {
+         forcing = dp_LB/(blocknx1*grid->getNX1());
+      }
+
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"Parameters:");
+         UBLOG(logINFO,"with forcing = " << with_forcing );
+         UBLOG(logINFO,"rho_LB = " << rho_LB );
+         UBLOG(logINFO,"nu_LB = " << nu_LB );
+         UBLOG(logINFO,"dp_LB = " << dp_LB );
+         UBLOG(logINFO,"forcing = " << forcing );
+         UBLOG(logINFO,"dx = " << dx << " m");
+         UBLOG(logINFO,"dt = " << dt << " s");
+         UBLOG(logINFO,"rho_real = " << rho_real << " kg*m^-3" );
+         UBLOG(logINFO,"nu_real = " << nu_real << " m^2/s" );
+         UBLOG(logINFO,"dp_real = " << dp_real << " Pa" );
+
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+         UBLOG(logINFO,"path = " << pathname );
+         UBLOG(logINFO,"Preprozess - start");
+      }
+
+      //walls
+      GbCuboid3DPtr addWallYmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_minX2, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallYmax (new GbCuboid3D(g_minX1-blockLength, g_maxX2, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmin (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_minX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmax (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_maxX3, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+      //inflow
+      GbCuboid3DPtr geoInflow (new GbCuboid3D(g_minX1-blockLength, g_minX2-blockLength, g_minX3-blockLength, g_minX1, g_maxX2+blockLength, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      //outflow
+      GbCuboid3DPtr geoOutflow (new GbCuboid3D(g_maxX1, g_minX2-blockLength, g_minX3-blockLength, g_maxX1+blockLength, g_maxX2+blockLength, g_maxX3+blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+
+      //   if (refineLevel > 0)
+      //   {
+      //      if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+      //      RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+      //      refineHelper.refine();
+      //      if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+      //   }
+
+
+
+      //bone interactor
+      int bcOptionBone = 2; //0=simple Bounce Back, 1=quadr. BB, 2=thin wall
+      D3Q27BoundaryConditionAdapterPtr bcBone(new D3Q27NoSlipBCAdapter(bcOptionBone));
+
+      D3Q27InteractorPtr boneInt(new D3Q27Interactor(bone, grid, bcBone,Interactor3D::SOLID));
+
+      //wall interactors
+      int bcOptionWall = 1; //0=simple Bounce Back, 1=quadr. BB, 2=thin wall
+      D3Q27BoundaryConditionAdapterPtr bcWall(new D3Q27NoSlipBCAdapter(bcOptionWall));
+      D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcWall,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcWall,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcWall,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcWall,Interactor3D::SOLID));
+
+      //   //inflow
+      //   //double dp_Ph=0.1*10000.0;//dp in Bar
+      //   //double dp_lb=dp_Ph*0.001*(nueLB*dx)*(nueLB*dx);//nue_ph=10e-6
+      //   //if(myid == 0) UBLOG(logINFO,"dp_lb = " << dp_lb );
+      //   //double rhoLBinflow = 3.0*(dp_lb-rhoLB);
+
+      D3Q27BoundaryConditionAdapterPtr denBCAdapterInflow(new D3Q27DensityBCAdapter(rhoLBinflow));
+      denBCAdapterInflow->setSecondaryBcOption(0);
+      D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, denBCAdapterInflow, Interactor3D::SOLID));
+
+      //outflow
+      D3Q27BoundaryConditionAdapterPtr denBCAdapterOutflow(new D3Q27DensityBCAdapter(rho_LB));
+      denBCAdapterOutflow->setSecondaryBcOption(0);
+      D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapterOutflow,Interactor3D::SOLID));
+
+      ////////////////////////////////////////////
+      //METIS
+      Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));   
+      ////////////////////////////////////////////
+      /////delete solid blocks
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+      InteractorsHelper intHelper(grid, metisVisitor);
+      intHelper.addInteractor(boneInt);
+      intHelper.addInteractor(addWallYminInt);
+      intHelper.addInteractor(addWallYmaxInt);
+      intHelper.addInteractor(addWallZminInt);
+      intHelper.addInteractor(addWallZmaxInt);
+      intHelper.addInteractor(inflowInt);
+      intHelper.addInteractor(outflowInt);
+      intHelper.selectBlocks();
+      if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+      //////////////////////////////////////
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      //domain decomposition for threads
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nodb = (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nod = nob * (blocknx1) * (blocknx2) * (blocknx3);
+      unsigned long nodg = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+      double needMemAll  = double(nodg*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         int minInitLevel = grid->getCoarsestInitializedLevel();
+         int maxInitLevel = grid->getFinestInitializedLevel();
+         for(int level = minInitLevel; level<=maxInitLevel; level++)
+         {
+            int nobl = grid->getNumberOfBlocks(level);
+            UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nobl);
+            UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nobl*nodb);
+         }
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      LBMKernel3DPtr kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+      //mu::Parser fctForcingX1;
+      //fctForcingX1.SetExpr("Fx1");
+      //fctForcingX1.DefineConst("Fx1", forcing);
+
+      //kernel->setForcingX1(fctForcingX1);
+      //kernel->setWithForcing(true);
+
+      BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nu_LB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+
+      //if (refineLevel > 0)
+      //{
+      //   D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+      //   grid->accept(undefNodesVisitor);
+      //}
+
+      //BC
+      intHelper.setBC();
+
+      //Press*1.6e8+(14.76-coordsX)/3.5*5000
+      //initialization of distributions
+      mu::Parser fct;
+      fct.SetExpr("(x1max-x1)/l*dp*3.0");
+      fct.DefineConst("dp", dp_LB);
+      fct.DefineConst("x1max", g_maxX1);
+      fct.DefineConst("l", g_maxX1-g_minX1);
+
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(nu_LB, rho_LB);
+      initVisitor.setRho(fct);
+      //initVisitor.setVx1(fct);
+      initVisitor.setVx1(0.0);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+      ppgeo->update(0);
+      ppgeo.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      double outTime = 1000;
+      UbSchedulerPtr stepSch(new UbScheduler(outTime));
+      stepSch->addSchedule(10,10,100);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+
+      double dxd2 = deltax / 2.0;
+      D3Q27IntegrateValuesHelperPtr ih1(new D3Q27IntegrateValuesHelper(grid, comm, bone->getX1Minimum() - dxd2, bone->getX2Minimum() - dxd2, bone->getX3Minimum() - dxd2,
+         bone->getX1Maximum() + dxd2, bone->getX2Maximum() + dxd2, bone->getX3Maximum() + dxd2));
+      if (myid == 0) GbSystem3D::writeGeoObject(ih1->getBoundingBox().get(), pathname + "/geo/ih1", WbWriterVtkXmlBinary::getInstance());
+
+      double factorp = dp_real/dp_LB;
+      double factorv = dx/dt;
+      D3Q27MeanValuesPostprocessor mvp1(grid, stepSch, pathname + "/mv/mv1.txt", comm, ih1, factorp, factorv);
+
+
+      D3Q27IntegrateValuesHelperPtr ih2(new D3Q27IntegrateValuesHelper(grid, comm, g_maxX1-2.0*deltax, g_minX2, g_minX3,
+         g_maxX1 - deltax, g_maxX2, g_maxX3));
+      if (myid == 0) GbSystem3D::writeGeoObject(ih2->getBoundingBox().get(), pathname + "/geo/ih2", WbWriterVtkXmlBinary::getInstance());
+
+      D3Q27MeanValuesPostprocessor mvp2(grid, stepSch, pathname + "/mv/mv2.txt", comm, ih2, factorp, factorv);
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      double endTime = UbSystem::stringTo<double>(cf.getValue("endTime")); //100001;//10001.0;
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, stepSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+
+   if ( argv != NULL )
+   {
+      sbonepd(argv[1]);
+   }
+
+   return 0;
+}
diff --git a/source/Applications/shear/CMakeLists.txt b/source/Applications/shear/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ce43e1f71988432bb9aadcf64408d6bb942e2037
--- /dev/null
+++ b/source/Applications/shear/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(shear)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(shear BINARY)
diff --git a/source/Applications/shear/shear.cpp b/source/Applications/shear/shear.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8026d17f5cf136fa28a797119d1852a0ef01bc56
--- /dev/null
+++ b/source/Applications/shear/shear.cpp
@@ -0,0 +1,514 @@
+#include <iostream>
+#include <string>
+
+#include <vfluids.h>
+using namespace std;
+
+
+void run(const char *cstr)
+{
+   CommunicatorPtr comm(new MPICommunicator());
+   try
+   {
+      //Sleep(30000);
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+	  string geosphere;	  
+      int numOfThreads = 1;
+      double availMem = 0;
+
+      
+      int myid = comm->getProcessID();
+
+      if(machine == "BOMBADIL") 
+      {
+         pathname = "d:/temp/shear";
+         numOfThreads = 1;
+         availMem = 3.0e9;
+         geosphere = "d:/Data/Ehsan/Agglomerat_n_00020_fd_1.882437_r_0033.930997.txt";
+      }
+       else if(machine == "M01" || machine == "M02")      
+      {
+         pathname = "/work/koskuche/scratch/smallAgg80";
+		// geosphere = "/work/ehsan/data/Agglomerat4.txt";
+	   // geosphere = "/work/ehsan/data/Agglomerat_n_00060_fd_1.858514_r_0061.500327.txt";
+		// geosphere = "/work/ehsan/data/Agglomerat_n_00080_fd_1.855984_r_0071.870085.txt";
+		//geosphere = "/work/ehsan/data/Agglomerat_n_00040_fd_1.864231_r_0049.358563.txt";
+		//geosphere = "/work/ehsan/data/Agglomerat_n_00020_fd_1.882437_r_0033.930997.txt";
+		geosphere = "/work/ehsan/data/Agglomerat_n_00500_fd_1.850643_r_0193.702967.txt";
+      
+		
+		
+		
+         numOfThreads = 1;
+         availMem =1.0e10;// 12.0e9;
+
+         if(myid ==0)
+         {
+            stringstream logFilename;
+            logFilename <<  pathname + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt";
+            UbLog::output_policy::setStream(logFilename.str());
+         }
+	   }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+      double dx =0.1*4.0;
+
+	  double eq_Diameter=2.0*38.0;//55.3586;//61.5003;//80;//71.8701;//61.5003;
+      double L1 =35.0*eq_Diameter;
+      double L2, L3, H;
+      L2 = L3 = H =35.0*eq_Diameter;//1.0;//0.42*3.9;
+
+      LBMReal radius = 6.0;
+      LBMReal rhoReal = 1.0; //kg/m^3
+      //LBMReal uReal = 0.45;//m/s
+   //   LBMReal uLB = 0.05;
+      LBMReal Re = 0.1;
+      LBMReal rhoLB = 0.0;
+      LBMReal l = L2 / dx;
+
+      //LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter(1.0, 1/sqrt(3.0)*(uReal/uLB), 1.0, 1.0/dx, dx*dx*dx));
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      const int baseLevel = 0;
+      const int refineLevel = 5;  
+  
+     
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+	  const int blocknx1 = 8;
+      const int blocknx2 = 8;
+      const int blocknx3 = 8;
+
+      dx =14.4*2.0;// ( 0.9) *(double)(1<<refineLevel);
+
+	  double area =/* radius/dx;*/radius*radius*PI/(dx/(double)(1<<refineLevel))/(dx/(double)(1<<refineLevel));//2.0*radius*H;
+	  double nueReal=1e-6;//water
+	  double uReal=Re*nueReal/(2.0*radius);//real velocity
+	  double F_stokss=6*PI*.001/*water*/*radius*uReal;
+      //LBMReal nueLB = (((4.0/9.0)*uLB)*2.0*(radius/dx))/Re;
+      LBMReal nueLB =.75/((double)(1<<refineLevel));// ((uLB)*2.0*(radius/dx))/Re;
+	//  LBMReal uLB  = ((nueLB)*Re)/ ( 2.0*(radius/dx));//base on the coarsest level
+	  LBMReal uLB  = ((0.75)*Re)/ ( 2.0*(radius/(dx/((double)(1<<refineLevel)))));//base on the coarsest level if nueLB =.75/((double)(1<<refineLevel)) and  dx = ( 0.9) *(double)(1<<refineLevel)
+  //     LBMReal uLB  = ((0.75)*Re)/ ((eq_Diameter/(dx/((double)(1<<refineLevel)))));//base on the coarsest level if nueLB =.75/((double)(1<<refineLevel)) and  dx = ( 0.9) *(double)(1<<refineLevel)
+	 double blockLength = blocknx1*dx;
+	
+
+		double xsphere=1.0*L1/2.0;//0.5;
+		double ysphere=L2/2.0;//0.75;
+		double zsphere=L3/2.0;//0.75;
+ //obstacle
+    	 //////////////////////////////////////////////////////////////////////////
+	  UbFileInputASCII file;
+	  file.open(geosphere);
+	  //file.skipLine();file.skipLine();//2line skiped
+	  std::string NOP=file.readString();
+	  std::string NOP2=file.readString();
+	  const int numberOfParticles=file.readDouble();
+	  if(myid == 0){UBLOG(logINFO,__FILE__<<" " <<__LINE__<<" number of particles="<<numberOfParticles);}	
+	  //std::string Dia=file.readString();
+	  double diameter=2.0*radius;//12;//file.readDouble();
+	  file.skipLine();file.skipLine();file.skipLine();file.skipLine();file.skipLine();file.skipLine();file.skipLine();//7 line skiped
+			GbSphere3DPtr *sphereP=new GbSphere3DPtr[numberOfParticles];
+			  
+			for (int i=0;i<numberOfParticles;i++)
+			{
+			double x=file.readDouble();
+			double y=file.readDouble();
+			double z=file.readDouble();
+		///0degree in x direction		
+			    double x_rotation= x;
+			    double y_rotation= y;
+			    double z_rotation= z;
+///180degree in x direction		
+			   // double x_rotation= x;
+			   // double y_rotation= -y;
+			   // double z_rotation= -z;			   
+		///90degree in y direction	
+			  // double x_rotation=-z;
+			  // double y_rotation= y;
+			  // double z_rotation=x;			
+	   // ///90degree in z axis	
+			   // double x_rotation=-y;
+			   // double y_rotation=x;
+			   // double z_rotation=z;
+		//transfer	
+			double x_final=x_rotation/*/1450*/  +xsphere;
+			double y_final=y_rotation/*/1450*/  +ysphere;
+			double z_final=z_rotation/*/1450*/  +zsphere;
+				sphereP[i]=GbSphere3DPtr(new GbSphere3D(x_final, y_final, z_final, diameter/2.0/*/1450*/));
+				if(myid == 0)GbSystem3D::writeGeoObject(sphereP[i].get(),pathname + "/sphere/sphere"+ "_" + UbSystem::toString(i), WbWriterVtkXmlASCII::getInstance());
+			}
+			file.close();
+///////////////////////////////	
+       D3Q27InteractorPtr *spherePInt=new D3Q27InteractorPtr[numberOfParticles];	
+      double offs = dx;
+
+      //double g_minX1 = d_minX1-offs-0.499999*dx;
+      double g_minX1 = d_minX1-offs;
+      double g_minX2 = d_minX2-offs;
+      double g_minX3 = d_minX3-offs;
+
+      double g_maxX1 = d_maxX1+offs;
+      double g_maxX2 = d_maxX2+offs;
+      double g_maxX3 = d_maxX3+offs;
+			if(myid == 0){UBLOG(logINFO,__FILE__<<" " <<__LINE__);}	  
+      GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+			if(myid == 0){UBLOG(logINFO,__FILE__<<" " <<__LINE__);}	  
+      
+
+      //refinement area
+      double rf = 0.50*blockLength;
+      // GbObject3DPtr refineCube(new  GbCuboid3D(sphereP[0]->getX1Minimum()-rf*3.0/4.0, sphereP[3]->getX2Minimum()-rf*3.0/4.0, sphereP[5]->getX3Minimum()-rf*1.0/2.0, 
+         // sphereP[2]->getX1Maximum()+rf*3.0/4.0, sphereP[4]->getX2Maximum()+rf*3.0/4.0, sphereP[6]->getX3Maximum()+rf*1.0/2.0));
+		 
+		 //////////
+	   double level5=xsphere-(xsphere-eq_Diameter/2-0.50*(blocknx1*dx/pow(2.0,5)));//0.065;//.085;
+	   double level4=level5+.1*(blocknx1*dx/pow(2.0,4));//0.015;//0.1;
+	   double level3=level4+0.50*(blocknx1*dx/pow(2.0,3));//0.015;//0.115;
+	   double level2=level3+1.0*(blocknx1*dx/pow(2.0,2));//.035;//0.15;
+	   double level1=level2+1.0*(blocknx1*dx/pow(2.0,1));//.05;//0.2;
+	   
+	    GbCuboid3DPtr refineCube1(new GbCuboid3D(  xsphere-level1,ysphere-level1, zsphere-level1,xsphere+level1,ysphere+level1, zsphere+level1));
+	    GbCuboid3DPtr refineCube2(new GbCuboid3D(  xsphere-level2,ysphere-level2, zsphere-level2,xsphere+level2,ysphere+level2, zsphere+level2));
+		GbCuboid3DPtr refineCube3(new GbCuboid3D(  xsphere-level3,ysphere-level3, zsphere-level3,xsphere+level3,ysphere+level3, zsphere+level3));
+		GbCuboid3DPtr refineCube4(new GbCuboid3D(  xsphere-level4,ysphere-level4, zsphere-level4,xsphere+level4,ysphere+level4, zsphere+level4));
+		GbCuboid3DPtr refineCube5(new GbCuboid3D(  xsphere-level5,ysphere-level5, zsphere-level5,xsphere+level5,ysphere+level5, zsphere+level5));
+		 ///////////
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      UbSchedulerPtr rSch(new UbScheduler(100000, 100000));
+      //RestartPostprocessorPtr rp(new RestartPostprocessor(grid, rSch, comm, pathname+"/checkpoints", RestartPostprocessor::BINARY));
+
+      //UbSchedulerPtr emSch(new UbScheduler(1000, 1000));
+      //EmergencyExitPostprocessor em(grid, emSch, pathname+"/checkpoints/emex.txt", rp, comm);
+
+      std::string opt;
+
+      if(cstr!= NULL)
+         opt = std::string(cstr);
+
+      if/*(cstr== NULL)*/(cstr!= NULL)
+      {
+         opt = std::string(cstr);
+
+         if(myid==0) UBLOG(logINFO,"Restart step: " << opt);
+
+         //grid = rp->restart(UbSystem::stringTo<int>(opt));
+         //rp->reconnect();
+
+         //cylinderInt = 
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+      }
+      else
+      {
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"L = " << L2/dx );
+            UBLOG(logINFO,"v = " << uLB );
+            UBLOG(logINFO,"rho = " << rhoLB );
+            UBLOG(logINFO,"nue = " << nueLB );
+            UBLOG(logINFO,"Re = " << Re );
+			UBLOG(logINFO,"F_stokss = " << F_stokss );
+			UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,conv->toString() );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         grid->setDeltaX(dx);
+         grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+		 grid->setPeriodicX1(false);
+         grid->setPeriodicX2(true);
+         grid->setPeriodicX3(true);
+
+         // UbTupleDouble6 bouningBox(gridCube->getX1Minimum(),gridCube->getX2Minimum(),gridCube->getX3Minimum(),
+         // gridCube->getX1Maximum(),gridCube->getX2Maximum(),gridCube->getX3Maximum());
+         // UbTupleInt3 blockNx(blocknx1, blocknx2, blocknx3);
+         // UbTupleInt3 gridNx(8, 16, 16);
+         // grid = Grid3DPtr(new Grid3D(bouningBox, blockNx, gridNx));
+
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+ //        if(myid ==0) GbSystem3D::writeGeoObject(refineCube.get(),pathname + "/geo/refineCube", WbWriterVtkXmlBinary::getInstance());
+ 
+         ////
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance());
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube1.get(), pathname + "/geo/refineCube1", WbWriterVtkXmlBinary::getInstance());
+		 if(myid ==0) GbSystem3D::writeGeoObject(refineCube2.get(),pathname + "/geo/refineCube2", WbWriterVtkXmlBinary::getInstance());
+         if(myid ==0) GbSystem3D::writeGeoObject(refineCube3.get(),pathname + "/geo/refineCube3", WbWriterVtkXmlBinary::getInstance());
+		 if(myid ==0) GbSystem3D::writeGeoObject(refineCube4.get(),pathname + "/geo/refineCube4", WbWriterVtkXmlBinary::getInstance());
+		 if(myid ==0) GbSystem3D::writeGeoObject(refineCube5.get(),pathname + "/geo/refineCube5", WbWriterVtkXmlBinary::getInstance());
+		 ////
+		 
+         GenBlocksGridVisitor genBlocks;
+         genBlocks.addGeoObject(gridCube);
+         grid->accept(genBlocks);
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+        if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+			RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+			refineHelper.addGbObject(refineCube5, refineLevel);
+			
+		//	refineHelper.addGbObject(refineCube1, refineLevel);
+			// refineHelper.addGbObject(refineCube2, refineLevel-1);
+			// refineHelper.addGbObject(refineCube3, refineLevel-2);
+			// refineHelper.addGbObject(refineCube4, refineLevel-3);
+			//refineHelper.addGbObject(refineCube5, refineLevel-4);
+			
+
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");   
+		 
+         }
+
+         MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B);
+         grid->accept( metisVisitor );
+
+         SolidBlocksHelper sd(grid, comm);
+
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcObst(new D3Q27NoSlipBCAdapter(bbOption));
+		 D3Q27BoundaryConditionAdapterPtr bcObst2(new D3Q27SlipBCAdapter(bbOption));
+        // cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(cylinder, grid, bcObst,Interactor3D::SOLID));
+		
+			for (int i=0;i<numberOfParticles;i++)
+			{      
+				spherePInt[i]= D3Q27InteractorPtr( new D3Q27Interactor(sphereP[i], grid, bcObst,Interactor3D::SOLID));
+			}
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcObst2,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcObst2,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcObst2,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcObst2,Interactor3D::SOLID));
+
+		  //for shear strees =0
+		 // D3Q27BoundaryConditionAdapterPtr velBCAdapter2(new D3Q27VelocityBCAdapter ());
+         // velBCAdapter2->setSecondaryBcOption(1);
+         // D3Q27InteractorPtr addWallYminInt  = D3Q27InteractorPtr( new D3Q27Interactor(addWallYmin, grid, velBCAdapter2, Interactor3D::SOLID));
+		 // D3Q27InteractorPtr addWallZminInt  = D3Q27InteractorPtr( new D3Q27Interactor(addWallZmin, grid, velBCAdapter2, Interactor3D::SOLID));
+		 // D3Q27InteractorPtr addWallYmaxInt  = D3Q27InteractorPtr( new D3Q27Interactor(addWallYmax, grid, velBCAdapter2, Interactor3D::SOLID));
+		 // D3Q27InteractorPtr addWallZmaxInt  = D3Q27InteractorPtr( new D3Q27Interactor(addWallZmax, grid, velBCAdapter2, Interactor3D::SOLID));
+
+		
+		 
+         mu::Parser fct;
+         //fct.SetExpr("16*U*x2*x3*(H-x2)*(H-x3)/H^4");
+         //fct.DefineConst("U", uLB);
+         //fct.DefineConst("H", H);
+
+		 fct.SetExpr("U");
+         fct.DefineConst("U", uLB);
+         
+         //inflow
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         velBCAdapter->setSecondaryBcOption(0);
+         D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+ 
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+	for (int i=0;i<numberOfParticles;i++)
+			{      
+				sd.addInteractor(spherePInt[i]  );
+			}
+         //sd.addInteractor(cylinderInt);
+         // sd.addInteractor(addWallYminInt);
+         // sd.addInteractor(addWallZminInt);
+         // sd.addInteractor(addWallYmaxInt);
+         // sd.addInteractor(addWallZmaxInt);
+         sd.addInteractor(inflowInt);
+         sd.addInteractor(outflowInt);
+if(myid == 0) UBLOG(logINFO,"delete - start"); 
+         sd.deleteSolidBlocks();
+if(myid == 0) UBLOG(logINFO,"delete - end"); 
+
+         grid->accept( metisVisitor );
+
+         sd.setTransBlocks();
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3));
+         //LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(blocknx1, blocknx2, blocknx3, true));
+         //option = 0 - ohne param., option = 1 - mit param.
+         int option = 0;
+       LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, option));
+      //   LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB_Geier(blocknx1, blocknx2, blocknx3, option));
+	 
+//	     LBMKernel3DPtr kernel(new  LBMKernelETD3Q27Cascaded(blocknx1, blocknx2, blocknx3, option));
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         //walls
+        // grid->addAndInitInteractor(addWallYminInt);
+        // grid->addAndInitInteractor(addWallZminInt);
+        // grid->addAndInitInteractor(addWallYmaxInt);
+        // grid->addAndInitInteractor(addWallZmaxInt);
+
+         //obstacle
+         //grid->addAndInitInteractor(cylinderInt);
+			for (int i=0;i<numberOfParticles;i++)
+			{      
+				grid->addAndInitInteractor(spherePInt[i]  );
+			}
+
+         //inflow
+         grid->addAndInitInteractor(inflowInt);
+
+         //outflow
+         grid->addAndInitInteractor(outflowInt);
+
+         //domain decomposition
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(rhoLB);
+         initVisitor.setVx1(fct);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname + "/grid/nodes", WbWriterVtkXmlBinary::getInstance(), conv, comm, true));
+ if(myid == 0) UBLOG(logINFO,"/grid/nodes");         
+		ppgeo->update(0);
+		 if(myid == 0) UBLOG(logINFO,"line"<<__LINE__); 
+         ppgeo.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }  
+      double outTime = 5000.0;
+      UbSchedulerPtr visSch(new UbScheduler(outTime));
+      visSch->addSchedule(1000, 1000, 10000);
+      visSch->addSchedule(10000, 10000, 50000);
+      visSch->addSchedule(1000, 1000, 100000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname + "/steps/step", WbWriterVtkXmlBinary::getInstance(), conv, comm);
+
+      double fdx = grid->getDeltaX(grid->getFinestInitializedLevel());
+      double point1[3] = {0.45, 0.20, 0.205};
+      double point2[3] = {0.55, 0.20, 0.205};
+
+      D3Q27IntegrateValuesHelperPtr h1(new D3Q27IntegrateValuesHelper(grid, comm, 
+         point1[0]-1.0*fdx, point1[1]-1.0*fdx, point1[2]-1.0*fdx, 
+         point1[0], point1[1], point1[2]));
+      if(myid ==0) GbSystem3D::writeGeoObject(h1->getBoundingBox().get(),pathname + "/geo/iv1", WbWriterVtkXmlBinary::getInstance());
+      D3Q27IntegrateValuesHelperPtr h2(new D3Q27IntegrateValuesHelper(grid, comm, 
+         point2[0], point2[1]-1.0*fdx, point2[2]-1.0*fdx, 
+         point2[0]+1.0*fdx, point2[1], point2[2]));
+      if(myid ==0) GbSystem3D::writeGeoObject(h2->getBoundingBox().get(),pathname + "/geo/iv2", WbWriterVtkXmlBinary::getInstance());
+      //D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, conv, comm);
+      D3Q27PressureDifferencePostprocessor rhopp(grid, visSch, pathname + "/results/rho_diff.txt", h1, h2, rhoReal, uReal, uLB, comm);
+    
+      
+      double v    = uLB;//4.0*uLB/9.0;
+    //  D3Q27ForcesPostprocessor fp(grid, visSch, pathname + "/results/forces.txt", comm, rhoLB, v, area, D3Q27ForcesPostprocessor::X, D3Q27ForcesPostprocessor::Y, D3Q27ForcesPostprocessor::Z);
+    //      for (int i=0;i<numberOfParticles;i++)
+			 //{      
+				// fp.addInteractor(spherePInt[i]  );
+			 //}
+	  
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 40));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+      double endTime = 65001.0;
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+
+   run(argv[1]);
+
+   return 0;
+}
+
diff --git a/source/Applications/sphere/CMakeLists.txt b/source/Applications/sphere/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1d17bc86606abc9645c5160bad894d2570b2ff3b
--- /dev/null
+++ b/source/Applications/sphere/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(sphere)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(sphere BINARY)
diff --git a/source/Applications/sphere/config.txt b/source/Applications/sphere/config.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f6440c07534adb884c2c819165c312edbe4d2615
--- /dev/null
+++ b/source/Applications/sphere/config.txt
@@ -0,0 +1,20 @@
+#Ordner für Simulationsergebnisse
+path=d:/temp/insitu_demo
+
+#Verfügbare Arbeitsspeicher in Byte
+memory=21e9
+
+#Pfad zum Metafile
+metafile=d:/Data/insituDemo/metafile.csv
+
+#Ausgabezeitschritt
+outstep=1
+
+#maximale Anzahl Simulationszeitschritte
+endstep=100000
+
+#Anzahl von Threads
+threads=4
+
+#max refierment level (1 - 5)
+level=1
\ No newline at end of file
diff --git a/source/Applications/sphere/sphere.cpp b/source/Applications/sphere/sphere.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b9a3746d1403490102c96f9b09371c87ca186ad
--- /dev/null
+++ b/source/Applications/sphere/sphere.cpp
@@ -0,0 +1,444 @@
+#include <vfluids.h>
+#include <set>
+#include <map>
+using namespace std;
+
+
+////////////////////////////////////////////////////////////////////////
+void chanel(const char *cstr)
+{
+   try
+   {
+
+      //Sleep(30000);
+
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname; 
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+
+      int myid = comm->getProcessID();
+      int mybundle = comm->getBundleID();
+      int root = comm->getRoot();
+
+      ConfigFileReader cf(cstr);
+      if ( !cf.read() )
+      {
+         std::string exceptionText = "Unable to read configuration file\n";
+         throw exceptionText;
+      }
+
+      pathname = cf.getValue("path");
+      availMem = UbSystem::stringTo<double>(cf.getValue("memory"));
+      string metafile = cf.getValue("metafile");
+      double outstep = UbSystem::stringTo<double>(cf.getValue("outstep"));
+      double endstep = UbSystem::stringTo<double>(cf.getValue("endstep"));
+      int numOfThreads = UbSystem::stringTo<int>(cf.getValue("threads"));
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      double dx = 1;
+
+      const int blocknx1 = 8;
+      const int blocknx2 = 8;
+      const int blocknx3 = 8;
+
+      const int gridNx1 = 8;// 18;
+      const int gridNx2 = 4;// 11;
+      const int gridNx3 = 4;// 11;
+
+      //const int blocknx1 = 40;
+      //const int blocknx2 = 40;
+      //const int blocknx3 = 40;
+
+      //const int gridNx1 = 2;
+      //const int gridNx2 = 2;
+      //const int gridNx3 = 2;
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3;
+      L2 = gridNx2*blocknx1;
+      L3 = gridNx3*blocknx1;
+
+      LBMReal radius = 2.5;
+      LBMReal uLB = 0.0000001;
+      LBMReal Re = 0.0001;
+      LBMReal rhoLB = 0.0;
+      //LBMReal nuLB = (uLB*2.0*radius)/Re;
+      //LBMReal nuLB = (uLB*L2)/Re;
+      LBMReal nuLB = 0.168666666667/100;
+
+      double dp_LB =1e-6;
+      double rhoLBinflow = dp_LB*3.0;
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+
+      BoundaryConditionProcessorPtr bcProcessor(new BoundaryConditionProcessor());
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr restartSch(new UbScheduler(100000, 100000, 100000));
+      RestartPostprocessor rp(grid, restartSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+
+         const int baseLevel = 0;
+         const int refineLevel = UbSystem::stringTo<int>(cf.getValue("level"));
+
+         //bounding box
+         double d_minX1 = 0.0;
+         double d_minX2 = 0.0;
+         double d_minX3 = 0.0;
+
+         double d_maxX1 = L1;
+         double d_maxX2 = L2;
+         double d_maxX3 = L3;
+
+         double blockLength = blocknx1*dx;
+
+         if(myid ==0)
+         {
+            UBLOG(logINFO,"Parameters:");
+            UBLOG(logINFO,"uLB = " << uLB );
+            UBLOG(logINFO,"rhoLB = " << rhoLB );
+            UBLOG(logINFO,"nueLB = " << nuLB );
+            UBLOG(logINFO,"Re = " << Re );
+            UBLOG(logINFO,"dx = " << dx );
+            UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+            UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+            UBLOG(logINFO,"Preprozess - start");
+         }
+
+         GbObject3DPtr gridCube(new GbCuboid3D(d_minX1, d_minX2, d_minX3, d_maxX1, d_maxX2, d_maxX3));
+         if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance()); 
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+         //sphere
+         //GbObject3DPtr sphereRef(new GbSphere3D(L1/4.0, L2*0.5, L3*0.5, radius+1.0));
+         //GbSystem3D::writeGeoObject(sphereRef.get(),pathname + "/geo/sphereRef", WbWriterVtkXmlBinary::getInstance());
+
+         //sphere
+         GbObject3DPtr sphere(new GbSphere3D(L1/4.0, L2*0.5, L3*0.5, radius));
+         //GbObject3DPtr sphere(new GbCuboid3D(L1/4.0-radius, L2/2.0-radius, L3/2.0-radius, L1/4.0+radius, L2/2.0+radius, L3/2.0+radius));
+         GbSystem3D::writeGeoObject(sphere.get(),pathname + "/geo/sphere", WbWriterVtkXmlBinary::getInstance());
+
+         double off = 0.0;
+         GbObject3DPtr refCube(new GbCuboid3D(sphere->getX1Minimum()-off, sphere->getX2Minimum()-off, sphere->getX3Minimum(), 
+            sphere->getX1Maximum()+off, sphere->getX2Maximum()+off, sphere->getX3Maximum()));
+         if(myid ==0) GbSystem3D::writeGeoObject(refCube.get(),pathname + "/geo/refCube", WbWriterVtkXmlBinary::getInstance()); 
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            //refineHelper.addGbObject(sphere, refineLevel);
+            refineHelper.addGbObject(refCube, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //walls
+         GbCuboid3DPtr addWallYmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_minX2, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallYmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_maxX2, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+
+         GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+         //inflow
+         GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+         //outflow
+         GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+         if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+         BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+
+
+
+         //sphere
+         int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcNoSlip(new D3Q27NoSlipBCAdapter(bbOption));
+         D3Q27InteractorPtr sphereInt = D3Q27InteractorPtr ( new D3Q27Interactor(sphere, grid, bcNoSlip,Interactor3D::SOLID));
+
+         D3Q27BoundaryConditionAdapterPtr bcSlip(new D3Q27SlipBCAdapter(bbOption));
+
+         //walls
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcNoSlip,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcNoSlip,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcNoSlip,Interactor3D::SOLID));
+         D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcNoSlip,Interactor3D::SOLID));
+
+         mu::Parser fct;
+         fct.SetExpr("U");
+         fct.DefineConst("U", uLB);
+ 
+         //inflow
+         //D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+         //velBCAdapter->setSecondaryBcOption(2);
+         //D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+         D3Q27BoundaryConditionAdapterPtr denBCAdapterInflow(new D3Q27DensityBCAdapter(rhoLBinflow));
+         denBCAdapterInflow->setSecondaryBcOption(0);
+         D3Q27InteractorPtr inflowInt = D3Q27InteractorPtr(new D3Q27Interactor(geoInflow, grid, denBCAdapterInflow, Interactor3D::SOLID));
+
+         //outflow
+         D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+         D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+         InteractorsHelper intHelper(grid, metisVisitor);
+         //intHelper.addInteractor(sphereInt);
+         intHelper.addInteractor(addWallYminInt);
+         intHelper.addInteractor(addWallZminInt);
+         intHelper.addInteractor(addWallYmaxInt);
+         intHelper.addInteractor(addWallZmaxInt);
+         intHelper.addInteractor(inflowInt);
+         intHelper.addInteractor(outflowInt);
+         intHelper.selectBlocks();
+
+         //domain decomposition for threads
+         PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+         grid->accept(pqPartVisitor);
+
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         Block3DConnectorFactoryPtr factory(new Block3DConnectorFactory());
+         //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
+         //grid->accept(setConnsVisitor);
+
+         ppblocks->update(0);
+         ppblocks.reset();
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         int gl = 3;
+         unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+         double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+         }            
+
+         LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         //BoundaryConditionPtr velocityBC(new VelocityBoundaryCondition(refineLevel+1));
+         BoundaryConditionPtr densityBC(new NonEqDensityBoundaryCondition());
+         //BoundaryConditionPtr noSlipBC(new NoSlipBoundaryCondition());
+
+         //BoundaryConditionPtr velocityBC(new NonReflectingVelocityBoundaryCondition());
+         //BoundaryConditionPtr densityBC(new NonReflectingDensityBoundaryCondition());
+         BoundaryConditionPtr noSlipBC(new HighViscosityNoSlipBoundaryCondition());
+
+         //bcProcessor->addBC(velocityBC);
+         bcProcessor->addBC(densityBC);
+         bcProcessor->addBC(noSlipBC);
+
+         kernel->setBCProcessor(bcProc);
+
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+         intHelper.setBC();
+
+
+         BoundaryConditionBlockVisitor bcVisitor;
+         grid->accept(bcVisitor);
+
+         mu::Parser fctRoh;
+         fctRoh.SetExpr("(x1max-x1)/l*dp*3.0");
+         fctRoh.DefineConst("dp", dp_LB);
+         fctRoh.DefineConst("x1max", d_maxX1);
+         fctRoh.DefineConst("l", d_maxX1-d_minX1);
+
+         //initialization of distributions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor(nuLB, rhoLB);
+         //initVisitor.setVx1(fct);
+         initVisitor.setRho(fctRoh);
+         grid->accept(initVisitor);
+
+         //Postrozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+      }
+      else
+      {
+         UBLOG(logINFO,"SetConnectors - start, id="<<myid);
+
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         //ConnectorFactoryPtr cFactory(new Block3DConnectorFactory());
+         //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, cFactory);
+         grid->accept( setConnsVisitor );
+
+         UBLOG(logINFO,"SetConnectors - end, id="<<myid); 
+      }
+
+      UbSchedulerPtr stepSch(new UbScheduler(outstep));
+      //stepSch->addSchedule(10000, 0, 1000000);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+      //D3Q27MacroscopicQuantitiesPostprocessor ppg(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv,true);
+
+      //InSituVTKPostprocessor isp(grid, stepSch, metafile, conv);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endstep, stepSch, bcProcessor));
+
+      if(myid == 0) 
+         UBLOG(logINFO,"Simulation-start");
+
+      calculation->calculate();
+
+      if(myid == 0) 
+         UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   //struct iNode
+   //{
+   //   int x1, x2, x3;
+   //   LBMReal x1off, x2off, x3off;
+   //};
+
+   //typedef boost::shared_ptr<iNode> iNodePtr;
+
+  
+   //
+
+   //set <vector<int>>  iNodesSetSender00;
+   //vector<double> offs;
+   //map <vector<int>>  iNodesSetSender00;
+
+   //{
+   //   iNodePtr inode1(new iNode());
+   //   inode1->x1 = 1;
+   //   inode1->x3 = 2;
+   //   inode1->x2 = 3;
+   //   inode1->x1off = 0;
+   //   inode1->x2off = 1;
+   //   inode1->x3off = 2;
+
+   //   iNodesSetSender00.insert(inode1);
+   //}
+
+   //{
+   //   iNodePtr inode1(new iNode());
+   //   inode1->x1 = 1;
+   //   inode1->x3 = 2;
+   //   inode1->x2 = 3;
+   //   inode1->x1off = 0;
+   //   inode1->x2off = 1;
+   //   inode1->x3off = 2;
+
+   //   iNodesSetSender00.insert(inode1);
+   //}
+
+   //std::pair<std::set<vector<int>>::iterator, bool> ret;
+
+   //   {
+   //      vector<int> inv;
+   //      inv.push_back(1);
+   //      inv.push_back(2);
+   //      inv.push_back(3);
+   //      inv.push_back(1);
+   //      inv.push_back(2);
+   //      inv.push_back(3);
+   //      ret=iNodesSetSender00.insert(inv);
+   //      if (ret.second==true)
+   //      {
+   //         offs.push_back(0);
+   //         offs.push_back(1);
+   //         offs.push_back(2);
+   //      }
+   //   }
+
+   //         {
+   //            vector<int> inv;
+   //            inv.push_back(1);
+   //            inv.push_back(1);
+   //            inv.push_back(3);
+   //            inv.push_back(1);
+   //            inv.push_back(2);
+   //            inv.push_back(3);
+   //            ret=iNodesSetSender00.insert(inv);
+   //            if (ret.second==true)
+   //            {
+   //               offs.push_back(0);
+   //               offs.push_back(1);
+   //               offs.push_back(2);
+   //            }
+   //         }
+
+   //         return 0;
+
+
+   if ( argv != NULL )
+   {
+      if (argc > 1)
+      {
+         chanel(argv[1]);
+      }
+      else
+      {
+         cout << "Configuration file must be set!: " <<  argv[0] << " <config file>" << endl << std::flush;
+      }
+   }
+}
+
diff --git a/source/Applications/stick/CMakeLists.txt b/source/Applications/stick/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8a8270faa4222ad583aa07ef2d1cb8e10622ba97
--- /dev/null
+++ b/source/Applications/stick/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(stick)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(stick BINARY)
diff --git a/source/Applications/stick/stick.cpp b/source/Applications/stick/stick.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..108b9aa91940d9f4de8ce7500a961d3a3e3fb57f
--- /dev/null
+++ b/source/Applications/stick/stick.cpp
@@ -0,0 +1,232 @@
+#include <iostream>
+#include <string>
+
+#include <boost/pointer_cast.hpp>
+
+#include "vfluids.h"
+
+using namespace std;
+
+
+
+void main()
+{
+
+   try
+   {
+      string machine = QUOTEME(CAB_MACHINE);
+      string pathname = "d:/temp/stick"; 
+      int numOfThreads = 4;
+      double availMem = 10e9;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      double dx = 1;
+
+      const int blocknx1 = 10;
+      const int blocknx2 = 10;
+      const int blocknx3 = 10;
+
+      const int gridNx1 = 60;
+      const int gridNx2 = 1;
+      const int gridNx3 = 8;
+
+      double L1 = gridNx1*blocknx1;
+      double L2, L3;
+      L2 = gridNx2*blocknx1;
+      L3 = gridNx3*blocknx1;
+
+      LBMReal radius = 1.0*dx;
+      LBMReal uLB = 0.07;
+      LBMReal Re = 1000.0;
+      LBMReal rhoLB = 0.0;
+      LBMReal nueLB = (uLB*1.0*radius)/Re;
+
+      LBMUnitConverterPtr conv = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      Grid3DPtr grid(new Grid3D(comm));
+      grid->setDeltaX(dx);
+      grid->setBlockNX(blocknx1, blocknx2, blocknx3);
+      grid->setPeriodicX1(false);
+      grid->setPeriodicX2(true);
+      grid->setPeriodicX3(false);
+
+      const int baseLevel = 0;
+      const int refineLevel = 0;
+
+      //bounding box
+      double d_minX1 = 0.0;
+      double d_minX2 = 0.0;
+      double d_minX3 = 0.0;
+
+      double d_maxX1 = L1;
+      double d_maxX2 = L2;
+      double d_maxX3 = L3;
+
+      double blockLength = blocknx1*dx;
+
+      if(myid ==0)
+      {
+         UBLOG(logINFO,"Parameters:");
+         UBLOG(logINFO,"uLB = " << uLB );
+         UBLOG(logINFO,"rhoLB = " << rhoLB );
+         UBLOG(logINFO,"nueLB = " << nueLB );
+         UBLOG(logINFO,"Re = " << Re );
+         UBLOG(logINFO,"dx = " << dx );
+         UBLOG(logINFO,"number of levels = " << refineLevel+1 );
+         UBLOG(logINFO,"numOfThreads = " << numOfThreads );
+         UBLOG(logINFO,"Preprozess - start");
+      }
+
+      GbObject3DPtr gridCube(new GbCuboid3D(d_minX1, d_minX2, d_minX3, d_maxX1, d_maxX2, d_maxX3));
+      if(myid ==0) GbSystem3D::writeGeoObject(gridCube.get(),pathname + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance()); 
+
+      GenBlocksGridVisitor genBlocks(gridCube);
+      grid->accept(genBlocks);
+
+      //cylinder
+      //GbObject3DPtr cylinder(new GbCylinder3D(L1/4.0, -2.0, radius, L1/4.0, L2+2.0, radius, radius));
+      //GbSystem3D::writeGeoObject(cylinder.get(),pathname + "/geo/cylinder", WbWriterVtkXmlBinary::getInstance());
+
+      GbCuboid3DPtr stick (new GbCuboid3D(L1/4.0, -2.0, 0.0, L1/4.0+150.0, L2+2.0, radius*3.0));
+      if(myid == 0) GbSystem3D::writeGeoObject(stick.get(), pathname+"/geo/stick", WbWriterVtkXmlASCII::getInstance());
+
+      //walls
+      GbCuboid3DPtr addWallZmin (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_minX3));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+
+      GbCuboid3DPtr addWallZmax (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_maxX3, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+
+      //inflow
+      GbCuboid3DPtr geoInflow (new GbCuboid3D(d_minX1-4.0*blockLength, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_minX1, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoInflow.get(), pathname+"/geo/geoInflow", WbWriterVtkXmlASCII::getInstance());
+
+      //outflow
+      GbCuboid3DPtr geoOutflow (new GbCuboid3D(d_maxX1, d_minX2-4.0*blockLength, d_minX3-4.0*blockLength, d_maxX1+4.0*blockLength, d_maxX2+4.0*blockLength, d_maxX3+4.0*blockLength));
+      if(myid == 0) GbSystem3D::writeGeoObject(geoOutflow.get(), pathname+"/geo/geoOutflow", WbWriterVtkXmlASCII::getInstance());
+
+      BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname + "/grid/blocks", WbWriterVtkXmlBinary::getInstance(), comm));
+
+
+      //cylinder
+      int bbOption = 1; //0=simple Bounce Back, 1=quadr. BB
+      D3Q27BoundaryConditionAdapterPtr noSlip(new D3Q27NoSlipBCAdapter(bbOption));
+      D3Q27InteractorPtr cylinderInt = D3Q27InteractorPtr ( new D3Q27Interactor(stick, grid, noSlip,Interactor3D::SOLID));
+
+      //walls
+      D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, noSlip,Interactor3D::SOLID));
+      D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, noSlip,Interactor3D::SOLID));
+
+      mu::Parser fct;
+      fct.SetExpr("U");
+      fct.DefineConst("U", uLB);
+
+      //inflow
+      D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter (true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST));
+      velBCAdapter->setSecondaryBcOption(2);
+      D3Q27InteractorPtr inflowInt  = D3Q27InteractorPtr( new D3Q27Interactor(geoInflow, grid, velBCAdapter, Interactor3D::SOLID));
+
+      //outflow
+      D3Q27BoundaryConditionAdapterPtr denBCAdapter(new D3Q27DensityBCAdapter(rhoLB));
+      D3Q27InteractorPtr outflowInt = D3Q27InteractorPtr( new D3Q27Interactor(geoOutflow, grid, denBCAdapter,Interactor3D::SOLID));
+
+      Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));
+      InteractorsHelper intHelper(grid, metisVisitor);
+      intHelper.addInteractor(cylinderInt);
+      intHelper.addInteractor(addWallZminInt);
+      intHelper.addInteractor(addWallZmaxInt);
+      intHelper.addInteractor(inflowInt);
+      intHelper.addInteractor(outflowInt);
+      intHelper.selectBlocks();
+
+      //domain decomposition for threads
+      PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+      grid->accept(pqPartVisitor);
+
+      ppblocks->update(0);
+      ppblocks.reset();
+
+      //set connectors
+      D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+      D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+      grid->accept( setConnsVisitor );
+
+      unsigned long nob = grid->getNumberOfBlocks();
+      int gl = 3;
+      unsigned long nod = nob * (blocknx1+gl) * (blocknx2+gl) * (blocknx3+gl);
+
+      double needMemAll  = double(nod*(27*sizeof(double) + sizeof(int) + sizeof(float)*4));
+      double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"Number of blocks = " << nob);
+         UBLOG(logINFO,"Number of nodes  = " << nod);
+         UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+         UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+         UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+      }            
+
+      LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(blocknx1, blocknx2, blocknx3, LBMKernelETD3Q27CCLB::NORMAL));
+
+      BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+      kernel->setBCProcessor(bcProc);
+
+      SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem);
+      grid->accept(kernelVisitor);
+
+      intHelper.setBC();
+
+      //initialization of distributions
+      D3Q27ETInitDistributionsBlockVisitor initVisitor(nueLB, rhoLB);
+      initVisitor.setVx1(fct);
+      grid->accept(initVisitor);
+
+      //Postrozess
+      UbSchedulerPtr geoSch(new UbScheduler(1));
+      D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+         new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv, true));
+      ppgeo->update(0);
+      ppgeo.reset();
+
+      if(myid == 0) UBLOG(logINFO,"Preprozess - end"); 
+
+      UbSchedulerPtr stepSch(new UbScheduler(10000));
+      //stepSch->addSchedule(1000, 0, 1000000);
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, stepSch, pathname, WbWriterVtkXmlBinary::getInstance(), conv);
+
+      //InSituVTKPostprocessor isp(grid, stepSch, "d:/Data/insituDemo/metafile.csv", conv);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 30, 100));
+      NUPSCounterPostprocessor npr(grid, nupsSch, pathname + "/results/nups.txt", comm);
+
+
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, 1000000, stepSch));
+
+      if(myid == 0) 
+         UBLOG(logINFO,"Simulation-start");
+
+      calculation->calculate();
+
+      if(myid == 0) 
+         UBLOG(logINFO,"Simulation-end");
+
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+
+
diff --git a/source/Applications/town/CMakeLists.txt b/source/Applications/town/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8cb7da8a658ce538b6f7edc8d83183d0912b811b
--- /dev/null
+++ b/source/Applications/town/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(town)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(town BINARY)
diff --git a/source/Applications/town/town.cpp b/source/Applications/town/town.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0aa0f289ccb6a229ab29d7b76fb5ba15b8656062
--- /dev/null
+++ b/source/Applications/town/town.cpp
@@ -0,0 +1,464 @@
+#include <iostream>
+#include <string>
+#include <math.h> 
+
+#include <vfluids.h>
+
+using namespace std;
+
+void run(const char *cstr1, const char *cstr2)
+{
+   try
+   {
+      string pathname; 
+      string pathGeo;
+      string pathLog;
+      int numOfThreads = 1;
+      bool logfile = false;
+      stringstream logFilename;
+      double availMem = 0;
+
+      CommunicatorPtr comm = MPICommunicator::getInstance();
+      int myid = comm->getProcessID();
+
+      string machine = string(cstr1);
+
+      if(machine == "my") 
+      {
+         //Sleep(30000);
+         pathname = "d:/temp/town";
+         pathGeo = "d:/Data/town";
+         pathLog = "d:/temp/town";
+         numOfThreads = 1;
+         logfile = false;
+         availMem = 15.0e9;
+      }
+      else if(machine == "Ludwig")      
+      {
+         pathname = "/work/koskuche/town";
+         pathGeo = "/home/koskuche/data/town";
+         pathLog = pathname;
+         numOfThreads = 8;
+         availMem = 12.0e9;///8*numOfThreads;
+         logfile = true;
+      }
+      else if(machine == "HLRS")      
+      {
+         pathname = "/univ_1/ws1/ws/xrmkuchr-plate3-0";
+         pathGeo = "/zhome/academic/HLRS/xrm/xrmkuchr/data/plate";
+         pathLog = "/zhome/academic/HLRS/xrm/xrmkuchr/work/plate";
+         numOfThreads = 16;
+         availMem = 2.0e9;
+         logfile = true;
+      }
+      else if(machine == "HLRN")      
+      {
+         pathname = "/gfs1/work/niivfcpu/scratch/plateEx";
+         pathGeo = "/gfs1/work/niivfcpu/data/plate";
+         pathLog = pathname;
+         numOfThreads = 24;
+         availMem = 64.0e9/24.0*numOfThreads;
+         logfile = true;
+      }
+      else throw UbException(UB_EXARGS, "unknown CAB_MACHINE");
+
+#if defined(__unix__)
+      if (myid==0) 
+      {
+         const char* str = pathLog.c_str();
+         int status=mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      }
+#endif 
+
+      if(myid == 0 && logfile)
+      {
+         //UbLog::reportingLevel() = logDEBUG5;
+         logFilename <<  pathLog + "/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+"_"+UbSystem::toString(myid)+".txt";
+         UbLog::output_policy::setStream(logFilename.str());
+      }
+
+      if(myid==0) UBLOG(logINFO,"Testcase town");
+
+      //string townFilename = pathGeo + "/Manhattan.stl";
+      string townFilename = pathGeo + "/town.stl"; 
+
+
+      ///////////////Knotenabmessungen:
+      int blocknx[3], nx[3];
+      blocknx[0] = 8;
+      blocknx[1] = 8;
+      blocknx[2] = 8;
+
+      nx[0] = 12;
+      nx[1] = 12;
+      nx[2] = 3;
+
+      int baseLevel   = 0;
+      int refineLevel = 2;
+
+      LBMUnitConverterPtr unitConverter = LBMUnitConverterPtr(new LBMUnitConverter());
+
+      //////////////////////////////////////////////////////////////////////////
+      //physik
+      //////////////////////////////////////////////////////////////////////////
+      LBMReal uLB = 0.05;
+      LBMReal rhoLB = 0.0;
+      LBMReal nuLB = 1e-5;
+
+      Grid3DPtr grid(new Grid3D(comm));
+
+      //////////////////////////////////////////////////////////////////////////
+      //restart
+      UbSchedulerPtr rSch(new UbScheduler(1000,1000,10000000));
+      RestartPostprocessor rp(grid, rSch, comm, pathname, RestartPostprocessor::BINARY);
+      //////////////////////////////////////////////////////////////////////////
+
+      if (grid->getTimeStep() == 0)
+      {
+
+         if(myid==0) UBLOG(logINFO,"Neustart..");
+
+         //////////////////////////////////////////////////////////////////////////
+         //town
+         GbTriFaceMesh3DPtr town(GbTriFaceMesh3DCreator::getInstance()->readMeshFromSTLFile(townFilename, "Netz"));
+         if(myid == 0) GbSystem3D::writeGeoObject( town.get(), pathname+"/geo/town", WbWriterVtkXmlBinary::getInstance() );
+         //////////////////////////////////////////////////////////////////////////
+
+         //double cdx = 0.8;
+         double cdx = town->getX3Maximum() / (double)(nx[2] * blocknx[2]);
+         double fdx = cdx/double(1<<refineLevel);
+ 
+         double blockLengthx = blocknx[0]*cdx; //geowerte
+
+         double geoLength[] = { nx[0] * blockLengthx, nx[1] * blockLengthx, nx[2] * blockLengthx };
+
+         double originX1 = town->getX1Minimum();
+         double originX2 = town->getX2Minimum();
+         double originX3 = town->getX3Minimum();
+
+
+         bool periodicx1 = true;
+         bool periodicx2 = true;
+         bool periodicx3 = false;
+
+         //bounding box
+         double g_minX1 = originX1-3.0*blockLengthx;
+         double g_minX2 = originX2-3.0*blockLengthx;
+         double g_minX3 = originX3;
+
+         double g_maxX1 = originX1 + geoLength[0]+3.0*blockLengthx;
+         double g_maxX2 = originX2 + geoLength[1]+1.0*blockLengthx;
+         double g_maxX3 = originX3 + geoLength[2]+2.0*blockLengthx;
+
+         //double g_maxX1 = town->getX1Maximum()+blockLengthx;
+         //double g_maxX2 = town->getX2Maximum()+2.0*blockLengthx;
+         //double g_maxX3 = town->getX3Maximum()+2.0*blockLengthx;
+
+
+         //set grid
+         grid->setDeltaX(cdx);
+         grid->setBlockNX(blocknx[0], blocknx[1], blocknx[2]);
+         grid->setPeriodicX1(periodicx1);
+         grid->setPeriodicX2(periodicx2);
+         grid->setPeriodicX3(periodicx3);
+
+         GbObject3DPtr gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3));
+         if(myid == 0) GbSystem3D::writeGeoObject(gridCube.get(), pathname+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance());
+
+         GenBlocksGridVisitor genBlocks(gridCube);
+         grid->accept(genBlocks);
+
+
+         //////////////////////////////////////////////////////////////////////////
+         if(myid == 0)
+         {
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* Parameters                            *");
+            //UBLOG(logINFO, "* Re            ="<<Re);
+            UBLOG(logINFO, "* nuLB          ="<<nuLB);
+            UBLOG(logINFO, "* uLB           ="<<uLB);
+            UBLOG(logINFO, "* cdx           ="<<cdx);
+            UBLOG(logINFO, "* fdx           ="<<fdx);
+            UBLOG(logINFO, "* blocknx1/2/3  ="<<blocknx[0]<<"/"<<blocknx[1]<<"/"<<blocknx[2]);
+            UBLOG(logINFO, "* x1Periodic    ="<<periodicx1);
+            UBLOG(logINFO, "* x2Periodic    ="<<periodicx2);
+            UBLOG(logINFO, "* x3Periodic    ="<<periodicx3);
+            UBLOG(logINFO, "* number of levels  ="<<refineLevel+1);
+            UBLOG(logINFO, "* path          ="<<pathname);
+
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "* number of threads    ="<<numOfThreads);
+            UBLOG(logINFO, "* number of processes  ="<<comm->getNumberOfProcesses());
+            UBLOG(logINFO, "*****************************************");
+            UBLOG(logINFO, "*****************************************");     
+         }
+         //////////////////////////////////////////////////////////////////////////
+
+
+         //////////////////////////////////////////////////////////////////////////
+         //refinement
+
+         /////////////////////////////////////////////////
+         ///interactor
+         int bbOption1 = 1; //0=simple Bounce Back, 1=quadr. BB
+         D3Q27BoundaryConditionAdapterPtr bcNoSlip(new D3Q27NoSlipBCAdapter(bbOption1));
+         D3Q27TriFaceMeshInteractorPtr triTownInteractor(new D3Q27TriFaceMeshInteractor(town, grid, bcNoSlip, Interactor3D::SOLID));
+
+         GbCuboid3DPtr addWallZmax(new GbCuboid3D(g_minX1-blockLengthx, g_minX2-blockLengthx, g_maxX3, g_maxX1+blockLengthx, g_maxX2+blockLengthx, g_maxX3+blockLengthx));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr velBCInteractor(new D3Q27Interactor(addWallZmax, grid, Interactor3D::SOLID));
+
+         double raiseVelSteps = 0;
+         vector<D3Q27BCFunction> velcX2BCs, dummy;
+
+         mu::Parser inflowProfile;
+         inflowProfile.SetExpr("uLB");
+         inflowProfile.DefineConst("uLB", uLB);
+         velcX2BCs.push_back(D3Q27BCFunction(inflowProfile, raiseVelSteps, D3Q27BCFunction::INFCONST));
+
+         D3Q27BoundaryConditionAdapterPtr velBCAdapter(new D3Q27VelocityBCAdapter(dummy, velcX2BCs, dummy));
+         velBCInteractor->addBCAdapter(velBCAdapter);
+
+         GbCuboid3DPtr addWallZmin(new GbCuboid3D(g_minX1-blockLengthx, g_minX2-blockLengthx, g_minX3-blockLengthx, g_maxX1+blockLengthx, g_maxX2+blockLengthx, g_minX3));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallZmin.get(), pathname+"/geo/addWallZmin", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr addWallZminInt(new D3Q27Interactor(addWallZmin, grid, bcNoSlip, Interactor3D::SOLID));
+
+         //GbCuboid3DPtr addWallZmax(new GbCuboid3D(g_minX1-blockLengthx, g_minX2-blockLengthx, g_maxX3, g_maxX1+blockLengthx, g_maxX2+blockLengthx, g_maxX3+blockLengthx));
+         //if (myid == 0) GbSystem3D::writeGeoObject(addWallZmax.get(), pathname+"/geo/addWallZmax", WbWriterVtkXmlASCII::getInstance());
+         //D3Q27InteractorPtr addWallZmaxInt(new D3Q27Interactor(addWallZmax, grid, bcNoSlip, Interactor3D::SOLID));
+
+         GbCuboid3DPtr addWallYmin(new GbCuboid3D(g_minX1-blockLengthx, g_minX2-blockLengthx, g_minX3-blockLengthx, g_maxX1+blockLengthx, g_minX2, g_maxX3+blockLengthx));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallYmin.get(), pathname+"/geo/addWallYmin", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr addWallYminInt(new D3Q27Interactor(addWallYmin, grid, bcNoSlip, Interactor3D::SOLID));
+
+         GbCuboid3DPtr addWallYmax(new GbCuboid3D(g_minX1-blockLengthx, g_minX2-blockLengthx, g_maxX3, g_maxX1+blockLengthx, g_maxX2+blockLengthx, g_maxX3+blockLengthx));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallYmax.get(), pathname+"/geo/addWallYmax", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr addWallYmaxInt(new D3Q27Interactor(addWallYmax, grid, bcNoSlip, Interactor3D::SOLID));
+
+         GbCuboid3DPtr addWallXmin(new GbCuboid3D(g_minX1-blockLengthx, g_minX2-blockLengthx, g_minX3-blockLengthx, g_minX1, g_maxX2+blockLengthx, g_maxX3+blockLengthx));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallXmin.get(), pathname+"/geo/addWallXmin", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr addWallXminInt(new D3Q27Interactor(addWallXmin, grid, bcNoSlip, Interactor3D::SOLID));
+
+         GbCuboid3DPtr addWallXmax(new GbCuboid3D(g_maxX1, g_minX2-blockLengthx, g_minX3-blockLengthx, g_maxX1+blockLengthx, g_maxX2+blockLengthx, g_maxX3+blockLengthx));
+         if (myid == 0) GbSystem3D::writeGeoObject(addWallXmax.get(), pathname+"/geo/addWallXmax", WbWriterVtkXmlASCII::getInstance());
+         D3Q27InteractorPtr addWallXmaxInt(new D3Q27Interactor(addWallXmax, grid, bcNoSlip, Interactor3D::SOLID));
+
+         GbCuboid3DPtr refineTownBox(new GbCuboid3D(town->getX1Minimum(), town->getX2Minimum(), town->getX3Minimum(), town->getX1Maximum(), town->getX2Maximum(), town->getX3Maximum()));
+         if (myid == 0) GbSystem3D::writeGeoObject(refineTownBox.get(), pathname + "/geo/refineTownBox", WbWriterVtkXmlASCII::getInstance());
+
+         if (refineLevel > 0)
+         {
+            if(myid == 0) UBLOG(logINFO,"Refinement - start");	
+            //RefineAroundGbObjectHelper refineHelper(grid, refineLevel, boost::dynamic_pointer_cast<D3Q27TriFaceMeshInteractor>(triTownInteractor), 0.0, 3.0, comm);
+            RefineCrossAndInsideGbObjectHelper refineHelper(grid, refineLevel);
+            //refineHelper.addGbObject(refineTownBox, refineLevel);
+            refineHelper.addGbObject(town, refineLevel);
+            refineHelper.refine();
+            if(myid == 0) UBLOG(logINFO,"Refinement - end");	
+         }
+
+         //Grid3D::BlockIDMap bmap = grid->getBlockIDs();
+         //bmap.clear();
+         //(grid->getBlockIDs()).clear();
+         //grid->deleteBlockIDs();
+
+         //RenumberBlockVisitor renumber;
+         //grid->accept(renumber);
+
+
+         ////////////////////////////////////////////
+         //METIS
+         Grid3DVisitorPtr metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::B));	
+
+         ////////////////////////////////////////////
+         /////delete solid blocks
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - start");
+         InteractorsHelper intHelper(grid, metisVisitor);
+         //intHelper.addInteractor(triTownInteractor);
+         intHelper.addInteractor(velBCInteractor);
+         intHelper.addInteractor(addWallZminInt);
+         //intHelper.addInteractor(addWallZmaxInt);
+         //intHelper.addInteractor(addWallYminInt);
+         //intHelper.addInteractor(addWallYmaxInt);
+         //intHelper.addInteractor(addWallXminInt);
+         //intHelper.addInteractor(addWallXmaxInt);
+         intHelper.selectBlocks();
+         if(myid == 0) UBLOG(logINFO,"deleteSolidBlocks - end");	 
+         //////////////////////////////////////
+
+         //grid->accept(renumber);
+
+         //if (myid == 0)
+         {
+            UBLOG(logINFO, "Write blocks - start");
+            BlocksPostprocessorPtr ppblocks(new BlocksPostprocessor(grid, UbSchedulerPtr(new UbScheduler(1)), pathname, WbWriterVtkXmlBinary::getInstance(), comm));
+            ppblocks->update(0);
+            UBLOG(logINFO, "Write blocks - end");
+         }
+
+         
+
+
+         //domain decomposition for threads
+         if(numOfThreads > 1)
+         {
+            PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+            grid->accept(pqPartVisitor);
+         }
+
+
+         unsigned long nob = grid->getNumberOfBlocks();
+         unsigned long nod = nob * blocknx[0]*blocknx[1]*blocknx[2];
+         unsigned long nod_real = nob * (blocknx[0]+3)*(blocknx[1]+3)*(blocknx[2]+3);
+         unsigned long nodb = (blocknx[0]) * (blocknx[1]) * (blocknx[2]);
+
+         double needMemAll  = double(nod_real*(27*sizeof(double) + sizeof(int)));
+         double needMem  = needMemAll / double(comm->getNumberOfProcesses());
+         
+         double nup = 0; 
+
+         if(myid == 0)
+         {
+            UBLOG(logINFO,"Number of blocks = " << nob);
+            UBLOG(logINFO,"Number of nodes  = " << nod);
+            int minInitLevel = grid->getCoarsestInitializedLevel();
+            int maxInitLevel = grid->getFinestInitializedLevel();
+            for(int level = minInitLevel; level<=maxInitLevel; level++)
+            {
+               int nobl = grid->getNumberOfBlocks(level);
+               UBLOG(logINFO,"Number of blocks for level " << level <<" = " << nobl);
+               UBLOG(logINFO,"Number of nodes for level " << level <<" = " << nobl*nodb);
+               nup += nobl*nodb*double(1<<level); 
+            }
+            UBLOG(logINFO,"Hypothetically time for calculation step for 120 nodes  = " << nup/6.0e5/(120*8)  << " s");
+            UBLOG(logINFO,"Necessary memory  = " << needMemAll  << " bytes");
+            UBLOG(logINFO,"Necessary memory per process = " << needMem  << " bytes");
+            UBLOG(logINFO,"Available memory per process = " << availMem << " bytes");
+            UBLOG(logINFO,"Available memory per node/8.0 = " << (availMem/8.0) << " bytes");
+         }
+         //////////////////////////////////////////
+         //set connectors
+         if(myid == 0) UBLOG(logINFO,"set connectors - start");
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+         if(myid == 0) UBLOG(logINFO,"set connectors - end");
+
+         ////////////////////////////
+         LBMKernel3DPtr kernel;
+         kernel = LBMKernel3DPtr(new LBMKernelETD3Q27CCLB(blocknx[0], blocknx[1], blocknx[2], LBMKernelETD3Q27CCLB::NORMAL));
+
+         //mu::Parser fctForcingX2;
+         //fctForcingX2.SetExpr("Fx2*dx");
+         //fctForcingX2.DefineConst("Fx2", 5e-6);
+
+         //kernel->setForcingX2(fctForcingX2);
+         //kernel->setWithForcing(true);
+
+         BCProcessorPtr bcProc(new D3Q27ETBCProcessor());
+         //BCProcessorPtr bcProc(new D3Q27ETForThinWallBCProcessor());
+         kernel->setBCProcessor(bcProc);
+         SetKernelBlockVisitor kernelVisitor(kernel, nuLB, availMem, needMem);
+         grid->accept(kernelVisitor);
+         //////////////////////////////////
+         //undef nodes
+         if (refineLevel > 0)
+         {
+            D3Q27SetUndefinedNodesBlockVisitor undefNodesVisitor;
+            grid->accept(undefNodesVisitor);
+         }
+
+
+         intHelper.setBC();
+
+         //initialization of decompositions
+         D3Q27ETInitDistributionsBlockVisitor initVisitor( nuLB,rhoLB);
+         initVisitor.setVx2(uLB);
+         grid->accept(initVisitor);
+
+         //Postprozess
+         UbSchedulerPtr geoSch(new UbScheduler(1));
+         D3Q27MacroscopicQuantitiesPostprocessorPtr ppgeo(
+            new D3Q27MacroscopicQuantitiesPostprocessor(grid, geoSch, pathname, WbWriterVtkXmlBinary::getInstance(), 
+            unitConverter, true));
+         ppgeo->update(0);
+         ppgeo.reset();
+         geoSch.reset();
+
+         if(myid == 0) UBLOG(logINFO,"Preprozess - end");      
+      }
+      else
+      {
+         //domain decomposition for threads
+         if(numOfThreads > 1)
+         {
+            PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads);
+            grid->accept(pqPartVisitor);
+         }
+         //set connectors
+         D3Q27InterpolationProcessorPtr iProcessor(new D3Q27IncompressibleOffsetInterpolationProcessor());
+         D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
+         grid->accept( setConnsVisitor );
+
+         if(myid == 0) UBLOG(logINFO,"Restart - end"); 
+      }
+      UbSchedulerPtr visSch(new UbScheduler());
+      visSch->addSchedule(1,0,3);
+      //visSch->addSchedule(100,100,1000);
+      //visSch->addSchedule(1000,1000,5000);
+      //visSch->addSchedule(5000,5000,100000);
+      //visSch->addSchedule(100000,100000,10000000);
+
+      visSch->addSchedule(1000,1000,10000000);
+
+      D3Q27MacroscopicQuantitiesPostprocessor pp(grid, visSch, pathname, WbWriterVtkXmlBinary::getInstance(), unitConverter);
+
+      UbSchedulerPtr nupsSch(new UbScheduler(10, 10, 30));
+      nupsSch->addSchedule(500,500,1e6);
+      NUPSCounterPostprocessor npr(grid, nupsSch, numOfThreads, comm);
+
+      //UbSchedulerPtr emSch(new UbScheduler(100));
+      //EmergencyExitPostprocessor empr(grid, emSch, pathname, RestartPostprocessorPtr(&rp), comm);
+
+      if(myid == 0)
+      {
+         UBLOG(logINFO,"PID = " << myid << " Total Physical Memory (RAM): " << Utilities::getTotalPhysMem());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used: " << Utilities::getPhysMemUsed());
+         UBLOG(logINFO,"PID = " << myid << " Physical Memory currently used by current process: " << Utilities::getPhysMemUsedByMe());
+      }
+
+      string lastStep = "1000000";// string(cstr2);
+      double endTime = UbSystem::stringTo<double>(lastStep);
+      CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, visSch));
+      if(myid == 0) UBLOG(logINFO,"Simulation-start");
+      calculation->calculate();
+      if(myid == 0) UBLOG(logINFO,"Simulation-end");
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+   if (argc == 1)
+   {
+      cout<<"Command line argument isn't specified!"<<endl;
+      cout<<"plate2 <machine name>"<<endl;
+      return 1;
+   }
+   run(argv[1], argv[2]);
+
+   return 0;
+}
+
diff --git a/source/Applications/vfscript/CMakeLists.txt b/source/Applications/vfscript/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f7a0bf1d28fc8d54d02fe8717598806733a77110
--- /dev/null
+++ b/source/Applications/vfscript/CMakeLists.txt
@@ -0,0 +1,29 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(vfscript)
+
+INCLUDE(${SOURCE_ROOT}/core/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES core)
+
+#YAML support
+SET(LINK_LIBRARY optimized ${YAML_RELEASE_LIBRARY} debug ${YAML_DEBUG_LIBRARY})
+SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(vfscript BINARY)
diff --git a/source/Applications/vfscript/input.json b/source/Applications/vfscript/input.json
new file mode 100644
index 0000000000000000000000000000000000000000..28aa5a4ba256493db73ed7bf707e5b1c1c4259bf
--- /dev/null
+++ b/source/Applications/vfscript/input.json
@@ -0,0 +1,35 @@
+{"Simulation": {
+   "GeoObjectList":
+   ["GeoObject" : { 
+      "ID": "channel",
+      "GeoType": "GbCuboid3D",
+      "Point1": [0.0, 0.0, 0.0],
+      "Point2": [5.0, 5.0, 5.0],
+      "Properties": {
+         "Physics": {
+            "Rho": 1.0,
+            "Vx1": 0.001
+         },
+         "Numerical":{
+            "BC": {
+               "Type": "NoSlip",
+               "State": "Fluid",
+               "SecondaryBcOptions": "SimpleBounceBack"
+            }
+         }
+      }
+    "GeoObject" : { 
+      "ID": "sphere",
+      "GeoType": "GbSphere3D",
+      "Center": [2.5, 2.5, 2.5], 
+      "Radius": 1.5,
+       "Properties": {
+         "Numerical":{
+            "BC": {
+               "Type": "NoSlip",
+               "State": "Solid",
+               "SecondaryBcOptions": "SimpleBounceBack"
+            }
+         }
+      }]      
+}}
\ No newline at end of file
diff --git a/source/Applications/vfscript/sphere.yaml b/source/Applications/vfscript/sphere.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..436cd633fe3b7143c96718c93c97d1cb84690d73
--- /dev/null
+++ b/source/Applications/vfscript/sphere.yaml
@@ -0,0 +1,37 @@
+#flow around sphere
+
+SimulationParametrs:
+   OutputPath: c:\temp\sphere\out
+   Steps: 1000
+   Output: 100
+
+Grid:
+ NumberOfThreads: 4
+ Block: [10, 10, 10]
+ BlockSize: [1.0, 1.0, 1.0]
+ RefineLevel: 1
+ 
+GeoObjects: 
+ - ID: channel
+   GeoType: GbCuboid3D,
+   Point1: [0.0, 0.0, 0.0]
+   Point2: [5.0, 5.0, 5.0]
+   Properties: 
+    Physics: 
+     Rho: 1.0
+     Vx1: 0.001
+    Numerical:
+     BC: 
+      Type: NoSlip
+      State: Fluid
+      SecondaryBcOptions: SimpleBounceBack
+ - ID: sphere
+   GeoType: GbSphere3D
+   Center: [2.5, 2.5, 2.5] 
+   Radius: 1.5
+   Properties:
+    Numerical:
+     BC:
+      Type: NoSlip
+      State: Solid
+      SecondaryBcOptions: SecondOrderBounceBack           
diff --git a/source/Applications/vfscript/vfscript.cpp b/source/Applications/vfscript/vfscript.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e7322b73f0807c0f8891e6706545b605b05d7fb9
--- /dev/null
+++ b/source/Applications/vfscript/vfscript.cpp
@@ -0,0 +1,120 @@
+#include <iostream>
+#include <string>
+
+#include "numerics/geometry3d/CoordinateTransformation3D.h"
+#include "Grid3D.h"
+#include "GenBlocksGridVisitor.h"
+#include "numerics/geometry3d/GbSystem3D.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include "numerics/geometry3d/GbCylinder3D.h"
+#include <numerics/geometry3d/GbSphere3D.h>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/writer/WbWriterVtkXmlBinary.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "RefineInterGbObjectsVisitor.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "SetKernelBlockVisitor.h"
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "MPICommunicator.h"
+#include "D3Q27ETBCProcessor.h"
+#include "SimulationParameters.h"
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "NullCommunicator.h"
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "CalculationManager.h"
+#include "PQueuePartitioningGridVisitor.h"
+#include "MetisPartitioningGridVisitor.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "StringUtil.hpp"
+//#include "rapidjson/document.h"		// rapidjson's DOM-style API
+//#include "rapidjson/filestream.h"
+
+#include <fstream>
+#include "yaml-cpp/yaml.h"
+
+using namespace std;
+
+
+void run(const char *istr)
+{
+   try
+   {
+      //// Prepare reader and input stream.
+      //rapidjson::Reader reader;
+      ////rapidjson::Document reader;
+      //FILE* fp;
+      //fp = fopen(istr, "r");
+      //rapidjson::FileStream is(fp);
+
+      //rapidjson::Document document;	// Default template parameter uses UTF8 and MemoryPoolAllocator.
+
+      //if (document.ParseStream<0>(is).HasParseError())
+      //{
+      //   //UBLOG(logINFO,"JSON parcing is fail" );
+      //   fprintf(stderr, "\nError(%u): %s\n", (unsigned)document.GetErrorOffset(), document.GetParseError());
+      //   return;
+      //}
+
+      //fclose(fp);
+
+      std::ifstream fin(istr);
+      YAML::Parser parser(fin);
+      YAML::Node doc;
+      parser.GetNextDocument(doc);
+
+      if(doc.FindValue("GeoObjects"))
+      {
+         const YAML::Node& geoObjects = doc["GeoObjects"];
+         string id;
+         for(unsigned i=0;i<geoObjects.size();i++)
+         {
+            geoObjects[i]["ID"] >> id;
+            std::cout << id << "\n";
+         }
+      }
+
+   }
+   catch(YAML::ParserException& e) {
+      std::cout << e.what() << "\n";
+   }
+   catch(std::exception& e)
+   {
+      cerr << e.what() << endl << flush;
+   }
+   catch(std::string& s)
+   {
+      cerr << s << endl;
+   }
+   catch(...)
+   {
+      cerr << "unknown exception" << endl;
+   }
+
+}
+int main(int argc, char* argv[])
+{
+   if ( argv != NULL )
+   {
+      if (argc > 1)
+      {
+         run(argv[1]);
+      }
+      else
+      {
+         cout << "Input file must be set!: " <<  argv[0] << " <input file>" << endl << std::flush;
+      }
+   }
+
+   return 0;
+}
+
diff --git a/source/CMake/CMakeCABMacros.txt b/source/CMake/CMakeCABMacros.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dccb05a5b9a5e07f0fbf98c31687dc00e854b12a
--- /dev/null
+++ b/source/CMake/CMakeCABMacros.txt
@@ -0,0 +1,391 @@
+###############################################################
+# Aktivieren von IF(ARG)...ELSE()...ENDIF() in CMake
+###############################################################
+SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 1)
+
+###############################################################################################################
+## Flags ruecksetzen
+###############################################################################################################
+SET(CAB_ADDTIONAL_COMPILER_FLAGS)
+#because of the fact that CMake does not support COMPILER_FLAGS_<CONFIG> right know we cannot use these options
+#SET(CAB_ADDTIONAL_COMPILER_FLAGS_DEBUG)
+#SET(CAB_ADDTIONAL_COMPILER_FLAGS_RELEASE)
+
+SET(CAB_ADDITIONAL_LINK_FLAGS)
+SET(CAB_ADDITIONAL_LINK_FLAGS_DEBUG)
+SET(CAB_ADDITIONAL_LINK_FLAGS_RELEASE)
+
+SET(CAB_ADDITIONAL_LINK_LIBRARIES)
+
+
+###############################################################
+# SOURCE_DIR variable wird beim einbinden automatisch gesetzt - ebenso das include dir!!!
+# SOURCE_DIR wird dem Projekt als Standardincludepfad hinzugefuegt
+###############################################################
+#CMakeCABMacros.txt liegt direkt im source-Ordner -> pfad == SOURCE_ROOT
+GET_FILENAME_COMPONENT( SOURCE_ROOT  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+STRING(REGEX REPLACE "(.*)/CMake" "\\1" SOURCE_ROOT "${SOURCE_ROOT}" )
+INCLUDE_DIRECTORIES(${SOURCE_ROOT})
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DSOURCE_ROOT=${SOURCE_ROOT} )
+
+###############################################################
+# hostename ermitteln -> CAB_MACHINE
+###############################################################
+IF(NOT CAB_MACHINE)
+   SET(CAB_MACHINE $ENV{CAB_MACHINE})
+
+   IF( CAB_MACHINE )
+     STRING(TOUPPER  "${CAB_MACHINE}" CAB_MACHINE)
+   ELSE()
+     EXECUTE_PROCESS( COMMAND hostname OUTPUT_VARIABLE CAB_MACHINE)
+     STRING(REGEX REPLACE "[ ]*([A-Za-z0-9]+).*[\\\\n]*" "\\1" CAB_MACHINE "${CAB_MACHINE}" )
+     STRING(TOUPPER  "${CAB_MACHINE}" CAB_MACHINE)
+   ENDIF()
+ENDIF()
+
+
+###############################################################
+# WITH_SUBFOLDERS_FOR_SG erstellen, wenn noch nicht vorhanden
+# ist diese auf true wird bei SOURCE_GROUP in VS unterordner erzeugt
+# dies funzt erst ab CMake-2.5 vernuenftig
+###############################################################
+IF(NOT WITH_SUBFOLDERS_FOR_SG)
+   SET(WITH_SUBFOLDERS_FOR_SG FALSE)
+ENDIF()
+
+
+############################################################################
+############################################################################
+##                  M      A      C      R      O      S                  ##
+##                  M      A      C      R      O      S                  ##
+##                  M      A      C      R      O      S                  ##
+############################################################################
+############################################################################
+# externe (ACHTUNG: die darin enthaltenen benoetigen teils noch macros die 
+# hier im Anschluss folgen
+INCLUDE("${SOURCE_ROOT}/CMake/CMakePCHMacros.txt")
+INCLUDE("${SOURCE_ROOT}/CMake/CMakeSetCompilerFlags.txt")
+#INCLUDE("${SOURCE_ROOT}/CMake/CMakeSetBoostStuff.txt")
+INCLUDE("${SOURCE_ROOT}/CMake/CMakeSetMPIStuff.txt")
+INCLUDE("${SOURCE_ROOT}/CMake/CMakeRubyMacros.txt")
+INCLUDE("${SOURCE_ROOT}/CMake/CMakeSwigMacros.txt")
+INCLUDE("${SOURCE_ROOT}/CMake/CMakeCompilerMacros.txt")
+
+################################################################
+###               ADD_TARGET_PROPERTIES                      ###
+################################################################
+MACRO(ADD_TARGET_PROPERTIES target property)
+
+   SET(property_values ${ARGN})
+   
+   # vorhandene properties holen
+   GET_TARGET_PROPERTY(TEMP_VAR ${target} ${property}) 
+   IF(TEMP_VAR)
+      LIST(APPEND property_values ${TEMP_VAR})     
+   ENDIF() 
+
+   #STRING(REGEX REPLACE ";" " " property_values ${property_values})
+   # doppelte Eintraege loeschen
+   SEPARATE_ARGUMENTS(property_values)
+   LIST(REMOVE_DUPLICATES property_values)
+
+   #aus Liste wieder einen String basteln (geht nich tmit regex replace...)
+   SET(new_property_values)
+   FOREACH(p ${property_values})
+      SET(new_property_values "${p} ${new_property_values}")
+   ENDFOREACH()
+
+   #property setzen
+   SET_TARGET_PROPERTIES(${target} PROPERTIES ${property} ${new_property_values})
+
+   #GET_TARGET_PROPERTY(TEMP_VAR ${target} ${property}) 
+   #MESSAGE("danach ${target} ${property} ${TEMP_VAR}")
+
+ENDMACRO(ADD_TARGET_PROPERTIES target property)
+
+
+################################################################
+###               CHECK_FOR_VARIABLE                         ###
+###  checks for a variable (also env-variables)
+###  if not found -> error-message!!!
+###  always: cache-entry update
+################################################################
+MACRO(CHECK_FOR_VARIABLE var)
+   #check ob evtl enviromentvariable gesetzt
+   IF(NOT DEFINED ${var})  #true if ${var} NOT: empty, 0, N, NO, OFF, FALSE, NOTFOUND, or <variable>-NOTFOUND
+     SET(${var} $ENV{${var}})
+   ENDIF()
+
+   IF(NOT DEFINED ${var})
+      SET(${var} "${var}-NOTFOUND" CACHE STRING "${ARGN}" FORCE)
+   ENDIF(NOT DEFINED ${var})
+
+   IF(${var} MATCHES ".*-NOTFOUND")
+      MESSAGE(FATAL_ERROR "CHECK_FOR_VARIABLE - error - set ${var}")
+   ENDIF()
+   
+   SET(${var} ${${var}} CACHE STRING "${ARGN}" FORCE) 
+ENDMACRO(CHECK_FOR_VARIABLE var)
+
+
+###############################################################
+###   CAB_SOURCE_GROUP( sourceGroupName )                   ###
+### creates a source group for the given folder and files.  ### 
+###############################################################
+MACRO(CAB_SOURCE_GROUP sourceGroupName)
+  SET(tempSourceGroupName ${sourceGroupName})
+  IF(WITH_SUBFOLDERS_FOR_SG)
+    STRING(REGEX REPLACE "/" "\\\\" tempSourceGroupName ${tempSourceGroupName})
+  ENDIF()
+  SOURCE_GROUP(${tempSourceGroupName} FILES ${ARGN})
+ENDMACRO(CAB_SOURCE_GROUP)
+
+#################################################################################
+###   COLLECT_PACKAGE_DATA( currentDir  sourceGroupName outFiles)             ###
+### collects header and cpp file of current dir and add them to "outfiles"    ###
+### all files will be put to the SOURCE_GROUP-folder "sourceGroupName"        ###
+### and this one will be with subfolders if  WITH_SUBFOLDERS_FOR_SG==YES      ###
+#################################################################################
+MACRO(COLLECT_PACKAGE_DATA currentDir sourceGroupName outFiles)
+  FILE( GLOB _HEADER_FILES ${currentDir}/*.h   )
+  FILE( GLOB _CPP_FILES    ${currentDir}/*.cpp )
+  FILE( GLOB _CXX_FILES    ${currentDir}/*.cxx )
+  FILE( GLOB _HPP_FILES    ${currentDir}/*.hpp )
+  FILE( GLOB _C_FILES      ${currentDir}/*.c   )
+  
+  IF(CAB_PACKAGE_DEFINTIONS)
+     SET_SOURCE_FILES_PROPERTIES( ${CPP_FILES} PROPERTIES COMPILE_FLAGS ${CAB_PACKAGE_DEFINTIONS} )
+  ENDIF(CAB_PACKAGE_DEFINTIONS)
+
+  CAB_SOURCE_GROUP( ${sourceGroupName} ${_HEADER_FILES} ${_CPP_FILES} ${_CXX_FILES} ${_HPP_FILES} ${_C_FILES} )
+
+  #SET( ${outFiles} ${${outFiles}} ${_HEADER_FILES} ${_CPP_FILES} ${_CXX_FILES} ${_HPP_FILES} ${_C_FILES} ) 
+  LIST(APPEND ${outFiles} ${_HEADER_FILES} ${_CPP_FILES} ${_CXX_FILES} ${_HPP_FILES} ${_C_FILES} )
+ENDMACRO(COLLECT_PACKAGE_DATA  currentDir sourceGroupName sourceGroupWithSubfolders outFiles)
+
+
+##################################################################################################################
+###   COLLECT_PACKAGE_DATA_WITH_OPTION( currentDir  outFiles [outOption] [outSourceGroupName]) ###
+### collects header and cpp file of current dir and add them to "outfiles"                                     ###
+### all files will be put to the SOURCE_GROUP-folder "sourceGroupName"                                         ###
+### and this one will be with subfolders if  WITH_SUBFOLDERS_FOR_SG==YES                                       ###
+##################################################################################################################
+MACRO(COLLECT_PACKAGE_DATA_WITH_OPTION currentDir outFiles)
+  STRING(REGEX REPLACE "(.*)/source/(.*)" "\\2" SOURCE_GROUP_NAME "${currentDir}")
+  STRING(REGEX REPLACE   "/" "_" OPTION_LABEL "${SOURCE_GROUP_NAME}")
+  STRING(REGEX REPLACE   ":" "" OPTION_LABEL "${OPTION_LABEL}")
+  STRING(TOUPPER ${OPTION_LABEL} OPTION_LABEL)  
+      
+  SET(OPTION_LABEL "BUILD_${OPTION_LABEL}")
+  OPTION(${OPTION_LABEL} "${currentDir}" ON)
+  
+  IF( ${OPTION_LABEL} ) 
+     COLLECT_PACKAGE_DATA( ${currentDir} ${SOURCE_GROUP_NAME} ${outFiles})
+  ENDIF(${OPTION_LABEL})
+
+  IF(${ARGC} GREATER 2)
+    SET( ${ARGV2} ${OPTION_LABEL} )
+  ENDIF()
+
+  IF(${ARGC} GREATER 3)
+     SET( ${ARGV3} ${SOURCE_GROUP_NAME} )
+  ENDIF()
+  
+ENDMACRO(COLLECT_PACKAGE_DATA_WITH_OPTION  currentDir outFiles)
+
+
+#################################################################
+###   GET_DIRECTORY_FROM_ENV( var env_var [CACHE] [STRING])   ###
+### if enn_var exists the value with corrected slashes will   ###
+### be stored in var.					      ###
+### if optional CACHE is activated the var will be stored as  ###
+### cache variable. optional you can use a status bar string   ###
+#################################################################
+MACRO(GET_DIRECTORY_FROM_ENV var env_var)
+  SET(${var} $ENV{${env_var}})
+  IF(${var}) 
+    STRING(REGEX REPLACE "\\\\" "/" ${var} ${${var}})   # "\" --> "/" 
+    IF(${ARGC} EQUAL 3 AND ${ARGV2} MATCHES "CACHE")
+       SET(${var} ${${var}} CACHE PATH "" FORCE)
+    ENDIF(${ARGC} EQUAL 3 AND ${ARGV2} MATCHES "CACHE")
+    IF(${ARGC} EQUAL 4 AND ${ARGV2} MATCHES "CACHE")
+       SET(${var} ${${var}} CACHE PATH "${ARGV3}" FORCE)
+    ENDIF(${ARGC} EQUAL 4 AND ${ARGV2} MATCHES "CACHE")
+  ENDIF(${var})
+ENDMACRO(GET_DIRECTORY_FROM_ENV var env_var)
+
+#################################################################
+###   GET_DIRECTORY_FROM_VAR( var  [CACHE] [STRING])          ###
+### if optional CACHE is activated the var will be stored as  ###
+### cache variable. optional you can use a status bar string   ###
+#################################################################
+MACRO(GET_DIRECTORY_FROM_VAR var )
+  IF(${var}) 
+    STRING(REGEX REPLACE "\\\\" "/" ${var} ${${var}})   # "\" --> "/" 
+    IF(${ARGC} EQUAL 2 AND ${ARGV1} MATCHES "CACHE")
+       SET(${var} ${${var}} CACHE PATH "" FORCE)
+    ENDIF(${ARGC} EQUAL 2 AND ${ARGV1} MATCHES "CACHE")
+    IF(${ARGC} EQUAL 3 AND ${ARGV1} MATCHES "CACHE")
+       SET(${var} ${${var}} CACHE PATH "${ARGV2}" FORCE)
+    ENDIF(${ARGC} EQUAL 3 AND ${ARGV1} MATCHES "CACHE")
+  ENDIF(${var})
+ENDMACRO(GET_DIRECTORY_FROM_VAR var env_var)
+
+
+#################################################################
+###   FINAL MACROS TO GENERATE PROJECT FILES                  ###
+###   project_name: name of the project                       ###
+###   build_type:   BINARY | SHARED | STATIC                  ###
+###   optinal:      prefix
+#################################################################
+MACRO(CREATE_CAB_PROJECT project_name build_type)
+
+   MESSAGE(STATUS "configuring ${project_name} (type=${build_type})...")
+
+   #################################################################
+   ###   RCF                                                     ###
+   #################################################################
+   IF(RCF_VERSION_NUMBER)
+      #RCF wird durch include(.../rcf/CMakePackage.txt) konfiguriert
+      MESSAGE(STATUS "RCF-Ver.${RCF_VERSION_NUMBER} is available")
+   ENDIF()
+
+   #################################################################
+   ###   BOOST                                                   ###
+   #################################################################
+   IF(NEED_BOOST)
+      MESSAGE(STATUS "INCLUDE BOOST")
+      #LIST(REMOVE_DUPLICATES NECESSARY_BOOST_LIBS)
+      SET_BOOST_STUFF( ${NECESSARY_BOOST_LIBS} )
+   ENDIF()
+   
+   #################################################################
+   ###   MPI                                                     ###
+   #################################################################
+   IF(NEED_MPI)
+      MESSAGE(STATUS "INCLUDE MPI")
+      SET_MPI_STUFF(CAB_MACHINE)
+   ENDIF(NEED_MPI)
+   
+   #################################################################
+   ###   SWIG                                                    ###
+   #################################################################
+   IF(SWIG_FILES)
+      MESSAGE(STATUS "INCLUDE SWIG")
+      IF(NOT SWIG_FOUND)
+         SET_SWIG_STUFF()
+      ENDIF()
+      SET(TMP_OUTFILES "")
+      SWIG_WAPP_CPP(SWIG_FILES "ruby" TMP_OUTFILES)
+      LIST(APPEND ALL_SOURCES ${TMP_OUTFILES})
+   ENDIF()
+
+   #################################################################
+   ###   RUBY                                                    ###
+   #################################################################
+   IF(NEED_RUBY)
+      MESSAGE(STATUS "INCLUDE RUBY")
+      IF(NOT FOUND_RUBY)
+         SET_RUBY_STUFF()
+      ENDIF()
+   ENDIF()
+
+   #################################################################
+   ###   OS DEFINES                                              ###
+   #################################################################
+   IF(WIN32)  
+      LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__WIN__)
+   ELSEIF(APPLE)
+      LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__APPLE__)
+   ELSEIF(UNIX)
+      LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+   ENDIF()
+
+   #################################################################
+   ###   ADDITIONAL_MAKE_CLEAN_FILES                             ###
+   #################################################################
+   SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${GENERATED_FILES}")
+   
+   #################################################################
+   ###   EXCECUTABLE                                             ###
+   #################################################################
+   IF(${build_type} MATCHES BINARY)
+      ADD_EXECUTABLE(${project_name} ${ALL_SOURCES} )
+   ELSEIF(${build_type} MATCHES SHARED)
+      ADD_LIBRARY(${project_name} SHARED ${ALL_SOURCES} )
+   ELSEIF(${build_type} MATCHES STATIC)
+      ADD_LIBRARY(${project_name} STATIC ${ALL_SOURCES} )
+   ELSE()
+      MESSAGE(FATAL_ERROR "build_type=${build_type} doesn't match BINARY, SHARED or STATIC")
+   ENDIF()
+
+   #################################################################
+   ###   ADDITIONAL LINK LIBRARIES                               ###
+   #################################################################
+   IF(CAB_ADDITIONAL_LINK_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${project_name} ${CAB_ADDITIONAL_LINK_LIBRARIES}) 
+   ENDIF()
+
+   #################################################################
+   ###   COMPILER Flags                                          ###
+   #################################################################
+   ADD_COMPILER_FLAGS_TO_PROJECT(${CAB_COMPILER}  ${project_name} "CXX" ${build_type})
+   MESSAGE(STATUS "compiler flags for compiler ${CAB_COMPILER} on machine ${CAB_MACHINE} for project ${project_name} (${build_type}) have been configured")
+
+   IF(CAB_ADDTIONAL_COMPILER_FLAGS)
+     ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS ${CAB_ADDTIONAL_COMPILER_FLAGS}) 
+   ENDIF()
+   IF(CAB_ADDTIONAL_COMPILER_FLAGS_DEBUG)
+     MESSAGE(FATAL_ERROR "COMPILE_FLAGS_DEBUG_<CONFIG> not supported by cmake yet :-(")
+     ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS_DEBUG ${CAB_ADDTIONAL_COMPILER_FLAGS_DEBUG}) 
+   ENDIF()
+   IF(CAB_ADDTIONAL_COMPILER_FLAGS_RELEASE)
+     MESSAGE(FATAL_ERROR "COMPILE_FLAGS_<CONFIG> not supported by cmake yet :-(")
+     ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS_RELEASE ${CAB_ADDTIONAL_COMPILER_FLAGS_RELEASE}) 
+   ENDIF()
+
+   #################################################################
+   ###   ADDITIONAL LINK PROPERTIES                              ###
+   #################################################################
+   IF(CAB_ADDITIONAL_LINK_FLAGS)
+     ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS ${CAB_ADDITIONAL_LINK_FLAGS}) 
+   ENDIF()
+   IF(CAB_ADDITIONAL_LINK_FLAGS_DEBUG)
+     ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS_DEBUG ${CAB_ADDITIONAL_LINK_FLAGS_DEBUG}) 
+   ENDIF()
+   IF(CAB_ADDITIONAL_LINK_FLAGS_RELEASE)
+     ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS_RELEASE ${CAB_ADDITIONAL_LINK_FLAGS_RELEASE}) 
+   ENDIF()
+
+   SET(project_name ${project_name} CACHE STRING "name of binary")
+
+   MESSAGE(STATUS "configuring ${project_name} (type=${build_type})... done")
+
+ENDMACRO(CREATE_CAB_PROJECT project_name build_type)
+
+#################################################################
+# fuer kompatibilit�t zu alten versionen (NICH TMEHR NUTZEN)
+###############################################################
+MACRO(CREATE_CAB_PROJECT_DEPRECATED)
+  MESSAGE(WARNING "You are still using the old CREATE_CAB_PROJECT_DEPRECATED Macro, please e.g. swith to CREATE_CAB_PROJECT(${PROJECT_NAME} BINARY)")
+  IF(NOT CAB_PROJECT_NAME)
+     SET(CAB_PROJECT_NAME ${CMAKE_PROJECT_NAME})
+  ENDIF()
+  CREATE_CAB_PROJECT(${CAB_PROJECT_NAME} BINARY)
+ENDMACRO(CREATE_CAB_PROJECT_DEPRECATED)
+
+#################################################################
+# ALLGEMEINGUELTIGER STUFF
+# CAB_COMPILER setzen und machinespecific configfile laden
+###############################################################
+SET_CAB_COMPILER()
+CHECK_FOR_VARIABLE(CAB_MACHINE "machine name, e.g. ALTIX, ARWEN")
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DCAB_MACHINE_${CAB_MACHINE})
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DCAB_MACHINE=${CAB_MACHINE})
+SET(CMAKE_CONFIG_FILE "${SOURCE_ROOT}/CMake/cmake_config_files/${CAB_MACHINE}.config.cmake")
+
+IF(NOT EXISTS ${CMAKE_CONFIG_FILE})
+  MESSAGE(FATAL_ERROR "${CMAKE_CONFIG_FILE} does not exists... maybe false CAB_MACHINE = ${CAB_MACHINE}")
+ELSE()
+  INCLUDE(${CMAKE_CONFIG_FILE})  
+ENDIF()
diff --git a/source/CMake/CMakeCompilerMacros.txt b/source/CMake/CMakeCompilerMacros.txt
new file mode 100644
index 0000000000000000000000000000000000000000..39a2c01670d977511251ffe2fa291bba2affd807
--- /dev/null
+++ b/source/CMake/CMakeCompilerMacros.txt
@@ -0,0 +1,398 @@
+###############################################################
+# Aktivieren von ELSIF in CMake
+###############################################################
+SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 1)
+
+###############################################################
+# IS_64BIT_SYSTEM (check put if OS is 64 bit compatible)
+###############################################################
+MACRO(IS_64BIT_SYSTEM is64BitOutVar)
+
+  SET(${is64BitOutVar} FALSE)
+
+  IF(APPLE)
+       EXEC_PROGRAM( arch                            
+                  ARGS -x86_64 echo "64bit"
+                  OUTPUT_VARIABLE CAB_SYSTEM_INFO_1 )
+    IF(${CAB_SYSTEM_INFO_1} MATCHES "64bit")
+      SET(${is64BitOutVar} TRUE)
+    ENDIF()
+
+  ELSEIF(UNIX)
+
+    EXEC_PROGRAM( uname                           
+                  ARGS -m
+                  OUTPUT_VARIABLE CAB_SYSTEM_INFO_1 )
+
+    STRING(REGEX MATCH "x86_64"  CAB_SYSTEM_INFO_1  ${CAB_SYSTEM_INFO_1})
+              
+
+    EXEC_PROGRAM( getconf
+                  ARGS -a | grep -i LONG_BIT
+                  OUTPUT_VARIABLE CAB_SYSTEM_INFO_2 )
+
+    STRING(REGEX MATCH "64"  CAB_SYSTEM_INFO_2  ${CAB_SYSTEM_INFO_2})
+
+    IF(CAB_SYSTEM_INFO_1 STREQUAL  "x86_64" AND CAB_SYSTEM_INFO_2 STREQUAL "64")
+      SET(${is64BitOutVar} TRUE)
+    ENDIF()
+
+  ELSEIF(WIN32)
+
+    MESSAGE(STATUS "IS_64BIT_SYSTEM: determining system type (32/64bit)...(this may take a few moments)")
+    EXEC_PROGRAM( SystemInfo OUTPUT_VARIABLE CAB_SYSTEM_INFO_1 )
+
+    STRING(REGEX MATCH "x64-based PC"  CAB_SYSTEM_INFO_1  ${CAB_SYSTEM_INFO_1})
+
+    IF(CAB_SYSTEM_INFO_1 MATCHES "x64-based PC")
+      SET(${is64BitOutVar} TRUE)
+      MESSAGE(STATUS "IS_64BIT_SYSTEM: determining system type (32/64bit)... done (-> 64 Bit)")
+    ELSE()
+      MESSAGE(STATUS "IS_64BIT_SYSTEM: determining system type (32/64bit)... done (-> 32 Bit)")
+    ENDIF()
+
+  ELSE()
+    MESSAGE(FATAL_ERROR "IS_64BIT_SYSTEM: unknown OS")
+  ENDIF()
+
+ENDMACRO(IS_64BIT_SYSTEM is64BitOutVar)
+
+
+###############################################################
+### SET_CAB_COMPILER                                        ###
+### Macro sets CAB_COMPILER variable if not set             ###
+### for msvc:      CMake Variables are used                 ###
+### for intel,gcc: --version call is evaluated              ###
+###############################################################
+MACRO(SET_CAB_COMPILER)
+   IF(NOT CMAKE_CXX_COMPILER)
+      MESSAGE(FATAL_ERROR "before SET_CAB_COMPILER-Macro PROJECT-Macro has to be called")
+   ELSE()
+      IF(NOT CAB_COMPILER)
+         IF(MSVC)
+            IF( ${MSVC_VERSION} MATCHES "1400" AND CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc8_64" )
+            ELSEIF( ${MSVC_VERSION} MATCHES "1400" AND NOT CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc8_32" )
+            ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc9_64" )
+            ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND NOT CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc9_32" )
+            ELSEIF( ${MSVC_VERSION} MATCHES "1600" AND CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc10_64" )
+            ELSEIF( ${MSVC_VERSION} MATCHES "1600" AND NOT CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc10_32" )
+            ELSEIF( ${MSVC_VERSION} MATCHES "1700" AND CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc11_64" )
+            ELSEIF( ${MSVC_VERSION} MATCHES "1700" AND NOT CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc11_32" )    
+            ELSEIF( ${MSVC_VERSION} MATCHES "1800" AND CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc11_64" )
+            ELSEIF( ${MSVC_VERSION} MATCHES "1800" AND NOT CMAKE_CL_64)
+              SET( CAB_COMPILER "msvc11_32" )               
+            ELSE()
+              MESSAGE(FATAL_ERROR "unknown ms studio version MSVC_VERSION = " ${MSVC_VERSION})  
+            ENDIF()
+         ELSE()
+           EXEC_PROGRAM( ${CMAKE_CXX_COMPILER}                          
+                          ARGS --version 
+                          OUTPUT_VARIABLE CAB_COMPILER_INFO )
+
+            STRING(REGEX REPLACE ".* \\((.*)\\) ([0-9]*)\\.([0-9]*)[\\. ]([0-9]*).*" "\\1" CAB_COMPILER_NAME          ${CAB_COMPILER_INFO})
+            STRING(REGEX REPLACE "[^ ]*[^0-9]*([0-9]*)\\.([0-9]*)[\\. ]([0-9]*)[^0-9]*.*" "\\1" CAB_COMPILER_VERSION_MAJOR ${CAB_COMPILER_INFO})
+            STRING(REGEX REPLACE "[^ ]*[^0-9]*([0-9]*)\\.([0-9]*)[\\. ]([0-9]*)[^0-9]*.*" "\\2" CAB_COMPILER_VERSION_MINOR ${CAB_COMPILER_INFO})
+            STRING(REGEX REPLACE "[^ ]*[^0-9]*([0-9]*)\\.([0-9]*)[\\. ]([0-9]*)[^0-9]*.*" "\\3" CAB_COMPILER_VERSION_PATCH ${CAB_COMPILER_INFO})
+
+            STRING(TOLOWER ${CAB_COMPILER_NAME} CAB_COMPILER_NAME)
+
+            IF(CMAKE_COMPILER_IS_GNUCXX)
+               SET(CAB_COMPILER_NAME "gcc")
+            ENDIF()
+            
+            SET(CAB_COMPILER "${CAB_COMPILER_NAME}${CAB_COMPILER_VERSION_MAJOR}${CAB_COMPILER_VERSION_MINOR}")
+         ENDIF()
+      ENDIF()
+
+      SET(CAB_COMPILER ${CAB_COMPILER} CACHE STRING "compiler") 
+   ENDIF()
+
+ENDMACRO(SET_CAB_COMPILER)
+
+################################################################
+###               CHECK_FOR_VARIABLE                         ###
+###  checks for a variable (also env-variables)
+###  if not found -> error-message!!!
+###  always: cache-entry update
+################################################################
+MACRO(CHECK_FOR_VARIABLE var)
+   #check ob evtl enviromentvariable gesetzt
+   IF(NOT ${var})  #true if ${var} NOT: empty, 0, N, NO, OFF, FALSE, NOTFOUND, or <variable>-NOTFOUND
+     SET(${var} $ENV{${var}})
+   ENDIF()
+
+   IF(NOT DEFINED ${var})
+      SET(${var} "${var}-NOTFOUND" CACHE STRING "${ARGN}" FORCE)
+   ENDIF(NOT DEFINED ${var})
+
+   IF(NOT ${var})
+      MESSAGE(FATAL_ERROR "CHECK_FOR_VARIABLE - error - set ${var}")
+   ENDIF()
+   
+SET(${var} ${${var}} CACHE STRING "${ARGN}" FORCE) 
+ENDMACRO(CHECK_FOR_VARIABLE var)
+
+
+#################################################################
+###   ADD_CXX_FLAGS(flags)     				      ###
+### flags will be added to CMAKE_CXX_FLAGS                    ###
+#################################################################
+MACRO(ADD_CXX_FLAGS)
+  FOREACH(arg ${ARGN})
+    SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+    SEPARATE_ARGUMENTS(TMP)
+    FOREACH(option ${TMP})
+      STRING(REGEX REPLACE " ${option}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+      STRING(REGEX REPLACE "${option}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${option}" CACHE STRING "common C++ build flags" FORCE)
+    ENDFOREACH(option ${TMP})  
+  ENDFOREACH(arg ${ARGN})
+ENDMACRO(ADD_CXX_FLAGS)
+
+#################################################################
+###   ADD_CXX_FLAGS_IF(option flags)             	      ###
+### flags will be added to CMAKE_CXX_FLAGS if option exists   ###
+#################################################################
+MACRO(ADD_CXX_FLAGS_IF condition)
+  IF(${condition})
+    ADD_CXX_FLAGS(${ARGN})
+  ENDIF(${condition})
+ENDMACRO(ADD_CXX_FLAGS_IF)
+
+#################################################################
+###   REMOVE_CXX_FLAGS(flags)     	  	              ###
+### flags will be removed from CMAKE_CXX_FLAGS                ###
+#################################################################
+MACRO(REMOVE_CXX_FLAGS)
+  FOREACH(arg ${ARGN})
+    SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+    SEPARATE_ARGUMENTS(TMP)
+    FOREACH(option ${TMP})
+      STRING(REGEX REPLACE " ${option}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+      STRING(REGEX REPLACE "${option}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+    ENDFOREACH(option ${TMP})  
+  ENDFOREACH(arg ${ARGN})
+ENDMACRO(REMOVE_CXX_FLAGS)
+
+#####################################################################
+###   REMOVE_CXX_FLAGS(option flags)     		          ###
+### flags will be removed from CMAKE_CXX_FLAGS if option exists   ###
+#####################################################################
+MACRO(REMOVE_CXX_FLAGS_IF condition)
+  IF(${condition})
+    REMOVE_CXX_FLAGS(${ARGN})
+  ENDIF(${condition})
+ENDMACRO(REMOVE_CXX_FLAGS_IF)
+
+#################################################################
+###   ADD_CXX_BUILDTYPE_FLAGS(buildtype flags)   	      ###
+### flags will be added to CMAKE_CXX_BUILDTYPE_FLAGS          ###
+#################################################################
+MACRO(ADD_CXX_BUILDTYPE_FLAGS buildtype)
+  IF(CMAKE_CXX_FLAGS_${buildtype})
+    FOREACH(arg ${ARGN})
+      SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+      SEPARATE_ARGUMENTS(TMP)
+      FOREACH(option ${TMP})
+        STRING(REGEX REPLACE " ${option}" "" CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}")
+        STRING(REGEX REPLACE "${option}" "" CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}")
+        SET(CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}} ${option}" CACHE STRING "common C++ build flags for ${buildtype}" FORCE)
+      ENDFOREACH(option ${TMP})  
+    ENDFOREACH(arg ${ARGN})
+  ENDIF(CMAKE_CXX_FLAGS_${buildtype})
+ENDMACRO(ADD_CXX_BUILDTYPE_FLAGS)
+
+#########################################################################
+###   ADD_CXX_BUILDTYPE_FLAGS(buildtype option flags)	              ###
+### flags will be added to CMAKE_CXX_BUILDTYPE_FLAGS if option exists ###
+#########################################################################
+MACRO(ADD_CXX_BUILDTYPE_FLAGS_IF buildtype condition)
+  IF(${condition})
+    ADD_CXX_BUILDTYPE_FLAGS(${buildtype} ${ARGN})
+  ENDIF(${condition})
+ENDMACRO(ADD_CXX_BUILDTYPE_FLAGS_IF)
+
+#################################################################
+###   REMOVE_CXX_BUILDTYPE_FLAGS(buildtype flags)             ###
+### flags will be removed from CMAKE_CXX_FLAGS                ###
+#################################################################
+MACRO(REMOVE_CXX_BUILDTYPE_FLAGS buildtype)
+  IF(CMAKE_CXX_FLAGS_${buildtype})
+    FOREACH(arg ${ARGN})
+      SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+      SEPARATE_ARGUMENTS(TMP)
+      FOREACH(option ${TMP})
+	STRING(REGEX REPLACE " ${option}" "" CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}")
+        STRING(REGEX REPLACE "${option}" "" CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}")
+        SET(CMAKE_CXX_FLAGS_${buildtype} "${CMAKE_CXX_FLAGS_${buildtype}}" 
+            CACHE STRING "C++ build flags for ${buildtype} configuration" FORCE)
+      ENDFOREACH(option ${TMP})  
+    ENDFOREACH(arg ${ARGN})
+  ENDIF(CMAKE_CXX_FLAGS_${buildtype})
+ENDMACRO(REMOVE_CXX_BUILDTYPE_FLAGS)
+
+#####################################################################
+###   REMOVE_CXX_BUILDTYPE_FLAGS_IF(buildtype option flags)       ###
+### flags will be removed from CMAKE_CXX_FLAGS if option exists   ###
+#####################################################################
+MACRO(REMOVE_CXX_BUILDTYPE_FLAGS_IF condition)
+  IF(${condition})
+    REMOVE_CXX_BUILDTYPE_FLAGS(${buildtype} ${ARGN})
+  ENDIF(${condition})
+ENDMACRO(REMOVE_CXX_BUILDTYPE_FLAGS_IF)
+
+#####################################################################
+###   SET_CXX_COMPILER( compiler)                                 ###
+### flags will be removed from CMAKE_CXX_FLAGS if option exists   ###
+#####################################################################
+#MACRO(SET_CXX_COMPILER compiler)
+#  INCLUDE (CMakeForceCompiler)
+#  SET(CMAKE_SYSTEM_NAME Generic)
+#  CMAKE_FORCE_CXX_COMPILER   (${compiler} "set by user")
+#  SET(CMAKE_CXX_COMPILER ${compiler} CACHE STRING "C++ compiler" FORCE)
+#ENDMACRO(SET_CXX_COMPILER)
+
+#################################################################
+###   ADD_C_FLAGS(flags)     				      ###
+### flags will be added to CMAKE_C_FLAGS                    ###
+#################################################################
+MACRO(ADD_C_FLAGS)
+  FOREACH(arg ${ARGN})
+    SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+    SEPARATE_ARGUMENTS(TMP)
+    FOREACH(option ${TMP})
+      STRING(REGEX REPLACE " ${option}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+      STRING(REGEX REPLACE "${option}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+      SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${option}" CACHE STRING "common C++ build flags" FORCE)
+    ENDFOREACH(option ${TMP})  
+  ENDFOREACH(arg ${ARGN})
+ENDMACRO(ADD_C_FLAGS)
+
+#################################################################
+###   ADD_C_FLAGS(option flags)     			      ###
+### flags will be added to CMAKE_C_FLAGS if option exists     ###
+#################################################################
+MACRO(ADD_C_FLAGS_IF condition)
+  IF(${condition})
+    ADD_C_FLAGS(${ARGN})
+  ENDIF(${condition})
+ENDMACRO(ADD_C_FLAGS_IF)
+
+#################################################################
+###   REMOVE_C_FLAGS(flags)     	  	              ###
+### flags will be removed from CMAKE_C_FLAGS                  ###
+#################################################################
+MACRO(REMOVE_C_FLAGS)
+  FOREACH(arg ${ARGN})
+    SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+    SEPARATE_ARGUMENTS(TMP)
+    FOREACH(option ${TMP})
+      STRING(REGEX REPLACE " ${option}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+      STRING(REGEX REPLACE "${option}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+    ENDFOREACH(option ${TMP})  
+  ENDFOREACH(arg ${ARGN})
+ENDMACRO(REMOVE_C_FLAGS)
+
+#####################################################################
+###   REMOVE_C_FLAGS(option flags)                                ###
+### flags will be removed from CMAKE_C_FLAGS if option exists     ###
+#####################################################################
+MACRO(REMOVE_C_FLAGS_IF condition)
+  IF(${condition})
+    REMOVE_C_FLAGS(${ARGN})
+  ENDIF(${condition})
+ENDMACRO(REMOVE_C_FLAGS_IF)
+
+#################################################################
+###   ADD_C_BUILDTYPE_FLAGS(buildtype flags)                  ###
+### flags will be added to CMAKE_C_BUILDTYPE_FLAGS            ###
+#################################################################
+MACRO(ADD_C_BUILDTYPE_FLAGS buildtype)
+  IF(CMAKE_C_FLAGS_${buildtype})
+    FOREACH(arg ${ARGN})
+      SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+      SEPARATE_ARGUMENTS(TMP)
+      FOREACH(option ${TMP})
+        STRING(REGEX REPLACE " ${option}" "" CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}")
+        STRING(REGEX REPLACE "${option}" "" CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}")
+        SET(CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}} ${option}" CACHE STRING "common C++ build flags for ${buildtype}" FORCE)
+      ENDFOREACH(option ${TMP})  
+    ENDFOREACH(arg ${ARGN})
+  ENDIF(CMAKE_C_FLAGS_${buildtype})
+ENDMACRO(ADD_C_BUILDTYPE_FLAGS)
+
+#########################################################################
+###   ADD_C_BUILDTYPE_FLAGS(buildtype option flags)	              ###
+### flags will be added to CMAKE_C_BUILDTYPE_FLAGS if option exists ###
+#########################################################################
+MACRO(ADD_C_BUILDTYPE_FLAGS_IF buildtype condition)
+  IF(${condition})
+    ADD_C_BUILDTYPE_FLAGS(${buildtype} ${ARGN})
+  ENDIF(${condition})
+ENDMACRO(ADD_C_BUILDTYPE_FLAGS_IF)
+
+#################################################################
+###   REMOVE_C_BUILDTYPE_FLAGS(buildtype flags)               ###
+### flags will be removed from CMAKE_C_FLAGS                  ###
+#################################################################
+MACRO(REMOVE_C_BUILDTYPE_FLAGS buildtype)
+  IF(CMAKE_C_FLAGS_${buildtype})
+    FOREACH(arg ${ARGN})
+      SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+      SEPARATE_ARGUMENTS(TMP)
+      FOREACH(option ${TMP})
+	STRING(REGEX REPLACE " ${option}" "" CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}")
+        STRING(REGEX REPLACE "${option}" "" CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}")
+        SET(CMAKE_C_FLAGS_${buildtype} "${CMAKE_C_FLAGS_${buildtype}}" 
+            CACHE STRING "C++ build flags for ${buildtype} configuration" FORCE)
+      ENDFOREACH(option ${TMP})  
+    ENDFOREACH(arg ${ARGN})
+  ENDIF(CMAKE_C_FLAGS_${buildtype})
+ENDMACRO(REMOVE_C_BUILDTYPE_FLAGS)
+
+#####################################################################
+###   REMOVE_C_BUILDTYPE_FLAGS_IF(buildtype option flags)         ###
+### flags will be removed from CMAKE_C_FLAGS if option exists     ###
+#####################################################################
+MACRO(REMOVE_C_BUILDTYPE_FLAGS_IF condition)
+  IF(${condition})
+    REMOVE_C_BUILDTYPE_FLAGS(${buildtype} ${ARGN})
+  ENDIF(${condition})
+ENDMACRO(REMOVE_C_BUILDTYPE_FLAGS_IF)
+
+#####################################################################
+###   SET_C_COMPILER( compiler)                                   ###
+### flags will be removed from CMAKE_C_FLAGS if option exists     ###
+#####################################################################
+MACRO(SET_C_COMPILER compiler)
+  INCLUDE (CMakeForceCompiler)
+  SET(CMAKE_SYSTEM_NAME Generic)
+  CMAKE_FORCE_C_COMPILER  (${compiler} "set by user")
+  SET(CMAKE_C_COMPILER ${compiler} CACHE STRING "C compiler" FORCE)
+ENDMACRO(SET_C_COMPILER)
+
+#################################################################
+###   ADD_EXE_LINKER_FLAGS(flags)                             ###
+### flags will be added to CMAKE_EXE_LINKER_FLAGS             ###
+#################################################################
+MACRO(ADD_EXE_LINKER_FLAGS)
+  FOREACH(arg ${ARGN})
+    SET(TMP ${arg}) #elsewise the Seperate command doesn't work)
+    SEPARATE_ARGUMENTS(TMP)
+    FOREACH(option ${TMP})
+      STRING(REGEX REPLACE " ${option}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+      STRING(REGEX REPLACE "${option}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+      SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${option}" CACHE STRING "common C++ build flags" FORCE)
+    ENDFOREACH(option ${TMP})  
+  ENDFOREACH(arg ${ARGN})
+ENDMACRO(ADD_EXE_LINKER_FLAGS)
+
diff --git a/source/CMake/CMakePCHMacros.txt b/source/CMake/CMakePCHMacros.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5bbaddcf4fecbeca1a5148fd367f8ddbd6c4a193
--- /dev/null
+++ b/source/CMake/CMakePCHMacros.txt
@@ -0,0 +1,44 @@
+#usage:
+#SET_PCH_FLAGS(precompile.h precompile.cpp main.cpp a.cpp b.cpp)
+#
+# precompile.h muss alle header inkluden
+# precompile.cpp muss precompile.h inkluden
+# main.cpp, a.cpp, b.cpp muess precompile.h inkluden
+#makro setzt die entsprechenden compiler flags
+
+MACRO(SET_PCH_FLAGS pre_h pre_cpp ) #argn = cpps_using_pch
+   IF(NOT CMAKE_CXX_COMPILER)
+      MESSAGE(FATAL_ERROR "before SET_CAB_COMPILER-Macro PROJECT-Macro has to be called")
+   ENDIF()
+   
+   IF(MSVC)
+	   LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DUSE_PRECOMPILED_HEADER_FILE)
+		##################################      
+		# precompiled.pch
+	   ##################################      
+		get_filename_component(PRE_NAME ${pre_h} NAME_WE)
+	   SET(PRE_PCH $(IntDir)/${PRE_NAME}.pch)
+
+	   ##################################      
+		# precompiled.cpp (=creating) anpassen
+	   ##################################      
+	   GET_TARGET_PROPERTY(oldProps ${pre_cpp} COMPILE_FLAGS)
+		  if (${oldProps} MATCHES NOTFOUND)
+		    SET(oldProps "")
+		  endif(${oldProps} MATCHES NOTFOUND)
+	   SET_SOURCE_FILES_PROPERTIES(${pre_cpp} PROPERTIES COMPILE_FLAGS "${oldProps} /Yc\"${pre_h}\" /Fp\"${PRE_PCH}\"")
+
+	   ##################################      
+		# restliche cpps (=using) anpassen
+		##################################      
+		FOREACH(cpp_file ${ARGN})
+			GET_TARGET_PROPERTY(oldProps ${cpp_file} COMPILE_FLAGS)
+			if (${oldProps} MATCHES NOTFOUND)
+				SET(oldProps "")
+			endif(${oldProps} MATCHES NOTFOUND)
+			SET_SOURCE_FILES_PROPERTIES(${cpp_file} PROPERTIES COMPILE_FLAGS "${oldProps} /Yu\"${pre_h}\" /Fp\"${PRE_PCH}\"")
+		ENDFOREACH()
+   ELSE()
+      MESSAGE(FATAL_ERROR "SET_PCH_FLAGS not working for anything else than MSVC right now")
+   ENDIF()
+ENDMACRO()
diff --git a/source/CMake/CMakePackages.txt b/source/CMake/CMakePackages.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f1f371400b880aa027a6ae47a1c62f7a5ef15ae5
--- /dev/null
+++ b/source/CMake/CMakePackages.txt
@@ -0,0 +1,12 @@
+#SUBDIRS(numerics/algebra/examples/tutorial)
+#SUBDIRS(numerics/geometry3d/examples/stl2inp)
+#SUBDIRS(lbmd2q9/a2pII/testcases/inputfile)
+SUBDIRS(lbmd2q9/a2pII/testcases/SFC_arne)
+IF(NEED_METIS)
+ MESSAGE(${NEED_METIS})
+ENDIF(NEED_METIS)
+SUBDIRS(lbmd2q9/a2pIIparallel/testcases/inputfile)
+#SUBDIRS(lbmd3q19/a2pII/testcases/inputfile)
+#SUBDIRS(lbmd3q19/OctLBM/testcases/inputfile)
+#SUBDIRS(lbmd3q19/OctLBMparallel/testcases/inputfile)
+#SUBDIRS(basics/network/examples/FourInOne)
diff --git a/source/CMake/CMakeQtMacros.txt b/source/CMake/CMakeQtMacros.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c5f5ea5aedf0fdd9b801be957c4595ffe5918989
--- /dev/null
+++ b/source/CMake/CMakeQtMacros.txt
@@ -0,0 +1,374 @@
+#####################################################################
+###   DARF ERST  - N A C H - PROJECT BEFEHL VEINGEBUNDEN WERDEN     #
+#####################################################################
+IF(NOT CMAKE_CXX_COMPILER)
+      MESSAGE(FATAL_ERROR "before SET_CAB_COMPILER-Macro PROJECT-Macro has to be called")
+ENDIF()
+#####################################################################
+###   OKAY, WENN  CMAKE_CXX_COMPILER gesetzte, dann wurd Project ausgefuehrt
+#####################################################################
+
+SET(NEED_QT "YES")
+
+IF(NOT QT_FOUND)
+   SET(QT_REQUIRED TRUE)
+   INCLUDE(${CMAKE_ROOT}/Modules/FindQt.cmake)
+ENDIF(NOT QT_FOUND)
+
+################################################################
+###                  QT_IMAGE_COLLECTION                     ###
+################################################################
+MACRO(QT_IMAGE_COLLECTION project output_file)
+  FOREACH(image ${ARGN})
+    #SET(image_collection ${image_collection} ${CMAKE_CURRENT_SOURCE_DIR}/${image})
+    SET(image_collection ${image_collection} ${image})
+  ENDFOREACH(image ${ARGN})
+  ADD_CUSTOM_COMMAND(
+                     #OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${output_file}
+                     OUTPUT  ${output_file}
+                     COMMAND ${QT_UIC_EXECUTABLE}
+                     #ARGS -embed ${project} -o ${CMAKE_CURRENT_BINARY_DIR}/${output_file} ${image_collection}
+                     ARGS -embed ${project} -o ${output_file} ${image_collection}
+                     DEPENDS ${image_collection}
+                    )
+  SET(GENERATED_FILES ${GENERATED_FILES} ${output_file}) 
+ENDMACRO(QT_IMAGE_COLLECTION)
+
+################################################################
+###                     QT_WRAP_CPP3                         ###
+### QT_WRAP_CPP3 outdirectory outfiles infileList)           ###
+################################################################
+MACRO(QT_WRAP_CPP3 outdirectory outfiles)
+  MAKE_DIRECTORY(outdirectory)
+  FOREACH(infile ${ARGN}) #ARGN is infiles-list!!!
+    GET_FILENAME_COMPONENT(outname ${infile} NAME_WE)
+    SET(outfile ${outdirectory}/${outname}MOC.cpp)
+    ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
+		       PRE_BUILD
+                       COMMAND ${QT_MOC_EXECUTABLE}
+                       ARGS -o ${outfile} ${infile}
+                       MAIN_DEPENDENCY ${infile})
+    SET(${outfiles} ${${outfiles}} ${outfile})
+  ENDFOREACH(infile ${infiles})
+  SET(GENERATED_FILES ${GENERATED_FILES} ${${outfiles}}) 
+ENDMACRO(QT_WRAP_CPP3)
+
+################################################################
+###                     QT_WRAP_UI3                          ###
+### QT_WRAP_UI3(houtdir   cppoutdir   mocoutdir              ###
+###             houtfiles cppoutfiles mocoutfiles)           ###
+###             infileList(=.ui files)             )         ###
+################################################################
+MACRO(QT_WRAP_UI3 houtdir cppoutdir mocoutdir houtfiles cppoutfiles mocoutfiles)
+  FOREACH(infile ${ARGN}) #ARGN is infiles-list!!!
+    GET_FILENAME_COMPONENT(filename_we ${infile} NAME_WE)
+    ########## HEADER ######################################
+    SET(houtfile ${houtdir}/${filename_we}.h)
+    ADD_CUSTOM_COMMAND(OUTPUT  ${houtfile}
+                       PRE_BUILD
+                       COMMAND ${QT_UIC_EXECUTABLE}
+                       ARGS -o ${houtfile} ${infile}
+                       DEPENDS ${infile}
+    )
+    SET(${houtfiles} ${${houtfiles}} ${houtfile})
+    ########## CPP #########################################
+    SET(cppoutfile ${cppoutdir}/${filename_we}.cpp)
+    ADD_CUSTOM_COMMAND(OUTPUT  ${cppoutfile}
+                       PRE_BUILD
+                       COMMAND ${QT_UIC_EXECUTABLE}
+                       ARGS ${infile} -i ${houtfile} -o ${cppoutfile}
+                       DEPENDS ${infile}
+    )
+    SET(${cppoutfiles} ${${cppoutfiles}} ${cppoutfile})
+    ########## MOC #########################################
+    SET(mocoutfile ${mocoutdir}/${filename_we}MOC.cpp)
+    ADD_CUSTOM_COMMAND(OUTPUT ${mocoutfile}
+                       PRE_BUILD
+                       COMMAND ${QT_MOC_EXECUTABLE}
+                       ARGS -o ${mocoutfile} ${houtfile}
+                       MAIN_DEPENDENCY ${houtfile})
+    SET(${mocoutfiles} ${${mocoutfiles}} ${mocoutfile})
+  ENDFOREACH(infile ${infiles})
+  SET(GENERATED_FILES ${GENERATED_FILES} ${${houtfiles}} ${${cppoutfiles}} ${${mocoutfiles}}) 
+ENDMACRO(QT_WRAP_UI3)
+
+####################################################################
+###                 QT4_WRAP_RESOURCES                           ###
+### QT4_WRAP_RESOURCES(resourcename oQRCFile oCPPFile bildfiles) ###
+####################################################################
+MACRO(QT4_WRAP_RESOURCES resourcename oQRCFile oCPPFile)
+  FOREACH(image ${ARGN}) #ARGN is infiles-list!!!
+    GET_FILENAME_COMPONENT(OUTDIR ${image} PATH)
+  ENDFOREACH(image ${ARGN})
+  
+  SET(${oQRCFile} ${OUTDIR}/${resourcename}.qrc)
+  
+  FILE(WRITE ${${oQRCFile}} "<!DOCTYPE RCC>\n<RCC>\n <qresource>\n")
+  FOREACH(image ${ARGN}) #ARGN is infiles-list!!!
+    GET_FILENAME_COMPONENT(image ${image} NAME)
+    FILE(APPEND ${${oQRCFile}} "<file>${image}</file>\n")
+  ENDFOREACH(image ${ARGN})
+  FILE(APPEND ${${oQRCFile}} "</qresource>\n</RCC>")
+
+  GET_FILENAME_COMPONENT(filename_we ${${oQRCFile}} NAME_WE)
+ 
+  SET(${oCPPFile} ${OUTDIR}/${filename_we}_QRC.cpp)
+  ADD_CUSTOM_COMMAND(OUTPUT ${${oCPPFile}}
+                     PRE_BUILD
+                     COMMAND ${QT_RCC_EXECUTABLE}
+                     ARGS -name "${filename_we}" -no-compress ${${oQRCFile}} -o ${${oCPPFile}}
+                     MAIN_DEPENDENCY ${${oQRCFile}} ${${imagefiles}})
+  SET(GENERATED_FILES ${GENERATED_FILES} ${${oCPPFile}}) 
+  #SET(GENERATED_FILES ${GENERATED_FILES} ${${oQRCFile}} ) wenn man es hier rauslöscht muss man jedes mal cmake aufrufen nach clean all um es zu erzeugen :(
+ENDMACRO(QT4_WRAP_RESOURCES)
+
+################################################################
+###                     QT4_WRAP_UI                          ###
+### QT4_WRAP_UI(outdir outfiles infileList(=.ui files))      ###
+### example:                                                 ###
+###   input:    TestClass.ui                                 ###
+###   outfiles: outdir/TestClass.h (generated if not exist)  ###
+###             outdir/TestClassUI.h                         ###
+###             outdir/TestClassMOC.cpp                      ### 
+################################################################
+MACRO(QT4_WRAP_UI outdir outfiles)
+  SET(${outfiles} )  #empty outfiles
+  SET(houtfiles )    #just empty the variable!
+
+  FOREACH(infile ${ARGN}) #ARGN is infiles-list!!!
+    GET_FILENAME_COMPONENT(filename_we ${infile} NAME_WE)
+
+    ########## UI_HEADER ######################################
+    SET(ui_houtfile ${outdir}/${QT_GEN_DIR}/${filename_we}UI.h)
+    STRING(REGEX REPLACE "//" "/" ui_houtfile ${ui_houtfile}) #doppeltes // entfernen bei nicht gesetztem QT_GEN_DIR
+  
+    ADD_CUSTOM_COMMAND( OUTPUT  ${ui_houtfile}
+                        PRE_BUILD
+                        COMMAND ${QT_UIC_EXECUTABLE}
+                        ARGS -o ${ui_houtfile} ${infile}
+                        MAIN_DEPENDENCY ${infile}
+                       )
+    SET(${outfiles} ${${outfiles}} ${ui_houtfile})
+    
+    ########## HEADER ######################################
+    SET(houtfile ${outdir}/${filename_we}.h)
+    IF(NOT EXISTS ${houtfile})
+       FILE(WRITE ${houtfile} "#ifndef ${filename_we}_H\n#define ${filename_we}_H\n\n")
+       FILE(APPEND ${houtfile} "#include \"${filename_we}UI.h\"\n\n")
+       FILE(APPEND ${houtfile} "class ${filename_we} : public QWidget \n")
+       FILE(APPEND ${houtfile} "{\n\n   Q_OBJECT\n\npublic:\n ${filename_we}()\n")
+       FILE(APPEND ${houtfile} "   {\n      ui.setupUi(this);\n   }\n\n")
+       FILE(APPEND ${houtfile} "protected:\n\n")
+       FILE(APPEND ${houtfile} "private:\nUi::${filename_we} ui;\n\n};\n\n")
+       FILE(APPEND ${houtfile} "#endif\n")
+    ENDIF(NOT EXISTS ${houtfile})
+    SET(houtfiles ${houtfiles}  ${houtfile})
+    
+    ########## MOC-CPP #####################################
+    SET(mocfile ${outdir}/${QT_GEN_DIR}/${filename_we}MOC.cpp)
+    STRING(REGEX REPLACE "//" "/" mocfile ${mocfile}) #doppeltes // entfernen bei nicht gesetztem QT_GEN_DIR
+    IF(WIN32)
+      ADD_CUSTOM_COMMAND(OUTPUT ${mocfile}
+                         PRE_BUILD
+                         COMMAND ${QT_MOC_EXECUTABLE}
+                         ARGS -o ${mocfile} ${houtfile}
+                         MAIN_DEPENDENCY ${ui_houtfile} ${houtfile} 
+                        )
+    ELSE(WIN32)  #weil sonst xxxUI.h unter Linux nicht erstellt wird!!!
+      ADD_CUSTOM_COMMAND(OUTPUT ${mocfile}
+                         PRE_BUILD
+                         COMMAND ${QT_MOC_EXECUTABLE}
+                         ARGS -o ${mocfile} ${houtfile}
+                         MAIN_DEPENDENCY  ${houtfile} ${ui_houtfile}
+                        )
+    ENDIF(WIN32)
+    SET(${outfiles} ${${outfiles}} ${mocfile})
+  ENDFOREACH(infile ${infiles})
+  
+  SET(GENERATED_FILES ${GENERATED_FILES} ${${outfiles}} ) 
+  SET(${outfiles} ${${outfiles}} ${houtfiles})
+ENDMACRO(QT4_WRAP_UI)
+
+################################################################
+###                     QT4_WRAP_CPP                         ###
+### QT4_WRAP_CPP(outdirectory outfiles infileList)           ###
+################################################################
+MACRO(QT4_WRAP_CPP outdir outfiles)
+  FOREACH(infile ${ARGN}) #ARGN is infiles-list!!!
+    GET_FILENAME_COMPONENT(outname ${infile} NAME_WE)
+    SET(outfile ${outdir}/${outname}MOC.cpp)
+    ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
+		       PRE_BUILD
+                       COMMAND ${QT_MOC_EXECUTABLE}
+                       ARGS -o ${outfile} ${infile}
+                       MAIN_DEPENDENCY ${infile})
+    #SET(${outfiles} ${${outfiles}} ${outfile})
+    SET(${outfiles} "${${outfiles}}" "${outfile}")
+  ENDFOREACH(infile ${infiles})
+  SET(GENERATED_FILES ${GENERATED_FILES} ${${outfiles}}) 
+ENDMACRO(QT4_WRAP_CPP)
+
+
+################################################################
+###               QT4_GET_TOBEMOCED_HEADERS                  ###
+### QT4_GET_TOBEMOCED_HEADERS(toBeMocedFiles infileList)     ###
+################################################################
+MACRO(QT4_GET_TOBEMOCED_HEADERS toBeMocedFiles)
+   SET(${toBeMocedFiles} "")
+   FOREACH(infile ${ARGN}) #ARGN is infiles-list!!!
+      FILE(READ "${infile}" file)
+      #STRING(REGEX MATCH Q_OBJECT check ${file})
+      STRING(REGEX MATCH "Q_OBJECT" check "${file}")
+      IF(${check} MATCHES "Q_OBJECT")
+         SET(${toBeMocedFiles} ${${toBeMocedFiles}}  ${infile})
+      ENDIF(${check} MATCHES "Q_OBJECT")
+  ENDFOREACH(infile ${infiles})
+ENDMACRO(QT4_GET_TOBEMOCED_HEADERS)
+
+#################################################################################
+###   COLLECT_QT_PACKAGE_DATA( currentDir  sourceGroupName outFiles)          ###
+### collects header and cpp file of current dir and add them to "outfiles"    ###
+### collects ui and Q_OBJECT files and adds build rules                       ###
+### all files will be put to the SOURCE_GROUP-folder "sourceGroupName"        ###
+### and this one will be with subfolders if  WITH_SUBFOLDERS_FOR_SG==YES      ###
+### all generated files will be added to a spefic folder QT_GEN_DIR           ###
+#################################################################################
+MACRO(COLLECT_QT_PACKAGE_DATA currentDir sourceGroupName outFiles)
+  IF(QT_GEN_DIR)
+    #stellt sicher, dass QT_GEN_DIR mit slash am Anfang
+    STRING(REGEX REPLACE "/" "" QT_GEN_DIR "${QT_GEN_DIR}")
+    SET(QT_GEN_DIR "/${QT_GEN_DIR}")
+  ENDIF()
+
+  FILE(GLOB QT_PACKAGE_HEADER_FILES ${currentDir}/*.h   )
+  FILE(GLOB QT_PACKAGE_CPP_FILES    ${currentDir}/*.cpp )
+  FILE(GLOB QT_PACKAGE_CXX_FILES    ${currentDir}/*.cxx )
+  FILE(GLOB QT_PACKAGE_HPP_FILES    ${currentDir}/*.hpp )
+  FILE(GLOB QT_PACKAGE_C_FILES    ${currentDir}/*.c) 
+
+  IF(NOT NEED_VTK)
+    FILE(GLOB VTK_FILES ${currentDir}/*vtk*  )
+    REMOVE(QT_PACKAGE_HEADER_FILES ${VTK_FILES} )
+    REMOVE(QT_PACKAGE_CPP_FILES    ${VTK_FILES} )
+    REMOVE(QT_PACKAGE_CXX_FILES    ${VTK_FILES} )
+    REMOVE(QT_PACKAGE_C_FILES      ${VTK_FILES} )
+    REMOVE(QT_PACKAGE_HPP_FILES    ${VTK_FILES} )
+  ENDIF(NOT NEED_VTK)
+  
+  IF(CAB_PACKAGE_DEFINTIONS)
+    SET_SOURCE_FILES_PROPERTIES(${QT_PACKAGE_CPP_FILES} PROPERTIES COMPILE_FLAGS ${CAB_PACKAGE_DEFINTIONS})
+    SET_SOURCE_FILES_PROPERTIES(${QT_PACKAGE_CXX_FILES} PROPERTIES COMPILE_FLAGS ${CAB_PACKAGE_DEFINTIONS})
+  ENDIF(CAB_PACKAGE_DEFINTIONS)
+  
+  SET(TEMP_FILES) #emty TEMP_FILES
+  SET(TEMP_FILES ${QT_PACKAGE_HEADER_FILES} ${QT_PACKAGE_CPP_FILES} ${QT_PACKAGE_CXX_FILES} ${QT_PACKAGE_C_FILES} ${QT_PACKAGE_HPP_FILES})
+  CAB_SOURCE_GROUP(${sourceGroupName} ${TEMP_FILES})
+  
+  IF(QT_FOUND)
+    ################################################################
+    ###         Qt4      Resources                               ###
+    ################################################################
+    FILE(GLOB IMAGES ${currentDir}/*.png
+                     ${currentDir}/*.jpg
+                     ${currentDir}/*.gif
+                     ${currentDir}/*.bmp )
+
+    IF(IMAGES)
+      #dynamische resourcename-filename bestimmung...
+      SET(RESOURCENAMELIST ${currentDir})
+      STRING(REGEX REPLACE "/" ";" RESOURCENAMELIST "${RESOURCENAMELIST}")
+      LIST(LENGTH RESOURCENAMELIST INDEX) 
+      MATH(EXPR INDEX "${INDEX}-2")     
+      LIST(GET RESOURCENAMELIST ${INDEX} RESOURCENAME)
+      IF(${RESOURCENAME} STREQUAL "presentation")
+         MATH(EXPR INDEX "${INDEX}-1")     
+         LIST(GET RESOURCENAMELIST ${INDEX} RESOURCENAME)
+      ENDIF()
+      #und nu geht das los
+
+      QT4_WRAP_RESOURCES(${RESOURCENAME} qrcfile cppfile ${IMAGES})
+      
+      REMOVE(TEMP_FILES ${cppfile} )
+      SET(TEMP_FILES ${TEMP_FILES} ${cppfile})
+      CAB_SOURCE_GROUP(${sourceGroupName} ${cppfile})
+
+      IF(WIN32)
+        SET(${outFiles} ${${outFiles}} ${qrcfile})
+        CAB_SOURCE_GROUP(${sourceGroupName} ${qrcfile})
+      ENDIF(WIN32)
+    ENDIF(IMAGES)
+    
+    ################################################################
+    ###         Qt4      UI FILES                                ###
+    ################################################################
+    FILE(GLOB UI_FILES ${currentDir}/*.ui)            #collect ui files
+    IF(UI_FILES)
+      MAKE_DIRECTORY(${currentDir}${QT_GEN_DIR})
+      QT4_WRAP_UI(${currentDir} OUTFILES ${UI_FILES})   #wrap ui files
+      REMOVE(TEMP_FILES ${OUTFILES} )
+      SET(TEMP_FILES ${TEMP_FILES} ${OUTFILES} )
+      
+      CAB_SOURCE_GROUP(${sourceGroupName} ${OUTFILES})
+      
+      #add generated directory to include path
+      INCLUDE_DIRECTORIES( ${currentDir}${QT_GEN_DIR} )
+
+      IF(WIN32)
+        SET(${outFiles} ${${outFiles}} ${UI_FILES})
+        CAB_SOURCE_GROUP(${sourceGroupName} ${UI_FILES})
+      ENDIF(WIN32)
+    ENDIF(UI_FILES)
+    
+    ################################################################
+    ###       Qt4        HEADERS TO BE MOCED                     ###
+    ################################################################
+    SET(HEADER_FILES_FOR_MOCCHECK ${QT_PACKAGE_HEADER_FILES})
+    
+    #remove header files that are allready processed by QT4_WRAP_UI
+    REMOVE(HEADER_FILES_FOR_MOCCHECK ${OUTFILES} )
+    
+    QT4_GET_TOBEMOCED_HEADERS(MOC_CLASSES ${HEADER_FILES_FOR_MOCCHECK})
+    IF(MOC_CLASSES)    
+      MAKE_DIRECTORY(${currentDir}${QT_GEN_DIR})
+      SET(MOC_FILES ) #empty MOC_FILES
+      QT4_WRAP_CPP(${currentDir}${QT_GEN_DIR} MOC_FILES ${MOC_CLASSES})
+      REMOVE(TEMP_FILES ${MOC_FILES})
+      SET(TEMP_FILES ${TEMP_FILES} ${MOC_FILES})
+      CAB_SOURCE_GROUP(${sourceGroupName} ${MOC_FILES})
+    ENDIF(MOC_CLASSES)
+    
+  ELSEIF(QT_FOUND)
+    MESSAGE("Could not collect Qt Package data.\n Qt was not found on your system.")
+  ENDIF(QT_FOUND)
+  
+  SET(${outFiles} ${${outFiles}} ${TEMP_FILES})
+ENDMACRO(COLLECT_QT_PACKAGE_DATA)
+
+##################################################################################################################
+###   COLLECT_QT_PACKAGE_DATA_WITH_OPTION( currentDir  sourceGroupName outFiles [outOption] [outSourceGroupName]) ###
+### collects header and cpp file of current dir and add them to "outfiles"                                     ###
+### all files will be put to the SOURCE_GROUP-folder "sourceGroupName"                                         ###
+### and this one will be with subfolders if  WITH_SUBFOLDERS_FOR_SG==YES                                       ###
+##################################################################################################################
+MACRO(COLLECT_QT_PACKAGE_DATA_WITH_OPTION currentDir outFiles)
+  STRING(REGEX REPLACE "(.*)/source/(.*)" "\\2" SOURCE_GROUP_NAME "${currentDir}")
+  STRING(REGEX REPLACE   "/" "_" OPTION_LABEL "${SOURCE_GROUP_NAME}")
+  STRING(REGEX REPLACE   ":" ""  OPTION_LABEL "${OPTION_LABEL}")
+  STRING(TOUPPER ${OPTION_LABEL} OPTION_LABEL)  
+  
+  SET(OPTION_LABEL "BUILD_${OPTION_LABEL}")
+  OPTION(${OPTION_LABEL} "${currentDir}" ON)
+
+  IF( ${OPTION_LABEL} ) 
+     COLLECT_QT_PACKAGE_DATA( ${currentDir} ${SOURCE_GROUP_NAME} ${outFiles})
+  ENDIF(${OPTION_LABEL})
+
+  IF(${ARGC} EQUAL 3)
+    SET( ${ARGV2} ${OPTION_LABEL} )
+  ENDIF()
+
+  IF(${ARGC} EQUAL 4)
+     SET( ${ARGV3} ${SOURCE_GROUP_NAME} )
+  ENDIF()
+  
+ENDMACRO(COLLECT_QT_PACKAGE_DATA_WITH_OPTION  currentDir outFiles)
\ No newline at end of file
diff --git a/source/CMake/CMakeRubyMacros.txt b/source/CMake/CMakeRubyMacros.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e887105f314f65c25e9b207646ac922f69d5cce3
--- /dev/null
+++ b/source/CMake/CMakeRubyMacros.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.8)
+
+################################################################
+###               SET_RUBY_STUFF                             ###
+################################################################
+MACRO(SET_RUBY_STUFF )
+   IF(NOT RUBY_FOUND) 
+      FIND_PACKAGE(Ruby REQUIRED)
+   ENDIF()
+
+   IF(NOT RUBY_FOUND)
+      MESSAGE(FATAL_ERROR "SET_RUBY_STUFF::could not find RUBY")
+   ELSE()
+     STRING(REGEX REPLACE "([0-9]*).([0-9]*).([0-9]*)" "\\1" CAB_RUBY_VERSION_MAJOR ${RUBY_VERSION})
+     STRING(REGEX REPLACE "([0-9]*).([0-9]*).([0-9]*)" "\\2" CAB_RUBY_VERSION_MINOR ${RUBY_VERSION})
+     STRING(REGEX REPLACE "([0-9]*).([0-9]*).([0-9]*)" "\\3" CAB_RUBY_VERSION_PATCH ${RUBY_VERSION})
+
+     MATH(EXPR CAB_RUBY_VERSION "${CAB_RUBY_VERSION_MAJOR}*10000 + ${CAB_RUBY_VERSION_MINOR}*100 + ${CAB_RUBY_VERSION_PATCH}")
+     LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS "-DCAB_RUBY=${CAB_RUBY_VERSION}")
+     LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DCAB_RUBY_EXECUTABLE=${RUBY_EXECUTABLE})
+
+     INCLUDE_DIRECTORIES( ${RUBY_INCLUDE_DIRS} )
+     SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${RUBY_LIBRARY})
+   ENDIF()
+ENDMACRO(SET_RUBY_STUFF )
+
diff --git a/source/CMake/CMakeSetBoostStuff.txt b/source/CMake/CMakeSetBoostStuff.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ad81d0530971077d63d3284ac869f74a66f6b391
--- /dev/null
+++ b/source/CMake/CMakeSetBoostStuff.txt
@@ -0,0 +1,496 @@
+# - Try to find Boost include dirs and libraries
+# Usage of this module as follows:
+#
+#     SET(BOOST_USE_STATIC_LIBS ON)
+#     SET(BOOST_USE_MULTITHREAD OFF)
+#     FIND_PACKAGE( Boost 1.34.1 COMPONENTS date_time filesystem iostreams ... )
+#
+# The BOOST_ADDITIONAL_VERSIONS variable can be used to specify a list of
+# boost version numbers that should be taken into account when searching
+# for the libraries. Unfortunately boost puts the version number into the
+# actual filename for the libraries, so this might be needed in the future
+# when new Boost versions are released.
+#
+# Currently this module searches for the following version numbers:
+# 1.33, 1.33.0, 1.33.1, 1.34, 1.34.0, 1.34.1, 1.35, 1.35.0, 1.35.1, 1.36.0,
+# 1.36.1, 1.37.0,1.38.0
+#
+# The components list needs to be the actual names of boost libraries, that is
+# the part of the actual library files that differ on different libraries. So
+# its "date_time" for "libBOOST_date_time...". Anything else will result in
+# errors
+#
+# You can provide a minimum version number that should be used. If you provide this 
+# version number and specify the REQUIRED attribute, this module will fail if it
+# can't find the specified or a later version. If you specify a version number this is
+# automatically put into the considered list of version numbers and thus doesn't need
+# to be specified in the BOOST_ADDITIONAL_VERSIONS variable
+#
+# Variables used by this module, they can change the default behaviour and need to be set
+# before calling find_package:
+#  BOOST_USE_MULTITHREAD         Can be set to OFF to use the non-multithreaded
+#                                boost libraries. Defaults to ON.
+#  BOOST_USE_STATIC_LIBS         Can be set to ON to force the use of the static
+#                                boost libraries. Defaults to OFF.
+#  BOOST_INCLUDEDIR              Set this to the include directory of Boost, if the
+#                                module has problems finding the proper Boost installation
+#  BOOST_LIBRARYDIR              Set this to the lib directory of Boost, if the
+#                                module has problems finding the proper Boost installation
+#  BOOST_AUTO_LIB_EXT_DETECTION  compiler suffix for boost libs will be detected automatically
+#                                (e.g. "-gcc33", "-il")
+#
+#  BOOST_LIB_COMPILER_EXTENSION  compiler suffix for boost libs (e.g. "-gcc33", "-il") 
+#                                (ONLY IF BOOST_AUTO_LIB_EXT_DETECTION is unset)
+#
+#
+# Variables defined by this module:
+#
+#  BOOST_FOUND                          System has Boost, this means the include dir was found,
+#                                       as well as all the libraries specified in the COMPONENTS list
+#  BOOST_LIBRARIES                      Link these to use the Boost libraries that you specified, not cached
+#  BOOST_FOUND_VERSION                  The version number of the boost libraries that have been found,
+#                                       same as in version.hpp from Boost
+#  BOOST_FOUND_LIB_VERSION              The version number in filename form as its appended to the library filenames
+#  BOOST_MAJOR_VERSION                  major version number of boost
+#  BOOST_MINOR_VERSION                  minor version number of boost
+#  BOOST_SUBMINOR_VERSION               subminor version number of boost
+#  BOOST_LIB_DIAGNOSTIC_DEFINITIONS     Only set on windows. Can be used with add_definitions 
+#                                       to print diagnostic information about the automatic 
+#                                       linking done on windows.
+
+# For each component you list the following variables are set.
+# ATTENTION: The component names need to be in lower case, just as the boost
+# library names however the cmake variables use upper case for the component
+# part. So you'd get BOOST_SERIALIZATION_FOUND for example.
+#
+#  BOOST_${COMPONENT}_FOUND             True IF the Boost library "component" was found.
+#  BOOST_${COMPONENT}_LIBRARY           The absolute path of the Boost library "component".
+#  BOOST_${COMPONENT}_LIBRARY_DEBUG     The absolute path of the debug version of the
+#                                       Boost library "component".
+#  BOOST_${COMPONENT}_LIBRARY_RELEASE   The absolute path of the release version of the
+#                                       Boost library "component"
+#
+
+# this module required CMake 2.5 for the BOOST_FIND_VERSION stuff
+#CMAKE_MINIMUM_REQUIRED(VERSION "2.6" FATAL_ERROR)
+SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 1)
+
+
+###########################################################################
+# das folgende macro sucht alle Header aus toBeIncludedFiles files nach
+# SF::register< XXX >("XXX") durch und stellt anhand dieser informationen 
+# eine Include Datei zusammen, die man benoetigt um boost serialization mit 
+# abgeleiteten Klassen zu verwenden
+###########################################################################
+MACRO( CREATE_BOOST_EXPORT_FILE toBeIncludedFiles )
+
+  ##################################################
+  # clear cars
+  ##################################################
+  SET(includeFiles   "")
+  SET(derivedClasses "")
+  
+  ##################################################
+  #find all classes and files for boost macro
+  ##################################################
+
+  FOREACH(infile ${toBeIncludedFiles}) #ARGN is infiles-list!!!
+    GET_FILENAME_COMPONENT(fileext ${infile} EXT)
+
+    IF("${fileext}" STREQUAL ".h")
+      FILE(READ "${infile}" file) #kopier kompletten dateiinhalt in variable "file"
+      SET(className "")
+      SET(isIncludeFile FALSE)
+      
+      while(NOT className STREQUAL file)
+         STRING(REGEX REPLACE ".*SF\\:\\:registerType<[ ]*(.*)[ ]*>[ ]*\\([ ]*\".*" "\\1" className "${file}")
+ 
+        IF(NOT className STREQUAL file) #wenn nichts zu ersetzen ist.. -> steht in className wieder komplettes file
+             #check ob Klasse abstrakt //MUSS MAN NICHT MACHEN
+             #STRING(REGEX MATCH "SF_NO_CTOR\\([ ]*${className}[ ]*\\)" abstractCheck "${file}")
+             STRING(REGEX REPLACE "(.*)SF\\:\\:registerType<[ ]*${className}[ ]*>\\(.*" "\\1" file "${file}")
+             
+             #IF(NOT abstractCheck)
+               SET(derivedClasses ${derivedClasses} ${className} )
+               SET(isIncludeFile TRUE)
+             #ENDIF()
+         ENDIF()
+
+      ENDWHILE()
+
+      IF(isIncludeFile)
+        SET(includeFiles ${includeFiles} ${infile} )
+      ENDIF()
+    ENDIF()  
+  ENDFOREACH(infile ${infiles})
+
+  ##################################################
+  # update main if necessary
+  # (hier wird u.a. das BoostExportFile.h erzeugt)
+  ##################################################
+  FOREACH(infile ${ARGN}) 
+    STRING(REGEX MATCH ".*main.cpp" myMain ${infile} )
+    IF(myMain)
+      GET_FILENAME_COMPONENT(myMainPath ${myMain} PATH)
+      SET(boostExportFile "${myMainPath}/BoostExportFile.h")
+    
+      #shorten boost-exportFileName
+      STRING(REGEX REPLACE "\\\\" "/" file "${boostExportFile}")       
+      STRING(REGEX REPLACE "${SOURCE_ROOT}/(.*)" "\\1" file "${boostExportFile}")
+
+      #split main
+      FILE(READ "${myMain}" myMainContent)
+
+      SET(newLines "//inserted by CMake\n#ifdef RCF_USE_BOOST_SERIALIZATION\n")
+      SET(newLines "${newLines}  #include \"./BoostExportFile.h\"\n")
+      SET(newLines "${newLines}#endif //RCF_USE_BOOST_SERIALIZATION\n//\n// insert nothing here (will be deleted by CMake)\n//\n")
+      
+      STRING(REGEX MATCH "#include \"./BoostExportFile.h\"" check "${myMainContent}")       
+
+      IF(NOT check)
+        #ALLES VOR //inserted by CMake in firstPartMain speichern buw alles vor main
+		  STRING(REGEX MATCH "//inserted by CMake" check "${myMainContent}")       
+        IF(check) 
+			 SET( firstPartMain ${myMainContent} )
+          WHILE(check)
+				STRING(REGEX REPLACE "(.*)//inserted by CMake(.*)" "\\1" firstPartMain  "${firstPartMain}")
+				STRING(REGEX MATCH "//inserted by CMake" check "${firstPartMain}")       
+          ENDWHILE()
+        ELSE()
+          STRING(REGEX REPLACE "(.*)int main\\((.*)" "\\1" firstPartMain  "${myMainContent}")       
+        ENDIF()
+        STRING(REGEX REPLACE "(.*)int main\\((.*)" "\\2" secondPartMain "${myMainContent}")       
+        #write new extended main
+        FILE(WRITE  ${myMain} "${firstPartMain}")
+        FILE(APPEND ${myMain} "${newLines}")
+        FILE(APPEND ${myMain} "int main(")
+        FILE(APPEND ${myMain} "${secondPartMain}")
+      ENDIF()
+    ENDIF()
+  ENDFOREACH()
+
+  ##################################################
+  # generate include file
+  ##################################################
+  IF(boostExportFile)
+      SET(boostExportFile_tmp ${boostExportFile}_tmp)
+      FILE(WRITE  ${boostExportFile_tmp} "//File is automatic generated by CMake::SET_BOOST_STUFF \n")
+      FILE(APPEND ${boostExportFile_tmp} "//do not change anything! SirAnn \n")
+      FILE(APPEND ${boostExportFile_tmp} "#ifndef CAB_BOOST_EXPORT\n")
+      FILE(APPEND ${boostExportFile_tmp} "#define CAB_BOOST_EXPORT\n\n")
+      FILE(APPEND ${boostExportFile_tmp} "  #ifdef RCF_USE_BOOST_SERIALIZATION\n\n")
+    
+      FOREACH(file ${includeFiles}) 
+        STRING(REGEX REPLACE "\\\\" "/" file "${file}")  
+        STRING(REGEX REPLACE "${SOURCE_ROOT}/(.*)" "\\1" file "${file}")
+        FILE(APPEND ${boostExportFile_tmp} "    #include<${file}>\n")
+      ENDFOREACH()
+    
+    	FILE(APPEND ${boostExportFile_tmp} "\n")
+    
+    	FILE(APPEND ${boostExportFile_tmp} "    #include <boost/serialization/export.hpp>\n")
+    	FILE(APPEND ${boostExportFile_tmp} "    #include <boost/serialization/void_cast.hpp>\n\n")
+
+    	FOREACH(className ${derivedClasses}) 
+    	  FILE(APPEND ${boostExportFile_tmp} "    BOOST_CLASS_EXPORT_GUID( ${className}, \"${className}\" )\n")
+    	ENDFOREACH()
+    
+    	FILE(APPEND ${boostExportFile_tmp} "\n  #endif //RCF_USE_BOOST_SERIALIZATION\n")
+    	FILE(APPEND ${boostExportFile_tmp} "#endif //CAB_BOOST_EXPORT\n")
+
+    	#compare
+    	SET(schonDa FALSE)
+    	FILE(READ ${boostExportFile_tmp} tmp)
+          
+    	IF(EXISTS ${boostExportFile})
+    	  FILE(READ ${boostExportFile}       org)
+    	  STRING(COMPARE EQUAL ${org} ${tmp} schonDa)
+    	ENDIF()
+
+    	IF(NOT schonDa)
+      	FILE(WRITE  ${boostExportFile} ${tmp})
+      	SOURCE_GROUP(generated_file FILES ${boostExportFile})
+      	LIST(APPEND ${boostExportFile} )
+    	ENDIF()
+    
+    	FILE(REMOVE ${boostExportFile_tmp})
+      
+  	ENDIF()
+
+ENDMACRO( CREATE_BOOST_EXPORT_FILE toBeIncludedFiles )
+
+
+############################################
+#
+# Check the existence of the libraries.
+#
+#########################################################################
+# This macro was taken directly from the FindQt4.cmake file that is included
+# with the CMake distribution. This is NOT my work. All work was done by the
+# original authors of the FindQt4.cmake file. Only minor modifications were
+# made to remove references to Qt and make this file more generally applicable
+#########################################################################
+MACRO(BOOST_ADJUST_LIB_VARS basename)
+  IF (BOOST_${basename}_LIBRARY_DEBUG AND BOOST_${basename}_LIBRARY_RELEASE)
+      # if the generator supports configuration types then set
+      # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value
+      IF (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
+        SET(BOOST_${basename}_LIBRARY optimized ${BOOST_${basename}_LIBRARY_RELEASE} debug ${BOOST_${basename}_LIBRARY_DEBUG})
+      ELSE(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
+        # if there are no configuration types and CMAKE_BUILD_TYPE has no value
+        # then just use the release libraries
+        SET(BOOST_${basename}_LIBRARY ${BOOST_${basename}_LIBRARY_RELEASE} )
+      ENDIF(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
+      SET(BOOST_${basename}_LIBRARIES optimized ${BOOST_${basename}_LIBRARY_RELEASE} debug ${BOOST_${basename}_LIBRARY_DEBUG})
+    ENDIF (BOOST_${basename}_LIBRARY_DEBUG AND BOOST_${basename}_LIBRARY_RELEASE)
+
+    # if only the release version was found, set the debug variable also to the release version
+    IF (BOOST_${basename}_LIBRARY_RELEASE AND NOT BOOST_${basename}_LIBRARY_DEBUG)
+      SET(BOOST_${basename}_LIBRARY_DEBUG ${BOOST_${basename}_LIBRARY_RELEASE})
+      SET(BOOST_${basename}_LIBRARY       ${BOOST_${basename}_LIBRARY_RELEASE})
+      SET(BOOST_${basename}_LIBRARIES     ${BOOST_${basename}_LIBRARY_RELEASE})
+    ENDIF (BOOST_${basename}_LIBRARY_RELEASE AND NOT BOOST_${basename}_LIBRARY_DEBUG)
+
+    # if only the debug version was found, set the release variable also to the debug version
+    IF (BOOST_${basename}_LIBRARY_DEBUG AND NOT BOOST_${basename}_LIBRARY_RELEASE)
+      SET(BOOST_${basename}_LIBRARY_RELEASE ${BOOST_${basename}_LIBRARY_DEBUG})
+      SET(BOOST_${basename}_LIBRARY         ${BOOST_${basename}_LIBRARY_DEBUG})
+      SET(BOOST_${basename}_LIBRARIES       ${BOOST_${basename}_LIBRARY_DEBUG})
+    ENDIF (BOOST_${basename}_LIBRARY_DEBUG AND NOT BOOST_${basename}_LIBRARY_RELEASE)
+    
+    IF (BOOST_${basename}_LIBRARY)
+      SET(BOOST_${basename}_LIBRARY ${BOOST_${basename}_LIBRARY} CACHE FILEPATH "The Boost ${basename} library")
+      GET_FILENAME_COMPONENT(BOOST_LIBRARYDIRS "${BOOST_${basename}_LIBRARY}" PATH)
+      SET(BOOST_${basename}_FOUND ON CACHE INTERNAL "Was the boost boost ${basename} library found")
+    ENDIF (BOOST_${basename}_LIBRARY)
+
+  # Make variables changeble to the advanced user
+  MARK_AS_ADVANCED(
+      BOOST_${basename}_LIBRARY
+      BOOST_${basename}_LIBRARY_RELEASE
+      BOOST_${basename}_LIBRARY_DEBUG
+  )
+ENDMACRO(BOOST_ADJUST_LIB_VARS)
+
+
+##################################################
+##################################################
+##################################################
+##################################################
+MACRO(SET_BOOST_STUFF )
+  	SET(BOOST_FOUND FALSE)
+  
+  	CHECK_FOR_VARIABLE(BOOST_VERSION         "1.37.0 1.36.0 1.35.0, 1.34.1, 1.34.1")
+  	IF(BOOST_VERSION)
+		CHECK_FOR_VARIABLE(BOOST_INCLUDEDIR      "BOOST_INCLUDEDIR floders that includes /boost/version.hpp")
+		CHECK_FOR_VARIABLE(BOOST_LIBRARYDIR      "BOOST_LIBRARYDIR floders that includes libs")
+		CHECK_FOR_VARIABLE(BOOST_USE_MULTITHREAD "BOOST_USE_MULTITHREAD ON/OFF")
+		CHECK_FOR_VARIABLE(BOOST_USE_STATIC_LIBS "BOOST_USE_STATIC_LIBS ON/OFF")                     
+  	ELSE()
+    	MESSAGE(FATAL_ERROR "BOOST_VERSION setzen, aber zackig!")
+  	ENDIF()
+                                                                                                  
+  	IF(BOOST_INCLUDEDIR AND BOOST_LIBRARYDIR)
+    	IF(EXISTS ${BOOST_INCLUDEDIR} AND EXISTS ${BOOST_LIBRARYDIR})
+     	 	IF(WIN32)
+	        # In windows, automatic linking is performed, so you do not have to specify the libraries.
+	        # If you are linking to a dynamic runtime, then you can choose to link to either a static or a
+	        # dynamic Boost library, the default is to do a static link.  You can alter this for a specific
+	        # library "whatever" by defining BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to
+	        # be linked dynamically.  Alternatively you can force all Boost libraries to dynamic link by
+	        # defining BOOST_ALL_DYN_LINK.
+	     
+	        # This feature can be disabled for Boost library "whatever" by defining BOOST_WHATEVER_NO_LIB,
+	        # or for all of Boost by defining BOOST_ALL_NO_LIB.
+	     
+	        # If you want to observe which libraries are being linked against then defining
+	        # BOOST_LIB_DIAGNOSTIC will cause the auto-linking code to emit a #pragma message each time
+	        # a library is selected for linking.
+                SET(BOOST_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC" CACHE STRING "Boost diagnostic define")
+      	ENDIF()
+      
+	      # Extract BOOST_FOUND_VERSION and BOOST_FOUND_LIB_VERSION from version.hpp
+	      # Read the whole file:
+	      #
+	      # Extract Boost_VERSION and BOOST_FOUND_LIB_VERSION from version.hpp
+	      # Read the whole file:
+	      #
+	      SET(BOOST_FOUND_VERSION 0)
+	      SET(BOOST_FOUND_LIB_VERSION "")
+	      FILE(READ "${BOOST_INCLUDEDIR}/boost/version.hpp" _BOOST_FOUND_VERSION_HPP_CONTENTS)
+	     
+	      STRING(REGEX REPLACE ".*#define BOOST_VERSION ([0-9]+).*" "\\1"          BOOST_FOUND_VERSION     "${_BOOST_FOUND_VERSION_HPP_CONTENTS}")
+	      STRING(REGEX REPLACE ".*#define BOOST_LIB_VERSION \"([0-9_]+)\".*" "\\1" BOOST_FOUND_LIB_VERSION "${_BOOST_FOUND_VERSION_HPP_CONTENTS}")
+	     
+	      IF(NOT "${BOOST_FOUND_VERSION}" STREQUAL "0")
+	        MATH(EXPR Boost_MAJOR_VERSION "${BOOST_FOUND_VERSION} / 100000")
+	        MATH(EXPR Boost_MINOR_VERSION "${BOOST_FOUND_VERSION} / 100 % 1000")
+	        MATH(EXPR Boost_SUBMINOR_VERSION "${BOOST_FOUND_VERSION} % 100")
+	      ENDIF(NOT "${BOOST_FOUND_VERSION}" STREQUAL "0")
+    
+	      SET(BOOST_FOUND_VERSION     ${BOOST_FOUND_VERSION}     CACHE INTERNAL "The version number for boost libraries")
+	      SET(BOOST_FOUND_LIB_VERSION ${BOOST_FOUND_LIB_VERSION} CACHE STRING "The library version string for boost libraries" FORCE)
+	      SET(BOOST_FOUND_VERSION_NUM ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION} CACHE STRING "The version number for boost libraries" FORCE)
+      
+	      #Setting some more suffixes for the library
+	      SET (BOOST_LIB_PREFIX "lib")
+	      IF ( WIN32 AND NOT BOOST_USE_STATIC_LIBS )
+	        SET (BOOST_LIB_PREFIX "")
+	      ENDIF( )
+      
+			IF( BOOST_COMPILER_SUFFIX )
+				SET(BOOST_COMPILER ${BOOST_COMPILER_SUFFIX})
+         ELSE()
+	        	SET (BOOST_COMPILER "-gcc")
+	        	IF(MSVC70)
+	         	 SET (BOOST_COMPILER "-vc70")
+	        	ELSEIF(MSVC71)
+	          	SET(BOOST_COMPILER "-vc71")
+	        	ELSEIF(MSVC80)
+	          	SET(BOOST_COMPILER "-vc80")
+	        	ELSEIF(MSVC90)
+	          	SET(BOOST_COMPILER "-vc90")
+	        	ELSEIF(MSVC100)
+	          	SET(BOOST_COMPILER "-vc100")
+	        	ELSEIF(MINGW)
+	          	#EXEC_PROGRAM(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE BOOST_COMPILER_VERSION)
+	          	#STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.[0-9] .*" "\\1\\2"
+	           	#BOOST_COMPILER_VERSION ${BOOST_COMPILER_VERSION})
+	          	SET (BOOST_COMPILER "-mgw${BOOST_COMPILER_VERSION}")
+	        	ELSEIF(CYGWIN)
+	         	SET (BOOST_COMPILER "-gcc")
+	        	ELSEIF(UNIX)
+	          IF (APPLE)
+	              SET (BOOST_COMPILER "")
+	          ELSE (APPLE)
+	            IF (NOT CMAKE_COMPILER_IS_GNUCC)
+	              # This is for the intel compiler
+	              SET (BOOST_COMPILER "-il")
+	            ELSE (NOT CMAKE_COMPILER_IS_GNUCC)
+	              #find out the version of gcc being used.
+	              EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
+	                            ARGS --version
+	                            OUTPUT_VARIABLE BOOST_COMPILER_VERSION
+	              	            )
+	               STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.[0-9] .*" "\\1\\2"
+	                      BOOST_COMPILER_VERSION ${BOOST_COMPILER_VERSION})
+	               SET (BOOST_COMPILER "-gcc${BOOST_COMPILER_VERSION}")
+	            	ENDIF (NOT CMAKE_COMPILER_IS_GNUCC)
+	          	ENDIF (APPLE)
+	        	ENDIF()
+	      ENDIF()
+
+	      IF( BOOST_USE_MULTITHREAD )
+	        SET (BOOST_MULTITHREADED "-mt")
+	      ELSE()
+	        SET (BOOST_MULTITHREADED "")
+	      ENDIF( )
+    
+	      SET( BOOST_STATIC_TAG "")
+	      IF (WIN32)
+	        IF(MSVC)
+	          SET (BOOST_ABI_TAG "g")
+	        ENDIF(MSVC)
+	        IF( BOOST_USE_STATIC_LIBS )
+	          SET( BOOST_STATIC_TAG "-s")
+	        ENDIF( BOOST_USE_STATIC_LIBS )
+	      ENDIF(WIN32)
+	      SET (BOOST_ABI_TAG "${BOOST_ABI_TAG}d")
+	      
+	      # ------------------------------------------------------------------------
+	      #  Begin finding boost libraries
+	      # ------------------------------------------------------------------------
+	      FOREACH(COMPONENT ${ARGN})
+	        STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
+	        SET( BOOST_${UPPERCOMPONENT}_LIBRARY "BOOST_${UPPERCOMPONENT}_LIBRARY-NOTFOUND" )
+	        SET( BOOST_${UPPERCOMPONENT}_LIBRARY_RELEASE "BOOST_${UPPERCOMPONENT}_LIBRARY_RELEASE-NOTFOUND" )
+	        SET( BOOST_${UPPERCOMPONENT}_LIBRARY_DEBUG "BOOST_${UPPERCOMPONENT}_LIBRARY_DEBUG-NOTFOUND")
+	      
+	        # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
+	        SET( BOOST_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+	        IF( BOOST_USE_STATIC_LIBS AND WIN32)
+	            SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+	        ENDIF( )
+	    
+	        IF( BOOST_USE_STATIC_LIBS AND NOT WIN32)
+	           SET(libExtension ".a") #irgendwie funzt CMAKE_FIND_LIBRARY_SUFFIXES unter unix nicht
+	        ENDIF( )
+	        IF( NOT BOOST_USE_STATIC_LIBS AND NOT WIN32)
+	           IF(APPLE)
+		           SET(libExtension ".dylib")
+	           ELSE(APPLE)
+		           SET(libExtension ".so") #irgendwie funzt CMAKE_FIND_LIBRARY_SUFFIXES unter unix nicht
+		        ENDIF(APPLE)
+	        ENDIF( )
+	    
+	       #MESSAGE(STATUS ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_COMPILER}${BOOST_MULTITHREADED}-${BOOST_FOUND_LIB_VERSION}${libExtension})
+	       
+	        FIND_LIBRARY(BOOST_${UPPERCOMPONENT}_LIBRARY_RELEASE
+	                     NAMES  ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_COMPILER}${BOOST_MULTITHREADED}-${BOOST_FOUND_LIB_VERSION}${libExtension}
+	                            ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_COMPILER}${BOOST_MULTITHREADED}${BOOST_STATIC_TAG}-${BOOST_FOUND_LIB_VERSION}${libExtension}
+	                            ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_MULTITHREADED}${libExtension}
+	                            ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_MULTITHREADED}${BOOST_STATIC_TAG}${libExtension}
+	                            ${BOOST_LIB_PREFIX}boost_${COMPONENT}${libExtension}
+	                     PATHS  ${BOOST_LIBRARYDIR}
+	                     NO_DEFAULT_PATH
+	                   )
+	        FIND_LIBRARY(BOOST_${UPPERCOMPONENT}_LIBRARY_DEBUG
+	                     NAMES  ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_COMPILER}${BOOST_MULTITHREADED}-${BOOST_ABI_TAG}-${BOOST_FOUND_LIB_VERSION}${libExtension}
+	                            ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_COMPILER}${BOOST_MULTITHREADED}${BOOST_STATIC_TAG}${BOOST_ABI_TAG}-${BOOST_FOUND_LIB_VERSION${libExtension}}
+	                            ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_MULTITHREADED}-${BOOST_ABI_TAG}${libExtension}
+	                            ${BOOST_LIB_PREFIX}boost_${COMPONENT}${BOOST_MULTITHREADED}${BOOST_STATIC_TAG}${BOOST_ABI_TAG}${libExtension}
+	                            ${BOOST_LIB_PREFIX}boost_${COMPONENT}-${BOOST_ABI_TAG}${libExtension}
+	                     PATHS  ${BOOST_LIBRARYDIR}
+	                     NO_DEFAULT_PATH
+	                    )
+	        
+	        BOOST_ADJUST_LIB_VARS(${UPPERCOMPONENT})
+	      
+	        SET(BOOST_LIBRARIES ${BOOST_LIBRARIES} ${BOOST_${UPPERCOMPONENT}_LIBRARY})
+	      
+	        SET(CMAKE_FIND_LIBRARY_SUFFIXES ${BOOST_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
+	      ENDFOREACH(COMPONENT ${ARGN})
+	      # ------------------------------------------------------------------------
+	      #  End finding boost libraries
+	      # ------------------------------------------------------------------------
+      
+	      ## BOOST_FOUND
+	      IF(BOOST_FOUND_VERSION)
+	        SET( BOOST_FOUND TRUE )
+	        LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DCAB_BOOST=${BOOST_FOUND_VERSION})
+	      ENDIF()
+	      
+	      #Under Windows, automatic linking is performed, so no need to specify the libraries.
+	      IF(WIN32)
+	        	IF(NOT MINGW)
+	          SET(BOOST_LIBRARIES "")
+	        	ENDIF (NOT MINGW)
+	      ENDIF(WIN32)
+
+	      INCLUDE_DIRECTORIES( ${BOOST_INCLUDEDIR}  )
+	      LINK_DIRECTORIES( ${BOOST_LIBRARYDIR} )
+	      LINK_LIBRARIES ( ${BOOST_LIBRARIES} )
+    	ELSE()
+	      IF( NOT EXISTS ${BOOST_INCLUDEDIR} )
+     	   	MESSAGE("BOOST_INCLUDEDIR = \\""${BOOST_INCLUDEDIR}"\\" does not exist")
+	      ENDIF()
+
+	      IF( NOT EXISTS ${BOOST_LIBRARYDIR} )
+     	      MESSAGE("BOOST_LIBRARYDIR = \\""${BOOST_LIBRARYDIR}"\\" does not exist")
+	      ENDIF()
+    	ENDIF()
+ 	ELSE() 
+   	IF(NOT BOOST_INCLUDEDIR)
+      	MESSAGE("variable BOOST_INCLUDEDIR not set")
+    	ENDIF()
+    	IF(NOT BOOST_LIBRARYDIR)
+       	MESSAGE("variable BOOST_LIBRARYDIR not set")
+    	ENDIF()
+    
+ 	ENDIF()
+ 
+ IF(NEED_BOOST_EXPORT_FILE)
+   CREATE_BOOST_EXPORT_FILE( ${ALL_SOURCES})
+ ENDIF()
+ENDMACRO(SET_BOOST_STUFF )
+   
diff --git a/source/CMake/CMakeSetCompilerFlags.txt b/source/CMake/CMakeSetCompilerFlags.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2a022d4d573a8b34a494ec43f3a96ee19f0ee0a0
--- /dev/null
+++ b/source/CMake/CMakeSetCompilerFlags.txt
@@ -0,0 +1,132 @@
+################################################################
+###               SET_COMPILER_SPECIFIC_FLAGS                ###
+###  determines compiler flags variabels                     ###
+###  compiler_type: e.g. msvc9_x64                           ###
+###  build_type  :    BINARY, STATIC, SHARED                 ###
+################################################################
+MACRO(SET_COMPILER_SPECIFIC_FLAGS compiler_type build_type)
+   IF(NOT CMAKE_CXX_COMPILER)
+      MESSAGE(FATAL_ERROR "before SET_CAB_COMPILER-Macro PROJECT-Macro has to be called")
+   ENDIF()
+  
+  OPTION(USE_OPENMP "activate open" OFF)
+  
+  ###############################################################################################################
+  ## Flags ruecksetzen
+  ###############################################################################################################
+  SET(CAB_COMPILER_ADDITIONAL_LINK_PROPS "")
+  SET(CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG "")
+  SET(CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE "")
+  
+  SET(CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "")
+  SET(CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG "")
+  SET(CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "")
+
+  SET(CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "")
+  SET(CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS_DEBUG "")
+  SET(CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS_RELEASE "")
+
+   ###############################################################################################################
+   ## ggf. spezielles compiler flag file lesen
+   ###############################################################################################################
+   IF( SPECIFIC_COMPILER_FLAG_FILE )
+      INCLUDE( ${SPECIFIC_COMPILER_FLAG_FILE})
+   ###############################################################################################################
+   ## standard compiler flags
+   ###############################################################################################################
+   ELSEIF( EXISTS "${SOURCE_ROOT}/CMake/compilerflags/${CAB_COMPILER}.cmake" )
+	   INCLUDE( ${SOURCE_ROOT}/CMake/compilerflags/${CAB_COMPILER}.cmake)
+	###############################################################################################################
+	## unknown compiler
+	###############################################################################################################
+	ELSE()
+	   MESSAGE(FATAL_ERROR "CAB_COMPILER=${CAB_COMPILER} seems to be a not supported compiler")
+	ENDIF()
+   
+
+   ###############################################################################################################
+	#64 Bit compilation??
+   ###############################################################################################################
+   IF(NOT DEFINED USE_64BIT_COMPILER_OPTIONS) 
+      IF(MSVC AND NOT CMAKE_CL_64)      
+        SET(OPTION64 OFF)
+      ELSEIF(MSVC AND CMAKE_CL_64)      
+        SET(OPTION64 ON)
+      ELSE()
+         IS_64BIT_SYSTEM( IS64BITSYSTEM )
+         IF(IS64BITSYSTEM STREQUAL "TRUE")
+            SET(OPTION64 ON)
+         ELSE()
+            SET(OPTION64 OFF)
+         ENDIF()
+      ENDIF()
+   ENDIF()
+
+   OPTION(USE_64BIT_COMPILER_OPTIONS "set 64 bit compiler flags"  ${OPTION64})
+
+   ###############################################################################################################
+	# set flags
+   ###############################################################################################################
+IF(USE_64BIT_COMPILER_OPTIONS)
+      SET_COMPILER_SPECIFIC_FLAGS_INTERN( ${build_type} 1)
+else()
+      SET_COMPILER_SPECIFIC_FLAGS_INTERN( ${build_type} 0)
+endif()
+  
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS compiler_type build_type)
+
+################################################################
+###             ADD_COMPILER_FLAGS_TO_PROJECT                ###
+###  adds COMPILER_FLGAS TO project                          ###
+###  project_language:    CXX , C                            ###
+################################################################
+MACRO(ADD_COMPILER_FLAGS_TO_PROJECT compiler_type project_name project_language build_type)
+
+   IF(NOT ${project_language} MATCHES "C")
+      IF(NOT ${project_language} MATCHES "CXX")
+         MESSAGE(FATAL_ERROR "project_language must be CXX or C")
+      ENDIF()
+   ENDIF()
+
+   ################################################################
+   # SET_COMPILER_SPECIFIC_FLAGS
+   ################################################################
+   SET_COMPILER_SPECIFIC_FLAGS( ${compiler_type} ${build_type} )
+
+   #workaround für itanium processoren
+   IF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ia64")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS -D_M_IA64)
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   -D_M_IA64)
+   ENDIF()
+
+   ################################################################
+   # LINKER PROPS
+   ################################################################
+   IF(CAB_COMPILER_ADDITIONAL_LINK_PROPS)
+     ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS ${CAB_COMPILER_ADDITIONAL_LINK_PROPS}) 
+   ENDIF()
+   IF(CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG)
+     ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS ${CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG}) 
+   ENDIF()
+   IF(CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE)
+     ADD_TARGET_PROPERTIES(${project_name} LINK_FLAGS ${CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE}) 
+   ENDIF()
+
+   ################################################################
+   # COMPILER FLAGS
+   ################################################################
+   IF(CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS)
+     ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS ${CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS}) 
+   ENDIF()
+   IF(CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_DEBUG)
+     MESSAGE(STATUS "ADD_COMPILER_FLAGS_TO_PROJECT: sorry, a long as CMake has no support for COMPILE_FLAGS_<CONFIG> -> DEBUG flags are neglected")
+     #ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS_DEBUG ${CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_DEBUG}) 
+   ENDIF()
+   IF(CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_RELEASE)
+     MESSAGE(STATUS "ADD_COMPILER_FLAGS_TO_PROJECT: sorry, a long as CMake has no support for COMPILE_FLAGS_<CONFIG> -> RELEASE flags are set for RELEASE AND DEBUG")
+     ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS ${CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_RELEASE}) 
+     #ADD_TARGET_PROPERTIES(${project_name} COMPILE_FLAGS_RELEASE ${CAB_COMPILER_ADDTIONAL_${project_language}_COMPILER_FLAGS_RELEASE}) 
+   ENDIF()
+
+
+ENDMACRO(ADD_COMPILER_FLAGS_TO_PROJECT compiler_type project_name project_language build_type)
\ No newline at end of file
diff --git a/source/CMake/CMakeSetMPIStuff.txt b/source/CMake/CMakeSetMPIStuff.txt
new file mode 100644
index 0000000000000000000000000000000000000000..90015e5161f779a8801f4e469f925d10053a6040
--- /dev/null
+++ b/source/CMake/CMakeSetMPIStuff.txt
@@ -0,0 +1,90 @@
+################################################################
+###               SET_MPI_STUFF                              ###
+### SET_MPI_STUFF( )                                         ###
+################################################################
+MACRO(SET_MPI_STUFF CAB_MACHINE)
+   # it will define the following values
+   #  MPI_INCLUDE_PATH = where mpi.h can be found
+   #  MPI_C_LIBRARY    = C library   (!!! if not set already  !!!)
+   #  MPI_CXX_LIBRARY  = C++ library (!!! if not set already  !!!)
+   #  MPI_CXX_COMPILER (!!! check for euqality with CMAKE_CXX_COMPILER  !!!)
+   #  MPI_C_COMPILER   (!!! check for euqality with CMAKE_C_COMPILER    !!!)
+   
+   LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DCAB_MPI)
+	LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DMPICH_IGNORE_CXX_SEEK)
+
+   IF(NOT MPI_DIR)
+     GET_DIRECTORY_FROM_ENV(MPI_DIR MPI_DIR CACHE "path to MPI dir")
+   ELSE(NOT MPI_DIR)
+     GET_DIRECTORY_FROM_VAR(MPI_DIR CACHE "path to MPI dir")
+   ENDIF(NOT MPI_DIR)
+
+   IF(NOT MPI_DIR)
+      SET(MPI_DIR "MPI_DIR - not found" CACHE PATH "path to MPI which inlcudes include" FORCE) 
+      MESSAGE("SET_MPI_STUFF - error - set MPI_DIR!")
+   ENDIF(NOT MPI_DIR)
+
+   IF(NOT EXISTS ${MPI_DIR} )
+      MESSAGE("SET_MPI_STUFF - error - MPI_DIR=${MPI_DIR} does not exist")
+   ELSE()
+      FIND_PROGRAM( MPI_CXX_COMPILER
+                    NAMES mpicxx mpic++ mpiCC
+                    PATHS
+                    ${MPI_DIR}/bin
+                    NO_DEFAULT_PATH
+                   )
+      FIND_PROGRAM( MPI_C_COMPILER
+                    NAMES mpicc
+                    PATHS
+                    ${MPI_DIR}/bin
+                    NO_DEFAULT_PATH
+                   )
+                   
+      # extract the parent directory path to get MPI_DIR 
+      FIND_PATH( MPI_INCLUDE_PATH mpi.h 
+                 "${MPI_DIR}/include"
+                )
+      
+      IF(NOT MPI_CXX_LIBRARY)
+         FIND_LIBRARY(MPI_CXX_LIBRARY 
+                      NAMES mpi++ pmpich++ mpichcxx mpich++ c++ cxx
+                      PATHS
+                      "${MPI_DIR}/lib"
+                      NO_DEFAULT_PATH
+                     )
+      ENDIF()
+      
+      IF(NOT MPI_C_LIBRARY)
+         FIND_LIBRARY(MPI_C_LIBRARY 
+                      NAMES mpi mpich
+                      PATHS 
+                   	 "${MPI_DIR}/lib"
+                      NO_DEFAULT_PATH
+                      )
+      ENDIF()
+
+
+      INCLUDE_DIRECTORIES( ${MPI_INCLUDE_PATH} )
+      LIST(APPEND CAB_ADDITIONAL_LINK_LIBRARIES ${MPI_CXX_LIBRARY})
+      LIST(APPEND CAB_ADDITIONAL_LINK_LIBRARIES ${MPI_C_LIBRARY})
+  
+      #IF(WIN32) 
+        #SET(CAB_ADDITIONAL_LINK_FLAGS "${CAB_ADDITIONAL_LINK_FLAGS} /NODEFAULTLIB:\"LIBCMT\"")
+      #ELSE(WIN32)
+      #  STRING(REGEX REPLACE ".*/(.*)" "\\1" temp_cxx_compiler    "${CMAKE_CXX_COMPILER}" )
+      #  STRING(REGEX REPLACE ".*/(.*)" "\\1" temp_mpicxx_compiler "${MPI_CXX_COMPILER}" )
+
+      #  IF(NOT temp_cxx_compiler STREQUAL temp_mpicxx_compiler)
+      #    MESSAGE(FATAL_ERROR "findMPI - CMAKE_CXX_COMPILER ${CMAKE_CXX_COMPILER} is not the right MPI_CXX_COMPILER ${MPI_CXX_COMPILER}")
+      #  ENDIF()
+        
+      #  STRING(REGEX REPLACE ".*/(.*)" "\\1" temp_c_compiler    "${CMAKE_C_COMPILER}" )
+      #  STRING(REGEX REPLACE ".*/(.*)" "\\1" temp_mpic_compiler "${MPI_C_COMPILER}" )
+
+      #   IF(NOT temp_c_compiler STREQUAL temp_mpic_compiler)
+      #    MESSAGE(FATAL_ERROR "findMPI - CMAKE_C_COMPILER ${CMAKE_C_COMPILER} is not the right MPI_C_COMPILER ${MPI_C_COMPILER}")
+      #   ENDIF()
+      #ENDIF() 
+   ENDIF() 
+ENDMACRO(SET_MPI_STUFF CAB_MACHINE)
+
diff --git a/source/CMake/CMakeSwigMacros.txt b/source/CMake/CMakeSwigMacros.txt
new file mode 100644
index 0000000000000000000000000000000000000000..25edf48dde31e307d54a239b5982e44d38593b06
--- /dev/null
+++ b/source/CMake/CMakeSwigMacros.txt
@@ -0,0 +1,162 @@
+################################################################
+###               SET_SWIG_STUFF                             ###
+################################################################
+MACRO(SET_SWIG_STUFF )
+
+   IF(NOT SWIG_FOUND)
+      FIND_PACKAGE(SWIG REQUIRED)
+   ENDIF()
+
+   IF(NOT SWIG_FOUND)
+      MESSAGE(FATAL_ERROR "SET_SWIG_STUFF::could not find SWIG")
+   ENDIF()
+
+   STRING(REGEX REPLACE "([0-9]*).([0-9]*).([0-9]*)" "\\1" CAB_SWIG_VERSION_MAJOR ${SWIG_VERSION})
+   STRING(REGEX REPLACE "([0-9]*).([0-9]*).([0-9]*)" "\\2" CAB_SWIG_VERSION_MINOR ${SWIG_VERSION})
+   STRING(REGEX REPLACE "([0-9]*).([0-9]*).([0-9]*)" "\\3" CAB_SWIG_VERSION_PATCH ${SWIG_VERSION})
+
+   MATH(EXPR CAB_SWIG_VERSION "${CAB_SWIG_VERSION_MAJOR}*10000 + ${CAB_SWIG_VERSION_MINOR}*100 + ${CAB_SWIG_VERSION_PATCH}")
+   LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS   "-DCAB_SWIG=${CAB_SWIG_VERSION}")
+
+   IF( CAB_SWIG_VERSION} LESS 10340 )
+      MESSAGE(FATAL_ERROR "SET_SWIG_STUFF: to get correct SWIG wrapper files SWIG version must be >= 1.3.40")
+   ENDIF()
+
+   IF(MSVC)   
+      LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS "-DNT=1")
+      LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS "-DIMPORT")
+   ENDIF()
+
+ENDMACRO(SET_SWIG_STUFF )
+
+
+################################################################
+###               SET_SWIG_STUFF                             ###
+################################################################
+# swigfiles: e.g. vf.i
+# language: e.g. ruby
+# outfiles: list generated files AND swig files will be append on!
+MACRO(SWIG_WAPP_CPP swigfiles language outFiles)
+   IF(NOT SWIG_FOUND)
+      MESSAGE(FATAL_ERROR "SWIG_WAPP_CPP::error SWIG package was not loaded")
+   ENDIF()
+
+   IF(${swigfiles})
+      FOREACH(swigfileName ${${swigfiles}}) 
+
+         ################################################################
+         # Dateiabhaengigkeiten ermitteln (includes in xxx.i ermitteln)
+         ################################################################
+         FILE(READ "${swigfileName}" swigfile)
+         SET(header_file_var "") #var initialisieren bzw. reseten
+
+         ################################################################
+         # Include directories ermitteln (um fuer dependency vollen pfad ermitteln zu koennen
+         GET_DIRECTORY_PROPERTY(cmake_include_directories INCLUDE_DIRECTORIES)
+         SET(swig_include_dirs)
+
+
+         MESSAGE(STATUS "scanning swigfile dependencies")
+#    WHILE(NOT header_file_var STREQUAL swigfile)
+#       #1. headerfile finden (mit #include "foo.h")
+#       #STRING(REGEX REPLACE ".*#include[ ]*[<\"]([^%]*)[>\"].*" "\\1" header_file_var "${swigfile}")
+#       STRING(REGEX REPLACE ".*#include[ ]*[\"]([^\"]*)[>\"].*" "\\1" header_file_var "${swigfile}")
+#       IF(NOT header_file_var STREQUAL swigfile) #wenn nichts zu ersetzen ist.. -> steht in className wieder komplettes file
+#         #headerfile aus swigfile löschen!
+#         STRING(REGEX REPLACE "(.*)#include[ ]*[<\"][ ]*${header_file_var}[ ]*[>\"].*" "\\1" swigfile "${swigfile}")
+#         SET(i_dependencies ${i_dependencies} ${header_file_var} )
+#       ENDIF()
+#
+#       #1. headerfile finden (mit #include <foo.h> --> es wird mit Hilfe der include pfade der vollstaendige Pfadname ermittelt )
+#       STRING(REGEX REPLACE ".*#include[ ]*[<]([^>]*)[>\"].*" "\\1" header_file_var "${swigfile}")
+#       IF(NOT header_file_var STREQUAL swigfile) #wenn nichts zu ersetzen ist.. -> steht in className wieder komplettes file
+#         #headerfile aus swigfile löschen!
+#         STRING(REGEX REPLACE "(.*)#include[ ]*[<\"][ ]*${header_file_var}[ ]*[>\"].*" "\\1" swigfile "${swigfile}")
+#         
+#         #vollstaendigen pfadnamen ermitteln
+#         SET(TEMP_FOUND FALSE)
+#         FOREACH(id ${cmake_include_directories})
+#           IF(NOT TEMP_FOUND)
+#             IF(EXISTS ${id}/${header_file_var})
+#               SET(i_dependencies ${i_dependencies} ${id}/${header_file_var} )
+#               SET(TEMP_FOUND TRUE)
+#             ENDIF()
+#           ENDIF()
+#         ENDFOREACH()
+#       ENDIF()
+#
+#    ENDWHILE()
+         MESSAGE(STATUS "scanning swigfile dependencies: done")
+
+         ################################################################
+         # Regel erstellen
+         ################################################################
+         ################################################################
+         # dateinamen fuer zu generiertes file erzeugen
+         GET_FILENAME_COMPONENT(outname      ${swigfileName} NAME_WE)
+         GET_FILENAME_COMPONENT(swigfiledir  ${swigfileName} PATH)
+         STRING(REGEX REPLACE "${SOURCE_ROOT}/" "" outdir ${swigfiledir})
+         SET(tempSourceGroupName ${outdir})
+         SET(outdir ${CMAKE_CURRENT_BINARY_DIR}/swig_cpp/${outdir}) 
+         FILE(MAKE_DIRECTORY ${outdir})
+         SET(wrapper_file ${outdir}/${outname}_wrapp.cpp)
+
+ 	 #IF(NOT EXISTS ${wrapper_file})
+         #  FILE(WRITE ${wrapper_file} "")
+         #ENDIF()
+    
+         
+         ################################################################
+         # Include directories uebernehmen
+         GET_DIRECTORY_PROPERTY(cmake_include_directories INCLUDE_DIRECTORIES)
+         SET(swig_include_dirs)
+         FOREACH(id ${cmake_include_directories})
+            SET(swig_include_dirs ${swig_include_dirs} "-I${id}")
+         ENDFOREACH(id)
+
+         ################################################################
+         # praeprozessor defines uebernehmen
+         GET_DIRECTORY_PROPERTY(preProcessorDefs COMPILE_DEFINITIONS)
+         SET(swigPreProcessorDefs "")
+         FOREACH(define ${preProcessorDefs})
+            LIST(APPEND swigPreProcessorDefs "-D${define}" )   
+         ENDFOREACH()
+         #auf die aus CAB_ADDTIONAL_COMPILER_FLAGS herausfinden
+         FOREACH(flag ${CAB_ADDTIONAL_COMPILER_FLAGS})
+            IF(flag MATCHES "[ ]?-D.*")
+               LIST(APPEND swigPreProcessorDefs ${flag} )   
+            ENDIF()
+         ENDFOREACH()
+         
+
+         ################################################################
+         # pre compile commando auf das interface file mappen
+         GET_FILENAME_COMPONENT(swigfiledir  ${swigfileName} PATH)
+         ADD_CUSTOM_COMMAND(OUTPUT ${wrapper_file}
+                            PRE_BUILD
+                            COMMAND echo on && ${SWIG_EXECUTABLE}
+                            ARGS -c++ 
+                                 -${language} 
+                                 ${swig_include_dirs} 
+                                 ${swigPreProcessorDefs} 
+                                 -o ${wrapper_file} 
+                                 ${swigfileName}
+                            WORKING_DIRECTORY ${swigfiledir}                            
+                            MAIN_DEPENDENCY ${swigfileName} 
+                            DEPENDS ${i_dependencies} 
+                            COMMENT SWIG: generating ${wrapper_file} )
+
+          #SET_SOURCE_FILES_PROPERTIES("${wrapper_file}" PROPERTIES GENERATED 1)
+          SET(GENERATED_FILES ${GENERATED_FILES} ${wrapper_file})
+          SET(${outFiles}  ${${outFiles}} ${wrapper_file} )
+
+         ################################################################
+         # SOURCE GROUP
+         ################################################################
+         STRING(REGEX REPLACE "${CMAKE_CURRENT_BINARY_DIR}/swig_cpp/" "" tempSourceGroupName ${outdir})
+         CAB_SOURCE_GROUP( ${tempSourceGroupName} ${swigfileName} ${wrapper_file} )
+
+      ENDFOREACH()
+   ENDIF()
+
+ENDMACRO(SWIG_WAPP_CPP swigfiles outFiles)
diff --git a/source/CMake/cmake_config_files/ALATAR.config.cmake b/source/CMake/cmake_config_files/ALATAR.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..e6d45e580866c963a43c0db09614c859e5ceaf90
--- /dev/null
+++ b/source/CMake/cmake_config_files/ALATAR.config.cmake
@@ -0,0 +1,67 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+#standard boost: 1.50.0
+SET(BOOST_VERSION "1.51.0" CACHE STRING "std: 1.51.0")
+
+#SET(MPI_DIR  "/hpc3lustre/software/lib/openmpi-1.4.1-gcc41")
+
+SET(USE_MPI_CXX_SYNTAX OFF)
+#SET(MPI_COMPILER "/hpc3lustre/software/lib/openmpi-1.4.1-gcc41/bin/mpicxx")
+
+IF(CAB_COMPILER MATCHES "gcc41")
+   SET(BOOST_USE_MULTITHREAD ON)
+
+   SET(BOOST_COMPILER_SUFFIX -gcc41)
+   SET(BOOST_USE_STATIC_LIBS ON)
+
+   IF(BOOST_VERSION MATCHES "1.51.0" )
+      SET(BOOST_INCLUDEDIR "/hpc3lustre/software/irmb/boost/boost_1_51_0")
+      SET(BOOST_LIBRARYDIR "/hpc3lustre/software/irmb/boost/boost_1_51_0/stageGCC/lib")
+
+   ENDIF()
+ENDIF()
+
+IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+ENDIF()
+
+#################################################################################
+#  ZOLTAN  
+#################################################################################
+IF(${USE_ZOLTAN})
+  SET(ZOLTAN_INCLUDEDIR "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Source/packages/zoltan/src/include")
+  SET(ZOLTAN_DEBUG_LIBRARY "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Build/packages/zoltan/src/libzoltan.a") 
+  SET(ZOLTAN_RELEASE_LIBRARY "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Build/packages/zoltan/src/libzoltan.a")
+ENDIF()
+
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "/hpc3lustre/software/irmb/metis/include")
+  SET(METIS_DEBUG_LIBRARY "/hpc3lustre/software/irmb/metis/lib/libmetis.a") 
+  SET(METIS_RELEASE_LIBRARY "/hpc3lustre/software/irmb/metis/lib/libmetis.a") 
+ENDIF()
+
+#################################################################################
+#  YAML  
+#################################################################################
+IF(${USE_YAML})
+  SET(YAML_INCLUDEDIR "/hpc3lustre/software/irmb/yaml/yaml-cpp/include")
+  SET(YAML_DEBUG_LIBRARY "/hpc3lustre/software/irmb/yaml/yaml-cpp/build/libyaml-cpp.a") 
+  SET(YAML_RELEASE_LIBRARY "/hpc3lustre/software/irmb/yaml/yaml-cpp/build/libyaml-cpp.a") 
+ENDIF()
+
+##################################################################################
+#  Bond
+##################################################################################
+IF(${USE_BOND})
+  SET(BOND_INCLUDEDIR "/hpc3lustre/home/koskuche/projects/bond/bond_src/cpp/bond/fetol")
+  SET(BOND_DEBUG_LIBRARY "/hpc3lustre/home/koskuche/projects/bond/bin/lib/libbond.a") 
+  SET(BOND_RELEASE_LIBRARY "/hpc3lustre/home/koskuche/projects/bond/bin/lib/libbond.a") 
+ENDIF()
+
diff --git a/source/CMake/cmake_config_files/ALTIX.config.cmake b/source/CMake/cmake_config_files/ALTIX.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..387da3bdb7069019545afa809d005a339e1ec170
--- /dev/null
+++ b/source/CMake/cmake_config_files/ALTIX.config.cmake
@@ -0,0 +1,53 @@
+OPTION(CAB_COMPILER_64BIT "64BIT COMPILATION"  ON)
+
+#################################################################################
+# COMPILER 
+#################################################################################
+SET( ALTIX_CXX_COMPILER  "mpiCC"   )
+SET( ALTIX_C_COMPILER    "mpicc"   )
+
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+IF(NOT CAB_COMPILER})
+  IF(NOT DEFINED CAB_COMPILER)
+    SET( CAB_COMPILER "intel9" )
+  ENDIF()
+ENDIF()
+
+SET(BOOST_DIR  "/home/hlrb2/h005x/h005xac/boost/include/boost-1_34_1")
+SET(USE_BOOST_STATIC_LIBS TRUE)
+
+#################################################################################
+# MPI
+#################################################################################
+
+
+#################################################################################
+#  BOOST  
+#################################################################################
+IF(NEED_BOOST)
+  SET(BOOST_USE_MULTITHREAD ON)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+  #IF(BOOST_VERSION MATCHES "1.35.0" )
+  #
+  #   SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_35")
+  #
+  #   IF(CMAKE_CL_64) 
+  #     SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35/lib/x86_64bit")
+  #   ELSE()
+  #     SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35/lib/x86_32bit")
+  #   ENDIF()
+  
+  #ELSE
+  IF(BOOST_VERSION MATCHES "1.34.1" )
+     SET(BOOST_INCLUDEDIR "/home/hlrb2/h005x/h005xac/boost/include/boost-1_34_1")
+     SET(BOOST_LIBRARYDIR "/home/hlrb2/h005x/h005xac/boost/include/boost-1_34_1/lib")
+  ENDIF()
+  
+  IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+    MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+  ENDIF()
+ENDIF()
+  
diff --git a/source/CMake/cmake_config_files/AMAN.config.cmake b/source/CMake/cmake_config_files/AMAN.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..49694f481dfcb9ab194f75bf55b10a8351931861
--- /dev/null
+++ b/source/CMake/cmake_config_files/AMAN.config.cmake
@@ -0,0 +1,83 @@
+########################################################################################
+##                                      CPU                                           ##
+########################################################################################
+SET(CPU_TYPE "Opteron")
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+#standard boost: 1.37.0
+SET(BOOST_VERSION "1.37.0" CACHE STRING "std: 1.37.0")
+
+########################################################################################
+##                                      gcc42                                         ##
+########################################################################################
+IF(CAB_COMPILER MATCHES "gcc42")
+   SET(BOOST_USE_MULTITHREAD ON)
+
+   SET(BOOST_COMPILER_SUFFIX -gcc42)
+   SET(BOOST_USE_STATIC_LIBS ON)
+		
+   IF(BOOST_VERSION MATCHES "1.37.0" )
+      SET(BOOST_INCLUDEDIR "/opt/boost/gcc-4.2/include/boost-1_37")
+      SET(BOOST_LIBRARYDIR "/opt/boost/gcc-4.2/lib")
+   ENDIF()
+
+   SET(MPI_DIR  "/opt/mpich-gm/gcc-4.2")
+
+########################################################################################
+##                                      gcc41                                         ##
+########################################################################################
+ELSEIF(CAB_COMPILER MATCHES "gcc41")
+   SET(BOOST_USE_MULTITHREAD ON)
+
+   SET(BOOST_COMPILER_SUFFIX -gcc41)
+   SET(BOOST_USE_STATIC_LIBS ON)
+		
+   IF(BOOST_VERSION MATCHES "1.37.0" )
+      SET(BOOST_INCLUDEDIR "/opt/boost/gcc-4.1/include/boost-1_37")
+      SET(BOOST_LIBRARYDIR "/opt/boost/gcc-4.1/lib")
+   ENDIF()
+
+   SET(MPI_DIR  "/opt/mpich-gm/gcc-4.1")
+
+########################################################################################
+##                                      gcc34                                         ##
+########################################################################################
+ELSEIF(CAB_COMPILER MATCHES "gcc34")
+   SET(BOOST_USE_MULTITHREAD ON)
+
+   SET(BOOST_COMPILER_SUFFIX -gcc34)
+   SET(BOOST_USE_STATIC_LIBS ON)
+		
+   IF(BOOST_VERSION MATCHES "1.37.0" )
+      SET(BOOST_INCLUDEDIR "/opt/boost/gcc-3.4/include/boost-1_37")
+      SET(BOOST_LIBRARYDIR "/opt/boost/gcc-3.4/lib")
+   ENDIF()
+
+   SET(MPI_DIR  "/opt/mpich-gm/gcc-3.4")
+
+########################################################################################
+##                                      intel10.1                                     ##
+########################################################################################
+ELSEIF(CAB_COMPILER MATCHES "intel10" )
+  SET(BOOST_USE_MULTITHREAD ON)
+
+  SET(BOOST_COMPILER_SUFFIX -il)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+  IF(BOOST_VERSION MATCHES "1.37.0" )
+    #SET(BOOST_INCLUDEDIR "/opt/boost/intel-10.1/include/boost-1_37")
+    #SET(BOOST_LIBRARYDIR "/opt/boost/intel-10.1/lib")
+   ENDIF()
+
+   #SET(MPI_DIR  "/opt/mpich/intel-10.1")
+ENDIF()
+
+
+IF(NEED_BOOST AND BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+ENDIF()
+
+
+
diff --git a/source/CMake/cmake_config_files/ARAGORN.config.cmake b/source/CMake/cmake_config_files/ARAGORN.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..26d71771a5f895f76e05fccd53e6b1165efce4d7
--- /dev/null
+++ b/source/CMake/cmake_config_files/ARAGORN.config.cmake
@@ -0,0 +1,53 @@
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+IF(NOT CAB_COMPILER})
+  IF( ${MSVC_VERSION} MATCHES "1400" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1400" AND NOT CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_32" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc9_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND NOT CMAKE_CL_64)
+     SET( CAB_COMPILER "msvc9_32" )
+  ELSE()
+     MESSAGE(ERROR, "unknown ms studio version MSVC_VERSION = "${MSVC_VERSION})  
+  ENDIF()
+ENDIF()
+
+#################################################################################
+# MPI
+#################################################################################
+SET(MPI_DIR  "c:/programme/mpich2")
+
+#################################################################################
+#  BOOST  
+#################################################################################
+IF(NEED_BOOST)
+
+  SET(BOOST_USE_MULTITHREAD ON)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+  IF(BOOST_VERSION MATCHES "1.35.0" )
+  
+     SET(BOOST_INCLUDEDIR "c:/cpp/boost/boost_1_35_0")
+  
+     IF(CMAKE_CL_64) 
+     #  SET(BOOST_LIBRARYDIR "c:/cpp/boost/boost_1_35_0/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "c:/cpp/boost/boost_1_35_0/lib")
+     ENDIF()
+
+  ELSEIF(BOOST_VERSION MATCHES "1.38.0" )
+     SET(BOOST_INCLUDEDIR "e:/cpp/boost/boost_1_38")
+     SET(BOOST_LIBRARYDIR "e:/cpp/boost/boost_1_38/lib")
+
+  ENDIF()
+  
+  IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+    MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+  ENDIF()
+ENDIF()
+  
+
+
diff --git a/source/CMake/cmake_config_files/ARWEN.config.cmake b/source/CMake/cmake_config_files/ARWEN.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..def82b2372d3be032263b389e2d01cc28689f1ba
--- /dev/null
+++ b/source/CMake/cmake_config_files/ARWEN.config.cmake
@@ -0,0 +1,103 @@
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+IF(NOT CAB_COMPILER})
+  IF( ${MSVC_VERSION} MATCHES "1400" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1400" AND NOT CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_32" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc9_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND NOT CMAKE_CL_64)
+     SET( CAB_COMPILER "msvc9_32" )
+  ELSE()
+     MESSAGE(ERROR, "unknown ms studio version MSVC_VERSION = "${MSVC_VERSION})  
+  ENDIF()
+ENDIF()
+
+#################################################################################
+# MPI
+#################################################################################
+IF(CMAKE_CL_64)
+  SET(MPI_DIR  "c:/Program Files/MPICH2")
+ELSE()
+  SET(MPI_DIR  "c:/Program Files (x86)/MPICH2")
+ENDIF()
+
+#################################################################################
+#  BOOST  
+#################################################################################
+IF(NEED_BOOST)
+  SET(BOOST_USE_MULTITHREAD ON)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+    IF(BOOST_VERSION MATCHES "1.38.0" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_38_0")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_38_0/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_38_0/lib/x86_32bit")
+     ENDIF()
+
+
+    ELSEIF(BOOST_VERSION MATCHES "1.37.0" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_37_0")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_37_0/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_37_0/lib/x86_32bit")
+     ENDIF()
+
+   ELSEIF(BOOST_VERSION MATCHES "1.36.0" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_36_0")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_36_0/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_36_0/lib/x86_32bit")
+     ENDIF()
+
+  ELSEIF(BOOST_VERSION MATCHES "1.35.0.svn" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_35_svn")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35_svn/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35_svn/lib/x86_32bit")
+     ENDIF()
+
+  ELSEIF(BOOST_VERSION MATCHES "1.35.0.std" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_35_0_std")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35_0_std/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35_0_std/lib/x86_32bit")
+     ENDIF()
+  
+  ELSEIF(BOOST_VERSION MATCHES "1.35.0" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_35_0")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35_0/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35_0/lib/x86_32bit")
+     ENDIF()
+
+  ELSEIF(BOOST_VERSION MATCHES "1.34.1" )
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_34_1")
+     SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_34_1/lib")
+  ENDIF()
+  
+  IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+    MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+  ENDIF()
+ENDIF()
diff --git a/source/CMake/cmake_config_files/BLOGIN.config.cmake b/source/CMake/cmake_config_files/BLOGIN.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..45102e380198cd9e4e22efba5403d2bb8dea726d
--- /dev/null
+++ b/source/CMake/cmake_config_files/BLOGIN.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/KONRAD.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/BLOGIN1.config.cmake b/source/CMake/cmake_config_files/BLOGIN1.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..45102e380198cd9e4e22efba5403d2bb8dea726d
--- /dev/null
+++ b/source/CMake/cmake_config_files/BLOGIN1.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/KONRAD.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/BLOGIN2.config.cmake b/source/CMake/cmake_config_files/BLOGIN2.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..45102e380198cd9e4e22efba5403d2bb8dea726d
--- /dev/null
+++ b/source/CMake/cmake_config_files/BLOGIN2.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/KONRAD.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/BOMBADIL.config.cmake b/source/CMake/cmake_config_files/BOMBADIL.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..f2a143ce05e4d0ca89792c52379e3d5cae684e5f
--- /dev/null
+++ b/source/CMake/cmake_config_files/BOMBADIL.config.cmake
@@ -0,0 +1,72 @@
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__APPLE__)
+
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+  
+#################################################################################
+# MPI
+#################################################################################
+#SET(MPI_DIR  "C:/Program Files (x86)/mpich2")
+#SET(MPI_DIR  "C:/Program Files/mpich2")
+#SET(USE_MPI_CXX_SYNTAX OFF)
+#SET(MPI_COMPILER "C:/Program Files/mpich2/bin/mpicxx")
+#SET(MPI_INCLUDE_PATH "C:/Program Files (x86)/mpich2/include")
+#SET(MPI_LIBRARY "C:/Program Files/mpich2/lib/libmpi.a")
+#SET(MPI_CXX_LIBRARY "C:/Program Files/MPICH2/lib/cxx.lib")
+#################################################################################
+#  BOOST  
+#################################################################################
+SET(BOOST_VERSION "1.58.0")
+SET(BOOST_ROOT "C:/Tools/boost/boost_1_58_0")
+SET(BOOST_DIR ${BOOST_ROOT})
+SET(BOOST_LIBRARYDIR ${BOOST_ROOT}"/stageMSVC64/lib")  
+#################################################################################
+#  VTK  
+#################################################################################
+#set(VTK_DIR "c:/Tools/VTK/build/VTK-6.1.0")
+#################################################################################
+#  ZOLTAN  
+#################################################################################
+IF(${USE_ZOLTAN})
+  SET(ZOLTAN_INCLUDEDIR "c:/Tools/zoltan/include")
+  SET(ZOLTAN_DEBUG_LIBRARY "c:/Tools/zoltan/lib/Debug/zoltan.lib") 
+  SET(ZOLTAN_RELEASE_LIBRARY "c:/Tools/zoltan/lib/Release/zoltan.lib") 
+ENDIF()
+
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "c:/Tools/metis-5.1.0/include")
+  SET(METIS_DEBUG_LIBRARY "c:/Tools/metis-5.1.0/build/libmetis/Debug/metis.lib") 
+  SET(METIS_RELEASE_LIBRARY "c:/Tools/metis-5.1.0/build/libmetis/Release/metis.lib") 
+ENDIF()
+
+##################################################################################
+#  FETOL
+##################################################################################
+IF(${USE_FETOL})
+  SET(FETOL_INCLUDEDIR "d:/Projects/FETOL/dev/CppFETOLlib")
+  SET(FETOL_DEBUG_LIBRARY "d:/Projects/FETOL/dev/CppFETOLlib/build/Debug/fetol.lib") 
+  SET(FETOL_RELEASE_LIBRARY "d:/Projects/FETOL/dev/CppFETOLlib/build/Release/fetol.lib") 
+  
+  SET(YAML_INCLUDEDIR "c:/Tools/yaml-cpp/include")
+  SET(YAML_DEBUG_LIBRARY "c:/Tools/yaml-cpp/buildVS11/Debug/libyaml-cppmdd.lib") 
+  SET(YAML_RELEASE_LIBRARY "c:/Tools/yaml-cpp/buildVS11/Release/libyaml-cppmd.lib") 
+  
+  SET(BOND_INCLUDEDIR "d:/Projects/FETOL/dev/bond_src/cpp/bond/fetol")
+  SET(BOND_DEBUG_LIBRARY "d:/Projects/FETOL/dev/bond_lib/Debug/bond.lib") 
+  SET(BOND_RELEASE_LIBRARY "d:/Projects/FETOL/dev/bond_lib/Release/bond.lib")   
+ENDIF()
+
+##################################################################################
+#  Java
+##############################################################################
+### FindJNI.cmake
+#find_package(JNI REQUIRED) 
+#SET(JNI_INCLUDE_DIRS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2} ${JAVA_AWT_INCLUDE_PATH})
+#SET(JNI_LIBRARIES ${JAVA_AWT_LIBRARY} ${JAVA_JVM_LIBRARY})
+#SET(JNI_FOUND 1) 
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/CCSMASTER.config.cmake b/source/CMake/cmake_config_files/CCSMASTER.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..1a7be411b4754573cd992c363930879df80aae89
--- /dev/null
+++ b/source/CMake/cmake_config_files/CCSMASTER.config.cmake
@@ -0,0 +1,57 @@
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+IF(NOT CAB_COMPILER})
+  IF( ${MSVC_VERSION} MATCHES "1400" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1400" AND NOT CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_32" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc9_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND NOT CMAKE_CL_64)
+     SET( CAB_COMPILER "msvc9_32" )
+  ELSE()
+     MESSAGE(ERROR, "unknown ms studio version MSVC_VERSION = "${MSVC_VERSION})  
+  ENDIF()
+ENDIF()
+
+#################################################################################
+# MPI
+#################################################################################
+IF(CMAKE_CL_64)
+  SET(MPI_DIR  "c:/Program Files/MPICH2")
+ELSE()
+  SET(MPI_DIR  "c:/Program Files (x86)/MPICH2")
+ENDIF()
+
+#################################################################################
+#  BOOST  
+#################################################################################
+IF(NEED_BOOST)
+  SET(BOOST_USE_MULTITHREAD ON)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+  IF(BOOST_VERSION MATCHES "1.35.0" )
+  
+     SET(BOOST_INCLUDEDIR "Y:/boost_1_35_0")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "Y:/boost_1_35_0/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "Y:/boost_1_35_0/lib/x86_32bit")
+     ENDIF()
+  
+  ELSEIF(BOOST_VERSION MATCHES "1.34.1" )
+     SET(BOOST_INCLUDEDIR "H:/boost1.34.1")
+          IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "H:/boost1.34.1/stage64/lib")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "H:/boost1.34.1/lib")
+     ENDIF()
+  ENDIF()
+  
+  IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+    MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+  ENDIF()
+ENDIF()
+
diff --git a/source/CMake/cmake_config_files/CCS_ERLANGEN.config.cmake b/source/CMake/cmake_config_files/CCS_ERLANGEN.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..933862768f6ef130cc367e16486bff36a6cc6d6c
--- /dev/null
+++ b/source/CMake/cmake_config_files/CCS_ERLANGEN.config.cmake
@@ -0,0 +1,57 @@
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+IF(NOT CAB_COMPILER})
+  IF( ${MSVC_VERSION} MATCHES "1400" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1400" AND NOT CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_32" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc9_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND NOT CMAKE_CL_64)
+     SET( CAB_COMPILER "msvc9_32" )
+  ELSE()
+     MESSAGE(ERROR, "unknown ms studio version MSVC_VERSION = "${MSVC_VERSION})  
+  ENDIF()
+ENDIF()
+
+#################################################################################
+# MPI
+#################################################################################
+IF(CMAKE_CL_64)
+  SET(MPI_DIR  "c:/Program Files/MPICH2")
+ELSE()
+  SET(MPI_DIR  "c:/Program Files (x86)/MPICH2")
+ENDIF()
+
+#################################################################################
+#  BOOST  
+#################################################################################
+IF(NEED_BOOST)
+  SET(BOOST_USE_MULTITHREAD ON)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+  IF(BOOST_VERSION MATCHES "1.35.0" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_35")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35/lib/x86_32bit")
+     ENDIF()
+  
+  ELSEIF(BOOST_VERSION MATCHES "1.34.1" )
+     SET(BOOST_INCLUDEDIR "H:/boost1.34.1")
+          IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "H:/boost1.34.1/stage64/lib")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "H:/boost1.34.1//lib")
+     ENDIF()
+  ENDIF()
+  
+  IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+    MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+  ENDIF()
+ENDIF()
+
diff --git a/source/CMake/cmake_config_files/COAST.config.cmake b/source/CMake/cmake_config_files/COAST.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..70b61016587b95c4587cd2928fea2e820a62aa19
--- /dev/null
+++ b/source/CMake/cmake_config_files/COAST.config.cmake
@@ -0,0 +1,63 @@
+
+#SET(CAB_COMPILER gcc41 CACHE STRING "gcc41" FORCE) 
+CHECK_FOR_VARIABLE(CAB_COMPILER "gcc41, geller_gcc41")
+
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+IF(NOT CAB_COMPILER})
+  IF(NOT DEFINED CAB_COMPILER)
+    SET(CAB_COMPILER "CAB_COMPILER-NOTFOUND")
+    MESSAGE("CHECK_FOR_VARIABLE - error - set CAB_COMPILER")
+  ENDIF()
+ENDIF()
+
+SET(CPU_TYPE "Opteron")
+
+#standard boost: 1.37.0
+SET(BOOST_VERSION "1.37.0" CACHE STRING "std: 1.37.0")
+
+########################################################################################
+##                                      gcc41                                         ##
+########################################################################################
+IF(CAB_COMPILER MATCHES "gcc41")
+   SET(BOOST_USE_MULTITHREAD ON)
+
+   SET(BOOST_COMPILER_SUFFIX -gcc41)
+   SET(BOOST_USE_STATIC_LIBS ON)
+		
+   IF(BOOST_VERSION MATCHES "1.37.0" )
+      SET(BOOST_INCLUDEDIR "/home/hegewald/bin/boost/boost_1_37_0")
+      SET(BOOST_LIBRARYDIR "/home/hegewald/bin/boost/boost_1_37_0/lib")
+   ENDIF()
+
+   #SET(MPI_DIR  "/opt/mpich-gm/gcc-4.1")
+
+   SET_CXX_COMPILER("/usr/bin/g++-4.1")
+   SET_C_COMPILER("/usr/bin/gcc-4.1")
+
+ELSEIF(CAB_COMPILER MATCHES "geller_gcc41")
+
+   SET(BOOST_USE_MULTITHREAD ON)
+
+   SET(BOOST_COMPILER_SUFFIX -gcc41)
+   SET(BOOST_USE_STATIC_LIBS ON)
+		
+   IF(BOOST_VERSION MATCHES "1.37.0" )
+      SET(BOOST_INCLUDEDIR "/home/hegewald/bin/boost/boost_1_37_0")
+      SET(BOOST_LIBRARYDIR "/home/hegewald/bin/boost/boost_1_37_0/lib")
+   ENDIF()
+
+   SET(MPI_DIR  "/home/geller/bin/mpich2-1.0.8")
+
+   SET_CXX_COMPILER("/usr/bin/g++-4.2")
+   SET_C_COMPILER("/usr/bin/gcc-4.2")
+ENDIF()
+
+
+IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+ENDIF()
+
+
+
diff --git a/source/CMake/cmake_config_files/ESLOGIN001.config.cmake b/source/CMake/cmake_config_files/ESLOGIN001.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..210df3d6c98d28535e00a1c0856763a3da25103d
--- /dev/null
+++ b/source/CMake/cmake_config_files/ESLOGIN001.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/HERMIT.config.cmake")
diff --git a/source/CMake/cmake_config_files/ESLOGIN002.config.cmake b/source/CMake/cmake_config_files/ESLOGIN002.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..210df3d6c98d28535e00a1c0856763a3da25103d
--- /dev/null
+++ b/source/CMake/cmake_config_files/ESLOGIN002.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/HERMIT.config.cmake")
diff --git a/source/CMake/cmake_config_files/ESLOGIN003.config.cmake b/source/CMake/cmake_config_files/ESLOGIN003.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..210df3d6c98d28535e00a1c0856763a3da25103d
--- /dev/null
+++ b/source/CMake/cmake_config_files/ESLOGIN003.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/HERMIT.config.cmake")
diff --git a/source/CMake/cmake_config_files/ESLOGIN008.config.cmake b/source/CMake/cmake_config_files/ESLOGIN008.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..210df3d6c98d28535e00a1c0856763a3da25103d
--- /dev/null
+++ b/source/CMake/cmake_config_files/ESLOGIN008.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/HERMIT.config.cmake")
diff --git a/source/CMake/cmake_config_files/FRWAB.config.cmake b/source/CMake/cmake_config_files/FRWAB.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..6b93153e5df17a8558e4a6d409c04c1a323a42e8
--- /dev/null
+++ b/source/CMake/cmake_config_files/FRWAB.config.cmake
@@ -0,0 +1,54 @@
+OPTION(CAB_COMPILER_64BIT "64BIT COMPILATION"  ON)
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+#standard boost: 1.38.0
+SET(BOOST_VERSION "1.38.0" CACHE STRING "std: 1.38.0")
+
+########################################################################################
+##                                      gcc41                                         ##
+########################################################################################
+IF(CAB_COMPILER MATCHES "gcc41")
+   SET(BOOST_USE_MULTITHREAD ON)
+
+   SET(BOOST_COMPILER_SUFFIX -gcc41)
+   SET(BOOST_USE_STATIC_LIBS ON)
+		
+   IF(BOOST_VERSION MATCHES "1.38.0" )
+      SET(BOOST_INCLUDEDIR "/nfs/HOME/HLRS/iws/iwsirmb/boost/gcc41/boost_1_38_0/include/boost-1_38")
+      SET(BOOST_LIBRARYDIR "/nfs/HOME/HLRS/iws/iwsirmb/boost/gcc41/boost_1_38_0/lib")
+   ENDIF()
+
+   SET(MPI_DIR  "/opt/bwgrid/mpi/openmpi/1.3-gnu-4.1")
+   SET(MPI_CXX_LIBRARY libmpi_cxx.so)
+   SET(MPI_C_LIBRARY libmpi.so)
+  
+########################################################################################
+##                                      intel10.1                                     ##
+########################################################################################
+ELSEIF(CAB_COMPILER MATCHES "intel10" )
+  SET(BOOST_USE_MULTITHREAD ON)
+
+  SET(BOOST_COMPILER_SUFFIX -il)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+  IF(BOOST_VERSION MATCHES "1.37.0" )
+      SET(BOOST_INCLUDEDIR "/nfs/HOME/HLRS/iws/iwsirmb/boost/intel101/boost_1_38_0/include/boost-1_38")
+      SET(BOOST_LIBRARYDIR "/nfs/HOME/HLRS/iws/iwsirmb/boost/intel101/boost_1_38_0/lib")
+   ENDIF()
+
+   #SET(MPI_DIR  "/opt/mpich/intel-10.1")
+   SET(MPI_DIR  "/opt/bwgrid/mpi/openmpi/1.3-intel-10.1")
+
+   SET_CXX_COMPILER("/opt/intel/vve/10.1.018/bin/icpc")
+   SET_C_COMPILER("/opt/intel/vve/10.1.018/bin/icc")
+ENDIF()
+
+
+IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+ENDIF()
+
+
+
diff --git a/source/CMake/cmake_config_files/GENIUS1.config.cmake b/source/CMake/cmake_config_files/GENIUS1.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..675a542085e90458b700c59a0b7ed95c1e9e2144
--- /dev/null
+++ b/source/CMake/cmake_config_files/GENIUS1.config.cmake
@@ -0,0 +1,33 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+
+#################################################################################
+# MPI
+#################################################################################
+SET(USE_MPI_CXX_SYNTAX OFF)
+
+#################################################################################
+#  BOOST
+#################################################################################
+SET(BOOST_VERSION "1.44")
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(BOOST_VERSION MATCHES "1.44" )
+  SET(BOOST_INCLUDEDIR "/u/lrz102bk/soft/boost_1_44_0/build/include")
+  SET(BOOST_LIBRARYDIR "/u/lrz102bk/soft/boost_1_44_0/build/lib")
+ENDIF()
+
+IF(${USE_ZOLTAN})
+  SET(ZOLTAN_INCLUDEDIR "/u/lrz102bk/BlueGene/soft/Zoltan_v3.1/bin/include")
+  SET(ZOLTAN_DEBUG_LIBRARY "/u/lrz102bk/BlueGene/soft/Zoltan_v3.1/bin/lib/libzoltan.a") 
+  SET(ZOLTAN_RELEASE_LIBRARY "/u/lrz102bk/BlueGene/soft/Zoltan_v3.1/bin/lib/libzoltan.a") 
+ENDIF()
+
+set(SOURCE_ROOT "/u/lrz102bk/BlueGene/projects/pFluid/source")
+
+
diff --git a/source/CMake/cmake_config_files/GIMLI.config.cmake b/source/CMake/cmake_config_files/GIMLI.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..753957d6d8583f5e114b9cfb78e8cde89f1b2f57
--- /dev/null
+++ b/source/CMake/cmake_config_files/GIMLI.config.cmake
@@ -0,0 +1,63 @@
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+IF(NOT CAB_COMPILER})
+  IF( ${MSVC_VERSION} MATCHES "1400" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1400" AND NOT CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_32" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc9_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND NOT CMAKE_CL_64)
+     SET( CAB_COMPILER "msvc9_32" )
+  ELSE()
+     MESSAGE(ERROR, "unknown ms studio version MSVC_VERSION = "${MSVC_VERSION})  
+  ENDIF()
+ENDIF()
+
+#################################################################################
+# MPI
+#################################################################################
+IF(CMAKE_CL_64)
+  SET(MPI_DIR  "c:/Program Files/MPICH2")
+ELSE()
+  SET(MPI_DIR  "c:/Program Files (x86)/MPICH2")
+ENDIF()
+
+#################################################################################
+#  BOOST  
+#################################################################################
+IF(NEED_BOOST)
+  SET(BOOST_USE_MULTITHREAD ON)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+  IF(BOOST_VERSION MATCHES "1.35.0.svn" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_35")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35/lib/x86_32bit")
+     ENDIF()
+
+  ELSEIF(BOOST_VERSION MATCHES "1.35.0" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_35_0")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35_0/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35_0/lib/x86_32bit")
+     ENDIF()
+  
+  ELSEIF(BOOST_VERSION MATCHES "1.34.1" )
+     SET(BOOST_INCLUDEDIR "C:/Program Files (x86)/boost/boost_1_34_1")
+     SET(BOOST_LIBRARYDIR "C:/Program Files (x86)/boost/boost_1_34_1/lib")
+  ENDIF()
+  
+  IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+    MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+  ENDIF()
+ENDIF()
+  
diff --git a/source/CMake/cmake_config_files/GOTTFRIED.config.cmake b/source/CMake/cmake_config_files/GOTTFRIED.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..05e2e99143ae78fb4b7cdbc50a36f15425d798c0
--- /dev/null
+++ b/source/CMake/cmake_config_files/GOTTFRIED.config.cmake
@@ -0,0 +1,55 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+#standard boost
+SET(BOOST_VERSION "1.55.0" CACHE STRING "std: 1.55.0")
+
+#SET(USE_MPI_CXX_SYNTAX OFF)
+
+#IF(CAB_COMPILER MATCHES "gcc41")
+#   SET(BOOST_USE_MULTITHREAD ON)
+
+   #SET(BOOST_COMPILER_SUFFIX -gcc41)
+#   SET(BOOST_USE_STATIC_LIBS ON)
+
+#    IF(BOOST_VERSION MATCHES "1.54.0" )
+#       SET(BOOST_INCLUDEDIR "/gfs1/work/niivfcpu/tools/boost_1_54_0")
+#       SET(BOOST_LIBRARYDIR "/gfs1/work/niivfcpu/tools/boost_1_54_0/stageGCC/lib")
+#    ENDIF()
+#ENDIF()
+
+#IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+#  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+#ENDIF()
+
+
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "/gfs1/work/niivfcpu/libs/metis/include")
+  SET(METIS_DEBUG_LIBRARY "/gfs1/work/niivfcpu/libs/metis/lib/libmetis.a") 
+  SET(METIS_RELEASE_LIBRARY "/gfs1/work/niivfcpu/libs/metis/lib/libmetis.a") 
+ENDIF()
+
+# #################################################################################
+# #  YAML  
+# #################################################################################
+# IF(${USE_YAML})
+#   SET(YAML_INCLUDEDIR "/hpc3lustre/software/irmb/yaml/yaml-cpp/include")
+#   SET(YAML_DEBUG_LIBRARY "/hpc3lustre/software/irmb/yaml/yaml-cpp/build/libyaml-cpp.a") 
+#   SET(YAML_RELEASE_LIBRARY "/hpc3lustre/software/irmb/yaml/yaml-cpp/build/libyaml-cpp.a") 
+# ENDIF()
+# 
+# ##################################################################################
+# #  Bond
+# ##################################################################################
+# IF(${USE_BOND})
+#   SET(BOND_INCLUDEDIR "/hpc3lustre/home/koskuche/projects/bond/bond_src/cpp/bond/fetol")
+#   SET(BOND_DEBUG_LIBRARY "/hpc3lustre/home/koskuche/projects/bond/bin/lib/libbond.a") 
+#   SET(BOND_RELEASE_LIBRARY "/hpc3lustre/home/koskuche/projects/bond/bin/lib/libbond.a") 
+# ENDIF()
+
diff --git a/source/CMake/cmake_config_files/HELM.config.cmake b/source/CMake/cmake_config_files/HELM.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..341d045f60e0a505f9abbc8b6c3e6b780af0762e
--- /dev/null
+++ b/source/CMake/cmake_config_files/HELM.config.cmake
@@ -0,0 +1,54 @@
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+
+SET(CAB_COMPILER "gcc41" CACHE STRING "gcc41, gcc43, intel9" FORCE) 
+# on MacOS X __APPLE__ is defined but not __unix__
+add_definitions(-D__unix__)
+SET(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING "ppc;i386;ppc64;x86_64" FORCE)
+
+#ADD_CXX_FLAGS(-arch x86_64 -L/usr/local/lib/x86_64)# -Wall -ansi)
+#ADD_CXX_BUILDTYPE_FLAGS(DEBUG -DDEBUG -D_DEBUG -gdwarf-2 -arch x86_64 -L/usr/local/lib/x86_64 -Wall -ansi)
+#ADD_CXX_BUILDTYPE_FLAGS(RELEASE -O3 -DNDEBUG -fomit-frame-pointer -finline-functions -funroll-all-loops -arch x86_64 -L/usr/local/lib/x86_64 -Wall -ansi)
+ADD_CXX_BUILDTYPE_FLAGS(DEBUG -DDEBUG -D_DEBUG -gdwarf-2 -Wall -ansi)
+ADD_CXX_BUILDTYPE_FLAGS(RELEASE -O3 -DNDEBUG -fomit-frame-pointer -finline-functions -funroll-all-loops -Wall -ansi)
+
+#ADD_C_FLAGS(-arch x86_64 -L/usr/local/lib/x86_64)# -Wall -ansi)
+
+
+SET(BOOST_VERSION "1.47.0")
+#IF(CAB_COMPILER MATCHES "gcc41")
+# SET(BOOST_USE_MULTITHREAD ON)
+# SET(BOOST_USE_STATIC_LIBS ON)
+#
+#   SET(BOOST_COMPILER_SUFFIX -xgcc40)
+# 
+# IF(BOOST_VERSION MATCHES "1.37.0" )
+#		SET(BOOST_INCLUDEDIR "/Users/hg/bin/boost/boost_1_37_0")
+#		SET(BOOST_LIBRARYDIR "/Users/hg/bin/boost/boost_1_37_0/lib")
+# ENDIF()
+## IF(BOOST_VERSION MATCHES "1.37.0" )
+##		SET(BOOST_INCLUDEDIR "/opt/local/include")
+##		SET(BOOST_LIBRARYDIR "/opt/local/lib")
+## ENDIF()
+#ENDIF()
+#IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+# MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+#ENDIF()
+
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(BOOST_VERSION MATCHES "1.47.0" )
+  SET(BOOST_INCLUDEDIR "/Users/hg/bin/boost/boost_1_47_0_bin/include")
+  SET(BOOST_LIBRARYDIR "/Users/hg/bin/boost/boost_1_47_0_bin/lib") 
+ENDIF()
+#################################################################################
+#  ZOLTAN  
+#################################################################################
+IF(${USE_ZOLTAN})
+  SET(ZOLTAN_INCLUDEDIR "/Users/hg/bin/zoltan_distrib_v3.501_bin/include")
+  SET(ZOLTAN_DEBUG_LIBRARY "/Users/hg/bin/zoltan_distrib_v3.501_bin/lib/libzoltan.a") 
+  SET(ZOLTAN_RELEASE_LIBRARY "/Users/hg/bin/zoltan_distrib_v3.501_bin/lib/libzoltan.a") 
+ENDIF()
+set(SOURCE_ROOT "/Users/hg/hg+/Konstantin_Kucher/Patchcode/src")  
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/HERMIT.config.cmake b/source/CMake/cmake_config_files/HERMIT.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..559bbb6deab44320693ac527a35e215b935e2743
--- /dev/null
+++ b/source/CMake/cmake_config_files/HERMIT.config.cmake
@@ -0,0 +1,28 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+
+SET(BOOST_VERSION "1.54.0" CACHE STRING "std: 1.54.0")
+
+# IF(BOOST_VERSION MATCHES "1.51.0" )
+#   SET(BOOST_INCLUDEDIR "/zhome/academic/HLRS/xrm/xrmkuchr/tools/boost_1_51_0")
+#   SET(BOOST_LIBRARYDIR "/zhome/academic/HLRS/xrm/xrmkuchr/tools/boost_1_51_0/stageGCC/lib")
+# 
+# ENDIF()
+# 
+# IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+#   MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+# ENDIF()
+
+
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "/zhome/academic/HLRS/xrm/xrmkuchr/tools/metis-5.0.2/include")
+  SET(METIS_DEBUG_LIBRARY "/zhome/academic/HLRS/xrm/xrmkuchr/tools/metis-5.0.2/build/Linux-x86_64/libmetis/libmetis.a") 
+  SET(METIS_RELEASE_LIBRARY "/zhome/academic/HLRS/xrm/xrmkuchr/tools/metis-5.0.2/build/Linux-x86_64/libmetis/libmetis.a") 
+ENDIF()
diff --git a/source/CMake/cmake_config_files/HICEGATE0.config.cmake b/source/CMake/cmake_config_files/HICEGATE0.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..efee9adbee829914f678e284a5473f5917866f88
--- /dev/null
+++ b/source/CMake/cmake_config_files/HICEGATE0.config.cmake
@@ -0,0 +1,63 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+#standard boost
+SET(BOOST_VERSION "1.54.0" CACHE STRING "std: 1.54.0")
+
+SET(USE_MPI_CXX_SYNTAX OFF)
+
+#IF(CAB_COMPILER MATCHES "gcc41")
+#   SET(BOOST_USE_MULTITHREAD ON)
+
+   #SET(BOOST_COMPILER_SUFFIX -gcc41)
+#   SET(BOOST_USE_STATIC_LIBS ON)
+
+   IF(BOOST_VERSION MATCHES "1.54.0" )
+      SET(BOOST_INCLUDEDIR "/gfs1/work/niivfcpu/tools/boost_1_54_0")
+      SET(BOOST_LIBRARYDIR "/gfs1/work/niivfcpu/tools/boost_1_54_0/stageGCC/lib")
+   ENDIF()
+#ENDIF()
+
+#IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+#  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+#ENDIF()
+
+#################################################################################
+#  ZOLTAN  
+#################################################################################
+IF(${USE_ZOLTAN})
+  SET(ZOLTAN_INCLUDEDIR "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Source/packages/zoltan/src/include")
+  SET(ZOLTAN_DEBUG_LIBRARY "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Build/packages/zoltan/src/libzoltan.a") 
+  SET(ZOLTAN_RELEASE_LIBRARY "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Build/packages/zoltan/src/libzoltan.a")
+ENDIF()
+
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "/gfs1/work/niivfcpu/tools/metis/include")
+  SET(METIS_DEBUG_LIBRARY "/gfs1/work/niivfcpu/tools/metis/lib/libmetis.a") 
+  SET(METIS_RELEASE_LIBRARY "/gfs1/work/niivfcpu/tools/metis/lib/libmetis.a") 
+ENDIF()
+
+#################################################################################
+#  YAML  
+#################################################################################
+IF(${USE_YAML})
+  SET(YAML_INCLUDEDIR "/gfs1/work/niivfcpu/tools/yaml-cpp/include")
+  SET(YAML_DEBUG_LIBRARY "/gfs1/work/niivfcpu/tools/yaml-cpp/build/libyaml-cpp.a") 
+  SET(YAML_RELEASE_LIBRARY "/gfs1/work/niivfcpu/tools/yaml-cpp/build/libyaml-cpp.a") 
+ENDIF()
+
+##################################################################################
+#  Bond
+##################################################################################
+IF(${USE_BOND})
+  SET(BOND_INCLUDEDIR "/gfs1/work/niivfcpu/tools/bond/bond_src/cpp/bond/fetol")
+  SET(BOND_DEBUG_LIBRARY "/gfs1/work/niivfcpu/tools/bond/bin/lib/libbond.a") 
+  SET(BOND_RELEASE_LIBRARY "/gfs1/work/niivfcpu/tools/bond/bin/lib/libbond.a") 
+ENDIF()
+
diff --git a/source/CMake/cmake_config_files/HLOGIN.config.cmake b/source/CMake/cmake_config_files/HLOGIN.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a88e4fa4cd56dcd3f74835e9bfe00a402eb21530
--- /dev/null
+++ b/source/CMake/cmake_config_files/HLOGIN.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/GOTTFRIED.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/HLOGIN1.config.cmake b/source/CMake/cmake_config_files/HLOGIN1.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a88e4fa4cd56dcd3f74835e9bfe00a402eb21530
--- /dev/null
+++ b/source/CMake/cmake_config_files/HLOGIN1.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/GOTTFRIED.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/HLOGIN2.config.cmake b/source/CMake/cmake_config_files/HLOGIN2.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a88e4fa4cd56dcd3f74835e9bfe00a402eb21530
--- /dev/null
+++ b/source/CMake/cmake_config_files/HLOGIN2.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/GOTTFRIED.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/HLOGIN3.config.cmake b/source/CMake/cmake_config_files/HLOGIN3.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a88e4fa4cd56dcd3f74835e9bfe00a402eb21530
--- /dev/null
+++ b/source/CMake/cmake_config_files/HLOGIN3.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/GOTTFRIED.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/HLOGIN4.config.cmake b/source/CMake/cmake_config_files/HLOGIN4.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a88e4fa4cd56dcd3f74835e9bfe00a402eb21530
--- /dev/null
+++ b/source/CMake/cmake_config_files/HLOGIN4.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/GOTTFRIED.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/HOST2.config.cmake b/source/CMake/cmake_config_files/HOST2.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..defe7bf92ad2089e4fa8f080a90514110cbdf83f
--- /dev/null
+++ b/source/CMake/cmake_config_files/HOST2.config.cmake
@@ -0,0 +1,46 @@
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__APPLE__)
+
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+  
+#################################################################################
+# MPI
+#################################################################################
+#SET(MPI_DIR  "C:/Program Files (x86)/mpich2")
+#SET(MPI_DIR  "C:/Program Files/mpich2")
+#SET(USE_MPI_CXX_SYNTAX OFF)
+#SET(MPI_COMPILER "C:/Program Files/mpich2/bin/mpicxx")
+#SET(MPI_INCLUDE_PATH "C:/Program Files (x86)/mpich2/include")
+#SET(MPI_LIBRARY "C:/Program Files/mpich2/lib/libmpi.a")
+#SET(MPI_CXX_LIBRARY "C:/Program Files/MPICH2/lib/cxx.lib")
+#################################################################################
+#  BOOST  
+#################################################################################
+SET(BOOST_VERSION "1.47")
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+#IF(BOOST_VERSION MATCHES "1.47" )
+  SET(BOOST_ROOT "/host/tools/boost/boost_1_47_0")
+  SET(BOOST_LIBRARYDIR "/host/tools/boost/boost_1_47_0/stageLinux/lib")  
+#ENDIF()
+#################################################################################
+#  ZOLTAN  
+#################################################################################
+IF(${USE_ZOLTAN})
+  SET(ZOLTAN_INCLUDEDIR "c:/Tools/zoltan/include")
+  SET(ZOLTAN_DEBUG_LIBRARY "c:/Tools/zoltan/lib/Debug/zoltan.lib") 
+  SET(ZOLTAN_RELEASE_LIBRARY "c:/Tools/zoltan/lib/Release/zoltan.lib") 
+ENDIF()
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "c:/Tools/metis-5.0.1/include")
+  SET(METIS_DEBUG_LIBRARY "c:/Tools/metis-5.0.1/build/libmetis/Debug/metis.lib") 
+  SET(METIS_RELEASE_LIBRARY "c:/Tools/metis-5.0.1/build/libmetis/Release/metis.lib") 
+ENDIF()
+set(SOURCE_ROOT "/host/Projects/pFluid/source")  
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/KONRAD.config.cmake b/source/CMake/cmake_config_files/KONRAD.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..7ae33238d176323ec8f1ef9a701877f3913d2ec1
--- /dev/null
+++ b/source/CMake/cmake_config_files/KONRAD.config.cmake
@@ -0,0 +1,55 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+#standard boost
+SET(BOOST_VERSION "1.54.0" CACHE STRING "std: 1.54.0")
+
+#SET(USE_MPI_CXX_SYNTAX OFF)
+
+#IF(CAB_COMPILER MATCHES "gcc41")
+#   SET(BOOST_USE_MULTITHREAD ON)
+
+   #SET(BOOST_COMPILER_SUFFIX -gcc41)
+#   SET(BOOST_USE_STATIC_LIBS ON)
+
+#    IF(BOOST_VERSION MATCHES "1.54.0" )
+#       SET(BOOST_INCLUDEDIR "/gfs1/work/niivfcpu/tools/boost_1_54_0")
+#       SET(BOOST_LIBRARYDIR "/gfs1/work/niivfcpu/tools/boost_1_54_0/stageGCC/lib")
+#    ENDIF()
+#ENDIF()
+
+#IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+#  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+#ENDIF()
+
+
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "/gfs1/work/niivfcpu/libs/metis/include")
+  SET(METIS_DEBUG_LIBRARY "/gfs1/work/niivfcpu/libs/metis/lib/libmetis.a") 
+  SET(METIS_RELEASE_LIBRARY "/gfs1/work/niivfcpu/libs/metis/lib/libmetis.a") 
+ENDIF()
+
+# #################################################################################
+# #  YAML  
+# #################################################################################
+# IF(${USE_YAML})
+#   SET(YAML_INCLUDEDIR "/hpc3lustre/software/irmb/yaml/yaml-cpp/include")
+#   SET(YAML_DEBUG_LIBRARY "/hpc3lustre/software/irmb/yaml/yaml-cpp/build/libyaml-cpp.a") 
+#   SET(YAML_RELEASE_LIBRARY "/hpc3lustre/software/irmb/yaml/yaml-cpp/build/libyaml-cpp.a") 
+# ENDIF()
+# 
+# ##################################################################################
+# #  Bond
+# ##################################################################################
+# IF(${USE_BOND})
+#   SET(BOND_INCLUDEDIR "/hpc3lustre/home/koskuche/projects/bond/bond_src/cpp/bond/fetol")
+#   SET(BOND_DEBUG_LIBRARY "/hpc3lustre/home/koskuche/projects/bond/bin/lib/libbond.a") 
+#   SET(BOND_RELEASE_LIBRARY "/hpc3lustre/home/koskuche/projects/bond/bin/lib/libbond.a") 
+# ENDIF()
+
diff --git a/source/CMake/cmake_config_files/KUBUNTU64.config.cmake b/source/CMake/cmake_config_files/KUBUNTU64.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..4d7a3091c40f90de1484a1cbc875956de5587526
--- /dev/null
+++ b/source/CMake/cmake_config_files/KUBUNTU64.config.cmake
@@ -0,0 +1,28 @@
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+SET(CAB_COMPILER "gcc43" FORCE) 
+SET(BOOST_VERSION "1.37.0")
+
+#################################################################################
+#  BOOST AND MPI
+#################################################################################
+IF(CAB_COMPILER MATCHES "gcc43")
+	IF(NEED_BOOST)
+	  SET(BOOST_USE_MULTITHREAD ON)
+	  SET(BOOST_USE_STATIC_LIBS ON)
+	  
+	  IF(BOOST_VERSION MATCHES "1.37.0" )
+
+	     SET(USER_DEFINED_BOOST_COMPILER -gcc43)
+        SET(BOOST_INCLUDEDIR "/opt/boost_1_37_0/gcc4.3.1/include/boost-1_37")
+	     SET(BOOST_LIBRARYDIR "/opt/boost_1_37_0/gcc4.3.1/lib")
+        SET(BOOST_COMPILER_SUFFIX -gcc43)
+   
+     ENDIF()
+   ENDIF()
+ENDIF()
+
+IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+ENDIF()
diff --git a/source/CMake/cmake_config_files/LRR_OPTERON.config.cmake b/source/CMake/cmake_config_files/LRR_OPTERON.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..dce597c90d151a4f8a08a35ed28fb7b736fe89a5
--- /dev/null
+++ b/source/CMake/cmake_config_files/LRR_OPTERON.config.cmake
@@ -0,0 +1,41 @@
+OPTION(CAB_COMPILER_64BIT "64BIT COMPILATION"  ON)
+
+IF(NOT CAB_COMPILER})
+   SET(BOOST_VERSION "1.37.0")
+ENDIF()
+
+IF(NOT CAB_COMPILER})
+  SET(CAB_COMPILER "intel10")
+ENDIF()
+
+SET(CAB_COMPILER ${CAB_COMPILER} CACHE STRING "intel10" FORCE) 
+SET(CPU_TYPE "Opteron")
+
+#################################################################################
+#  BOOST AND MPI
+#################################################################################
+IF(CAB_COMPILER MATCHES "intel10" )
+########################################################################################
+##                                      intel10                                      ##
+########################################################################################
+   SET(BOOST_USE_MULTITHREAD ON)
+   
+   IF(BOOST_VERSION MATCHES "1.37.0" )
+   
+     SET(BOOST_USE_STATIC_LIBS ON)
+
+     SET(BOOST_INCLUDEDIR "/home/freudigx/sw/boost/intel/boost_1_37_0")
+     SET(BOOST_LIBRARYDIR "/home/freudigx/sw/boost/intel/boost_1_37_0/lib")
+
+     SET( BOOST_COMPILER_SUFFIX "-il" ) 
+   ENDIF()
+
+   SET(MPI_DIR  "/sw/mpi/mvapich-1.0-intel101")
+
+   SET_CXX_COMPILER("icpc")
+   SET_C_COMPILER("icc")
+ENDIF()
+
+IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+  MESSAGE("${BOOST_VERSION} not found on "${CAB_MACHINE}" for specified compiler")
+ENDIF()
diff --git a/source/CMake/cmake_config_files/LUDWIG.config.cmake b/source/CMake/cmake_config_files/LUDWIG.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..c25c581297138278bb789fc4bc1d5533116f98df
--- /dev/null
+++ b/source/CMake/cmake_config_files/LUDWIG.config.cmake
@@ -0,0 +1,66 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+#standard boost: 1.50.0
+SET(BOOST_VERSION "1.54.0" CACHE STRING "std: 1.54.0")
+
+#SET(MPI_DIR  "/hpc3lustre/software/lib/openmpi-1.4.1-gcc41")
+
+SET(USE_MPI_CXX_SYNTAX OFF)
+#SET(MPI_COMPILER "/hpc3lustre/software/lib/openmpi-1.4.1-gcc41/bin/mpicxx")
+
+#IF(CAB_COMPILER MATCHES "gcc41")
+   #SET(BOOST_USE_MULTITHREAD ON)
+
+   #SET(BOOST_COMPILER_SUFFIX -gcc41)
+   #SET(BOOST_USE_STATIC_LIBS ON)
+
+   #IF(BOOST_VERSION MATCHES "1.54.0" )
+      SET(BOOST_INCLUDEDIR "/hpc3lustre/software/irmb/boost/boost_1_54_0")
+      SET(BOOST_LIBRARYDIR "/hpc3lustre/software/irmb/boost/boost_1_54_0/stageINTEL/lib")
+   #ENDIF()
+#ENDIF()
+
+IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+ENDIF()
+
+#################################################################################
+#  ZOLTAN  
+#################################################################################
+IF(${USE_ZOLTAN})
+  SET(ZOLTAN_INCLUDEDIR "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Source/packages/zoltan/src/include")
+  SET(ZOLTAN_DEBUG_LIBRARY "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Build/packages/zoltan/src/libzoltan.a") 
+  SET(ZOLTAN_RELEASE_LIBRARY "/hpc3lustre/software/irmb/Trilinos/trilinos-10.6.4-Build/packages/zoltan/src/libzoltan.a")
+ENDIF()
+
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "/hpc3lustre/software/irmb/metis/include")
+  SET(METIS_DEBUG_LIBRARY "/hpc3lustre/software/irmb/metis/lib/libmetis.a") 
+  SET(METIS_RELEASE_LIBRARY "/hpc3lustre/software/irmb/metis/lib/libmetis.a") 
+ENDIF()
+
+#################################################################################
+#  YAML  
+#################################################################################
+IF(${USE_YAML})
+  SET(YAML_INCLUDEDIR "/hpc3lustre/software/irmb/yaml/yaml-cpp/include")
+  SET(YAML_DEBUG_LIBRARY "/hpc3lustre/software/irmb/yaml/yaml-cpp/build/libyaml-cpp.a") 
+  SET(YAML_RELEASE_LIBRARY "/hpc3lustre/software/irmb/yaml/yaml-cpp/build/libyaml-cpp.a") 
+ENDIF()
+
+##################################################################################
+#  Bond
+##################################################################################
+IF(${USE_BOND})
+  SET(BOND_INCLUDEDIR "/hpc3lustre/home/koskuche/projects/bond/bond_src/cpp/bond/fetol")
+  SET(BOND_DEBUG_LIBRARY "/hpc3lustre/home/koskuche/projects/bond/bin/lib/libbond.a") 
+  SET(BOND_RELEASE_LIBRARY "/hpc3lustre/home/koskuche/projects/bond/bin/lib/libbond.a") 
+ENDIF()
+
diff --git a/source/CMake/cmake_config_files/M01.config.cmake b/source/CMake/cmake_config_files/M01.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..3553a2a9282a752c3ed96c644aa8003e90fb0b36
--- /dev/null
+++ b/source/CMake/cmake_config_files/M01.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/LUDWIG.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/M02.config.cmake b/source/CMake/cmake_config_files/M02.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..3553a2a9282a752c3ed96c644aa8003e90fb0b36
--- /dev/null
+++ b/source/CMake/cmake_config_files/M02.config.cmake
@@ -0,0 +1 @@
+INCLUDE("CMake/cmake_config_files/LUDWIG.config.cmake")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/MAFALDA.config.cmake b/source/CMake/cmake_config_files/MAFALDA.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..cfc0d659a30f82d79e54df76637050e35a10b87d
--- /dev/null
+++ b/source/CMake/cmake_config_files/MAFALDA.config.cmake
@@ -0,0 +1,68 @@
+#################################################################################
+# COMPILER FLAG VAR
+#################################################################################
+IF(NOT CAB_COMPILER})
+  IF( ${MSVC_VERSION} MATCHES "1400" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1400" AND NOT CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc8_32" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND CMAKE_CL_64)
+      SET( CAB_COMPILER "msvc9_64" )
+  ELSEIF( ${MSVC_VERSION} MATCHES "1500" AND NOT CMAKE_CL_64)
+     SET( CAB_COMPILER "msvc9_32" )
+  ELSE()
+     MESSAGE(ERROR, "unknown ms studio version MSVC_VERSION = "${MSVC_VERSION})  
+  ENDIF()
+ENDIF()
+
+#################################################################################
+# MPI
+#################################################################################
+IF(CMAKE_CL_64)
+  SET(MPI_DIR  "c:/Program Files/MPICH2")
+ELSE()
+  SET(MPI_DIR  "c:/Program Files (x86)/MPICH2")
+ENDIF()
+
+#################################################################################
+#  BOOST  
+#################################################################################
+IF(NEED_BOOST)
+  SET(BOOST_USE_MULTITHREAD ON)
+  SET(BOOST_USE_STATIC_LIBS ON)
+  
+  IF(BOOST_VERSION MATCHES "1.35.0.svn" )
+  
+     SET(BOOST_INCLUDEDIR "E:/3rdPartyLibs/boost/boost_1_35")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35/lib/x86_64bit")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "E:/3rdPartyLibs/boost/boost_1_35/lib/x86_32bit")
+     ENDIF()
+
+  ELSEIF(BOOST_VERSION MATCHES "1.35.0" )
+  
+     SET(BOOST_INCLUDEDIR "D:/code/3rdParty/PhysicsEngine/boost")
+  
+     IF(CMAKE_CL_64) 
+       SET(BOOST_LIBRARYDIR "D:/code/3rdParty/PhysicsEngine/boost")
+     ELSE()
+       SET(BOOST_LIBRARYDIR "D:/code/3rdParty/PhysicsEngine/boost")
+     ENDIF()
+  
+  ELSEIF(BOOST_VERSION MATCHES "1.34.1" )
+     SET(BOOST_INCLUDEDIR "D:/code/boost_1_34_1")
+     SET(BOOST_LIBRARYDIR "D:/code/boost_1_34_1")
+
+  ELSEIF(BOOST_VERSION MATCHES "1.36.0" )
+     SET(BOOST_INCLUDEDIR "D:/code/boost_1_36_0")
+     SET(BOOST_LIBRARYDIR "D:/code/boost_1_36_0")
+
+  ENDIF()
+  
+  IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+    MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+  ENDIF()
+ENDIF()
+  
diff --git a/source/CMake/cmake_config_files/PIPPIN.config.cmake b/source/CMake/cmake_config_files/PIPPIN.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..8c548b2f1c8bfdf816894cbc4b6b48fa2fa05034
--- /dev/null
+++ b/source/CMake/cmake_config_files/PIPPIN.config.cmake
@@ -0,0 +1,25 @@
+#################################################################################
+# MPI
+#################################################################################
+IF(CMAKE_CL_64)
+  IF(NEED_MPI) 
+     MESSAGE(FATAL_ERROR "kein 64 bit mpi installiert")
+  ENDIF()
+  #SET(MPI_DIR  "c:/Program Files/MPICH2")
+ELSE()
+  SET(MPI_DIR  "c:/Program Files (x86)/MPICH2")
+ENDIF()
+
+#################################################################################
+#  BOOST  
+#################################################################################
+SET(BOOST_VERSION 1.38.0)
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(CMAKE_CL_64)
+   MESSAGE(FATAL_ERROR "kein 64 bit boost ${BOOST_VERSION} installiert")
+ELSE()
+  SET(BOOST_INCLUDEDIR "C:/Program Files (x86)/boost/boost_1_38")
+  SET(BOOST_LIBRARYDIR "C:/Program Files (x86)/boost/boost_1_38/lib")
+ENDIF()
diff --git a/source/CMake/cmake_config_files/SHELOB.config.cmake b/source/CMake/cmake_config_files/SHELOB.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..f2f62ad9dd1c710ca881653d56a4c1c2a422a348
--- /dev/null
+++ b/source/CMake/cmake_config_files/SHELOB.config.cmake
@@ -0,0 +1,49 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__APPLE__)
+
+#################################################################################
+#  RUBY
+#################################################################################
+#IF(CMAKE_CL_64)
+#   SET(RUBY_EXECUTABLE "C:/ruby191/bin/ruby.exe")
+#   SET(RUBY_LIBRARY "C:/ruby191/lib/msvcr90-ruby191.lib")
+#ELSE()
+#   SET(RUBY_EXECUTABLE "C:/ruby186/bin/ruby.exe")
+#   SET(RUBY_LIBRARY "C:/ruby186/lib/msvcrt-ruby18.lib")
+#ENDIF()
+
+#################################################################################
+#  SWIG
+#################################################################################
+SET(SWIG_EXECUTABLE "/Users/freud/dev/swig/bin/swig")
+
+
+########################################################################################
+##                            BOOST ALLGMEINGUELTIG                                   ##
+########################################################################################
+#standard boost: 1.41.0
+SET(BOOST_VERSION "1.41.0" CACHE STRING "std: 1.41.0")
+
+SET(MPI_DIR  "/usr/local/mpich2/gcc401")
+
+IF(CAB_COMPILER MATCHES "gcc42")
+   SET(BOOST_USE_MULTITHREAD ON)
+
+   SET(BOOST_COMPILER_SUFFIX -xgcc40)
+   SET(BOOST_USE_STATIC_LIBS ON)
+
+   IF(BOOST_VERSION MATCHES "1.41.0" )
+      SET(BOOST_INCLUDEDIR "/scratch/shared/boost_1_41_0/include")
+      SET(BOOST_LIBRARYDIR "/scratch/shared/boost_1_41_0/lib")
+   ELSEIF(BOOST_VERSION MATCHES "1.39.0" )
+      SET(BOOST_INCLUDEDIR "/usr/local/boost/gcc401/boost_1_39_0/include/boost-1_39")
+      SET(BOOST_LIBRARYDIR "/usr/local/boost/gcc401/boost_1_39_0/lib")
+   ENDIF()
+ENDIF()
+
+IF(BOOST_VERSION AND NOT BOOST_INCLUDEDIR)
+  MESSAGE("${BOOST_VERSION} not found on ${CAB_MACHINE} for specified compiler")
+ENDIF()
+
+
diff --git a/source/CMake/cmake_config_files/SMAUG.config.cmake b/source/CMake/cmake_config_files/SMAUG.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..09c9f4420ea26d937e5dacbe2573022f318c2989
--- /dev/null
+++ b/source/CMake/cmake_config_files/SMAUG.config.cmake
@@ -0,0 +1,27 @@
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+  
+
+#################################################################################
+#  BOOST  
+#################################################################################
+SET(BOOST_VERSION "1.44")
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(BOOST_VERSION MATCHES "1.44" )
+  SET(BOOST_INCLUDEDIR "C:/boost/boost_1_44_0")
+  SET(BOOST_LIBRARYDIR "C:/boost/boost_1_44_0/stage64/lib") 
+ENDIF()
+#################################################################################
+#  ZOLTAN  
+#################################################################################
+  SET(ZOLTAN_INCLUDEDIR "c:/zoltan/include")
+  SET(ZOLTAN_LIBRARY "c:/zoltan/lib/Debug/zoltan.lib") 
+
+set(SOURCE_ROOT "g:/Kostja/pFluid/source") 
+
+
+
+  
diff --git a/source/CMake/cmake_config_files/SP0201.config.cmake b/source/CMake/cmake_config_files/SP0201.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..bf28750def2e59a571e64af3c62ef9149041e616
--- /dev/null
+++ b/source/CMake/cmake_config_files/SP0201.config.cmake
@@ -0,0 +1,27 @@
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__AIX__)
+
+
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+
+#################################################################################
+# MPI
+#################################################################################
+SET(USE_MPI_CXX_SYNTAX OFF)
+#################################################################################
+#  BOOST
+#################################################################################
+SET(BOOST_VERSION "1.44")
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(BOOST_VERSION MATCHES "1.44" )
+  SET(BOOST_INCLUDEDIR "/sp6/userdeisa/lrz102bk/tools/boost_1_44_0")
+  SET(BOOST_LIBRARYDIR "/sp6/userdeisa/lrz102bk/tools/boost_1_44_0/stage/lib")
+ENDIF()
+
+set(SOURCE_ROOT "/sp6/userdeisa/lrz102bk/projects/pFluid/source")
+set(pFluid_ROOT "/sp6/userdeisa/lrz102bk/projects/pFluid")
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/TOLKIEN.config.cmake b/source/CMake/cmake_config_files/TOLKIEN.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..5ad8d989c1d5f26368190237f1ea89d8898595bd
--- /dev/null
+++ b/source/CMake/cmake_config_files/TOLKIEN.config.cmake
@@ -0,0 +1,22 @@
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+  
+#################################################################################
+# MPI
+#################################################################################
+SET(MPI_DIR  "C:/Program Files/mpich2")
+
+#################################################################################
+#  BOOST  
+#################################################################################
+SET(BOOST_VERSION "1.38")
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(BOOST_VERSION MATCHES "1.38" )
+  SET(BOOST_INCLUDEDIR "C:/Program Files/boost/boost_1_38")
+  SET(BOOST_LIBRARYDIR "C:/Program Files/boost/boost_1_38/lib")
+ENDIF()
+  
+
diff --git a/source/CMake/cmake_config_files/TOLKIEN2.config.cmake b/source/CMake/cmake_config_files/TOLKIEN2.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..5ad8d989c1d5f26368190237f1ea89d8898595bd
--- /dev/null
+++ b/source/CMake/cmake_config_files/TOLKIEN2.config.cmake
@@ -0,0 +1,22 @@
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+  
+#################################################################################
+# MPI
+#################################################################################
+SET(MPI_DIR  "C:/Program Files/mpich2")
+
+#################################################################################
+#  BOOST  
+#################################################################################
+SET(BOOST_VERSION "1.38")
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(BOOST_VERSION MATCHES "1.38" )
+  SET(BOOST_INCLUDEDIR "C:/Program Files/boost/boost_1_38")
+  SET(BOOST_LIBRARYDIR "C:/Program Files/boost/boost_1_38/lib")
+ENDIF()
+  
+
diff --git a/source/CMake/cmake_config_files/UBUNTU.config.cmake b/source/CMake/cmake_config_files/UBUNTU.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..b266286f44fe98575f932128080c22a57b1535d2
--- /dev/null
+++ b/source/CMake/cmake_config_files/UBUNTU.config.cmake
@@ -0,0 +1,46 @@
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__unix__)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__UNIX__)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D__APPLE__)
+
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+  
+#################################################################################
+# MPI
+#################################################################################
+#SET(MPI_DIR  "C:/Program Files (x86)/mpich2")
+#SET(MPI_DIR  "C:/Program Files/mpich2")
+#SET(USE_MPI_CXX_SYNTAX OFF)
+#SET(MPI_COMPILER "C:/Program Files/mpich2/bin/mpicxx")
+#SET(MPI_INCLUDE_PATH "C:/Program Files (x86)/mpich2/include")
+#SET(MPI_LIBRARY "C:/Program Files/mpich2/lib/libmpi.a")
+#SET(MPI_CXX_LIBRARY "C:/Program Files/MPICH2/lib/cxx.lib")
+#################################################################################
+#  BOOST  
+#################################################################################
+SET(BOOST_VERSION "1.47")
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(BOOST_VERSION MATCHES "1.47" )
+  SET(BOOST_ROOT "/host/tools/boost/boost_1_47_0")
+  SET(BOOST_LIBRARYDIR "/host/tools/boost/boost_1_47_0/stageLinux/lib")  
+ENDIF()
+#################################################################################
+#  ZOLTAN  
+#################################################################################
+IF(${USE_ZOLTAN})
+  SET(ZOLTAN_INCLUDEDIR "/home/kostja/tools/Zoltan_v3.5/bin/include")
+  SET(ZOLTAN_DEBUG_LIBRARY "/home/kostja/tools/Zoltan_v3.5/bin/lib/libzoltan.a") 
+  SET(ZOLTAN_RELEASE_LIBRARY "/home/kostja/tools/Zoltan_v3.5/bin/lib/libzoltan.a") 
+ENDIF()
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "/home/kostja/tools/metis-5.0.1/include")
+  SET(METIS_DEBUG_LIBRARY "/home/kostja/tools/metis-5.0.1/build/Linux-x86_64/libmetis/libmetis.a") 
+  SET(METIS_RELEASE_LIBRARY "/home/kostja/tools/metis-5.0.1/build/Linux-x86_64/libmetis/libmetis.a") 
+ENDIF()
+set(SOURCE_ROOT "/host/Projects/pFluid/source")  
\ No newline at end of file
diff --git a/source/CMake/cmake_config_files/YWANG.config.cmake b/source/CMake/cmake_config_files/YWANG.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..9e802e4840926ccbd1ff24df77e6ef8752c46fb6
--- /dev/null
+++ b/source/CMake/cmake_config_files/YWANG.config.cmake
@@ -0,0 +1,24 @@
+IF(NOT CMAKE_CXX_COMPILER)
+   MESSAGE(FATAL_ERROR "before cmake-config-file can be included -> project must be extecuted")
+ENDIF()
+  
+#################################################################################
+#  BOOST  
+#################################################################################
+SET(BOOST_VERSION "1.49")
+SET(BOOST_USE_MULTITHREAD ON)
+SET(BOOST_USE_STATIC_LIBS ON)
+
+IF(BOOST_VERSION MATCHES "1.49" )
+  SET(BOOST_ROOT "C:/boost/boost_1_49_0")
+  SET(BOOST_LIBRARYDIR "c:/boost/boost_1_49_0/stageMSVC64/lib")  
+ENDIF()
+
+#################################################################################
+#  METIS  
+#################################################################################
+IF(${USE_METIS})
+  SET(METIS_INCLUDEDIR "c:/metis-5.1.0/include")
+  SET(METIS_DEBUG_LIBRARY "c:/metis-5.1.0/build/libmetis/Debug/metis.lib") 
+  SET(METIS_RELEASE_LIBRARY "c:/metis-5.1.0/build/libmetis/Release/metis.lib") 
+ENDIF()
diff --git a/source/CMake/compilerflags/gcc33.cmake b/source/CMake/compilerflags/gcc33.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..88e52224110fa5177048e4aa40737fc846d9cb29
--- /dev/null
+++ b/source/CMake/compilerflags/gcc33.cmake
@@ -0,0 +1,44 @@
+###############################################################################################################
+## 
+##  gcc33
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type)
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -ffast-math -Wall -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   IF(CPU_TYPE MATCHES "Opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-march=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-march=opteron" )
+     
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-march=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-march=opteron" )
+   ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+      MESSAGE(STATUS "gcc33 has no OpenMP support -> OpenMP deactivated")
+      SET(USE_OPENMP "OFF")
+   ENDIF()
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type)
+
diff --git a/source/CMake/compilerflags/gcc34.cmake b/source/CMake/compilerflags/gcc34.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..f052bf9fe2dabc36b72afdbf5424fafb7410676b
--- /dev/null
+++ b/source/CMake/compilerflags/gcc34.cmake
@@ -0,0 +1,44 @@
+###############################################################################################################
+## 
+##  gcc34
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -ffast-math -Wall -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+   
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   IF(CPU_TYPE MATCHES "Opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" )
+
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" )
+   ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+      MESSAGE(STATUS "gcc34 has no OpenMP support -> OpenMP deactivated")
+      SET(USE_OPENMP "OFF")
+   ENDIF()
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
diff --git a/source/CMake/compilerflags/gcc40.cmake b/source/CMake/compilerflags/gcc40.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..e16bc3504dd436253d05ce24e56ba297f3ef6760
--- /dev/null
+++ b/source/CMake/compilerflags/gcc40.cmake
@@ -0,0 +1,54 @@
+###############################################################################################################
+## 
+##  gcc40
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   IF(CPU_TYPE MATCHES "Opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" )
+
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" )
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## 64Bit support
+   ###############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	MESSAGE(STATUS "gcc40 has no OpenMP support -> OpenMP deactivated")
+   	SET(USE_OPENMP "OFF")
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc41.cmake b/source/CMake/compilerflags/gcc41.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..34f54b74c2bb6030fea770d0599cb9545550b17e
--- /dev/null
+++ b/source/CMake/compilerflags/gcc41.cmake
@@ -0,0 +1,51 @@
+###############################################################################################################
+## 
+##  gcc41
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   IF(CPU_TYPE MATCHES "Opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" )
+   ENDIF()
+
+   ###############################################################################################################
+   ## 64Bit support
+   ###############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	MESSAGE(STATUS "gcc41 has no OpenMP support -> OpenMP deactivated")
+   	SET(USE_OPENMP "OFF")
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc42.cmake b/source/CMake/compilerflags/gcc42.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a81e7ff0f3e8234944e11bdb0f7716785e86862b
--- /dev/null
+++ b/source/CMake/compilerflags/gcc42.cmake
@@ -0,0 +1,57 @@
+###############################################################################################################
+## 
+##  gcc42
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   #Anmerkung: bei O3 oder "O2 mit finline-function" gibt es Probleme beim MuParser. bug im gcc? 
+   #Bug kann durch "test" in MuParser/examples ueberprueft werden
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O2 -fomit-frame-pointer -funroll-all-loops -fPIC")
+   #LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O2 -fomit-frame-pointer -finline-functions -funroll-all-loops")
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   IF(CPU_TYPE MATCHES "Opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" )
+
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" )
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## 64Bit support
+   ###############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp")
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc43.cmake b/source/CMake/compilerflags/gcc43.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..bc7deed357ea326e258c7ee3f110fd38a0ce917b
--- /dev/null
+++ b/source/CMake/compilerflags/gcc43.cmake
@@ -0,0 +1,49 @@
+###############################################################################################################
+## 
+##  gcc43
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   IF(CPU_TYPE MATCHES "Opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" )
+
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" )
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## 64Bit support
+   ###############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp")
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc44.cmake b/source/CMake/compilerflags/gcc44.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..10b8f71f7693789d79f298fedebb5e03d89ddc07
--- /dev/null
+++ b/source/CMake/compilerflags/gcc44.cmake
@@ -0,0 +1,54 @@
+###############################################################################################################
+## 
+##  gcc44
+##
+###############################################################################################################
+
+#MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type)
+#ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type)
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+  
+   IF(CPU_TYPE MATCHES "Opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" )
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## 64Bit support
+   ###############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp")
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc45.cmake b/source/CMake/compilerflags/gcc45.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..5c4d597e2ebef788272bb7cc48941797ee20d779
--- /dev/null
+++ b/source/CMake/compilerflags/gcc45.cmake
@@ -0,0 +1,54 @@
+###############################################################################################################
+## 
+##  gcc45
+##
+###############################################################################################################
+
+#MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type)
+#ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type)
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+  
+   # IF(CPU_TYPE MATCHES "Opteron")
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron")
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" )
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron")
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" )
+   # ENDIF()
+
+
+   # ###############################################################################################################
+   # ## 64Bit support
+   # ###############################################################################################################
+   # IF( ${use64BitOptions} ) 
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   # ENDIF()
+
+
+   # ###############################################################################################################
+   # ## OpenMP support
+   # ###############################################################################################################
+   # IF(USE_OPENMP)
+   	# LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp")
+   # ENDIF()
+
+
+   # ###############################################################################################################
+   # ## mt support
+   # ###############################################################################################################
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   # IF(NOT APPLE)
+      # LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   # ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc46.cmake b/source/CMake/compilerflags/gcc46.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..2f56fac857cf3a63f2c9eb3ef8e857c94941ac4e
--- /dev/null
+++ b/source/CMake/compilerflags/gcc46.cmake
@@ -0,0 +1,54 @@
+###############################################################################################################
+## 
+##  gcc46
+##
+###############################################################################################################
+
+#MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type)
+#ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type)
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+  
+   # IF(CPU_TYPE MATCHES "Opteron")
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mtune=opteron")
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-mcpu=opteron" )
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mtune=opteron")
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-mcpu=opteron" )
+   # ENDIF()
+
+
+   # ###############################################################################################################
+   # ## 64Bit support
+   # ###############################################################################################################
+   # IF( ${use64BitOptions} ) 
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   # ENDIF()
+
+
+   # ###############################################################################################################
+   # ## OpenMP support
+   # ###############################################################################################################
+   # IF(USE_OPENMP)
+   	# LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp")
+   # ENDIF()
+
+
+   # ###############################################################################################################
+   # ## mt support
+   # ###############################################################################################################
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   # LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   # IF(NOT APPLE)
+      # LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   # ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc47.cmake b/source/CMake/compilerflags/gcc47.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..2a6b91042c55e3bb0159030676310b541a952a2f
--- /dev/null
+++ b/source/CMake/compilerflags/gcc47.cmake
@@ -0,0 +1,42 @@
+###############################################################################################################
+## 
+##  gcc47
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+   #############################################################################################################
+   # Flags
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   #############################################################################################################
+   # 64Bit support
+   #############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+   #############################################################################################################
+   # OpenMP support
+   #############################################################################################################
+   IF(USE_OPENMP)
+   	MESSAGE(STATUS "gcc41 has no OpenMP support -> OpenMP deactivated")
+   	SET(USE_OPENMP "OFF")
+   ENDIF()
+
+   #############################################################################################################
+   # mt support
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc48.cmake b/source/CMake/compilerflags/gcc48.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..989afcc3e886ef1a92921982bdda4e720f7df436
--- /dev/null
+++ b/source/CMake/compilerflags/gcc48.cmake
@@ -0,0 +1,42 @@
+###############################################################################################################
+## 
+##  gcc48
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+   #############################################################################################################
+   # Flags
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   #############################################################################################################
+   # 64Bit support
+   #############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+   #############################################################################################################
+   # OpenMP support
+   #############################################################################################################
+   IF(USE_OPENMP)
+   	MESSAGE(STATUS "gcc48 has no OpenMP support -> OpenMP deactivated")
+   	SET(USE_OPENMP "OFF")
+   ENDIF()
+
+   #############################################################################################################
+   # mt support
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc49.cmake b/source/CMake/compilerflags/gcc49.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..26f641ae19d9d0270f17e234ee37b3c5e0496f20
--- /dev/null
+++ b/source/CMake/compilerflags/gcc49.cmake
@@ -0,0 +1,42 @@
+###############################################################################################################
+## 
+##  gcc49
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+   #############################################################################################################
+   # Flags
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   #############################################################################################################
+   # 64Bit support
+   #############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+   #############################################################################################################
+   # OpenMP support
+   #############################################################################################################
+   IF(USE_OPENMP)
+   	MESSAGE(STATUS "gcc49 has no OpenMP support -> OpenMP deactivated")
+   	SET(USE_OPENMP "OFF")
+   ENDIF()
+
+   #############################################################################################################
+   # mt support
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc51.cmake b/source/CMake/compilerflags/gcc51.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..1c4df2a693a8104ef4204715f4910d576a777336
--- /dev/null
+++ b/source/CMake/compilerflags/gcc51.cmake
@@ -0,0 +1,50 @@
+###############################################################################################################
+## 
+##  gcc51
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+   #############################################################################################################
+   # Flags
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   #############################################################################################################
+   # 64Bit support
+   #############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+   #############################################################################################################
+   # OpenMP support
+   #############################################################################################################
+   IF(USE_OPENMP)
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp")
+   ENDIF()
+
+   #############################################################################################################
+   # mt support
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+   
+   #############################################################################################################
+   # c++ 11 support
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11")
+   
+   
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/gcc52.cmake b/source/CMake/compilerflags/gcc52.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..41649c34a3b94c3703878554309c1c3cf032876e
--- /dev/null
+++ b/source/CMake/compilerflags/gcc52.cmake
@@ -0,0 +1,50 @@
+###############################################################################################################
+## 
+##  gcc52
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+   #############################################################################################################
+   # Flags
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-Wno-deprecated") #deprecated header warning (jarl benutzt sstream weil schneller und so) 
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops -fPIC")
+
+   #############################################################################################################
+   # 64Bit support
+   #############################################################################################################
+   IF( ${use64BitOptions} ) 
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-m64" )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS   "-m64" )
+   ENDIF()
+
+   #############################################################################################################
+   # OpenMP support
+   #############################################################################################################
+   IF(USE_OPENMP)
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fopenmp")
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fopenmp")
+   ENDIF()
+
+   #############################################################################################################
+   # mt support
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+   
+   #############################################################################################################
+   # c++ 11 support
+   #############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-std=c++11")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-std=c++11")
+   
+   
+
+   IF(NOT APPLE)
+      LIST(APPEND CAB_ADDITIONAL_LINK_PROPS "-lrt")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/icc101.cmake b/source/CMake/compilerflags/icc101.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..3cd6b535e82ca27b02b055428d1103ef363e8e0a
--- /dev/null
+++ b/source/CMake/compilerflags/icc101.cmake
@@ -0,0 +1,51 @@
+###############################################################################################################
+## 
+##  intel10 
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF( ${use64BitOptions} )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) 
+   ENDIF()
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266")  #function "__GKfree" declared implicitly
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops")
+
+   IF(CPU_TYPE MATCHES "Opteron")
+     IF(WIN32)
+     		LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-QxO") #Enables SSE3, SSE2 and SSE instruction sets optimizations for non-Intel CPUs
+     		LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-QxO")     #Enables SSE3, SSE2 and SSE instruction sets optimizations for non-Intel CPUs
+      ELSE()
+     		#auf unserem cluster gibt es kein ss3 SET( CAB_CXX_FLAGS "${CAB_CXX_FLAGS} -xO")  #Enables SSE3, SSE2 and SSE instruction sets optimizations for non-Intel CPUs
+     		#gibt teils probleme beim ausfuehren: SET( CAB_C_FLAGS "${CAB_C_FLAGS} -xO")      #Enables SSE3, SSE2 and SSE instruction sets optimizations for non-Intel CPUs
+      ENDIF()
+   ELSE()
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-fast")
+     	LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-fast")    
+   ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp")
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/icc130.cmake b/source/CMake/compilerflags/icc130.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..346b9c25768f93df7d48e9c499aa712b502e11c9
--- /dev/null
+++ b/source/CMake/compilerflags/icc130.cmake
@@ -0,0 +1,38 @@
+###############################################################################################################
+## 
+##  intel10 
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   #~ IF( ${use64BitOptions} )
+     #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) 
+   #~ ENDIF()
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O")
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654")
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+#~ 
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266")  #function "__GKfree" declared implicitly
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops")
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp")
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/icc140.cmake b/source/CMake/compilerflags/icc140.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..e2ff9a1c2ed7401ce81667c5cc8fbba60a301741
--- /dev/null
+++ b/source/CMake/compilerflags/icc140.cmake
@@ -0,0 +1,38 @@
+###############################################################################################################
+## 
+##  intel140 
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   #~ IF( ${use64BitOptions} )
+     #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) 
+   #~ ENDIF()
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O")
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654")
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+#~ 
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266")  #function "__GKfree" declared implicitly
+   #~ LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fomit-frame-pointer -finline-functions -funroll-all-loops")
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp")
+   ENDIF()
+
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/icc91.cmake b/source/CMake/compilerflags/icc91.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a77f20ff8e98de88ac3379269240c1fd2420a6fa
--- /dev/null
+++ b/source/CMake/compilerflags/icc91.cmake
@@ -0,0 +1,47 @@
+###############################################################################################################
+## 
+##  intel9 
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF( ${use64BitOptions} )
+     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D__amd64" ) 
+   ENDIF()
+
+   #IF( ${compiler} MATCHES "INTEL_91_IPO")
+   #	LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-ipo" ) 
+   #	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-ipo" ) 
+   #	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-opt-mem-bandwidth2" ) 
+   #ENDIF( ${compiler} MATCHES "INTEL_91_IPO")
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-O3 -fast -fomit-frame-pointer -finline-functions")
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd68" ) #integer conversion resulted in a change of sign
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd186") # pointless comparison of unsigned integer with zero
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd654")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1125") #virtual function override intended
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd1224") #warning directive: This file includes at least one deprecated or antiquated header
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd377")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-wd327")  #class "std::auto_ptr<RCF::I_ClientTransport>" has no suitable copy constructor
+
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-wd266")  #function "__GKfree" declared implicitly
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-O3 -fast -fomit-frame-pointer -finline-functions")
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-openmp")
+   ENDIF()
+
+   ###############################################################################################################
+   ## mt support
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-pthread")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_C_COMPILER_FLAGS "-pthread")
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/msvc10_32.cmake b/source/CMake/compilerflags/msvc10_32.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..60f733c7ed5faf3bd7d1f6e1d563201ebdf1fd62
--- /dev/null
+++ b/source/CMake/compilerflags/msvc10_32.cmake
@@ -0,0 +1,59 @@
+###############################################################################################################
+## 
+##  MSVC 2010 (Version 10.0) 32bit (msvc10_32)
+##
+###############################################################################################################
+    
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF(${use64BitOptions})
+      MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be OFF for msvc10_32")
+   ENDIF()
+
+   ###############################################################################################################
+   ## USE_UNSECURE_STL_VECTORS_RELEASE ?
+   ###############################################################################################################
+   OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF)
+   IF(USE_UNSECURE_STL_VECTORS_RELEASE)
+      # More MSVC specific compilation flags
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE")
+   ENDIF()
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_WARNINGS")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy...
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #ansonsten funzt mit boost das compilieren unter windows nimmer
+
+#foreach(flag_var
+#        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+#        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+#   if(${flag_var} MATCHES "/MD")
+#      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+#   endif(${flag_var} MATCHES "/MD")
+#endforeach(flag_var)
+       
+#  IF(${build_type} MATCHES BINARY)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES STATIC)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES SHARED)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MDd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MD"  )
+#  ELSE()
+#     MESSAGE(FATAL_ERROR "build_type=${build_type} doesn't match BINARY, SHARED or STATIC")
+#  ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp")
+   ENDIF()
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/msvc10_64.cmake b/source/CMake/compilerflags/msvc10_64.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..5db3a092d55f22eca2acdd271198d6ed48fa3c3e
--- /dev/null
+++ b/source/CMake/compilerflags/msvc10_64.cmake
@@ -0,0 +1,78 @@
+###############################################################################################################
+## 
+##  MSVC 2010 (Version 10.0) 64bit (msvc10_64)
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF(NOT ${use64BitOptions})
+      MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be ON for msvc10_64")
+   ENDIF()
+
+   ###############################################################################################################
+   ## USE_UNSECURE_STL_VECTORS_RELEASE ?
+   ###############################################################################################################
+   OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF)
+   IF(USE_UNSECURE_STL_VECTORS_RELEASE)
+      # More MSVC specific compilation flags
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS")
+   ENDIF()
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy...
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #ansonsten funzt mit boost das compilieren unter windows nimmer
+
+#folgendes kann man mittlerweile weglassen..
+#unser project kompilert einwandfrei durch!
+
+#hack (solange CMAke OMPILER_FLAGS_<CONFIG> nicht supported
+#foreach(flag_var
+#        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+#        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+#   if(${flag_var} MATCHES "/MD")
+#      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+#   endif(${flag_var} MATCHES "/MD")
+#endforeach(flag_var)
+
+#  IF(${build_type} MATCHES BINARY)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES STATIC)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES SHARED)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MDd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MD"  )
+#  ELSE()
+#     MESSAGE(FATAL_ERROR "build_type=${build_type} doesn't match BINARY, SHARED or STATIC")
+#  ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp")
+   ENDIF()
+
+   ###############################################################################################################
+   ## boost + rcf extensions
+   ###############################################################################################################
+   IF(NEED_BOOST)
+      IF(BOOST_VERSION)
+         STRING(REGEX REPLACE "(.*)\\.(.*)\\.(.*)" "\\2" BoostMinorVersion "${BOOST_VERSION}")
+         IF(NOT BoostMinorVersion LESS 35 )     
+         
+            #IF(NOT ${build_type} MATCHES SHARED)
+               #LIST(APPEND CAB_COMPILER_ADDITIONAL_LINK_PROPS "/NODEFAULTLIB:\"MSVCRT\"" )
+            #ENDIF()
+         ENDIF() 
+      ENDIF()
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/msvc11_32.cmake b/source/CMake/compilerflags/msvc11_32.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..67c463f99d09861742a1c973258e90351da33b54
--- /dev/null
+++ b/source/CMake/compilerflags/msvc11_32.cmake
@@ -0,0 +1,38 @@
+###############################################################################################################
+## 
+##  MSVC 2012 (Version 11.0) 32bit (msvc11_32)
+##
+###############################################################################################################
+    
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF(${use64BitOptions})
+      MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be OFF for msvc11_32")
+   ENDIF()
+
+   ###############################################################################################################
+   ## USE_UNSECURE_STL_VECTORS_RELEASE ?
+   ###############################################################################################################
+   OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF)
+   IF(USE_UNSECURE_STL_VECTORS_RELEASE)
+      # More MSVC specific compilation flags
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE")
+   ENDIF()
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_WARNINGS")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy...
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #ansonsten funzt mit boost das compilieren unter windows nimmer
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp")
+   ENDIF()
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/msvc11_64.cmake b/source/CMake/compilerflags/msvc11_64.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..53a667bc930a42239cd88c65550062e92d01f6c7
--- /dev/null
+++ b/source/CMake/compilerflags/msvc11_64.cmake
@@ -0,0 +1,38 @@
+###############################################################################################################
+## 
+##  MSVC 2012 (Version 11.0) 64bit (msvc11_64)
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF(NOT ${use64BitOptions})
+      MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be ON for msvc11_64")
+   ENDIF()
+
+   ###############################################################################################################
+   ## USE_UNSECURE_STL_VECTORS_RELEASE ?
+   ###############################################################################################################
+   OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF)
+   IF(USE_UNSECURE_STL_VECTORS_RELEASE)
+      # More MSVC specific compilation flags
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS")
+   ENDIF()
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy...
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #ansonsten funzt mit boost das compilieren unter windows nimmer
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp")
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/msvc8_32.cmake b/source/CMake/compilerflags/msvc8_32.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..cebc116464760924ba4214e645c2b54b16d988df
--- /dev/null
+++ b/source/CMake/compilerflags/msvc8_32.cmake
@@ -0,0 +1,51 @@
+###############################################################################################################
+## 
+##  MSVC 2005 (Version 8.0) 32bit (msvc8_32)
+##
+###############################################################################################################
+    
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF(${use64BitOptions})
+      MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be OFF for msvc10_32")
+   ENDIF()
+
+   ###############################################################################################################
+   ## USE_UNSECURE_STL_VECTORS_RELEASE ?
+   ###############################################################################################################
+   OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF)
+   IF(USE_UNSECURE_STL_VECTORS_RELEASE)
+      # More MSVC specific compilation flags
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE")
+   ENDIF()
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_WARNINGS")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy...
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #ansonsten funzt mit boost das compilieren unter windows nimmer
+
+#  IF(${build_type} MATCHES BINARY)
+#     LIST(APPEND CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES STATIC)
+#     LIST(APPEND CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES SHARED)
+#     LIST(APPEND CAB_COMPILER_ADDITIONAL_LINK_PROPS_DEBUG   "/MDd" )
+#     LIST(APPEND CAB_COMPILER_ADDITIONAL_LINK_PROPS_RELEASE "/MD"  )
+#  ELSE()
+#     MESSAGE(FATAL_ERROR "build_type=${build_type} doesn't match BINARY, SHARED or STATIC")
+#  ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp")
+   ENDIF()
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/msvc8_64.cmake b/source/CMake/compilerflags/msvc8_64.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..b5cd87c5ccd29abfaa7388f44e7ead2f572079f8
--- /dev/null
+++ b/source/CMake/compilerflags/msvc8_64.cmake
@@ -0,0 +1,51 @@
+###############################################################################################################
+## 
+##  MSVC 2005 (Version 8.0) 32bit (msvc8_64)
+##
+###############################################################################################################
+    
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF(NOT ${use64BitOptions})
+      MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be ON for msvc8_64")
+   ENDIF()
+
+   ###############################################################################################################
+   ## USE_UNSECURE_STL_VECTORS_RELEASE ?
+   ###############################################################################################################
+   OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF)
+   IF(USE_UNSECURE_STL_VECTORS_RELEASE)
+      # More MSVC specific compilation flags
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE")
+   ENDIF()
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -D_CRT_SECURE_NO_WARNINGS)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy...
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #ansonsten funzt mit boost das compilieren unter windows nimmer
+
+#   IF(${build_type} MATCHES BINARY)
+#      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#   ELSEIF(${build_type} MATCHES STATIC)
+#      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#   ELSEIF(${build_type} MATCHES SHARED)
+#      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MDd" )
+#      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MD"  )
+#   ELSE()
+#      MESSAGE(FATAL_ERROR "build_type=${build_type} doesn't match BINARY, SHARED or STATIC")
+#   ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp")
+   ENDIF()
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/msvc9_32.cmake b/source/CMake/compilerflags/msvc9_32.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..b3792c099669323bc537a9291a8cccda37e18eb6
--- /dev/null
+++ b/source/CMake/compilerflags/msvc9_32.cmake
@@ -0,0 +1,59 @@
+###############################################################################################################
+## 
+##  MSVC 2008 (Version 9.0) 32bit (msvc9_32)
+##
+###############################################################################################################
+    
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF(${use64BitOptions})
+      MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be OFF for msvc9_32")
+   ENDIF()
+
+   ###############################################################################################################
+   ## USE_UNSECURE_STL_VECTORS_RELEASE ?
+   ###############################################################################################################
+   OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF)
+   IF(USE_UNSECURE_STL_VECTORS_RELEASE)
+      # More MSVC specific compilation flags
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE")
+   ENDIF()
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_WARNINGS")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy...
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #ansonsten funzt mit boost das compilieren unter windows nimmer
+
+#foreach(flag_var
+#        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+#        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+#   if(${flag_var} MATCHES "/MD")
+#      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+#   endif(${flag_var} MATCHES "/MD")
+#endforeach(flag_var)
+       
+#  IF(${build_type} MATCHES BINARY)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES STATIC)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES SHARED)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MDd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MD"  )
+#  ELSE()
+#     MESSAGE(FATAL_ERROR "build_type=${build_type} doesn't match BINARY, SHARED or STATIC")
+#  ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp")
+   ENDIF()
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMake/compilerflags/msvc9_64.cmake b/source/CMake/compilerflags/msvc9_64.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..1bedf31255862982bcb1cb6630a2ede438a15995
--- /dev/null
+++ b/source/CMake/compilerflags/msvc9_64.cmake
@@ -0,0 +1,80 @@
+###############################################################################################################
+## 
+##  MSVC 2008 (Version 9.0) 64bit (msvc9_64)
+##
+## 
+##
+###############################################################################################################
+
+MACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
+
+   IF(NOT ${use64BitOptions})
+      MESSAGE(FATAL_ERROR "SET_COMPILER_SPECIFIC_FLAGS: use64BitOptions must be ON for msvc10_64")
+   ENDIF()
+
+   ###############################################################################################################
+   ## USE_UNSECURE_STL_VECTORS_RELEASE ?
+   ###############################################################################################################
+   OPTION(USE_UNSECURE_STL_VECTORS_RELEASE "_SECURE_SCL=0" OFF)
+   IF(USE_UNSECURE_STL_VECTORS_RELEASE)
+      # More MSVC specific compilation flags
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SECURE_SCL=0")
+      LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_SCL_SECURE_NO_WARNINGS")
+   ENDIF()
+
+   ###############################################################################################################
+   ## Flags
+   ###############################################################################################################
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "-D_CRT_SECURE_NO_DEPRECATE")
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4996") #deprecated strcpy...
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/wd4800") #forcing value to bool 'true' or 'false' (performance warning)
+   LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/bigobj") #ansonsten funzt mit boost das compilieren unter windows nimmer
+
+#folgendes kann man mittlerweile weglassen..
+#unser project kompilert einwandfrei durch!
+
+#hack (solange CMAke OMPILER_FLAGS_<CONFIG> nicht supported
+#foreach(flag_var
+#        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+#        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+#   if(${flag_var} MATCHES "/MD")
+#      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+#   endif(${flag_var} MATCHES "/MD")
+#endforeach(flag_var)
+
+#  IF(${build_type} MATCHES BINARY)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES STATIC)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MTd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MT"  )
+#  ELSEIF(${build_type} MATCHES SHARED)
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_DEBUG   "/MDd" )
+#     LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS_RELEASE "/MD"  )
+#  ELSE()
+#     MESSAGE(FATAL_ERROR "build_type=${build_type} doesn't match BINARY, SHARED or STATIC")
+#  ENDIF()
+
+   ###############################################################################################################
+   ## OpenMP support
+   ###############################################################################################################
+   IF(USE_OPENMP)
+   	LIST(APPEND CAB_COMPILER_ADDTIONAL_CXX_COMPILER_FLAGS "/openmp")
+   ENDIF()
+
+   ###############################################################################################################
+   ## boost + rcf extensions
+   ###############################################################################################################
+   IF(NEED_BOOST)
+      IF(BOOST_VERSION)
+         STRING(REGEX REPLACE "(.*)\\.(.*)\\.(.*)" "\\2" BoostMinorVersion "${BOOST_VERSION}")
+         IF(NOT BoostMinorVersion LESS 35 )     
+         
+            #IF(NOT ${build_type} MATCHES SHARED)
+               #LIST(APPEND CAB_COMPILER_ADDITIONAL_LINK_PROPS "/NODEFAULTLIB:\"MSVCRT\"" )
+            #ENDIF()
+         ENDIF() 
+      ENDIF()
+   ENDIF()
+
+ENDMACRO(SET_COMPILER_SPECIFIC_FLAGS_INTERN build_type use64BitOptions)
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..951b10e5a59baf533e81183393764bf6b9bd1f7f
--- /dev/null
+++ b/source/CMakeLists.txt
@@ -0,0 +1,127 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+#workaround for machine with mpi compiler wrapper
+#it most define before project
+
+#MPI
+#set(CMAKE_C_COMPILER mpicc)
+#set(CMAKE_CXX_COMPILER mpicxx)
+
+#Intel MPI
+#set(CMAKE_C_COMPILER mpiicc)
+#set(CMAKE_CXX_COMPILER mpiicpc)
+
+#Cray
+#set(CMAKE_C_COMPILER cc)
+#set(CMAKE_CXX_COMPILER CC)
+
+PROJECT(VirtualFluids)
+
+set(SOURCE_ROOT "../source")
+
+#debug build for unix
+ #IF(UNIX)
+  #SET(CMAKE_BUILD_TYPE DEBUG)
+ #ENDIF()
+
+SET(USE_ZOLTAN OFF CACHE BOOL "include Zoltan library support")
+SET(USE_METIS ON CACHE BOOL "include METIS library support")
+SET(USE_MPI ON CACHE BOOL "include MPI library support")
+SET(USE_VTK OFF CACHE BOOL "include VTK library support")
+SET(USE_CATALYST OFF CACHE BOOL "include Paraview Catalyst support")
+SET(USE_PYTHON OFF CACHE BOOL "include Python scripting support")
+SET(USE_FETOL OFF CACHE BOOL "include FETOL library support")
+SET(USE_INTEL OFF CACHE BOOL "include Intel compiler support")
+SET(USE_GCC OFF CACHE BOOL "include gcc compiler support")
+
+#CAB
+INCLUDE("CMake/CMakeCABMacros.txt")
+
+#MPI
+FIND_PACKAGE(MPI REQUIRED)
+#SET(MPI_CXX_LINK_FLAGS -mpe=mpilog)
+
+SET(BOOST_USE_MULTITHREAD ON)
+SET(Boost_USE_STATIC_LIBS ON)
+#SET(Boost_DEBUG TRUE)
+
+SET(bv ${BOOST_VERSION}) #hack for find boost, after next command ${BOOST_VERSION} would be set to 0
+#FIND_PACKAGE(Boost ${bv} COMPONENTS system date_time thread serialization chrono regex)
+#FIND_PACKAGE(Boost ${BOOST_VERSION} COMPONENTS system date_time thread serialization chrono regex)
+#FIND_PACKAGE(Boost ${bv} COMPONENTS system thread serialization date_time)
+#SET(BOOST_VERSION ${bv})
+IF(${USE_PYTHON})
+  FIND_PACKAGE(Boost ${BOOST_VERSION} COMPONENTS system date_time thread serialization chrono regex python)
+ELSE(${USE_PYTHON})
+    FIND_PACKAGE(Boost ${BOOST_VERSION} COMPONENTS system date_time thread serialization chrono regex)
+ENDIF()
+
+##################################################################################
+#  Java
+##############################################################################
+### FindJNI.cmake
+IF(${USE_FETOL})
+    find_package(JNI REQUIRED) 
+ENDIF()
+
+#VTK
+IF(${USE_VTK})
+    #find_package(VTK 6.1 NO_MODULE)
+    FIND_PACKAGE(VTK REQUIRED)
+    INCLUDE_DIRECTORIES(${VTK_INCLUDE_DIRS})
+ENDIF()
+MESSAGE("VTK_INCLUDE_DIRS = " ${VTK_INCLUDE_DIRS})
+
+IF(${USE_CATALYST})
+    find_package(ParaView 4.3 REQUIRED COMPONENTS vtkPVPythonCatalyst)
+    include("${PARAVIEW_USE_FILE}")
+ENDIF()
+
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DCAB_BOOST)
+LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DNOMINMAX)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DBOOST_SIGNALS_NO_DEPRECATION_WARNING)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DCAB_RUBY)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -mpe=mpilog)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -noshlib)
+#LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DSINGLEPRECISION)
+
+IF(${USE_ZOLTAN})
+ LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DVF_ZOLTAN)
+ENDIF() 
+IF(${USE_METIS})
+  LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DVF_METIS)
+ENDIF()
+IF(${USE_MPI})
+  LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DVF_MPI)
+ENDIF()
+IF(${USE_FETOL})
+  LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DVF_FETOL)
+ENDIF()
+IF(${USE_VTK})
+  LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DVF_VTK)
+ENDIF()
+IF(${USE_CATALYST})
+  LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DVF_CATALYST)
+ENDIF()
+IF(${USE_PYTHON})
+  FIND_PACKAGE(PythonLibs)
+  INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIR})
+  LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DVF_PYTHON)
+  LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DBOOST_PYTHON_STATIC_LIB)
+  add_subdirectory(python)
+ENDIF()
+
+IF(${USE_INTEL})
+   LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DMPICH_IGNORE_CXX_SEEK)
+   LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DMPICH_SKIP_MPICXX)
+ENDIF()
+#message("MPI_CXX_LIBRARY: " ${MPI_CXX_LIBRARY})
+#IF(MPI_CXX_LIBRARY)
+   #SET(MPI_LIBRARY ${MPI_LIBRARY} ${MPI_CXX_LIBRARY})
+   #message("MPI_LIBRARY: " ${MPI_LIBRARY})
+#ENDIF() 
+
+add_subdirectory(VirtualFluidsCore)
+
+INCLUDE("Applications.cmake")
+
diff --git a/source/Documentation/doc.h b/source/Documentation/doc.h
new file mode 100644
index 0000000000000000000000000000000000000000..bdac8f8c3e0922cff1b31fead26d3c324a8647fe
--- /dev/null
+++ b/source/Documentation/doc.h
@@ -0,0 +1,31 @@
+//index page for doxygen
+
+/*! \mainpage
+ *
+ *  \section intro_sec Introduction
+ *  <i>VirtualFluids</i> is an adaptive, parallel Lattice-Boltzmann flow solver 
+ *  which is comprised of various cores 
+ *  and use second order accurate compact interpolation at the interfaces, 
+ *  coupling grids of different resolutions. 
+ *  The software framework is based on object-oriented technology and uses tree-like data structures. 
+ *  These data structures are also suitable for hierarchical parallelization using a combination of PThreads and MPI and dynamic load balancing. 
+ *   
+ *  \section install_sec Installation
+ *
+ *  \subsection step1 Step 1: CMake
+ *  Download and install <a href="http://www.cmake.org/">CMake</a>. 
+ *  If you have Windows OS oder X-Windows for Linux/Unix start <i>cmake-gui</i>.
+ *  If you work in terminal start <i>ccmake</i>.
+ *  \subsection step2 Step 2: project configuration
+ *  You need set a path for <i>VirtualFluids</i> source code. It is allays <i>source</i> directory at the end of path.
+ *  E.g. c:/vf/source. You need also set a path to build binaries. If you click <b>Configure</b> button start a project wizard and you can choose a compiler.
+ *  Set <b>Grouped</b> and <b>Advanced</b> check boxes in CMake. In the group <i>USE</i> you have follow important options:
+ *  \li USE_BOND    - using an agent based communication framework for fault tolerance BOND
+ *  \li USE_METIS   - using a domain decomposition tool METIS    
+ *  \li USE_MPI       - using MPI for distributed memory parallelization   
+ *  \li USE_YAML     - using YAML
+ *  \li USE_ZOLTAN - using domain decomposition tool ZOLTAN 
+ *  There are externals library and you need additionally compile them.    
+ *  \subsection step3 Step 4: project compilation
+ *  Compile you project with suitable compiler.  
+ */
\ No newline at end of file
diff --git a/source/Documentation/doc/install.html b/source/Documentation/doc/install.html
new file mode 100644
index 0000000000000000000000000000000000000000..06eaea91eb71b0c33cee25b215ffc53b17f66727
--- /dev/null
+++ b/source/Documentation/doc/install.html
@@ -0,0 +1,18 @@
+\section install_sec Installation
+
+\subsection step1 Step 1: CMake
+Download and install <a href="http://www.cmake.org/">CMake</a>. 
+If you have Windows OS oder X-Windows for Linux/Unix start <i>cmake-gui</i>.
+If you work in terminal start <i>ccmake</i>.
+\subsection step2 Step 2: project configuration
+You need set a path for <i>VirtualFluids</i> source code. It is allays <i>source</i> directory at the end of path.
+E.g. c:/vf/source. You need also set a path to build binaries. If you click <b>Configure</b> button start a project wizard and you can choose a compiler.
+Set <b>Grouped</b> and <b>Advanced</b> check boxes in CMake. In the group <i>USE</i> you have follow important options:
+\li USE_BOND    - using an agent based communication framework for fault tolerance BOND
+\li USE_METIS   - using a domain decomposition tool METIS    
+\li USE_MPI       - using MPI for distributed memory parallelization   
+\li USE_YAML     - using YAML
+\li USE_ZOLTAN - using domain decomposition tool ZOLTAN 
+There are externals library and you need additionally compile them.    
+\subsection step3 Step 4: project compilation
+Compile you project with suitable compiler.  
diff --git a/source/Documentation/doc/intstall.md b/source/Documentation/doc/intstall.md
new file mode 100644
index 0000000000000000000000000000000000000000..fdf6a0069f431e72ee1df584c99becfe2b497bc8
--- /dev/null
+++ b/source/Documentation/doc/intstall.md
@@ -0,0 +1,18 @@
+# Installation    {#installation}
+## Step 1: CMake  
+Download and install [CMake](http://www.cmake.org). 
+If you have Windows OS oder X-Windows for Linux/Unix start *cmake-gui*.
+If you work in terminal start *ccmake*.
+## Step 2: project configuration
+You need set a path for *VirtualFluids* source code. It is allays *source* directory at the end of path.
+E.g. *c:/vf/source*. You need also set a path to build binaries. E.g. *c:/vf/bin*. If you click **Configure** button start a project wizard and you can choose a compiler.
+Set **Grouped** and **Advanced** check boxes in CMake. In the group *USE* you have follow important options:
+* USE_BOND    - using an agent based communication framework for fault tolerance BOND
+* USE_METIS   - using a domain decomposition tool METIS    
+* USE_MPI       - using MPI for distributed memory parallelization   
+* USE_YAML     - using YAML
+* USE_ZOLTAN - using domain decomposition tool ZOLTAN  
+
+There are externals library and you need additionally compile them.    
+## Step 4: project compilation
+Compile you project with suitable compiler
\ No newline at end of file
diff --git a/source/Documentation/doc/main.md b/source/Documentation/doc/main.md
new file mode 100644
index 0000000000000000000000000000000000000000..aa5b8a8ae1d6e229bcd329db89d44ed07314bb6e
--- /dev/null
+++ b/source/Documentation/doc/main.md
@@ -0,0 +1,11 @@
+# Introduction {#mainpage}
+
+## Introduction
+*VirtualFluids* is an adaptive, parallel Lattice-Boltzmann flow solver 
+which is comprised of various cores 
+and use second order accurate compact interpolation at the interfaces, 
+coupling grids of different resolutions. 
+The software framework is based on object-oriented technology and uses tree-like data structures. 
+These data structures are also suitable for hierarchical parallelization using a combination of PThreads and MPI and dynamic load balancing. 
+
+[Installation](md__d_1__projects_b_fluid_source_doc_doc_intstall.html)
diff --git a/source/Documentation/doxygen/VF_Doxyfile.dox b/source/Documentation/doxygen/VF_Doxyfile.dox
new file mode 100644
index 0000000000000000000000000000000000000000..194815b406b3a45742a370db167fb22980aff689
--- /dev/null
+++ b/source/Documentation/doxygen/VF_Doxyfile.dox
@@ -0,0 +1,2365 @@
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = VirtualFluids
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         = 
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = 
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO           = D:/Projects/bFluid/source/doc/doxygen/logo.png
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = z:\VirtualFluids\doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                = 
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            = 
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES         = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = ../doc \
+                         ../../lib
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS = 
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = main.md
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more acurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS          = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        = 
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  = 
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       = 
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               = 
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           = 
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     = 
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           = 
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     = 
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       = 
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       = 
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     = 
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           = 
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           = 
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             = VF_FETOL \
+                         VF_MPI \
+                         VF_METIS \
+                         VF_ZOLTAN
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            = 
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               = 
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           = 
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           = 
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/source/Documentation/doxygen/logo.png b/source/Documentation/doxygen/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..61253fbec8bf6a1617f19f8629de5ebc4f0f02e6
Binary files /dev/null and b/source/Documentation/doxygen/logo.png differ
diff --git a/source/Documentation/doxygen/start.html b/source/Documentation/doxygen/start.html
new file mode 100644
index 0000000000000000000000000000000000000000..215fb59dc23071c4001359ff551109c8232b33d4
--- /dev/null
+++ b/source/Documentation/doxygen/start.html
@@ -0,0 +1 @@
+<meta http-equiv="refresh" content="0; URL=html/index.html">
\ No newline at end of file
diff --git a/source/IncludsList.cmake b/source/IncludsList.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..730ed546d3c2743db77b63bab8bbe06929f33665
--- /dev/null
+++ b/source/IncludsList.cmake
@@ -0,0 +1,40 @@
+#directory pathes for header files
+
+INCLUDE_DIRECTORIES(${SOURCE_ROOT})
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/BoundaryCondition )
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Connectors)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Data)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Interactors)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/LBM)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Parallel)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Grid)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Visitors)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/CoProcessors)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/Utilities)
+
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/numerics/geometry3d)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/numerics/geometry3d/Creator)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/numerics/geometry3d/KdTree)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/basics/container)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/basics/memory)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/basics/objects)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/basics/transmiitter)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/basics/utilities)
+INCLUDE_DIRECTORIES(${SOURCE_ROOT}/ThirdParty/Library/basics/writer)
+
+INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+INCLUDE_DIRECTORIES(${METIS_INCLUDEDIR})
+INCLUDE_DIRECTORIES(${ZOLTAN_INCLUDEDIR})
+IF(${USE_VTK})
+    INCLUDE_DIRECTORIES(${VTK_INCLUDE_DIRS})
+ENDIF()
+IF(${USE_FETOL})
+    INCLUDE_DIRECTORIES(${SOURCE_ROOT}/VirtualFluidsCore/FETOL)
+    INCLUDE_DIRECTORIES(${YAML_INCLUDEDIR})
+    INCLUDE_DIRECTORIES(${BOND_INCLUDEDIR})
+    INCLUDE_DIRECTORIES(${FETOL_INCLUDEDIR})
+ENDIF()
\ No newline at end of file
diff --git a/source/PythonVirtualFluids/CMakeLists.txt b/source/PythonVirtualFluids/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7d6e0595950c8a4a14c51e33b43970b1a1f2d97c
--- /dev/null
+++ b/source/PythonVirtualFluids/CMakeLists.txt
@@ -0,0 +1,25 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(PyVirtualFluids)
+
+INCLUDE(${SOURCE_ROOT}/lib/IncludsList.txt) 
+
+#################################################################
+###   LOCAL FILES                                             ###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp  )
+ 
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(src FILES ${SPECIFIC_FILES})
+  
+SET(CAB_ADDITIONAL_LINK_LIBRARIES vfluids)
+
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(virtualfluids SHARED)
diff --git a/source/PythonVirtualFluids/PySimulation.h b/source/PythonVirtualFluids/PySimulation.h
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/source/PythonVirtualFluids/PyVirtualFluids.cpp b/source/PythonVirtualFluids/PyVirtualFluids.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..23fa9574e85881a663fa76cf38dc1e4bf30c9f5b
--- /dev/null
+++ b/source/PythonVirtualFluids/PyVirtualFluids.cpp
@@ -0,0 +1,38 @@
+#ifdef VF_PYTHON
+
+#include <boost/python.hpp>
+#include "vfluids.h"
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE(virtualfluids)
+{
+   //bool (Configuration::*get1)(const std::string&, std::string&)const = &Configuration::get;
+   //bool (Configuration::*get2)(const std::string&, int&)const = &Configuration::get;
+   //bool (Configuration::*get3)(const std::string&, long&)const = &Configuration::get;
+   //bool (Configuration::*get4)(const std::string&, double&)const = &Configuration::get;
+   //bool (Configuration::*get5)(const std::string&, bool&)const = &Configuration::get;
+   //class_<Configuration>("Configuration")
+
+   //   .def("load", &Configuration::load)
+   //   .def("get", get1)
+   //   .def("get", get2)
+   //   .def("get", get3)
+   //   .def("get", get4)
+   //   .def("get", get5)
+   //   ;
+   class_<Configuration>("Configuration")
+
+      .def("load", &Configuration::load)
+      .def("getString", &Configuration::getString)
+      .def("getInt", &Configuration::getInt)
+      .def("getLong", &Configuration::getLong)
+      .def("getDouble", &Configuration::getDouble)
+      .def("getFloat", &Configuration::getFloat)
+      .def("getBool", &Configuration::getBool)
+      ;
+
+
+
+}
+
+#endif
diff --git a/source/PythonVirtualFluids/VFtest.py b/source/PythonVirtualFluids/VFtest.py
new file mode 100644
index 0000000000000000000000000000000000000000..2af3ad55ebb358d842a1bee3b7c29253bf0ca642
--- /dev/null
+++ b/source/PythonVirtualFluids/VFtest.py
@@ -0,0 +1,2 @@
+import virtualfluids
+config=virtualfluids.load("config.txt")
diff --git a/source/Scripts/CollectHeader.py b/source/Scripts/CollectHeader.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b5a80996748854b99ad9aa62bde6f5787b788cd
--- /dev/null
+++ b/source/Scripts/CollectHeader.py
@@ -0,0 +1,28 @@
+import os
+import string
+
+file_name = 'lib.h'
+folder='c:/Projects/bFluid/source/lib'
+
+if os.path.exists(file_name):
+    os.remove(file_name)
+
+fo=file(file_name,'w')
+
+folder='c:/Projects/bFluid/source/lib'
+
+for roots,dirs,files in os.walk(folder):
+    for header in files:
+        if header.endswith(('.h','.hpp')):
+            header=str(os.path.join(roots,header))
+            header_new = header.lstrip(folder)
+            x=header_new.replace('\\','/')
+            y=str('#include <'+x+'>\n')
+            y=y.replace('</','<')
+            fo.write(y)
+fo.close()
+
+print 'lib.h is generated!'
+
+
+            
diff --git a/source/Scripts/CollectTar.py b/source/Scripts/CollectTar.py
new file mode 100644
index 0000000000000000000000000000000000000000..5db2d22bb4bf1fb45fe423c1d9144e3518fc7bf4
--- /dev/null
+++ b/source/Scripts/CollectTar.py
@@ -0,0 +1,17 @@
+import os
+os.system("date")
+
+pathin = "/gfs1/work/niivfcpu/scratch/kucher/BKanaltest/steps/step*"
+pathout = "/gfs1/work/niivfcpu/scratch/kucher/BKanaltest/tar/step"
+tar = "tar -cvf "
+
+start = 281750
+step = 2250
+stop = start + step * 10
+
+print stop
+
+for i in range(start, stop, step):
+  command = tar + pathout + str(i) + ".tar " + pathin + str(i) + "*"
+  #print command
+  os.system(command)
\ No newline at end of file
diff --git a/source/Scripts/ConnTest.py b/source/Scripts/ConnTest.py
new file mode 100644
index 0000000000000000000000000000000000000000..757ce30241c9d252f0e0678bfd20d8c6d419d79a
--- /dev/null
+++ b/source/Scripts/ConnTest.py
@@ -0,0 +1,44 @@
+print 30*27
+print 675/27
+print 3*1*9
+
+bMaxX1 = 10
+bMaxX2 = 10
+bMaxX3 = 10
+
+minX1 = 0
+minX2 = 0
+minX3 = 0
+maxX1 = bMaxX1 - 1
+maxX2 = bMaxX2 - 1
+maxX3 = bMaxX3 - 1
+
+lMin1X1 = maxX1 - 6
+lMax1X1 = lMin1X1 + 4
+lMin1X3 = maxX3 - 6
+lMax1X3 = lMin1X3
+
+lMin2X1 = maxX1 - 6
+lMax2X1 = lMin2X1
+lMin2X3 = maxX3 - 6
+lMax2X3 = lMin2X3 + 4
+
+lMin1X2 = minX2;
+lMax1X2 = maxX2 + - 1;
+
+print 'FC send: ' + str(((lMax1X1-lMin1X1+1)*(lMax1X2-lMin1X2+1)*(lMax1X3-lMin1X3+1) + (lMax2X1-lMin2X1+1)*(lMax1X2-lMin1X2+1)*(lMax2X3-lMin2X3+1)) / 2)
+
+lMin1X1 = maxX1 - 3
+lMax1X1 = lMin1X1 + 2
+lMin1X3 = maxX3 - 3
+lMax1X3 = lMin1X3
+
+lMin2X1 = maxX1 - 3
+lMax2X1 = lMin2X1
+lMin2X3 = maxX3 - 3
+lMax2X3 = lMin2X3 + 2
+
+lMin1X2 = minX2
+lMax1X2 = 4
+
+print 'CF receive: ' + str(((lMax1X1-lMin1X1+1)*(lMax1X2-lMin1X2+1)*(lMax1X3-lMin1X3+1) + (lMax2X1-lMin2X1+1)*(lMax1X2-lMin1X2+1)*(lMax2X3-lMin2X3+1)))
diff --git a/source/Scripts/ExtractTar.py b/source/Scripts/ExtractTar.py
new file mode 100644
index 0000000000000000000000000000000000000000..b9d94216ad1d1a658831a06dd4fda3f809e142a1
--- /dev/null
+++ b/source/Scripts/ExtractTar.py
@@ -0,0 +1,17 @@
+import os
+os.system("date")
+
+pathin = "/hpc3lustre/work/koskuche/SFB880/BKanalTestBerlin/tar/step"
+pathout = "/hpc3lustre/work/koskuche/SFB880/BKanalTestBerlin/steps"
+tar = "tar -xvf "
+
+start = 491000
+step = 2250
+stop = start + step * 2
+
+print stop
+
+for i in range(start, stop, step):
+  command = tar + pathin + str(i) + ".tar -C " + pathout + " --strip-components=7"
+  #print command
+  os.system(command)
\ No newline at end of file
diff --git a/source/Scripts/PathLinesMax.py b/source/Scripts/PathLinesMax.py
new file mode 100644
index 0000000000000000000000000000000000000000..8afa41b9adfbdfe0ace2623a06b0f0b4923d1658
--- /dev/null
+++ b/source/Scripts/PathLinesMax.py
@@ -0,0 +1,27 @@
+#script create data file for maximum strain rate in path lines
+ 
+from paraview.simple import *
+
+file='d:/temp/pathLine/pathLine.pvtu'
+print file
+#read data set file
+reader = XMLPartitionedUnstructuredGridReader(FileName=file)
+
+threshold = Threshold(reader)
+threshold.Scalars = 'ID'
+r=1.0
+threshold.ThresholdRange = [r, r]
+print threshold.ThresholdRange
+#help(threshold)
+
+pcalc = PythonCalculator(threshold)
+pcalc.Expression = 'max(tauxy)'
+pcalc.UpdatePipeline()
+#pcalc.GetOutput()
+#help(pcalc)
+#pcalc.inputs[0].Points[:,0]
+print pcalc.PointData.Points
+points = pcalc.Points
+#help(points)
+
+print pcalc.GetPointDataInformation().GetArray("result").GetRange()[0]
\ No newline at end of file
diff --git a/source/Scripts/SurfaceAveraging.py b/source/Scripts/SurfaceAveraging.py
new file mode 100644
index 0000000000000000000000000000000000000000..c9a4ba6af2350f36704c7d2c4a0fc8678b5c03c3
--- /dev/null
+++ b/source/Scripts/SurfaceAveraging.py
@@ -0,0 +1,81 @@
+#script create data file for surface averaged velocity plot
+ 
+from paraview.simple import *
+
+file='/hpc3lustre/work/sonjaOutputs/BKanaltest0Ref2nue0312/steps/stepAV_150000.pvtu'
+print file
+#read data set file
+reader = XMLPartitionedUnstructuredGridReader(FileName=file)
+
+#create slice filter for z
+sliceFilter = Slice(reader)
+sliceFilter.SliceType.Normal = [0, 0, 1]
+
+#create calculator filter for calculate surface of elements
+calc = Calculator(sliceFilter)
+calc.ResultArrayName = "one"
+calc.Function = "1"
+
+#create integrate variables filter for integration of velocity (integration = summation * surface of elements)
+intVal = IntegrateVariables(calc)
+
+f = open('/work/koskuche/SFB880/BKanalPlotData/BKanalAvVx400s2.dat', 'w')   
+f.write("z")
+f.write(" ")
+f.write("avVx")
+f.write(" ")
+f.write("avVxx")
+f.write(" ")
+f.write("avVyy")
+f.write(" ")
+f.write("avVzz")
+f.write(" ")
+f.write("avVxz")
+f.write("\n")
+
+#for i in range (1, 400, 1):
+z = 0.995
+while z <= 396:
+    #shift a slice
+    sliceFilter.SliceType.Origin = [298.668884754181, 198.835281848907, z]
+    sliceFilter.UpdatePipeline()
+    print z
+    numPoints=sliceFilter.GetDataInformation().GetNumberOfPoints()
+    print numPoints
+    intVal.UpdatePipeline()
+    pointData=intVal.GetPointDataInformation()
+    vxArray=pointData.GetArray("vx")
+    vxxArray=pointData.GetArray("vxx")
+    vyyArray=pointData.GetArray("vyy")
+    vzzArray=pointData.GetArray("vzz")
+    vxzArray=pointData.GetArray("vxz")
+    sArray  =pointData.GetArray("one")
+    surface =sArray.GetRange()[0]
+    if numPoints > 0:
+      avVx=vxArray.GetRange()[0]/surface
+      avVxx=vxxArray.GetRange()[0]/surface
+      avVyy=vyyArray.GetRange()[0]/surface
+      avVzz=vzzArray.GetRange()[0]/surface
+      avVxz=vxzArray.GetRange()[0]/surface
+
+      f.write(str(z))
+      f.write(" ")
+      f.write(str(avVx))
+      f.write(" ")
+      f.write(str(avVxx))
+      f.write(" ")
+      f.write(str(avVyy))
+      f.write(" ")
+      f.write(str(avVzz))
+      f.write(" ")
+      f.write(str(avVxz))
+      f.write("\n")
+
+    if z < 280:
+      z=z+1.99005
+    else:
+      z=z+3.9801
+
+f.close()
+
+print "!!!ready!!!"
\ No newline at end of file
diff --git a/source/Scripts/TimeAveraging.nb b/source/Scripts/TimeAveraging.nb
new file mode 100644
index 0000000000000000000000000000000000000000..7182fe8d775d0e16c49ac3edc48ccc014331e73b
--- /dev/null
+++ b/source/Scripts/TimeAveraging.nb
@@ -0,0 +1,374 @@
+(* Content-type: application/vnd.wolfram.mathematica *)
+
+(*** Wolfram Notebook File ***)
+(* http://www.wolfram.com/nb *)
+
+(* CreatedBy='Mathematica 10.0' *)
+
+(*CacheID: 234*)
+(* Internal cache information:
+NotebookFileLineBreakTest
+NotebookFileLineBreakTest
+NotebookDataPosition[       158,          7]
+NotebookDataLength[     10447,        365]
+NotebookOptionsPosition[      9362,        321]
+NotebookOutlinePosition[      9705,        336]
+CellTagsIndexPosition[      9662,        333]
+WindowFrame->Normal*)
+
+(* Beginning of Notebook Content *)
+Notebook[{
+
+Cell[CellGroupData[{
+Cell[BoxData[
+ RowBox[{"Expand", "[", 
+  RowBox[{
+   RowBox[{"(", 
+    RowBox[{"ux", "-", "Ux"}], ")"}], "^", "3"}], "]"}]], "Input",
+ CellChangeTimes->{{3.6652333854347067`*^9, 3.665233411326749*^9}}],
+
+Cell[BoxData[
+ RowBox[{
+  SuperscriptBox["ux", "3"], "-", 
+  RowBox[{"3", " ", 
+   SuperscriptBox["ux", "2"], " ", "Ux"}], "+", 
+  RowBox[{"3", " ", "ux", " ", 
+   SuperscriptBox["Ux", "2"]}], "-", 
+  SuperscriptBox["Ux", "3"]}]], "Output",
+ CellChangeTimes->{3.665233412534567*^9}]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{"Expand", "[", 
+  RowBox[{
+   RowBox[{"(", 
+    RowBox[{"ux", "-", "Ux"}], ")"}], "*", 
+   RowBox[{"(", 
+    RowBox[{"uy", "-", "Uy"}], ")"}], "*", 
+   RowBox[{"(", 
+    RowBox[{"uz", "-", "Uz"}], ")"}]}], "]"}]], "Input",
+ CellChangeTimes->{{3.665234958289308*^9, 3.665234978795968*^9}}],
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{"ux", " ", "uy", " ", "uz"}], "-", 
+  RowBox[{"Ux", " ", "uy", " ", "uz"}], "-", 
+  RowBox[{"ux", " ", "Uy", " ", "uz"}], "+", 
+  RowBox[{"Ux", " ", "Uy", " ", "uz"}], "-", 
+  RowBox[{"ux", " ", "uy", " ", "Uz"}], "+", 
+  RowBox[{"Ux", " ", "uy", " ", "Uz"}], "+", 
+  RowBox[{"ux", " ", "Uy", " ", "Uz"}], "-", 
+  RowBox[{"Ux", " ", "Uy", " ", "Uz"}]}]], "Output",
+ CellChangeTimes->{3.6652349812057548`*^9}]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{"Expand", "[", 
+  RowBox[{
+   RowBox[{
+    RowBox[{"(", 
+     RowBox[{"ux", "-", "Ux"}], ")"}], "^", "2"}], "*", 
+   RowBox[{"(", 
+    RowBox[{"uy", "-", "Uy"}], ")"}]}], "]"}]], "Input",
+ CellChangeTimes->{{3.6652350670376253`*^9, 3.665235078036113*^9}}],
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{
+   SuperscriptBox["ux", "2"], " ", "uy"}], "-", 
+  RowBox[{"2", " ", "ux", " ", "Ux", " ", "uy"}], "+", 
+  RowBox[{
+   SuperscriptBox["Ux", "2"], " ", "uy"}], "-", 
+  RowBox[{
+   SuperscriptBox["ux", "2"], " ", "Uy"}], "+", 
+  RowBox[{"2", " ", "ux", " ", "Ux", " ", "Uy"}], "-", 
+  RowBox[{
+   SuperscriptBox["Ux", "2"], " ", "Uy"}]}]], "Output",
+ CellChangeTimes->{3.6652350792380753`*^9}]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{"Expand", "[", 
+  RowBox[{
+   RowBox[{
+    RowBox[{"(", 
+     RowBox[{"ux", "-", "Ux"}], ")"}], "^", "2"}], "*", 
+   RowBox[{"(", 
+    RowBox[{"ux", "-", "Ux"}], ")"}]}], "]"}]], "Input",
+ CellChangeTimes->{{3.665235285108924*^9, 3.665235288876026*^9}}],
+
+Cell[BoxData[
+ RowBox[{
+  SuperscriptBox["ux", "3"], "-", 
+  RowBox[{"3", " ", 
+   SuperscriptBox["ux", "2"], " ", "Ux"}], "+", 
+  RowBox[{"3", " ", "ux", " ", 
+   SuperscriptBox["Ux", "2"]}], "-", 
+  SuperscriptBox["Ux", "3"]}]], "Output",
+ CellChangeTimes->{3.665235291918062*^9}]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{"Expand", "[", 
+  RowBox[{
+   RowBox[{"1", "/", "n"}], "*", 
+   RowBox[{"Sum", "[", 
+    RowBox[{
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"ux", "[", "i", "]"}], "-", "Ux"}], ")"}], "^", "2"}], "*", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{"uz", "[", "i", "]"}], "-", "Uz"}], ")"}]}], ",", 
+     RowBox[{"{", 
+      RowBox[{"i", ",", "0", ",", "n"}], "}"}]}], "]"}]}], "]"}]], "Input",
+ CellChangeTimes->{{3.6652353351359625`*^9, 3.6652353384183865`*^9}, {
+  3.665235469081513*^9, 3.665235491832822*^9}, {3.6652355801722608`*^9, 
+  3.6652356889244556`*^9}, {3.66523574166329*^9, 3.6652357781472335`*^9}}],
+
+Cell[BoxData[
+ FractionBox[
+  RowBox[{
+   UnderoverscriptBox["\[Sum]", 
+    RowBox[{"i", "=", "0"}], "n"], 
+   RowBox[{
+    SuperscriptBox[
+     RowBox[{"(", 
+      RowBox[{
+       RowBox[{"-", "Ux"}], "+", 
+       RowBox[{"ux", "[", "i", "]"}]}], ")"}], "2"], " ", 
+    RowBox[{"(", 
+     RowBox[{
+      RowBox[{"-", "Uz"}], "+", 
+      RowBox[{"uz", "[", "i", "]"}]}], ")"}]}]}], "n"]], "Output",
+ CellChangeTimes->{
+  3.6652353396467347`*^9, 3.6652355168932877`*^9, {3.665235673513936*^9, 
+   3.665235690097102*^9}, 3.6652357791478987`*^9}]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{
+   RowBox[{"Sum", "[", 
+    RowBox[{
+     RowBox[{"Expand", "[", 
+      RowBox[{
+       RowBox[{"1", "/", "n"}], "*", 
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"ux", "[", "i", "]"}], "-", "Ux"}], ")"}], "*", 
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"uy", "[", "i", "]"}], "-", "Uy"}], ")"}], "*", 
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"uz", "[", "i", "]"}], "-", "Uz"}], ")"}]}], "]"}], ",", 
+     RowBox[{"{", 
+      RowBox[{"i", ",", "1", ",", "n"}], "}"}]}], "]"}], "/.", 
+   RowBox[{
+    RowBox[{"uy", "[", "i", "]"}], "\[Rule]", 
+    RowBox[{"ux", "[", "i", "]"}]}]}], "/.", 
+  RowBox[{"Uy", "\[Rule]", "Ux"}]}]], "Input",
+ CellChangeTimes->{{3.665236764045683*^9, 3.6652367697271566`*^9}, {
+  3.665237436328154*^9, 3.665237442171824*^9}, {3.6652374810518904`*^9, 
+  3.6652374987393093`*^9}}],
+
+Cell[BoxData[
+ RowBox[{
+  UnderoverscriptBox["\[Sum]", 
+   RowBox[{"i", "=", "1"}], "n"], 
+  RowBox[{"(", 
+   RowBox[{
+    RowBox[{"-", 
+     FractionBox[
+      RowBox[{
+       SuperscriptBox["Ux", "2"], " ", "Uz"}], "n"]}], "+", 
+    FractionBox[
+     RowBox[{"2", " ", "Ux", " ", "Uz", " ", 
+      RowBox[{"ux", "[", "i", "]"}]}], "n"], "-", 
+    FractionBox[
+     RowBox[{"Uz", " ", 
+      SuperscriptBox[
+       RowBox[{"ux", "[", "i", "]"}], "2"]}], "n"], "+", 
+    FractionBox[
+     RowBox[{
+      SuperscriptBox["Ux", "2"], " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"], "-", 
+    FractionBox[
+     RowBox[{"2", " ", "Ux", " ", 
+      RowBox[{"ux", "[", "i", "]"}], " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"], "+", 
+    FractionBox[
+     RowBox[{
+      SuperscriptBox[
+       RowBox[{"ux", "[", "i", "]"}], "2"], " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"]}], ")"}]}]], "Output",
+ CellChangeTimes->{
+  3.6652367708783035`*^9, 3.665237448476756*^9, {3.665237486558442*^9, 
+   3.665237499752672*^9}}]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{"Sum", "[", 
+  RowBox[{
+   RowBox[{"Expand", "[", 
+    RowBox[{
+     RowBox[{"1", "/", "n"}], "*", 
+     RowBox[{"(", 
+      RowBox[{
+       RowBox[{"ux", "[", "i", "]"}], "-", "Ux"}], ")"}], "*", 
+     RowBox[{"(", 
+      RowBox[{
+       RowBox[{"uy", "[", "i", "]"}], "-", "Uy"}], ")"}], "*", 
+     RowBox[{"(", 
+      RowBox[{
+       RowBox[{"uz", "[", "i", "]"}], "-", "Uz"}], ")"}]}], "]"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"i", ",", "1", ",", "n"}], "}"}]}], "]"}]], "Input",
+ CellChangeTimes->{{3.6652367948266797`*^9, 3.665236831166998*^9}}],
+
+Cell[BoxData[
+ RowBox[{
+  UnderoverscriptBox["\[Sum]", 
+   RowBox[{"i", "=", "1"}], "n"], 
+  RowBox[{"(", 
+   RowBox[{
+    RowBox[{"-", 
+     FractionBox[
+      RowBox[{"Ux", " ", "Uy", " ", "Uz"}], "n"]}], "+", 
+    FractionBox[
+     RowBox[{"Uy", " ", "Uz", " ", 
+      RowBox[{"ux", "[", "i", "]"}]}], "n"], "+", 
+    FractionBox[
+     RowBox[{"Ux", " ", "Uz", " ", 
+      RowBox[{"uy", "[", "i", "]"}]}], "n"], "-", 
+    FractionBox[
+     RowBox[{"Uz", " ", 
+      RowBox[{"ux", "[", "i", "]"}], " ", 
+      RowBox[{"uy", "[", "i", "]"}]}], "n"], "+", 
+    FractionBox[
+     RowBox[{"Ux", " ", "Uy", " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"], "-", 
+    FractionBox[
+     RowBox[{"Uy", " ", 
+      RowBox[{"ux", "[", "i", "]"}], " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"], "-", 
+    FractionBox[
+     RowBox[{"Ux", " ", 
+      RowBox[{"uy", "[", "i", "]"}], " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"], "+", 
+    FractionBox[
+     RowBox[{
+      RowBox[{"ux", "[", "i", "]"}], " ", 
+      RowBox[{"uy", "[", "i", "]"}], " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"]}], ")"}]}]], "Output",
+ CellChangeTimes->{{3.665236806892251*^9, 3.6652368327940598`*^9}}]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{"Sum", "[", 
+  RowBox[{
+   RowBox[{"Expand", "[", 
+    RowBox[{
+     RowBox[{"1", "/", "n"}], "*", 
+     RowBox[{"(", 
+      RowBox[{
+       RowBox[{"ux", "[", "i", "]"}], "-", "Ux"}], ")"}], "*", 
+     RowBox[{"(", 
+      RowBox[{
+       RowBox[{"uz", "[", "i", "]"}], "-", "Uz"}], ")"}]}], "]"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"i", ",", "1", ",", "n"}], "}"}]}], "]"}]], "Input",
+ CellChangeTimes->{{3.666867798745492*^9, 3.6668678014904623`*^9}, {
+  3.6668679338550305`*^9, 3.6668679547564764`*^9}}],
+
+Cell[BoxData[
+ RowBox[{
+  UnderoverscriptBox["\[Sum]", 
+   RowBox[{"i", "=", "1"}], "n"], 
+  RowBox[{"(", 
+   RowBox[{
+    FractionBox[
+     RowBox[{"Ux", " ", "Uz"}], "n"], "-", 
+    FractionBox[
+     RowBox[{"Uz", " ", 
+      RowBox[{"ux", "[", "i", "]"}]}], "n"], "-", 
+    FractionBox[
+     RowBox[{"Ux", " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"], "+", 
+    FractionBox[
+     RowBox[{
+      RowBox[{"ux", "[", "i", "]"}], " ", 
+      RowBox[{"uz", "[", "i", "]"}]}], "n"]}], ")"}]}]], "Output",
+ CellChangeTimes->{3.666867803381354*^9, 3.666867956606307*^9}]
+}, Open  ]]
+},
+WindowSize->{944, 981},
+WindowMargins->{{Automatic, 0}, {Automatic, 0}},
+FrontEndVersion->"10.0 for Microsoft Windows (64-bit) (December 4, 2014)",
+StyleDefinitions->"Default.nb"
+]
+(* End of Notebook Content *)
+
+(* Internal cache information *)
+(*CellTagsOutline
+CellTagsIndex->{}
+*)
+(*CellTagsIndex
+CellTagsIndex->{}
+*)
+(*NotebookFileOutline
+Notebook[{
+Cell[CellGroupData[{
+Cell[580, 22, 201, 5, 31, "Input"],
+Cell[784, 29, 282, 8, 31, "Output"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[1103, 42, 311, 9, 31, "Input"],
+Cell[1417, 53, 442, 10, 31, "Output"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[1896, 68, 278, 8, 31, "Input"],
+Cell[2177, 78, 426, 12, 31, "Output"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[2640, 95, 276, 8, 31, "Input"],
+Cell[2919, 105, 282, 8, 31, "Output"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[3238, 118, 682, 18, 31, "Input"],
+Cell[3923, 138, 543, 17, 49, "Output"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[4503, 160, 879, 25, 31, "Input"],
+Cell[5385, 187, 1022, 32, 55, "Output"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[6444, 224, 575, 17, 31, "Input"],
+Cell[7022, 243, 1184, 35, 93, "Output"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[8243, 283, 530, 15, 31, "Input"],
+Cell[8776, 300, 570, 18, 88, "Output"]
+}, Open  ]]
+}
+]
+*)
+
+(* End of internal cache information *)
diff --git a/source/Scripts/VFtest.py b/source/Scripts/VFtest.py
new file mode 100644
index 0000000000000000000000000000000000000000..717b8aa3b8a32961c2b7c3be490f68a79c94b098
--- /dev/null
+++ b/source/Scripts/VFtest.py
@@ -0,0 +1,2 @@
+from virtualfluids import *
+config=virtualfluids.load("config.txt")
diff --git a/source/Scripts/deltat.py b/source/Scripts/deltat.py
new file mode 100644
index 0000000000000000000000000000000000000000..91c546fad1fa93b3cafd9e70a05c05794ad5ed20
--- /dev/null
+++ b/source/Scripts/deltat.py
@@ -0,0 +1,10 @@
+u_real = 17 
+u_LB = 0.1 
+deltax =  0.078125  
+number_of_timesteps = 84000
+
+deltat=(u_LB/u_real)*deltax
+
+print 'delta t =', deltat, 's'
+print 'simulated time =', deltat*number_of_timesteps, 'sec'
+print 'simulated time =', deltat*number_of_timesteps/60.0, 'min'
diff --git a/source/Scripts/u_tau.py b/source/Scripts/u_tau.py
new file mode 100644
index 0000000000000000000000000000000000000000..65640a7a5cee70b60afbf16bc24b7c2be2cd3ef4
--- /dev/null
+++ b/source/Scripts/u_tau.py
@@ -0,0 +1,11 @@
+import math
+
+k = 0.41
+u1=1.2
+u2=0
+y1=6
+y2=0.05
+
+u_tau = k/2.3 * (u2 - u1) / math.log10(y1/y2)
+
+print 'u_tau = ', u_tau 
diff --git a/source/Scripts/y_plus.py b/source/Scripts/y_plus.py
new file mode 100644
index 0000000000000000000000000000000000000000..f5a681f9e963f01504bfb4010557e557b9f77eb0
--- /dev/null
+++ b/source/Scripts/y_plus.py
@@ -0,0 +1,16 @@
+import math
+
+u = 0.0154946
+nu = 7.05882e-05 * pow(2,4) 
+y0 = 0.00595276
+deltax = 0.078125
+
+q = y0/deltax
+
+utau = math.sqrt(nu*(u/q))
+
+yplus = (utau*q)/nu
+
+print 'u_tau = ', utau
+print 'y_plus = ', yplus
+
diff --git a/source/ThirdParty/Library/basics/container/CMakePackage.txt b/source/ThirdParty/Library/basics/container/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f7766736561db92faa97bdef5d1c1a6a40533148
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/CMakePackage.txt
@@ -0,0 +1,4 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
+
+
diff --git a/source/ThirdParty/Library/basics/container/CbArray2D.h b/source/ThirdParty/Library/basics/container/CbArray2D.h
new file mode 100644
index 0000000000000000000000000000000000000000..2dc54329b868a760d1803d4c03ba7099c52b4b44
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/CbArray2D.h
@@ -0,0 +1,414 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBARRAY2D_H
+#define CBARRAY2D_H
+
+//////////////////////////////////////////////////////////////////////////
+// 4D Array
+// die Daten werden in einem Vector gehalten
+//
+// Ver 1.2
+// Nov. 2003 muffmolch@gmx.de
+// Ver 1.3
+// Aug. 2006 - Kosmetik
+// Ver 1.4
+// Sep. 2006 - indexer eingefuehrt
+// Ver 1.5
+// Jul. 2006 - size_t + range check bei getIndex
+// Ver 1.6
+// Mrz. 2008 - typedefs, new index checks, NO_CB_RANGECHECK, no base class
+//             assigmetcomparison between Matrices with different value_type and/or index-class
+// Oct. 2008 - +isEmpty()
+//
+// Rangecheck aktiv, wenn:
+// -debug  : not defined "NO_CB_RANGECHECK"
+// -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK"
+//////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbEqual.h>
+#include <algorithm>
+#include <typeinfo>
+
+#ifdef CAB_RCF
+  #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// IndexClasses
+
+//IndexerX2X1:
+//        4 5 6
+// Array  1 2 3  -->  vector 1 2 3 4 5 6
+//optimaler schleifendurchlauf
+//for(alle X2)
+//  for(alle X1)
+class IndexerX2X1
+{
+public:
+   typedef int size_type;
+public:
+   inline std::size_t getIndex(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const
+   {
+      return nx1* x2 + x1;
+   }
+   inline std::size_t getStartIndexOfSortedArray(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const
+   {
+      return  nx1* x2;
+   }
+};
+
+//IndexerX1X2:
+//        4 5 6
+// Array  1 2 3  -->  vector 1 4 2 5 3 6
+//optimaler schleifendurchlauf
+//for(alle X1)
+//  for(alle X2)
+class IndexerX1X2
+{
+public:
+   typedef int size_type;
+public:
+   inline std::size_t getIndex(const size_type& x1, const size_type& x2, const size_type& nx1,const size_type& nx2) const
+   {
+      return nx2* x1+ x2;
+   }
+   inline std::size_t getStartIndexOfSortedArray(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const
+   {
+      return  nx2* x1;
+   }
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// CbArray2D
+
+template<typename T, typename IndexClass = IndexerX2X1>
+class CbArray2D
+{
+public:
+   typedef T                                                   value_type;
+   typedef IndexClass                                          indexer_type;
+   typedef typename IndexClass::size_type                      size_type;
+   typedef typename std::vector< value_type >::reference       reference;
+   typedef typename std::vector< value_type >::const_reference const_reference;
+   typedef typename std::vector< value_type >::pointer         pointer;
+   typedef typename std::vector< value_type >::const_pointer   const_pointer;
+
+private:
+   template< typename value_type2, typename IndexClass2 > friend class CbArray2D;
+
+public:
+   /*=======================================================================*/
+   CbArray2D()
+   {
+      this->resize(0,0);
+   }
+   /*=======================================================================*/
+   CbArray2D(const size_type& nx2, const size_type& nx1)
+   {
+      this->resize(nx2,nx1);
+   }
+   /*=======================================================================*/
+   CbArray2D(const size_type& nx2, const size_type& nx1, const value_type& val)
+   {
+      this->resize(nx2,nx1,val);
+   }
+   /*=======================================================================*/
+   CbArray2D(const size_type& uniformDimensionSize /*nx1==nx2*/)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   //übernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird)
+   CbArray2D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2)
+   {
+      assert( (nx1*nx2)==vec.size() );
+      this->data.swap(vec);
+      this->resize(nx1,nx2);
+   }
+   /*=======================================================================*/
+   CbArray2D(const CbArray2D& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , data(src.data)
+   {
+   }
+   /*=======================================================================*/
+   template< typename value_type2 >
+   CbArray2D(const CbArray2D< value_type2 >& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+   {
+      //Sourcedaten kopieren
+      this->data.resize( src.data.size() );
+      for(std::size_t i=0; i<data.size(); ++i)
+         this->data[i] = src.data[i];
+   }
+   /*=======================================================================*/
+   virtual ~CbArray2D()
+   {
+      //vector wird automatisch zerstoert
+   }
+   /*=======================================================================*/
+   CbArray2D& operator= (const CbArray2D& rhs)
+   {
+      if(this == &rhs) return *this;
+
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+
+      //Sourcedaten kopieren
+      this->data  = rhs.data;
+
+      return *this;
+   }
+   /*=======================================================================*/
+   //durch value_type2 kann man z.B. ein float array einem double array zuweisen!
+   template< typename value_type2, typename IndexClass2 >
+   CbArray2D& operator= (const CbArray2D< value_type2, IndexClass2 >& rhs)
+   {
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+
+      //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      //ACHTUNG: für diese Konvertierung muss bei Klassen der demenstrechende operator
+      //         implementiert sein, e.g.: class value_type2 {public: inline operator value_type2() const { return value_type2(); }
+      for(int x1=0; x1<this->nx1; x1++)
+         for(int x2=0; x2<this->nx2; x2++)
+               this->operator()(x1,x2) = static_cast< value_type >( rhs.operator()(x1,x2) );
+
+      return *this;
+   }
+   /*=======================================================================*/
+   bool operator== (const CbArray2D& rhs) const
+   {
+      if( this == &rhs ) return true;
+
+      if(   this->nx1!=rhs.nx1
+         || this->nx2!=rhs.nx2
+         || this->data.size() != rhs.data.size() )
+      {
+         return false;
+      }
+
+      return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() );
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator== (const CbArray2D< value_type2, IndexClass2 >& rhs) const
+   {
+      if( this->data.size() != rhs.data.size() ) return false;
+
+      //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x1=0; x1<this->nx1; x1++)
+         for(int x2=0; x2<this->nx2; x2++)
+            if( !isUbEqual(this->operator()(x1,x2), rhs.operator()(x1,x2)) )
+               return false;
+
+      return true;
+   }
+   /*=======================================================================*/
+   bool operator!= (const CbArray2D& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator!= (const CbArray2D< value_type2, IndexClass2 >& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   reference operator() (const size_type& x1,const size_type& x2)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,nx1,nx2)];
+   }
+   /*=======================================================================*/
+   const_reference operator() (const size_type& x1,const size_type& x2)	const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,nx1,nx2)];
+   }
+   /*=======================================================================*/
+   pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,nx1,nx2)];
+   }
+   /*=======================================================================*/
+   const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,nx1,nx2)];
+   }
+   /*=======================================================================*/
+   void setObject(const size_type& x1,const size_type& x2,const value_type& value)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+      this->data[indexer.getIndex(x1,x2,nx1,nx2)] = value;
+   }
+   /*=======================================================================*/
+   reference getObject(const size_type& x1, const size_type& x2)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+      return this->data[indexer.getIndex(x1,x2,nx1,nx2)] ;
+   }
+   /*=======================================================================*/
+   typename std::vector<value_type>::const_reference getObject(const size_type& x1, const size_type& x2) const
+   {
+      return this->operator()(x1,x2);
+   }
+   /*=======================================================================*/
+   bool      isEmpty() const { return data.empty(); }
+   size_type getNX1()  const { return this->nx1;    }
+   size_type getNX2()  const { return this->nx2;    }
+   /*=======================================================================*/
+   void reset(const T& val)
+   {
+      std::fill( this->data.begin(), this->data.end(), val );
+   }
+   /*=======================================================================*/
+   std::string toString() const
+   {
+      std::stringstream text;
+      for(size_type x2=0; x2<this->nx2; x2++)
+      {
+         for(size_type x1=0; x1<this->nx1; x1++)
+         {
+            //hier kommts zum Konflikt ab  und an ...
+            text<<this->getObject(x1,x2)<<", ";
+         }
+         text<<"\n";
+      }
+
+      return text.str();
+   }
+   /*=======================================================================*/
+   std::string getInfo() const
+   {
+      std::stringstream text;
+      text<<"CbArray2D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >";
+      text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<")";
+      return text.str();
+   }
+   /*=======================================================================*/
+   void resize(const size_type& uniformDimensionSize)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1,const size_type& nx2)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->data.resize(nx1*nx2);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1, const size_type& nx2, const value_type& initVal )
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->data.resize(nx1*nx2,initVal);
+   }
+   /*=======================================================================*/
+   void clear()
+   {
+      this->nx1 = 0;
+      this->nx2 = 0;
+      this->data.clear();
+   }
+   /*=======================================================================*/
+   std::vector< value_type >& getDataVector() { return this->data; }
+   /*=======================================================================*/
+   const std::vector< value_type >& getDataVector() const { return this->data; }
+   /*=======================================================================*/
+   inline size_type getDataVectorIndex(const size_type& x1, const size_type& x2) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+
+      return indexer.getIndex(x1,x2,nx1,nx2);
+   }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & data;
+   }
+#endif //CAB_RCF
+
+protected:
+   /*=======================================================================*/
+   //success -> true
+   //else    -> false
+   inline bool indicesInRange(const size_type& x1, const size_type& x2) const
+   {
+      if(   x1 < 0 || x1 >= this->nx1
+         || x2 < 0 || x2 >= this->nx2 )
+      {
+         return false;
+      }
+      return true;
+   }
+   /*=======================================================================*/
+   std::string getExceptionErrorString(const size_type& x1, const size_type& x2) const
+   {
+      std::stringstream out("index out of range - ");
+      out<<"("<<x1<<","<<x2<<") not in ("<<nx1<<","<<nx2<<")";
+      return out.str();
+   }
+   /*=======================================================================*/
+
+protected:
+   size_type    nx1;
+   size_type    nx2;
+   indexer_type indexer;
+   std::vector< value_type > data;
+};
+
+#endif //CBARRAY2D_H
diff --git a/source/ThirdParty/Library/basics/container/CbArray3D.h b/source/ThirdParty/Library/basics/container/CbArray3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..e3a172a379ccaa01a26ba06e16b9e6d18a235b67
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/CbArray3D.h
@@ -0,0 +1,479 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBARRAY3D_H
+#define CBARRAY3D_H
+
+//////////////////////////////////////////////////////////////////////////
+// 3D Array
+// die Daten werden in einem Vector gehalten
+//
+// Ver 1.2
+// Nov. 2003 muffmolch@gmx.de
+// Ver 1.3
+// Aug. 2006 - Kosmetik
+// Ver 1.4
+// Sep. 2006 - indexer eingefuehrt
+// Ver 1.5
+// Jul. 2006 - size_t + range check bei getIndex
+// Ver 1.2
+// Mrz. 2008 - typedefs, new index checks, NO_CB_RANGECHECK, no base class
+//             assigmetcomparison between Matrices with different value_type and/or index-class
+// Oct. 2008 - +isEmpty()
+//
+// Rangecheck aktiv, wenn:
+// -debug  : not defined "NO_CB_RANGECHECK"
+// -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK"
+//////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbEqual.h>
+#include <algorithm>
+#include <typeinfo>
+#include <boost/serialization/serialization.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// IndexClasses
+
+//IndexerX3X2X1:
+//                4 5 6          10 11 12
+// Array  ebene A 1 2 3  ebene B  7  8  9 -->  vector 1 2 3 4 5 6 7 8 9 10 11 12
+//x1-reihen "liegen am stueck" im speicher
+//optimaler schleifendurchlauf
+//for(alle X3)
+//  for(alle X2)
+//    for(alle X1)
+class IndexerX3X2X1// FunctorX1SortedForX1X2Plane
+{
+public:
+   typedef size_t size_type;
+public:
+   inline std::size_t getIndex(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                               , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx1 * ( nx2 * x3 + x2) + x1 ;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                                                 , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx1 * ( nx2 * x3 + x2);
+   }
+};
+
+//IndexerX1X2X3:
+//                4 5 6          10 11 12
+// Array  ebene A 1 2 3  ebene B  7  8  9 -->
+//optimaler schleifendurchlauf
+//for(alle X1)
+//  for(alle X2)
+//    for(alle X3)
+class IndexerX1X2X3 //FunctorX3SortedForX3X2Plane
+{
+public:
+   typedef size_t size_type;
+public:
+   inline std::size_t getIndex(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                               , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx3 * ( nx2 * x1 + x2) + x3 ;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                                                 , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx3 * ( nx2 * x1 + x2);
+   }
+};
+
+//IndexerX2X1X3:
+//                4 5 6          10 11 12
+// Array  ebene A 1 2 3  ebene B  7  8  9 -->  vector 1 7 2 8 3 9 4 10 5 11 6 12
+//optimaler schleifendurchlauf
+//for(alle X2)
+//  for(alle X1)
+//    for(alle X3)
+class IndexerX2X1X3
+{
+public:
+   typedef size_t size_type;
+public:
+   inline std::size_t getIndex(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                               , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx3* ( nx1 * x2 + x1) + x3 ;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                                                 , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx3* ( nx1 * x2 + x1);
+   }
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// CbArray3D
+template<typename T, typename IndexClass = IndexerX3X2X1>
+class CbArray3D
+{
+public:
+   typedef boost::shared_ptr< CbArray3D <T,IndexClass> > CbArray3DPtr;
+
+   typedef T                                                   value_type;
+   typedef IndexClass                                          indexer_type;
+   typedef typename IndexClass::size_type                      size_type;
+   typedef typename std::vector< value_type >::reference       reference;
+   typedef typename std::vector< value_type >::const_reference const_reference;
+   typedef typename std::vector< value_type >::pointer         pointer;
+   typedef typename std::vector< value_type >::const_pointer   const_pointer;
+
+private:
+   template< typename value_type2, typename IndexClass2 > friend class CbArray3D;
+
+public:
+   /*=======================================================================*/
+   CbArray3D()
+   {
+      this->resize(0,0,0);
+   }
+   /*=======================================================================*/
+   CbArray3D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const value_type& val)
+   {
+      this->resize(nx1,nx2,nx3,val);
+   }
+   /*=======================================================================*/
+    CbArray3D(const size_type& nx1,const size_type& nx2, const size_type& nx3)
+    {
+       this->resize(nx1,nx2,nx3);
+    }
+   /*=======================================================================*/
+   CbArray3D(const size_type& uniformDimensionSize /*nx1==nx2==nx3*/)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   //übernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird)
+   CbArray3D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2, const size_type& nx3)
+   {
+      assert( (nx1*nx2*nx3)==vec.size() );
+      this->data.swap(vec);
+      this->resize(nx1,nx2,nx3);
+   }
+   /*=======================================================================*/
+   CbArray3D(const CbArray3D& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , nx3(src.nx3)
+       , data(src.data)
+   {
+   }
+   /*=======================================================================*/
+   template< typename value_type2 >
+   CbArray3D(const CbArray3D< value_type2 >& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , nx3(src.nx3)
+   {
+      //Sourcedaten kopieren
+      this->data.resize( src.data.size() );
+      for(std::size_t i=0; i<data.size(); ++i)
+         this->data[i] = src.data[i];
+   }
+   /*=======================================================================*/
+   virtual ~CbArray3D()
+   {
+      //vector wird automatisch zerstoert
+   }
+   /*=======================================================================*/
+   CbArray3D& operator= (const CbArray3D& rhs)
+   {
+      if(this == &rhs) return *this;
+
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+      this->nx3 = rhs.nx3;
+
+      //gespeicherte Datenelemente loeschen
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+
+      //Sourcedaten kopieren
+      this->data = rhs.data;
+
+      return *this;
+   }
+   /*=======================================================================*/
+   //durch value_type2 kann man z.B. ein float array einer double array zuweisen!
+   template< typename value_type2, typename IndexClass2 >
+   CbArray3D& operator= (const CbArray3D< value_type2, IndexClass2 >& rhs)
+   {
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+      this->nx3 = rhs.nx3;
+
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+
+      //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x3=0; x3<this->nx3; x3++)
+         for(int x2=0; x2<this->nx2; x2++)
+            for(int x1=0; x1<this->nx1; x1++)
+               this->operator()(x1,x2,x3) = static_cast< value_type >( rhs.operator()(x1,x2,x3) );
+
+      return *this;
+   }
+   /*=======================================================================*/
+   bool operator== (const CbArray3D& rhs) const
+   {
+      if(this == &rhs) return true;
+
+      if(   this->nx1!=rhs.nx1
+         || this->nx2!=rhs.nx2
+         || this->nx3!=rhs.nx3
+         || this->data.size() != rhs.data.size() )
+      {
+         return false;
+      }
+
+      return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() );
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator== (const CbArray3D< value_type2, IndexClass2 >& rhs) const
+   {
+      if( this->data.size() != rhs.data.size() ) return false;
+
+      //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x3=0; x3<this->nx3; x3++)
+         for(int x2=0; x2<this->nx2; x2++)
+            for(int x1=0; x1<this->nx1; x1++)
+               if( !isUbEqual(this->operator()(x1,x2,x3), rhs.operator()(x1,x2,x3)) )
+               return false;
+
+      return true;
+   }
+   /*=======================================================================*/
+   bool operator!= (const CbArray3D& src) const
+   {
+      return !(*this==src);
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator!= (const CbArray3D< value_type2, IndexClass2 >& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   reference operator() (const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ];
+   }
+   /*=======================================================================*/
+   const_reference operator() (const size_type& x1, const size_type& x2, const size_type& x3)	const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ];
+   }
+   /*=======================================================================*/
+   pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,nx1,nx2,nx3)];
+   }
+   /*=======================================================================*/
+   const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3)  const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,nx1,nx2,nx3)];
+   }
+   /*=======================================================================*/
+   void setObject(const size_type& x1, const size_type& x2, const size_type& x3, const value_type& value)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ] = value;
+   }
+   /*=======================================================================*/
+   reference getObject(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ] ;
+   }
+   /*=======================================================================*/
+   const_reference getObject(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return (*this)(x1,x2,x3);
+   }
+   /*=======================================================================*/
+   bool      isEmpty() const { return data.empty(); }
+   size_type getNX1()  const { return this->nx1;    }
+   size_type getNX2()  const { return this->nx2;    }
+   size_type getNX3()  const { return this->nx3;    }
+   /*=======================================================================*/
+   void reset(const value_type& val)
+   {
+      std::fill( this->data.begin(), this->data.end(), val );
+   }
+   /*=======================================================================*/
+   std::string toString() const
+   {
+      std::stringstream text;
+      for(size_type x1=0; x1<this->nx1; x1++)
+      {
+      	for(size_type x2=0; x2<this->nx2; x2++)
+      	{
+         	for(size_type x3=0; x3<this->nx3; x3++)
+         	{
+            	text<<(*this)(x1,x2,x3)<<", ";
+         	}
+         	text<<std::endl;
+      	}
+      	text<<std::endl<<std::endl;
+      }
+
+      return text.str();
+   }
+   /*=======================================================================*/
+   std::string getInfo() const
+   {
+      std::stringstream text;
+      text<<"CbArray3D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >";
+      text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<", nx3="<<this->nx3<<")";
+      return text.str();
+   }
+   /*=======================================================================*/
+   void resize(const int& uniformDimensionSize)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1,const size_type& nx2, const size_type& nx3)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->nx3 = nx3;
+      this->data.resize(nx1*nx2*nx3);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1,const size_type& nx2, const size_type& nx3,const value_type& val)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->nx3 = nx3;
+      this->data.resize(nx1*nx2*nx3,val);
+   }
+   /*=======================================================================*/
+   void clear()
+   {
+      this->nx1 = 0;
+      this->nx2 = 0;
+      this->nx3 = 0;
+      this->data.clear();
+   }
+   /*=======================================================================*/
+   std::vector< value_type >& getDataVector() { return this->data; }
+   /*=======================================================================*/
+   const std::vector< value_type >& getDataVector() const { return this->data; }
+   /*=======================================================================*/
+   inline std::size_t getDataVectorIndex(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return indexer.getIndex(x1,x2,x3,nx1,nx2,nx3);
+   }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & data;
+   }
+#endif //CAB_RCF
+
+
+   /*=======================================================================*/
+   //success -> true
+   //else    -> false
+   inline bool indicesInRange(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      if(   x1 < 0 || x1 >= this->nx1
+         || x2 < 0 || x2 >= this->nx2
+         || x3 < 0 || x3 >= this->nx3 )
+      {
+         return false;
+      }
+      return true;
+   }
+protected:
+   /*=======================================================================*/
+   std::string getExceptionErrorString(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      std::stringstream out("index out of range - ");
+      out<<"("<<x1<<","<<x2<<","<<x3<<") not in ("<<nx1<<","<<nx2<<","<<nx3<<")";
+      return out.str();
+   }
+   /*=======================================================================*/
+
+protected:
+   size_type    nx1;
+   size_type    nx2;
+   size_type    nx3;
+   indexer_type indexer;
+   std::vector< value_type > data;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & data;
+   }
+};
+
+#endif //CBARRAY3D_H
diff --git a/source/ThirdParty/Library/basics/container/CbArray4D.h b/source/ThirdParty/Library/basics/container/CbArray4D.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed2e6aa778efa366d182c5180c20e4e11186cbab
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/CbArray4D.h
@@ -0,0 +1,463 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBARRAY4D_H
+#define CBARRAY4D_H
+
+//////////////////////////////////////////////////////////////////////////
+// 4D Array
+// die Daten werden in einem Vector gehalten
+//
+// Ver 1.0
+// Sept. 2006 muffmolch@gmx.de
+// Ver 1.1
+// Jul. 2006 - size_t + range check bei getIndex
+// Ver 1.2
+// Mrz. 2008 - typedefs, new index checks, NO_CB_RANGECHECK, no base class
+//             assigmetcomparison between Matrices with different value_type and/or index-class
+// Oct. 2008 - +isEmpty()
+//
+// Rangecheck aktiv, wenn:
+// -debug  : not defined "NO_CB_RANGECHECK"
+// -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK"
+//////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbEqual.h>
+#include <algorithm>
+#include <typeinfo>
+#include <boost/serialization/serialization.hpp>
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// IndexClasses
+
+//IndexerX1X2X3X4:
+//x4-reihen "liegen am stueck" im speicher
+//optimaler schleifendurchlauf
+//for(alle X1)
+//  for(alle X2)
+//    for(alle X3)
+//      for(alle X4)
+class IndexerX1X2X3X4
+{
+public:
+   typedef int size_type;
+public:
+   inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4
+                            , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 )  const
+   {
+      return nx4*(nx3*(nx2*x1+ x2)+x3)+x4 ;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4
+                                               , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 )  const
+   {
+      return  nx4*(nx3*(nx2*x1+ x2)+x3);
+   }
+};
+//////////////////////////////////////////////////////////////////////////
+// IndexClasses
+
+//IndexerX4X3X2X1:
+//x1-reihen "liegen am stueck" im speicher
+//optimaler schleifendurchlauf
+//for(alle X4)
+//  for(alle X3)
+//    for(alle X2)
+//      for(alle X1)
+class IndexerX4X3X2X1
+{
+public:
+   typedef size_t size_type;
+public:
+   inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4
+      , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 )  const
+   {
+      return nx1*(nx2*(nx3*x4+ x3)+x2)+x1;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4
+      , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 )  const
+   {
+      return  nx1*(nx2*(nx3*x4+ x3)+x2);
+   }
+};
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// CbArray4D
+template<typename T, typename IndexClass = IndexerX4X3X2X1>
+class CbArray4D
+{
+public:
+   typedef boost::shared_ptr< CbArray4D <T,IndexClass> > CbArray4DPtr;
+
+   typedef T                                                   value_type;
+   typedef IndexClass                                          indexer_type;
+   typedef typename IndexClass::size_type                      size_type;
+   typedef typename std::vector< value_type >::reference       reference;
+   typedef typename std::vector< value_type >::const_reference const_reference;
+   typedef typename std::vector< value_type >::pointer         pointer;
+   typedef typename std::vector< value_type >::const_pointer   const_pointer;
+
+private:
+   template< typename value_type2, typename IndexClass2 > friend class CbArray4D;
+
+public:
+   /*=======================================================================*/
+   CbArray4D()
+   {
+      this->resize(0,0,0,0);
+   }
+   /*=======================================================================*/
+   CbArray4D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4)
+   {
+      this->resize(nx1,nx2,nx3,nx4);
+   }
+   /*=======================================================================*/
+   CbArray4D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4, const value_type& val)
+   {
+      this->resize(nx1,nx2,nx3,nx4,val);
+   }
+   /*=======================================================================*/
+   CbArray4D(const size_type& uniformDimensionSize /*nx1=nx2=nx3=nx4*/)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   //ubernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird)
+   CbArray4D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4)
+   {
+      assert( (nx1*nx2*nx3*nx4)==vec.size() );
+      this->data.swap(vec);
+      this->resize(nx1,nx2,nx3,nx4);
+   }
+   /*=======================================================================*/
+   CbArray4D(const CbArray4D& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , nx3(src.nx3)
+       , nx4(src.nx4)
+       , data(src.data)
+   {
+   }
+   /*=======================================================================*/
+   template< typename value_type2 >
+   CbArray4D(const CbArray4D< value_type2 >& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , nx3(src.nx3)
+       , nx4(src.nx4)
+   {
+      //Sourcedaten kopieren
+      this->data.resize( src.data.size() );
+      for(std::size_t i=0; i<data.size(); ++i)
+         this->data[i] = src.data[i];
+   }
+   /*=======================================================================*/
+   virtual ~CbArray4D()
+   {
+      //vector wird automatisch zerstoert
+   }
+   /*=======================================================================*/
+   CbArray4D& operator= (const CbArray4D& rhs)
+   {
+      if(this == &rhs) return *this;
+
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+      this->nx3 = rhs.nx3;
+      this->nx4 = rhs.nx4;
+
+      //gespeicherte Datenelemente loeschen
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+
+      //Sourcedaten kopieren
+      this->data = rhs.data;
+
+      return *this;
+   }
+   /*=======================================================================*/
+   //durch value_type2 kann man z.B. ein float Array einem double Array zuweisen!
+   template< typename value_type2, typename IndexClass2 >
+   CbArray4D& operator= (const CbArray4D< value_type2, IndexClass2 >& rhs)
+   {
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+      this->nx3 = rhs.nx3;
+      this->nx4 = rhs.nx4;
+
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+
+      //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x1=0; x1<this->nx1; x1++)
+         for(int x2=0; x2<this->nx2; x2++)
+            for(int x3=0; x3<this->nx3; x3++)
+               for(int x4=0; x4<this->nx4; x4++)
+                  this->operator()(x1,x2,x3,x4) = static_cast< value_type >( rhs.operator()(x1,x2,x3,x4));
+
+      return *this;
+   }
+   /*=======================================================================*/
+   bool operator== (const CbArray4D& rhs) const
+   {
+      if( this == &rhs ) return true;
+
+      if(   this->nx1!=rhs.nx1
+         || this->nx2!=rhs.nx2
+         || this->nx3!=rhs.nx3
+         || this->nx4!=rhs.nx4
+         || this->data.size() != rhs.data.size() )
+      {
+         return false;
+      }
+
+      return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() );
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator== (const CbArray4D< value_type2, IndexClass2 >& rhs) const
+   {
+      if( this->data.size() != rhs.data.size() ) return false;
+
+      //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x4=0; x4<this->nx4; x4++)
+         for(int x3=0; x3<this->nx3; x3++)
+            for(int x2=0; x2<this->nx2; x2++)
+             for(int x1=0; x1<this->nx1; x1++)
+               if( !isUbEqual(this->operator()(x1,x2,x3,x4), rhs.operator()(x1,x2,x3,x4)) )
+                  return false;
+
+      return true;
+   }
+   /*=======================================================================*/
+   bool operator!= (const CbArray4D& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator!= (const CbArray4D< value_type2, IndexClass2 >& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   reference operator() (const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   const_reference operator() (const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)	const
+   {
+      #ifdef CbArray4D_RANGECHECKING
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)  const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   void setObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4, const value_type& value)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)] = value;
+   }
+   /*=======================================================================*/
+   reference getObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   const_reference getObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+      return (*this)(x1,x2,x3,x4,nx1,nx2,nx3,nx4);
+   }
+   /*=======================================================================*/
+   bool      isEmpty() const { return data.empty(); }
+   size_type getNX1()  const { return this->nx1;    }
+   size_type getNX2()  const { return this->nx2;    }
+   size_type getNX3()  const { return this->nx3;    }
+   size_type getNX4()  const { return this->nx4;    }
+   /*=======================================================================*/
+   void reset(const value_type& val)
+   {
+      std::fill( this->data.begin(), this->data.end(), val );
+   }
+   /*=======================================================================*/
+   std::string toString() const
+   {
+      std::stringstream text;
+      text<<std::setprecision(19);
+      for(size_type x1=0; x1<this->nx1; x1++)
+      {
+      	for(size_type x2=0; x2<this->nx2; x2++)
+      	{
+         	for(size_type x3=0; x3<this->nx3; x3++)
+         	{
+               for(size_type x4=0; x4<this->nx4; x4++)
+               {
+                 	text<<(*this)(x1,x2,x3,x4)<<", ";
+               }
+               text<<std::endl;
+         	}
+         	text<<std::endl;
+      	}
+      	text<<std::endl<<std::endl;
+      }
+
+      return text.str();
+   }
+   /*=======================================================================*/
+   std::string getInfo() const
+   {
+      std::stringstream text;
+      text<<"CbArray4D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >";
+      text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<", nx3="<<this->nx3<<", nx4="<<this->nx4<<")";
+      return text.str();
+   }
+   /*=======================================================================*/
+   void resize(const size_type& uniformDimensionSize) { this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize); }
+   /*=======================================================================*/
+   void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->nx3 = nx3;
+      this->nx4 = nx4;
+      this->data.resize(nx1*nx2*nx3*nx4);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4, const value_type& val)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->nx3 = nx3;
+      this->nx4 = nx4;
+      this->data.resize(nx1*nx2*nx3*nx4,val);
+   }
+   /*=======================================================================*/
+   std::vector< value_type >& getDataVector() { return this->data; }
+   /*=======================================================================*/
+   const std::vector< value_type >& getDataVector() const { return this->data; }
+   /*=======================================================================*/
+   inline std::size_t getDataVectorIndex(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4);
+   }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & nx4;
+      ar & data;
+   }
+#endif //CAB_RCF
+
+protected:
+   /*=======================================================================*/
+   //success -> true
+   //else    -> false
+   inline bool indicesInRange(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const
+   {
+      if(   x1 < 0 || x1 >= this->nx1
+         || x2 < 0 || x2 >= this->nx2
+         || x3 < 0 || x3 >= this->nx3
+         || x4 < 0 || x4 >= this->nx4 )
+      {
+         return false;
+      }
+      return true;
+   }
+   /*=======================================================================*/
+   std::string getExceptionErrorString(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const
+   {
+      std::stringstream out("index out of range - ");
+      out<<"("<<x1<<","<<x2<<","<<x3<<","<<x4<<") not in ("<<nx1<<","<<nx2<<","<<nx3<<","<<nx4<<")";
+      return out.str();
+   }
+   /*=======================================================================*/
+
+protected:
+   size_type    nx1;
+   size_type    nx2;
+   size_type    nx3;
+   size_type    nx4;
+   indexer_type indexer;
+   std::vector< value_type > data;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & nx4;
+      ar & data;
+   }
+};
+
+#endif //CBARRAY4D_H
diff --git a/source/ThirdParty/Library/basics/container/CbVector.h b/source/ThirdParty/Library/basics/container/CbVector.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b16e077308c2773a71530845ed5f98c6243144a
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/CbVector.h
@@ -0,0 +1,365 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBVECTOR_H
+#define CBVECTOR_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+   #include <RCF/ByteBuffer.hpp>
+#endif
+
+#include <vector>
+#include <algorithm> //for std::swap
+#include <typeinfo>  //for typeid
+#include <memory>    //for memcopy
+
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbEqual.h>
+
+/*=========================================================================*/
+/*  CbVector                                                               */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+@version 1.1 - 09.02.08
+@version 1.2 - 23.04.08 - swap added
+@version 1.3 - 08.05.08 - boosting up serialization performance!
+*/
+
+/*
+usage: ...
+Da es Voraussetzun bei doeser Klasse war, dass lediglich der Typ als
+template-parameter miteingeht, muss der allcocator eine abstrakte klasse sein
+ansonsten hätte sich hier der allokator als zweites argument
+wie beim STL vector angeboten, womit man auch keinen pointer speichern muesste.
+Im letzteren Fall würde aber jeweils ein bestimmeter Klassentyp in Abhaengigkeit
+des allokators zur compilezeit erzeugt. Problem wir wollen ein und denselben
+typ benutzen und nur der allokator innerhalb der klasse soll sich unterscheiden
+//
+// Rangecheck aktiv, wenn:
+// -debug  : not defined "NO_CB_RANGECHECK"
+// -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK"
+*/
+
+template< typename T > class CbVectorAllocator;
+template< typename T > class CbVectorAllocatorStd;
+
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+class CbVector
+{
+public:
+   typedef T           value_type;
+   typedef value_type* pointer;
+   typedef std::size_t size_type;
+
+   friend class CbVectorAllocator<value_type>; //um auf ptrData und dataSize zugreifen zu koennen!
+
+public:
+   /*==========================================================*/
+   CbVector( CbVectorAllocator<value_type>* const& allocator = new CbVectorAllocatorStd<value_type> )
+      :  ptrData(NULL)
+       , dataSize(0)
+       , allocator(allocator)
+   {
+      this->allocator->alloc(*this,0,value_type());
+   }
+   /*==========================================================*/
+   CbVector( const size_type size, CbVectorAllocator<value_type>* const& allocator = new CbVectorAllocatorStd<value_type>, const value_type& value=value_type() )
+      :  ptrData(NULL)
+       , dataSize(0)
+       , allocator(allocator)
+   {
+      this->allocator->alloc(*this,size,value);
+   }
+   /*==========================================================*/
+   virtual ~CbVector()
+   {
+      if(allocator)
+      {
+         this->allocator->dealloc(*this);
+         delete allocator;
+         allocator=NULL;
+      }
+   }
+   /*=======================================================================*/
+   CbVector& operator= (const CbVector& src)
+   {
+      if(this == &src) return *this;
+
+      //gespeicherte Datenelemente loeschen
+      //Laenge anpassen
+      this->allocator->resize(*this, src.size());
+
+      //gespeicherte Datenelemente kopieren
+      if( !src.empty() ) 
+      {
+         memcpy( (char*)ptrData, (char*)&src[0], src.size()*sizeof(value_type) ); 
+         //for(size_type i=0; i<src.size(); i++)
+         //   (*this)[i] = src[i];
+      }
+
+      return *this;
+   }
+   /*=======================================================================*/
+   CbVector& operator= (const std::vector< value_type >& src)
+   {
+      //gespeicherte Datenelemente loeschen
+      //Laenge anpassen
+      this->allocator->resize(*this, src.size());
+
+      //gespeicherte Datenelemente kopieren
+      if( !src.empty() ) 
+      {
+         memcpy( (char*)ptrData, (char*)&src[0], src.size()*sizeof(value_type) ); 
+         //for(size_type i=0; i<src.size(); i++)
+         //   (*this)[i] = src[i];
+      }
+      
+      return *this;
+   }
+   /*=======================================================================*/
+   bool operator== (const CbVector& rhs) const
+   {
+      if( this           == &rhs         ) return true;
+      if( this->dataSize != rhs.dataSize ) return false;
+
+      for(size_type i=0; i<rhs.size(); i++)
+         if( !isUbEqual( this->operator[](i), rhs.operator[](i) ) )
+            return false;
+
+      return true;
+   }
+   /*==========================================================*/
+   void setAllocator( CbVectorAllocator<value_type>* const& allocator )
+   {
+      if(this->allocator)
+      {
+         if(this->allocator==allocator) return;
+         this->allocator->dealloc(*this);
+         delete this->allocator;
+      }
+      this->allocator = allocator;
+      this->allocator->alloc(*this,0);
+   }
+   /*==========================================================*/
+   size_type size() const { return dataSize; }
+   /*==========================================================*/
+   bool empty() const { return dataSize==0; }
+   /*==========================================================*/
+   bool resize(const size_type& dataSize)
+   {
+      return allocator->resize(*this, dataSize);
+   }
+   /*==========================================================*/
+   bool resize(const size_type& dataSize, const value_type& value)
+   {
+      return allocator->resize(*this, dataSize, value);
+   }
+   /*==========================================================*/
+   void swap(CbVector& rhs)
+   {
+      if( this == &rhs ) return;
+
+      std::swap( this->ptrData  , rhs.ptrData   );
+      std::swap( this->dataSize , rhs.dataSize  );
+      std::swap( this->allocator, rhs.allocator );
+   }
+   /*==========================================================*/
+   value_type& operator[](const size_type& i)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if(i>=dataSize) 
+            UB_THROW( UbException(UB_EXARGS,"T="+(std::string)typeid(*this).name()+UbSystem::toString(i)+" out of range (size="+UbSystem::toString(dataSize)+")") );
+      #endif // _DEBUG
+
+      return ptrData[i];
+   }
+   /*==========================================================*/
+   const value_type& operator[](const size_type& i) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if(i>=dataSize) 
+            UB_THROW( UbException(UB_EXARGS,"T="+(std::string)typeid(*this).name()+UbSystem::toString(i)+" out of range (size="+UbSystem::toString(dataSize)+")") );
+      #endif // _DEBUG
+
+      return ptrData[i];
+   }
+   /*==========================================================*/
+   CbVectorAllocator<value_type>* getAllocator() const { return allocator; }
+   /*==========================================================*/
+   #ifdef CAB_RCF
+      template<typename Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         if( ArchiveTools::isWriting(ar) )
+         {
+            ar & allocator;
+            ar & dataSize; //!!!erst hier
+
+            //old:
+            //for(size_type i=0; i<dataSize; i++)
+            // ar & ptrData[i];
+
+            //new and boosting to the sky:
+            RCF::ByteBuffer byteBuffer( (char*) &ptrData[0], dataSize*sizeof(value_type) );
+            ar & byteBuffer;
+         }
+         else
+         {
+            CbVectorAllocator<value_type>* tmpCbVectorAllocator(NULL);
+            size_type tmpInteger;
+            ar & tmpCbVectorAllocator;
+            ar & tmpInteger;
+            this->setAllocator(tmpCbVectorAllocator);
+            allocator->resize(*this,tmpInteger);
+
+            //old:
+            //for(size_type i=0; i<dataSize; i++)
+            // ar & ptrData[i];
+
+            //new and boosting to the sky:
+            RCF::ByteBuffer byteBuffer;
+            ar & byteBuffer;
+            memcpy( (char*)ptrData, byteBuffer.getPtr(), byteBuffer.getLength() ); 
+         }
+      }
+   #endif //CAB_RCF
+
+private:
+   value_type* ptrData;
+   size_type   dataSize;
+   CbVectorAllocator<value_type>* allocator;
+   CbVector<value_type>(const CbVector<value_type>& src);
+   //CbVector<value_type>& operator=(const CbVector<value_type>& src);
+};
+
+//////////////////////////////////////////////////////////////////////////
+// CbVectorAllocator-Interface
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+class CbVectorAllocator
+{
+public:
+   typedef typename CbVector<T>::value_type          value_type;
+   typedef typename CbVector<value_type>::size_type  size_type;
+
+public:
+   CbVectorAllocator() {}
+   virtual ~CbVectorAllocator() {}
+
+   virtual bool alloc(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type()) = 0;
+   virtual bool resize(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type()) = 0;
+   virtual bool dealloc(CbVector< value_type >& vec) = 0;
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+   }
+#endif //CAB_RCF
+
+protected:
+   //folgende Methoden ersparen eine friend Deklaierung aller moeglichen Allocatoren
+   //denn durch diese beiden Methoden haben sie exklusive Zugriffsrechte!
+   //**********************************************************************************//
+   inline value_type*& ptrDataOf( CbVector< value_type >& vec )
+   {
+      if( vec.getAllocator()!=this ) UB_THROW( UbException(UB_EXARGS,"allocator is not member of vec!") );
+      return vec.ptrData;
+   }
+   //**********************************************************************************//
+   inline size_type& dataSizeOf( CbVector< value_type >& vec )
+   {
+      if( vec.getAllocator()!=this ) UB_THROW( UbException(UB_EXARGS,"allocator is not member of vec!") );
+      return vec.dataSize;
+   }
+};
+
+#ifdef RCF_USE_SF_SERIALIZATION
+SF_NO_CTOR(CbVectorAllocator<double>);
+SF_NO_CTOR(CbVectorAllocator<float>);
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+//////////////////////////////////////////////////////////////////////////
+// CbVectorAllocatorStd
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+class CbVectorAllocatorStd : public CbVectorAllocator<T>
+{
+public:
+   //typedefs wiederholen, da Basisklasse = template -> "Dependent-Base"-Problem
+   typedef typename CbVector<T>::value_type          value_type;
+   typedef typename CbVector<value_type>::size_type  size_type;
+
+public:
+   CbVectorAllocatorStd() : CbVectorAllocator<value_type>()
+   {
+
+   }
+   /*==========================================================*/
+   bool alloc(CbVector< value_type >& src, const size_type& dataSize, const value_type& value=value_type())
+   {
+      return this->resize(src,dataSize,value);
+   }
+   /*==========================================================*/
+   bool resize(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type())
+   {
+      if( CbVectorAllocatorStd< value_type >::dataSizeOf(vec) == dataSize) return false;
+
+      //new array
+      value_type* new_data = new value_type[dataSize];
+      //copy existing data to array
+      if( this->ptrDataOf(vec) )
+      {
+         for(size_type i=0; (i<vec.size() && i<dataSize); ++i) new_data[i] = CbVectorAllocatorStd< value_type >::ptrDataOf(vec)[i];
+         delete[] this->ptrDataOf(vec);
+      }
+      this->ptrDataOf(vec) = new_data;
+      //new value for new items
+      for(size_type i=this->dataSizeOf(vec); i<dataSize; ++i) this->ptrDataOf(vec)[i] = value;
+      //assign new dataSize
+      this->dataSizeOf(vec) = dataSize;
+
+      return true;
+   }
+   /*==========================================================*/
+   bool dealloc(CbVector< value_type >& vec)
+   {
+      if( this->ptrDataOf(vec) )
+      {
+         delete[] this->ptrDataOf(vec);
+         this->ptrDataOf(vec) = NULL;
+      }
+      this->dataSizeOf(vec) = 0;
+      return true;
+   }
+   /*==========================================================*/
+   #ifdef CAB_RCF
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         serializeParent< CbVectorAllocator<value_type> >(ar, *this);
+      }
+   #endif //CAB_RCF
+
+private:
+};
+
+
+#ifdef RCF_USE_SF_SERIALIZATION
+   UB_AUTO_RUN_NAMED(   SF::registerType< CbVectorAllocatorStd<double> >(" CbVectorAllocatorStd<double> ")       , SF_CbVectorAllocatorStd_double );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< CbVectorAllocator<double>, CbVectorAllocatorStd<double> >() ), SF_CbVectorAllocatorStd_double_BD1 );
+
+   UB_AUTO_RUN_NAMED(   SF::registerType< CbVectorAllocatorStd<float> >(" CbVectorAllocatorStd<float> "  )       , SF_CbVectorAllocatorStd_float  );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< CbVectorAllocator<float> , CbVectorAllocatorStd<float> >()  ), SF_CbVectorAllocatorStd_float_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //CBVECTOR_H
diff --git a/source/ThirdParty/Library/basics/container/CbVectorPool.h b/source/ThirdParty/Library/basics/container/CbVectorPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..000fe51593997759bee3446501750eb2eb87db8c
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/CbVectorPool.h
@@ -0,0 +1,465 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBVECTORPOOL_H
+#define CBVECTORPOOL_H
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <limits>
+#include <typeinfo>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/container/CbVector.h>
+
+//#include "MPICommunicator.h"
+//
+//#include <execinfo.h>
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <unistd.h>
+
+/*=========================================================================*/
+/*  CbVectorPool                                                               */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+@version 1.1 - 09.02.08
+*/
+
+/*
+Durch Verwendung eines CbVectors in Verbindung mit einem CbVectorAllocatorPool
+wird der Datenvector nicht direkt im CbVector gehalten, sondern ist ein Teil
+des Datenvectors des Übergabe-CbVectorPools.
+Die Methoden der von CbVectors funktionieren fehlerfrei
+Es mss einem jedoch bewußt sein, dass die "resize"-Methoden länger benötigen, da
+u.U. viele Elemente im Speicher verschoeben werden muessen.
+Der Poolvector enthaelt KEINE gaps, so dass er z.B. gut zur Übertragung via MPI
+geeignet ist...
+
+Verhaltensweise bei Zerstören des Pools:
+wird der Pool zerstört bevor man die CbVectoren zerstört, so wird beim nächsten
+Datenzugriffsversuch eine entsprechende Exception geworfen, denn alle DatenElemente
+des CbVEctors werden restet und der Pool dort zu NULL gesetzt.
+
+Verhaltensweise bei Zerstören eines CbVectors:
+hier ganz normal der Datenspeicher wieder freigegen und der Poolvektor verkürzt
+*/
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+
+template<typename T> class CbVectorAllocatorPool;
+
+/*==================================================================*/
+template<typename T>
+class CbVectorPool
+{
+public:
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned int CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+public:
+   //////////////////////////////////////////////////////////////////////////
+   CbVectorPool( const size_type& startPoolSize = 20000) //startPoolSize*sizeof(T)/1024/1024 [MB]
+      :  poolStartAdress(NULL)
+       , nextCbVectorStartIndexInPool(0)
+       , nextCbVectorKey(0)
+   {
+      pool.reserve(startPoolSize);
+   }
+   /*==================================================================*/
+   virtual ~CbVectorPool()
+   {
+      //hier werden lediglich ihre datenvektoren "resetet"
+      for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+      {
+         CbVector< value_type >& vec = *it->second;
+         CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+         if(allocator.ptrVectorPool != this) UB_THROW( UbException(UB_EXARGS,"CbVectorAllocator is part of different Pool") );
+
+         //allocator daten reseten
+         allocator.ptrVectorPool    = NULL;
+         allocator.key              = 0;
+         allocator.startIndexInPool = 0;
+
+         //Datenzeiger/-groessen reseten
+         allocator.ptrDataOf(vec)  = NULL;
+         allocator.dataSizeOf(vec) = 0;
+      }
+   }
+   /*==========================================================*/
+   CbVectorKey getNextCbVectorKey() const
+   {
+      return this->nextCbVectorKey;
+   }
+   /*==================================================================*/
+   bool allocVectorData(CbVector<value_type>& vec, const size_type& dataSize, const value_type& value=value_type() )
+   {
+      //pool-allocator holen
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+      if(allocator.ptrVectorPool != this) UB_THROW( UbException(UB_EXARGS,"CbVectorAllocator is part of different Pool") );
+
+      //alloc nur wenn cbVector noch kein Element von Pool!
+      if( cbVectorMap.find(allocator.key)==cbVectorMap.end()   )
+      {
+         return this->allocData(allocator, vec, dataSize, value );
+      }
+
+      UB_THROW( UbException(UB_EXARGS,"vector-key="+UbSystem::toString(allocator.key)+" bereits vergeben!") );
+   }
+   /*==================================================================*/
+   bool resizeVectorData(CbVector<value_type>& vec, const size_type& dataSize, const value_type& value=value_type() )
+   {
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+      if(allocator.ptrVectorPool != this) UB_THROW( UbException(UB_EXARGS,"CbVectorAllocator is part of different Pool") );
+
+      //cbVector noch nicht in map?
+      CbVectorMapIter pos = cbVectorMap.find(allocator.key);
+
+      if( pos!=cbVectorMap.end()  ) //cbVector vorhanden
+      {
+         //wenn bei alloc keine Laenge zugewiesen wurde, so erfolgt das nun
+         if( allocator.startIndexInPool==0 && allocator.ptrDataOf(vec)==NULL )
+            return this->allocData(allocator, vec, dataSize, value ) ;
+         else
+            return this->resizeData(allocator, vec, dataSize, value );
+      }
+
+      UB_THROW( UbException(UB_EXARGS,"vector gehoert laut allocator zum pool aber den key gibt s nicht... wie kann das sein?") );
+   }
+   /*==================================================================*/
+   bool deallocVectorData(CbVector<value_type>& vec)
+   {
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+      if(allocator.ptrVectorPool != this) UB_THROW( UbException(UB_EXARGS,"CbVectorAllocator is part of different Pool") );
+
+      //nur wenn vector auch teil des
+      if( cbVectorMap.erase(allocator.key) > 0 )
+      {
+         if( this->resizeData(allocator,vec,0,0) )
+         {
+            allocator.ptrVectorPool    = NULL;
+            allocator.key              = 0;
+            allocator.startIndexInPool = 0;
+
+            //das Datenzeiger/-groessen reseten wird bereits in resize durchgefuehrt
+            return true;
+         }
+         else UB_THROW( UbException(UB_EXARGS,"unknown error") );
+      }
+
+      
+      //CommunicatorPtr comm = MPICommunicator::getInstance();
+      //int myid = comm->getProcessID();
+
+//      // Get the name of the processor
+//      char machinename[MPI_MAX_PROCESSOR_NAME];
+//      int name_len;
+//      MPI_Get_processor_name(machinename, &name_len);
+//      UBLOG(logINFO, "PID = " << myid << " host name: " << machinename);
+//
+//      int j, nptrs;
+//#define SIZE 100
+//      void *buffer[100];
+//      char **strings;
+//
+//      nptrs = backtrace(buffer, SIZE);
+//      printf("backtrace() returned %d addresses\n", nptrs);
+//
+//      /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
+//      would produce similar output to the following: */
+//
+//      strings = backtrace_symbols(buffer, nptrs);
+//      if (strings == NULL)
+//      {
+//         perror("backtrace_symbols");
+//         exit(EXIT_FAILURE);
+//      }
+//
+//      for (j = 0; j < nptrs; j++)
+//         printf("%s\n", strings[j]);
+//
+//      free(strings);
+
+      UB_THROW(UbException(UB_EXARGS, "vector gehoert laut allocator zum pool aber den key gibt s nicht... wie kann das sein?"));
+   }
+   /*==================================================================*/
+   friend std::ostream& operator<<(std::ostream& os, const CbVectorPool& cbPool)
+   {
+      os<<"map"<<std::endl;
+      for(CbVectorMapIter pos=cbPool.cbVectorMap.begin(); pos!=cbPool.cbVectorMap.end(); ++pos)
+      {
+         CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool<value_type>& >(*pos->second->getAllocator());
+         os<<"vector-size="<<pos->second->size()<<"vector-Adress="<<tmpAllocator->ptrDataOf(*pos->second)<<", allocator(key="<<tmpAllocator.key<<", startIndex="<<tmpAllocator.startIndexInPool<<")"<<std::endl;
+         for(size_type i=0; i<pos->second->size(); i++) os<<(*pos->second)[i]<<","; 
+         os<<std::endl;
+      }
+      os<<"pool"<<std::endl;
+      for(size_type i=0; i<cbPool.pool.size(); i++)
+            os<<cbPool.pool[i]<<","; os<<std::endl;
+
+      return os;
+   }
+   /*==================================================================*/
+   typename CbVectorMap::size_type getNofStoredVectors() const
+   {
+      return this->cbVectorMap.size();
+   }
+   /*==================================================================*/
+   typename Pool::size_type getPoolSize() const
+   {
+      return this->pool.size();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   bool consistencyCheck()
+   {
+      std::vector<int> pool2(pool.size(),0);
+      for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+      {
+         CbVector< value_type >& tmpVec = *it->second;
+         CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool<value_type>& >(*tmpVec.getAllocator());
+         for(size_type i=tmpAllocator.startIndexInPool; i<tmpAllocator.startIndexInPool+tmpVec.size(); ++i)
+         {
+            pool2.at(i)++;
+         }
+      }
+      for( size_type i=0; i<pool2.size(); ++i )
+      {
+         if(pool2.at(i) > 1 ) { UBLOG(logERROR,UB_FUNCTION<<" - test failed typo 1"); return false; }
+         if(pool2.at(i) < 1 ) { UBLOG(logERROR,UB_FUNCTION<<" - test failed typo 2"); return false; }
+      }
+      return true;
+   }
+protected:
+   /*==================================================================*/
+   inline bool allocData(CbVectorAllocatorPool< value_type >& allocator, CbVector< value_type >& vec, const size_type& dataSize, const value_type& value )
+   {
+      //safety checks
+      if(    allocator.startIndexInPool!=0
+          || allocator.ptrDataOf(vec)!=NULL
+          || allocator.dataSizeOf(vec)!=0   )
+      {
+         UB_THROW( UbException(UB_EXARGS,"zu allokierender vector ist nicht ganz sauber!!") );
+      }
+
+      //poolVector vergroessern
+      if( dataSize>0 )
+      {
+         pool.resize( pool.size() + dataSize, value );
+
+         //Zeiger der vorhandenen CbVectoren neu setzen, wenn Pool im Speicher verschoben wurde
+         if( poolStartAdress != &pool.front() )
+         {
+            poolStartAdress = &pool.front();
+            for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+            {
+               CbVector< value_type >& tmpVec = *it->second;
+               CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*tmpVec.getAllocator());
+
+               if( !tmpAllocator.ptrDataOf(tmpVec) ) continue; //Fall: CbVector hat noch keinen Datenbereich (data zeigt auf NULL)
+               tmpAllocator.ptrDataOf(tmpVec) = &pool[ tmpAllocator.startIndexInPool];
+            }
+            //std::cout<<"CbVectorPoolMpi::allocVectorData vector wurde im speicher verschoben - adressen angepasst!!!"<<std::endl;
+         }
+
+         //aktuellem element adresse zuweisen (wurde evtl schon inder schleife zuvor gemacht)
+         allocator.ptrDataOf(vec) = &pool.at(nextCbVectorStartIndexInPool);
+         allocator.startIndexInPool = nextCbVectorStartIndexInPool;
+
+         //neuen StartIndex fuer naechstes Element berechnen
+         nextCbVectorStartIndexInPool += dataSize;
+         if(nextCbVectorStartIndexInPool!=pool.size())
+            UB_THROW( UbException(UB_EXARGS,"index Problem... Annahme falsch?") );
+      }
+
+      //vector zu map hinzufügen (speicher wird dann anschliessend zugwiesen)
+      cbVectorMap.insert( std::make_pair( allocator.key, &vec ) ); // ist angeblich performanter als  cbVectorMap[ allocator.key ] = cbVector; //aus Effective STL von Scott Meyer
+      allocator.dataSizeOf(vec) = dataSize;
+
+      //dummDoof nextKey-Generung...
+      if( allocator.key >= this->nextCbVectorKey ) this->nextCbVectorKey = allocator.key + 1;
+
+      return true;
+   }
+   /*==========================================================*/
+   bool resizeData(CbVectorAllocatorPool< value_type >& allocator, CbVector<value_type>& vec, const size_type& dataSize, const value_type& value )
+   {
+      //datenvector verlaengern/-kuerzen
+      typename Pool::iterator startPos = pool.begin()+allocator.startIndexInPool; //startPosition der cbVector-Daten im Pool
+      if( vec.size() > dataSize ) pool.erase( startPos+dataSize, startPos+vec.size());
+      else                        pool.insert( startPos+vec.size(), dataSize-vec.size(), value );
+
+      //////////////////////////////////////////////////////////////////////////
+      //adressen und laengen der einzelnen vectoren anpassen
+      if( !pool.empty() )
+      {
+         bool poolMoved   = ( poolStartAdress != &pool.front() );
+         poolStartAdress  = &pool.front();
+
+         for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+         {
+            CbVector< value_type >& tmpVec = *it->second;
+
+            if( tmpVec.size()>0 )
+            {
+               CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool<value_type>& >(*tmpVec.getAllocator());
+               //liegt CbVector VOR verändertem CbVector?
+               if( tmpAllocator.startIndexInPool <= allocator.startIndexInPool ) //ja: anpassung NUR wenn pool verschoben wurde!
+               {
+                  if(poolMoved && tmpVec.size()>0 ) tmpAllocator.ptrDataOf(tmpVec) = &pool[ tmpAllocator.startIndexInPool];
+               }
+               else //nein: -> Adresse + Index MUSS immer angepasst werden
+               {
+                  tmpAllocator.startIndexInPool += dataSize-vec.size();
+                  tmpAllocator.ptrDataOf(tmpVec) = &pool[ tmpAllocator.startIndexInPool ];
+               }
+            }
+         }
+      }
+      else //Sonderfall: alle Elemente haben Laenge 0 -> kein pool -> alle Feld-Adressen auf NULL setzen!
+      {
+         poolStartAdress = NULL;
+         for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+         {
+            CbVector< value_type >& tmpVec = *it->second;
+            CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool<value_type>& >(*tmpVec.getAllocator());
+            tmpAllocator.startIndexInPool = 0;
+         }
+
+      }
+
+      //restliche Daten von cbVector + allocator aktualisieren
+      allocator.dataSizeOf(vec) = dataSize;
+      if(dataSize==0)
+      {
+         allocator.ptrDataOf(vec)   = NULL;
+         allocator.startIndexInPool = 0;
+      }
+
+      nextCbVectorStartIndexInPool = pool.size();
+
+      return true;
+   }
+
+protected:
+   /*==================================================================*/
+   void getCbVectorData(const CbVector< value_type >& vec, CbVectorKey& vectorKey, size_type& startIndexInPool, size_type& dataSize )
+   {
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+
+      startIndexInPool  = allocator.startIndexInPool;
+      vectorKey         = allocator.key;
+      dataSize          = vec.size();
+   }
+   /*==================================================================*/
+   void setCbVectorData(CbVector< value_type >& vec, const CbVectorKey& vectorKey, const size_type& startIndexInPool, const size_type& dataSize )
+   {
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+
+      allocator.startIndexInPool = startIndexInPool;
+      allocator.key              = vectorKey;
+      allocator.dataSizeOf(vec)  = dataSize;
+      allocator.ptrDataOf(vec)   = &this->pool[ startIndexInPool ];
+   }
+   /*==================================================================*/
+
+   CbVectorMap                cbVectorMap;                      //informationsmap fuer MPIData und zugewiesener vector
+
+   Pool                       pool;                             //globaler Datenvector
+   typename Pool::pointer     poolStartAdress;                  //StartAdresse des aktuellen Datenvektors
+   typename Pool::size_type   nextCbVectorStartIndexInPool;     //StartIndex fuer den naechsten CbVector
+
+   //key - erstmal dummdoof
+   CbVectorKey nextCbVectorKey;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//  CbVectorAllocatorPool
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+class CbVectorAllocatorPool : public CbVectorAllocator<T>
+{
+public:
+   //typedefs wiederholen, da Basisklasse = template -> "Dependent-Base"-Problem
+   typedef typename CbVector<T>::value_type          value_type;
+   typedef typename CbVector<value_type>::size_type  size_type;
+
+   friend class CbVectorPool< value_type >;
+
+public:
+   /*==========================================================*/
+   CbVectorAllocatorPool(const typename CbVectorPool< value_type >::CbVectorKey& key, CbVectorPool<value_type>* const& ptrVectorPool)
+      :  CbVectorAllocator<value_type>()
+       , key(key)
+       , startIndexInPool(0)
+       , ptrVectorPool(ptrVectorPool)
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"ptrVectorPool==NULL") );
+   }
+   /*==========================================================*/
+   //hier wird der key automatisch erzeugt!
+   CbVectorAllocatorPool(CbVectorPool<value_type>* const& ptrVectorPool)
+      :  CbVectorAllocator<value_type>()
+       , startIndexInPool(0)
+       , ptrVectorPool(ptrVectorPool)
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"ptrVectorPool==NULL") );
+      key = ptrVectorPool->getNextCbVectorKey();
+   }
+   /*==========================================================*/
+   bool alloc(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type())
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"vectorPool seems to be destroyed, ptrVectorPool==NULL") );
+      return ptrVectorPool->allocVectorData(vec, dataSize, value);
+   }
+   /*==========================================================*/
+   bool resize(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type())
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"vectorPool seems to be destroyed, ptrVectorPool==NULL") );
+      return ptrVectorPool->resizeVectorData(vec, dataSize, value);
+   }
+   /*==========================================================*/
+   bool dealloc(CbVector< value_type >& vec)
+   {
+      if(ptrVectorPool) return this->ptrVectorPool->deallocVectorData(vec);
+      //wenn kein ptrVectorPool -> wurde bereits deallokiert
+      return true;
+   }
+   /*==========================================================*/
+   const CbVectorPool< value_type >& getCbVectorPool()
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"vectorPool seems to be destroyed, ptrVectorPool==NULL") );
+      return *ptrVectorPool;
+   }
+   /*==========================================================*/
+
+private:
+   typename CbVectorPool< value_type >::CbVectorKey     key;
+   typename CbVectorPool< value_type >::Pool::size_type startIndexInPool;
+
+   CbVectorPool< value_type >* ptrVectorPool;
+
+   CbVectorAllocatorPool( const CbVectorAllocatorPool& );                 //no copy allowed
+   const CbVectorAllocatorPool& operator=( const CbVectorAllocatorPool& );//no copy allowed
+};
+
+
+#endif //CBVECTORPOOL_H
diff --git a/source/ThirdParty/Library/basics/container/examples/CbVectorPool/CMakeLists.txt b/source/ThirdParty/Library/basics/container/examples/CbVectorPool/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6cf6d2526048573fa4bbf1426f28279b0dc46bb4
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/examples/CbVectorPool/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(CbVectorPoolTests)
+
+#################################################################
+# MACHINE_SPECIFIC CMAKE_CONFIG_FILE
+#################################################################
+INCLUDE("../../../../../../../CMake/CMakeCABMacros.txt")
+
+#################################################################
+###   PACKAGES                                               ###
+#################################################################
+INCLUDE(${SOURCE_ROOT}/basics/container/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/memory/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/objects/CMakePackage.txt)
+
+#################################################################
+###   OWN DEFINES 						###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${SOURCE_ROOT}/basics/container/examples/CbVectorPool/*.h
+                         ${SOURCE_ROOT}/basics/container/examples/CbVectorPool/*.cpp ) 
+
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(z_specific FILES ${SPECIFIC_FILES})
+
+#################################################################
+###  PROJECT ERSTELLEN                                        ###
+#################################################################
+CREATE_CAB_PROJECT()
diff --git a/source/ThirdParty/Library/basics/container/examples/CbVectorPool/functions.h b/source/ThirdParty/Library/basics/container/examples/CbVectorPool/functions.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9e376731e5581c75efbfa093122afc42f2405ad
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/examples/CbVectorPool/functions.h
@@ -0,0 +1,190 @@
+#include <iostream>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string>
+#include <fstream>
+
+#include <basics/utilities/UbTuple.h>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <basics/utilities/UbTiming.h>
+
+#include <basics/memory/MbSmartPtr.h>
+
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+
+typedef long double value_type;
+typedef MbSmartPtr<CbVector< value_type > > CbVectorPtr;
+typedef MbSmartPtr<vector< value_type > >   StlVectorPtr;
+
+/*==========================================================*/
+template<typename T>
+inline void setValues(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec)
+{
+   if(stlvec.size() != cbvec.size() || stlvec.size() != cbpoolvec.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvec.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvec.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvec.size()<<endl;
+      throw UB_THROW( UbException("setValues - sizeCheck failed") );
+   }
+   static value_type stlVal    = 1;
+   static value_type cbVal     = 1;
+   static value_type cbPoolVal = 1;
+
+   for(size_t i=0; i<cbvec.size(); i++) stlvec[i]    = stlVal   ++;
+   for(size_t i=0; i<cbvec.size(); i++) cbvec[i]     = cbVal    ++;
+   for(size_t i=0; i<cbvec.size(); i++) cbpoolvec[i] = cbPoolVal++;
+}
+/*==========================================================*/
+template<typename T>
+inline void setValues(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      throw UB_THROW( UbException("setValues glob - sizeCheck failed") );
+   }
+
+   for(size_t i=0; i<cbvecs.size(); i++)
+      setValues(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i]);
+}
+/*==========================================================*/
+template<typename T>
+inline void resize(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec, std::size_t size, const T& val)
+{
+   stlvec.resize(size,val);
+   cbvec.resize(size,val);
+   cbpoolvec.resize(size,val);
+}
+/*==========================================================*/
+template<typename T>
+inline void resize(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, std::size_t size, const value_type& val, bool timed=false)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      throw UB_THROW( UbException("resize glob - sizeCheck failed") );
+   }
+
+   if(timed)
+   {
+      UbTimer timer;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) stlvecs[i]->resize(size,val);    if(timed) cout<<"stl-resize    in "<<timer.stop()<<"s"<<endl;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) cbvecs[i]->resize(size,val);     if(timed) cout<<"cbStd-resize  in "<<timer.stop()<<"s"<<endl;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) cbpoolvecs[i]->resize(size,val); if(timed) cout<<"cbPool-resize in "<<timer.stop()<<"s"<<endl;
+   }
+   else
+   {
+      for(size_t i=0; i<cbvecs.size(); i++)
+         resize(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i],size,val);
+   }
+}
+/*==========================================================*/
+inline void createVecs(size_t number, int size,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, CbVectorPool<value_type>*& pool, bool timed=false)
+{
+   UbTimer timer;
+   timer.start(); for(size_t i=0; i<number; i++) stlvecs.push_back(StlVectorPtr(new vector<value_type>(size)));                                                  if(timed) cout<<"stl-createVecs    in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbvecs.push_back(CbVectorPtr(new CbVector<value_type>(size)));                                                  if(timed) cout<<"cbStd-createVecs  in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbpoolvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorPool<value_type>(pool))));  if(timed) cout<<"cbPool-createVecs in "<<timer.stop()<<"s"<<endl;
+
+   for(size_t i=0; i<cbvecs.size(); i++) setValues(*stlvecs.back(),*cbvecs.back(),*cbpoolvecs.back());
+}
+/*==========================================================*/
+inline void createVecs(size_t number, size_t size, const value_type& val,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, CbVectorPool<value_type>*& pool, bool timed=false)
+{
+   UbTimer timer;
+   timer.start(); for(size_t i=0; i<number; i++) stlvecs.push_back(StlVectorPtr(new vector<value_type>(size,val)));                                                  if(timed) cout<<"stl-createVecs    in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorStd<value_type>(),val)));           if(timed) cout<<"cbStd-createVecs  in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbpoolvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorPool<value_type>(pool),val)));  if(timed) cout<<"cbPool-createVecs in "<<timer.stop()<<"s"<<endl;
+}
+/*==========================================================*/
+template<typename T>
+inline void equalCheck(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec)
+{
+   if(stlvec.size() != cbvec.size() || stlvec.size() != cbpoolvec.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvec.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvec.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvec.size()<<endl;
+      throw UB_THROW( UbException("equalCheck - sizeCheck failed") );
+   }
+
+   bool check=true;
+   for(size_t i=0; i<cbvec.size(); i++)
+      if(stlvec[i] != cbvec[i] || stlvec[i] != cbpoolvec[i]  )
+         check=false;
+
+   if(!check)
+   {
+      cerr<<"\nstl - "; for(size_t i=0; i<cbvec.size(); i++) cout<<stlvec[i]<<" ";    cout<<endl;
+      cerr<<  "cbv - "; for(size_t i=0; i<cbvec.size(); i++) cout<<cbvec[i]<<" ";     cout<<endl;
+      cerr<<  "cbp - "; for(size_t i=0; i<cbvec.size(); i++) cout<<cbpoolvec[i]<<" "; cout<<endl;
+      throw UB_THROW( UbException("equalCheck - equalCheck failed") );
+   }
+}
+/*==========================================================*/
+template<typename T>
+void equalCheck(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      throw UB_THROW( UbException("equalCheck - sizeCheck failed") );
+   }
+
+   for(size_t i=0; i<cbvecs.size(); i++)
+   {
+      //cout<<"equalCheck i="<<i<<"/"<<cbvecs.size()-1;
+      equalCheck(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i]);
+      //cout<<" passed"<<endl;
+   }
+}
+/*==========================================================*/
+void accessCheck(int times,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   UbTimer timer;
+   timer.start();
+   for(size_t i=0; i<stlvecs.size(); i++)
+   {
+      vector<value_type>& vec = *stlvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"stl-accessCheck       in "<<timer.stop()<<"s"<<endl;
+   timer.start();
+   for(size_t i=0; i<cbvecs.size(); i++)
+   {
+      CbVector<value_type>& vec = *cbvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"cbStd-accessCheck     in "<<timer.stop()<<"s"<<endl;
+   timer.start();
+   for(size_t i=0; i<cbpoolvecs.size(); i++)
+   {
+      CbVector<value_type>& vec = *cbpoolvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"cbPool-accessCheck    in "<<timer.stop()<<"s"<<endl;
+}
diff --git a/source/ThirdParty/Library/basics/container/examples/CbVectorPool/main.cpp b/source/ThirdParty/Library/basics/container/examples/CbVectorPool/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b3fe50b252cacff1c0484a54a77ee4427316d748
--- /dev/null
+++ b/source/ThirdParty/Library/basics/container/examples/CbVectorPool/main.cpp
@@ -0,0 +1,277 @@
+#include "./functions.h"
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char** argv)
+{
+   try
+   {
+       {
+         CbVectorPool<float>* floatPool = new CbVectorPool<float>(0);
+         CbVector<float> v1,v2,v3;
+         CbVector<float> v0(new CbVectorAllocatorPool<float>(104,floatPool) );
+         v0.resize(20);
+         v0[3] = 60000;
+         v0.resize(40);
+         v0[3] = 90000;
+         v1.setAllocator( new CbVectorAllocatorPool<float>(100,floatPool) );
+         v2.setAllocator( new CbVectorAllocatorPool<float>(101,floatPool) );
+         v3.setAllocator( new CbVectorAllocatorPool<float>(102,floatPool) );
+         v1.resize(20, 0.0);
+         v1.resize(30, 0.0);
+         v2.resize(0);
+         v2.resize(40, 0.0);
+         v3.resize(30, 0.0);
+         v3.resize(50, 0.0);
+
+         for(CbVector<float>::size_type i=v1.size()-1; i>=15; i--)
+            v1[i] = (CbVector<float>::value_type)i;
+         for(CbVector<float>::size_type i=v2.size()-1; i>=35; i--)
+            v2[i] = (CbVector<float>::value_type)i;
+         for(CbVector<float>::size_type i=v3.size()-1; i>=10; i--)
+            v3[i] = (CbVector<float>::value_type)i;
+         v1.size(); 
+         v2.size();
+         v3.size();
+         for(CbVector<float>::size_type i=0; i<v1.size(); i++)  v1[i];
+         v1.size();
+         v2.size();
+         v3.size();
+         for(CbVector<float>::size_type i=0; i<v2.size(); i++) v2[i];
+         v1.size();
+         v2.size();
+         v3.size();
+         for(CbVector<float>::size_type i=0; i<v3.size(); i++) v3[i];
+      }
+      
+     CbVectorPool<value_type>* vectorPool = new CbVectorPool<value_type>(0);
+
+     vector< StlVectorPtr > stlVecs;
+     vector< CbVectorPtr >  cbVecs;
+     vector< CbVectorPtr >  cbPoolVecs;
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(10,12,0,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,0,2);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,3,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(8,5,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,7);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,0,7);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(4,3,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,0,7);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     //dealloc check
+     stlVecs.resize(5);
+     cbVecs.resize(5);
+     cbPoolVecs.resize(5);
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(4,3,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(4,3,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+
+     //operator= check
+     CbVector<value_type> testPool1(10, new CbVectorAllocatorPool<value_type>(vectorPool));
+     CbVector<value_type> testPool2(1 , new CbVectorAllocatorPool<value_type>(vectorPool));
+     CbVector<value_type> testPool3(8 , new CbVectorAllocatorPool<value_type>(vectorPool));
+     CbVector<value_type> testPool4(8 , new CbVectorAllocatorPool<value_type>(vectorPool));
+     CbVector<value_type> testStd1(10);
+
+     for(CbVector<value_type>::size_type i=0; i<testStd1.size(); i++ )
+        testStd1[i] = (value_type)i*10;
+
+     testPool1 = testStd1;
+     testPool4 = testStd1;
+     testPool3 = testPool4;
+     testPool2 = testPool3;
+
+     for(CbVector<value_type>::size_type i=0; i<testStd1.size(); i++ )
+        cout<<testStd1[i]<<" "; cout<<endl;
+     for(CbVector<value_type>::size_type i=0; i<testPool1.size(); i++ )
+        cout<<testPool1[i]<<" "; cout<<endl;
+     for(CbVector<value_type>::size_type i=0; i<testPool2.size(); i++ )
+        cout<<testPool2[i]<<" "; cout<<endl;
+     for(CbVector<value_type>::size_type i=0; i<testPool3.size(); i++ )
+        cout<<testPool3[i]<<" "; cout<<endl;
+     for(CbVector<value_type>::size_type i=0; i<testPool4.size(); i++ )
+        cout<<testPool4[i]<<" "; cout<<endl;
+    ///end
+
+
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"// access test - start"<<endl;
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(1000,1000,stlVecs,cbVecs,cbPoolVecs,vectorPool,true);
+
+     CbVectorPool<value_type>* pool2 = new CbVectorPool<value_type>(1);
+     vector< StlVectorPtr > stlVecs2;
+     vector< CbVectorPtr >  cbVecs2;
+     vector< CbVectorPtr >  cbPoolVecs2;
+     createVecs(1000,1000,stlVecs2,cbVecs2,cbPoolVecs2,pool2,true);
+
+     cout<<"access check\n";
+     //accessCheck(1000,stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,120,3,true);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"// access test - end"<<endl;
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"// EXCEPTION TEST - start"<<endl;
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     delete vectorPool;
+     vectorPool = NULL;
+     try
+     {
+        resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     }
+     catch(UbException& e)
+     {
+        cout<<"if exception tells something about \"vectorPool==NULL\" -> test successfully passed:"<<endl;
+        cout<<e<<endl;
+     }
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"// EXCEPTION TEST - end"<<endl;
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+
+     cout<<"\n\n\nALL TESTS PASSED\n";
+   }
+   catch(UbException& e)
+   {
+      std::cerr<<e<<std::endl;
+   }
+   catch(const std::exception &e)
+   {
+      std::cerr << "Caught exception:\n";
+      std::cerr << "Type: " << typeid(e).name() << "\n";
+      std::cerr << "What: " << e.what() << "\n";
+   }
+   catch(...)
+   {
+      std::cerr<<" **            Verdammte Scheisse - mal wieder Mist gebaut!                **"<<endl;
+   }
+    return 0;
+}
+
+// #include <functional>
+// #include <iostream>
+// #include <vector>
+// #include <algorithm>
+// #include <typeinfo>
+//
+// struct bar
+// {
+//    bar()
+//       : data(0)
+//    {}
+//
+//    void foo(const std::size_t value) { std::cout << "data = " << value << " (old: " << data << ");" << std::endl; data = value; }
+//
+// private:
+//    std::size_t data;
+// };
+//
+// int main()
+// {
+//    std::vector<bar> data(10);
+//
+//    /* operator[] => Indexoperator */
+//    for (std::size_t i(0); i < data.size(); ++i)
+//       data[i].foo(2);
+//
+//    /* begin(), end() => Iterator */
+//    const std::vector<bar>::iterator it_end(data.end());
+//    for (std::vector<bar>::iterator it(data.begin()); it != it_end; ++it)
+//       it->foo(3);
+//
+//    /* for_each => Algorithm | Iterator */
+//    std::for_each(data.begin(), data.end(), std::bind2nd(std::mem_fun_ref(&bar::foo), 2));
+// }
diff --git a/source/ThirdParty/Library/basics/memory/CMakePackage.txt b/source/ThirdParty/Library/basics/memory/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/ThirdParty/Library/basics/memory/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/ThirdParty/Library/basics/memory/MbChessMemPool2D.h b/source/ThirdParty/Library/basics/memory/MbChessMemPool2D.h
new file mode 100644
index 0000000000000000000000000000000000000000..c665f7798f096fd9bc95d70e6d45e7b4f2716b30
--- /dev/null
+++ b/source/ThirdParty/Library/basics/memory/MbChessMemPool2D.h
@@ -0,0 +1,519 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBCHESSMEMPOOL2D_H
+#define MBCHESSMEMPOOL2D_H
+
+#include <map>
+#include <vector>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <cmath>
+#include <typeinfo>
+
+#include <basics/utilities/UbException.h>
+
+
+template <class TData, std::size_t cachSize>
+class MbChessMemPool2D;
+
+//////////////////////////////////////////////////////////////////////////
+//class MbChessMap2DKey
+//key zum Auffinden der ChessMem2DBlocks
+class MbChessMap2DKey
+{
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //Konstruktoren
+   MbChessMap2DKey(): mVectorPos(0),mFirstCriteria(0),mSecondCriteria(0)
+   {
+
+   }
+   /*==========================================================*/
+   MbChessMap2DKey(std::size_t vectorPos, std::size_t firstCriteria, std::size_t secondCriteria)
+      : mVectorPos(vectorPos), mFirstCriteria(firstCriteria), mSecondCriteria(secondCriteria)
+   {
+   }
+   /*==========================================================*/
+   MbChessMap2DKey& operator=(const MbChessMap2DKey& srcKey)
+   {
+      if(this == &srcKey ) return *this;
+
+      mVectorPos      = srcKey.mVectorPos;
+      mFirstCriteria  = srcKey.mFirstCriteria;
+      mSecondCriteria = srcKey.mSecondCriteria;
+
+      return *this;
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //global ueberladene Operatoren
+   friend inline bool operator<(const MbChessMap2DKey& lhsKey,const MbChessMap2DKey& rhsKey)
+   {
+      if(lhsKey.mFirstCriteria  < rhsKey.mFirstCriteria ) return true;
+      if(lhsKey.mFirstCriteria  > rhsKey.mFirstCriteria ) return false;
+      if(lhsKey.mSecondCriteria < rhsKey.mSecondCriteria) return true;
+
+      return false;
+   }
+   /*==========================================================*/
+   friend inline bool operator==(const MbChessMap2DKey& lhsKey,const MbChessMap2DKey& rhsKey)
+   {
+      if(lhsKey.mVectorPos      != rhsKey.mVectorPos      ) return false;
+      if(lhsKey.mFirstCriteria  != rhsKey.mFirstCriteria  ) return false;
+      if(lhsKey.mSecondCriteria != rhsKey.mSecondCriteria ) return false;
+
+      return true;
+   }
+   //ueberladene Operatoren
+   friend inline bool operator!=(const MbChessMap2DKey& lhsKey,const MbChessMap2DKey& rhsKey)
+   {
+      return !(lhsKey==rhsKey);
+   }
+   //ueberladene Operatoren
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const MbChessMap2DKey& key)
+   {
+      os<<"VectorPos,first-,second-,third Criteria) (";
+      os<<key.mVectorPos<<","<<key.mFirstCriteria<<","<<key.mSecondCriteria<<")";
+      return os;
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //public Methoden
+   std::size_t getVectorPos() {return mVectorPos;}
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private Member
+   std::size_t mVectorPos;
+   std::size_t mFirstCriteria;
+   std::size_t mSecondCriteria;
+};
+
+
+
+template<class T,std::size_t cachSize>
+class MbChessMem2DBlock
+{
+   friend class MbChessMemPool2D<T,cachSize>;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //Konstruktoren
+   MbChessMem2DBlock()
+   {
+      mUsedElements = 0;
+      std::size_t arrayLength = mBlockWidth*mBlockWidth;
+      //mDataElements = new T[arrayLength];
+      mDataElements = operator new(arrayLength*sizeof(T));
+      mFlagVector   = new bool[arrayLength];
+      for(std::size_t i=0;i<arrayLength;i++) mFlagVector[i] = false;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //Destruktor
+   ~MbChessMem2DBlock()
+   {
+      //if(mDataElements) delete[] mDataElements;
+      if(mDataElements) operator delete(mDataElements);
+      if(mFlagVector)   delete[] mFlagVector;
+   }
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private Methoden
+   void* getReference(std::size_t chessX1, std::size_t chessX2)
+   {
+      std::size_t arrayIndex = chessX2*mBlockWidth + chessX1;
+      #ifdef _DEBUG
+         if(arrayIndex>=mBlockWidth*mBlockWidth) UB_THROW( UbException(UB_EXARGS,"index out of range") );
+      #endif
+
+      if(mFlagVector[arrayIndex]==true) UB_THROW( UbException(UB_EXARGS,"memory already allocated!") );
+
+      mUsedElements++;
+      mFlagVector[arrayIndex]=true;
+
+      return (void*)((T*)(mDataElements)+arrayIndex);//&(mDataElements[arrayIndex]);
+   }
+   /*==========================================================*/
+   std::size_t freeReference(void* p)
+   {
+      //std::size_t arrayIndex = static_cast<std::size_t>(static_cast<T*>(p) - mDataElements); //mDataElements = &mDataElements[0]
+      std::size_t arrayIndex = static_cast<std::size_t>(static_cast<T*>(p) - static_cast<T*>(mDataElements));
+
+      #ifdef _DEBUG
+         if(arrayIndex>=mBlockWidth*mBlockWidth) UB_THROW( UbException(UB_EXARGS,"index out of range") );
+      #endif
+
+      if(mFlagVector[arrayIndex]==false) UB_THROW( UbException(UB_EXARGS,"memory not allocated!") );
+
+      mFlagVector[arrayIndex]=false;
+
+      return --mUsedElements;
+   }
+   /*==========================================================*/
+   std::size_t getNofUsedElements()   { return mUsedElements; }
+   /*==========================================================*/
+   void addPointerToTElementsToVector(std::vector<T*>& tdataVector)
+   {
+      std::size_t arrayLength = mBlockWidth*mBlockWidth;
+      for(std::size_t arrayIndex=0;arrayIndex<arrayLength;arrayIndex++)
+      {
+         //if(mFlagVector[arrayIndex]) tdataVector.push_back(&mDataElements[arrayIndex]);
+         if(mFlagVector[arrayIndex]) tdataVector.push_back(static_cast<T*>(mDataElements)+arrayIndex);
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   void addPointerToTElementsToVector(std::vector<T*>& tdataVector, Pred& pred)
+   {
+      std::size_t arrayLength = mBlockWidth*mBlockWidth;
+      T* tmp;
+      for(std::size_t arrayIndex=0;arrayIndex<arrayLength;arrayIndex++)
+      {
+         if(mFlagVector[arrayIndex])
+         {
+            //tmp = &mDataElements[arrayIndex];
+            tmp = (static_cast<T*>(mDataElements))+arrayIndex;
+            if( pred(*tmp) ) tdataVector.push_back(tmp);
+         }
+      }
+   }
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //static Member
+   static const std::size_t   mBlockWidth;
+
+   //////////////////////////////////////////////////////////////////////////
+   //private Member
+   std::size_t   mUsedElements;
+   //T*    mDataElements;
+   void* mDataElements;
+   bool* mFlagVector;
+
+};
+
+//////////////////////////////////////////////////////////////////////////
+//class MbChessMemPool2D
+//zum Verwalten von TData Elementen in einer Schabrett-artigen Struktur
+//die ChessMemBloecke haben hier eine Groesse von ~cachSize
+template <class TData, std::size_t cachSize>
+class MbChessMemPool2D
+{
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //protected static const Member
+   const static std::size_t mCacheSize;
+
+   //////////////////////////////////////////////////////////////////////////
+   //protected Member
+   static std::vector< std::map< MbChessMap2DKey , MbChessMem2DBlock< TData,cachSize >* > > mMapVector;
+   static std::map< void*, MbChessMap2DKey > mPointerKeyMap;
+
+   //////////////////////////////////////////////////////////////////////////
+   //protected Konstrukoren
+   MbChessMemPool2D() //protected, um max einmal vererbt werden zu koennen!!!
+   {              //zudem kann man so keine elmente von TreeBasedMemPool erstellen
+
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //Destruktor
+    ~MbChessMemPool2D()
+   {
+   }
+
+public:
+
+   //////////////////////////////////////////////////////////////////////////
+   //static public Methoden
+   static void* getReference(std::size_t level, std::size_t ix1, std::size_t ix2)
+   {
+      if(!MbChessMem2DBlock< TData,cachSize >::mBlockWidth)
+      {
+         std::stringstream ss;
+         ss<<"TreeBasedMemPool() - InitialisationError\n";
+         ss<<"\t size of StorageData ("<<typeid(TData).name()<<", "<<sizeof(TData)<<" byte)\n";
+         ss<<"\t exceeds user-specifyed cache-zize ("<<mCacheSize<<" byte)\n";
+         ss<<"\t cache-size has to be larger than data-size";
+         UB_THROW( UbException(ss.str()) );
+      }
+
+      if( mMapVector.size()<=level ) mMapVector.resize(level+1);
+
+      std::size_t chessX1 = ix1/(MbChessMem2DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t chessX2 = ix2/(MbChessMem2DBlock<TData,cachSize>::mBlockWidth);
+
+      MbChessMap2DKey mapKey(level,chessX1,chessX2);
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos = mMapVector[level].find(mapKey);
+
+      MbChessMem2DBlock<TData,cachSize>* memBlock = NULL;
+
+      if(pos==mMapVector[level].end())
+      {
+         memBlock = new MbChessMem2DBlock<TData,cachSize>;
+         (mMapVector[level])[mapKey] = memBlock;
+      }
+      else memBlock = pos->second;
+
+      std::size_t internalChessX1 = ix1%(MbChessMem2DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t internalChessX2 = ix2%(MbChessMem2DBlock<TData,cachSize>::mBlockWidth);
+
+      void* p = memBlock->getReference(internalChessX1,internalChessX2);
+
+      mPointerKeyMap[p]=mapKey;
+
+      return p;
+   }
+   /*==========================================================*/
+   static void freeReference(void *p)
+   {
+      typename std::map<void*,MbChessMap2DKey>::iterator posPointerKeyMap = mPointerKeyMap.find(p);
+
+      if(posPointerKeyMap==mPointerKeyMap.end()) UB_THROW( UbException(UB_EXARGS,"pointer not in map") );
+
+      MbChessMap2DKey mapKey = posPointerKeyMap->second;
+      mPointerKeyMap.erase(posPointerKeyMap);
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator posMemBlockMap;
+      posMemBlockMap = mMapVector[mapKey.getVectorPos()].find(mapKey);
+
+      if(posMemBlockMap == mMapVector[mapKey.getVectorPos()].end())
+         UB_THROW( UbException(UB_EXARGS,"mapKey not in ChessMem2DBlockMap") );
+
+      std::size_t leftElements = posMemBlockMap->second->freeReference(p);
+      if(!leftElements)
+      {
+         MbChessMem2DBlock<TData,cachSize>* tmp = posMemBlockMap->second;
+         mMapVector[mapKey.getVectorPos()].erase(posMemBlockMap);
+         delete tmp;
+      }
+   }
+   /*==========================================================*/
+   static void fillVectorWithPointerToTDataElements(std::size_t level,std::vector<TData*>& tdataVector)
+   {
+      tdataVector.clear();
+
+      if(level>=mMapVector.size()) return;
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+      for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+      {
+         pos->second->addPointerToTElementsToVector(tdataVector);
+      }
+   }
+   /*==========================================================*/
+   static void fillVectorWithPointerToTDataElements(std::vector<TData*>& tdataVector)
+   {
+      tdataVector.clear();
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t vecIndex=0; vecIndex<mMapVector.size(); vecIndex++ )
+      {
+         for(pos=mMapVector[vecIndex].begin();pos!=mMapVector[vecIndex].end();++pos)
+         {
+            pos->second->addPointerToTElementsToVector(tdataVector);
+         }
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   static void fillVectorWithPointerToTDataElements(std::size_t level,std::vector<TData*>& tdataVector, Pred pred)
+   {
+      tdataVector.clear();
+
+      if(level>=mMapVector.size()) return;
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+      for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+      {
+         pos->second->addPointerToTElementsToVector(tdataVector,pred);
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   static void fillVectorWithPointerToTDataElements(std::vector<TData*>& tdataVector, Pred pred)
+   {
+      tdataVector.clear();
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t vecIndex=0; vecIndex<mMapVector.size(); vecIndex++ )
+      {
+         for(pos=mMapVector[vecIndex].begin();pos!=mMapVector[vecIndex].end();++pos)
+         {
+            pos->second->addPointerToTElementsToVector(tdataVector,pred);
+         }
+      }
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfChessMemoryBlocks()
+   {
+      std::size_t nofElements = 0;
+      for(std::size_t i=0; i<mMapVector.size(); i++)
+      {
+         nofElements+=mMapVector[i].size();
+      }
+      return nofElements;
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfChessMemoryBlocks(std::size_t level)
+   {
+      if(level<mMapVector.size() )return mMapVector[level].size();
+      return 0;
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfStoredDataElements()
+   {
+      return mPointerKeyMap.size();
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfStoredDataElements(std::size_t level)
+   {
+      if(level<mMapVector.size() )
+      {
+         std::size_t nofElements = 0;
+         typename std::map< MbChessMap2DKey , MbChessMem2DBlock< TData,cachSize >* >::iterator pos;
+
+         for(pos=mMapVector[level].begin(); pos!=mMapVector[level].end(); ++pos)
+         {
+            nofElements += pos->second->getNofUsedElements();
+         }
+         return nofElements;
+      }
+      return 0;
+
+   }
+   /*==========================================================*/
+   static std::string toString()
+   {
+      long double capaticityPerBlock   = (std::size_t)pow((double)MbChessMem2DBlock<TData,cachSize>::mBlockWidth,2.0);
+      std::size_t storedElements       = MbChessMemPool2D<TData,cachSize>::getNumberOfStoredDataElements();
+      std::size_t initialisedMemBlocks = MbChessMemPool2D<TData,cachSize>::getNumberOfChessMemoryBlocks();
+
+      std::stringstream ss;
+      ss<<std::endl;
+      ss<<"****************** MbChessMemPool2D-Info (BEGIN) ******************"<<std::endl;
+      ss<<"type of Storage-Data.................. : "<<typeid(TData).name()<<std::endl;
+      ss<<"size of Storage-Data........... [bytes]: "<<sizeof(TData)<<std::endl;
+      ss<<"specified cache-size........... [bytes]: "<<mCacheSize<<std::endl;
+      ss<<"#elements per MbChessMem2DBlock [bytes]: "<<capaticityPerBlock<<std::endl;
+      ss<<"mem per MbChessMem2DBlock...... [bytes]: "<<capaticityPerBlock*sizeof(TData)<<std::endl;
+      ss<<"used cache-size[%]............. [bytes]: "<<capaticityPerBlock*sizeof(TData)/(double)mCacheSize*100<<std::endl;
+      ss<<"\n";
+      ss<<"#stored Elements  = "<<storedElements<<std::endl;
+      ss<<"#ChessMem2DBlocks = "<<initialisedMemBlocks<<std::endl;
+      ss<<std::endl;
+      ss<<"level | #ChessMem2DBlocks | #stored Elements | used capaticity [%] \n";
+      ss<<"----------------------------------------------------------------\n";
+      for(std::size_t level=0;level<mMapVector.size();level++)
+      {
+         std::size_t nofStoredElements = MbChessMemPool2D<TData,cachSize>::getNumberOfStoredDataElements(level);
+         std::size_t nofChessMem2DBlocks = MbChessMemPool2D<TData,cachSize>::getNumberOfChessMemoryBlocks(level);
+
+         ss<<std::left<<" "<<std::setw(5)<<level<<"| "
+            <<std::setw(16)<<nofChessMem2DBlocks<<"| "
+            <<std::setw(17)<<nofStoredElements<<"| ";
+         if(nofStoredElements)
+            ss<<setw(15)<<nofStoredElements/(double)(capaticityPerBlock*nofChessMem2DBlocks)*100<<std::endl;
+         else ss<<"-"<<std::endl;
+      }
+      ss<<std::endl;
+      ss<<"called memory..... [bytes]: "<<storedElements*sizeof(TData)<<std::endl;
+      ss<<"initialised memory [bytes]: "<<initialisedMemBlocks*capaticityPerBlock*sizeof(TData)<<std::endl;
+      double denominator = (double)(initialisedMemBlocks*capaticityPerBlock*sizeof(TData));
+      if(fabs(denominator)>1.E-13) ss<<"used.............. [%]    : "<<100.*storedElements*sizeof(TData)/denominator<<std::endl;
+      else                         ss<<"used.............. [%]    : 0.0"<<std::endl;
+      ss<<"****************** MbChessMemPool2D-Info (END)  *******************"<<std::endl;
+      return ss.str();
+   }
+   /*==========================================================*/
+   static void writeStatisticFiles(const std::string& filename)
+   {
+      //liefert Statistik ueber aufuellung der einzelnen bloecke (gesamt und pro level)
+      //x-Achse: 0... max moegliche Anzahl von moeglichen Elementen pro MemBlock
+      //y-Achse: Anzahl an Bloecken, die die Anzahl an Elementen beinhalten
+      std::ofstream spreadingFile(((std::string)(filename+"_spreading.txt")).c_str());
+      if(!spreadingFile) UB_THROW( UbException(UB_EXARGS,"couldn't open file") );
+
+      std::size_t initialisedMemBlocks       =   MbChessMemPool2D<TData,cachSize>::getNumberOfChessMemoryBlocks();
+      std::size_t maxNofDataElementsPerBlock =   MbChessMem2DBlock<TData,cachSize>::mBlockWidth
+                                               * MbChessMem2DBlock<TData,cachSize>::mBlockWidth
+                                               * MbChessMem2DBlock<TData,cachSize>::mBlockWidth;
+      std::vector<std::size_t> spreading;
+      spreading.resize(maxNofDataElementsPerBlock+1,0);
+      std::vector< std::vector<std::size_t> > spreadingPerLevel;
+      spreadingPerLevel.resize(mMapVector.size());
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t level=0; level<mMapVector.size(); level++ )
+      {
+         spreadingPerLevel[level].resize(maxNofDataElementsPerBlock+1,0);
+         for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+         {
+            std::size_t number = pos->second->getNofUsedElements();
+            spreading[number]++;
+            spreadingPerLevel[level][number]++;
+         }
+      }
+      spreadingFile<<"#BlockUsage nofBlocks(all Level) ";
+      for(std::size_t level=0; level<mMapVector.size(); level++ )
+         spreadingFile<<"nofBlockLevel"<<level<<" ";
+      spreadingFile<<std::endl;
+
+      for(std::size_t i=0; i<spreading.size(); i++)
+      {
+         spreadingFile<<i<<" "<<spreading[i];
+         for(std::size_t level=0; level<mMapVector.size(); level++ )
+            spreadingFile<<" "<<spreadingPerLevel[level][i];
+         spreadingFile<<std::endl;
+      }
+      spreadingFile.flush();
+      spreadingFile.close();
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //ueberladene operatoren
+   void* operator new(size_t size, std::size_t level, std::size_t ix1, std::size_t ix2)
+   {
+      if(level<0) UB_THROW( UbException(UB_EXARGS,"level ist negativ!") );
+      void *p = getReference(level,ix1,ix2);
+      return p;
+   }
+   /*==========================================================*/
+   void operator delete(void* p, std::size_t level, std::size_t ix1, std::size_t ix2)
+   {
+      //ACHTUNG: wenn man hier ne Exception schmeisst, dann gibts einen BoeSEN compilerFehler!!!
+      //UB_THROW( UbException(UB_EXARGS,"Scheisse noch nicht gerafft, wie das geht!") );
+      std::cerr<<"MbChessMemPool2D::delete(void* p, std::size_t level, std::size_t ix1, std::size_t ix2) - Scheisse noch nicht gerafft, wie das geht!\n";
+   }
+
+   /*==========================================================*/
+   void operator delete(void* p)
+   {
+      freeReference(p);
+   }
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private statische Methoden
+};
+
+//statische Variablen initialisieren
+template <class TData, std::size_t cachSize>
+std::vector< std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* > > MbChessMemPool2D<TData,cachSize>::mMapVector;
+
+template <class TData, std::size_t cachSize>
+std::map<void*,MbChessMap2DKey >  MbChessMemPool2D< TData, cachSize>::mPointerKeyMap;
+
+template <class TData, std::size_t cachSize>
+const std::size_t  MbChessMemPool2D<TData,cachSize>::mCacheSize=cachSize;
+
+template <class TData,std::size_t cachSize>
+const std::size_t  MbChessMem2DBlock<TData,cachSize>::mBlockWidth=static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1./3.));
+
+#endif
diff --git a/source/ThirdParty/Library/basics/memory/MbChessMemPool3D.h b/source/ThirdParty/Library/basics/memory/MbChessMemPool3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..99fef93f6c79612e298e08dc3f504df7b0cd695d
--- /dev/null
+++ b/source/ThirdParty/Library/basics/memory/MbChessMemPool3D.h
@@ -0,0 +1,537 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBCHESSMEMPOOL3D_H
+#define MBCHESSMEMPOOL3D_H
+
+#include <map>
+#include <vector>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <cmath>
+
+#include <basics/utilities/UbException.h>
+
+template <class TData, std::size_t cachSize>
+class MbChessMemPool3D;
+
+//////////////////////////////////////////////////////////////////////////
+//class MbChessMap3DKey
+//key zum Auffinden der ChessMem3DBlocks
+class MbChessMap3DKey
+{
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //Konstruktoren
+   MbChessMap3DKey(): mVectorPos(0),mFirstCriteria(0),mSecondCriteria(0),mThirdCriteria(0)
+   {
+   }
+   /*==========================================================*/
+   MbChessMap3DKey(std::size_t vectorPos,std::size_t firstCriteria,std::size_t secondCriteria,std::size_t thirdCriteria)
+      : mVectorPos(vectorPos), mFirstCriteria(firstCriteria), mSecondCriteria(secondCriteria), mThirdCriteria(thirdCriteria)
+   {
+   }
+   /*==========================================================*/
+   MbChessMap3DKey& operator=(const MbChessMap3DKey& srcKey)
+   {
+      if(this == &srcKey ) return *this;
+
+      mVectorPos      = srcKey.mVectorPos;
+      mFirstCriteria  = srcKey.mFirstCriteria;
+      mSecondCriteria = srcKey.mSecondCriteria;
+      mThirdCriteria  = srcKey.mThirdCriteria;
+
+      return *this;
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //global ueberladene Operatoren
+   friend inline bool operator<(const MbChessMap3DKey& lhsKey,const MbChessMap3DKey& rhsKey)
+   {
+      if(lhsKey.mFirstCriteria  < rhsKey.mFirstCriteria ) return true;
+      if(lhsKey.mFirstCriteria  > rhsKey.mFirstCriteria ) return false;
+      if(lhsKey.mSecondCriteria < rhsKey.mSecondCriteria) return true;
+      if(lhsKey.mSecondCriteria > rhsKey.mSecondCriteria) return false;
+      if(lhsKey.mThirdCriteria  < rhsKey.mThirdCriteria ) return true;
+
+      return false;
+   }
+   /*==========================================================*/
+   friend inline bool operator==(const MbChessMap3DKey& lhsKey,const MbChessMap3DKey& rhsKey)
+   {
+      if(lhsKey.mVectorPos      != rhsKey.mVectorPos      ) return false;
+      if(lhsKey.mFirstCriteria  != rhsKey.mFirstCriteria  ) return false;
+      if(lhsKey.mSecondCriteria != rhsKey.mSecondCriteria ) return false;
+      if(lhsKey.mThirdCriteria  != rhsKey.mThirdCriteria  ) return false;
+
+      return true;
+   }
+   //ueberladene Operatoren
+   friend inline bool operator!=(const MbChessMap3DKey& lhsKey,const MbChessMap3DKey& rhsKey)
+   {
+      return !(lhsKey==rhsKey);
+   }
+   //ueberladene Operatoren
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const MbChessMap3DKey& key)
+   {
+      os<<"VectorPos,first-,second-,third Criteria) (";
+      os<<key.mVectorPos<<","<<key.mFirstCriteria<<","<<key.mSecondCriteria<<","<<key.mThirdCriteria<<")";
+      return os;
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //public Methoden
+   std::size_t getVectorPos() {return mVectorPos;}
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private Member
+   std::size_t mVectorPos;
+   std::size_t mFirstCriteria;
+   std::size_t mSecondCriteria;
+   std::size_t mThirdCriteria;
+};
+
+
+
+template<class T,std::size_t cachSize>
+class MbChessMem3DBlock
+{
+   friend class MbChessMemPool3D<T,cachSize>;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //Konstruktoren
+   MbChessMem3DBlock()
+   {
+      mUsedElements = 0;
+      std::size_t arrayLength = mBlockWidth*mBlockWidth*mBlockWidth;
+      //mDataElements = new T[arrayLength];
+      mDataElements = operator new(arrayLength*sizeof(T));
+      if(!mDataElements) UB_THROW( UbException(UB_EXARGS,"out of memeory!") );
+      mFlagVector   = new bool[arrayLength];
+      if(!mFlagVector) UB_THROW( UbException(UB_EXARGS,"out of memeory!") );
+      for(std::size_t i=0;i<arrayLength;i++) mFlagVector[i] = false;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //Destruktor
+   ~MbChessMem3DBlock()
+   {
+      //if(mDataElements) delete[] mDataElements;
+      if(mDataElements) operator delete(mDataElements);
+      if(mFlagVector)   delete[] mFlagVector;
+   }
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private Methoden
+   void* getReference(std::size_t chessX1, std::size_t chessX2, std::size_t chessX3)
+   {
+      //std::size_t arrayIndex = (chessX1*mBlockWidth+chessX2)*mBlockWidth + chessX3;
+      std::size_t arrayIndex = (chessX3*mBlockWidth+chessX2)*mBlockWidth + chessX1;
+      #ifdef _DEBUG
+         if(arrayIndex>=mBlockWidth*mBlockWidth*mBlockWidth) UB_THROW( UbException(UB_EXARGS,"index out of range") );
+      #endif
+
+      if(mFlagVector[arrayIndex]==true) UB_THROW( UbException(UB_EXARGS,"memory already allocated!") );
+
+      mUsedElements++;
+      mFlagVector[arrayIndex]=true;
+
+      return (void*)((T*)(mDataElements)+arrayIndex);//&(mDataElements[arrayIndex]);
+   }
+   /*==========================================================*/
+   std::size_t freeReference(void* p)
+   {
+      //std::size_t arrayIndex = static_cast<std::size_t>(static_cast<T*>(p) - mDataElements); //mDataElements = &mDataElements[0]
+      std::size_t arrayIndex = static_cast<std::size_t>(static_cast<T*>(p) - static_cast<T*>(mDataElements));
+
+      #ifdef _DEBUG
+        if(arrayIndex>=mBlockWidth*mBlockWidth*mBlockWidth) UB_THROW( UbException(UB_EXARGS,"index out of range") );
+      #endif
+
+      if(mFlagVector[arrayIndex]==false) UB_THROW( UbException(UB_EXARGS,"memory not allocated!") );
+
+      mFlagVector[arrayIndex]=false;
+
+      return --mUsedElements;
+   }
+   /*==========================================================*/
+   std::size_t  getNofUsedElements()   { return mUsedElements; }
+   /*==========================================================*/
+   void addPointerToTElementsToVector(std::vector<T*>& tdataVector)
+   {
+      std::size_t arrayLength = mBlockWidth*mBlockWidth*mBlockWidth;
+      for(std::size_t arrayIndex=0; arrayIndex<arrayLength; arrayIndex++)
+      {
+         //if(mFlagVector[arrayIndex]) tdataVector.push_back(&mDataElements[arrayIndex]);
+         if(mFlagVector[arrayIndex]) tdataVector.push_back(static_cast<T*>(mDataElements)+arrayIndex);
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   void addPointerToTElementsToVector(std::vector<T*>& tdataVector,Pred& pred )
+   {
+      std::size_t arrayLength = mBlockWidth*mBlockWidth*mBlockWidth;
+      T* tmp;
+      for(std::size_t arrayIndex=0;arrayIndex<arrayLength;arrayIndex++)
+      {
+         if(mFlagVector[arrayIndex])
+         {
+            //tmp = &mDataElements[arrayIndex];
+            tmp = static_cast<T*>(mDataElements)+arrayIndex;
+            if( pred(*tmp) ) tdataVector.push_back(tmp);
+         }
+      }
+   }
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //static Member
+   static const std::size_t  mBlockWidth;
+
+   //////////////////////////////////////////////////////////////////////////
+   //private Member
+   std::size_t mUsedElements;
+   //T*    mDataElements;
+   void* mDataElements;
+   bool* mFlagVector;
+
+};
+
+//////////////////////////////////////////////////////////////////////////
+//class MbChessMemPool3D
+//zum Verwalten von TData Elementen in einer Schabrett-artigen Struktur
+//die ChessMemBloecke haben hier eine Groesse von ~cachSize
+template <class TData, std::size_t cachSize>
+class MbChessMemPool3D
+{
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //protected static const Member
+   const static std::size_t mCacheSize;
+
+   //////////////////////////////////////////////////////////////////////////
+   //protected Member
+   static std::vector< std::map< MbChessMap3DKey , MbChessMem3DBlock< TData,cachSize >* > > mMapVector;
+   static std::map< void*, MbChessMap3DKey > mPointerKeyMap;
+
+   //////////////////////////////////////////////////////////////////////////
+   //protected Konstrukoren
+   MbChessMemPool3D() //private, da NUR static erlaubt!!!
+   {
+
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //Destruktor
+   ~MbChessMemPool3D()
+   {
+   }
+
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //static public Methoden
+   static void* getReference(std::size_t level, std::size_t ix1, std::size_t ix2, std::size_t ix3)
+   {
+      if(!MbChessMem3DBlock< TData,cachSize >::mBlockWidth)
+      {
+         std::stringstream ss;
+         ss<<"TreeBasedMemPool() - InitialisationError\n";
+         ss<<"\t size of StorageData ("<<typeid(TData).name()<<", "<<sizeof(TData)<<" byte)\n";
+         ss<<"\t exceeds user-specifyed cache-zize ("<<mCacheSize<<" byte)\n";
+         ss<<"\t cache-size has to be larger than data-size";
+         UB_THROW( UbException(UB_EXARGS,ss.str()) );
+      }
+
+      if( mMapVector.size()<=level ) mMapVector.resize(level+1);
+
+      std::size_t chessX1 = ix1/(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t chessX2 = ix2/(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t chessX3 = ix3/(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+
+      MbChessMap3DKey mapKey(level,chessX1,chessX2,chessX3);
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos = mMapVector[level].find(mapKey);
+
+      MbChessMem3DBlock<TData,cachSize>* memBlock = NULL;
+
+      if(pos==mMapVector[level].end())
+      {
+         memBlock = new MbChessMem3DBlock<TData,cachSize>;
+         (mMapVector[level])[mapKey] = memBlock;
+      }
+      else memBlock = pos->second;
+
+      std::size_t internalChessX1 = ix1%(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t internalChessX2 = ix2%(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t internalChessX3 = ix3%(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+
+      void* p = memBlock->getReference(internalChessX1,internalChessX2,internalChessX3);
+
+      mPointerKeyMap[p]=mapKey;
+
+      return p;
+   }
+   static void freeReference(void *p)
+   {
+      typename std::map<void*,MbChessMap3DKey>::iterator posPointerKeyMap = mPointerKeyMap.find(p);
+
+      if(posPointerKeyMap==mPointerKeyMap.end()) UB_THROW( UbException(UB_EXARGS,"pointer not in map") );
+
+      MbChessMap3DKey mapKey = posPointerKeyMap->second;
+      mPointerKeyMap.erase(posPointerKeyMap);
+
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator posMemBlockMap;
+      posMemBlockMap = mMapVector[mapKey.getVectorPos()].find(mapKey);
+
+
+      if(posMemBlockMap == mMapVector[mapKey.getVectorPos()].end())
+         UB_THROW( UbException(UB_EXARGS,"mapKey not in ChessMem3DBlockMap") );
+
+      std::size_t leftElements = posMemBlockMap->second->freeReference(p);
+      if(!leftElements)
+      {
+         MbChessMem3DBlock<TData,cachSize>* tmp = posMemBlockMap->second;
+         mMapVector[mapKey.getVectorPos()].erase(posMemBlockMap);
+         try{ delete tmp; }
+         catch(...){UB_THROW( UbException(UB_EXARGS,"could not delete MbChessMem3DBlock") );}
+      }
+   }
+   /*==========================================================*/
+   static void fillVectorWithPointerToTDataElements(std::size_t level,std::vector<TData*>& tdataVector)
+   {
+      tdataVector.clear();
+
+      if(level>=mMapVector.size()) return;
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+      for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+      {
+         pos->second->addPointerToTElementsToVector(tdataVector);
+      }
+   }
+   /*==========================================================*/
+   static void fillVectorWithPointerToTDataElements(std::vector<TData*>& tdataVector)
+   {
+      tdataVector.clear();
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t vecIndex=0; vecIndex<mMapVector.size(); vecIndex++ )
+      {
+         for(pos=mMapVector[vecIndex].begin();pos!=mMapVector[vecIndex].end();++pos)
+         {
+            pos->second->addPointerToTElementsToVector(tdataVector);
+         }
+      }
+   }
+   /*==========================================================*/
+   template<class Pred>
+   static void fillVectorWithPointerToTDataElements(std::size_t level,std::vector<TData*>& tdataVector, Pred pred)
+   {
+      tdataVector.clear();
+
+      if(level>=mMapVector.size()) return;
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+      for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+      {
+         pos->second->addPointerToTElementsToVector(tdataVector,pred);
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   static void fillVectorWithPointerToTDataElements(std::vector<TData*>& tdataVector, Pred pred)
+   {
+      tdataVector.clear();
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t vecIndex=0; vecIndex<mMapVector.size(); vecIndex++ )
+      {
+         for(pos=mMapVector[vecIndex].begin();pos!=mMapVector[vecIndex].end();++pos)
+         {
+            pos->second->addPointerToTElementsToVector(tdataVector,pred);
+         }
+      }
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfChessMemoryBlocks()
+   {
+      std::size_t nofElements = 0;
+      for(std::size_t i=0;i<mMapVector.size();i++)
+      {
+         nofElements+=mMapVector[i].size();
+      }
+      return nofElements;
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfChessMemoryBlocks(std::size_t level)
+   {
+      if(level<mMapVector.size() ) return mMapVector[level].size();
+      return 0;
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfStoredDataElements()
+   {
+      return mPointerKeyMap.size();
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfStoredDataElements(std::size_t level)
+   {
+      if(level<mMapVector.size() )
+      {
+         std::size_t nofElements = 0;
+         typename std::map< MbChessMap3DKey , MbChessMem3DBlock< TData,cachSize >* >::iterator pos;
+
+         for(pos=mMapVector[level].begin(); pos!=mMapVector[level].end(); ++pos)
+         {
+            nofElements+= pos->second->getNofUsedElements();
+         }
+         return nofElements;
+      }
+      return 0;
+   }
+   /*==========================================================*/
+   static std::string toString()
+   {
+      long double capaticityPerBlock   = pow((double)MbChessMem3DBlock<TData,cachSize>::mBlockWidth,3.0);
+      std::size_t storedElements       = MbChessMemPool3D<TData,cachSize>::getNumberOfStoredDataElements();
+      std::size_t initialisedMemBlocks = MbChessMemPool3D<TData,cachSize>::getNumberOfChessMemoryBlocks();
+
+      std::stringstream ss;
+      ss<<std::endl;
+      ss<<"****************** MbChessMemPool3D-Info (BEGIN) ******************"<<std::endl;
+      ss<<"type of Storage-Data.................. : "<<typeid(TData).name()<<std::endl;
+      ss<<"size of Storage-Data........... [bytes]: "<<sizeof(TData)<<std::endl;
+      ss<<"specified cache-size........... [bytes]: "<<mCacheSize<<std::endl;
+      ss<<"#elements per MbChessMem3DBlock [bytes]: "<<capaticityPerBlock<<std::endl;
+      ss<<"mem per MbChessMem3DBlock...... [bytes]: "<<capaticityPerBlock*sizeof(TData)<<std::endl;
+      ss<<"used cache-size[%]............. [bytes]: "<<capaticityPerBlock*sizeof(TData)/(double)mCacheSize*100<<std::endl;
+      ss<<"\n";
+      ss<<"#stored Elements   = "<<storedElements<<std::endl;
+      ss<<"#ChessMem3DBlocks  = "<<initialisedMemBlocks<<std::endl;
+      ss<<std::endl;
+      ss<<"level | #ChessMem3DBlocks | #stored Elements | used capaticity [%] \n";
+      ss<<"----------------------------------------------------------------\n";
+      for(std::size_t level=0;level<mMapVector.size();level++)
+      {
+         std::size_t nofStoredElements   = MbChessMemPool3D<TData,cachSize>::getNumberOfStoredDataElements(level);
+         std::size_t nofChessMem3DBlocks = MbChessMemPool3D<TData,cachSize>::getNumberOfChessMemoryBlocks(level);
+
+         ss<<std::left<<" "<<std::setw(5)<<level<<"| "
+            <<std::setw(16)<<nofChessMem3DBlocks<<"| "
+            <<std::setw(17)<<nofStoredElements<<"| ";
+         if(nofStoredElements)
+            ss<<std::setw(15)<<nofStoredElements/(double)(capaticityPerBlock*nofChessMem3DBlocks)*100<<std::endl;
+         else ss<<"-"<<std::endl;
+      }
+      ss<<std::endl;
+      ss<<"called memory..... [bytes]: "<<storedElements*sizeof(TData)<<std::endl;
+      ss<<"initialised memory [bytes]: "<<initialisedMemBlocks*capaticityPerBlock*sizeof(TData)<<std::endl;
+      double denominator = (double)(initialisedMemBlocks*capaticityPerBlock*sizeof(TData));
+      if(fabs(denominator)>1.E-13) ss<<"used.............. [%]    : "<<100.*storedElements*sizeof(TData)/denominator<<std::endl;
+      else                         ss<<"used.............. [%]    : 0.0"<<std::endl;
+      ss<<"****************** MbChessMemPool3D-Info (END)  *******************"<<std::endl;
+      return ss.str();
+   }
+   /*==========================================================*/
+   static void writeStatisticFiles(const std::string& filename)
+   {
+      //liefert Statistik ueber aufuellung der einzelnen bloecke (gesamt und pro level)
+      //x-Achse: 0... max moegliche Anzahl von moeglichen Elementen pro MemBlock
+      //y-Achse: Anzahl an Bloecken, die die Anzahl an Elementen beinhalten
+      std::ofstream spreadingFile(((std::string)(filename+"_spreading.txt")).c_str());
+      if(!spreadingFile) UB_THROW( UbException(UB_EXARGS,"couldn't open file") );
+
+      //std::size_t initialisedMemBlocks       =  MbChessMemPool3D<TData,cachSize>::getNumberOfChessMemoryBlocks();
+      std::size_t maxNofDataElementsPerBlock =  MbChessMem3DBlock<TData,cachSize>::mBlockWidth
+                                               *MbChessMem3DBlock<TData,cachSize>::mBlockWidth
+                                               *MbChessMem3DBlock<TData,cachSize>::mBlockWidth;
+      std::vector<std::size_t> spreading;
+      spreading.resize(maxNofDataElementsPerBlock+1,0);
+      std::vector< std::vector<std::size_t> > spreadingPerLevel;
+      spreadingPerLevel.resize(mMapVector.size());
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t level=0; level<mMapVector.size(); level++ )
+      {
+         spreadingPerLevel[level].resize(maxNofDataElementsPerBlock+1,0);
+         for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+         {
+            std::size_t number = pos->second->getNofUsedElements();
+            spreading[number]++;
+            spreadingPerLevel[level][number]++;
+         }
+      }
+      spreadingFile<<"#BlockUsage nofBlocks(all Level) ";
+      for(std::size_t level=0; level<mMapVector.size(); level++ )
+         spreadingFile<<"nofBlockLevel"<<level<<" ";
+      spreadingFile<<std::endl;
+
+      for(std::size_t i=0;i<spreading.size();i++)
+      {
+         spreadingFile<<i<<" "<<spreading[i];
+         for(std::size_t level=0; level<mMapVector.size(); level++ )
+            spreadingFile<<" "<<spreadingPerLevel[level][i];
+         spreadingFile<<std::endl;
+      }
+      spreadingFile.flush();
+      spreadingFile.close();
+   }
+
+   ////////////////////////////////////////////////////////////////////////////
+   ////ueberladene operatoren
+   //void* operator new(size_t size, std::size_t level, std::size_t ix1, std::size_t ix2, std::size_t ix3)
+   //{
+   //   if(level<0) UB_THROW( UbException(UB_EXARGS,"level ist negativ!") );
+   //   void *p = getReference(level,ix1,ix2,ix3);
+   //   return p;
+   //}
+   ///*==========================================================*/
+   //void operator delete(void* p, std::size_t level, std::size_t ix1, std::size_t ix2, std::size_t ix3)
+   //{
+   //   //ACHTUNG: wenn man hier ne Exception schmeisst, dann gibts einen BoeSEN compilerFehler!!!
+   //   //UB_THROW( UbException(__FILE__, __LINE__, "MbChessMemPool3D::delete - Scheisse noch nicht gerafft, wie das geht!") );
+   //   cout<<"MbChessMemPool3D::delete(void* p, std::size_t level, std::size_t ix1, std::size_t ix2, std::size_t ix3) - Scheisse noch nicht gerafft, wie das geht!\n";
+   //}
+
+   ///*==========================================================*/
+   //void operator delete(void* p)
+   //{
+   //   freeReference(p);
+   //}
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private statische Methoden
+};
+
+
+//statische Variablen initialisieren
+template <class TData, std::size_t cachSize>
+std::vector< std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* > > MbChessMemPool3D<TData,cachSize>::mMapVector;
+
+template <class TData, std::size_t cachSize>
+std::map<void*,MbChessMap3DKey >  MbChessMemPool3D< TData, cachSize>::mPointerKeyMap;
+
+template <class TData, std::size_t cachSize>
+const std::size_t  MbChessMemPool3D<TData,cachSize>::mCacheSize=cachSize;
+
+//template <class TData, std::size_t cachSize>
+//const std::size_t  MbChessMemPool3D<TData,cachSize>::mNofElementsWidthMemBlock=static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1./3.));
+
+//template <class TData, std::size_t cachSize>
+//const std::size_t  MbChessMemPool3D<TData,cachSize>::mNofElementsInMemBlock=static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1./3.))),3.0));
+
+template <class TData,std::size_t cachSize>
+const std::size_t  MbChessMem3DBlock<TData,cachSize>::mBlockWidth=static_cast<std::size_t>(std::pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1./3.));
+
+//template <class TData,std::size_t cachSize>
+//const std::size_t  MbChessMem3DBlock<TData,cachSize>::mMaxElements=static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1.0/3.0))),3.0))),3.0));
+
+#endif
diff --git a/source/ThirdParty/Library/basics/memory/MbMemPool.h b/source/ThirdParty/Library/basics/memory/MbMemPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a835596a9c717e4e31bf3f6570b7615759a754b
--- /dev/null
+++ b/source/ThirdParty/Library/basics/memory/MbMemPool.h
@@ -0,0 +1,87 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBMEMPOOL_H
+#define MBMEMPOOL_H
+
+#include <queue>
+#include <list>
+
+
+template <typename TData, int asize>
+class MbMemPool
+{
+
+protected:
+   MbMemPool(){}
+   // Alle 3 Attribute sind Singleton-Objekte !
+   // Allokiere Blocke der Groesse m_asize
+   static int m_asize;       
+   // Halte alle freien Pointer (jedes einzelne Element)  in eine FIFO Liste
+   static std::queue<void*> m_queue;
+   // Pointer auf Bloecke zum Loeschen !
+   static std::list<TData*> m_list;
+
+public:
+
+   
+   ~MbMemPool(){}
+
+   // Daten-Bloecke Loeschen, damit wird der gesamte Speicher freigegeben,
+   // erst aufrufen, wenn die objekte nicht mehr gebraucht werden!
+   static void	deallocatePool();
+
+   void* operator new(std::size_t size)
+   {
+      void*  pNew;
+      TData* feld;	
+      int i;
+
+      //i=m_queue.size();
+      //pNew = m_queue.front();
+      if(m_queue.size()==0) 
+      {
+         //Wenn kein freier Speicher mehr vorhanden, Block anlegen
+         feld = new TData[m_asize];
+         m_list.push_back(feld);
+         for(i=0 ; i<m_asize ; i++)
+         {
+            pNew = (void*) &(feld[i]);
+            m_queue.push( pNew );
+         }
+      }
+      pNew = m_queue.front();
+      m_queue.pop();
+      return pNew;
+
+   }
+
+   void  operator delete(void* p)
+   {
+      m_queue.push(p);
+   }
+};
+
+
+template <typename TData, int asize> 
+std::queue<void*>  MbMemPool<TData,asize>::m_queue;
+
+template <typename TData, int asize> 
+std::list<TData*>  MbMemPool<TData,asize>::m_list;
+
+template <typename TData, int asize> 
+int  MbMemPool<TData,asize>::m_asize=asize;
+
+template <typename TData, int asize> 
+void MbMemPool<TData,asize>::deallocatePool()
+{	
+   for(typename std::list<TData*>::iterator pos=m_list.begin() ; pos!=m_list.end(); ++pos)
+   {
+      delete[] pos;
+   }
+}
+
+#endif //MBMEMPOOL_H
diff --git a/source/ThirdParty/Library/basics/memory/MbSharedPointerDefines.h b/source/ThirdParty/Library/basics/memory/MbSharedPointerDefines.h
new file mode 100644
index 0000000000000000000000000000000000000000..25c9311e7e5ec10585c96c3cd70792cb7b330ef3
--- /dev/null
+++ b/source/ThirdParty/Library/basics/memory/MbSharedPointerDefines.h
@@ -0,0 +1,39 @@
+
+#ifndef MBSHAREDPOINTERDEFINES_H
+#define MBSHAREDPOINTERDEFINES_H
+
+
+// Boost includes
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#define VFSharedFromThis boost::enable_shared_from_this
+#define VFSharedPtr boost::shared_ptr
+#define VFWeakPtr   boost::weak_ptr
+#define VFDynamicPtrCast boost::dynamic_pointer_cast
+
+template<typename T>
+class VFPtrDeleter
+{
+public:
+   void operator()(T* p) { delete p; }
+};
+
+
+
+// std includes
+#include <vector>
+
+//#ifdef WIN32
+//#  include <memory>
+//#else
+//#  include<tr1/memory>
+//#endif
+
+//#  define DCSharedFromThis std::tr1::enable_shared_from_this
+//#  define DCSharedPtr std::tr1::shared_ptr
+//#  define DCWeakPtr   std::tr1::weak_ptr
+//#  define DCDynamicPtrCast std::tr1::dynamic_pointer_cast
+
+#endif
diff --git a/source/ThirdParty/Library/basics/memory/MbSmartPtr.h b/source/ThirdParty/Library/basics/memory/MbSmartPtr.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f2bf7631745b9940817d41014205f0a5b6e1077
--- /dev/null
+++ b/source/ThirdParty/Library/basics/memory/MbSmartPtr.h
@@ -0,0 +1,147 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBSMARTPTR_H
+#define MBSMARTPTR_H
+
+#include <basics/memory/MbSmartPtrBase.h>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+//=====================================================
+// Globale Funktion, um das Loeschen des referenzierten
+// Objektes flexibler zu gestalten.
+//
+template<class ObjType>
+void deleteRefPtr(ObjType* ptr)
+{
+   delete ptr;
+}
+
+//======================================================
+// Die Reference-Pointer Klasse:
+//
+// Beim Referenzieren eines Objektes ueber einen SmartPointer wird ein Zaehler fuer die referezierte Objekt-
+// adresse inkrementiert. Wird der Pointer wieder einem anderen Objekt zugewiesen, so wird der Zaehler fuer das
+// urspruenglich referenzierte Objekt wieder dekremtiert, ebenfalls beim Destruktor des Reference-Pointers.
+// Tatsaechlich geloescht wird das referenzierte Objekt erst, wenn der zugehoerige Zaehler auf 0 ist. Dies geschieht
+// ueber die globale Template-Funktion deleteRefPtr(), die bei Bedarf ueberschrieben werden kann.
+// Der Reference-Pointer verfuegt also sozusagen ueber eine automatische Garbage Collection
+
+template<class ObjType>
+class MbSmartPtr  : public MbSmartPtrBase
+{
+public:
+   // Konstruktoren //bei explicit geht der implizite cast nicht mehr, aber um keinen stress zu verursachen
+   /*explicit*/ MbSmartPtr<ObjType>(const ObjType* pPtr=NULL)
+      : MbSmartPtrBase(), mpPtr(NULL)
+	{
+		init(pPtr);
+	}
+	template<class ParamType>
+	MbSmartPtr<ObjType>(const MbSmartPtr<ParamType>& ptr)
+      : MbSmartPtrBase(), mpPtr(NULL)
+	{
+		init(ptr.get());
+	}
+	// Destruktor
+   ~MbSmartPtr<ObjType>()
+	{
+      init(NULL);
+	}
+   //---------------------------------------------------
+   // Kopierkonstruktor
+   MbSmartPtr<ObjType>(const MbSmartPtr<ObjType>& ptr)
+     : MbSmartPtrBase(), mpPtr(NULL)
+	{
+		init(ptr.get());
+	}
+   //---------------------------------------------------
+   // Zuweisungsoperatoren
+	template<class ParamType>
+	const MbSmartPtr<ObjType>& operator =(const MbSmartPtr<ParamType>& ptr)
+	{
+   	init(ptr.get());
+		return *this;
+	}
+	const MbSmartPtr<ObjType>& operator =(const MbSmartPtr<ObjType>& ptr)
+	{
+		init(ptr.get());
+		return *this;
+	}
+
+	const MbSmartPtr<ObjType>& operator =(const ObjType *pPtr)
+	{
+		init(pPtr);
+		return *this;
+	}
+   //---------------------------------------------------
+   // Dereferenzierung-Operatoren
+	ObjType& operator *() const  { return *mpPtr; }
+   ObjType* operator ->() const { return mpPtr;  }
+   bool operator !() const      { return !mpPtr; }
+   operator ObjType *() const   { return mpPtr;  }
+   //---------------------------------------------------
+	// Methoden
+	ObjType* get() const
+   {
+      return mpPtr;
+   }
+   //---------------------------------------------------
+   int ref_count() const
+   {
+      return MbSmartPtrBase::ref_count(mpPtr);
+   }
+   //---------------------------------------------------
+   bool release() const
+   {
+      return MbSmartPtrBase::removeFromGC(mpPtr);
+   }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      if(ArchiveTools::isWriting(ar))
+      {
+         ar & mpPtr;
+      }
+      else
+      {
+         ObjType* ptr;
+         ar & ptr;
+
+         mpPtr=NULL;
+         init(ptr);
+      }
+   }
+#endif //CAB_RCF
+
+private:
+   void init(const ObjType* pPtr)
+	{
+      // Nur was tun, wenn wirklich noetig
+		if(pPtr==mpPtr) return;
+
+      // Aktuell referenziertes Objekt freigeben, dabei ueberpruefen, ob letztes Release
+		if(mpPtr && releaseRef(mpPtr))
+		{
+         // referenziertes Objekt loeschen
+			deleteRefPtr(mpPtr);
+		}
+
+      // Wenn pPtr ein neues Objekt ist, Zugriffszaehler auf neues Objekt erhoehen
+		mpPtr=const_cast<ObjType*>(pPtr);
+	   if(mpPtr) addRef(mpPtr);
+	}
+
+private:
+   ObjType* mpPtr;
+};
+
+#endif //MBSMARTPTR_H
diff --git a/source/ThirdParty/Library/basics/memory/MbSmartPtrBase.cpp b/source/ThirdParty/Library/basics/memory/MbSmartPtrBase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d0e07fa9503fe01f94128543d84927804505b97a
--- /dev/null
+++ b/source/ThirdParty/Library/basics/memory/MbSmartPtrBase.cpp
@@ -0,0 +1,44 @@
+#include <basics/memory/MbSmartPtrBase.h>
+
+using namespace std;
+
+bool MbSmartPtrBase::addRef(void* ptr)
+{
+   MbSmartPtrBaseMap::getInstance()->getMap()[ptr]++;
+	return true;
+}
+//-------------------------------------------------
+bool MbSmartPtrBase::releaseRef(void* ptr)
+{
+   map<void*,int>& ptrMap = MbSmartPtrBaseMap::getInstance()->getMap();
+   map<void*,int>::iterator pos=ptrMap.find(ptr);
+	
+   if( pos!=ptrMap.end() )
+	{
+		pos->second--;
+		
+      if(pos->second==0)
+		{
+			ptrMap.erase(pos);
+			return true;
+		}
+	}
+	return false;
+}
+//-------------------------------------------------
+bool MbSmartPtrBase::removeFromGC(void* ptr) const 
+{
+   if( MbSmartPtrBaseMap::getInstance()->getMap().erase(ptr) ) return true;
+   return false;
+}
+//-------------------------------------------------
+int MbSmartPtrBase::ref_count(void* ptr) const 
+{
+   map<void*,int>& ptrMap = MbSmartPtrBaseMap::getInstance()->getMap();
+   map<void*,int>::iterator pos=ptrMap.find(ptr);
+
+   if( pos!=ptrMap.end() ) return pos->second;
+   else                    return 0;
+}
+
+
diff --git a/source/ThirdParty/Library/basics/memory/MbSmartPtrBase.h b/source/ThirdParty/Library/basics/memory/MbSmartPtrBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1bf281ce1f7fe8b41c19cd0d6deac9dd43f9574
--- /dev/null
+++ b/source/ThirdParty/Library/basics/memory/MbSmartPtrBase.h
@@ -0,0 +1,50 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBSMARTPTRBASE_H
+#define MBSMARTPTRBASE_H
+
+#include <iostream>
+#include <map>
+
+//============================================================
+// Klasse MbSmartPtrBase
+//
+// Basisklasse, speziell fuer MbSmartPtr, die das eigentliche
+// Reference-Counting uebernimmt.
+//
+class MbSmartPtrBase
+{
+   //Ursprung:
+   // mpCntrMap ist ein Pointer, weil sichergestellt sein muss, dass die
+   // Map existiert, wenn das erste mal darauf zugegriffen wird.
+   // Ein Zugriff zwischen zwei statischen Objekten kann zum Fehler fuehren, da
+   // die Reihenfolge der Konstruktorenaufrufe dann vom Linker bestimmt wird.
+
+   //Anpassung a la UbWriter mit SingletonMap
+   class MbSmartPtrBaseMap
+   {
+   private:
+      MbSmartPtrBaseMap() { }
+      MbSmartPtrBaseMap( const MbSmartPtrBaseMap& );                  //no copy allowed
+      const MbSmartPtrBaseMap& operator=( const MbSmartPtrBaseMap& ); //no copy allowed
+
+      std::map<void*,int> mpCntrMap;
+   public:
+      static MbSmartPtrBaseMap* getInstance() { static MbSmartPtrBaseMap instance; return &instance; }
+      std::map<void*,int>& getMap()           { return mpCntrMap;                                    }
+   };
+
+protected:
+   MbSmartPtrBase() {}
+   virtual ~MbSmartPtrBase() {}
+   bool addRef(void* p);
+	bool releaseRef(void* p);
+   bool removeFromGC(void* ptr) const;
+   int  ref_count(void* ptr) const;
+};
+
+#endif //MBSMARTPTRBASE_H
diff --git a/source/ThirdParty/Library/basics/objects/CMakePackage.txt b/source/ThirdParty/Library/basics/objects/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/ThirdParty/Library/basics/objects/ObCreator.h b/source/ThirdParty/Library/basics/objects/ObCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..253fc616e2f1d9c2b279423ce93462095e698774
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObCreator.h
@@ -0,0 +1,112 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBCREATOR_H
+#define OBCREATOR_H
+
+#include <string>
+
+/*=========================================================================*/
+/*  ObCreator / ObCreatorImpl                                              */
+/*                                                                         */
+/**
+generic factory
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 14.06.07
+@version 1.1 - 12.04.08
+*/ 
+
+/*
+usage: see bottom of file "./ObFactory.h"
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// ObCreator
+// Um in der Factory verschiedene Typen von Creaors in einer 
+// std::map<std::string,ObCreator<BaseT>*> halten zu koennen
+// muss eine gemeinsame Basisklasse existieren
+//////////////////////////////////////////////////////////////////////////
+template< class BaseT >
+class ObCreator
+{
+public:
+   virtual std::string  getObjectTypeID()=0;
+   virtual BaseT*       createObject() = 0;
+
+   virtual ~ObCreator() {  }
+
+protected:
+   ObCreator() {}
+private:
+   ObCreator( const ObCreator< BaseT >& );         //no copy allowed 
+   const ObCreator& operator=( const ObCreator& ); //no copy allowed
+};
+
+//////////////////////////////////////////////////////////////////////////
+// ObCreatorImpl
+// Implementierung des speziellen Creators 
+//////////////////////////////////////////////////////////////////////////
+template< class T, class BaseT=T >
+class ObCreatorImpl : public ObCreator< BaseT >
+{
+public:
+   static ObCreator<BaseT >* getInstance()
+   {
+      static ObCreatorImpl< T, BaseT > instance;
+      return &instance;
+   }
+
+public:
+   ~ObCreatorImpl() {}
+
+   //aus portabilitaetsgruenden kann man nicht typeinfo nehmen, da diese compilerabhaengig ist
+   std::string getObjectTypeID()  { return T::getStaticClassObjectTypeID();  } 
+   
+   virtual T*  createObject() { return new T(); }
+
+protected:
+	ObCreatorImpl() {}
+private:
+	ObCreatorImpl( const ObCreatorImpl< T, BaseT >& );      //no copy allowed 
+   const ObCreatorImpl& operator=( const ObCreatorImpl& ); //no copy allowed
+};
+
+//////////////////////////////////////////////////////////////////////////
+// ObCreatorImpl
+// Implementierung des speziellen Creators fuer Singletons
+//////////////////////////////////////////////////////////////////////////
+template< class T, class BaseT=T >
+class ObSingletonCreatorImpl : public ObCreator< BaseT >
+{
+public:
+   static ObCreator<BaseT >* getInstance()
+   {
+      static ObSingletonCreatorImpl< T, BaseT > instance;
+      return &instance;
+   }
+public:
+   ~ObSingletonCreatorImpl() {}
+
+   //aus portabilitaetsgruenden kann man nicht typeinfo nehmen, da diese compilerabhaengig ist
+   std::string getObjectTypeID()  { return T::getStaticClassObjectTypeID();  } 
+
+   virtual T* createObject() { return T::getInstance(); }
+
+protected:
+   ObSingletonCreatorImpl() {}
+private:
+   ObSingletonCreatorImpl( const ObSingletonCreatorImpl< T, BaseT >& );      //no copy allowed 
+   const ObSingletonCreatorImpl& operator=( const ObSingletonCreatorImpl& ); //no copy allowed
+};
+
+//workaround for the not perfect C++ world. typeinfo::name is not usable for this purpose!
+//see Andrei Alexandrescu, "Modern C++ Design: Generic Programming and Design Patterns Applied", Chapter 8.5
+#define OBCREATOR_EXT( ClassObject ) \
+   static  std::string  getStaticClassObjectTypeID() { return #ClassObject;                 } \
+   virtual std::string  getClassObjectTypeID()       { return getStaticClassObjectTypeID(); } 
+
+#endif //OBCREATOR_H
diff --git a/source/ThirdParty/Library/basics/objects/ObFactory.h b/source/ThirdParty/Library/basics/objects/ObFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b51787819b0548efc89960be450d129753aa0b3
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObFactory.h
@@ -0,0 +1,174 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBFACTORY_H
+#define OBFACTORY_H
+
+
+#include <string>
+#include <map>
+#include <sstream>
+#include <iomanip>
+#include <typeinfo>
+
+#include <basics/objects/ObCreator.h>
+
+/*=========================================================================*/
+/*  ObFactory                                                            */
+/*                                                                         */
+/**
+generic factory
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 14.06.07
+@version 1.1 - 12.04.08
+*/ 
+
+/*
+usage:  T       = zu erzeugende Klasse
+        Creator = Erzeugerklasse
+//////////////////////////////////////////////////////////////////////////
+//example
+//////////////////////////////////////////////////////////////////////////
+//  class Base{ 
+//  public:
+//        OBCREATOR_EXT(Base)
+//  };
+//  //automatisches registrieren:
+//  UB_AUTO_RUN_NAMED(ObFactory<Base>::getInstance()->addObCreator(ObCreatorImpl<Base,Base>::getInstance()), CAB_Base);
+//  class Derived : public Base 
+//  {
+//   public:
+//        OBCREATOR_EXT(Derived)
+//};
+//  //automatisches registrieren:
+//  UB_AUTO_RUN_NAMED(ObFactory<Base>::getInstance()->addObCreator(ObCreatorImpl<Base,Derived>::getInstance()), CAB_Derived);
+////////////////////////////////////////////////////////////////////////////
+//  int main()
+//  {
+//       //Alternativ zu UB_AUTO_RUN_NAMED: haendisches registrieren
+//       ObFactory<Base>::getInstance()->addObCreator(ObCreatorImpl<Base>::getInstance());
+//       ObFactory<Base>::getInstance()->addObCreator(ObCreatorImpl<Derived,Base>::getInstance());
+// 
+//       //create objects - method1
+//       Base* test1 = ObFactory<Base>::getInstance()->createObject<Base>();
+//       Base* test2 = ObFactory<Base>::getInstance()->createObject<Derived>();
+// 
+//       //create objects - method2
+//       Base* test1 = ObFactory<Base>::getInstance()->createObject(Base::getStaticClassObjectTypeID()    );
+//       Base* test2 = ObFactory<Base>::getInstance()->createObject(Derived::getStaticClassObjectTypeID() );
+//   //...
+// }
+*/
+
+
+template<class  T, typename Creator = ObCreator< T > >
+class ObFactory
+{
+   typedef std::map<  std::string, Creator* > CreatorMap;
+   typedef typename CreatorMap::iterator      CreatorMapIt;
+   typedef std::pair< std::string, Creator* > CreatorMapElement;
+
+protected:
+   ObFactory() {}  //so ist vererbung gewahrleistet
+
+private:
+   ObFactory( const ObFactory< T, Creator >& );    //no copy allowed 
+   const ObFactory& operator=( const ObFactory& ); //no copy allowed
+
+
+public:
+   virtual ~ObFactory() {}
+
+   static ObFactory< T, Creator >* getInstance() 
+   {
+      static ObFactory< T, Creator > instance;
+      return &instance;
+   }
+
+   bool addObCreator(Creator* creator);
+   bool removeObCreator(Creator* creator);
+
+   T* createObject(const std::string& objectTypeID);
+   
+   template< typename T2 > 
+   T* createObject() { return this->createObject( T2::getStaticClassObjectTypeID() ); }
+   
+   Creator* getCreator(const std::string& objectTypeID);
+
+   virtual std::string toString();
+  
+private:
+   CreatorMap creatorMap;
+};
+
+//////////////////////////////////////////////////////////////////////////
+//Implementation
+template<class  T, typename Creator >
+bool ObFactory< T, Creator >::addObCreator(Creator* creator)
+{
+	if(creatorMap.insert( CreatorMapElement(creator->getObjectTypeID(), creator) ).second )
+   {
+      //insert succeeded
+      return true;
+   }
+   //insert fails
+   return false;
+}
+/*======================================================================*/
+template<class  T, typename Creator >
+bool ObFactory< T, Creator >::removeObCreator(Creator* creator)
+{
+   if(creator && creatorMap->erase( creator->getClassObjectTypeID() ) ) 
+      return true;
+
+   return false;
+}
+/*======================================================================*/
+template<class  T, typename Creator >
+Creator* ObFactory< T, Creator >::getCreator(const std::string& obtypeID)
+{
+   CreatorMapIt it = creatorMap.find(obtypeID);
+   if(it == creatorMap.end()) return NULL;
+
+   Creator* creator = it->second;
+   if(!creator) return NULL;
+
+   return creator;
+}
+/*======================================================================*/
+ template<class  T, typename Creator >
+ T* ObFactory< T, Creator >::createObject(const std::string& objectTypeID)
+ {
+    Creator* creator = this->getCreator(objectTypeID);
+    
+    if(!creator) 
+    {
+       UB_THROW( UbException(UB_EXARGS,"no creator avaivlable for ID="+objectTypeID ) );
+    }
+ 
+    return creator->createObject();
+ }
+/*======================================================================*/
+template<class  T, typename Creator >
+std::string ObFactory< T, Creator >::toString() 
+{
+   std::size_t maxL = 6;
+   for(CreatorMapIt it=creatorMap.begin(); it!=creatorMap.end(); ++it)
+      if( it->first.size() > maxL ) 
+         maxL = it->first.size();
+   
+   std::stringstream os;
+   os<<(std::string)typeid(*this).name()<<" - info:"<<std::endl;
+   os<<"   "<<std::left<<std::setw(maxL)<<"object"<<" <-> "<<"creator "<<std::endl;
+   for(CreatorMapIt it=creatorMap.begin(); it!=creatorMap.end(); ++it)
+      os<< " - " << std::setw(maxL) << it->first << " <-> " << (std::string)typeid(*it->second).name() << std::endl;
+
+   return os.str();
+}
+/*======================================================================*/
+
+#endif //OBFACTORY_H
diff --git a/source/ThirdParty/Library/basics/objects/ObObject.cpp b/source/ThirdParty/Library/basics/objects/ObObject.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..452791ad8f43507c069ea9e90e59193fd39334f6
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObObject.cpp
@@ -0,0 +1,10 @@
+//#include <basics/objects/ObObject.h>
+
+// ObObject::ObObject()
+// { 
+// }
+// /*=======================================*/
+// std::string ObObject::getName()
+// {
+//    return name;
+// }
diff --git a/source/ThirdParty/Library/basics/objects/ObObject.h b/source/ThirdParty/Library/basics/objects/ObObject.h
new file mode 100644
index 0000000000000000000000000000000000000000..aeb3ed9c48bb7bbe0b58fc534c6c2313d17ce35b
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObObject.h
@@ -0,0 +1,60 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBOBJECT_H
+#define OBOBJECT_H
+
+#include <string>
+
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/utilities/UbObservable.h>
+
+#ifdef CAB_RCF
+#include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+
+class ObObjectCreator;
+
+class ObObject : public UbObservable
+{
+public:
+   ObObject() : name("") { }
+   ObObject(const std::string& name) : name(name) { }
+
+   virtual ~ObObject() { }
+
+   virtual ObObject*   clone()=0;
+   virtual std::string getTypeID()=0;
+
+   virtual std::string getName()  { return name; }
+   void setName(std::string name) { this->name=name; }
+
+   virtual std::string toString()=0;
+
+   virtual ObObjectCreator* getCreator()=0;
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar) 
+   {
+      //SF::SF_SERIALIZE_PARENT<UbObservable>(ar, *this);
+      SF_SERIALIZE_PARENT<UbObservable>(ar, *this);
+      ar & name;
+   }
+#endif //CAB_RCF
+
+private:
+   std::string name;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+SF_NO_CTOR(ObObject);
+UB_AUTO_RUN_NAMED( ( SF::registerType<ObObject>("ObObject") ),                SF_ObObject     );
+UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived<UbObservable, ObObject >() ), SF_ObObject_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/ThirdParty/Library/basics/objects/ObObjectCreator.h b/source/ThirdParty/Library/basics/objects/ObObjectCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..540f422d5ddc6ef9320743bfbee4432a85225796
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObObjectCreator.h
@@ -0,0 +1,58 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBOBJECTCREATOR_H
+#define OBOBJECTCREATOR_H
+
+#include <string>
+
+class ObObject;
+class ObObjectManager;
+
+class Presentator;
+class QViewer;
+
+#ifdef CAB_QT 
+class QObObjectSpecificInstrument;
+class QWidget;
+class QActionGroup;
+#endif
+
+class ObObjectCreator
+{
+public:
+   virtual ~ObObjectCreator() {}
+
+	virtual ObObject* createObObject()=0;
+
+	virtual std::string getTypeID()	{ return "ObObject"; }
+	virtual std::string toString()	{ return "ObObjectCreator"; }
+   
+#ifdef CAB_QT 
+   //virtual Presentator* createObjectPresentator(ObObject *object)=0;
+   virtual Presentator* createObjectPresentator(ObObject *object) { return NULL; }
+   virtual QActionGroup* getSpecificPresentatorGroup(ObObject* object, QViewer *viewer, QWidget* parent) { return NULL; }
+   virtual QActionGroup* getSpecificActionGroup(ObObjectManager* manager, ObObject* object, QWidget* parent) 
+   { 
+      return NULL; 
+   }
+
+   virtual ObObject* createObObjectWithQt() { return NULL; }
+   virtual void showSpecificInstrument(ObObject* object, QWidget* parent=0) {}
+   virtual QObObjectSpecificInstrument* getSpecificInstrument() { return NULL; }
+   
+   //virtual QActionGroup *getSpecificContextMenuActionGroup() { return NULL; }
+#endif
+
+protected:
+	ObObjectCreator() {}
+
+private:
+   ObObjectCreator( const ObObjectCreator& );                  //no copy allowed 
+   const ObObjectCreator& operator=( const ObObjectCreator& ); //no copy allowed
+
+};
+#endif
diff --git a/source/ThirdParty/Library/basics/objects/ObObjectFactory.cpp b/source/ThirdParty/Library/basics/objects/ObObjectFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5cc03a78f2b2d550406e14a95cdbcffe22157e9c
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObObjectFactory.cpp
@@ -0,0 +1,54 @@
+#include <basics/objects/ObObjectFactory.h>
+
+/**** Eigene ****/
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/utilities/UbException.h>
+
+using namespace std;
+
+//ObObjectFactory::ObObjectFactory()
+//{
+//}
+//
+//ObObjectFactory::~ObObjectFactory()
+//{
+//}
+/*======================================================================*/  
+//ObObjectFactory* ObObjectFactory::getInstance()
+//{
+//	static ObObjectFactory instance;
+//	return &instance;
+//}
+/*======================================================================*/
+void ObObjectFactory::addObObjectCreator(ObObjectCreator *creator)
+{
+	//cout<<"Meth:"<<creator->toString()<<" Meth-ID:"<<creator->getTypeID()<<endl;
+	creatorSet.insert(std::pair<string, ObObjectCreator*>(creator->getTypeID(), creator));
+}
+/*======================================================================*/
+void ObObjectFactory::removeObObjectCreator(ObObjectCreator *creator)
+{
+	UB_THROW( UbException(UB_EXARGS,"not implemented") );
+}
+/*======================================================================*/
+ObObjectCreator* ObObjectFactory::getCreator(string objectType) 
+{
+	std::map<string, ObObjectCreator*>::iterator creatorIterator = creatorSet.find(objectType);
+	if(creatorIterator == creatorSet.end()) UB_THROW( UbException(UB_EXARGS,"factory has no creator for "+objectType) );
+	ObObjectCreator *creator = creatorIterator->second;
+	if(!creator) UB_THROW( UbException(UB_EXARGS,"no time series creator for type available") );
+	return creator;
+}
+/*======================================================================*/
+string ObObjectFactory::toString() 
+{
+   stringstream text;
+
+   std::map<string, ObObjectCreator*>::iterator creatorIterator;
+   std::map<string, ObObjectCreator*>* creatorSet = this->getCreatorSet();
+
+   for(creatorIterator = creatorSet->begin(); creatorIterator!=creatorSet->end(); ++creatorIterator)
+      text<<"   - "<<(creatorIterator->second)->toString()<<" for "<<(creatorIterator->first)<<endl;
+
+   return text.str();
+}
diff --git a/source/ThirdParty/Library/basics/objects/ObObjectFactory.h b/source/ThirdParty/Library/basics/objects/ObObjectFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..da8ef389c6ef433d96be6663eefaf34c9c99bd1c
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObObjectFactory.h
@@ -0,0 +1,42 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBOBJECTFACTORY_H
+#define OBOBJECTFACTORY_H
+
+#include <string>
+#include <map>
+
+class ObObjectCreator; 
+
+class ObObjectFactory
+{
+public:
+   ObObjectFactory() {}
+   virtual ~ObObjectFactory() {}
+
+   //static geht nicht, da abgeleitete Factories existieren ...
+   //static ObObjectFactory* getInstance();
+   //virtual ObObjectFactory* getInstance()=0;
+
+   ObObjectCreator* getCreator(std::string objectType);
+
+	void addObObjectCreator(ObObjectCreator* creator);
+	void removeObObjectCreator(ObObjectCreator* creator);
+
+   std::map<std::string, ObObjectCreator*>* getCreatorSet() { return &creatorSet;  }
+
+   virtual std::string toString();
+	
+private:
+   ObObjectFactory( const ObObjectFactory& );                  //no copy allowed 
+   const ObObjectFactory& operator=( const ObObjectFactory& ); //no copy allowed
+
+   std::map<std::string, ObObjectCreator*> creatorSet;
+};
+
+
+#endif //OBOBJECTFACTORY_H
diff --git a/source/ThirdParty/Library/basics/objects/ObObjectManager.cpp b/source/ThirdParty/Library/basics/objects/ObObjectManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..44bba546bf9e157bc21baff5d6e24aa8f3700786
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObObjectManager.cpp
@@ -0,0 +1,216 @@
+#include <basics/objects/ObObjectManager.h>
+#include <basics/objects/ObObject.h>
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/utilities/UbTableModel.h>
+#include <basics/utilities/UbException.h>
+
+using namespace std;
+
+ObObjectEntry::ObObjectEntry(ObObjectManager *parent, ObObject *object)
+{
+   this->parent = parent;
+   this->object = object;
+}
+/*======================================================*/
+ObObjectManager::ObObjectManager()
+{
+	this->selectedObject = NULL;
+	this->tableModel = NULL;
+}
+
+/*======================================================*/
+ObObjectManager::~ObObjectManager()
+{
+	//cerr<<"NEIN, notifyObserversObjectWillBeDeleted wird AUSSCHLIESSLICH von BasisKlasse aufgerufen!!!"<<endl;
+ //  cerr<<"das muss so sein, denn ansonsten duerfte diese funktion nur in der speziellen klasse stehen, da\n";
+ //  cerr<<"virtuelle destruktoren sich rekursiv vom speziellen ins allg. aufrufen --> notify.. wuerde\n";
+ //  cerr<<"oefters aufgerufen werden...\n";
+
+	this->objectList.clear();
+	if(this->tableModel) delete this->tableModel;
+}
+/*======================================================*/
+UbTableModel* ObObjectManager::getTableModel()
+{ 
+	return tableModel; 
+}
+/*======================================================*/
+//bool ObObjectManager::addObObject(ObObject *object)
+//{
+//   cout<<"ObObjectManager::addObObject "<<object->toString()<<endl;
+//	for(int pos=0; pos<(int)this->objectList.size(); pos++)
+//		if(this->objectList[pos]->object==object) 
+//			return false;
+//
+//	this->objectList.push_back(new ObObjectEntry(this,object));
+//	//object->addObserver(this);
+//	this->selectObObject(object);
+//	return true;
+//}
+/*======================================================*/
+bool ObObjectManager::addObObjectEntry(ObObjectEntry* objectEntry)
+{
+   for(int pos=0; pos<(int)this->objectList.size(); pos++)
+      if(this->objectList[pos]->object==objectEntry->object) 
+         return false;
+
+   this->objectList.push_back(objectEntry);
+//   objectEntry->getObject()->addObserver(this);
+   this->selectObObject(objectEntry->object);
+   return true;
+}
+/*======================================================*/
+bool ObObjectManager::removeObObject(ObObject* object)
+{
+	if (this->selectedObject == object) this->selectedObject=NULL;
+	for(int pos=0; pos<(int)this->objectList.size(); pos++)
+	{
+
+		if(this->objectList[pos]->object==object) 
+		{
+         return this->removeObObject(pos);
+//			this->objectList.erase(objectList.begin()+pos);
+//			//this->removeObserver(this);
+//			return true;
+		}
+	}
+	return false;
+}
+/*======================================================*/
+bool ObObjectManager::removeObObject(int index)
+{
+	try
+	{
+		if ( objectList[index]->object == this->selectedObject ) this->selectedObject=NULL;
+      //den entry loeschen ... das object im Entry ??? erstmal ausserhalb ...
+      delete objectList[index]; 
+		objectList.erase(objectList.begin()+index);
+   	this->notifyObserversObjectChanged();
+   	return true;
+	}
+	catch(const std::exception& e)  {  cerr<<e.what()<<endl;    }
+   catch(...)                      {  cerr<<"Fehler in ObObjectManager::removeObObject"<<endl; }
+   return false;
+}
+/*======================================================*/
+void ObObjectManager::removeAllObObjects() 
+{  
+	//TODO: implementieren!!
+	//foreach grid:
+	//grid->removeObserver(this);
+	//vector<ObObject*>::iterator it;
+	//for(it=objectList.begin();  it!=objectList.end(); it++)
+	//{
+	//	it->removeObserver(this);
+	//}
+// 	for(int i=0; i<(int)objectList.size(); i++)
+// 	{
+// 		delete objectList[i]->object->removeObserver(this);
+// 	} 
+	this->objectList.clear();
+	this->selectedObject = NULL;
+	this->notifyObserversObjectChanged();
+}
+/*======================================================*/
+int ObObjectManager::getNumberOfObObjects()
+{ 
+	return (int)this->objectList.size();
+}
+/*======================================================*/
+vector<ObObject*>* ObObjectManager::getAllObObjects()  
+{ 
+   UB_THROW( UbException(UB_EXARGS,"hier muss noch was getan werden") );
+//	return this->objectList;  
+}
+vector<ObObjectEntry*>* ObObjectManager::getAllObObjectEntries()
+{
+   return &this->objectList;  
+}
+/*======================================================*/
+ObObject* ObObjectManager::getObObject(int index)
+{
+	if(index <  0)                            return NULL;
+	if(index >= (int)this->objectList.size()) return NULL;
+
+	return(this->objectList[index]->object);
+}
+/*======================================================*/
+ObObjectEntry* ObObjectManager::getObObjectEntry(int index)
+{
+   if(index <  0)                            return NULL;
+   if(index >= (int)this->objectList.size()) return NULL;
+
+   return(this->objectList[index]);
+}
+/*====================================================*/
+string ObObjectManager::toString()
+{
+	stringstream ss; ss<<endl;
+
+	for(int pos=0; pos<(int)this->objectList.size(); pos++)          
+	{
+		ObObject* object = this->objectList[pos]->object;
+		ss<<(pos+1)<<". "<<object->toString()<<endl;
+	}
+	return ss.str();
+}
+/*======================================================*/
+void ObObjectManager::objectChanged(UbObservable* observable)
+{
+   //cout<<"ObObjectManager::objectChanged ??";
+	this->notifyObserversObjectChanged();
+}
+/*======================================================*/
+void ObObjectManager::objectWillBeDeleted(UbObservable* observable)
+{
+   cout<<"ObObjectManager::objectWillBeDeleted ??";
+	//observable->removeObserver(this);
+}
+/*======================================================*/
+bool ObObjectManager::selectObObject(int index)
+{
+   if((int)this->objectList.size()==0) 
+   {
+      this->selectedObject = NULL; return false; 
+   }
+	if (index > (int)this->objectList.size()-1 || index < 0) return false; 
+	if ( this->selectedObject == this->getObObject(index) ) return true;
+   
+	this->selectedObject = this->getObObject(index);
+   //cout<<this->getObserverList()->size()<<endl;
+
+	this->notifyObserversObjectChanged();
+	return true;
+}
+/*======================================================*/
+bool ObObjectManager::selectObObject(ObObject* object)
+{
+   if((int)this->objectList.size()==0) { this->selectedObject = NULL; return false; }
+	for(int pos=0; pos<(int)this->objectList.size(); pos++)
+	{
+		if(this->objectList[pos]->object==object) 
+		{
+			return this->selectObObject(pos);
+		}
+	}
+	return false;
+}
+/*======================================================*/
+ObObject* ObObjectManager::getSelectedObObject()
+{
+	return this->selectedObject;
+}
+/*======================================================*/
+int ObObjectManager::getSelectedIndex()
+{
+	for(int pos=0; pos<(int)this->objectList.size(); pos++)
+	{
+		if(this->objectList[pos]->object==this->selectedObject) 
+		{
+			return pos;
+		}
+	}
+	return -1;
+}
+/*======================================================*/
+
diff --git a/source/ThirdParty/Library/basics/objects/ObObjectManager.h b/source/ThirdParty/Library/basics/objects/ObObjectManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..632e124bf72f3a259f638f12116eeac2b661e61f
--- /dev/null
+++ b/source/ThirdParty/Library/basics/objects/ObObjectManager.h
@@ -0,0 +1,79 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBOBJECTMANAGER_H
+#define OBOBJECTMANAGER_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <basics/utilities/UbObservable.h>
+#include <basics/utilities/UbObserver.h>
+
+class UbException;
+class UbTableModel;
+class ObObjectManager;
+class ObObjectFactory;
+class ObObject;
+
+
+class ObObjectEntry
+{
+   friend class ObObjectManager;
+public:
+   ObObjectManager* getParent() { return parent; }
+   ObObject*        getObject() { return object; }
+   
+   ObObjectEntry(ObObjectManager* parent, ObObject* object);
+   virtual ~ObObjectEntry() {  }
+
+protected:
+   ObObjectManager* parent;
+   ObObject* object;
+};
+
+
+class ObObjectManager : public UbObservable, public UbObserver
+{
+public:
+	ObObjectManager();
+	~ObObjectManager();
+	
+   //virtual bool addObObject(ObObject* object);   
+   virtual bool addObObjectEntry(ObObjectEntry* objectEntry);
+
+   virtual ObObjectEntry* createNewObObjectEntry(ObObject* obj) { return new ObObjectEntry(this, obj); }
+
+	bool removeObObject(ObObject* object);
+	bool removeObObject(int index);
+	void removeAllObObjects();
+	bool selectObObject(int index);
+	bool selectObObject(ObObject* object);
+	ObObject* getSelectedObObject();
+	int getSelectedIndex();
+
+	int getNumberOfObObjects();                 
+   std::vector<ObObject*>* getAllObObjects();
+   std::vector<ObObjectEntry*>* getAllObObjectEntries();
+	ObObject* getObObject(int index);
+   ObObjectEntry* getObObjectEntry(int index);
+
+	std::string toString();
+
+	virtual void objectChanged(UbObservable* observable);
+	virtual void objectWillBeDeleted(UbObservable* observable);
+
+	UbTableModel* getTableModel();
+   virtual ObObjectFactory* getObObjectFactory()=0;
+
+protected:
+	 std::vector<ObObjectEntry*> objectList;
+	 ObObject* selectedObject;
+	 UbTableModel* tableModel;
+};
+
+#endif //OBOBJECTMANAGER_H
diff --git a/source/ThirdParty/Library/basics/parallel/CMakePackage.txt b/source/ThirdParty/Library/basics/parallel/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/ThirdParty/Library/basics/parallel/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/ThirdParty/Library/basics/parallel/PbMpi.h b/source/ThirdParty/Library/basics/parallel/PbMpi.h
new file mode 100644
index 0000000000000000000000000000000000000000..21dd38f923eed543af9be4262366db5caf2b37f6
--- /dev/null
+++ b/source/ThirdParty/Library/basics/parallel/PbMpi.h
@@ -0,0 +1,454 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef PbMpi_H
+#define PbMpi_H
+
+#include <vector>
+#include <sstream>
+
+#ifndef VF_MPI
+#  error VF_MPI has to be defined
+#endif
+
+//#undef SEEK_SET
+//#undef SEEK_CUR
+//#undef SEEK_END
+#include <mpi.h>
+
+#include <basics/utilities/UbException.h>
+
+#ifdef USE_MPI_CXX_SYNTAX
+   #define PbMpi_COMM_WORLD MPI::COMM_WORLD
+   #define PbMpi_INT        MPI::INT  
+   #define PbMpi_CHAR       MPI::CHAR 
+   #define PbMpi_SHORT      MPI::SHORT
+   #define PbMpi_FLOAT      MPI::FLOAT
+   #define PbMpi_DOUBLE     MPI::DOUBLE
+   #define PbMpi_COMM_NULL  MPI::COMM_NULL   
+
+
+namespace PbMpi
+{
+   typedef MPI::Intracomm Comm;
+   typedef MPI::Group     Group;
+   typedef MPI::Request   Request;
+   typedef MPI::Status    Status;
+
+   inline void Init( )  
+   {
+      MPI::Init(); 
+      MPI::COMM_WORLD.Set_errhandler(MPI::ERRORS_THROW_EXCEPTIONS); 
+   }
+   inline void Init(int& argc, char** argv )  
+   {
+      MPI::Init(argc, argv); 
+      MPI::COMM_WORLD.Set_errhandler(MPI::ERRORS_THROW_EXCEPTIONS); 
+   }
+   inline void Finalize()                      { MPI::Finalize();        }
+
+   inline int  GetCommSize( const Comm& comm ) { return comm.Get_size(); }
+   inline int  GetCommRank( const Comm& comm ) { return comm.Get_rank(); }
+   inline void Barrier( const Comm& comm  )    { comm.Barrier();         }
+
+   inline double Wtime()                       { return MPI::Wtime();    }
+   inline double Wtick()                       { return MPI::Wtick();    }
+
+   inline void Wait( Request& request, Status* outStatus=NULL) 
+   { 
+      if(outStatus) request.Wait(*outStatus); 
+      else request.Wait();   
+   }
+
+   inline Group GetCommGroup(Comm& comm)                               { return comm.Get_group();     }
+   inline Group GetGroupIncl( Group& group, const int& n, int* ranks ) { return group.Incl(n, ranks); }
+   inline Comm  CommCreateComm( Comm& comm, Group& group )             { return comm.Create(group);   }
+
+   inline void Alltoall( Comm& comm, void* sendBuffer, const int& sn, const MPI_Datatype& sdatatype, void* recvBuffer, const int& rn, const MPI_Datatype& rdatatype)
+   {
+      comm.Alltoall(sendBuffer, sn, sdatatype, recvBuffer, rn, rdatatype);
+   }
+   inline void Bcast(Comm& comm, void* data, const int& n, const MPI_Datatype& datatype , const int& srcRank )
+   {
+      comm.Bcast(data, n, datatype, srcRank);
+   }
+   inline void Send(Comm& comm,  const void* data, const int& length, const MPI_Datatype& dataType, const int& destRank, const int& tag)
+   {
+      try
+      { 
+         comm.Send(data, length, dataType, destRank, tag);
+      }
+      catch(MPI::Exception& e)
+      {
+         std::stringstream ss; 
+         ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+         throw UbException(UB_EXARGS,"MPI:Exception catched\n"+ss.str());
+      }
+      catch(...)  
+      {
+         throw UbException(UB_EXARGS,"unknown exception"); 
+      }
+   }
+   inline void Recv(Comm& comm,  const void* data, const int& length, const MPI_Datatype& dataType, const int& srcRank, const int& tag)
+   {
+      try
+      { 
+         comm.Recv(const_cast<void*>(data), length, dataType, srcRank, tag);
+      }
+      catch(MPI::Exception& e)
+      {
+         std::stringstream ss; 
+         ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+         throw UbException(UB_EXARGS,"MPI:Exception catched \n"+ss.str());
+      }
+      catch(...)  
+      {
+         throw UbException(UB_EXARGS,"unknown exception"); 
+      }
+   }
+
+   inline void Irecv(Comm comm,  const void* data, const int& length, const MPI_Datatype& dataType, const int& srcRank, const int& tag, Request& outRequest)
+   {
+      outRequest = comm.Irecv(const_cast<void*>(data), length, dataType, srcRank, tag);
+   }
+   inline void Ssend(Comm& comm,  const void* data, const int& length, const MPI_Datatype& dataType, const int& destRank, const int& tag)
+   {
+      try
+      { 
+         comm.Ssend(data, length, dataType, destRank, tag);
+      }
+      catch(MPI::Exception& e)
+      {
+         std::stringstream ss; 
+         ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+         throw UbException(UB_EXARGS,"MPI:Exception catched\n"+ss.str());
+      }
+      catch(...)  
+      {
+         throw UbException(UB_EXARGS,"unknown exception"); 
+      }
+   }
+
+}
+#else //////////////////////////////////////////////////////////////////////////
+   //////////////////////////////////////////////////////////////////////////
+   // C-Syntax 
+   //////////////////////////////////////////////////////////////////////////
+   namespace PbMpi
+   {
+      typedef MPI_Comm    Comm;
+      typedef MPI_Group   Group;
+      typedef MPI_Request Request;
+      typedef MPI_Status  Status;
+   }
+
+   #define PbMpi_COMM_WORLD ((PbMpi::Comm)MPI_COMM_WORLD)
+   #define PbMpi_INT        MPI_INT
+   #define PbMpi_CHAR       MPI_CHAR
+   #define PbMpi_SHORT      MPI_SHORT
+   #define PbMpi_FLOAT      MPI_FLOAT
+   #define PbMpi_DOUBLE     MPI_DOUBLE
+   #define PbMpi_COMM_NULL  MPI_COMM_NULL   
+
+namespace PbMpi
+{
+   inline void Init( )  
+   {
+      int    argc = 1;
+      char** argv = new char*[1];
+      argv[0]     = new char[1];
+      argv[0][0]  = 'n';
+      MPI_Init(&argc, &argv); 
+   }
+   inline void Init(int& argc, char** argv ) { MPI_Init(&argc, &argv);                         }
+   inline void Finalize( )                   { MPI_Finalize();                                 }
+   inline int  GetCommSize( Comm comm )      { int tmp; MPI_Comm_size(comm, &tmp); return tmp; }
+   inline int  GetCommRank( Comm comm )      { int tmp; MPI_Comm_rank(comm, &tmp); return tmp; }
+   inline void Barrier(  Comm comm )         { MPI_Barrier( comm );                            }
+   inline double Wtime()                     { return MPI_Wtime();                             }
+   inline double Wtick()                     { return MPI_Wtick();                             }
+   inline void   Wait( Request& request, Status* outStatus=NULL) { MPI_Wait( &request, outStatus);   }
+
+   inline Group GetCommGroup(Comm comm)                               { Group out; MPI_Comm_group(comm, &out);            return out; }
+   inline Group GetGroupIncl( Group group, const int& n, int* ranks ) { Group out; MPI_Group_incl(group, n, ranks, &out); return out; }
+   inline Comm  CommCreateComm( Comm comm, Group& group )             { Comm out;  MPI_Comm_create(comm, group, &out);    return out; }
+
+   inline void Alltoall( Comm comm, void* sendBuffer, const int& sn, const MPI_Datatype& sdatatype, void* recvBuffer, const int& rn, const MPI_Datatype& rdatatype)
+   {
+      MPI_Alltoall(sendBuffer, sn, sdatatype, recvBuffer, rn, rdatatype, comm);
+   }
+   inline void Bcast(Comm comm, void* data, const int& n, const MPI_Datatype& datatype , const int& srcRank )
+   {
+      MPI_Bcast(data, n, datatype, srcRank, comm);
+   }
+   inline void Send(Comm comm,  const void* data, const int& length, const MPI_Datatype& dataType, const int& destRank, const int& tag)
+   {
+      MPI_Send(const_cast<void*>(data), length, dataType, destRank, tag, comm);
+   }
+   inline void Recv(Comm comm,  const void* data, const int& length, const MPI_Datatype& dataType, const int& srcRank, const int& tag)
+   {
+      MPI_Recv(const_cast<void*>(data), length, dataType, srcRank, tag, comm, MPI_STATUS_IGNORE);
+   }
+   inline void Ssend(Comm comm,  const void* data, const int& length, const MPI_Datatype& dataType, const int& destRank, const int& tag)
+   {
+      MPI_Ssend(const_cast<void*>(data), length, dataType, destRank, tag, comm);
+   }
+   inline void Irecv(Comm comm,  const void* data, const int& length, const MPI_Datatype& dataType, const int& srcRank, const int& tag, Request& outRequest)
+   {
+      MPI_Irecv(const_cast<void*>(data), length, dataType, srcRank, tag, comm, &outRequest);
+   }
+
+}
+#endif
+
+namespace PbMpi
+{
+   /*======================================================================*/  
+   // send a single value "value" of MPI_Datatype
+   template <class T>
+   inline void sendSingleValue(const T& value, MPI_Datatype datatype, int dest, int tag, PbMpi::Comm comm);
+   
+   /*======================================================================*/  
+   // receives a single value "value" of MPI_Datatype
+   template <class T>
+   inline void receiveSingleValue(T& value, MPI_Datatype datatype, int source, int tag, PbMpi::Comm comm);
+   
+   /*======================================================================*/  
+   // receives and returns a single value of MPI_Datatype
+   // expample: int value = PbMpi::receiveSingleValue<int>(MPI::INT,0,10,comm);
+   template <class T>
+   inline T receiveSingleValue(MPI_Datatype datatype, int source, int tag, PbMpi::Comm comm);
+   
+   /*======================================================================*/  
+   // sends bool value (doesn't work with template, why ever... stupid MPI)
+   inline void sendBoolValue(const bool& value,int dest, int tag, PbMpi::Comm comm);
+
+   /*======================================================================*/  
+   // receives bool value (doesn't work with template, why ever... stupid MPI)
+   inline bool receiveBoolValue(int source, int tag, PbMpi::Comm comm);
+
+   /*======================================================================*/  
+   // sends bool value (doesn't work with template, why ever... stupid MPI)
+   inline void sendStringValue(const std::string& value,int dest, int tag, PbMpi::Comm comm);
+
+   /*======================================================================*/  
+   // receives bool value (doesn't work with template, why ever... stupid MPI)
+   inline std::string receiveStringValue(int source, int tag, PbMpi::Comm comm);
+
+   /*======================================================================*/  
+   // send a vector of MPI_Datatype
+   template <class T>
+	inline void sendVector(const std::vector<T>& v, MPI_Datatype datatype, int dest, int tag, PbMpi::Comm comm);
+	
+   /*======================================================================*/  
+   // receive a std::vector of MPI_Datatype
+   template <class T>
+   inline void receiveVector(std::vector<T>& v, MPI_Datatype datatype, int source, int tag, PbMpi::Comm comm);
+
+   /*======================================================================*/  
+   // receive a vector of MPI_Datatype and adds this vector to existing vector
+   // ans returns number of received elements
+   template <class T>
+   inline int receiveVectorAndAddToVector(std::vector<T>& v, MPI_Datatype datatype, int source, int tag, PbMpi::Comm comm);
+
+   /*======================================================================*/  
+   // send a std::vector of strings
+   inline void sendStringVector(const std::vector<std::string>& v, int dest, int tag, PbMpi::Comm comm);
+
+   /*======================================================================*/  
+   // send a vector of strings
+   inline void receiveStringVector(std::vector<std::string>& v, int dest, int tag, PbMpi::Comm comm);
+};
+
+/*======================================================================*/  
+// send a single value of MPI_Datatype
+template <class T>
+void PbMpi::sendSingleValue(const T& value, MPI_Datatype datatype, int dest, int tag, PbMpi::Comm comm)
+{
+   PbMpi::Send(comm, &value, 1, datatype, dest, tag); 
+   //comm.Send(&value, 1, datatype, dest, tag); 
+}
+/*======================================================================*/  
+template <class T>
+void PbMpi::receiveSingleValue(T& value, MPI_Datatype datatype, int source, int tag, PbMpi::Comm comm) 
+{
+   PbMpi::Recv(comm, &value, 1, datatype, source, tag); 
+   //comm.Recv(&value, 1, datatype, source, tag); 
+}
+/*======================================================================*/  
+template <class T>
+T PbMpi::receiveSingleValue(MPI_Datatype datatype, int source, int tag, PbMpi::Comm comm) 
+{
+   T value;
+   PbMpi::Recv(comm, &value, 1, datatype, source, tag); 
+   //comm.Recv(&value, 1, datatype, source, tag); 
+
+   return value;
+}
+/*======================================================================*/  
+// send a bool value (bool doesn't work with template, why ever)
+void PbMpi::sendBoolValue(const bool& value,int dest, int tag, PbMpi::Comm comm)
+{
+   short dummy;
+   if(value) dummy=1;                  
+   else      dummy=0;
+
+   PbMpi::Send(comm, &dummy, 1, PbMpi_SHORT, dest, tag); 
+   //comm.Send(&dummy, 1, MPI::SHORT, dest, tag); 
+}
+/*======================================================================*/  
+bool PbMpi::receiveBoolValue(int source, int tag, PbMpi::Comm comm) 
+{
+   short dummy;
+   PbMpi::Recv(comm, &dummy, 1, PbMpi_SHORT, source, tag); 
+   //comm.Recv(&dummy, 1, MPI::SHORT, source, tag);
+ 
+   return (dummy==1);
+}
+/*======================================================================*/  
+// sends bool value (doesn't work with template, why ever... stupid MPI)
+void PbMpi::sendStringValue(const std::string& value,int dest, int tag, PbMpi::Comm comm)
+{
+   std::vector<char> vec;
+   for(std::size_t i=0; i<value.size(); i++)
+      vec.push_back(value[i]);
+ 
+   PbMpi::sendVector(vec,PbMpi_CHAR,dest,tag,comm);
+}
+
+/*======================================================================*/  
+// receives bool value (doesn't work with template, why ever... stupid MPI)
+std::string PbMpi::receiveStringValue(int source, int tag, PbMpi::Comm comm)
+{
+   std::vector<char> vec;
+   PbMpi::receiveVector(vec,PbMpi_CHAR,source,tag,comm);
+   
+   std::string str;
+   for(std::size_t i=0; i<vec.size(); i++)
+      str+=vec[i];
+
+   return str;
+}
+/*======================================================================*/  
+// send a vector of MPI_Datatype
+template <class T>
+void PbMpi::sendVector(const std::vector<T>& v, MPI_Datatype datatype, int dest, int tag, PbMpi::Comm comm)
+{
+   // send size
+   int size = (int)v.size();
+   
+   PbMpi::Send(comm, &size, 1, PbMpi_INT, dest, tag);
+   //comm.Send(&size, 1, MPI::INT, dest, tag); 
+   
+   if(size>0)
+	{
+      PbMpi::Send(comm, &v[0], size, datatype, dest, tag);
+      //comm.Send(&v[0], size, datatype, dest, tag);
+   }
+}
+/*======================================================================*/  
+// receive a vector of MPI_Datatype
+template <class T>
+void PbMpi::receiveVector(std::vector<T>& v, MPI_Datatype datatype, int source, int tag, PbMpi::Comm comm) 
+{
+   int size;
+
+   PbMpi::Recv(comm, &size, 1, PbMpi_INT, source, tag);
+   //comm.Recv(&size, 1, MPI::INT, source, tag); 
+
+   v.resize(size);
+
+   if( size>0 )
+   {
+      PbMpi::Recv(comm, &v[0], size, datatype, source, tag);
+      //comm.Recv(&v[0], size, datatype, source, tag); 
+   }
+}
+/*======================================================================*/  
+// receive a vector of MPI_Datatype and adds this vector to existing vector
+// return value is size of received elements
+template <class T>
+int PbMpi::receiveVectorAndAddToVector(std::vector<T>& v, MPI_Datatype datatype, int source, int tag, PbMpi::Comm comm) 
+{
+   int incommingSize;
+
+   PbMpi::Recv(comm, &incommingSize, 1, PbMpi_INT, source, tag);
+   //comm.Recv(&incommingSize, 1, MPI::INT, source, tag);
+
+   int oldSize = (int)v.size();
+   v.resize(oldSize+incommingSize);
+
+   if( incommingSize>0 )
+   {
+      PbMpi::Recv(comm, &v[oldSize], incommingSize, datatype, source, tag);
+      //comm.Recv(&v[oldSize], incommingSize, datatype, source, tag);
+   }
+
+   return incommingSize;
+}
+/*======================================================================*/  
+// send a vector of strings
+void PbMpi::sendStringVector(const std::vector<std::string>& v, int dest, int tag, PbMpi::Comm comm)
+{
+   // send size
+   int stringVectorSize = (int)v.size();
+
+   PbMpi::Send(comm, &stringVectorSize, 1, PbMpi_INT, dest, tag); 
+   //comm.Send(&stringVectorSize, 1, MPI::INT, dest, tag); 
+
+   if(stringVectorSize>0)
+   {
+      std::vector<int> singleStringSizes(stringVectorSize+1);
+      int nofChars = 0;
+      for(int i=0; i<stringVectorSize; i++)
+         nofChars += singleStringSizes[i] = (int)v[i].length();
+      singleStringSizes[stringVectorSize] = nofChars;
+
+      PbMpi::Send(comm, &singleStringSizes[0], stringVectorSize+1, PbMpi_INT, dest, tag); 
+
+      std::vector<char> charVector(nofChars);
+      int pos = 0;
+      for(int i=0; i<stringVectorSize; i++)
+         for(int j=0; j<singleStringSizes[i]; j++)
+            charVector[pos++] = v[i][j];      
+
+      PbMpi::Send(comm, &charVector[0], nofChars, PbMpi_CHAR, dest, tag); 
+      //comm.Send(&charVector[0], nofChars, MPI::CHAR, dest, tag); 
+   }
+}
+/*======================================================================*/  
+// send a vector of strings
+void PbMpi::receiveStringVector(std::vector<std::string>& v, int source, int tag, PbMpi::Comm comm)
+{
+   // send size
+   int stringVectorSize;
+   PbMpi::Recv(comm, &stringVectorSize, 1, PbMpi_INT, source, tag);
+   //comm.Recv(&stringVectorSize, 1, MPI::INT, source, tag); 
+
+   v.clear();
+   v.resize(stringVectorSize);
+
+   if(stringVectorSize>0)
+   {
+      std::vector<int> singleStringSizes(stringVectorSize+1);
+
+      PbMpi::Recv(comm, &singleStringSizes[0], stringVectorSize+1, PbMpi_INT, source, tag); 
+      //comm.Recv(&singleStringSizes[0], stringVectorSize+1, MPI::INT, source, tag); 
+
+      int nofChars = singleStringSizes[stringVectorSize];
+      std::vector<char> charVector(nofChars);
+
+      PbMpi::Recv(comm, &charVector[0], nofChars, PbMpi_CHAR, source, tag); 
+      //comm.Recv(&charVector[0], nofChars, MPI::CHAR, source, tag); 
+
+      int pos=0;
+      for(int i=0; i<stringVectorSize; i++)
+         for(int j=0; j<singleStringSizes[i]; j++)
+            v[i].push_back(charVector[pos++]);      
+   }
+}
+
+#endif //PbMpi_H
diff --git a/source/ThirdParty/Library/basics/parallel/PbMpiTools.h b/source/ThirdParty/Library/basics/parallel/PbMpiTools.h
new file mode 100644
index 0000000000000000000000000000000000000000..0842c54b9dad7ca73f7e68613d802bc36c65d378
--- /dev/null
+++ b/source/ThirdParty/Library/basics/parallel/PbMpiTools.h
@@ -0,0 +1,303 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef PBMPITOOLS_H
+#define PBMPITOOLS_H
+
+#include <vector>
+#include <sstream>
+
+//#undef SEEK_SET
+//#undef SEEK_CUR
+//#undef SEEK_END
+#include <mpi.h>
+#include <basics/utilities/UbException.h>
+
+#ifdef USE_MPI_CXX_SYNTAX
+
+namespace PbMpiTools
+{
+   /*======================================================================*/  
+   // send a single value "value" of MPI_Datatype
+   template <class T>
+   inline void sendSingleValue(const T& value, MPI_Datatype datatype, int dest, int tag, MPI::Intracomm comm);
+   
+   /*======================================================================*/  
+   // receives a single value "value" of MPI_Datatype
+   template <class T>
+   inline void receiveSingleValue(T& value, MPI_Datatype datatype, int source, int tag, MPI::Intracomm comm);
+   
+   /*======================================================================*/  
+   // receives and returns a single value of MPI_Datatype
+   // expample: int value = PbMpiTools::receiveSingleValue<int>(MPI::INT,0,10,comm);
+   template <class T>
+   inline T receiveSingleValue(MPI_Datatype datatype, int source, int tag, MPI::Intracomm comm);
+   
+   /*======================================================================*/  
+   // sends bool value (doesn't work with template, why ever... stupid MPI)
+   inline void sendBoolValue(const bool& value,int dest, int tag, MPI::Intracomm comm);
+
+   /*======================================================================*/  
+   // receives bool value (doesn't work with template, why ever... stupid MPI)
+   inline bool receiveBoolValue(int source, int tag, MPI::Intracomm comm);
+
+   /*======================================================================*/  
+   // sends bool value (doesn't work with template, why ever... stupid MPI)
+   inline void sendStringValue(const std::string& value,int dest, int tag, MPI::Intracomm comm);
+
+   /*======================================================================*/  
+   // receives bool value (doesn't work with template, why ever... stupid MPI)
+   inline std::string receiveStringValue(int source, int tag, MPI::Intracomm comm);
+
+   /*======================================================================*/  
+   // send a vector of MPI_Datatype
+   template <class T>
+	inline void sendVector(const std::vector<T>& v, MPI_Datatype datatype, int dest, int tag, MPI::Intracomm comm);
+	
+   /*======================================================================*/  
+   // receive a std::vector of MPI_Datatype
+   template <class T>
+   inline void receiveVector(std::vector<T>& v, MPI_Datatype datatype, int source, int tag, MPI::Intracomm comm);
+
+   /*======================================================================*/  
+   // receive a vector of MPI_Datatype and adds this vector to existing vector
+   // ans returns number of received elements
+   template <class T>
+   inline int receiveVectorAndAddToVector(std::vector<T>& v, MPI_Datatype datatype, int source, int tag, MPI::Intracomm comm);
+
+   /*======================================================================*/  
+   // send a std::vector of strings
+   inline void sendStringVector(const std::vector<std::string>& v, int dest, int tag, MPI::Intracomm comm);
+
+   /*======================================================================*/  
+   // send a vector of strings
+   inline void receiveStringVector(std::vector<std::string>& v, int dest, int tag, MPI::Intracomm comm);
+};
+
+/*======================================================================*/  
+// send a single value of MPI_Datatype
+template <class T>
+void PbMpiTools::sendSingleValue(const T& value, MPI_Datatype datatype, int dest, int tag, MPI::Intracomm comm)
+{
+   try{ comm.Send(&value, 1, datatype, dest, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"catched with info at send size\n"+ss.str()) ); }
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send size") ); }
+}
+/*======================================================================*/  
+template <class T>
+void PbMpiTools::receiveSingleValue(T& value, MPI_Datatype datatype, int source, int tag, MPI::Intracomm comm) 
+{
+   try { comm.Recv(&value, 1, datatype, source, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss;ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at receive size\n"+ss.str()) );}
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at receive size") ); }
+}
+/*======================================================================*/  
+template <class T>
+T PbMpiTools::receiveSingleValue(MPI_Datatype datatype, int source, int tag, MPI::Intracomm comm) 
+{
+   T value;
+   try { comm.Recv(&value, 1, datatype, source, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss;ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at receive size\n"+ss.str()) );}
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at receive size") ); }
+
+   return value;
+}
+/*======================================================================*/  
+// send a bool value (bool doesn't work with template, why ever)
+void PbMpiTools::sendBoolValue(const bool& value,int dest, int tag, MPI::Intracomm comm)
+{
+   short dummy;
+   if(value) dummy=1;                  
+   else      dummy=0;
+
+   try{ comm.Send(&dummy, 1, MPI::SHORT, dest, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send size\n"+ss.str()) ); }
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send size") ); }
+}
+/*======================================================================*/  
+bool PbMpiTools::receiveBoolValue(int source, int tag, MPI::Intracomm comm) 
+{
+   short dummy;
+   try { comm.Recv(&dummy, 1, MPI::SHORT, source, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss;ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at receive size\n"+ss.str()) );}
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at receive size") ); }
+
+   return (dummy==1);
+}
+/*======================================================================*/  
+// sends bool value (doesn't work with template, why ever... stupid MPI)
+void PbMpiTools::sendStringValue(const std::string& value,int dest, int tag, MPI::Intracomm comm)
+{
+   std::vector<char> vec;
+   for(std::size_t i=0; i<value.size(); i++)
+      vec.push_back(value[i]);
+   PbMpiTools::sendVector(vec,MPI::CHAR,dest,tag,comm);
+}
+
+/*======================================================================*/  
+// receives bool value (doesn't work with template, why ever... stupid MPI)
+std::string PbMpiTools::receiveStringValue(int source, int tag, MPI::Intracomm comm)
+{
+   std::vector<char> vec;
+   PbMpiTools::receiveVector(vec,MPI::CHAR,source,tag,comm);
+   std::string str;
+   for(std::size_t i=0; i<vec.size(); i++)
+      str+=vec[i];
+
+   return str;
+}
+/*======================================================================*/  
+// send a vector of MPI_Datatype
+template <class T>
+void PbMpiTools::sendVector(const std::vector<T>& v, MPI_Datatype datatype, int dest, int tag, MPI::Intracomm comm)
+{
+   // send size
+   int size = (int)v.size();
+   
+   try{ comm.Send(&size, 1, MPI::INT, dest, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send size\n"+ss.str()) ); }
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send size") ); }
+   
+   if(size>0)
+	{
+      try{ comm.Send(&v[0], size, datatype, dest, tag); }
+      catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                                UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send vector<T>\n"+ss.str()) );}
+      catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send vector<T>") ); }
+   }
+}
+/*======================================================================*/  
+// receive a vector of MPI_Datatype
+template <class T>
+void PbMpiTools::receiveVector(std::vector<T>& v, MPI_Datatype datatype, int source, int tag, MPI::Intracomm comm) 
+{
+   int size;
+
+   try { comm.Recv(&size, 1, MPI::INT, source, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss;ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at receive size\n"+ss.str()) );}
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at receive size") ); }
+
+   v.resize(size);
+
+   if( size>0 )
+   {
+      try{ comm.Recv(&v[0], size, datatype, source, tag); }
+      catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                                UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at receive vector\n"+ss.str()) ); }
+      catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at receive vector") ); }
+   }
+}
+/*======================================================================*/  
+// receive a vector of MPI_Datatype and adds this vector to existing vector
+// return value is size of received elements
+template <class T>
+int PbMpiTools::receiveVectorAndAddToVector(std::vector<T>& v, MPI_Datatype datatype, int source, int tag, MPI::Intracomm comm) 
+{
+   int incommingSize;
+
+   try { comm.Recv(&incommingSize, 1, MPI::INT, source, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss;ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at receive size\n"+ss.str()) );}
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at receive size") ); }
+
+   int oldSize = (int)v.size();
+   v.resize(oldSize+incommingSize);
+
+   if( incommingSize>0 )
+   {
+      try{ comm.Recv(&v[oldSize], incommingSize, datatype, source, tag); }
+      catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                                UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at receive vector\n"+ss.str()) ); }
+      catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at receive vector") ); }
+   }
+
+   return incommingSize;
+}
+/*======================================================================*/  
+// send a vector of strings
+void PbMpiTools::sendStringVector(const std::vector<std::string>& v, int dest, int tag, MPI::Intracomm comm)
+{
+   // send size
+   int stringVectorSize = (int)v.size();
+
+   try{ comm.Send(&stringVectorSize, 1, MPI::INT, dest, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send size\n"+ss.str()) ); }
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send size") ); }
+
+   if(stringVectorSize>0)
+   {
+      std::vector<int> singleStringSizes(stringVectorSize+1);
+      int nofChars = 0;
+      for(int i=0; i<stringVectorSize; i++)
+         nofChars += singleStringSizes[i] = (int)v[i].length();
+      singleStringSizes[stringVectorSize] = nofChars;
+
+      try{ comm.Send(&singleStringSizes[0], stringVectorSize+1, MPI::INT, dest, tag); }
+      catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                                UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send vector<T>\n"+ss.str()) );}
+      catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send vector<T>") ); }
+
+      std::vector<char> charVector(nofChars);
+      int pos = 0;
+      for(int i=0; i<stringVectorSize; i++)
+         for(int j=0; j<singleStringSizes[i]; j++)
+            charVector[pos++] = v[i][j];      
+
+      try{ comm.Send(&charVector[0], nofChars, MPI::CHAR, dest, tag); }
+      catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                                UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send vector<T>\n"+ss.str()) );}
+      catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send vector<T>") ); }
+   }
+}
+/*======================================================================*/  
+// send a vector of strings
+void PbMpiTools::receiveStringVector(std::vector<std::string>& v, int source, int tag, MPI::Intracomm comm)
+{
+   // send size
+   int stringVectorSize;
+   try { comm.Recv(&stringVectorSize, 1, MPI::INT, source, tag); }
+   catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                             UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send size\n"+ss.str()) ); }
+   catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send size") ); }
+
+   v.clear();
+   v.resize(stringVectorSize);
+
+   if(stringVectorSize>0)
+   {
+      std::vector<int> singleStringSizes(stringVectorSize+1);
+
+      try{ comm.Recv(&singleStringSizes[0], stringVectorSize+1, MPI::INT, source, tag); }
+      catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                                UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send vector<T>\n"+ss.str()) );}
+      catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send vector<T>") ); }
+
+      int nofChars = singleStringSizes[stringVectorSize];
+      std::vector<char> charVector(nofChars);
+
+       try{ comm.Recv(&charVector[0], nofChars, MPI::CHAR, source, tag); }
+       catch(MPI::Exception& e){ std::stringstream ss; ss<<"MPI::Exception error_string="<<e.Get_error_string()<<std::endl;
+                                 UB_THROW( UbException(UB_EXARGS,"MPI:Exception catched with info at send vector<T>\n"+ss.str()) );}
+       catch(...)              { UB_THROW( UbException(UB_EXARGS,"unknown exception at send vector<T>") ); }
+      
+      int pos=0;
+      for(int i=0; i<stringVectorSize; i++)
+         for(int j=0; j<singleStringSizes[i]; j++)
+            v[i].push_back(charVector[pos++]);      
+   }
+}
+
+#endif
+
+#endif //PBMPITOOLS_H
diff --git a/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/CMakeLists.txt b/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2c93dee4f1f17b3084223e50c1f1628f2878e4df
--- /dev/null
+++ b/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/CMakeLists.txt
@@ -0,0 +1,64 @@
+cmake_minimum_required(VERSION 2.6)
+
+INCLUDE("../../../../CMakeCABMacros.txt")
+INCLUDE("../../../../CMakeSetCompilerFlags.txt")
+  
+CHECK_FOR_VARIABLE(CAB_MACHINE "machine name, e.g. ALTIX, ARWEN")
+SET(CMAKE_CONFIG_FILE "${SOURCE_ROOT}/cmake_config_files/${CAB_MACHINE}.config.cmake")
+
+PROJECT(simpleMPI)
+
+#erst hier das config file einfügen, ansonsten werden manche settings durch (Project) überschrieben)  
+INCLUDE(${CMAKE_CONFIG_FILE})  
+  
+SET(EXECUTABLE_NAME simpleMPI)
+
+################################################################
+##   PACKAGES						###
+################################################################
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/memory/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/parallel/CMakePackage.txt)
+   
+#################################################################
+###   OWN DEFINES 						###
+#################################################################
+SET(ALL_SOURCES ${ALL_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp )
+
+SOURCE_GROUP(main FILES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp )
+   
+ADD_CXX_FLAGS("/wd4996") #deprecated strcpy...
+
+#################################################################
+###   MPI                                                     ###
+#################################################################
+SET_MPI_STUFF(CAB_MACHINE)
+SET(EXECUTABLE_NAME ${EXECUTABLE_NAME}_mpi)
+
+#################################################################
+###   EXCECUTABLE						###
+#################################################################
+ADD_EXECUTABLE(${EXECUTABLE_NAME} ${ALL_SOURCES} )
+
+#################################################################
+###   ADDITIONAL LINK LIBRARIES                               ###
+#################################################################
+IF(ADDITIONAL_LINK_LIBRARIES)
+ TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME} ${ADDITIONAL_LINK_LIBRARIES}) 
+ENDIF(ADDITIONAL_LINK_LIBRARIES)
+
+#################################################################
+###   ADDITIONAL LINK PROPERTIES                              ###
+#################################################################
+IF(ADDITIONAL_LINK_PROPS)
+ SET_TARGET_PROPERTIES(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS ${ADDITIONAL_LINK_PROPS})
+ENDIF(ADDITIONAL_LINK_PROPS)
+IF(ADDITIONAL_LINK_PROPS_DEBUG)
+ SET_TARGET_PROPERTIES(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS_DEBUG ${ADDITIONAL_LINK_PROPS_DEBUG})
+ENDIF(ADDITIONAL_LINK_PROPS_DEBUG)
+IF(ADDITIONAL_LINK_PROPS_RELEASE)
+ SET_TARGET_PROPERTIES(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS_RELEASE ${ADDITIONAL_LINK_PROPS_RELEASE})
+ENDIF(ADDITIONAL_LINK_PROPS_RELEASE)
+
+
+
diff --git a/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/functions.h b/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/functions.h
new file mode 100644
index 0000000000000000000000000000000000000000..3977c69e00299b64773cb0ff16dc4ed536c37ca6
--- /dev/null
+++ b/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/functions.h
@@ -0,0 +1,193 @@
+#include <iostream>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string>
+#include <fstream>
+
+#include <basics/utilities/UbTuple.h>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <basics/utilities/UbTiming.h>
+
+#include <basics/memory/MbSmartPtr.h>
+
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+
+typedef long double value_type;
+typedef MbSmartPtr<CbVector< value_type > > CbVectorPtr;
+typedef MbSmartPtr<vector< value_type > >   StlVectorPtr;
+
+/*==========================================================*/
+template<typename T>
+inline void setValues(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec)
+{
+   if(stlvec.size() != cbvec.size() || stlvec.size() != cbpoolvec.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvec.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvec.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvec.size()<<endl;
+      throw UB_THROW( UbException("setValues - sizeCheck failed") );
+   }
+   static value_type stlVal    = 1;
+   static value_type cbVal     = 1;
+   static value_type cbPoolVal = 1;
+
+   for(size_t i=0; i<cbvec.size(); i++) stlvec[i]    = stlVal   ++;
+   for(size_t i=0; i<cbvec.size(); i++) cbvec[i]     = cbVal    ++;
+   for(size_t i=0; i<cbvec.size(); i++) cbpoolvec[i] = cbPoolVal++;
+}
+/*==========================================================*/
+template<typename T>
+inline void setValues(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      UB_THROW( UbException("setValues glob - sizeCheck failed") );
+   }
+
+   for(size_t i=0; i<cbvecs.size(); i++)
+      setValues(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i]);
+}
+/*==========================================================*/
+template<typename T>
+inline void resize(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec, std::size_t size, const T& val)
+{
+   stlvec.resize(size,val);
+   cbvec.resize(size,val);
+   cbpoolvec.resize(size,val);
+}
+/*==========================================================*/
+template<typename T>
+inline void resize(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, std::size_t size, const value_type& val, bool timed=false)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      UB_THROW( UbException("resize glob - sizeCheck failed") );
+   }
+
+   if(timed)
+   {
+      UbTimer timer;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) stlvecs[i]->resize(size,val);    if(timed) cout<<"stl-resize    in "<<timer.stop()<<"s"<<endl;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) cbvecs[i]->resize(size,val);     if(timed) cout<<"cbStd-resize  in "<<timer.stop()<<"s"<<endl;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) cbpoolvecs[i]->resize(size,val); if(timed) cout<<"cbPool-resize in "<<timer.stop()<<"s"<<endl;
+   }
+   else
+   {
+      for(size_t i=0; i<cbvecs.size(); i++)
+         resize(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i],size,val);
+   }
+}
+/*==========================================================*/
+template<typename T>
+inline void createVecs(size_t number, int size,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, CbVectorPool<value_type>*& pool, bool timed=false)
+{
+   UbTimer timer;
+   timer.start(); for(size_t i=0; i<number; i++) stlvecs.push_back(StlVectorPtr(new vector<value_type>(size)));                                                  if(timed) cout<<"stl-createVecs    in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbvecs.push_back(CbVectorPtr(new CbVector<value_type>(size)));                                                  if(timed) cout<<"cbStd-createVecs  in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbpoolvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorPool<value_type>(pool))));  if(timed) cout<<"cbPool-createVecs in "<<timer.stop()<<"s"<<endl;
+
+   for(size_t i=0; i<cbvecs.size(); i++) setValues(*stlvecs.back(),*cbvecs.back(),*cbpoolvecs.back());
+}
+/*==========================================================*/
+template<typename T>
+inline void createVecs(size_t number, size_t size, const value_type& val,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, CbVectorPool<value_type>*& pool, bool timed=false)
+{
+   UbTimer timer;
+   timer.start(); for(size_t i=0; i<number; i++) stlvecs.push_back(StlVectorPtr(new vector<value_type>(size,val)));                                                  if(timed) cout<<"stl-createVecs    in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorStd<value_type>(),val)));           if(timed) cout<<"cbStd-createVecs  in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbpoolvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorPool<value_type>(pool),val)));  if(timed) cout<<"cbPool-createVecs in "<<timer.stop()<<"s"<<endl;
+}
+/*==========================================================*/
+template<typename T>
+inline void equalCheck(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec)
+{
+   if(stlvec.size() != cbvec.size() || stlvec.size() != cbpoolvec.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvec.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvec.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvec.size()<<endl;
+      throw UB_THROW( UbException("equalCheck - sizeCheck failed") );
+   }
+
+   bool check=true;
+   for(size_t i=0; i<cbvec.size(); i++)
+      if(stlvec[i] != cbvec[i] || stlvec[i] != cbpoolvec[i]  )
+         check=false;
+
+   if(!check)
+   {
+      cerr<<"\nstl - "; for(size_t i=0; i<cbvec.size(); i++) cout<<stlvec[i]<<" ";    cout<<endl;
+      cerr<<  "cbv - "; for(size_t i=0; i<cbvec.size(); i++) cout<<cbvec[i]<<" ";     cout<<endl;
+      cerr<<  "cbp - "; for(size_t i=0; i<cbvec.size(); i++) cout<<cbpoolvec[i]<<" "; cout<<endl;
+      throw UB_THROW( UbException("equalCheck - equalCheck failed") );
+   }
+}
+/*==========================================================*/
+template<typename T>
+void equalCheck(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      UB_THROW( UbException("equalCheck - sizeCheck failed") );
+   }
+
+   for(size_t i=0; i<cbvecs.size(); i++)
+   {
+      //cout<<"equalCheck i="<<i<<"/"<<cbvecs.size()-1;
+      equalCheck(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i]);
+      //cout<<" passed"<<endl;
+   }
+}
+/*==========================================================*/
+template<typename T>
+void accessCheck(int times,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   UbTimer timer;
+   timer.start();
+   for(size_t i=0; i<stlvecs.size(); i++)
+   {
+      vector<value_type>& vec = *stlvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"stl-accessCheck       in "<<timer.stop()<<"s"<<endl;
+   timer.start();
+   for(size_t i=0; i<cbvecs.size(); i++)
+   {
+      CbVector<value_type>& vec = *cbvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"cbStd-accessCheck     in "<<timer.stop()<<"s"<<endl;
+   timer.start();
+   for(size_t i=0; i<cbpoolvecs.size(); i++)
+   {
+      CbVector<value_type>& vec = *cbpoolvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"cbPool-accessCheck    in "<<timer.stop()<<"s"<<endl;
+}
diff --git a/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/main.cpp b/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ff9dfcbfd4d458d1bfac99df9bf7fea0a4f2374
--- /dev/null
+++ b/source/ThirdParty/Library/basics/parallel/examples/simpleMPI/main.cpp
@@ -0,0 +1,101 @@
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <mpi.h>
+
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+
+int randomNumber () { return (rand()%100); }
+
+struct RankSetter{
+   RankSetter(int rank) : rank(rank) {}
+   
+   int operator()() 
+   {
+      return rank;
+   }
+  
+   int rank;
+} /*rankSetter*/;
+
+
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char** argv)
+{
+   MPI::Init(argc, argv);
+   MPI::COMM_WORLD.Set_errhandler(MPI::ERRORS_THROW_EXCEPTIONS); 
+
+   try
+   {  
+      MPI::Intracomm comm = MPI::COMM_WORLD;
+      
+      int rank = comm.Get_rank();
+      
+      vector<int> sendData(1000,0);
+      generate(sendData.begin(), sendData.end(), RankSetter(rank+1) );
+
+      vector<int> recvData(1000,0);
+
+      if(rank==0)
+      {
+         UBLOG(logINFO,"rank="<<rank<<" - recv request");
+         MPI::Request request = comm.Irecv(&recvData[0], (int)recvData.size(), MPI::INT, 1, 100);
+         UBLOG(logINFO,"rank="<<rank<<" - sendData");
+         comm.Ssend(&sendData[0],(int)sendData.size(), MPI::INT, 1, 100);
+         sendData.back() = 999;
+
+         UBLOG(logINFO,"rank="<<rank<<" - Wait");
+         request.Wait();
+         UBLOG(logINFO,"rank="<<rank<<" - all data received, last = "<<recvData.back());
+      }
+      else if(rank == 1)
+      {
+         UbSystem::sleepS(5);
+         UBLOG(logINFO,"rank="<<rank<<" - recv request");
+         MPI::Request request = comm.Irecv(&recvData[0],(int)recvData.size(), MPI::INT, 0, 100);
+         
+         request.Wait();
+         UBLOG(logINFO,"rank="<<rank<<" - all data received, last = "<<recvData.back());
+
+         UbSystem::sleepS(5);
+         UBLOG(logINFO,"rank="<<rank<<" - sendData");
+         comm.Ssend(&sendData[0],(int)sendData.size(), MPI::INT, 0, 100);
+         sendData.back() = 999;
+         UBLOG(logINFO,"rank="<<rank<<" - data sent");
+      }
+      else 
+      {
+         throw UB_THROW( UbException(UB_EXARGS,"only two ranks allwoed") );
+      }
+
+      UBLOG(logINFO,"rank="<<rank<<" barrier start");
+      MPI::COMM_WORLD.Barrier();
+      UBLOG(logINFO,"rank="<<rank<<" barrier done ");
+
+   }
+   catch(const std::exception& e)
+   {
+      UBLOG2(  logERROR,std::cerr, "caught exception:" );
+      UBLOG2(  logERROR,std::cerr, "type: " << typeid(e).name() );
+      UBLOG2ML(logERROR,std::cerr, "what: " << e.what() );
+   }
+   catch(MPI::Exception e)
+   { 
+      UBLOG2ML(logERROR,std::cerr, "caught exception:" << e.Get_error_string());
+
+      MPI::COMM_WORLD.Abort(99); 
+   } 
+   catch(...)
+   {
+      UBLOG2(logERROR,std::cerr,"Verdammte Scheisse - mal wieder Mist gebaut!");
+   }
+
+   MPI::Finalize();
+
+   return 0;
+}
+
diff --git a/source/ThirdParty/Library/basics/relation/CMakePackage.txt b/source/ThirdParty/Library/basics/relation/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/ThirdParty/Library/basics/relation/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/ThirdParty/Library/basics/relation/RbAggregation.h b/source/ThirdParty/Library/basics/relation/RbAggregation.h
new file mode 100644
index 0000000000000000000000000000000000000000..409336c9ec9f2d4ec31e5151c61bf7afe08fabd8
--- /dev/null
+++ b/source/ThirdParty/Library/basics/relation/RbAggregation.h
@@ -0,0 +1,70 @@
+#ifndef RBAGGREGATION_H
+#define RBAGGREGATION_H
+
+#include <sstream>
+#include <iostream>
+#include <map>
+
+using namespace std;
+
+template <class T1, class T2>
+class RbAggregation 
+{
+private:
+   string name;
+   std::multimap<T1,T2> obj1Map;
+   std::multimap<T2,T1> obj2Map;
+                       
+public:
+   RbAggregation(string name)
+   {
+      this->name = name;
+   }
+   /*=========================================================================*/
+   void insertPair(T1& to1, T2& to2)
+   {
+      obj1Map.insert(pair<T1,T2>(to1,to2));
+      obj2Map.insert(pair<T2,T1>(to2,to1));
+   }     
+   /*=========================================================================*/
+   int countObj2forObj1(T1& to1)
+   {                                                                
+      return((int)obj1Map.count(to1));
+   }
+
+   /*=========================================================================*/
+   int countObj1forObj2(T2& to2)
+   {
+      return((int)obj2Map.count(to2));
+   }
+   /*=========================================================================*/
+   vector<T2> getObj2vectorForObj1(T1& to1)
+   {
+      vector<T2> obj2vector;
+      unsigned number = (unsigned)obj1Map.count(to1);
+      typedef std::multimap<T1, T2>::iterator obj1MapIterator = obj1Map.find(to1);
+      for(unsigned u =0; u<number; u++) 
+      {
+         obj2vector.push_back(obj1MapIterator->second);
+         obj1MapIterator++;
+      }
+      return obj2vector;
+   }
+   ///*=========================================================================*/
+   vector<T1>  getObj1vectorForObj2(T2& to2)
+   {
+      vector<T1> obj1vector;
+      unsigned number = (unsigned)obj2Map.count(to2);
+      typedef std::multimap<T2, T1>::iterator obj2MapIterator = obj2Map.find(to2);
+      for(unsigned u =0; u<number; u++) 
+      {
+         obj1vector.push_back(obj2MapIterator->second);
+         obj2MapIterator++;
+      }
+      return obj1vector;
+   }
+};
+/*=========================================================================*/
+#endif
+
+
diff --git a/source/ThirdParty/Library/basics/transmitter/CMakePackage.txt b/source/ThirdParty/Library/basics/transmitter/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de1dc5a88225180b8e40c6cf46f4a6fbb102778f
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
\ No newline at end of file
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitter.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitter.h
new file mode 100644
index 0000000000000000000000000000000000000000..9560e8a771c5c4892579aa38d119bca67c45a354
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitter.h
@@ -0,0 +1,69 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTER_H
+#define TBTRANSMITTER_H
+
+#include <string>
+
+/*================================================================================*/
+/*  TbTransmitter                                                                 */
+/*                                                                                */
+/**
+This Class provides the base for sending and receiving of data.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+*/ 
+
+/*
+usage: ...
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// Transmitter 
+// macht nichts ausser daten senden und empfangen
+template<typename T>
+class TbTransmitter
+{
+public:
+   typedef T value_type;
+
+public:
+   TbTransmitter() {}
+   virtual ~TbTransmitter()  {  /*std::cout<<typeid(*this).name()<<" dtor"<<std::endl;*/  }
+
+   virtual bool isLocalTransmitter()  const = 0;
+   virtual bool isRemoteTransmitter() const = 0;
+
+   //preprocess (e.g. synchronizing send-/receive-buffer)
+   virtual void sendDataSize()   = 0;
+   virtual void receiveDataSize()= 0; 
+   
+   //calculation
+   virtual void        prepareForSend() {}
+   virtual void        sendData()=0;
+   virtual void        prepareForReceive() {}
+   virtual value_type& receiveData()=0;
+   virtual void        saveData() {}
+
+   //data-access
+   inline value_type&       getData()       { return this->data; }
+   inline const value_type& getData() const { return this->data; }
+
+   //info-section (usable for remote transmitter)
+   virtual int  getSendToRank()   const { return  -1; }
+   virtual int  getSendToTag()    const { return  -1; }
+   virtual int  getRecvFromRank() const { return  -1; }
+   virtual int  getRecvFromTag()  const { return  -1; }
+
+   virtual std::string toString() const = 0;
+
+protected:
+   value_type data;
+};
+
+#endif //TBTRANSMITTER_H 
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterLocal.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterLocal.h
new file mode 100644
index 0000000000000000000000000000000000000000..981f880c143d4ed614dfc8cc2c20e6684de91f8a
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterLocal.h
@@ -0,0 +1,130 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TOTRANSMITTERLOCAL_H
+#define TOTRANSMITTERLOCAL_H
+
+#include <basics/utilities/UbException.h>
+#include <basics/transmitter/TbTransmitter.h>
+
+#include <boost/shared_ptr.hpp>
+
+/*================================================================================*/
+/*   TbLocalTransmitter, TbVectorSenderLocal, TbVectorReceiverLocal               */
+/*                                                                                */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+*/ 
+
+/*
+usage: ...
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// LocalTransmitter lokalen Datenaustausch
+// data = send- und zugleich receive-buffer
+template<typename T>
+class TbLocalTransmitter : public TbTransmitter<T>
+{
+public:
+   typedef boost::shared_ptr< TbLocalTransmitter<T> > TbLocalTransmitterPtr;
+
+   typedef T value_type;
+
+public:
+   TbLocalTransmitter() : TbTransmitter<T>() 
+   {
+
+   }
+   
+   bool isLocalTransmitter()  const { return true;                         }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   //send buffer wird autom resized
+   void sendDataSize()    { }
+   //reiceive braucht nichts machen, da send==receive buffer ;-)
+   void receiveDataSize() { } 
+
+   void        sendData()    { }
+   value_type& receiveData() { return this->data; }
+
+   std::string toString()  const { return "TbLocalTransmitter"+(std::string)typeid(T).name(); }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSender/ReceiverLocal lokalen Datenaustausch ueber ZWEI vektoren
+template<typename T>
+class TbVectorReceiverLocal : public TbTransmitter<T>
+{
+public:
+   typedef T value_type;
+
+public:
+   TbVectorReceiverLocal() : TbTransmitter<value_type>() 
+   {
+
+   }
+   //virtual ~TbVectorReceiverLocal() { std::cout<<typeid(*this).name()<<" tot"<<std::endl;   }
+
+   bool isLocalTransmitter()  const { return true;                         }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   //send buffer wird autom resized
+   void sendDataSize()    { UB_THROW( UbException(UB_EXARGS,"empfaengt nur") ); }
+   //reiceive braucht nichts machen, das macht der sender :-)
+   void receiveDataSize() { } 
+
+   void         sendData()    { UB_THROW( UbException(UB_EXARGS,"empfaengt nur") ); }
+   value_type&  receiveData() { return this->data; }
+
+   std::string toString() const { return "TbVectorReceiverLocal<"+(std::string)typeid(T).name()+">"; }
+};
+
+template<typename T>
+class TbVectorSenderLocal : public TbTransmitter<T>
+{
+public:
+   typedef T value_type;
+
+public:
+   TbVectorSenderLocal(boost::shared_ptr< TbVectorReceiverLocal< value_type > > receiver) 
+      : TbTransmitter< value_type >(), receiver(receiver) 
+   {
+
+   }
+   //virtual ~TbVectorSenderLocal() { std::cout<<typeid(*this).name()<<" tot"<<std::endl;   }
+
+   bool isLocalTransmitter()  const { return true;                         }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   //send buffer wird autom resized
+   void sendDataSize()  
+   { 
+      assert(receiver!=NULL); 
+      receiver->getData().resize( this->data.size() ); 
+   }
+   //reiceive braucht nichts machen, da send==receive buffer ;-)
+   void receiveDataSize()  { UB_THROW( UbException(UB_EXARGS,"sendet nur") ); } 
+   
+   void sendData()    
+   { 
+      assert( this->data.size() == receiver->getData().size() );
+      receiver->getData() = this->data;
+//       for(int i=(int)this->data.size()-1; i>=0; --i)
+//          receiver->getData()[i]= this->data[i];
+   }
+   value_type& receiveData() { UB_THROW( UbException(UB_EXARGS,"sendet nur") ); }
+
+   std::string toString() const { return "TbVectorSenderLocal<"+(std::string)typeid(T).name()+">"; }
+
+protected:
+   boost::shared_ptr< TbVectorReceiverLocal< value_type > > receiver; 
+};
+                                        
+#endif //TOTRANSMITTERLOCAL_H 
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpi.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpi.h
new file mode 100644
index 0000000000000000000000000000000000000000..16d5f8c7f986b9b6832f999be80f6ee5dc81aa76
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpi.h
@@ -0,0 +1,237 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPI_H
+#define TBTRANSMITTERMPI_H
+
+#ifdef VF_MPI
+
+/*=========================================================================*/
+/*  MPI Transmitter                                                        */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+Old TbTransmitter was renamed in TbTransmitterCPPB (C++ binding in MPI is deprecated)
+Rewrite from K. Kucher with C binding
+<BR><BR>
+@author <A HREF="mailto:kucher@irmb.tu-bs.de">K. Kucher</A>
+@version 1.0 - 21.11.11
+*/ 
+
+/*
+usage: ...
+*/
+
+#include <iostream>
+#include <mpi.h>
+#include <basics/transmitter/TbTransmitter.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderMpiUnblocked
+template< typename Vector  >
+class TbVectorSenderMpiUnblocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorSenderMpiUnblocked(const int& sendTbRank, const int& sendTag, MPI_Comm comm) 
+      : comm(comm), request(MPI_REQUEST_NULL), sendTbRank(sendTbRank), sendTag(sendTag), dataSize(0)    
+   { 
+      //temporaeren vector erstellen um den datentyp zu ermittlen
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for type="+(std::string)typeid(typename Vector::value_type).name()) );
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()   
+   {
+      dataSize = (unsigned int)this->getData().size();
+      //MPI_Isend(&dataSize, 1, MPI_UNSIGNED, sendTbRank, sendTag, comm, &request);
+      MPI_Send(&dataSize, 1, MPI_UNSIGNED, sendTbRank, sendTag, comm);
+   }  
+   void receiveDataSize()   { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   void prepareForSend()    { if(request!=MPI_REQUEST_NULL) MPI_Wait(&request, &status); }
+   void sendData()          { MPI_Isend(&this->getData()[0],(int)this->getData().size(), mpiDataType, sendTbRank, sendTag, comm, &request);  }
+
+   void prepareForReceive() { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   Vector& receiveData()    { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  sendTbRank; }
+   int  getSendTbTag()    const { return  sendTag;    }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   std::string toString()  const { return "TbVectorSenderMpiUnblocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(sendTbRank)+"("+UbSystem::toString(sendTag)+")"; }
+
+protected:
+   MPI_Comm comm;
+   MPI_Request   request;
+   MPI_Datatype  mpiDataType;
+   MPI_Status    status;
+   int sendTbRank, sendTag;
+   unsigned dataSize;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderMpiBlocked
+template< typename Vector  >
+class TbVectorSenderMpiBlocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorSenderMpiBlocked(const int& sendTbRank, const int& sendTag, MPI_Comm comm) 
+      : comm(comm), request(MPI_REQUEST_NULL), sendTbRank(sendTbRank), sendTag(sendTag), dataSize(0)    
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector"+(std::string)typeid(Vector).name()) );
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()   
+   {
+      dataSize = (unsigned int)this->getData().size();
+      MPI_Isend(&dataSize, 1, MPI_UNSIGNED, sendTbRank, sendTag, comm, &request);
+   }  
+   void receiveDataSize()   { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   void sendData()          { MPI_Wait(&request, &status); MPI_Send(&this->getData()[0],(int)this->getData().size(), mpiDataType, sendTbRank, sendTag, comm); }
+
+   void prepareForReceive()  { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   value_type& receiveData() { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  sendTbRank; }
+   int  getSendTbTag()    const { return  sendTag;    }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   std::string toString() const { return "TbVectorSenderMpiBlocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(sendTbRank)+"("+UbSystem::toString(sendTag)+")"; }
+
+protected:
+   MPI_Comm comm;
+   MPI_Request   request;
+   MPI_Datatype  mpiDataType;
+   MPI_Status    status;
+   int sendTbRank, sendTag;
+   unsigned dataSize;
+};
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorReceiverMpiUnblocked
+template<typename Vector  >
+class TbVectorReceiverMpiUnblocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorReceiverMpiUnblocked(const int& receiveFromRank, const int& receiveTag, MPI_Comm comm) 
+      : comm(comm), request(MPI_REQUEST_NULL), receiveFromRank(receiveFromRank), receiveTag(receiveTag)       
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector"+(std::string)typeid(Vector).name()) );
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()     { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   void receiveDataSize()   
+   {
+      unsigned dataSize;
+      MPI_Recv(&dataSize, 1, MPI_UNSIGNED, receiveFromRank, receiveTag, comm, &status);
+      this->getData().resize(dataSize,0.0);
+   }  
+   void sendData()          { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+
+   void prepareForReceive() { MPI_Irecv(&this->getData()[0],(int)this->getData().size(), mpiDataType, receiveFromRank, receiveTag, comm, &request);  }
+   Vector& receiveData()    { MPI_Wait(&request, &status); return this->getData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getSendTbTag()    const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getRecvFromRank() const { return  receiveFromRank; }
+   int  getRecvFromTag()  const { return  receiveTag;      }
+
+   std::string toString() const { return "TbVectorReceiverMpiUnblocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(receiveFromRank)+"("+UbSystem::toString(receiveTag)+")"; }
+
+protected:
+   MPI_Comm comm;
+   MPI_Request   request;
+   MPI_Datatype  mpiDataType;
+   MPI_Status    status;
+   int receiveFromRank, receiveTag;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+template<typename Vector>
+class TbVectorReceiverMpiBlocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorReceiverMpiBlocked(const int& receiveFromRank, const int& receiveTag, MPI_Comm comm) 
+      : comm(comm), request(MPI_REQUEST_NULL), receiveFromRank(receiveFromRank), receiveTag(receiveTag)
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector+(std::string)typeid(Vector).name()") );
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()     { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   void receiveDataSize()   
+   {
+      unsigned dataSize;
+      MPI_Recv(&dataSize, 1, MPI_UNSIGNED, receiveFromRank, receiveTag, comm, &status);
+      this->getData().resize(dataSize,0.0);
+   }  
+   void sendData()         { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   Vector& receiveData()
+   {
+      MPI_Recv(&this->getData()[0],(int)this->getData().size(), mpiDataType, receiveFromRank, receiveTag, comm, &status);
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getSendTbTag()    const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getRecvFromRank() const { return  receiveFromRank; }
+   int  getRecvFromTag()  const { return  receiveTag;      }
+
+   std::string toString() const { return "TbVectorReceiverMpiBlocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(receiveFromRank)+"("+UbSystem::toString(receiveTag)+")"; }
+
+protected:
+   MPI_Comm comm;
+   MPI_Request   request;
+   MPI_Datatype  mpiDataType;
+   MPI_Status    status;
+   int receiveFromRank, receiveTag;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPI_H
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiCPPB.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiCPPB.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a08a867cb24be0dbbace7570756a5283daf953b
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiCPPB.h
@@ -0,0 +1,230 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPICPPB_H
+#define TBTRANSMITTERMPICPPB_H
+
+#ifdef VF_MPI
+
+/*=========================================================================*/
+/*  MPI Transmitter                                                        */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+*/ 
+
+/*
+usage: ...
+*/
+
+#include <iostream>
+#include <mpi.h>
+#include <basics/transmitter/TbTransmitter.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderMpiUnblocked
+template< typename Vector  >
+class TbVectorSenderMpiUnblocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorSenderMpiUnblocked(const int& sendTbRank, const int& sendTag, MPI::Intracomm comm) 
+      : comm(comm), request(MPI::REQUEST_NULL), sendTbRank(sendTbRank), sendTag(sendTag), dataSize(0)    
+   { 
+      //temporaeren vector erstellen um den datentyp zu ermittlen
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for type="+(std::string)typeid(typename Vector::value_type).name()) );
+   }
+   
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()   
+   {
+      dataSize = (unsigned int)this->getData().size();
+      request = comm.Isend(&dataSize, 1, MPI::UNSIGNED, sendTbRank, sendTag);
+   }  
+   void receiveDataSize()   { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   void prepareForSend()    { if(request!=MPI::REQUEST_NULL) request.Wait(); }
+   void sendData()          { request = comm.Isend(&this->getData()[0],(int)this->getData().size(), mpiDataType, sendTbRank, sendTag);  }
+   
+   void prepareForReceive() { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   Vector& receiveData()    { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  sendTbRank; }
+   int  getSendTbTag()    const { return  sendTag;    }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   std::string toString()  const { return "TbVectorSenderMpiUnblocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(sendTbRank)+"("+UbSystem::toString(sendTag)+")"; }
+
+protected:
+   MPI::Intracomm comm;
+   MPI::Request   request;
+   MPI::Datatype  mpiDataType;
+   int sendTbRank, sendTag;
+   unsigned dataSize;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderMpiBlocked
+template< typename Vector  >
+class TbVectorSenderMpiBlocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorSenderMpiBlocked(const int& sendTbRank, const int& sendTag, MPI::Intracomm comm) 
+      : comm(comm), request(MPI::REQUEST_NULL), sendTbRank(sendTbRank), sendTag(sendTag), dataSize(0)    
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector"+(std::string)typeid(Vector).name()) );
+   }
+   
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()   
+   {
+      dataSize = (unsigned int)this->getData().size();
+      request = comm.Isend(&dataSize, 1, MPI::UNSIGNED, sendTbRank, sendTag);
+   }  
+   void receiveDataSize()   { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   void sendData()          { request.Wait(); comm.Send(&this->getData()[0],(int)this->getData().size(), mpiDataType, sendTbRank, sendTag); }
+   
+   void prepareForReceive()  { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   value_type& receiveData() { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  sendTbRank; }
+   int  getSendTbTag()    const { return  sendTag;    }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   std::string toString() const { return "TbVectorSenderMpiBlocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(sendTbRank)+"("+UbSystem::toString(sendTag)+")"; }
+
+protected:
+   MPI::Intracomm comm;
+   MPI::Request   request;
+   MPI::Datatype  mpiDataType;
+   int sendTbRank, sendTag;
+   unsigned dataSize;
+};
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorReceiverMpiUnblocked
+template<typename Vector  >
+class TbVectorReceiverMpiUnblocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorReceiverMpiUnblocked(const int& receiveFromRank, const int& receiveTag, MPI::Intracomm comm) 
+      : comm(comm), request(MPI::REQUEST_NULL), receiveFromRank(receiveFromRank), receiveTag(receiveTag)       
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector"+(std::string)typeid(Vector).name()) );
+   }
+   
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()     { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   void receiveDataSize()   
+   {
+      unsigned dataSize;
+      comm.Recv(&dataSize, 1, MPI::UNSIGNED, receiveFromRank, receiveTag);
+      this->getData().resize(dataSize,0.0);
+   }  
+   void sendData()          { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   
+   void prepareForReceive() { request = comm.Irecv(&this->getData()[0],(int)this->getData().size(), mpiDataType, receiveFromRank, receiveTag);  }
+   Vector& receiveData()    { request.Wait(); return this->getData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getSendTbTag()    const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getRecvFromRank() const { return  receiveFromRank; }
+   int  getRecvFromTag()  const { return  receiveTag;      }
+
+   std::string toString() const { return "TbVectorReceiverMpiUnblocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(receiveFromRank)+"("+UbSystem::toString(receiveTag)+")"; }
+
+protected:
+   MPI::Intracomm comm;
+   MPI::Request   request;
+   MPI::Datatype  mpiDataType;
+   int receiveFromRank, receiveTag;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+template<typename Vector>
+class TbVectorReceiverMpiBlocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorReceiverMpiBlocked(const int& receiveFromRank, const int& receiveTag, MPI::Intracomm comm) 
+      : comm(comm), request(MPI::REQUEST_NULL), receiveFromRank(receiveFromRank), receiveTag(receiveTag)
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector+(std::string)typeid(Vector).name()") );
+   }
+   
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()     { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   void receiveDataSize()   
+   {
+      unsigned dataSize;
+      comm.Recv(&dataSize, 1, MPI::UNSIGNED, receiveFromRank, receiveTag);
+      this->getData().resize(dataSize,0.0);
+   }  
+   void sendData()         { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   Vector& receiveData()
+   {
+      comm.Recv(&this->getData()[0],(int)this->getData().size(), mpiDataType, receiveFromRank, receiveTag);
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getSendTbTag()    const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getRecvFromRank() const { return  receiveFromRank; }
+   int  getRecvFromTag()  const { return  receiveTag;      }
+
+   std::string toString() const { return "TbVectorReceiverMpiBlocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(receiveFromRank)+"("+UbSystem::toString(receiveTag)+")"; }
+
+protected:
+   MPI::Intracomm comm;
+   MPI::Request   request;
+   MPI::Datatype  mpiDataType;
+   int receiveFromRank, receiveTag;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPI_H
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd406ac49c4c49bd5245ea5a483bffb40fbbf75b
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool.h
@@ -0,0 +1,510 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPIPOOL_H
+#define TBTRANSMITTERMPIPOOL_H
+
+#ifdef VF_MPI
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+#include <boost/shared_ptr.hpp>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorMpiPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder MpiPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbMpiVectorPool verwaltet
+//MpiPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderMpiPool;
+template<typename T> class TbCbVectorReceiverMpiPool;
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorMpiPool : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorMpiPool< T > > MpiPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map<unsigned int, MpiPoolPtr >      MpiPoolPtrMap;
+   typedef typename MpiPoolPtrMap::iterator MpiPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned int CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderMpiPool< T >; 
+   friend class TbCbVectorReceiverMpiPool< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static MpiPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createTbCbVectorMpiPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   // mpiRemoteRank: mpi-rank des Empfaengers/Senders
+   // mpiTag       : mpi-tag mit dem empfangen/gesendet wird
+   static MpiPoolPtr createTbCbVectorMpiPool(CbVectorKey poolKey, int mpiRemoteRank, int mpiTag, MPI_Comm comm, size_type startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+
+      //pool erstellen
+      MpiPoolPtr mpiPool(new TbCbVectorMpiPool<T>(poolKey, mpiRemoteRank, mpiTag, comm, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorMpiPool< value_type >::poolMap[poolKey] = mpiPool;
+
+      return mpiPool; 
+   }
+   static void deleteTbCbVectorMpiPool(CbVectorKey poolKey)
+   {
+      MpiPoolPtrMapIter it = TbCbVectorMpiPool< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorMpiPool< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static MpiPoolPtr getTbCbVectorMpiPool(CbVectorKey poolKey)
+   {
+      MpiPoolPtrMapIter it;
+      if( (it=TbCbVectorMpiPool< T >::poolMap.find(poolKey))!=TbCbVectorMpiPool< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return MpiPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorMpiPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void eraseMap()
+   {
+      poolMap.clear();
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   TbCbVectorMpiPool(CbVectorKey poolKey, int mpiRemoteRank, int mpiTag, MPI_Comm comm, size_type startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI_REQUEST_NULL)
+      , sendRequest(MPI_REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+
+public:
+   /*==================================================================*/
+   //returns key of Pool in MpiPoolMap
+   CbVectorKey  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->mpiRemoteRank; }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->mpiTag;        }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         //allg.: bei MPI muss man darauf achten, dass bei unblocked operationen die puffer (aus dem oder in den 
+         //geschrieben wird auch noch vorhanden sind!!! wuerde man hier z.B. einen lokalen vector mit Isend() los-
+         //schicken, dann wurde der scope verlassen werden und der vector evtl geloescht werden, bevor mpi den
+         //vorgang abgeschlossen hat!!! ->  tmpOrderVec ist class-member!!!
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         unsigned index = 0;
+         tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+         MPI_Isend(&tmpSendOrderVec[0],(int)tmpSendOrderVec.size(), MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, &sendRequest);
+
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         //receiveRequest.Wait();
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+
+         //MPI_Status status;
+         MPI_Recv(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, MPI_STATUS_IGNORE);
+
+         if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+            throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+            //if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               //throw UbException(UB_EXARGS, "entweder hat map nicht die gleiche reihenfolge oder vectorKey = "+UbSystem::toString(vectorKey)+" nicht vorhanden");
+            if (it==this->cbVectorMap.end())
+               throw UbException(UB_EXARGS,"map ist leer");
+            else if (it->first != vectorKey)
+               throw UbException(UB_EXARGS, "vectorKey = "+UbSystem::toString(vectorKey)+" nicht vorhanden it->first =" + UbSystem::toString(it->first));
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&sendRequest, MPI_STATUS_IGNORE);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+
+
+      //A - non blocking
+      ////der ERSTE is entscheidend 
+      ////Grund: wenn man 
+      //// for(all trans) { trans->prepare(); trans->fillBuffer(); }
+      //// aufruft, dann wuerde u.U. der Buffer neu beschrieben werden obwohl noch nicht versendet wurde!!!
+      //counterPrepareForSend++;
+      //if(counterPrepareForSend==1)
+      //{
+      //   if(sendRequest != MPI::REQUEST_NULL) sendRequest.Wait();
+      //}
+      //
+      //if(counterPrepareForSend==nofStoredVectors)
+      //   counterPrepareForSend=0;  
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      //A - non blocking
+      //der LETZTE is entscheidend 
+      //counterSend++;
+      //if(counterSend==nofStoredVectors)
+      //{
+      //   //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+      //   sendRequest = comm.Isend(&pool[0],(int)nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //   counterSend=0;
+      //}
+      //B - blocking
+      //der LETZTE is entscheidend 
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+         //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         //synchronous send 
+         //comm.Ssend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+
+         //standard send
+         MPI_Send(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+////////////////////////////////////////////////////////////////////////////////////////////
+//DEBUG///////////////////////////////////////
+         //int irank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &irank);
+         //std::cout << "MPI_Send: " << irank <<  " "  << mpiRemoteRank << " "  <<mpiTag<<std::endl;
+///////////////////////////////////////////////////
+         counterSend=0;
+      }                           
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+      //A - non blocking
+      //sobald der Letzte kann man den den request holen.
+      //andernfalls kann nicht gewaehrleistet werden, dass evtl noch mit dem buffer gearbeitet wird!!!
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         MPI_Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         counterPrepareForReceive=0;
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      //A - non blocking
+      //sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      //denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      if(counterReceive==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+      counterReceive++;
+      if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+
+      ////B - blocking
+      ////sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      ////denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      //if(counterReceive==0)
+      //{
+      //   comm.Recv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //}
+      //counterReceive++;
+      //if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      //   counterReceive=0;
+   }
+
+protected:
+   CbVectorKey poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   std::vector< unsigned > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+
+   MPI_Comm     comm;
+   MPI_Request  receiveRequest;
+   MPI_Request  sendRequest;
+   //MPI_Status   sendStatus;
+   //MPI_Status   receiveStatus;
+   MPI_Datatype mpiDataType;
+
+   int mpiRemoteRank, mpiTag;
+
+#ifdef _DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorMpiPool<T>::MpiPoolPtrMap TbCbVectorMpiPool<T>::poolMap;
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderMpiPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderMpiPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;
+
+public:
+   TbCbVectorSenderMpiPool(unsigned int cbVectorKey, TbCbVectorMpiPool< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->mpiVectorPool) );
+   }
+   ~TbCbVectorSenderMpiPool()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->mpiVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }
+   void prepareForSend()        { this->mpiVectorPool->prepareForSendData(); }
+   void sendData()              { this->mpiVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->mpiVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->mpiVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool<T>* mpiVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverMpiPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverMpiPool(unsigned int cbVectorKey, TbCbVectorMpiPool< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->mpiVectorPool) );
+   }
+   ~TbCbVectorReceiverMpiPool()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only");  }   
+   void receiveDataSize()   { this->mpiVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   void prepareForReceive() { this->mpiVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->mpiVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getRecvFromRank() const { return  this->mpiVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->mpiVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool<T>* mpiVectorPool;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPIPOOL_H
+ 
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool2.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool2.h
new file mode 100644
index 0000000000000000000000000000000000000000..e09d9f4c295be8f1e95ed84eea90389f7fe22f98
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool2.h
@@ -0,0 +1,453 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPIPOOL2_H
+#define TBTRANSMITTERMPIPOOL2_H
+
+#ifdef VF_MPI
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorMpiPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder MpiPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbMpiVectorPool verwaltet
+//MpiPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderMpiPool2;
+template<typename T> class TbCbVectorReceiverMpiPool2;
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorMpiPool2 : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorMpiPool2< T > > MpiPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< int, MpiPoolPtr >      MpiPoolPtrMap;
+   typedef typename MpiPoolPtrMap::iterator MpiPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderMpiPool2< T >; 
+   friend class TbCbVectorReceiverMpiPool2< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static MpiPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createTbCbVectorMpiPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   // mpiRemoteRank: mpi-rank des Empfaengers/Senders
+   // mpiTag       : mpi-tag mit dem empfangen/gesendet wird
+static MpiPoolPtr createTbCbVectorMpiPool(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI_Comm comm, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+      //pool erstellen
+      MpiPoolPtr mpiPool(new TbCbVectorMpiPool2<T>(poolKey, mpiRemoteRank, mpiTag, comm, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorMpiPool2< value_type >::poolMap[poolKey] = mpiPool;
+
+      return mpiPool; 
+   }
+   static void deleteTbCbVectorMpiPool(const int& poolKey)
+   {
+      MpiPoolPtrMapIter it = TbCbVectorMpiPool2< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorMpiPool2< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static MpiPoolPtr getTbCbVectorMpiPool(const int& poolKey)
+   {
+      MpiPoolPtrMapIter it;
+      if( (it=TbCbVectorMpiPool2< T >::poolMap.find(poolKey))!=TbCbVectorMpiPool2< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return MpiPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorMpiPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+TbCbVectorMpiPool2(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI_Comm comm, const size_type& startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI_REQUEST_NULL)
+      , sendRequest(MPI_REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+
+public:
+   /*==================================================================*/
+   //returns key of Pool in MpiPoolMap
+   int  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->mpiRemoteRank; }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->mpiTag;        }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         //allg.: bei MPI muss man darauf achten, dass bei unblocked operationen die puffer (aus dem oder in den 
+         //geschrieben wird auch noch vorhanden sind!!! wuerde man hier z.B. einen lokalen vector mit Isend() los-
+         //schicken, dann wurde der scope verlassen werden und der vector evtl geloescht werden, bevor mpi den
+         //vorgang abgeschlossen hat!!! ->  tmpOrderVec ist class-member!!!
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         unsigned index = 0;
+         tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+
+         MPI_Isend(&tmpSendOrderVec[0],(int)tmpSendOrderVec.size(), MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, &sendRequest);
+
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+
+         MPI_Irecv(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+         //MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+
+         //if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+         //   throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         //unsigned index = 0;
+         //this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         //this->pool.resize(this->nextCbVectorStartIndexInPool);
+         //CbVectorMapIter it = this->cbVectorMap.begin();
+         //for(/*index*/; index<nofElements; index+=3, ++it)
+         //{
+         //   CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+         //   size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+         //   size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+         //   if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+         //      throw UbException(UB_EXARGS,"entweder hat map nicht die gleiche reihenfolge oder vectorKey nicht vorhanden");
+
+         //   this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         //}
+         //if(it!=this->cbVectorMap.end())
+         //   throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void saveDataOrder()
+   {
+      if(counterPrepareForSend==0)
+      {
+         if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&sendRequest, MPI_STATUS_IGNORE);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      //A - non blocking
+      //der LETZTE is entscheidend 
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+#ifdef DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         MPI_Isend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &sendRequest);
+////////////////////////////////////////////////////////////////////////////////////////////
+         counterSend=0;
+      }                           
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      //A - non blocking
+      //sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      //denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      //if(counterReceive==0)
+      //{
+      //   MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+      //}
+      //counterReceive++;
+      //if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      //{
+      //   counterReceive=0;
+      //}
+
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+#ifdef DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         MPI_Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+         MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+         counterPrepareForReceive=0;
+      }
+   }
+
+protected:
+   int       poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   std::vector< unsigned > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+
+   MPI_Comm     comm;
+   MPI_Request  receiveRequest;
+   MPI_Request  sendRequest;
+   MPI_Datatype mpiDataType;
+   int mpiRemoteRank, mpiTag;
+
+#ifdef DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorMpiPool2<T>::MpiPoolPtrMap TbCbVectorMpiPool2<T>::poolMap;
+
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderMpiPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderMpiPool2 : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorSenderMpiPool2(const unsigned int& cbVectorKey, TbCbVectorMpiPool2< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->mpiVectorPool) );
+   }
+   ~TbCbVectorSenderMpiPool2()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool2< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->mpiVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }
+   void prepareForSend()        { this->mpiVectorPool->prepareForSendData(); }
+   void sendData()              { this->mpiVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->mpiVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->mpiVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool2<T>* mpiVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverMpiPool2 : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverMpiPool2(const unsigned int& cbVectorKey, TbCbVectorMpiPool2< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->mpiVectorPool) );
+   }
+   ~TbCbVectorReceiverMpiPool2()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool2< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only");  }   
+   void receiveDataSize()   { this->mpiVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   void prepareForReceive() { this->mpiVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->mpiVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getRecvFromRank() const { return  this->mpiVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->mpiVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool2<T>* mpiVectorPool;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPIPOOL_H
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool3.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool3.h
new file mode 100644
index 0000000000000000000000000000000000000000..1666ecf080a9a4a1dceb22108eed952dddd1e0b0
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPool3.h
@@ -0,0 +1,530 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPIPOOL_H
+#define TBTRANSMITTERMPIPOOL_H
+
+#ifdef VF_MPI
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+#include <boost/shared_ptr.hpp>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorMpiPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder MpiPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbMpiVectorPool verwaltet
+//MpiPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderMpiPool;
+template<typename T> class TbCbVectorReceiverMpiPool;
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorMpiPool : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorMpiPool< T > > MpiPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< std::string, MpiPoolPtr >      MpiPoolPtrMap;
+   typedef typename MpiPoolPtrMap::iterator MpiPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef std::string CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderMpiPool< T >; 
+   friend class TbCbVectorReceiverMpiPool< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static MpiPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createTbCbVectorMpiPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   // mpiRemoteRank: mpi-rank des Empfaengers/Senders
+   // mpiTag       : mpi-tag mit dem empfangen/gesendet wird
+   static MpiPoolPtr createTbCbVectorMpiPool(CbVectorKey poolKey, int mpiRemoteRank, int mpiTag, MPI_Comm comm, size_type startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+
+      //pool erstellen
+      MpiPoolPtr mpiPool(new TbCbVectorMpiPool<T>(poolKey, mpiRemoteRank, mpiTag, comm, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorMpiPool< value_type >::poolMap[poolKey] = mpiPool;
+
+      return mpiPool; 
+   }
+   static void deleteTbCbVectorMpiPool(CbVectorKey poolKey)
+   {
+      MpiPoolPtrMapIter it = TbCbVectorMpiPool< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorMpiPool< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static MpiPoolPtr getTbCbVectorMpiPool(CbVectorKey poolKey)
+   {
+      MpiPoolPtrMapIter it;
+      if( (it=TbCbVectorMpiPool< T >::poolMap.find(poolKey))!=TbCbVectorMpiPool< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return MpiPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorMpiPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void eraseMap()
+   {
+      poolMap.clear();
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   TbCbVectorMpiPool(CbVectorKey poolKey, int mpiRemoteRank, int mpiTag, MPI_Comm comm, size_type startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI_REQUEST_NULL)
+      , sendRequest(MPI_REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+
+public:
+   /*==================================================================*/
+   //returns key of Pool in MpiPoolMap
+   CbVectorKey  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->mpiRemoteRank; }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->mpiTag;        }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         //allg.: bei MPI muss man darauf achten, dass bei unblocked operationen die puffer (aus dem oder in den 
+         //geschrieben wird auch noch vorhanden sind!!! wuerde man hier z.B. einen lokalen vector mit Isend() los-
+         //schicken, dann wurde der scope verlassen werden und der vector evtl geloescht werden, bevor mpi den
+         //vorgang abgeschlossen hat!!! ->  tmpOrderVec ist class-member!!!
+         //unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         //tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         //unsigned index = 0;
+         //tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         tmpSendOrderVec = "";
+         tmpSendOrderVec+= UbSystem::toString(this->pool.size()+"#";
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            //CbVectorKey vectorKey=0;
+            //size_type   dataSize=0, startIndexInPool=0;
+            //this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            //if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            //tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            //tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            //tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+
+            CbVectorKey vectorKey = "";
+            size_type   dataSize = 0, startIndexInPool = 0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize);
+            if (it->first != vectorKey) throw UbException(UB_EXARGS, "key mismatch!");
+            str += vectorKey+"#"+UbSystem::toString(startIndexInPool)+"#"+UbSystem::toString(dataSize);
+            
+         }
+
+         int vsize = tmpSendOrderVec.length();
+         MPI_Isend(&vsize, 1, MPI_INT, mpiRemoteRank, mpiTag, comm, &sendRequest[0]);
+
+         MPI_Isend(&tmpSendOrderVec.c_str(), vsize, MPI_CHAR, mpiRemoteRank, mpiTag, comm, &sendRequest[1]);
+
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         //receiveRequest.Wait();
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+
+         //MPI_Status status;
+         //MPI_Recv(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, MPI_STATUS_IGNORE);
+
+         MPI_Irecv(&rbuf.blocksSize, 1, MPI_INT, nProcessID, 0, mpi_comm, &request[rcount]);
+
+         if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+            throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+            //if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               //throw UbException(UB_EXARGS, "entweder hat map nicht die gleiche reihenfolge oder vectorKey = "+UbSystem::toString(vectorKey)+" nicht vorhanden");
+            if (it==this->cbVectorMap.end())
+               throw UbException(UB_EXARGS,"map ist leer");
+            else if (it->first != vectorKey)
+               throw UbException(UB_EXARGS, "vectorKey = "+UbSystem::toString(vectorKey)+" nicht vorhanden it->first =" + UbSystem::toString(it->first));
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&sendRequest, MPI_STATUS_IGNORE);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+
+
+      //A - non blocking
+      ////der ERSTE is entscheidend 
+      ////Grund: wenn man 
+      //// for(all trans) { trans->prepare(); trans->fillBuffer(); }
+      //// aufruft, dann wuerde u.U. der Buffer neu beschrieben werden obwohl noch nicht versendet wurde!!!
+      //counterPrepareForSend++;
+      //if(counterPrepareForSend==1)
+      //{
+      //   if(sendRequest != MPI::REQUEST_NULL) sendRequest.Wait();
+      //}
+      //
+      //if(counterPrepareForSend==nofStoredVectors)
+      //   counterPrepareForSend=0;  
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      //A - non blocking
+      //der LETZTE is entscheidend 
+      //counterSend++;
+      //if(counterSend==nofStoredVectors)
+      //{
+      //   //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+      //   sendRequest = comm.Isend(&pool[0],(int)nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //   counterSend=0;
+      //}
+      //B - blocking
+      //der LETZTE is entscheidend 
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+         //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         //synchronous send 
+         //comm.Ssend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+
+         //standard send
+         MPI_Send(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+////////////////////////////////////////////////////////////////////////////////////////////
+//DEBUG///////////////////////////////////////
+         //int irank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &irank);
+         //std::cout << "MPI_Send: " << irank <<  " "  << mpiRemoteRank << " "  <<mpiTag<<std::endl;
+///////////////////////////////////////////////////
+         counterSend=0;
+      }                           
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+      //A - non blocking
+      //sobald der Letzte kann man den den request holen.
+      //andernfalls kann nicht gewaehrleistet werden, dass evtl noch mit dem buffer gearbeitet wird!!!
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         MPI_Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         counterPrepareForReceive=0;
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      //A - non blocking
+      //sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      //denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      if(counterReceive==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+      counterReceive++;
+      if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+
+      ////B - blocking
+      ////sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      ////denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      //if(counterReceive==0)
+      //{
+      //   comm.Recv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //}
+      //counterReceive++;
+      //if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      //   counterReceive=0;
+   }
+
+protected:
+   CbVectorKey poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   //std::vector< char > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+   std::string tmpSendOrderVec;
+
+   MPI_Comm     comm;
+   MPI_Request  receiveRequest;
+   MPI_Request  sendRequest;
+   //MPI_Status   sendStatus;
+   //MPI_Status   receiveStatus;
+   MPI_Datatype mpiDataType;
+
+   int mpiRemoteRank, mpiTag;
+
+   std::vector<MPI_Request> request;
+   int rcount;
+
+#ifdef _DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorMpiPool<T>::MpiPoolPtrMap TbCbVectorMpiPool<T>::poolMap;
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderMpiPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderMpiPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;
+
+public:
+   TbCbVectorSenderMpiPool(std::string cbVectorKey, TbCbVectorMpiPool< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->mpiVectorPool) );
+   }
+   ~TbCbVectorSenderMpiPool()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->mpiVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }
+   void prepareForSend()        { this->mpiVectorPool->prepareForSendData(); }
+   void sendData()              { this->mpiVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->mpiVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->mpiVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool<T>* mpiVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverMpiPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverMpiPool(std::string cbVectorKey, TbCbVectorMpiPool< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->mpiVectorPool) );
+   }
+   ~TbCbVectorReceiverMpiPool()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only");  }   
+   void receiveDataSize()   { this->mpiVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   void prepareForReceive() { this->mpiVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->mpiVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getRecvFromRank() const { return  this->mpiVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->mpiVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool<T>* mpiVectorPool;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPIPOOL_H
+ 
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPoolEx.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPoolEx.h
new file mode 100644
index 0000000000000000000000000000000000000000..dcb52d842363effe7dacca9ddbfb0c81efd50b9a
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterMpiPoolEx.h
@@ -0,0 +1,602 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPIPOOLEX_H
+#define TBTRANSMITTERMPIPOOLEX_H
+
+#ifdef VF_MPI
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+#include <boost/shared_ptr.hpp>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorMpiPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder MpiPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbMpiVectorPool verwaltet
+//MpiPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderMpiPoolEx;
+template<typename T> class TbCbVectorReceiverMpiPoolEx;
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorMpiPoolEx : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorMpiPoolEx< T > > MpiPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< int, MpiPoolPtr >      MpiPoolPtrMap;
+   typedef typename MpiPoolPtrMap::iterator MpiPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderMpiPoolEx< T >; 
+   friend class TbCbVectorReceiverMpiPoolEx< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static MpiPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createTbCbVectorMpiPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   // mpiRemoteRank: mpi-rank des Empfaengers/Senders
+   // mpiTag       : mpi-tag mit dem empfangen/gesendet wird
+#ifdef USE_MPI_CXX_SYNTAX 
+   static MpiPoolPtr createTbCbVectorMpiPool(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI::Intracomm comm, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+#else
+   static MpiPoolPtr createTbCbVectorMpiPool(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI_Comm comm, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+#endif 
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+
+      //pool erstellen
+      MpiPoolPtr mpiPool(new TbCbVectorMpiPoolEx<T>(poolKey, mpiRemoteRank, mpiTag, comm, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorMpiPoolEx< value_type >::poolMap[poolKey] = mpiPool;
+
+      return mpiPool; 
+   }
+   static void deleteTbCbVectorMpiPool(const int& poolKey)
+   {
+      MpiPoolPtrMapIter it = TbCbVectorMpiPoolEx< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorMpiPoolEx< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static MpiPoolPtr getTbCbVectorMpiPool(const int& poolKey)
+   {
+      MpiPoolPtrMapIter it;
+      if( (it=TbCbVectorMpiPoolEx< T >::poolMap.find(poolKey))!=TbCbVectorMpiPoolEx< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return MpiPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorMpiPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void eraseMap()
+   {
+      poolMap.clear();
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+#ifdef USE_MPI_CXX_SYNTAX 
+   TbCbVectorMpiPoolEx(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI::Intracomm comm, const size_type& startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI::REQUEST_NULL)
+      , sendRequest(MPI::REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+#else
+   TbCbVectorMpiPoolEx(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI_Comm comm, const size_type& startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI_REQUEST_NULL)
+      , sendRequest(MPI_REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+#endif
+
+
+public:
+   /*==================================================================*/
+   //returns key of Pool in MpiPoolMap
+   int  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->mpiRemoteRank; }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->mpiTag;        }
+
+protected:
+   /*==================================================================*/
+   /*==================================================================*/
+   /*==================================================================*/
+   /*==================================================================*/
+   /*==================================================================*/
+   //void prepareTbReceiveDataOrder() 
+   //{
+   //counterPrepareReceiveDataOrder++;
+   //if(counterPrepareReceiveDataOrder==nofStoredVectors)
+   //{
+   //   unsigned nofElements = relationMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+   //   tmpOrderVec.resize(nofElements);
+   //   std::cout<<RcfSystem::getRank()<<" prepForRecv from rank="<<mpiRemoteRank<<" with tag="<<mpiTag<<"e="<<nofElements<<std::endl;
+   //   receiveRequest = comm.Irecv(&tmpOrderVec[0], nofElements, MPI::UNSIGNED, mpiRemoteRank, mpiTag);
+   //   counterPrepareReceiveDataOrder = 0;
+   //}
+   //}
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         //allg.: bei MPI muss man darauf achten, dass bei unblocked operationen die puffer (aus dem oder in den 
+         //geschrieben wird auch noch vorhanden sind!!! wuerde man hier z.B. einen lokalen vector mit Isend() los-
+         //schicken, dann wurde der scope verlassen werden und der vector evtl geloescht werden, bevor mpi den
+         //vorgang abgeschlossen hat!!! ->  tmpOrderVec ist class-member!!!
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         unsigned index = 0;
+         tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+         //std::cout<<RcfSystem::getRank()<<" send to rank="<<mpiRemoteRank<<" with tag="<<mpiTag<<" e="<<nofElements<<std::endl;
+         //comm.Send(&tmpOrderVec[0],nofElements, MPI::UNSIGNED, mpiRemoteRank, mpiTag);
+
+         ////////////////////////////
+         //int rank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+         //std::cout<<"rank = " << rank <<" sendDataOrder() nofElements = "<<nofElements<<std::endl;
+         ////////////////////////////
+
+#ifdef USE_MPI_CXX_SYNTAX 
+         sendRequest = comm.Isend(&tmpSendOrderVec[0],(int)tmpSendOrderVec.size(), MPI::UNSIGNED, mpiRemoteRank, mpiTag);
+#else
+         MPI_Isend(&tmpSendOrderVec[0],(int)tmpSendOrderVec.size(), MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, &sendRequest);
+#endif
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+#ifdef DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         //receiveRequest.Wait();
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         //////////////TODO////////////DEBUG
+         //int rank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+         //std::cout<<"rank = " << rank <<" receiveDataOrder() nofElements = "<<nofElements << " from " << mpiRemoteRank <<std::endl;
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         //////////////////////////
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+
+#ifdef USE_MPI_CXX_SYNTAX 
+         comm.Recv(&tmpRecvOrderVec[0], nofElements, MPI::UNSIGNED, mpiRemoteRank, mpiTag);
+#else
+         //MPI_Status status;
+         MPI_Recv(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, MPI_STATUS_IGNORE);
+#endif
+
+         if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+            throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+            if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               throw UbException(UB_EXARGS,"entweder hat map nicht die gleiche reihenfolge oder vectorKey nicht vorhanden");
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef USE_MPI_CXX_SYNTAX 
+         if(sendRequest != MPI::REQUEST_NULL) sendRequest.Wait();
+#else
+         //if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&sendRequest, MPI_STATUS_IGNORE);
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+
+
+      //A - non blocking
+      ////der ERSTE is entscheidend 
+      ////Grund: wenn man 
+      //// for(all trans) { trans->prepare(); trans->fillBuffer(); }
+      //// aufruft, dann wuerde u.U. der Buffer neu beschrieben werden obwohl noch nicht versendet wurde!!!
+      //counterPrepareForSend++;
+      //if(counterPrepareForSend==1)
+      //{
+      //   if(sendRequest != MPI::REQUEST_NULL) sendRequest.Wait();
+      //}
+      //
+      //if(counterPrepareForSend==nofStoredVectors)
+      //   counterPrepareForSend=0;  
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      //A - non blocking
+      //der LETZTE is entscheidend 
+      //counterSend++;
+      //if(counterSend==nofStoredVectors)
+      //{
+      //   //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+      //   sendRequest = comm.Isend(&pool[0],(int)nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //   counterSend=0;
+      //}
+      //B - blocking
+      //der LETZTE is entscheidend 
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+         //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         //synchronous send 
+         //comm.Ssend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#ifdef DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+
+         //standard send
+#ifdef USE_MPI_CXX_SYNTAX 
+         comm.Send(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#else
+         //MPI_Send(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm);
+         MPI_Isend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &sendRequest);
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+////////////////////////////////////////////////////////////////////////////////////////////
+//DEBUG///////////////////////////////////////
+         //int irank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &irank);
+         //std::cout << "MPI_Send: " << irank <<  " "  << mpiRemoteRank << " "  <<mpiTag<<std::endl;
+///////////////////////////////////////////////////
+         counterSend=0;
+      }                           
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+      //A - non blocking
+      //sobald der Letzte kann man den den request holen.
+      //andernfalls kann nicht gewaehrleistet werden, dass evtl noch mit dem buffer gearbeitet wird!!!
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         //std::cout<<"Irecv von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+#ifdef USE_MPI_CXX_SYNTAX 
+         receiveRequest = comm.Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#else
+         //MPI_Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         counterPrepareForReceive=0;
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      //A - non blocking
+      //sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      //denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      if(counterReceive==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef USE_MPI_CXX_SYNTAX 
+         receiveRequest.Wait();
+#else
+         //MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+         MPI_Recv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, MPI_STATUS_IGNORE);
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+      counterReceive++;
+      if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+
+      ////B - blocking
+      ////sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      ////denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      //if(counterReceive==0)
+      //{
+      //   comm.Recv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //}
+      //counterReceive++;
+      //if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      //   counterReceive=0;
+   }
+
+protected:
+   int       poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   std::vector< unsigned > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+
+#ifdef USE_MPI_CXX_SYNTAX 
+   MPI::Intracomm comm;
+   MPI::Request   receiveRequest;
+   MPI::Request   sendRequest;
+   MPI::Datatype  mpiDataType;
+#else
+   MPI_Comm     comm;
+   MPI_Request  receiveRequest;
+   MPI_Request  sendRequest;
+   //MPI_Status   sendStatus;
+   //MPI_Status   receiveStatus;
+   MPI_Datatype mpiDataType;
+#endif
+
+   int mpiRemoteRank, mpiTag;
+
+#ifdef DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorMpiPoolEx<T>::MpiPoolPtrMap TbCbVectorMpiPoolEx<T>::poolMap;
+
+//   static MpiPoolPtrMap poolMap;
+
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderMpiPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderMpiPoolEx : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorSenderMpiPoolEx(const unsigned int& cbVectorKey, TbCbVectorMpiPoolEx< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->mpiVectorPool) );
+   }
+   ~TbCbVectorSenderMpiPoolEx()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPoolEx< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->mpiVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }
+   void prepareForSend()        { this->mpiVectorPool->prepareForSendData(); }
+   void sendData()              { this->mpiVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->mpiVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->mpiVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorMpiPoolEx<T>* mpiVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverMpiPoolEx : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverMpiPoolEx(const unsigned int& cbVectorKey, TbCbVectorMpiPoolEx< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->mpiVectorPool) );
+   }
+   ~TbCbVectorReceiverMpiPoolEx()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPoolEx< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only");  }   
+   void receiveDataSize()   { this->mpiVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   void prepareForReceive() { this->mpiVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->mpiVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getRecvFromRank() const { return  this->mpiVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->mpiVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorMpiPoolEx<T>* mpiVectorPool;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPIPOOL_H
+ 
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterRcf.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterRcf.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ec1c25dddabe3aea4c87331df6536f3e2a58fdd
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterRcf.h
@@ -0,0 +1,326 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERRCF_H
+#define TBTRANSMITTERRCF_H
+
+/*=========================================================================*/
+/*  RCF Transmitter                                                        */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+*/ 
+
+/*
+usage: ...
+*/
+
+#include <iostream>
+#include <vector>
+#include <map>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/utilities/UbLogger.h>
+
+#ifdef CAB_RCF
+//////////////////////////////////////////////////////////////////////////
+// RCF STUFF
+//////////////////////////////////////////////////////////////////////////
+
+#include <RCF/Idl.hpp>
+#include <RCF/TcpEndpoint.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <3rdParty/rcf/RcfSerializationIncludes.h>
+#include <3rdParty/rcf/RcfSystem.h>
+#include <3rdParty/rcf/IRcfIpService.h>
+#include <3rdParty/rcf/RcfConnection.h>
+
+//zum ausstausch mittels RCF transmitter:
+RCF_BEGIN(IRcfTransmitterReceiverService, "IRcfTransmitterReceiverService")
+   RCF_METHOD_V2(void, receiveVectorForTransmitter,int /*tag*/, const std::vector<double>& /*data*/);
+   RCF_METHOD_V2(void, receiveVectorForTransmitter,int /*tag*/, const CbVector<double>& /*data*/);
+   RCF_METHOD_V2(void, receiveVectorForTransmitter,int /*tag*/, const std::vector<float>& /*data*/);
+   RCF_METHOD_V2(void, receiveVectorForTransmitter,int /*tag*/, const CbVector<float>& /*data*/);
+RCF_END(IRcfTransmitterReceiverService);
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderRcf< Vector > 
+//////////////////////////////////////////////////////////////////////////
+template< typename Vector >
+class TbVectorSenderRcf : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;   
+   
+   //static members
+private:
+   static std::vector< RcfClient<IRcfTransmitterReceiverService> >  recvServices;
+
+   static void setRcfClients(const std::string& recvServiceID);
+
+public:
+   TbVectorSenderRcf(const std::string& recvServiceName,const RcfConnection& receiveProcess, const int& tag) 
+      : TbTransmitter< Vector >()
+   { 
+      if( recvServices.empty() ) setRcfClients(recvServiceName);
+      this->receiveRank	   = receiveProcess.getRank();
+      this->tag            = tag;
+      this->receiveProcess = receiveProcess;
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()    { this->sendData(); }
+   void receiveDataSize() { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorSender sends only") ); } 
+
+   void sendData() 
+   { 
+      //remote prozess=client erhaelt daten
+      recvServices[receiveRank].receiveVectorForTransmitter(tag, TbTransmitter< Vector >::getData());
+   }
+   void prepareForReceive() { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorSender sends only") ); }
+   Vector& receiveData()    { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()    const { return  this->receiveRank; /*=der rank an den gesendet wird*/}
+   int  getSendTbTag()     const { return  this->tag;                                           }
+   int  getRecvFromRank()  const { UB_THROW( UbException(UB_EXARGS,"TbVectorSenderRcf sends only") ); }
+   int  getRecvFromTag()   const { UB_THROW( UbException(UB_EXARGS,"TbVectorSenderRcf sends only") ); }
+
+   std::string toString() const { return "TbVectorSenderRcf< "+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name() +"> > to rank (tag)"+UbSystem::toString(receiveRank)+"("+UbSystem::toString(tag)+") connection "+receiveProcess.toString(); }
+
+private:
+   RcfConnection receiveProcess;
+   int tag;
+   int receiveRank;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template< typename Vector >
+std::vector< RcfClient<IRcfTransmitterReceiverService> >  TbVectorSenderRcf< Vector >::recvServices;
+
+template< typename Vector >
+void TbVectorSenderRcf< Vector >::setRcfClients(const std::string& recvServiceID)
+{
+   UBLOG(logINFO,"invoked setRcfClients");
+   RcfConnection ipConnection = RcfSystem::getIpServiceConnection();
+   if(!ipConnection) UB_THROW( UbException(UB_EXARGS,"ups, no IpServiceConnection") );
+   RcfClient<IRcfIpService> ipService(RCF::TcpEndpoint(ipConnection.getIp(), ipConnection.getPort()));
+
+   //Mit RecvServices verbinden
+   std::vector<RcfConnection> connections = ipService.getServiceConnections(recvServiceID);
+   if(connections.empty()) 
+      UB_THROW( UbException(UB_EXARGS,"no existing RecvService with ID = "+recvServiceID) );
+   std::sort(connections.begin(),connections.end(),RcfConnection::compareRank());
+
+   for(std::size_t i=0; i<connections.size(); i++)
+   {
+      if( (int)i != connections[i].getRank() )
+         UB_THROW( UbException(UB_EXARGS,"recvServices must have continougs ranks sarting from 0") );
+      recvServices.push_back(RcfClient<IRcfTransmitterReceiverService>(RCF::TcpEndpoint(connections[i].getIp(), connections[i].getPort())) );
+   }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorReceiverRcf
+//////////////////////////////////////////////////////////////////////////
+template< typename Vector >
+class TbVectorReceiverRcf : public TbTransmitter< Vector >
+{
+   typedef std::map<int, TbVectorReceiverRcf< Vector >* >  ReceiverMap;
+   typedef typename ReceiverMap::iterator                  ReceiverMapIt;
+   
+public:
+   typedef Vector value_type;
+
+   //static members
+private:
+   static ReceiverMap  receiverMap;
+   static boost::mutex staticReceiverMapMutex;
+
+public:
+   static void receiveVectorForTransmitter(int tag, const Vector& data)
+   {
+      TbVectorReceiverRcf< Vector >* receiver = NULL;
+      
+      //receiver ermitteln (map nicht thread-safe->lock! aber nur kurz, ansonsten ab einer gewissen anzahl an clients/blöcken->deadlock)
+      //vermutlich brauch man den nicht mal... (denn das registrieren sollte zu diesem zeitpunkt abgeschlossen sein)
+      //allerdings sollte man nicht gleichzeitig Suchoperationen in ner nich thread sicheren map durchführen!!!
+      {
+         boost::mutex::scoped_lock lock(staticReceiverMapMutex); //wenn man das ausserhalb macht, gibt es ab einer bestimmten anzahl an clients/bloecke einen deadlock
+         
+         ReceiverMapIt result = TbVectorReceiverRcf< Vector >::receiverMap.find(tag);
+         if( result == TbVectorReceiverRcf< Vector >::receiverMap.end() )
+            UB_THROW( UbException(UB_EXARGS,"receiver is not registered") );
+         
+         receiver = result->second;
+         if(!receiver) 
+            UB_THROW( UbException(UB_EXARGS,"receiver is NULL") );
+      }
+      
+      boost::mutex::scoped_lock lock(receiver->bufferMutex); 
+
+      // wait until buffer is empty 
+      while(receiver->isBufferFull) 
+         receiver->bufferEmptiedCondition.wait(lock); 
+
+      //////////////////////////////////////////////////////////////////////////
+      // put data in buffer 
+      //old: receiver->buffer = data;
+      
+      //new:
+      if( receiver->buffer.size() != data.size() )
+      {
+         receiver->buffer.resize( data.size() );
+      }
+      memcpy( (char*)&receiver->buffer[0], (char*)&data[0],  data.size()*sizeof(typename Vector::value_type) ); 
+      
+      //////////////////////////////////////////////////////////////////////////
+      //evtl wartende clients benachrichtigen
+      //notify "buffer filled" waiters 
+      receiver->isBufferFull = true; 
+      receiver->bufferFilledCondition.notify_all(); // notify_one muesste eigentlich reichen 
+   }
+
+public:
+   TbVectorReceiverRcf(const int& tag, const int& recvFromRank/*just for info section*/) 
+      : TbTransmitter< Vector >(), tag(tag), recvFromRank(recvFromRank)
+   {
+      {
+         //receiver registrieren
+         boost::mutex::scoped_lock lock( TbVectorReceiverRcf< Vector >::staticReceiverMapMutex ); 
+
+         std::pair< ReceiverMapIt, bool> result = receiverMap.insert(std::make_pair(tag, this));
+         if( !result.second )
+         {
+            ReceiverMapIt existingReceiver = TbVectorReceiverRcf< Vector >::receiverMap.find(tag);
+            TbVectorReceiverRcf< Vector >::receiverMap.erase(existingReceiver);
+            TbVectorReceiverRcf< Vector >::receiverMap.insert(std::pair<int, TbVectorReceiverRcf< Vector >* >(tag, this));
+         }
+      }
+      isBufferFull = false; 
+   }
+
+   ~TbVectorReceiverRcf()
+   {
+      ReceiverMapIt existingReceiver = receiverMap.find(tag);
+      TbVectorReceiverRcf< Vector >::receiverMap.erase(existingReceiver);
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()    { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorReceiver receives only") ); }
+   void receiveDataSize() { this->receiveData(); } 
+
+   void sendData()        { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorReceiver receives only") ); }
+
+   Vector& receiveData()
+   {
+      boost::mutex::scoped_lock lock(bufferMutex); 
+
+      // wait until buffer is full 
+      while(!isBufferFull) 
+         bufferFilledCondition.wait(lock); 
+
+      // get data from buffer 
+      //std::size_t dataSize = this->buffer.size();
+      //if( this->getData().size()!=dataSize ) this->getData().resize(dataSize);
+      //for(std::size_t i=0; i<dataSize; ++i)
+      //   this->getData()[i]=buffer[i]; 
+      
+      //folgende assert schlaegt bei receiveDataSize(), das receiveData() aufgerufen wird fehl...
+      //daher ausdokumentiert
+      //assert( this->getData().size() == this->buffer.size() );
+      
+      this->getData().swap(this->buffer);
+      
+      isBufferFull = false; 
+
+      // notify "buffer emptied" waiters 
+      bufferEmptiedCondition.notify_all(); // notify_one sollte auch hier reichen 
+      return this->getData(); 
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()    const { UB_THROW( UbException(UB_EXARGS,"getSendTbRank  sends only") ); }
+   int  getSendTbTag()     const { UB_THROW( UbException(UB_EXARGS,"getSendTbTag  sends only") ); }
+   int  getRecvFromRank()  const { return  this->recvFromRank; /*=der rank an den gesendet wird*/ }
+   int  getRecvFromTag()   const { return  this->tag;                                             }
+
+   std::string toString() const { return "TbVectorReceiverRcf< "+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name() +"> > to rank (tag)"+UbSystem::toString(recvFromRank)+"("+UbSystem::toString(tag)+")"; }
+
+private:
+   int tag;
+   int recvFromRank; //just for info-section
+
+   boost::mutex     bufferMutex; 
+   boost::condition bufferFilledCondition; 
+   boost::condition bufferEmptiedCondition; 
+   bool isBufferFull; 
+
+   Vector buffer; 
+};
+
+//////////////////////////////////////////////////////////////////////////
+// template< typename Vector >
+// std::map<int, TbVectorReceiverRcf< Vector >* > TbVectorReceiverRcf< Vector >::receiverMap;
+template< typename Vector >
+typename TbVectorReceiverRcf< Vector >::ReceiverMap TbVectorReceiverRcf< Vector >::receiverMap;
+
+template< typename Vector >
+boost::mutex TbVectorReceiverRcf< Vector >::staticReceiverMapMutex;
+
+
+// 
+// 
+// 
+// 
+// //derzeit funzt es nur mit vector<double> dafuer gibt es weiter unten eine spezialisierung
+// //Grund: man muss  fuer jeden datentyp eine RCF methode beim service registrieren
+// //        und derzeit ist eben nur eine fuer vector<double> vorhanden
+// template< typename Vector >
+// class TbVectorSenderRcf : public TbTransmitter< Vector >
+// {
+// public:
+//    TbVectorSenderRcf(const std::string& calcServiceName, const RcfConnection& receiveProcess, const int& tag) 
+//       : TbTransmitter< Vector >()
+//    {  
+//       UB_THROW( UbException("TbVectorSenderRcf::TbVectorSenderRcf() - TbRcfVectorSender not implmeneted for that type ") );    
+//    }
+//    void sendDataSize()      { UB_THROW( UbException("TbVectorSenderRcf::sendDataSize() - not defined for that type") );         }
+//    void receiveDataSize()   { UB_THROW( UbException("TbVectorSenderRcf::receiveDataSize() - not defined for that type") );      } 
+//    void sendData()          { UB_THROW( UbException("TbVectorSenderRcf::sendData() - not defined for that type") );             }
+//    void prepareForReceive() { UB_THROW( UbException("TbVectorSenderRcf::prepareForReceive() - TbRcfVectorSender sends only") ); }
+//    Vector& receiveData()         { UB_THROW( UbException("TbVectorSenderRcf::receiveData() - TbRcfVectorSender sends only") );       } 
+//    std::string toString()   { return "undefined TbVectorSenderRcf"; }
+// };
+// 
+// template< typename Vector  >
+// class TbVectorReceiverRcf : public TbTransmitter< Vector >
+// {
+// public:
+//    TbVectorReceiverRcf(const int& tag, const int& receiveRank) : TbTransmitter< Vector >()
+//    {
+//       UB_THROW( UbException("TbVectorReceiverRcf::TbVectorReceiverRcf() - not defined for that type") );  
+//    }
+//    void sendDataSize()    { UB_THROW( UbException("TbVectorReceiverRcf::sendDataSize() - not defined for that type") );     }    
+//    void receiveDataSize() { UB_THROW( UbException("TbVectorReceiverRcf::receiveDataSize() - not defined for that type") );  } 
+//    void sendData()        { UB_THROW( UbException("TbVectorReceiverRcf::sendData() - TbRcfVectorReceiver receives only") ); }
+//    Vector& receiveData()       { UB_THROW( UbException("TbVectorReceiverRcf::receiveData() - not defined for that type") );      }
+//    std::string toString() { return "undefined TbVectorReceiverRcf"; }
+// };
+// 
+#endif // CAB_RCF
+
+#endif //TBTRANSMITTERRCF_H
diff --git a/source/ThirdParty/Library/basics/transmitter/TbTransmitterRcfPool.h b/source/ThirdParty/Library/basics/transmitter/TbTransmitterRcfPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..361cd7a4475806aeb98bce5a82899147fffe1c65
--- /dev/null
+++ b/source/ThirdParty/Library/basics/transmitter/TbTransmitterRcfPool.h
@@ -0,0 +1,593 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBCBVECTORRCFPOOL_H
+#define TBCBVECTORRCFPOOL_H
+
+#ifdef CAB_RCF
+
+/*=========================================================================*/
+/*  ToCbVectorRcfPool                                                      */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 09.10.08
+*/ 
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+#include <cassert>
+
+#include <RCF/Idl.hpp>
+#include <RCF/TcpEndpoint.hpp>
+#include <RCF/ByteBuffer.hpp>
+
+#include <boost/shared_ptr.hpp>
+
+#include <3rdParty/rcf/RcfSerializationIncludes.h>
+#include <3rdParty/rcf/RcfSystem.h>
+#include <3rdParty/rcf/IRcfIpService.h>
+#include <3rdParty/rcf/RcfConnection.h>
+
+#include <basics/transmitter/ToTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/utilities/UbLogger.h>
+
+
+// zum ausstausch mittels RCF transmitter:
+RCF_BEGIN(IRcfTransmitterReceiverPoolService, "IRcfTransmitterReceiverPoolService")
+RCF_METHOD_V3(void, receiveRcfPoolData     , const float&  /*dummy*/, const int& /*poolKey*/, const RCF::ByteBuffer&         /*databuffer*/ )
+RCF_METHOD_V3(void, receiveRcfPoolDataOrder, const float&  /*dummy*/, const int& /*poolKey*/, const std::vector< unsigned >& /*dataOrder*/  )
+RCF_METHOD_V3(void, receiveRcfPoolData     , const double& /*dummy*/, const int& /*poolKey*/, const RCF::ByteBuffer&         /*databuffer*/ )
+RCF_METHOD_V3(void, receiveRcfPoolDataOrder, const double& /*dummy*/, const int& /*poolKey*/, const std::vector< unsigned >& /*dataOrder*/  )
+RCF_END(IRcfTransmitterReceiverPoolService);
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//ToRcfPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder RcfPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im ToRcfVectorPool verwaltet
+//RcfPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class ToCbVectorSenderRcfPool;
+template<typename T> class ToCbVectorReceiverRcfPool;
+
+/*==================================================================*/
+template<typename T>
+class ToCbVectorRcfPool : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< ToCbVectorRcfPool< T > > RcfPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< int, RcfPoolPtr >      RcfPoolPtrMap;
+   typedef typename RcfPoolPtrMap::iterator RcfPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class ToCbVectorSenderRcfPool< T >; 
+   friend class ToCbVectorReceiverRcfPool< T >; 
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   static RcfPoolPtrMap poolMap;
+
+//    //wenn pool als recevier fungiert
+//    static ReceiverPoolMap  receiverPoolMap;
+   static boost::mutex     staticPoolMapMutex;
+
+   //wenn pool als sender fungiert
+   static std::vector< RcfConnection >  recvConnections;   
+   static std::vector< RcfClient<IRcfTransmitterReceiverPoolService> >  recvServices;
+   static void setRcfSendToClients(const std::string& receiveServiceID, const int& rcfSendToRank);
+
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createToCbVectorRcfPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   //              : (dieser schluessel ist eindeutig und muss bei send und recevicePool uebereinstimmen (ersetzt Tag)
+   // rcfRemoteRank: rcf-rank des Empfaengers/Senders
+   // rcfTag       : rcf-tag mit dem empfangen/gesendet wird
+   static RcfPoolPtr createToCbVectorRcfSendPool(const std::string& rcfSendToServiceName, const int& poolKey, const int& rcfSendToRank, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+   {
+      if( poolMap.find(poolKey)!=ToCbVectorRcfPool< value_type >::poolMap.end() )
+      {
+         UB_THROW( UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!") );
+      }
+      //pool erstellen
+      RcfPoolPtr rcfPool(new ToCbVectorRcfPool<T>(rcfSendToServiceName, poolKey, rcfSendToRank, startPoolSize) ); 
+      
+      //pool "speichern"
+      ToCbVectorRcfPool< value_type >::poolMap[poolKey] = rcfPool;
+
+      ToCbVectorRcfPool::setRcfSendToClients(rcfSendToServiceName, rcfSendToRank);
+      
+      return rcfPool; 
+   }
+   /*==================================================================*/
+   static RcfPoolPtr createToCbVectorRcfRecvPool(const int& poolKey, const int& rcfRecvRank, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         UB_THROW( UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!") );
+      }
+      //pool erstellen
+      RcfPoolPtr rcfPool(new ToCbVectorRcfPool<T>( "", poolKey, rcfRecvRank, startPoolSize ) ); 
+                                                  
+      //pool "speichern"
+      ToCbVectorRcfPool< value_type >::poolMap[poolKey] = rcfPool;
+
+      return rcfPool; 
+   }
+   /*==================================================================*/
+   static void deleteToCbVectorRcfPool(const int& poolKey)
+   {
+      RcfPoolPtrMapIter it = ToCbVectorRcfPool< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         UB_THROW( UbException(UB_EXARGS,"kein Pool mit dem key vorhanden") );
+      }
+      ToCbVectorRcfPool< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static RcfPoolPtr getToCbVectorRcfPool(const int& poolKey)
+   {
+      RcfPoolPtrMapIter it;
+      if( (it=ToCbVectorRcfPool< T >::poolMap.find(poolKey))!=ToCbVectorRcfPool< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return NULL;
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"ToCbVectorRcfPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(RcfPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+             <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+             <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+             <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(RcfPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+      return true;
+   }
+   /*==================================================================*/
+   static void receiveDataOrder(int poolKey, const std::vector< unsigned >& dataOrder)
+   {
+      RcfPoolPtr receiverPool;
+
+      //receiver ermitteln (map nicht thread-safe->lock! aber nur kurz, ansonsten ab einer gewissen anzahl an clients/blöcken->deadlock)
+      //vermutlich brauch man den nicht mal... (denn das registrieren sollte zu diesem zeitpunkt abgeschlossen sein)
+      //allerdings sollte man nicht gleichzeitig Suchoperationen in ner nicht thread sicheren map durchführen!!!
+      {
+         boost::mutex::scoped_lock lock(staticPoolMapMutex); //wenn man das ausserhalb macht, gibt es ab einer bestimmten anzahl an clients/bloecke einen deadlock
+         receiverPool = getToCbVectorRcfPool(poolKey);
+         if(!receiverPool) UB_THROW( UbException(UB_EXARGS,"kein pool mit poolKey="+UbSystem::toString(poolKey)) );
+      }
+
+      boost::mutex::scoped_lock lock(receiverPool->receiveDataOrderMutex); 
+      
+      // wait until buffer is empty 
+      while(receiverPool->receivedDataOrderBufferIsFull) 
+         receiverPool->dataOrderVectorEmptiedCondition.wait(lock); 
+      
+      receiverPool->recvOrderVec = dataOrder;
+                
+      //////////////////////////////////////////////////////////////////////////
+      //evtl wartende clients benachrichtigen
+      //notify "buffer filled" waiters 
+     
+      receiverPool->receivedDataOrderBufferIsFull = true; 
+      receiverPool->dataOrderVectorFilledCondition.notify_all(); 
+   }
+   /*==================================================================*/
+   static void receivePoolData(const int& poolKey, const RCF::ByteBuffer& byteBuffer) //const typename CbVectorPool< T >::Pool& data)
+   {
+      RcfPoolPtr receiverPool;
+
+      //receiver ermitteln (map nicht thread-safe->lock! aber nur kurz, ansonsten ab einer gewissen anzahl an clients/blöcken->deadlock)
+      //vermutlich brauch man den nicht mal... (denn das registrieren sollte zu diesem zeitpunkt abgeschlossen sein)
+      //allerdings sollte man nicht gleichzeitig Suchoperationen in ner nich thread sicheren map durchführen!!!
+      {
+         boost::mutex::scoped_lock lock(staticPoolMapMutex); //wenn man das ausserhalb macht, gibt es ab einer bestimmten anzahl an clients/bloecke einen deadlock
+         receiverPool = getToCbVectorRcfPool(poolKey);
+         if(!receiverPool) UB_THROW( UbException(UB_EXARGS,"kein pool mit poolKey="+UbSystem::toString(poolKey)) );
+
+         //std::cout<<"poolMap.size()="<<poolMap.size()<<std::endl;
+      }
+
+      boost::mutex::scoped_lock lock(receiverPool->receiveMutex); 
+      //UBLOG(logDEBUG5,"receivePoolVector - entered, pool");
+      // wait until buffer is full 
+      while(!receiverPool->performPoolUpdate)
+         receiverPool->performPoolUpdateCond.wait(lock); 
+      //UBLOG(logDEBUG5,"receivePoolVector - es kann losgehen buggercopy");
+
+      //ACHTUNG! nie einen pool.swap(data) machen -> startadressen der "kleinen" vektoren passen sonst nimmer!
+      if( receiverPool->pool.size()*sizeof( T ) != byteBuffer.getLength() )
+      {
+         UB_THROW( UbException(UB_EXARGS,"pool.size()!=byteBuffer.size()") );
+      }
+      memcpy( (char*)&receiverPool->pool[0], byteBuffer.getPtr(),  byteBuffer.getLength() ); 
+//      memcpy( (char*)&receiverPool->pool[0], (char*)&data[0],  data.size()*sizeof( T ) ); 
+      //UBLOG(logDEBUG5,"receivePoolVector - nach memcopy");
+
+      receiverPool->poolWasUpdated    = true;
+      receiverPool->performPoolUpdate = false;
+      receiverPool->waitForPoolUpdateCond.notify_one(); // notify_one sollte auch hier reichen 
+   }
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   ToCbVectorRcfPool(const std::string& rcfReceiveServiceName, const int& poolKey, const int& rcfRank, const size_type& startPoolSize  )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+         , poolKey(poolKey)                           
+         , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+         , counterPrepareReceiveDataOrder(0)          
+         , counterSendDataOrder(0)                    
+         , counterReceiveDataOrder(0)                 
+         , counterPrepareForReceive(0)                
+         , counterReceive(0)                          
+         , counterSend(0)                             
+         , rcfReceiveServiceName(rcfReceiveServiceName)
+         , rcfRank(rcfRank)                                 
+         , receivedDataOrderBufferIsFull(false)
+         , performPoolUpdate(false)
+         , poolWasUpdated(false)
+   {
+   }
+
+public:
+   //returns key of Pool in RcfPoolMap
+   int  getPoolKey()    const { return  this->poolKey;  }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->rcfRank;  }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->rcfRank;  }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         std::vector< unsigned >localSendOrderVec(nofElements); 
+         unsigned index = 0;
+         localSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  UB_THROW( UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!") );
+         
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) UB_THROW( UbException(UB_EXARGS,"key mismatch!") );
+            
+            localSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            localSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            localSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+         
+         //remote prozess=client erhaelt daten
+         recvServices[this->rcfRank].receiveRcfPoolDataOrder(T(), this->poolKey, localSendOrderVec);
+         
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   { 
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         boost::mutex::scoped_lock lock(receiveDataOrderMutex); 
+         
+         // wait until buffer is full 
+         while(!receivedDataOrderBufferIsFull) 
+            dataOrderVectorFilledCondition.wait(lock); //wird in receivePoolVectorForTransmitter freigegeben :)
+         
+         //////////////////////////////////////////////////////////////////////////
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         if(nofElements!=(unsigned)recvOrderVec.size())
+            UB_THROW( UbException(UB_EXARGS,"error... vec size stimmt nicht") );
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = recvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)recvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)recvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)recvOrderVec.at(index+2);
+
+            if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               UB_THROW( UbException(UB_EXARGS,"entweder hat map nicht die gleiche reihenfolge oder vectorKey nicht vorhanden") );
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            UB_THROW( UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...") );
+
+         recvOrderVec.resize(0);
+
+         // notify "buffer emptied" waiters 
+         this->receivedDataOrderBufferIsFull = false; //->somit kann wieder neue reihenfolge empfangen werden
+         dataOrderVectorEmptiedCondition.notify_all(); // notify_one sollte auch hier reichen 
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData() {}
+   /*==================================================================*/
+   void sendData()
+   {
+      counterSend++;
+      if( counterSend == nofStoredVectors )
+      {
+         //remote prozess=client erhaelt daten
+         //T() -> auf der empfangsseite wird automatisch die methode für den entsprechenden ToCbVectorRcfPool< T >
+         //aufgerufen
+         RCF::ByteBuffer byteBuffer( (char*)&this->pool[0], this->pool.size()*sizeof( T ), true );
+         recvServices[this->rcfRank].receiveRcfPoolData( T(), this->poolKey, byteBuffer );
+         counterSend=0;
+      }
+   }                              
+   /*==================================================================*/
+   void prepareForReceiveData() 
+   {
+      counterPrepareForReceive++;
+      if( counterPrepareForReceive == this->nofStoredVectors )
+      {
+         boost::mutex::scoped_lock lock(receiveMutex); 
+         //UBLOG(logDEBUG5,"prepareForReceiveData - entered -> notfifiziere performPoolUpdateCond");
+
+         counterPrepareForReceive = 0;
+         this->performPoolUpdate = true;
+         performPoolUpdateCond.notify_one();
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      if( counterReceive == 0 )
+      {
+         boost::mutex::scoped_lock lock(receiveMutex); 
+         //UBLOG(logDEBUG5,"receiveData - wait for pool update");
+
+         while(!this->poolWasUpdated)
+            waitForPoolUpdateCond.wait(lock);
+         this->poolWasUpdated    = false;
+         //UBLOG(logDEBUG5,"receiveData - pool update seems to be finished");
+      }
+
+      counterReceive++;
+      if( counterReceive == this->nofStoredVectors ) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+   }
+
+protected:
+   int       poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterSend;
+
+   std::string rcfReceiveServiceName; //nur als SENDER wichtig!!
+   int         rcfRank; 
+
+   bool             receivedDataOrderBufferIsFull; 
+   boost::mutex     receiveDataOrderMutex; 
+   boost::condition dataOrderVectorFilledCondition; 
+   boost::condition dataOrderVectorEmptiedCondition;
+   std::vector< unsigned > recvOrderVec;
+
+   bool             performPoolUpdate;
+   boost::mutex     receiveMutex;
+   bool             poolWasUpdated;
+   boost::condition waitForPoolUpdateCond;
+   boost::condition performPoolUpdateCond;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+std::vector< RcfClient<IRcfTransmitterReceiverPoolService> >  ToCbVectorRcfPool< T >::recvServices;
+
+template< typename T >
+std::vector< RcfConnection >  ToCbVectorRcfPool< T >::recvConnections;
+
+template< typename T >                                              
+void ToCbVectorRcfPool< T >::setRcfSendToClients(const std::string& recvServiceID, const int& rcfSendToRank)
+{
+   UBLOG(logINFO,"ToCbVectorRcfPool< T >::setRcfSendToClients - invoked setRcfClients");
+   RcfConnection ipConnection = RcfSystem::getIpServiceConnection();
+   if(!ipConnection) UB_THROW( UbException(UB_EXARGS,"ups, no IpServiceConnection") );
+   RcfClient<IRcfIpService> ipService(RCF::TcpEndpoint(ipConnection.getIp(), ipConnection.getPort()));
+
+   //////////////////////////////////////////////////////////////////////////
+   //CalcService Verbindungsdaten holen und nach rank sortiere
+   std::vector<RcfConnection> connections = ipService.getServiceConnections(recvServiceID);
+   if(connections.empty()) UB_THROW( UbException(UB_EXARGS,"no existing RecvService with ID = "+recvServiceID) );
+   std::sort(connections.begin(),connections.end(),RcfConnection::compareRank());
+
+   //////////////////////////////////////////////////////////////////////////
+   //CalcServiceClient für rcfSendToRank übernehmen
+   assert( recvConnections.size() == recvServices.size() );
+
+   if( rcfSendToRank >= (int)recvConnections.size() ) 
+   {
+      recvConnections.resize(rcfSendToRank+1);
+      recvServices.resize( rcfSendToRank+1 );
+   }
+   
+   //Anm.: nur, wenn nicht schon vorhanden (hierfür merkt man sich zusätzlich die connection!
+   if( recvConnections[rcfSendToRank] != connections[rcfSendToRank] )
+   {
+      if( connections[rcfSendToRank].getRank() != rcfSendToRank )
+         UB_THROW( UbException(UB_EXARGS,"error - ranks ranks anscheinend nicht kontinierlich von [0..n]") );
+      
+      recvConnections[rcfSendToRank] = connections[rcfSendToRank];
+      recvServices[rcfSendToRank] = RcfClient<IRcfTransmitterReceiverPoolService>(RCF::TcpEndpoint(connections[rcfSendToRank].getIp(), connections[rcfSendToRank].getPort()));
+      UBLOG(logINFO,"ToCbVectorRcfPool< T >::setRcfSendToClients - rank="<<rcfSendToRank<<" : set RcfClient with connection = " << connections[rcfSendToRank] );
+   }
+   else
+   {
+       UBLOG(logINFO,"ToCbVectorRcfPool< T >::setRcfSendToClients - rank="<<rcfSendToRank<<" : RcfClient already exists with connection = " << connections[rcfSendToRank] );
+   }
+   //for(std::size_t i=0; i<connections.size(); i++)
+   //{
+   //   if( (int)i != connections[i].getRank() )
+   //      UB_THROW( UbException(UB_EXARGS,"recvServices must have continous ranks sarting from 0") );
+   //   recvServices[i] = RcfClient<IRcfTransmitterReceiverPoolService>(RCF::TcpEndpoint(connections[i].getIp(), connections[i].getPort()));
+   //   UBLOG(logINFO,"ToCbVectorRcfPool< T >::setRcfSendToClients - pos="<<i<<" : set RcfClient with connection = " << connections[i] );
+   //}
+}
+
+template<typename T>
+typename ToCbVectorRcfPool<T>::RcfPoolPtrMap ToCbVectorRcfPool<T>::poolMap;
+
+template< typename T >
+boost::mutex ToCbVectorRcfPool< T >::staticPoolMapMutex;
+
+
+//////////////////////////////////////////////////////////////////////////
+//  ToSenderRcfPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class ToCbVectorSenderRcfPool : public ToTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   ToCbVectorSenderRcfPool(const unsigned int& cbVectorKey, ToCbVectorRcfPool< T >* rcfVectorPool)
+      : rcfVectorPool(rcfVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->rcfVectorPool) );
+   }
+   ~ToCbVectorSenderRcfPool()
+   {
+      if( this->rcfVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         ToCbVectorRcfPool< T >::deleteToCbVectorRcfPool(this->rcfVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->rcfVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { UB_THROW( UbException(UB_EXARGS,"ToRcfPoolSender sends only") );  }   
+   CbVector< T >& receiveData() { UB_THROW( UbException(UB_EXARGS,"ToRcfPoolSender sends only") );  }
+   void prepareForSend()        { this->rcfVectorPool->prepareForSendData(); }
+   void sendData()              { this->rcfVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendToRank()   const { return  this->rcfVectorPool->getRemoteRank(); }
+   int  getSendToTag()    const { return  this->rcfVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"ToCbVectorSenderRcfPool sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"ToCbVectorSenderRcfPool sends only") ); }
+
+   std::string toString() const { return "ToCbVectorSenderRcfPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendToRank())+"("+UbSystem::toString(getSendToTag())+")"; }
+
+protected:
+   ToCbVectorRcfPool<T>* rcfVectorPool;
+};
+
+/*==================================================================*/
+template<typename T>
+class ToCbVectorReceiverRcfPool : public ToTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   ToCbVectorReceiverRcfPool(const unsigned int& cbVectorKey, ToCbVectorRcfPool< T >* rcfVectorPool)
+      : rcfVectorPool(rcfVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->rcfVectorPool) );
+   }
+   ~ToCbVectorReceiverRcfPool()
+   {
+      if( this->rcfVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         UBLOG(logINFO,"ToCbVectorReceiverRcfPool - loesche map - poolKey "<<this->rcfVectorPool->getPoolKey());
+         ToCbVectorRcfPool< T >::deleteToCbVectorRcfPool(this->rcfVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                         }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();   }
+
+   void sendDataSize()      { UB_THROW( UbException(UB_EXARGS,"ToCbVectorReceiverRcfPool receives only") ); }   
+   void receiveDataSize()   { this->rcfVectorPool->receiveDataOrder();   }  
+   void sendData()          { UB_THROW( UbException(UB_EXARGS,"ToCbVectorReceiverRcfPool receives only") ); }
+   void prepareForReceive() { this->rcfVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()   { this->rcfVectorPool->receiveData(); return this->getData();  }
+
+   //info-section (usable for remote transmitter)
+   int  getSendToRank()   const { UB_THROW( UbException(UB_EXARGS,"ToCbVectorReceiverRcfPool receives only") ); }
+   int  getSendToTag()    const { UB_THROW( UbException(UB_EXARGS,"ToCbVectorReceiverRcfPool receives only") ); }
+   int  getRecvFromRank() const { return  this->rcfVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->rcfVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "ToCbVectorReceiverRcfPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   ToCbVectorRcfPool<T>* rcfVectorPool;
+};
+
+#endif //CAB_RCF
+
+#endif //TOCBVECTORRCFPOOL_H
diff --git a/source/ThirdParty/Library/basics/utilities/CMakePackage.txt b/source/ThirdParty/Library/basics/utilities/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2bae505538e07aa6c724c29a4b8d472975ef29e0
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/CMakePackage.txt
@@ -0,0 +1,21 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES outOption)
+
+IF(${outOption})
+   IF(WIN32)
+      ADD_DEFINITIONS( -DNOMINMAX )
+   ENDIF(WIN32) 
+   
+   IF(BOOST_VERSION)
+    OPTION(USE_THREADSAFE_LOGGER "ON=thread safe, OFF=not thread safe" ON)
+    IF(NOT ${outOption})
+      ADD_DEFINITIONS( -DNO_THREADSAFE_LOGGING)
+    ELSE()
+      SET(NECESSARY_BOOST_LIBS ${NECESSARY_BOOST_LIBS} thread)
+    ENDIF()
+   ELSE()
+    #um die thread safe zu machen benoetigt man boost
+    ADD_DEFINITIONS( -DNO_THREADSAFE_LOGGING)
+   ENDIF()
+  
+ENDIF()
\ No newline at end of file
diff --git a/source/ThirdParty/Library/basics/utilities/UbAutoRun.hpp b/source/ThirdParty/Library/basics/utilities/UbAutoRun.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c9ac45115bb4ff37c45d69e101e9a58d936e5d7e
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbAutoRun.hpp
@@ -0,0 +1,58 @@
+#ifndef UB_AUTORUN_HPP
+#define UB_AUTORUN_HPP
+
+#define UB_AUTO_RUN(func)                              UB_AUTO_RUN_(func,  __LINE__)
+#define UB_AUTO_RUN_(func, nID)                        UB_AUTO_RUN__(func, nID)
+#define UB_AUTO_RUN__(func, nID)                       UB_AUTO_RUN___(func, nID)
+#define UB_AUTO_RUN___(func, ID)                                                           \
+    namespace {                                                                         \
+        struct UbAutoRun##ID {                                                            \
+            UbAutoRun##ID() {                                                             \
+                func;                                                                   \
+            }                                                                           \
+        } UbAutoRunInst##ID;                                                              \
+    }
+
+    // More concise to implement UB_AUTO_RUN using the following, but BCB emits an ICE on it.
+    //static bool UB_AutoRun##ID = ( func , false);
+
+
+#define UB_AUTO_RUN_1(func)                            UB_AUTO_RUN_NAMED(func, 1)                   
+#define UB_AUTO_RUN_2(func)                            UB_AUTO_RUN_NAMED(func, 2)                   
+#define UB_AUTO_RUN_3(func)                            UB_AUTO_RUN_NAMED(func, 3)                   
+#define UB_AUTO_RUN_4(func)                            UB_AUTO_RUN_NAMED(func, 4)                   
+#define UB_AUTO_RUN_5(func)                            UB_AUTO_RUN_NAMED(func, 5)                   
+                                                       
+#define UB_AUTO_RUN_NAMED(func, name)                  UB_AUTO_RUN_NAMED_(func, name, __LINE__)
+#define UB_AUTO_RUN_NAMED_(func, name, nID)            UB_AUTO_RUN_NAMED__(func, name, nID)
+#define UB_AUTO_RUN_NAMED__(func, name, nID)           UB_AUTO_RUN___(func, _##name##_##nID)
+                                                       
+#define UB_AUTO_RUN_ONCE(func)                         UB_AUTO_RUN_ONCE_(func,  __LINE__)
+#define UB_AUTO_RUN_ONCE_(func, nID)                   UB_AUTO_RUN_ONCE__(func, nID)
+#define UB_AUTO_RUN_ONCE__(func, nID)                  UB_AUTO_RUN_ONCE___(func, nID)
+#define UB_AUTO_RUN_ONCE___(func, ID)                                                   \
+    struct UbAutoRunOnce##ID {                                                            \
+        UbAutoRunOnce##ID() {                                                             \
+            if (!init()) {                                                              \
+                init() = true;                                                          \
+                func;                                                                   \
+            }                                                                           \
+        }                                                                               \
+        static bool &init() {                                                           \
+            static bool bInit = false;                                                  \
+            return bInit;                                                               \
+        }                                                                               \
+    };                                                                                  \
+    static UbAutoRunOnce##ID AutoRunOnceInst##ID;
+
+#define UB_AUTO_RUN_ONCE_1(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 1)                   
+#define UB_AUTO_RUN_ONCE_2(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 2)                   
+#define UB_AUTO_RUN_ONCE_3(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 3)                   
+#define UB_AUTO_RUN_ONCE_4(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 4)                   
+#define UB_AUTO_RUN_ONCE_5(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 5)                   
+                                                           
+#define UB_AUTO_RUN_ONCE_NAMED(func, name)                 UB_AUTO_RUN_ONCE_NAMED_(func, name, __LINE__)
+#define UB_AUTO_RUN_ONCE_NAMED_(func, name, nID)           UB_AUTO_RUN_ONCE_NAMED__(func, name, nID)
+#define UB_AUTO_RUN_ONCE_NAMED__(func, name, nID)          UB_AUTO_RUN_ONCE___(func, _##name##_##nID)
+
+#endif // ! UB_AUTORUN_HPP
diff --git a/source/ThirdParty/Library/basics/utilities/UbComparators.h b/source/ThirdParty/Library/basics/utilities/UbComparators.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d1448c93b6c0ee2b6361aad87a379140ffa0f49
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbComparators.h
@@ -0,0 +1,208 @@
+#ifndef UBCOMPARATORS_H 
+#define UBCOMPARATORS_H
+
+#include <functional> 
+
+/*=========================================================================*/
+/*  UbComparators                                                             */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 16.08.2007
+*/ 
+
+namespace UbComparators
+{
+   //type_traits 
+   template <typename T> struct MemberInfo; //not defined for correct compiler errors!
+
+   // specialization for MemberFunctionsPtr
+   // C - class with return T method
+   template <typename T, typename C> 
+   struct MemberInfo<T C::*> 
+   { 
+      typedef T type; 
+      typedef C class_type; 
+
+      static       T& apply(       C& c, T C::* ptr ) { return c.*ptr; } 
+      static const T& apply( const C& c, T C::* ptr ) { return c.*ptr; } 
+   }; 
+   //specialization for MemberFunctionsPtr
+   //C - class with return T method
+   template <typename T, typename C> 
+   struct MemberInfo<T (C::*)()> 
+   { 
+      typedef T type; 
+      typedef C class_type; 
+
+      static T apply( C& c, T (C::*ptr)() ) { return (c.*ptr)(); } 
+   }; 
+   //specialization for const MemberFunctionsPtr
+   //C - class with return T method
+   template <typename T, typename C> 
+   struct MemberInfo<T (C::*)() const> 
+   { 
+      typedef T type; 
+      typedef C class_type; 
+
+      static T apply( const C& c, T (C::*ptr)() const ) { return (c.*ptr)(); } 
+   }; 
+
+   //MemberComparative-Class
+   template <typename Ptr, typename Comp = std::less<typename MemberInfo<Ptr>::type> > 
+   class MemComp 
+      : private Comp  // -> usage of Empty Base Class Optimization (EBCO) 
+   { 
+      typedef typename MemberInfo<Ptr>::class_type C; 
+
+   public: 
+      MemComp( Ptr ptr, Comp c = Comp() ) 
+         : Comp(c), mp_(ptr) 
+      {} 
+
+      bool operator()(C& lhs, C& rhs) 
+      { 
+         return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); 
+      } 
+      bool operator()(C& lhs, C& rhs) const 
+      { 
+         return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); 
+      } 
+      bool operator()(const C& lhs, const C& rhs) 
+      { 
+         return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); 
+      } 
+      bool operator()(const C& lhs, const C& rhs) const 
+      { 
+         return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); 
+      } 
+
+   private: 
+      Ptr mp_; 
+   }; 
+
+   // Factoryfunktionen 
+   template <typename Ptr> 
+   MemComp<Ptr> membercomp(Ptr p) 
+   { 
+      return MemComp<Ptr>(p); 
+   } 
+
+   template<typename Comp, typename Ptr> 
+   MemComp<Ptr, Comp> membercomp(Ptr p, Comp c = Comp()) 
+   { 
+      return MemComp<Ptr, Comp>(p, c); 
+   } 
+
+   template<template<typename> class Comp, typename Ptr> 
+   MemComp<Ptr, Comp<typename MemberInfo<Ptr>::type> > 
+      membercomp(Ptr p, Comp<typename MemberInfo<Ptr>::type> c = Comp<typename MemberInfo<Ptr>::type>()) 
+   {
+      return MemComp<Ptr, Comp<typename MemberInfo<Ptr>::type> >(p, c); 
+   } 
+
+    
+   //////////////////////////////////////////////////////////////////////////
+   //////////////////////////////////////////////////////////////////////////
+   //////////////////////////////////////////////////////////////////////////
+   //andere Variante (alerdings ist hier keine Deduction moeglich!!!)
+   //////////////////////////////////////////////////////////////////////////
+   //Vergleichs-Templates:
+   //Funktor zum "non-const" Methodenvergleich: liste.sort( compareMethods<Klasse, int, &Klasse::getVal1  );
+   template<typename K/*Klasse*/, typename M /*MethodenRueckgabeTyp*/, M (K::*fct)() /*MethodenPointer*/> // Allgemeiner Fall
+   struct compareMethods
+   {
+      bool operator()(K& r, K& l) const // da fct nicht const ist, kann auch K nicht const sein. das const hinter der deklaration besagt dass compareMethods const sein kann
+      { return (r.*fct)() < (l.*fct)();  }
+   };
+   //////////////////////////////////////////////////////////////////////////
+   //Funktor zum "const" Methodenvergleich: liste.sort( compareMethods<Klasse, int, &Klasse::getVal1  );
+   template<typename K/*Klasse*/, typename M /*MethodenRueckgabeTyp*/, M (K::*fct)() const /*MethodenPointer*/> // <- hier const 
+   struct compareConstMethods
+   {
+      bool operator()(const K& r, const K& l) const //hier koennen die K's auch const sein, muessen sie aber nicht (const hinzufuegen geht ja problemlos)
+      { return (r.*fct)() < (l.*fct)();  }
+   };
+   //////////////////////////////////////////////////////////////////////////
+   //Funktor zum Membervergleich: lise.sort( compareMember<Klasse, int, &Klasse::member>() );
+   template<typename K/*Klasse*/, typename M /*MemberTyp*/, M (K::*Member) /*MemberPointer*/> // <- hier const 
+   struct compareMember
+   { 
+      bool operator()(const K& r,const K& l) const
+      { return r.*Member < l.*Member; } 
+   };
+   //Bsp:
+   //class Klasse{ 
+   //public: 
+   //   Klasse(double val1, double val2 ) : val1(val1),val2(val2) {} 
+   //   double getVal1()       { return val1; } 
+   //   double getVal2() const { return val2; } // <- hier const
+   //   double val1, val2; 
+   //}; 
+   //int main(int argc, char** argv){ 
+   //   std::list<Klasse> l; 
+   //   l.push_back( Klasse(10,10) ); 
+   //   l.push_back( Klasse(1,5)   ); 
+   //   l.sort( compareMember<Klasse, double,  &Klasse::val1 >() ); 
+   //   l.sort( compareMethods<Klasse, double,  &Klasse::getVal1 >() ); 
+   //   l.sort( compareConstMethods<Klasse, double,  &Klasse::getVal1 >() ); 
+   //} 
+
+};
+
+#endif //UBCOMPARATOR_H
+
+//example
+// #include <basics/utilities/UbComparators.h" 
+// #include <list> 
+// using namespace std; 
+// using namespace UbComparators; 
+// 
+// struct S { 
+//    S(int i) :x(i) {} 
+//    int x; 
+//    float f() {return x;}; 
+//    double g() const {return x;} 
+// }; 
+// 
+// struct intComp { 
+//    bool operator()(int l, int r) const 
+//    { return l > r; } 
+// }; 
+// 
+// struct dblComp { 
+//    bool operator()(double l,  double r) const 
+//    { return l > r; } 
+// }; 
+// 
+// template <typename T> 
+// struct genComp { 
+//    bool operator()(const T& l, const T& r) const
+//    { return l > r; } 
+// }; 
+// 
+// 
+// int main() 
+// { 
+//    S a(1); 
+//    S b(2); 
+//    list<S> sList; 
+//    sList.push_back(a); 
+//    sList.push_back(b); 
+//    sList.sort(UbComparators::membercomp(&S::x,intComp()));  //calls overload (1) 
+//    sList.sort(UbComparators::membercomp<intComp>(&S::x));   //same 
+//    sList.sort(UbComparators::membercomp(&S::x));            //calls overload (5) 
+//    sList.sort(UbComparators::membercomp<genComp>(&S::x));   //calls overload(3) 
+//    sList.sort(UbComparators::membercomp(&S::x, genComp<int>())); //calls overload(1) 
+//    //same for nonconst function 
+//    sList.sort(UbComparators::membercomp(&S::f, dblComp())); //overload(2) 
+//    sList.sort(UbComparators::membercomp<dblComp>(&S::f));   //same      
+//    sList.sort(UbComparators::membercomp(&S::f));            //overload(6) 
+//    sList.sort(UbComparators::membercomp<genComp>(&S::f));   //overload(4) 
+//    //same for const function 
+//    sList.sort(UbComparators::membercomp(&S::g, dblComp())); //overload(2) 
+//    sList.sort(UbComparators::membercomp<dblComp>(&S::g));   //same      
+//    sList.sort(UbComparators::membercomp(&S::g));            //overload(6) 
+//    sList.sort(UbComparators::membercomp<genComp>(&S::g));   //overload(4) 
+// } 
diff --git a/source/ThirdParty/Library/basics/utilities/UbConverter.cpp b/source/ThirdParty/Library/basics/utilities/UbConverter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad5a99923c0985192555d6ed95efd7502a0efe18
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbConverter.cpp
@@ -0,0 +1,96 @@
+#include <basics/utilities/UbConverter.h>
+
+const std::string UbConverter::base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                              "abcdefghijklmnopqrstuvwxyz"
+                                              "0123456789+/";
+
+
+std::string UbConverter::base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) 
+{
+   std::string ret;
+   int i = 0;
+   int j = 0;
+   unsigned char char_array_3[3];
+   unsigned char char_array_4[4];
+
+   while (in_len--)
+   {
+      char_array_3[i++] = *(bytes_to_encode++);
+      if( i==3)
+      {
+         char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2;
+         char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+         char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+         char_array_4[3] = char_array_3[2] & 0x3f;
+
+         for( i=0; i<4 ; i++)
+            ret += base64_chars[char_array_4[i]];
+         i=0;
+      }
+   }
+
+   if( i )
+   {
+      for( j=i; j<3; j++)
+         char_array_3[j] = '\0';
+
+      char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2;
+      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+      char_array_4[3] = char_array_3[2] & 0x3f;
+
+      for ( j=0; j<i+1; j++)
+         ret += base64_chars[char_array_4[j]];
+
+      while( i++<3 )
+         ret += '=';
+   }
+
+   return ret;
+}
+/*=======================================================*/
+std::string UbConverter::base64_decode(std::string const& encoded_string) 
+{
+   int in_len = (int)encoded_string.size();
+   int i = 0;
+   int j = 0;
+   int in_ = 0;
+   unsigned char char_array_4[4], char_array_3[3];
+   std::string ret;
+
+   while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) 
+   {
+      char_array_4[i++] = encoded_string[in_]; in_++;
+      if(i ==4)
+      {
+         for (i = 0; i <4; i++)
+            char_array_4[i] = (unsigned char)base64_chars.find(char_array_4[i]);
+
+         char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+         char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+         char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+         for (i = 0; (i < 3); i++)
+            ret += char_array_3[i];
+         i = 0;
+      }
+   }
+
+   if( i )
+   {
+      for(j = i; j <4; j++)
+         char_array_4[j] = 0;
+
+      for(j = 0; j <4; j++)
+         char_array_4[j] = (unsigned char)base64_chars.find(char_array_4[j]);
+
+      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+      for(j = 0; (j < i - 1); j++) 
+         ret += char_array_3[j];
+   }
+
+   return ret;
+}
diff --git a/source/ThirdParty/Library/basics/utilities/UbConverter.h b/source/ThirdParty/Library/basics/utilities/UbConverter.h
new file mode 100644
index 0000000000000000000000000000000000000000..51e713cd47e832848d47a9db022078666222b3e6
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbConverter.h
@@ -0,0 +1,49 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBCONVERTER_H 
+#define UBCONVERTER_H 
+
+#include <cstdlib> 
+#include <ctime> 
+#include <cassert> 
+#include <string>
+
+/*=========================================================================*/
+/*  UBConverter                                                             */
+/*                                                                         */
+//
+// encodes  vals to   e.g. base64
+// dencodes vals from e.g. base64
+// author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+// version 1.0 - 22.10.2007
+
+
+class UbConverter
+{
+public:
+   static std::string base64_encode(unsigned char const* , unsigned int len);
+   static std::string base64_decode(std::string const& s);
+
+   static inline bool is_base64(const unsigned char& c)
+   {
+      return (isalnum(c) || (c == '+') || (c == '/'));
+   }
+
+protected:
+   UbConverter() {}
+   ~UbConverter() {}
+
+private:
+   UbConverter(const UbConverter&);  // not implemented.
+   void operator=(const UbConverter&);  //not implemented.
+
+   static const std::string base64_chars;
+};
+
+
+
+#endif //UBCONVERTER_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbEqual.h b/source/ThirdParty/Library/basics/utilities/UbEqual.h
new file mode 100644
index 0000000000000000000000000000000000000000..e838aca00223d0e0064784dc555ee51d13efe144
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbEqual.h
@@ -0,0 +1,120 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBEQUAL_H
+#define UBEQUAL_H
+
+#include<cmath>
+
+//////////////////////////////////////////////////////////////////////////
+//isUbEqual<T1,T2>(a,b)
+//vergleicht die gleichtheit der beiden werte a und b
+//
+//std-maessig wird hierfür der operator== verwendet
+//
+//Ausnahme: floating-points
+//hier wird jeweils der "genauere typ zum ungenaueren gecastet und dann verglichen"
+//e.g.: double d=1.2; int i=1; bool check = isUbEqual(d,i); -> true
+//
+//bei klassen muss hier operator== fuer const objecte implementiert sein!!!
+//e.g.: bool operator==(const Test&) const { if(blabla) return true; else return false; }
+//
+//
+//author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//version 1.0 - 25.03.2008
+//////////////////////////////////////////////////////////////////////////
+
+//std-trait, fuer alle nicht spezifischen typen:
+template < typename T1, typename T2 >
+struct UbEqualTrait
+{
+   typedef T1 High;
+   typedef T1 Low;
+};
+
+//std-trait, fuer gleiche T
+template < typename T >
+struct UbEqualTrait< T, T >
+{
+   typedef T High;
+   typedef T Low;
+};
+
+//spezialisierung für diverse Typen-Tuples
+template<> struct UbEqualTrait< short, int >          { typedef int         High; typedef short  Low; };
+template<> struct UbEqualTrait< short, long >         { typedef long        High; typedef short  Low; };
+template<> struct UbEqualTrait< short, float >        { typedef float       High; typedef short  Low; };
+template<> struct UbEqualTrait< short, double >       { typedef double      High; typedef short  Low; };
+template<> struct UbEqualTrait< short, long double >  { typedef long double High; typedef short  Low; };
+
+template<> struct UbEqualTrait< int, short >          { typedef int         High; typedef short  Low; };
+template<> struct UbEqualTrait< int, long >           { typedef long        High; typedef int    Low; };
+template<> struct UbEqualTrait< int, float >          { typedef float       High; typedef int    Low; };
+template<> struct UbEqualTrait< int, double >         { typedef double      High; typedef int    Low; };
+template<> struct UbEqualTrait< int, long double >    { typedef long double High; typedef int    Low; };
+
+template<> struct UbEqualTrait< long, short >         { typedef long        High; typedef short  Low; };
+template<> struct UbEqualTrait< long, int >           { typedef long        High; typedef int    Low; };
+template<> struct UbEqualTrait< long, float >         { typedef float       High; typedef long   Low; };
+template<> struct UbEqualTrait< long, double >        { typedef double      High; typedef long   Low; };
+template<> struct UbEqualTrait< long, long double >   { typedef long double High; typedef long   Low; };
+
+template<> struct UbEqualTrait< float, short >        { typedef float       High; typedef short  Low; };
+template<> struct UbEqualTrait< float, int >          { typedef float       High; typedef int    Low; };
+template<> struct UbEqualTrait< float, long >         { typedef float       High; typedef long   Low; };
+template<> struct UbEqualTrait< float, double >       { typedef double      High; typedef float  Low; };
+template<> struct UbEqualTrait< float, long double >  { typedef long double High; typedef float  Low; };
+
+template<> struct UbEqualTrait< double, short >       { typedef double      High; typedef short  Low; };
+template<> struct UbEqualTrait< double, int >         { typedef double      High; typedef int    Low; };
+template<> struct UbEqualTrait< double, long >        { typedef double      High; typedef long   Low; };
+template<> struct UbEqualTrait< double, float >       { typedef double      High; typedef float  Low; };
+template<> struct UbEqualTrait< double, long double > { typedef long double High; typedef double Low; };
+
+template<> struct UbEqualTrait< long double, short >  { typedef long double High; typedef short  Low; };
+template<> struct UbEqualTrait< long double, int >    { typedef long double High; typedef int    Low; };
+template<> struct UbEqualTrait< long double, long >   { typedef long double High; typedef long   Low; };
+template<> struct UbEqualTrait< long double, float >  { typedef long double High; typedef float  Low; };
+template<> struct UbEqualTrait< long double, double > { typedef long double High; typedef double Low; };
+
+//////////////////////////////////////////////////////////////////////////
+//fuer Allgmeine-Typen ( operator== ):
+template< typename T1, typename T2 >
+inline bool specific_equal(const T1& a, const T2& b) { return a==b; }
+
+//////////////////////////////////////////////////////////////////////////
+//fuer floating point build-in-type
+//float.float
+template< /*float,float*/>
+inline bool specific_equal< float, float >(const float& a, const float& b) {  return std::fabs( a - b ) < 1E-8; }
+
+template</*double,double*/>
+inline bool specific_equal< double, double >(const double& a, const double& b) { return std::fabs( a - b ) < 1E-13; }
+
+template</*long double,long double*/>
+inline bool specific_equal< long double, long double >(const long double& a, const long double& b) { return std::fabs( a - b ) < 1E-16; }
+
+//////////////////////////////////////////////////////////////////////////
+//globale isUbEqual - Funktion
+template< typename T1, typename T2 >
+inline bool isUbEqual(const T1& a, const T2& b)
+{
+   typedef typename UbEqualTrait<T1,T2>::Low Low;
+   return specific_equal< Low, Low >(static_cast< Low >( a ),static_cast< Low >( b ));
+};
+
+//////////////////////////////////////////////////////////////////////////
+//UbEqual-Functor
+template< typename T1, typename T2 >
+struct UbEqual
+{
+   bool operator()(const T1& a, const T2& b)
+   {
+      return isUbEqual(a,b);
+   }
+};
+
+#endif //UBEQUAL_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbException.h b/source/ThirdParty/Library/basics/utilities/UbException.h
new file mode 100644
index 0000000000000000000000000000000000000000..48d1e1a60065d6f6e057aafa59abded38b800664
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbException.h
@@ -0,0 +1,163 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBEXCEPTION_H
+#define UBEXCEPTION_H
+
+#include <vector>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <boost/exception/all.hpp>
+
+#include "./UbTuple.h"
+
+/*=========================================================================*/
+/*  UbException                                                             */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0  - 23.11.04
+@version 1.5  - 14.03.08
+@version 1.6  - 31.03.08 derivation from std::run_time_error
+@version 1.6a - helper marco UB_EXARGS
+*/ 
+
+/*
+usage: UB_THROW( UbException("error message") );
+       UB_THROW( UbException(__FILE__, __LINE__,"error message") );
+       UB_THROW( UbException(__FILE__, __LINE__,UB_FUNCTION,"error message") );
+       UB_THROW( UbException(UB_EXARGS,"error") ); //same as above
+*/
+
+//Macro UB_FUNCTION: figures out the method/function name (platform dependant)
+#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
+ # define UB_FUNCTION __PRETTY_FUNCTION__
+#elif defined(__DMC__) && (__DMC__ >= 0x810)
+ # define UB_FUNCTION __PRETTY_FUNCTION__
+#elif defined(__FUNCSIG__)
+ # define UB_FUNCTION __FUNCSIG__
+#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
+ # define UB_FUNCTION __FUNCTION__
+#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
+ # define UB_FUNCTION __FUNC__
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
+ # define UB_FUNCTION __func__
+#else
+ # define UB_FUNCTION "(unknown)"
+#endif
+
+//Helper Marco
+#define UB_EXARGS __FILE__,__LINE__,UB_FUNCTION
+
+#ifdef CAB_BOOST
+   #define UB_THROW(e) throw boost::enable_current_exception(e)
+#else
+   #define UB_THROW(e) throw e
+#endif
+
+class UbException : public std::runtime_error, public boost::exception
+{
+public:
+   typedef UbTuple< std::string, int, std::string, std::string > ExceptionData;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //constructors
+   UbException()
+      : std::runtime_error("")
+   { 
+   }
+   /*==========================================================*/
+   UbException(const std::string& str)
+      : std::runtime_error("")
+   {
+      this->addInfo(str);		
+   }
+   /*==========================================================*/
+   UbException(const std::string& file, const int& line, const std::string& err_str)
+      : std::runtime_error("")
+   {
+      this->addInfo(file,line,"unknown",err_str);		
+   }
+   /*==========================================================*/
+   //UbException(const char* file, const int& line, const char* function, const std::string& err_str)
+   UbException(const std::string& file, const int& line, const std::string& function, const std::string& err_str)
+      : std::runtime_error("")
+   {
+      this->addInfo(file,line,function,err_str);		
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //destructor
+   virtual ~UbException() throw() { }
+   //////////////////////////////////////////////////////////////////////////
+   //virtual public methods
+   //returns  exception-string
+   virtual const char* what() const throw()
+   {
+      exceptionString = this->toString();
+      return exceptionString.c_str();  //ansonsten ist das Verhalten anschließend undefiniert!
+   }
+   /*==========================================================*/
+   virtual void addInfo(const std::string& err_str)	 
+   { 
+      exceptionData.push_back( makeUbTuple( (std::string)"-", 0, (std::string)"unknown", err_str) ); 
+   }
+   /*==========================================================*/
+   //add exception
+   virtual void addInfo(const std::string& file, const int& line, const std::string& function, const std::string& err_str)	 
+   { 
+      exceptionData.push_back( makeUbTuple( file, line, function, err_str ) ); 
+   }
+   /*==========================================================*/
+   //returns exception-string with all calles exceptions
+   virtual const std::vector<std::string> getInfo() const
+   { 
+      std::vector<std::string> tmp;
+      for(std::size_t i=0; i<exceptionData.size(); i++)
+      {
+         std::stringstream str;
+         str << val<1>( exceptionData[i] ) << ", " 
+             << val<2>( exceptionData[i] ) << ", " 
+             << val<3>( exceptionData[i] ) << ", " 
+             << val<4>( exceptionData[i] );
+         tmp.push_back( str.str());
+      }
+      return tmp; 
+   }
+   /*==========================================================*/
+   //returns exception-string with all calles exceptions and detailes informations
+   virtual std::string toString() const
+   { 
+      std::stringstream str("UbExeption");
+      
+      for(std::size_t i=0; i<exceptionData.size(); i++)
+         str<<(std::string)"caller[" << i << "]\n"
+            <<"  - file:     "<< val<1>( exceptionData[i] )<<"\n"
+            <<"  - line:     "<< val<2>( exceptionData[i] )<<"\n"
+            <<"  - function: "<< val<3>( exceptionData[i] )<<"\n"
+            <<"  - what:     "<< val<4>( exceptionData[i] )<< std::endl; 
+
+      return str.str();
+   }
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   //protected member
+   std::vector< ExceptionData > exceptionData;
+   mutable std::string exceptionString;
+};
+
+//overlading operator <<
+inline std::ostream& operator<<(std::ostream& os, const UbException& e)
+{
+   return os<<e.toString();
+}
+
+#endif //UBEXCEPTION_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileInput.h b/source/ThirdParty/Library/basics/utilities/UbFileInput.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b08a7fdb532c3b5b45cc14d3315dd1eee52b379
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileInput.h
@@ -0,0 +1,97 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEINPUT_H
+#define UBFILEINPUT_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <cstdlib> //atoi
+#include <cstring> //strstr
+
+#include <basics/utilities/UbException.h>
+
+/*=========================================================================*/
+/*  UbFileInput                                                            */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/
+
+/*
+usage: ...
+*/
+
+class UbFileInput
+{
+public:
+   enum FILETYPE {ASCII, BINARY};      
+
+public:
+   UbFileInput() : filename(""), commentindicator('C') { }
+   virtual ~UbFileInput() { infile.close(); }
+
+   virtual bool        operator!() { return !(infile); }
+   virtual bool        isOpen()    { return !(!(infile)); }
+
+   virtual bool        open(std::string filename)=0;
+   virtual void        close() { infile.close(); }
+   virtual int         eof()   { return infile.eof(); }
+
+   virtual void        skipLine()=0;					// Springt zur naechsten Zeile
+	virtual void        readLine()=0;
+   virtual std::string readStringLine()=0;
+	virtual int		     readInteger()=0;				// Liest einen Int-Wert ein
+   virtual std::size_t readSize_t()=0;
+   virtual double	     readDouble()=0;				   // Liest einen double-Wert ein
+	virtual float	     readFloat()=0;				   // Liest einen float-Wert ein
+	virtual bool  	     readBool()=0;				   // Liest einen bool-Wert ein
+   virtual char  	     readChar()=0;				   // Liest einen char-Wert ein
+   virtual std::string readString()=0;			      // Liest ein Wort ein
+	virtual std::string readLineTill(char stop)=0;	// Liest gesamte Zeile ein bis zu einem bestimmten Zeichen
+	virtual std::string parseString()=0;	         // Liest
+
+   virtual void        setCommentIndicator(char commentindicator) {this->commentindicator = commentindicator;}
+
+   virtual bool        containsString( const std::string& var)=0;
+   virtual void        setPosAfterLineWithString( const std::string& var)=0;
+   virtual int		     readIntegerAfterString( const std::string& var)=0;
+   virtual double	     readDoubleAfterString( const std::string& var)=0;
+   virtual bool        readBoolAfterString( const std::string& var)=0;
+   virtual std::string readStringAfterString( const std::string& var)=0;
+
+   virtual std::string getFileName() {return this->filename;}
+
+   //returns file extension:
+   //e.g. "./../test/ich.inp" -> "inp", "./../test/ich" -> ""
+   virtual std::string getFileExtension()
+   {
+      std::size_t pos1 = filename.rfind("/");
+      if(pos1==std::string::npos) pos1 = 0;
+      std::size_t pos2 = filename.rfind(".");
+      if(pos2!=std::string::npos && pos2>pos1)
+         return filename.substr(pos2+1);
+
+      return "";
+   }
+
+   //returns "ASCII", "BINARY"
+   virtual FILETYPE getFileType()=0;
+
+protected:
+   std::ifstream infile;
+   std::string   filename;
+   char          commentindicator;
+};
+
+#endif //UBFILEINPUT_H
+
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileInputASCII.cpp b/source/ThirdParty/Library/basics/utilities/UbFileInputASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d17d69cf9c3555f3ab742ec5922e3872ba93b796
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileInputASCII.cpp
@@ -0,0 +1,227 @@
+#include <basics/utilities/UbFileInputASCII.h>
+#include <cstring>
+
+using namespace std;
+
+UbFileInputASCII::UbFileInputASCII(string filename)
+{
+	this->filename         = filename;
+   this->commentindicator = 'C';
+
+   infile.open(filename.c_str());
+
+   //if(!infile) UB_THROW( UbException((string)("UbFileInputASCII::UbFileInputASCII(string filename, int how) couldn't open file:\n "+filename)) );
+}
+/*==========================================================*/
+bool UbFileInputASCII::open(string filename)
+{
+   infile.close();
+   infile.clear(); //setzt flags zurueck
+
+   this->filename = filename;
+   infile.open(this->filename.c_str());
+
+   return infile.is_open();
+}
+/*==========================================================*/
+int UbFileInputASCII::readInteger()
+{
+	int dummy;
+	infile>>dummy;
+	return dummy;
+}
+/*==========================================================*/
+string UbFileInputASCII::getFileName()
+{
+	return this->filename;
+}
+
+/*==========================================================*/
+void UbFileInputASCII::skipLine()
+{
+	string dummy;
+	getline(infile, dummy);
+}
+/*==========================================================*/
+void UbFileInputASCII::readLine()
+{
+	string dummy;
+	getline(infile, dummy);
+}
+/*==========================================================*/
+string UbFileInputASCII::readStringLine()
+{
+   string dummy;
+   getline(infile, dummy);
+   return dummy;
+}
+/*==========================================================*/
+string UbFileInputASCII::readLineTill(char stop)
+{
+	string dummy;
+	getline(infile, dummy, stop);
+	return dummy;
+}
+/*==========================================================*/
+string UbFileInputASCII::parseString()
+{
+	string dummy;
+	getline(infile, dummy, ' ');
+	return dummy;
+}
+/*==========================================================*/
+double UbFileInputASCII::readDouble()
+{
+   double dummy;
+   infile>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+float UbFileInputASCII::readFloat()
+{
+   float dummy;
+   infile>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+string UbFileInputASCII::readString()
+{
+	string dummy;
+	infile>>dummy;
+	return dummy;
+}
+/*==========================================================*/
+char UbFileInputASCII::readChar()
+{
+   int dummy;
+   infile>>dummy;
+   return (char)dummy;
+}
+/*==========================================================*/
+std::size_t UbFileInputASCII::readSize_t()
+{
+   std::size_t dummy;
+   infile>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+void UbFileInputASCII::setPosAfterLineWithString(const string& var)
+{
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+   char line[512];
+   do
+   {
+      infile.getline(line,512);
+      if(infile.eof()) UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> string "+var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+}
+/*==========================================================*/
+bool UbFileInputASCII::containsString(const string& var)
+{
+   infile.clear(); // setzt den EOF-Status zurueck (wird durch infile.seekg() NICHT getan!!!)
+
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+   char line[512];
+   do
+   {
+      infile.getline(line,512);
+      if(infile.eof()) return false;
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+
+   return true;
+}
+/*==========================================================*/
+int UbFileInputASCII::readIntegerAfterString(const string& var)
+// last change [10.3.2004] at [9:46]
+//suchts in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. timesteps 9
+{
+   infile.clear(); // setzt den EOF-Status zurueck (wird durch infile.seekg() NICHT getan!!!)
+   
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];
+
+   do
+   {
+      infile.getline(line,512);
+      if(infile.eof()) UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> "+var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+
+   strcpy (line, (line+strlen(var.c_str())));	    // zeile um "varname" kuerzen
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   return(atoi(line));						// Umwandlung in int
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46]
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+double UbFileInputASCII::readDoubleAfterString(const string& var)
+{
+   infile.clear(); // setzt den EOF-Status zurueck (wird durch infile.seekg() NICHT getan!!!)
+   
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];
+
+   do
+   {
+      infile.getline(line,512);
+      if(infile.eof()) UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> "+var+" wasn't found in "+this->filename) );
+   }while (/*!strncmp(varname,line,sizeof(varname))==0*/strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+
+
+   strcpy (line, (line+strlen(var.c_str())));	    // zeile um "varname" kuerzen
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   return (atof(line));			// Umwandlung in double
+}
+/*==========================================================*/
+//  [9.9.2002]
+// liefert string-Wert der hinter dem uebergebenen char feld in der datei infile steht
+// zudem wird der wert in die uebergebene variable value uebertragen (falls man das ergebniss als char benoetig)
+string UbFileInputASCII::readStringAfterString(const string& var)//,char *value)
+{
+   infile.clear(); // setzt den EOF-Status zurueck (wird durch infile.seekg() NICHT getan!!!)
+   
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];
+   //string line_copy[512];
+
+   do{
+      infile.getline(line,512);
+      if(infile.eof()) UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> "+var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+
+   strcpy (line, (line+strlen(var.c_str())));										// zeile um "varname" kuerzen
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   char *p;
+   p=strtok(line," "); //schneidet alles "ab und inklusive space " nach namen ab
+   p=strtok(line,"\t");//schneidet alles "ab und inklusive tab   " nach namen ab
+
+   return static_cast<string>(p);			// Umwandlung in string
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46]
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+bool UbFileInputASCII::readBoolAfterString(const string& var)
+{
+   if(this->readStringAfterString(var)      == "true" ) return true;
+   else if(this->readStringAfterString(var) == "false") return false;
+   else UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> expression after "+var+" is not equal to 'true' or 'false' in "+this->filename) );
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46]
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+bool UbFileInputASCII::readBool()
+{
+   string tmp = this->readString();
+   if(     tmp == "true" ) return true;
+   else if(tmp == "false") return false;
+   else UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> expression=\""+tmp+"\" is not equal to 'true' or 'false' in "+this->filename) );
+}
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileInputASCII.h b/source/ThirdParty/Library/basics/utilities/UbFileInputASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..77c07137bbaf9c9b542ac1b1e939729af15dd85f
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileInputASCII.h
@@ -0,0 +1,73 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEINPUTASCII_H
+#define UBFILEINPUTASCII_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+
+/*=========================================================================*/
+/*  UbFileInputASCII                                                       */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileInputASCII : public UbFileInput
+{                               
+public:
+   UbFileInputASCII() : UbFileInput() { }
+   UbFileInputASCII(std::string filename);
+	
+   bool open(std::string filename);
+
+   std::string getFileName();				
+	void	      skipLine();					   // Springt zur naechsten Zeile
+
+   void        readLine();		 
+   std::string readStringLine();				
+	int		   readInteger();				   // Liest einen Int-Wert ein
+   std::size_t readSize_t();
+   double	   readDouble();				   // Liest einen double-Wert ein
+	float 	   readFloat();				   // Liest einen float-Wert ein
+	bool  	   readBool();				      // Liest einen bool-Wert ein
+   char        readChar();                // Liest einen char-Wert ein
+   std::string	readString();				   // Liest ein Wort ein
+	std::string	readLineTill(char stop);	// Liest gesamte Zeile ein bis zu einem bestimmten Zeichen
+	std::string	parseString();	
+
+   bool        containsString(const std::string& var);
+   void        setPosAfterLineWithString(const std::string& var);
+   int		   readIntegerAfterString(const std::string& var);
+   double	   readDoubleAfterString(const std::string& var);
+   bool        readBoolAfterString(const std::string& var);
+   std::string readStringAfterString(const std::string& var);
+
+   FILETYPE getFileType() { return ASCII; }
+
+   template< typename T >
+   friend inline UbFileInputASCII& operator>>(UbFileInputASCII& file, T& data) 
+   {
+      file.infile>>data;
+      return file;
+   }
+};
+
+#endif //UBFILEINPUTASCII_H
+
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileInputBinary.cpp b/source/ThirdParty/Library/basics/utilities/UbFileInputBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0bcf60ce0ca665403e95d6f0f5366e03c18382fb
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileInputBinary.cpp
@@ -0,0 +1,150 @@
+#include <basics/utilities/UbFileInputBinary.h>
+#include <cstring>
+
+using namespace std;
+
+/*==========================================================*/
+UbFileInputBinary::UbFileInputBinary(string filename)
+{
+	this->filename = filename;
+   infile.open(filename.c_str(), ios::in | ios::binary);
+}
+/*==========================================================*/
+bool UbFileInputBinary::open(string filename)
+{
+   infile.close();
+   infile.clear(); //setzt flags zurueck
+   
+   this->filename = filename;
+   infile.open(this->filename.c_str(), ios::in | ios::binary);
+
+   return infile.is_open();
+}
+/*==========================================================*/
+int UbFileInputBinary::readInteger()				
+{
+   int dummy;
+   infile.read((char*)&dummy,sizeof(int));
+   return dummy; 
+}
+/*==========================================================*/
+std::size_t UbFileInputBinary::readSize_t()				
+{
+   std::size_t dummy;
+   infile.read((char*)&dummy,sizeof(std::size_t));
+   return dummy;
+}
+/*==========================================================*/
+double UbFileInputBinary::readDouble()	
+{
+   double dummy;
+   infile.read((char*)&dummy,sizeof(double));
+   return dummy; 
+}
+/*==========================================================*/
+float UbFileInputBinary::readFloat()	
+{
+	float dummy;
+	infile.read((char*)&dummy,sizeof(float));
+	return dummy; 
+}
+/*==========================================================*/
+char UbFileInputBinary::readChar()	
+{
+   char dummy;
+   infile.read((char*)&dummy,sizeof(char));
+   return dummy; 
+}
+/*==========================================================*/
+string UbFileInputBinary::readString()	
+{
+   char c;
+   infile.read(&c,sizeof(char));
+   while(c==' ' || c=='\t') infile.read(&c,sizeof(char));  
+   
+   string dummy;
+   dummy+=c;
+
+   infile.read(&c,sizeof(char));
+   while(c!='\0' && c!=' ' && c!='\t' && c!='\n')
+   {
+      dummy+=c;
+      infile.read(&c,sizeof(char));
+   }
+   return dummy;
+}
+/*==========================================================*/
+bool UbFileInputBinary::readBool()	
+{
+   bool dummy;
+   infile.read((char*)&dummy,sizeof(bool));
+   return dummy; 
+}
+/*==========================================================*/
+void UbFileInputBinary::skipLine()				
+{
+   char c;
+   do{
+      infile.read(&c,sizeof(char));
+   }while(c!='\n');
+}
+/*==========================================================*/
+void UbFileInputBinary::readLine()				
+{
+   char c;
+   infile.read(&c,sizeof(char));
+   while(c!='\n') infile.read(&c,sizeof(char));
+}
+/*==========================================================*/
+string UbFileInputBinary::readStringLine()				
+{
+   char c;
+   string dummy;
+   infile.read(&c,sizeof(char));
+   while(c!='\n')
+   {
+      dummy+=c;
+      infile.read(&c,sizeof(char));
+   }
+   return dummy;
+}
+/*==========================================================*/
+string UbFileInputBinary::readLineTill(char stop)				
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+string UbFileInputBinary::parseString()				
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+bool UbFileInputBinary::containsString(const string& var)
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+void UbFileInputBinary::setPosAfterLineWithString(const string& var)
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+int UbFileInputBinary::readIntegerAfterString(const string& var)
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+double UbFileInputBinary::readDoubleAfterString(const string& var)	
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+string UbFileInputBinary::readStringAfterString(const string& var)	
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+bool UbFileInputBinary::readBoolAfterString(const string& var)	
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileInputBinary.h b/source/ThirdParty/Library/basics/utilities/UbFileInputBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e994ba792ccf82941cd6cf2aba87e5edeb9f51e
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileInputBinary.h
@@ -0,0 +1,71 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEINPUTBINARY_H
+#define UBFILEINPUTBINARY_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+
+/*=========================================================================*/
+/*  UbFileInputBinary                                                      */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileInputBinary : public UbFileInput
+{                               
+public:
+   UbFileInputBinary() : UbFileInput() {  }
+   UbFileInputBinary(std::string filename);
+	
+	bool        open(std::string filename);
+
+   void	      skipLine();					   // Springt zur naechsten Zeile
+	void        readLine();		 
+   std::string readStringLine();				
+   std::size_t readSize_t();				
+   int		   readInteger();				   // Liest einen Int-Wert ein
+	double	   readDouble();				   // Liest einen double-Wert ein
+	float 	   readFloat();				   // Liest einen float-Wert ein
+	bool  	   readBool();				      // Liest einen bool-Wert ein
+   char        readChar();                // Liest einen char-Wert ein
+   std::string	readString();				   // Liest ein Wort ein
+	std::string	readLineTill(char stop);	// Liest gesamte Zeile ein bis zu einem bestimmten Zeichen
+	std::string	parseString();	// Liest 
+
+   bool        containsString(const std::string& var);
+   void        setPosAfterLineWithString(const std::string& var);
+   int		   readIntegerAfterString(const std::string& var);
+   double	   readDoubleAfterString(const std::string& var);
+   bool        readBoolAfterString(const std::string& var);
+   std::string readStringAfterString(const std::string& var);
+
+   FILETYPE getFileType() { return BINARY; }
+
+   template< typename T >
+   friend inline UbFileInputBinary& operator>>(UbFileInputBinary& file, T& data) 
+   {
+      file.infile.read((char*)&data,sizeof(T));
+      return file;
+   }
+};
+
+#endif
+
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileOutput.h b/source/ThirdParty/Library/basics/utilities/UbFileOutput.h
new file mode 100644
index 0000000000000000000000000000000000000000..c55dd82fcf5074e66f709fb662dd680732dacbc3
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileOutput.h
@@ -0,0 +1,93 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEOUTPUT_H
+#define UBFILEOUTPUT_H            
+
+#include <iomanip>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbException.h>
+
+/*=========================================================================*/
+/*  UbFileOutput                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileOutput
+{
+public:
+   enum CREATEOPTION {OUTFILE=0, INANDOUTFILE=1, APPENDFILE=2};      
+   enum FILETYPE {ASCII, BINARY};      
+
+public:
+   UbFileOutput() : filename(""), commentindicator('C') {  }
+   UbFileOutput(const std::string& filename)  : filename(filename), commentindicator('C') { }             
+   virtual ~UbFileOutput() { outfile.flush();outfile.close(); }
+
+   virtual bool open(const std::string& filename, CREATEOPTION opt=OUTFILE) = 0;
+
+   virtual bool operator!() { return !(outfile); }
+   virtual bool isOpen()    { return !(!(outfile)); }
+   
+   virtual void flush() { outfile.flush(); }
+   virtual void close() { outfile.close(); }
+   
+   virtual void writeInteger(const int& value, const int& width=0)=0;
+	virtual void writeDouble(const double& value, const int& width=0)=0;
+	virtual void writeFloat(const float& value, const int& width=0)=0;
+   virtual void writeBool(const bool& value, const int& width=0)=0;
+   virtual void writeSize_t(const std::size_t& value, const int& width=0)=0;
+   virtual void writeChar(const char& value, const int& width=0)=0;
+   virtual void writeString(const std::string& value, const int& width=0)=0;
+   virtual void writeStringOnly(const std::string& value)=0;
+	virtual void writeLine(const std::string& value, const int& width=0)=0;
+	virtual void writeLine()=0;
+
+	virtual void writeCommentLine(const std::string& line)=0;
+	virtual void writeCommentLine(char indicator, const std::string& line)=0;
+   virtual void writeCopyOfFile(const std::string& filename)=0;
+	
+   virtual void setCommentIndicator(char commentindicator) {this->commentindicator = commentindicator;} 
+   
+   virtual void setPrecision(const int& precision)=0;
+   virtual int  getPrecision()=0;
+
+   //returns "ASCII", "BINARY"
+   virtual FILETYPE getFileType()=0;
+
+   //returns file extension:
+   //e.g. "./../test/ich.inp" -> "inp", "./../test/ich" -> ""
+   virtual std::string getFileExtension()  
+   {
+	   std::size_t pos1 = filename.rfind("/");
+      if(pos1==std::string::npos) pos1 = 0;
+      std::size_t pos2 = filename.rfind(".");
+      if(pos2!=std::string::npos && pos2>pos1)
+         return filename.substr(pos2+1);
+
+      return "";
+   }				
+
+   virtual std::string  getFileName() {return this->filename;}
+protected:
+   std::ofstream outfile;
+   std::string   filename; 
+   char          commentindicator; 
+};
+
+#endif //UBFILEOUTPUT_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileOutputASCII.cpp b/source/ThirdParty/Library/basics/utilities/UbFileOutputASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d68a766be8622f1138f6a0e22863b0962141f0bc
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileOutputASCII.cpp
@@ -0,0 +1,177 @@
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbInfinity.h>
+#include <basics/utilities/UbMath.h>
+#include <cstring>
+
+using namespace std;
+
+UbFileOutputASCII::UbFileOutputASCII(const string& filename, const bool& createPath, const int& precision)
+   : UbFileOutput(filename)
+{
+	this->commentindicator = 'C'; 
+	this->setPrecision(20);
+
+   outfile.open(filename.c_str(),ios::out);
+   
+   if(!outfile && createPath) 
+   {
+      outfile.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0) 
+      {
+         UbSystem::makeDirectory(path);
+         outfile.open(filename.c_str(),ios::out);
+      }
+   }
+
+      if(!outfile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+}
+/*==========================================================*/
+UbFileOutputASCII::UbFileOutputASCII(const std::string& filename, CREATEOPTION opt, const bool& createPath, const int& precision)
+   : UbFileOutput(filename)
+{
+	this->commentindicator = 'C'; 
+   this->setPrecision(precision);
+	
+   if(!this->open(filename,opt) && createPath) 
+   {
+      outfile.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0) UbSystem::makeDirectory(path);
+
+      this->open(filename,opt);
+   }
+
+   if(!outfile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+}
+/*==========================================================*/
+bool UbFileOutputASCII::open(const std::string& filename, CREATEOPTION opt)
+{
+   outfile.close();
+   outfile.clear(); //setzt flags zurueck
+   this->filename = filename;
+
+   if     (opt==UbFileOutput::OUTFILE      ) outfile.open(this->filename.c_str(),ios::out); 
+   else if(opt==UbFileOutput::INANDOUTFILE ) outfile.open(this->filename.c_str(),ios::out | ios::in);
+   else if(opt==UbFileOutput::APPENDFILE   ) outfile.open(this->filename.c_str(),ios::app);
+   else UB_THROW( UbException(UB_EXARGS,"undefined CREATEOPTION") );
+
+   return outfile.is_open();
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeBool(const bool& value, const int& width)				
+{
+   outfile.width(width);
+   if(value) outfile<<"true ";
+   else      outfile<<"false ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeDouble(const double& value, const int& width)				
+{
+   outfile.width(width);
+   //Problem: Ub::inf wird gerundet 
+   //         -> beim Einlesen ist der Wert evtl zu gross und es kommt murks raus 
+   //         -> max Laenge darstellen und gut ist
+   if(UbMath::equal(value, (double)Ub::inf) )
+   {
+      ios_base::fmtflags flags = outfile.flags();
+      outfile<<setprecision(std::numeric_limits<double>::digits10+2);
+      outfile<<value<<" ";
+      outfile.flags(flags);
+      return;
+   }
+   outfile<<value<<" ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeFloat(const float& value, const int& width)				
+{
+   outfile.width(width);
+   //Problem: Ub::inf wird gerundet 
+   //         -> beim Einlesen ist der Wert evtl zu gross und es kommt murks raus 
+   //         -> max Laenge darstellen und gut ist
+   if(UbMath::equal(value, (float)Ub::inf) )
+   {
+      ios_base::fmtflags flags = outfile.flags();
+      outfile<<setprecision(std::numeric_limits<float>::digits10+2);
+      outfile<<value<<" ";
+      outfile.flags(flags);
+      return;
+   }
+   outfile<<value<<" ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::setPrecision(const int& precision)				
+{
+   outfile<<setprecision(precision);
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeInteger(const int& value, const int& width)				
+{
+   outfile.width(width);
+   outfile<<value<<" ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeSize_t(const std::size_t& value, const int& width)
+{
+   outfile.width(width);
+   outfile<<value<<" ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeChar(const char& value, const int& width)
+{
+   outfile.width(width);
+   outfile<<(int)value<<" ";	
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeString(const string& value, const int& width)				
+{
+   outfile.width(width);
+   outfile<<value.c_str()<<" ";	
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeStringOnly(const string& value)				
+{
+	outfile<<value.c_str();	
+}
+
+/*==========================================================*/
+void UbFileOutputASCII::writeLine(const string& value, const int& width)				
+{
+   outfile.width(width);
+   outfile<<value.c_str()<<endl;	
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeLine()				
+{
+	outfile<<endl;	
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeCommentLine(const string& line) 
+{
+   this->writeCommentLine(this->commentindicator, line); 
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeCommentLine(char indicator, const string& line) 
+{
+	this->outfile<<indicator<<line<<endl;
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeCopyOfFile(const string& filename)
+{
+   ifstream infile(filename.c_str());
+   if(!infile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+
+   try
+   {
+      char c;
+      while(infile.get(c)) 
+      {
+         outfile.put(c);  //=out<<c;
+      }
+      outfile.flush();
+      infile.close();
+   }
+   catch(std::exception& e) { UB_THROW( UbException(UB_EXARGS,"catched std::exception, error: "+(std::string)e.what()) ); }
+   catch(...)               { UB_THROW( UbException(UB_EXARGS,"unknown error") ); }
+}
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileOutputASCII.h b/source/ThirdParty/Library/basics/utilities/UbFileOutputASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0accdfbefc4f78aefc4812ff6f10fbce7e13ac7
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileOutputASCII.h
@@ -0,0 +1,72 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEOUTPUTASCII_H
+#define UBFILEOUTPUTASCII_H
+
+#include <iomanip>
+#include <fstream>
+#include <iostream>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileOutput.h>
+
+/*=========================================================================*/
+/*  UbFileOutputASCII                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileOutputASCII : public UbFileOutput
+{
+public:
+   UbFileOutputASCII() : UbFileOutput() {}
+   UbFileOutputASCII(const std::string& filename, const bool& createPath=true,  const int& precision=15);             
+   UbFileOutputASCII(const std::string& filename, CREATEOPTION opt, const bool& createPath=true, const int& precision=15);
+   
+   bool open(const std::string& filename, CREATEOPTION opt=OUTFILE);
+   
+   void writeBool(const bool& value, const int& width=0);
+   void writeDouble(const double& value, const int& width=0);
+	void writeFloat(const float& value, const int& width=0);
+	void writeInteger(const int& value, const int& width=0);
+   void writeSize_t(const std::size_t& value, const int& width=0);
+   void writeChar(const char& value, const int& width=0);
+   void writeString(const std::string& value, const int& width=0);
+   void writeStringOnly(const std::string& value);
+   void writeLine(const std::string& value, const int& width=0);
+   void writeLine();
+  
+   void setPrecision(const int& precision);
+   int  getPrecision() { return (int)outfile.precision(); }
+
+   void setCommentIndicator(char commentindicator) {this->commentindicator = commentindicator;} 
+   
+   void writeCommentLine(const std::string& line);
+   void writeCommentLine(char indicator, const std::string& line);
+   void writeCopyOfFile(const std::string& filename);
+
+   FILETYPE getFileType() { return ASCII; }
+
+   template< typename T >
+   friend inline UbFileOutputASCII& operator<<(UbFileOutputASCII& file, const T& data) 
+   {
+      file.outfile<<data;
+      return file;
+   }
+};
+
+#endif
+
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileOutputBinary.cpp b/source/ThirdParty/Library/basics/utilities/UbFileOutputBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..144adbc76b1b020f049f237bbd23c496110ebd9a
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileOutputBinary.cpp
@@ -0,0 +1,180 @@
+#include <basics/utilities/UbFileOutputBinary.h>
+#include <basics/utilities/UbSystem.h>
+#include <cstring>
+
+using namespace std;
+
+/*==========================================================*/
+UbFileOutputBinary::UbFileOutputBinary(const string& filename, const bool& createPath)
+{
+   this->filename         = filename;
+   this->commentindicator = 'C'; 
+
+   outfile.open(filename.c_str(),ios::out | ios::binary);
+
+   if(!outfile && createPath) 
+   {
+      string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0)
+      {
+         outfile.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+         UbSystem::makeDirectory(path);
+         outfile.open(filename.c_str(),ios::out | ios::binary);
+      }
+   }
+
+   if(!outfile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+
+}
+/*==========================================================*/
+UbFileOutputBinary::UbFileOutputBinary(const string& filename,UbFileOutput::CREATEOPTION opt, const bool& createPath)
+{
+   this->filename         = filename;
+   this->commentindicator = 'C'; 
+
+   this->open(filename,opt);
+
+   if(!this->open(filename,opt) && createPath) 
+   {
+      string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0)
+      {
+         outfile.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+         UbSystem::makeDirectory(path,20);
+
+         this->open(filename,opt);     
+      }      
+   }
+
+   if(!outfile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+}
+/*==========================================================*/
+bool UbFileOutputBinary::open(const string& filename, UbFileOutput::CREATEOPTION opt)
+{
+   outfile.close();
+   outfile.clear(); //setzt flags zurueck
+
+   this->filename         = filename;
+
+   if     (opt==UbFileOutput::OUTFILE    )  outfile.open(this->filename.c_str(),ios::out | ios::binary);
+   else if(opt==UbFileOutput::APPENDFILE )  outfile.open(this->filename.c_str(),ios::app | ios::binary);
+   else if(opt==UbFileOutput::INANDOUTFILE) UB_THROW( UbException(UB_EXARGS,"undefined CREATEOPTION - INANDOUTFILE not possible for BINARY files") );
+   else UB_THROW( UbException(UB_EXARGS,"undefined CREATEOPTION") );
+
+   return outfile.is_open();
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeBool(const bool& value, const int& width)				
+{
+   outfile.write((char*)&value,sizeof(bool));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeDouble(const double& value, const int& width)				
+{
+   outfile.write((char*)&value,sizeof(double));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeFloat(const float& value, const int& width)				
+{
+	outfile.write((char*)&value,sizeof(float));
+}
+/*==========================================================*/
+void UbFileOutputBinary::setPrecision(const int& precision)				
+{
+   UB_THROW( UbException(UB_EXARGS,"no way") );
+}
+/*==========================================================*/
+int UbFileOutputBinary::getPrecision()				
+{
+   UB_THROW( UbException(UB_EXARGS,"no way") );
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeInteger(const int& value, const int& width)				
+{
+   outfile.write((char*)&value,sizeof(value));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeSize_t(const std::size_t& value, const int& width)
+{
+   outfile.write((char*)&value,sizeof(value));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeChar(const char& value, const int& width)				
+{
+   outfile.write((char*)&value,sizeof(value));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeString(const string& value, const int& width)				
+{
+   char c='\0';
+   unsigned int length = (unsigned)value.length();
+   
+   unsigned pos;
+   //whitespaces und tabs am stringanfang uebergehen
+   for(pos=0; pos<length; pos++)
+      if( value[pos]!=' ' && value[pos]!='\t' ) break;
+
+   while(pos<length)
+   {
+      while(pos<length && value[pos]!=' ' && value[pos]!='\t' && value[pos]!='\0')
+      {
+         outfile.write((char*)&(value[pos++]),sizeof(char));
+      }
+
+      outfile.write(&c,sizeof(char));
+      pos++;
+
+      while(pos<length && (value[pos]==' ' || value[pos]=='\t' || value[pos]=='\0') )
+      {
+         pos++;
+      }
+   }
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeStringOnly(const string& value)				
+{
+   UbException(UB_EXARGS,"no way... causes to many errors");
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeLine(const std::string& value, const int& width)				
+{
+   this->writeString(value);
+   char c='\n';
+   outfile.write(&c,sizeof(char));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeLine()				
+{
+   char c='\n';
+   outfile.write(&c,sizeof(char));   
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeCommentLine(const string& line) 
+{
+   try        { this->writeCommentLine(this->commentindicator, line); }
+   catch(...) { UB_THROW( UbException(UB_EXARGS,"unknown error") ); }
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeCommentLine(char indicator, const string& line) 
+{
+   string dummy = indicator + line;
+   this->writeLine(dummy);
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeCopyOfFile(const string& filename)
+{
+   ifstream infile(filename.c_str(),ios::in | ios::binary);
+   if(!infile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+
+   try
+   {
+      char c;
+      while(infile.get(c)) 
+      {
+         outfile.put(c);  //=out<<c;
+      }
+      outfile.flush();
+      infile.close();
+   }
+   catch(...) {UB_THROW( UbException(UB_EXARGS,"unknown error") );}
+}
diff --git a/source/ThirdParty/Library/basics/utilities/UbFileOutputBinary.h b/source/ThirdParty/Library/basics/utilities/UbFileOutputBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..fac53e7ac439f4fe55410043f5830ff72fc4c852
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbFileOutputBinary.h
@@ -0,0 +1,70 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEOUTPUTBINARY_H
+#define UBFILEOUTPUTBINARY_H
+
+#include <iomanip>
+#include <fstream>
+#include <iostream>
+
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileOutput.h>
+
+/*=========================================================================*/
+/*  UbFileOutputBinary                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileOutputBinary : public UbFileOutput
+{
+public:
+   UbFileOutputBinary() : UbFileOutput() {}
+   UbFileOutputBinary(const std::string& filename, const bool& createPath=true);
+   UbFileOutputBinary(const std::string& filename, UbFileOutput::CREATEOPTION opt, const bool& createPath);
+   
+   bool open(const std::string& filename, UbFileOutput::CREATEOPTION opt=OUTFILE);
+
+   void writeInteger(const int& value, const int& width=0);
+   void writeDouble(const double& value, const int& width=0);
+	void writeFloat(const float& value, const int& width=0);
+	void writeBool(const bool& value, const int& width=0);
+   void writeChar(const char& value, const int& width=0);
+   void writeSize_t(const std::size_t& value, const int& width=0);
+   void writeString(const std::string& value, const int& width=0);
+   void writeStringOnly(const std::string& value);
+   void writeLine(const std::string& value, const int& width=0);
+   void writeLine();
+   void writeCommentLine(const std::string& line);
+   void writeCommentLine(char indicator, const std::string& line);
+   void writeCopyOfFile(const std::string& filename);
+
+   void setPrecision(const int& precision);
+   int  getPrecision();
+
+   FILETYPE getFileType() { return BINARY; }
+
+   template< typename T >
+   friend inline UbFileOutputBinary& operator<<(UbFileOutputBinary& file, const T& data) 
+   {
+      file.outfile.write((char*)&data,sizeof(T));
+      return file;
+   }
+};
+
+#endif
+
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbInfinity.h b/source/ThirdParty/Library/basics/utilities/UbInfinity.h
new file mode 100644
index 0000000000000000000000000000000000000000..18546b8ad9d29c6c6119446243953ae235342724
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbInfinity.h
@@ -0,0 +1,180 @@
+#ifndef UB_INFINITY_H
+#define UB_INFINITY_H
+#include <limits>
+
+#include <basics/utilities/UbLimits.h>
+#include <basics/utilities/UbSystem.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+//  UbNegInfinity
+//  Anm: keine template klasse, da man am Ende eine Instanz "inf" verwendet
+//       die in "verschiedene"(!!!) Typen konvertiert werden kann und nicht 
+//       nur in den template Typ!
+//  Note: The UbNegInfinity class cannot be instantiated on its own, but works 
+//        as a base class for the Infinity class.
+//////////////////////////////////////////////////////////////////////////
+class UbNegInfinity
+{
+ public:
+   //name Conversion operators 
+   inline operator signed char() const { return UbLimits<signed char>::ninf(); }
+   inline operator char()        const { return UbLimits<char>::ninf();        }
+   inline operator wchar_t()     const { return UbLimits<wchar_t>::ninf();     }
+   inline operator short()       const { return UbLimits<short>::ninf();       }
+   inline operator int()         const { return UbLimits<int>::ninf();         }
+   inline operator long()        const { return UbLimits<long>::ninf();        }
+   inline operator float()       const { return UbLimits<float>::ninf();       }
+   inline operator double()      const { return UbLimits<double>::ninf();      }
+   inline operator long double() const { return UbLimits<long double>::ninf(); }
+
+   // This function compares built-in data types with their largest possible value. The function
+   // only works for built-in data types. The attempt to compare user-defined class types will
+   // result in a compile time error.
+   template< typename T >
+   inline bool equal( const T& rhs ) const
+   {
+      UB_STATIC_ASSERT( std::numeric_limits<T>::is_specialized );
+      return UbLimits<T>::ninf() == rhs;
+   }
+ protected:
+    inline UbNegInfinity() {}
+
+ private:
+   UbNegInfinity( const UbNegInfinity& ninf );             //copy constructor (private & undefined)
+   UbNegInfinity& operator=( const UbNegInfinity& ninf );  //copy assignment operator (private & undefined)
+   void* operator&() const;                                //address operator (private & undefined)
+};
+
+//=================================================================================================
+//
+//  GLOBAL OPERATORS
+//
+//=================================================================================================
+template< typename T >
+inline bool operator==( const UbNegInfinity& lhs, const T& rhs )
+{
+   return lhs.equal( rhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator==( const T& lhs, const UbNegInfinity& rhs )
+{
+   return rhs.equal( lhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator!=( const UbNegInfinity& lhs, const T& rhs )
+{
+   return !lhs.equal( rhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator!=( const T& lhs, const UbNegInfinity& rhs )
+{
+   return !rhs.equal( lhs );
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+//  UbInfinity
+//
+//////////////////////////////////////////////////////////////////////////
+class UbInfinity : public UbNegInfinity //um später -UbInfinity leichter zu implementieren!!!
+{
+ public:
+   inline UbInfinity() 
+      : UbNegInfinity()
+    {}
+   
+   inline operator unsigned char()  const  { return UbLimits<unsigned char>::inf();  }
+   inline operator signed char()    const  { return UbLimits<signed char>::inf();    }
+   inline operator char()           const  { return UbLimits<char>::inf();           }
+   inline operator wchar_t()        const  { return UbLimits<wchar_t>::inf();        }
+   inline operator unsigned short() const  { return UbLimits<unsigned short>::inf(); }
+   inline operator short()          const  { return UbLimits<short>::inf();          }
+   inline operator unsigned int()   const  { return UbLimits<unsigned int>::inf();   }
+   inline operator int()            const  { return UbLimits<int>::inf();            }
+   inline operator unsigned long()  const  { return UbLimits<unsigned long>::inf();  }
+   inline operator long()           const  { return UbLimits<long>::inf();           }
+   inline operator float()          const  { return UbLimits<float>::inf();          }
+   inline operator double()         const  { return UbLimits<double>::inf();         }
+   inline operator long double()    const  { return UbLimits<long double>::inf();    }
+
+   inline const UbNegInfinity& operator-() const { return static_cast<const UbNegInfinity&>( *this ); }
+
+   /*==========================================================*/
+   template< typename T >
+   inline bool equal( const T& rhs ) const
+   {
+      UB_STATIC_ASSERT( std::numeric_limits<T>::is_specialized );
+      return UbLimits<T>::inf() == rhs;
+   }
+
+ private:
+   UbInfinity( const UbInfinity& inf );             //Copy constructor (private & undefined)
+   UbInfinity& operator=( const UbInfinity& inf );  //Copy assignment operator (private & undefined)
+   void* operator&() const;                         //Address operator (private & undefined)
+};
+
+//////////////////////////////////////////////////////////////////////////
+//  GLOBAL OPERATORS
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+inline bool operator==( const UbInfinity& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator==( const T& lhs, const UbInfinity& rhs );
+
+template< typename T >
+inline bool operator!=( const UbInfinity& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator!=( const T& lhs, const UbInfinity& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between an Infinity object and a built-in data type.
+// \ingroup util
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator==( const UbInfinity& lhs, const T& rhs )
+{
+   return lhs.equal( rhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator==( const T& lhs, const UbInfinity& rhs )
+{
+   return rhs.equal( lhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator!=( const UbInfinity& lhs, const T& rhs )
+{
+   return !lhs.equal( rhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator!=( const T& lhs, const UbInfinity& rhs )
+{
+   return !rhs.equal( lhs );
+}
+//*************************************************************************************************
+
+//////////////////////////////////////////////////////////////////////////
+//  GLOBAL INFINITY VALUE
+//////////////////////////////////////////////////////////////////////////
+namespace Ub
+{
+   //e.g. double x = UbSystem::inf;  float x = -Ub::inf; 
+   const UbInfinity inf; 
+} 
+
+#endif //UB_INFINITY_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbKeys.h b/source/ThirdParty/Library/basics/utilities/UbKeys.h
new file mode 100644
index 0000000000000000000000000000000000000000..feaf5cab8c58e6fe2f26bd3ce6d63b2aee609ed5
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbKeys.h
@@ -0,0 +1,311 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBKEYS_H
+#define UBKEYS_H
+
+#include <iostream>
+
+#include <boost/serialization/serialization.hpp>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+/*=========================================================================*/
+/*  UbKeys                                                             */
+/*                                                                         */
+/**
+namespace for global Keys (e.g. for STL-maps)
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.08.07
+*/ 
+
+/*
+usage: ...
+*/
+
+namespace UbKeys
+{
+   //nested class
+   template< typename T1, typename T2 = T1 >
+   class Key2 
+   {
+   public:
+      //////////////////////////////////////////////////////////////////////////
+      //Konstruktoren
+      Key2(const T1& t1, const T2& t2) 
+         : t1(t1), t2(t2)
+      { 
+      }
+      /*==========================================================*/
+      Key2& operator=(const Key2& srcKey) 
+      {
+         if(this == &srcKey ) return *this;
+
+         t1    = srcKey.t1;
+         t2    = srcKey.t2;
+
+         return *this;
+      }
+      /*==========================================================*/
+      T1 getT1() const { return t1; }
+      T2 getT2() const { return t2; }
+
+      //////////////////////////////////////////////////////////////////////////
+      //global ueberladene Operatoren
+      friend inline bool operator<(const Key2& lhsKey,const Key2& rhsKey)  
+      {
+         if( lhsKey.t1 < rhsKey.t1 ) return true;
+         if( lhsKey.t1 > rhsKey.t1 ) return false;
+         if( lhsKey.t2 < rhsKey.t2 ) return true;
+
+         return false;
+      }
+      /*==========================================================*/
+      friend inline bool operator==(const Key2& lhsKey, const Key2& rhsKey)  
+      {
+         if(lhsKey.t1 != rhsKey.t1 ) return false;
+         if(lhsKey.t2 != rhsKey.t2 ) return false;
+
+         return true;
+      }
+      //ueberladene Operatoren
+      friend inline bool operator!=(const Key2& lhsKey, const Key2& rhsKey)  
+      {
+         return !(lhsKey == rhsKey); 
+      }
+      //ueberladene Operatoren
+      /*==========================================================*/
+      friend inline std::ostream& operator << (std::ostream& os, const Key2& key) 
+      {
+         os<<"Key2<"<<typeid(T1).name()<<","<<typeid(T2).name()<<">,("<<key.t1<<","<<key.t2<<")";
+         return os;
+      }
+      /*==========================================================*/
+      #ifdef CAB_RCF
+	      template<class Archive>
+	      void serialize(Archive & ar, const unsigned int version)
+	      {
+		      ar & t1;
+		      ar & t2;
+	      }
+      #endif //CAB_RCF
+
+   private:
+      //////////////////////////////////////////////////////////////////////////
+      //private Member
+      T1 t1;
+      T2 t2;
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & t1;
+         ar & t2;
+      }
+   };
+
+   //////////////////////////////////////////////////////////////////////////
+   //
+   //////////////////////////////////////////////////////////////////////////
+   template< typename T1, typename T2 = T1, typename T3 = T1 >
+   class Key3 
+   {
+   public:
+      //////////////////////////////////////////////////////////////////////////
+      //Konstruktoren
+      Key3() : t1(0), t2(0), t3(0)
+      {
+
+      }
+      Key3(const T1& t1, const T2& t2, const T3& t3) 
+         : t1(t1), t2(t2), t3(t3)
+      { 
+      }
+      /*==========================================================*/
+      T1 getT1() const { return t1; }
+      T2 getT2() const { return t2; }
+      T3 getT3() const { return t3; }
+      /*==========================================================*/
+      Key3& operator=(const Key3& srcKey) 
+      {
+         if(this == &srcKey ) return *this;
+
+         t1    = srcKey.t1;
+         t2    = srcKey.t2;
+         t3    = srcKey.t3;
+
+         return *this;
+      }
+
+      //////////////////////////////////////////////////////////////////////////
+      //global ueberladene Operatoren
+      friend inline bool operator<(const Key3& lhsKey,const Key3& rhsKey)  
+      {
+         if( lhsKey.t1 < rhsKey.t1 ) return true;
+         if( lhsKey.t1 > rhsKey.t1 ) return false;
+         if( lhsKey.t2 < rhsKey.t2 ) return true;
+         if( lhsKey.t2 > rhsKey.t2 ) return false;
+         if( lhsKey.t3 < rhsKey.t3 ) return true;
+
+         return false;
+      }
+      /*==========================================================*/
+      friend inline bool operator==(const Key3& lhsKey,const Key3& rhsKey)  
+      {
+         if(lhsKey.t1 != rhsKey.t1 ) return false;
+         if(lhsKey.t2 != rhsKey.t2 ) return false;
+         if(lhsKey.t3 != rhsKey.t3 ) return false;
+
+         return true;
+      }
+      /*==========================================================*/
+      //ueberladene Operatoren
+      friend inline bool operator!=(const Key3& lhsKey, const Key3& rhsKey) 
+      {
+         return !(lhsKey == rhsKey); 
+      }
+
+      //ueberladene Operatoren
+      /*==========================================================*/
+      friend inline std::ostream& operator << (std::ostream& os, const Key3& key) 
+      {
+         os<<"Key3<"<<typeid(T1).name()<<","<<typeid(T2).name()<<","<<typeid(T3).name();
+         os<<">,("<<key.t1<<","<<key.t2<<","<<key.t3<<")";
+         return os;
+      }
+      /*==========================================================*/
+      #ifdef CAB_RCF
+	      template<class Archive>
+	      void serialize(Archive & ar, const unsigned int version)
+	      {
+		      ar & t1;
+		      ar & t2;
+            ar & t3;
+         }
+      #endif //CAB_RCF
+
+   private:
+      //////////////////////////////////////////////////////////////////////////
+      //private Member
+      T1 t1;
+      T2 t2;
+      T3 t3;
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & t1;
+         ar & t2;
+         ar & t3;
+      }
+   };
+
+   //////////////////////////////////////////////////////////////////////////
+   //
+   //////////////////////////////////////////////////////////////////////////
+   template< typename T1, typename T2 = T1, typename T3 = T1, typename T4 = T1 >
+   class Key4 
+   {
+   public:
+      //////////////////////////////////////////////////////////////////////////
+      //Konstruktoren
+      Key4(const T1& t1, const T2& t2, const T3& t3, const T4& t4) 
+         : t1(t1), t2(t2), t3(t3), t4(t4)
+      { 
+      }
+      /*==========================================================*/
+      T1 getT1() const { return t1; }
+      T2 getT2() const { return t2; }
+      T3 getT3() const { return t3; }
+      T4 getT4() const { return t4; }
+      /*==========================================================*/
+      Key4& operator=(const Key4& srcKey) 
+      {
+         if(this == &srcKey ) return *this;
+
+         t1    = srcKey.t1;
+         t2    = srcKey.t2;
+         t3    = srcKey.t3;
+         t4    = srcKey.t4;
+
+         return *this;
+      }
+      //////////////////////////////////////////////////////////////////////////
+      //global ueberladene Operatoren
+      friend inline bool operator<(const Key4& lhsKey,const Key4& rhsKey)  
+      {
+         if( lhsKey.t1 < rhsKey.t1 ) return true;
+         if( lhsKey.t1 > rhsKey.t1 ) return false;
+         if( lhsKey.t2 < rhsKey.t2 ) return true;
+         if( lhsKey.t2 > rhsKey.t2 ) return false;
+         if( lhsKey.t3 < rhsKey.t3 ) return true;
+         if( lhsKey.t3 > rhsKey.t3 ) return false;
+         if( lhsKey.t4 < rhsKey.t4 ) return true;
+
+         return false;
+      }
+      /*==========================================================*/
+      friend inline bool operator==(const Key4& lhsKey,const Key4& rhsKey)  
+      {
+         if(lhsKey.t1 != rhsKey.t1 ) return false;
+         if(lhsKey.t2 != rhsKey.t2 ) return false;
+         if(lhsKey.t3 != rhsKey.t3 ) return false;
+         if(lhsKey.t4 != rhsKey.t4 ) return false;
+
+         return true;
+      }
+
+      //ueberladene Operatoren
+      friend inline bool operator!=(const Key4& lhsKey, const Key4& rhsKey) 
+      {
+         return !(lhsKey == rhsKey); 
+      }
+      //ueberladene Operatoren
+      /*==========================================================*/
+      friend inline std::ostream& operator << (std::ostream& os, const Key4& key) 
+      {
+         os<<"Key4<"<<typeid(T1).name()<<","<<typeid(T2).name()<<","<<typeid(T3).name()<<","<<typeid(T4).name();
+         os<<">,("<<key.t1<<","<<key.t2<<","<<key.t3<<","<<key.t4<<")";
+         return os;
+      }
+      /*==========================================================*/
+      #ifdef CAB_RCF
+	      template<class Archive>
+	      void serialize(Archive & ar, const unsigned int version)
+	      {
+		      ar & t1;
+		      ar & t2;
+            ar & t3;
+            ar & t4;
+         }
+      #endif //CAB_RCF
+
+   private:
+      //////////////////////////////////////////////////////////////////////////
+      //private Member
+      T1 t1;
+      T2 t2;
+      T3 t3;
+      T4 t4;
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & t1;
+         ar & t2;
+         ar & t3;
+         ar & t4;
+      }
+   };
+}
+
+#endif //UBKEYS_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbLimits.h b/source/ThirdParty/Library/basics/utilities/UbLimits.h
new file mode 100644
index 0000000000000000000000000000000000000000..9313f0620a138785dd9b7e6c334917806da93c30
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbLimits.h
@@ -0,0 +1,139 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UB_LIMITS_H
+#define UB_LIMITS_H
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <limits>
+
+//////////////////////////////////////////////////////////////////////////
+//  CLASS DEFINITION
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+struct UbLimits  {};
+
+//////////////////////////////////////////////////////////////////////////
+//  SPECIALIZATIONS
+//////////////////////////////////////////////////////////////////////////
+template<>
+struct UbLimits<unsigned char>
+{
+   //return the largest possible positive unsigned char value
+   static inline unsigned char inf() { return std::numeric_limits<unsigned char>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<char>
+{
+   //return the largest possible positive char value. */
+   static inline char inf () { return std::numeric_limits<char>::max(); }
+   //return the largest possible negative char value
+   static inline char ninf() { return std::numeric_limits<char>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<signed char>
+{
+   //return the largest possible positive signed char value
+   static inline signed char inf () { return std::numeric_limits<signed char>::max(); }
+
+   //return The largest possible negative signed char value
+   static inline signed char ninf() { return std::numeric_limits<signed char>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<wchar_t>
+{
+   //return The largest possible positive wchar_t value
+   static inline wchar_t inf () { return std::numeric_limits<wchar_t>::max(); }
+   //return The largest possible negative wchar_t value
+   static inline wchar_t ninf() { return std::numeric_limits<wchar_t>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<unsigned short>
+{
+   //return The largest possible positive unsigned short value
+   static inline unsigned short inf() { return std::numeric_limits<unsigned short>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<short>
+{
+   //return The largest possible positive short value
+   static inline short inf () { return std::numeric_limits<short>::max(); }
+   //return The largest possible negative short value
+   static inline short ninf() { return std::numeric_limits<short>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<unsigned int>
+{
+   //return The largest possible positive unsigned int value
+   static inline unsigned int inf() { return std::numeric_limits<unsigned int>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<int>
+{
+   //return The largest possible positive int value
+   static inline int inf () { return std::numeric_limits<int>::max(); }
+
+   //return The largest possible negative int value
+   static inline int ninf() { return std::numeric_limits<int>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<unsigned long>
+{
+   //return The largest possible positive unsigned long value
+   static inline unsigned long inf() { return std::numeric_limits<unsigned long>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<long>
+{
+   //return The largest possible positive long value
+   static inline long inf () { return std::numeric_limits<long>::max(); }
+
+   //return The largest possible negative long value
+   static inline long ninf() { return std::numeric_limits<long>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<float>
+{
+   //return The largest possible positive float value
+   static inline float inf () { return  std::numeric_limits<float>::max(); }
+
+   //return The largest possible negative float value
+   static inline float ninf() { return -std::numeric_limits<float>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<double>
+{
+   //return The largest possible positive double value
+   static inline double inf () { return  std::numeric_limits<double>::max(); }
+   //return The largest possible negative double value
+   static inline double ninf() { return -std::numeric_limits<double>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<long double>
+{
+   //return The largest possible positive long double value
+   static inline long double inf () { return  std::numeric_limits<long double>::max(); }
+   //return The largest possible negative long double value
+   static inline long double ninf() { return -std::numeric_limits<long double>::max(); }
+};
+
+#endif //UB_LIMITS_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbLogger.cpp b/source/ThirdParty/Library/basics/utilities/UbLogger.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f487a02ed08408d632ccab624b657f0283686ad5
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbLogger.cpp
@@ -0,0 +1,8 @@
+#include <basics/utilities/UbLogger.h>
+
+#if defined(CAB_BOOST) && !defined(NO_THREADSAFE_LOGGING)
+
+boost::mutex Output2Stream::mtx;
+
+#endif // CAB_BOOST
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbLogger.h b/source/ThirdParty/Library/basics/utilities/UbLogger.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d4e432ce7c4ec2284aba328cc7344d1db6aec4b
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbLogger.h
@@ -0,0 +1,362 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBLOGGER_H
+#define UBLOGGER_H
+
+#include <sstream>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <memory>
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)  || defined(_WIN64)  || defined(__WIN64__)
+   #include <windows.h>
+#else
+   #include <sys/time.h>
+#endif
+
+#if defined(CAB_BOOST) && !defined(NO_THREADSAFE_LOGGING)
+   #include <boost/thread.hpp>
+#endif // CAB_BOOST
+
+//////////////////////////////////////////////////////////////////////////
+// UbLogger
+// C++ Logger
+// Funktionsweise:
+// pro Logeintrag wird ein UbLogger-Objekt erstellt, der logstring uebergeben und beim "zerstroeren"
+// wird der logstring mittels der entsprechenden policy (=template paramter)  z.B. in eine Datei
+// oder auf dem Bildschirm ausgegeben. Es werden verschiedene LogLevel unterstuetzt 
+//
+// Hilfsmakro:  UBLOG
+// Bsp1:        UBLOG(logINFO) << "Klasse::foo entered"; //endl wir nicht benötigt
+//              --> Eintrag:
+//
+// Bsp2: siehe Dateiende!
+//
+//Idee basierend auf: 
+//Artikel von Dr. Dobbs Portal
+//September 05, 2007
+//Logging In C++
+//
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@version 1.0 - 12.10.2008
+
+enum LogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4, logDEBUG5};
+
+//////////////////////////////////////////////////////////////////////////
+// template <typename OutputPolicy> class Log  - declaration
+//////////////////////////////////////////////////////////////////////////
+template <typename OutputPolicy>
+class UbLogger
+{   
+public:
+   typedef OutputPolicy output_policy;
+public:
+    UbLogger();
+    virtual ~UbLogger();
+    std::ostringstream& get(const LogLevel& level = logINFO);
+public:
+   //static, weil man so später die ObjErstellunge ersparen kann,
+   //falls level kleiner als Level
+   static LogLevel&   reportingLevel();
+    
+    static std::string logLevelToString(const LogLevel& level);
+    static LogLevel    logLevelFromString(const std::string& level);
+
+    static std::string logTimeString();
+
+protected:
+    std::ostringstream os;
+
+private:
+    UbLogger(const UbLogger&);
+    UbLogger& operator =(const UbLogger&);
+};
+
+//////////////////////////////////////////////////////////////////////////
+// template <typename OutputPolicy> class Log  - implementation
+//////////////////////////////////////////////////////////////////////////
+template <typename OutputPolicy>
+UbLogger<OutputPolicy>::UbLogger()
+{
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+std::ostringstream& UbLogger<OutputPolicy>::get(const LogLevel& level) 
+{
+   os << logTimeString() << " " << std::setw(6) 
+#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING)
+      <<boost::this_thread::get_id() << " "
+#endif
+      << std::setw(8) << std::left << UbLogger<OutputPolicy>::logLevelToString(level) << ": "
+      << std::string(level > logDEBUG ? 3*(level - logDEBUG) : 0, ' '); //<baumartiger output :D
+   
+    return os;
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+UbLogger<OutputPolicy>::~UbLogger()
+{
+    os << std::endl;
+    OutputPolicy::output(os.str());
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+LogLevel& UbLogger<OutputPolicy>::reportingLevel()
+{
+    static LogLevel reportLevel = logINFO;
+    return reportLevel;
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+std::string UbLogger<OutputPolicy>::logLevelToString(const LogLevel& level)
+{
+   static std::string const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"};
+   return buffer[level];
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+LogLevel UbLogger<OutputPolicy>::logLevelFromString(const std::string& level)
+{
+   if (level == "DEBUG5" ) return logDEBUG5;
+   if (level == "DEBUG4" ) return logDEBUG4;
+   if (level == "DEBUG3" ) return logDEBUG3;
+   if (level == "DEBUG2" ) return logDEBUG2;
+   if (level == "DEBUG1" ) return logDEBUG1;
+   if (level == "DEBUG"  ) return logDEBUG;
+   if (level == "INFO"   ) return logINFO;
+   if (level == "WARNING") return logWARNING;
+   if (level == "ERROR"  ) return logERROR;
+       
+   UbLogger<OutputPolicy>().get(logWARNING) << "UbLogger<OutputPolicy>::logLevelFromString(level) - unknown logging level '" << level << "'. Using INFO level as default.";
+   return logINFO;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// logTimeString
+//////////////////////////////////////////////////////////////////////////
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)  || defined(_WIN64)  || defined(__WIN64__)
+template <typename OutputPolicy>
+inline std::string UbLogger<OutputPolicy>::logTimeString()
+{
+   const int MAX_LEN = 200;
+   char buffer[MAX_LEN];
+   if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, "HH':'mm':'ss", buffer, MAX_LEN) == 0 )
+   {
+      return "Error in std::string UbLogger<OutputPolicy>::logTimeString()";
+   }
+
+   char result[100] = {0};
+   static DWORD first = GetTickCount();
+   std::sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % 1000); 
+   return result;
+}
+#else
+template <typename OutputPolicy>
+inline std::string UbLogger<OutputPolicy>::logTimeString()
+{
+   char buffer[11];
+   time_t t;
+   time(&t);
+   tm r = {0};
+   strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
+   struct timeval tv;
+   gettimeofday(&tv, 0);
+   char result[100] = {0};
+   std::sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000); 
+   return result;
+}
+#endif 
+
+
+//////////////////////////////////////////////////////////////////////////
+// Output2Stream (=implementation of OutputPolicy)
+//////////////////////////////////////////////////////////////////////////
+//Anm: die erste Version mit auto_ptr fuer den stream fuehrte zu
+//     exceptions bei Verwedung vom Logger in dtors stat. globaler
+//     Objekte. Aber auch die Pointer-Lsg. ist noch nicht die 
+//     optimale Lösung
+class Output2Stream // implementation of OutputPolicy
+{
+public:
+   static std::ostream*& getStream();
+   static void output(const std::string& msg);
+   
+   //creates output-file-stream (of file opening fails -> stream is set to std::cerr)
+   static void setStream(const std::string& filename);
+   
+   //direct set outputstream, gcControl = true -> object will be deleted by Output2Stream 
+   static void setStream(std::ostream* pStream, const bool& gcControl = false);
+
+protected:
+#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING)
+   static boost::mutex mtx;
+#endif
+};
+/*==========================================================*/
+inline std::ostream*& Output2Stream::getStream()
+{
+   static std::ostream* pStream = &std::clog;
+   return pStream;
+}
+/*==========================================================*/
+inline void Output2Stream::setStream(std::ostream* pFile, const bool& gcControl)
+{
+#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING)
+   boost::mutex::scoped_lock lock(mtx);
+#endif
+   static bool s_gcControl = false;
+   
+   if( s_gcControl && Output2Stream::getStream() ) 
+   {
+      delete Output2Stream::getStream();
+   }
+   
+   s_gcControl = gcControl;
+   
+   Output2Stream::getStream() = pFile;
+}
+/*==========================================================*/
+inline void Output2Stream::setStream(const std::string& filename)
+{
+   std::ofstream* file = new std::ofstream( filename.c_str() );
+   if( !(*file) ) 
+   {
+      delete file;
+      Output2Stream::setStream(&std::cerr, false);
+      UbLogger<Output2Stream>().get(logERROR) << " Output2Stream::setStream(const std::string& filename) could not open file "
+                                               << filename << " -> std::cerr is used instead " << std::endl;
+      return;
+   }
+   std::cout<<"UbLog writes to "<<filename<<std::endl;
+   Output2Stream::setStream(file,true);
+}
+/*==========================================================*/
+inline void Output2Stream::output(const std::string& msg)
+{
+#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING)
+   boost::mutex::scoped_lock lock(mtx);
+#endif
+   std::ostream* pStream = getStream();
+   if (!pStream) return;
+   (*pStream) << msg << std::flush;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// UbLog
+//////////////////////////////////////////////////////////////////////////
+class UbLog : public UbLogger< Output2Stream > 
+{
+public:
+   typedef Output2Stream output_policy;
+};
+
+//Makro um compilerseitig maxLevel zu beschränken
+#ifndef UBLOG_MAX_LEVEL
+   #define UBLOG_MAX_LEVEL logDEBUG5
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//Hauptmakro fuers Loggen
+// example UBLOG(logINFO) << "das ist ein log eintrag";
+//////////////////////////////////////////////////////////////////////////
+#define UBLOG(level, logtext) \
+   if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \
+   else UbLog().get(level) << logtext;                                                             
+   
+//wieso dieses Macro (was der der scheaeaeaesss???)
+// z.B. UBLOG(logDEBUG2) << "Ich bin sooo toll " << username;
+//also, was macht der praeprozessor draus?:
+// if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ;
+// else // Log().Get(logINFO) << "Ich bin sooo toll " << username;
+//Ergo: das prinzip des logging beruht auf: Log-Objekt erstellen und rauschreiben beim zerstoeren
+//    -> ist der zu loggende Level < als der im UBLOG angegebene erspart man sich hier die
+//       Objekt erstellung -> optimale Performance -> laut Petru Marginean (dem Verfasser des
+//       Ursprungslogger ist der Performance Unterschied kaum messbar, wenn NICHT geloggt wird!
+
+//////////////////////////////////////////////////////////////////////////
+//makro 2 fuer korrekten MultiLineOutput (teuer!!)
+// example1: UBLOGML(logINFO, "line1"<<endl<<"line2"<<endl<<"line3" )
+// example2: UBLOGML(logINFO, "line1\nline2\nendl\nline3" )
+//////////////////////////////////////////////////////////////////////////
+#define UBLOGML(level, multiline) \
+   if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \
+   else                                                                                            \
+   {                                                                                               \
+      std::ostringstream output;                                                                   \
+      output << multiline;                                                                         \
+      std::istringstream input( output.str() );                                                    \
+      while(!input.eof())                                                                          \
+      {                                                                                            \
+         std::string dummy;                                                                        \
+         getline(input,dummy,'\n');                                                                \
+         UbLog().get(level) << dummy;                                                              \
+      }                                                                                            \
+   }                                                                                          
+//////////////////////////////////////////////////////////////////////////
+//makro3, falls auch bildschirmausgabe erwünscht
+//   -> es wird sowohl ins logfile als auch auf den "stream" geschrieben
+//      wenn reporting level und level passen :D
+//example1: UBLOG2ML(logINFO, std::cout,  "line1"<<endl<<"line2"<<endl<<"line3" ) 
+//example2: UBLOG2ML(logINFO, std::cout,  "line1\nline2\nendl\nline3" ) 
+//////////////////////////////////////////////////////////////////////////
+#define UBLOG2(level, stream,  text ) \
+   if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \
+   else { stream << text <<std::endl; UbLog().get(level) << text;   }                             
+
+//////////////////////////////////////////////////////////////////////////
+//makro4, wie 3 nur mit multiline
+//example: UBLOG2(logINFO, std::cout,  "test" ) 
+//////////////////////////////////////////////////////////////////////////
+#define UBLOG2ML(level, stream,  multiline ) \
+   if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \
+   else                                                                                            \
+   {                                                                                               \
+      stream << multiline << std::endl;                                                            \
+      std::ostringstream output;                                                                   \
+      output << multiline;                                                                         \
+      std::istringstream input( output.str() );                                                    \
+      while(!input.eof())                                                                          \
+      {                                                                                            \
+         std::string dummy;                                                                        \
+         getline(input,dummy,'\n');                                                                \
+         UbLog().get(level) << dummy;                                                              \
+      }                                                                                            \
+   }                                                                                               
+
+//////////////////////////////////////////////////////////////////////////
+// example 2
+//////////////////////////////////////////////////////////////////////////
+// try
+// {
+//    UbLog::reportingLevel() = UbLog::logLevelFromString("DEBUG3");
+//    //UbLog::output_policy::setStream(&std::cerr); //<- clog ist stdandard
+//    UbLog::output_policy::setStream("c:/temp/out.txt");  //kann man diese nicht oeffnen -> fehlermeldung -> Log wird in cerr ausgegben
+// 
+//    int count = 3;
+//    UBLOG(logINFO, "A loop with " << count << " iterations");
+//    for (int i = 0; i != count; ++i)
+//    {
+//        UBLOG(logERROR , "error  - the counter i = " << i );
+//        UBLOG(logDEBUG1, "debug1 - the counter i = " << i );
+//        UBLOG(logDEBUG2, "debug2 - the counter i = " << i );
+//        UBLOG(logDEBUG3, "debug3 - the counter i = " << i );
+//        //fuer MultiLine Eintraege: --> koerrekte formatierung im logfile
+//        UBLOGML(logDEBUG3, "debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i);
+//        UBLOGML(logDEBUG3, "debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i);
+//        UBLOG2ML(logDEBUG3,std:cout,"debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i);
+//    }
+//    return 0;
+// }
+// catch(const std::exception& e)
+// {
+//    UBLOG(logERROR) << e.what();
+// }
+
+
+#endif //UBLOGGER_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbMath.cpp b/source/ThirdParty/Library/basics/utilities/UbMath.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad38b9cf945d569e8f2d7bd6118c35b27fadd4fe
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbMath.cpp
@@ -0,0 +1,614 @@
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbInfinity.h>
+#include <cstring> //for memcmp
+
+// namespace UbMath
+// {
+//double UbMath::EPSILON  = 1.0E-10;           
+const double UbMath::PI = 4.0* std::atan(1.0);   //3.1415926535897932384626433832795
+//}
+namespace UbMath{
+
+//////////////////////////////////////////////////////////////////////////
+const Vector3D Vector3D::ZERO(0.0,0.0,0.0);
+const Vector3D Vector3D::UNIT_X1(1.0,0.0,0.0);
+const Vector3D Vector3D::UNIT_X2(0.0,1.0,0.0);
+const Vector3D Vector3D::UNIT_X3(0.0,0.0,1.0);
+
+/*=======================================================*/
+Vector3D::Vector3D() 
+{                                      
+   m_afTuple[0] = 0.0;
+   m_afTuple[1] = 0.0;
+   m_afTuple[2] = 0.0;
+}
+/*=======================================================*/
+Vector3D::Vector3D(const double& fX, const double& fY, const double& fZ) 
+{
+   m_afTuple[0] = fX;
+   m_afTuple[1] = fY;
+   m_afTuple[2] = fZ;
+}
+/*=======================================================*/
+Vector3D::Vector3D (const Vector3D& rkV) 
+{
+   m_afTuple[0] = rkV.m_afTuple[0];
+   m_afTuple[1] = rkV.m_afTuple[1];
+   m_afTuple[2] = rkV.m_afTuple[2];
+}
+/*=======================================================*/
+std::string Vector3D::toString()  const
+{
+   std::stringstream os;
+   os<< "Vector3D["<<m_afTuple[0]<<","<<m_afTuple[1]<<","<<m_afTuple[2]<<"]";
+   return os.str();
+}
+/*=======================================================*/
+Vector3D::operator const double*() const
+{
+   return m_afTuple;
+}
+/*=======================================================*/
+Vector3D::operator double*()
+{
+   return m_afTuple;
+}
+/*=======================================================*/
+double Vector3D::operator[](const int& i) const
+{
+   assert( i >= 0 && i <= 2 );
+   return m_afTuple[i];
+}
+/*=======================================================*/
+double& Vector3D::operator[](const int& i)
+{
+   assert( i >= 0 && i <= 2 );
+   return m_afTuple[i];
+}
+/*=======================================================*/
+double Vector3D::X1() const
+{
+   return m_afTuple[0];
+}
+/*=======================================================*/
+double& Vector3D::X1()
+{
+   return m_afTuple[0];
+}
+/*=======================================================*/
+double Vector3D::X2() const
+{
+   return m_afTuple[1];
+}
+/*=======================================================*/
+double& Vector3D::X2()
+{
+   return m_afTuple[1];
+}
+/*=======================================================*/
+double Vector3D::X3() const
+{
+   return m_afTuple[2];
+}
+/*=======================================================*/
+double& Vector3D::X3()
+{
+   return m_afTuple[2];
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator=(const Vector3D& rkV)
+{
+   m_afTuple[0] = rkV.m_afTuple[0];
+   m_afTuple[1] = rkV.m_afTuple[1];
+   m_afTuple[2] = rkV.m_afTuple[2];
+   return *this;
+}
+/*=======================================================*/
+int Vector3D::CompareArrays(const Vector3D& rkV) const
+{
+   return memcmp(m_afTuple,rkV.m_afTuple,3*sizeof(double));
+}
+/*=======================================================*/
+bool Vector3D::operator==(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) == 0;
+}
+/*=======================================================*/
+bool Vector3D::operator!=(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) != 0;
+}
+/*=======================================================*/
+bool Vector3D::operator<(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) < 0;
+}
+/*=======================================================*/
+bool Vector3D::operator<=(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) <= 0;
+}
+/*=======================================================*/
+bool Vector3D::operator> (const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) > 0;
+}
+/*=======================================================*/
+bool Vector3D::operator>=(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) >= 0;
+}
+/*=======================================================*/
+Vector3D Vector3D::operator+(const Vector3D& rkV) const
+{
+   return Vector3D( m_afTuple[0]+rkV.m_afTuple[0],
+                    m_afTuple[1]+rkV.m_afTuple[1],
+                    m_afTuple[2]+rkV.m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D Vector3D::Add(Vector3D& vector)
+{
+   return Vector3D( m_afTuple[0]+vector.m_afTuple[0],
+                    m_afTuple[1]+vector.m_afTuple[1],
+                    m_afTuple[2]+vector.m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D Vector3D::operator- (const Vector3D& rkV) const
+{
+   return Vector3D( m_afTuple[0]-rkV.m_afTuple[0],
+                    m_afTuple[1]-rkV.m_afTuple[1],
+                    m_afTuple[2]-rkV.m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D Vector3D::Subtract(Vector3D& vector)
+{
+   return Vector3D( m_afTuple[0]-vector.m_afTuple[0],
+                    m_afTuple[1]-vector.m_afTuple[1],
+                    m_afTuple[2]-vector.m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D Vector3D::operator*(const double& fScalar) const
+{
+   return Vector3D( fScalar*m_afTuple[0],
+                    fScalar*m_afTuple[1],
+                    fScalar*m_afTuple[2]  );
+}
+/*=======================================================*/
+Vector3D Vector3D::operator/(const double& fScalar) const
+{
+   Vector3D kQuot;
+
+   if ( fScalar != 0.0 )
+   {
+      double fInvScalar = 1.0/fScalar;
+      kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0];
+      kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1];
+      kQuot.m_afTuple[2] = fInvScalar*m_afTuple[2];
+   }
+   else
+   {
+      kQuot.m_afTuple[0] = Ub::inf;
+      kQuot.m_afTuple[1] = Ub::inf;
+      kQuot.m_afTuple[2] = Ub::inf;
+   }
+
+   return kQuot;
+}
+/*=======================================================*/
+Vector3D Vector3D::operator-() const
+{
+   return Vector3D( -m_afTuple[0],
+                    -m_afTuple[1],
+                    -m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator+=(const Vector3D& rkV)
+{
+   m_afTuple[0] += rkV.m_afTuple[0];
+   m_afTuple[1] += rkV.m_afTuple[1];
+   m_afTuple[2] += rkV.m_afTuple[2];
+   return *this;
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator-=(const Vector3D& rkV)
+{
+   m_afTuple[0] -= rkV.m_afTuple[0];
+   m_afTuple[1] -= rkV.m_afTuple[1];
+   m_afTuple[2] -= rkV.m_afTuple[2];
+   return *this;
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator*=(const double& fScalar)
+{
+   m_afTuple[0] *= fScalar;
+   m_afTuple[1] *= fScalar;
+   m_afTuple[2] *= fScalar;
+   return *this;
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator/=(const double& fScalar)
+{
+   if ( !zero(fScalar) )
+   {
+      double fInvScalar = 1.0/fScalar;
+      m_afTuple[0] *= fInvScalar;
+      m_afTuple[1] *= fInvScalar;
+      m_afTuple[2] *= fInvScalar;
+   }
+   else
+   {
+      m_afTuple[0] = Ub::inf;
+      m_afTuple[1] = Ub::inf;
+      m_afTuple[2] = Ub::inf;
+   }
+
+   return *this;
+}
+/*=======================================================*/
+Vector3D Vector3D::Scale(const double& x)
+{
+   Vector3D PointA(0.0,0.0,0.0);
+   PointA.m_afTuple[0] = x * m_afTuple[0];
+   PointA.m_afTuple[1] = x * m_afTuple[1];
+   PointA.m_afTuple[2] = x * m_afTuple[2];
+   return PointA;	
+}
+/*=======================================================*/
+double Vector3D::Length() const
+{
+   return std::sqrt( m_afTuple[0]*m_afTuple[0] +
+                     m_afTuple[1]*m_afTuple[1] +
+                     m_afTuple[2]*m_afTuple[2] );
+}
+/*=======================================================*/
+double Vector3D::SquaredLength() const
+{
+   return m_afTuple[0]*m_afTuple[0] +
+          m_afTuple[1]*m_afTuple[1] +
+          m_afTuple[2]*m_afTuple[2];
+}
+/*=======================================================*/
+double Vector3D::Dot(const Vector3D& rkV) const
+{
+   return m_afTuple[0]*rkV.m_afTuple[0] +
+          m_afTuple[1]*rkV.m_afTuple[1] +
+          m_afTuple[2]*rkV.m_afTuple[2];
+}
+/*=======================================================*/
+double Vector3D::Normalize()
+{
+   double fLength = Length();
+
+   if( !zero(fLength) )
+   {
+      double fInvLength = 1.0/fLength;
+      m_afTuple[0] *= fInvLength;
+      m_afTuple[1] *= fInvLength;
+      m_afTuple[2] *= fInvLength;
+   }
+   else
+   {
+      fLength = 0.0;
+      m_afTuple[0] = 0.0;
+      m_afTuple[1] = 0.0;
+      m_afTuple[2] = 0.0;
+   }
+
+   return fLength;
+}
+/*=======================================================*/
+Vector3D Vector3D::Cross(const Vector3D& rkV) const
+{
+   return Vector3D( m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
+                    m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
+                    m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0] );
+}
+/*=======================================================*/
+Vector3D Vector3D::UnitCross(const Vector3D& rkV) const
+{
+   Vector3D kCross( m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
+                    m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
+                    m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0] );
+   kCross.Normalize();
+   return kCross;
+}
+/*=======================================================*/
+void Vector3D::GetBarycentrics(const Vector3D& rkV0,const Vector3D& rkV1, const Vector3D& rkV2,const Vector3D& rkV3, double afBary[4]) const
+{
+   // compute the vectors relative to V3 of the tetrahedron
+   Vector3D akDiff[4] = { rkV0  - rkV3,
+                          rkV1  - rkV3,
+                          rkV2  - rkV3,
+                          *this - rkV3 };
+
+   // If the vertices have large magnitude, the linear system of
+   // equations for computing barycentric coordinates can be
+   // ill-conditioned.  To avoid this, uniformly scale the tetrahedron
+   // edges to be of order 1.  The scaling of all differences does not
+   // change the barycentric coordinates.
+   double fMax = 0.0,fValue=0.0;
+   for(int i=0; i<3; i++)
+      for (int j=0; j<3; j++)
+      {
+         fValue = std::fabs(akDiff[i][j]);
+         if ( fValue > fMax )  fMax = fValue;
+      }
+   
+   // scale down only large data
+   if( greater(fMax,1.0) )
+   {
+      double fInvMax = ((double)1.0)/fMax;
+      for( int i=0; i<4; i++)
+         akDiff[i] *= fInvMax;
+   }
+
+   double     fDet = akDiff[0].Dot(akDiff[1].Cross(akDiff[2]));
+   Vector3D kE1cE2 = akDiff[1].Cross(akDiff[2]);
+   Vector3D kE2cE0 = akDiff[2].Cross(akDiff[0]);
+   Vector3D kE0cE1 = akDiff[0].Cross(akDiff[1]);
+   
+   if( !zero( fDet ) )
+   {
+      double fInvDet = 1.0/fDet;
+      afBary[0] = akDiff[3].Dot(kE1cE2)*fInvDet;
+      afBary[1] = akDiff[3].Dot(kE2cE0)*fInvDet;
+      afBary[2] = akDiff[3].Dot(kE0cE1)*fInvDet;
+      afBary[3] = 1.0 - afBary[0] - afBary[1] - afBary[2];
+   }
+   else
+   {
+      // The tetrahedron is potentially flat.  Determine the face of
+      // maximum area and compute barycentric coordinates with respect
+      // to that face.
+      Vector3D kE02 = rkV0 - rkV2;
+      Vector3D kE12 = rkV1 - rkV2;
+      Vector3D kE02cE12 = kE02.Cross(kE12);
+      double fMaxSqrArea = kE02cE12.SquaredLength();
+      int iMaxIndex = 3;
+      double fSqrArea = kE0cE1.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 0;
+         fMaxSqrArea = fSqrArea;
+      }
+      fSqrArea = kE1cE2.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 1;
+         fMaxSqrArea = fSqrArea;
+      }
+      fSqrArea = kE2cE0.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 2;
+         fMaxSqrArea = fSqrArea;
+      }
+
+      if ( greater(fMaxSqrArea,0.0)  )
+      {
+         double fInvSqrArea = 1.0/fMaxSqrArea;
+         Vector3D kTmp;
+         if( iMaxIndex==0 )
+         {
+            kTmp      = akDiff[3].Cross(akDiff[1]);
+            afBary[0] = kE0cE1.Dot(kTmp)*fInvSqrArea;
+            kTmp      = akDiff[0].Cross(akDiff[3]);
+            afBary[1] = kE0cE1.Dot(kTmp)*fInvSqrArea;
+            afBary[2] = 0.0;
+            afBary[3] = 1.0 - afBary[0] - afBary[1];
+         }
+         else if( iMaxIndex == 1 )
+         {
+            afBary[0] = 0.0;
+            kTmp      = akDiff[3].Cross(akDiff[2]);
+            afBary[1] = kE1cE2.Dot(kTmp)*fInvSqrArea;
+            kTmp      = akDiff[1].Cross(akDiff[3]);
+            afBary[2] = kE1cE2.Dot(kTmp)*fInvSqrArea;
+            afBary[3] = 1.0 - afBary[1] - afBary[2];
+         }
+         else if( iMaxIndex == 2 )
+         {
+            kTmp      = akDiff[2].Cross(akDiff[3]);
+            afBary[0] = kE2cE0.Dot(kTmp)*fInvSqrArea;
+            afBary[1] = 0.0;
+            kTmp      = akDiff[3].Cross(akDiff[0]);
+            afBary[2] = kE2cE0.Dot(kTmp)*fInvSqrArea;
+            afBary[3] = 1.0 - afBary[0] - afBary[2];
+         }
+         else
+         {
+            akDiff[3] = *this - rkV2;
+            kTmp      = akDiff[3].Cross(kE12);
+            afBary[0] = kE02cE12.Dot(kTmp)*fInvSqrArea;
+            kTmp      = kE02.Cross(akDiff[3]);
+            afBary[1] = kE02cE12.Dot(kTmp)*fInvSqrArea;
+            afBary[2] = 1.0 - afBary[0] - afBary[1];
+            afBary[3] = 0.0;
+         }
+      }
+      else
+      {
+         // The tetrahedron is potentially a sliver.  Determine the edge of
+         // maximum length and compute barycentric coordinates with respect
+         // to that edge.
+         double fMaxSqrLength = akDiff[0].SquaredLength();
+         iMaxIndex            = 0;  // <V0,V3>
+         double fSqrLength    = akDiff[1].SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 1;  // <V1,V3>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = akDiff[2].SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 2;  // <V2,V3>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = kE02.SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 3;  // <V0,V2>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = kE12.SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 4;  // <V1,V2>
+            fMaxSqrLength = fSqrLength;
+         }
+         
+         Vector3D kE01 = rkV0 - rkV1;
+         fSqrLength    = kE01.SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 5;  // <V0,V1>
+            fMaxSqrLength = fSqrLength;
+         }
+
+         if( greater(fMaxSqrLength, 0.0) )
+         {
+            double fInvSqrLength = 1.0/fMaxSqrLength;
+            if( iMaxIndex == 0 )
+            {
+               // P-V3 = t*(V0-V3)
+               afBary[0] = akDiff[3].Dot(akDiff[0])*fInvSqrLength;
+               afBary[1] = 0.0;
+               afBary[2] = 0.0;
+               afBary[3] = 1.0 - afBary[0];
+            }
+            else if( iMaxIndex == 1 )
+            {
+               // P-V3 = t*(V1-V3)
+               afBary[0] = 0.0;
+               afBary[1] = akDiff[3].Dot(akDiff[1])*fInvSqrLength;
+               afBary[2] = 0.0;
+               afBary[3] = 1.0 - afBary[1];
+            }
+            else if( iMaxIndex == 2 )
+            {
+               // P-V3 = t*(V2-V3)
+               afBary[0] = 0.0;
+               afBary[1] = 0.0;
+               afBary[2] = akDiff[3].Dot(akDiff[2])*fInvSqrLength;
+               afBary[3] = 1.0 - afBary[2];
+            }
+            else if( iMaxIndex == 3 )
+            {      
+               // P-V2 = t*(V0-V2)
+               akDiff[3] = *this - rkV2;
+               afBary[0] = akDiff[3].Dot(kE02)*fInvSqrLength;
+               afBary[1] = 0.0;
+               afBary[2] = 1.0 - afBary[0];
+               afBary[3] = 0.0;
+            }
+            else if( iMaxIndex == 4 )
+            {
+               // P-V2 = t*(V1-V2)
+               akDiff[3] = *this - rkV2;
+               afBary[0] = 0.0;
+               afBary[1] = akDiff[3].Dot(kE12)*fInvSqrLength;
+               afBary[2] = 1.0 - afBary[1];
+               afBary[3] = 0.0;
+            }
+            else
+            {
+               // P-V1 = t*(V0-V1)
+               akDiff[3] = *this - rkV1;
+               afBary[0] = akDiff[3].Dot(kE01)*fInvSqrLength;
+               afBary[1] = 1.0 - afBary[0];
+               afBary[2] = 0.0;
+               afBary[3] = 0.0;
+            }
+         }
+         else
+         {
+            // tetrahedron is a nearly a point, just return equal weights
+            afBary[0] = 0.25;
+            afBary[1] = afBary[0];
+            afBary[2] = afBary[0];
+            afBary[3] = afBary[0];
+         }
+      }
+   }
+}
+/*=======================================================*/
+void Vector3D::Orthonormalize(Vector3D& rkU, Vector3D& rkV, Vector3D& rkW)
+{
+   // If the input vectors are v0, v1, and v2, then the Gram-Schmidt
+   // orthonormalization produces vectors u0, u1, and u2 as follows,
+   //
+   //   u0 = v0/|v0|
+   //   u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
+   //   u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1|
+   //
+   // where |A| indicates length of vector A and A*B indicates dot
+   // product of vectors A and B.
+
+   // compute u0
+   rkU.Normalize();
+
+   // compute u1
+   double fDot0 = rkU.Dot(rkV); 
+   rkV -= fDot0*rkU;
+   rkV.Normalize();
+
+   // compute u2
+   double fDot1 = rkV.Dot(rkW);
+   fDot0 = rkU.Dot(rkW);
+   rkW  -= fDot0*rkU + fDot1*rkV;
+   rkW.Normalize();
+}
+/*=======================================================*/
+void Vector3D::Orthonormalize(Vector3D* akV)
+{
+   Orthonormalize(akV[0],akV[1],akV[2]);
+}
+/*=======================================================*/
+void Vector3D::GenerateOrthonormalBasis(Vector3D& rkU, Vector3D& rkV,Vector3D& rkW, bool bUnitLengthW)
+{
+   if ( !bUnitLengthW )
+      rkW.Normalize();
+
+   double fInvLength;
+
+   if ( greaterEqual( std::fabs(rkW.m_afTuple[0]),std::fabs(rkW.m_afTuple[1]) ) )
+   {
+      // W.x or W.z is the largest magnitude component, swap them
+      fInvLength = UbMath::invSqrt(rkW.m_afTuple[0]*rkW.m_afTuple[0] + rkW.m_afTuple[2]*rkW.m_afTuple[2]);
+      rkU.m_afTuple[0] = -rkW.m_afTuple[2]*fInvLength;
+      rkU.m_afTuple[1] = (double)0.0;
+      rkU.m_afTuple[2] = +rkW.m_afTuple[0]*fInvLength;
+   }
+   else
+   {
+      // W.y or W.z is the largest magnitude component, swap them
+      fInvLength = UbMath::invSqrt(rkW.m_afTuple[1]*rkW.m_afTuple[1] + rkW.m_afTuple[2]*rkW.m_afTuple[2]);
+      rkU.m_afTuple[0] = (double)0.0;
+      rkU.m_afTuple[1] = +rkW.m_afTuple[2]*fInvLength;
+      rkU.m_afTuple[2] = -rkW.m_afTuple[1]*fInvLength;
+   }
+
+   rkV = rkW.Cross(rkU);
+}
+/*=======================================================*/
+//globaler operator* 
+Vector3D operator*(const double& fScalar, const Vector3D& rkV)
+{
+   return Vector3D( fScalar*rkV[0],
+                    fScalar*rkV[1],
+                    fScalar*rkV[2] );
+}
+/*=======================================================*/
+std::ostream& operator* (std::ostream& os, const Vector3D& rkV)
+{
+   os<<rkV.toString();
+   return os;
+}
+} //end namespace UbMath
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbMath.h b/source/ThirdParty/Library/basics/utilities/UbMath.h
new file mode 100644
index 0000000000000000000000000000000000000000..4571514f86d3cc743008dd9b5d4ba1d5f687dd5e
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbMath.h
@@ -0,0 +1,548 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBMATH_H
+#define UBMATH_H
+
+#include <cmath>
+#include <limits>
+#include <iostream>
+#include <cassert>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbEqual.h>
+
+/*=========================================================================*/
+/*  UbMath                                                             */
+/*                                                                         */
+/**
+namespace for global math-functions
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.4 - 04.10.07
+*/ 
+
+/*
+usage: ...
+*/
+
+namespace UbMath 
+{
+   extern const double PI;
+   
+   
+   //////////////////////////////////////////////////////////////////////////
+   //Hilfsfunktion fuer Genauigkeit
+   template< typename T >
+   struct Epsilon {  };
+
+   //////////////////////////////////////////////////////////////////////////
+   //  SPECIALIZATIONS von Epsilon
+   //////////////////////////////////////////////////////////////////////////
+   template<>
+   struct Epsilon<double>        { static inline double      val() { return 1.0E-11; } };
+   template<>
+   struct Epsilon<float>         { static inline float       val() { return 1.0E-7f; } };
+   template<>
+   struct Epsilon<long double>   { static inline long double val() { return 1.0E-15; } };
+   template<>
+   struct Epsilon<int>           { static inline int         val() { return 0;       } };
+
+   /*=======================================================*/
+   // -------------------------------------------------------------------------------------------------
+   // Funktion berechnet den Logarithmus einer Zahl z bzgl. der Basis b
+   // -------------------------------------------------------------------------------------------------
+   template<typename T>
+   inline T log(const T& z, const T& base)
+   {
+      if( ::log(base)==0 ) return 1.0f;
+      return ::log(z) / ::log(base);
+   }
+   /*=======================================================*/
+   //double x = UbMath::getNegativeInfinity<double>();
+   template<typename T>
+   inline T getNegativeInfinity()
+   {
+      //assert(std::numeric_limits<T>::has_infinity);
+      UB_STATIC_ASSERT(std::numeric_limits<T>::has_infinity);
+      return -std::numeric_limits<T>::infinity();
+   }
+   /*=======================================================*/
+   //double x = UbMath::getPositiveInfinity<double>();
+   template<typename T>
+   inline T getPositiveInfinity()
+   {
+      //assert(std::numeric_limits<T>::has_infinity);
+      UB_STATIC_ASSERT(std::numeric_limits<T>::has_infinity);
+      return std::numeric_limits<T>::infinity();
+   }
+   /*=======================================================*/
+   //double x; bool b = UbMath::isInfinity(x);
+   template<typename T>
+   inline bool isInfinity(const T& value)
+   {
+      if(value==getNegativeInfinity<T>()) return true;
+      if(value==getPositiveInfinity<T>()) return true;
+      return false;
+   }
+   /*=======================================================*/
+   //double x = UbMath::getNaN<double>(x);
+   template<typename T>
+   inline T getNaN()
+   {
+      UB_STATIC_ASSERT(std::numeric_limits<T>::has_quiet_NaN);
+      return std::numeric_limits<T>::quiet_NaN();
+   }
+   /*=======================================================*/
+   //double x; bool b = UbMath::isNaN(x);
+   // x!=x liefert bei #QNAN "true"!
+   template<typename T>
+   inline bool isNaN(const T& x)
+   {
+      UB_STATIC_ASSERT(std::numeric_limits<T>::has_quiet_NaN);
+      return (x != x); 
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T getEqualityEpsilon()		  
+   { 
+      return  Epsilon<T>::val();  
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool zero(const T& value)		  
+   { 
+      return std::fabs( value ) < Epsilon<T>::val();
+      //return value >= -UbMath::EPSILON && value <= UbMath::EPSILON;	
+   }
+   /*=======================================================*/
+   //spezialisierung fuer ints
+   template<>
+   inline bool zero(const int& value)		  
+   { 
+      return value == 0;
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool zero(const T1& value1, const T2& value2)		  
+   { 
+      return !(!UbMath::zero(value1) || !UbMath::zero(value2));	
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline bool zero(const T1& value1, const T2& value2, const T3& value3)		  
+   { 
+      return !(!UbMath::zero(value1) || !UbMath::zero(value2,value3));	
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool negative(const T& value)    
+   { 
+      return value < -Epsilon<T>::val();  
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool nonPositive(const T& value) 
+   { 
+      return value <= Epsilon<T>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool positive(const T& value)    
+   { 
+      return value > +Epsilon<T>::val();   
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool nonNegative(const T& value) 
+   { 
+      return value >= -Epsilon<T>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool equal(const T1& value, const T2& reference) 
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return std::fabs(value-reference) < Epsilon<High>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline bool equal(const T1& val1, const T2& val2, const T3& val3) 
+   { 
+      return ( UbMath::equal(val1,val2) && UbMath::equal(val1,val3) ); 
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool less(const T1& value, const T2& reference)   
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return value < reference - Epsilon<High>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool lessEqual(const T1& value, const T2& reference) 
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return value <= reference + Epsilon<High>::val();
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool greater(const T1& value, const T2& reference)      
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return value > reference + Epsilon<High>::val();  
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool greaterEqual(const T1& value, const T2& reference) 
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return value >= reference - Epsilon<High>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T round(const T& value, const int& decimalPlaces) 
+   { 
+      return static_cast<T>(floor(value * pow( 10.0, decimalPlaces) + 0.5 ) * pow(10.0, -decimalPlaces)); 
+   } 
+   /*=======================================================*/
+   template<typename T>
+   inline int integerRounding(const T& value) 
+   { 
+      return static_cast<int>( UbMath::zero(value) ?  0 : ( (value<0.0) ? (value-0.5) : (value+0.5) ) );
+   } 
+   /*=======================================================*/
+   template<typename T>
+   inline T getRad(const T& degrees) 
+   {
+      return degrees*static_cast<T>(UbMath::PI/180.0);
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T getDegrees(const T& rad) 
+   {
+      return rad*static_cast<T>(UbMath::PI/180.0);
+   }
+   /*=======================================================*/
+   //aus wildmagic
+   template<typename T>
+   inline T ACos (const T& fValue)
+   {
+      if ( -1.0 < fValue )
+      {
+         if ( fValue < 1.0 ) return static_cast<T>( acos(fValue) );
+         else                return static_cast<T>( 0.0          );
+      }
+      else return static_cast<T>( PI );
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T ASin(const T& fValue)
+   {
+      double HALF_PI = 0.5*UbMath::PI;
+      if ( -1.0 < fValue )
+      {
+         if ( fValue < 1.0 ) return static_cast<T>( asin(fValue) );
+         else                return static_cast<T>( HALF_PI      );
+      }
+      else return -static_cast<T>( HALF_PI );         
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T invSqrt(const T& fValue)   
+   { 
+      return static_cast<T>(1.0/sqrt(fValue));
+   }
+
+   /*=======================================================*/
+   /**
+   * Returns true, if specified values a and b are less both values c and d.
+   * @param a the first value to check
+   * @param b the second value to check
+   * @param c the first value to check against
+   * @param d the second value to check against
+   * @return true, if specified values a and b are less both values c and d
+   **/
+   template<typename T1, typename T2, typename T3, typename T4>
+   inline bool less2(const T1& value1, const T2& value2, T3 toBeLessAs1, T4 toBeLessAs2) 
+   {	
+      return (   less(value1,toBeLessAs1)
+              && less(value1,toBeLessAs2)
+              && less(value2,toBeLessAs1)
+              && less(value2,toBeLessAs2) );
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3, typename T4>
+   inline bool greater2(const T1& value1, const T2& value2, T3 toBeGreaterAs1, T4 toBeGreaterAs2)
+   { 
+      return (   greater(value1,toBeGreaterAs1)
+              && greater(value1,toBeGreaterAs2)
+              && greater(value2,toBeGreaterAs1)
+              && greater(value2,toBeGreaterAs2) );
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline bool inClosedInterval(const T1& value, const T2& threshold1, const T3& threshold2)
+   { 
+      if(threshold1 < threshold2)
+      {
+         return ( greaterEqual( value, threshold1) && lessEqual( value, threshold2) );
+      }
+
+      return ( greaterEqual( value, threshold2) && lessEqual( value, threshold1) );
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline bool inOpenInterval(const T1& value, const T2& threshold1, const T3& threshold2)
+   {	
+      if(threshold1 < threshold2) 
+      {
+         return (greater( value, threshold1) && less( value, threshold2));
+      }
+
+      return (greater( value, threshold2) && less( value, threshold1));
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline double adaptToClosedInterval(const T1& value, const T2& threshold1, const T3& threshold2)
+   { 
+      if(threshold1 < threshold2)
+      {
+         if     ( less(   value, threshold1) ) return threshold1;
+         else if( greater(value, threshold2) ) return threshold2;
+      }
+      else
+      {
+         if     ( less(   value, threshold2) ) return threshold2;
+         else if( greater(value, threshold1) ) return threshold1;
+      }
+      return value;
+   }
+   /*=======================================================*/
+   // -------------------------------------------------------------------------------------------------
+   // Funktion berechnet den groessten gemeinsamen Teiler zweier Zahlen (MK)
+   // -------------------------------------------------------------------------------------------------
+   /*=======================================================*/
+   inline int calcGgt(int val1, int val2)
+   {
+      if( val1 < val2 ) std::swap(val1,val2);
+      int ggt=val2;
+      while(ggt > 1)
+      {
+         if( (val1%ggt)==0 && (val2%ggt)==0 ) break;
+
+         ggt -=1;
+      }
+      return ggt;
+   }
+   /*=======================================================*/
+   // -------------------------------------------------------------------------------------------------
+   // Funktion berechnet den groessten gemeinsamen Teiler von drei Zahlen (MK)
+   // -------------------------------------------------------------------------------------------------
+   inline int calcGgt(int val1, const int& val2, int val3)
+   {
+      return UbMath::calcGgt( UbMath::calcGgt(val1, val2), val3 );
+   }
+   /*=======================================================*/
+   //returns the max of two values
+   //to avoid errors at mixed argument-types use: double myMax = max<double>(2,2.3);
+   template< typename T >
+   inline const T& max(const T& a1, const T& a2) 
+   { 
+     return (a1<a2) ? a2 : a1;
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& max(const T& a1, const T& a2, const T& a3) 
+   { 
+      return max(max(a1,a2),a3);
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& max(const T& a1, const T& a2, const T& a3, const T& a4)
+   {
+      return max(max(max(a1,a2),a3),a4);
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& min(const T& a1,const T& a2) 
+   { 
+      return (a1<a2) ? a1 : a2;
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& min(const T& a1, const T& a2, const T& a3) 
+   { 
+      return min(min(a1,a2),a3);
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& min(const T& a1, const T& a2, const T& a3, const T& a4)
+   {
+      return min(min(min(a1,a2),a3),a4);
+      
+//       double tmp = a1;
+//       if(tmp>a2) tmp=a2;
+//       if(tmp>a3) tmp=a3;
+//       if(tmp>a4) tmp=a4;
+//       return tmp;
+   }
+   /*=======================================================*/
+
+   class Vector3D
+   {
+   public:
+      // construction
+      Vector3D(); 
+      Vector3D(const double& fX1, const double& fX2, const double& fX3);
+      Vector3D(const Vector3D& rkV);
+
+      std::string toString() const;
+
+      // coordinate access
+      operator const double*() const;
+      operator double*();
+      double   operator[](const int& i) const;
+      double&  operator[](const int& i);
+      double   X1() const;
+      double&  X1();
+      double   X2() const;
+      double&  X2();                                    
+      double   X3() const;
+      double&  X3();
+
+      // assignment
+      Vector3D& operator=(const Vector3D& rkV);
+
+      // comparison
+      bool operator==(const Vector3D& rkV) const;
+      bool operator!=(const Vector3D& rkV) const;
+      bool operator< (const Vector3D& rkV) const;
+      bool operator<=(const Vector3D& rkV) const;
+      bool operator> (const Vector3D& rkV) const;
+      bool operator>=(const Vector3D& rkV) const;
+
+      // arithmetic operations
+      Vector3D operator+(const Vector3D& rkV) const;
+      Vector3D operator-(const Vector3D& rkV) const;
+      Vector3D operator*(const double& fScalar) const;
+      Vector3D operator/(const double& fScalar) const;
+      Vector3D operator-() const;
+
+      // arithmetic updates
+      Vector3D& operator+= (const Vector3D& rkV);
+      Vector3D& operator-= (const Vector3D& rkV);
+      Vector3D& operator*= (const double& fScalar);
+      Vector3D& operator/= (const double& fScalar);
+
+      Vector3D Add(Vector3D& vector);
+      Vector3D Subtract(Vector3D& vector);
+      Vector3D Scale(const double& x);
+
+      // vector operations
+      double Length () const;
+      double SquaredLength () const;
+      double Dot (const Vector3D& rkV) const;
+      double Normalize ();
+
+      // The cross products are computed using the right-handed rule.  Be aware
+      // that some graphics APIs use a left-handed rule.  If you have to compute
+      // a cross product with these functions and send the result to the API
+      // that expects left-handed, you will need to change sign on the vector
+      // (replace each component value c by -c).
+      Vector3D Cross (const Vector3D& rkV) const;
+      Vector3D UnitCross (const Vector3D& rkV) const;
+
+      // Compute the barycentric coordinates of the point with respect to the
+      // tetrahedron <V0,V1,V2,V3>, P = b0*V0 + b1*V1 + b2*V2 + b3*V3, where
+      // b0 + b1 + b2 + b3 = 1.
+      void GetBarycentrics (const Vector3D& rkV0, const Vector3D& rkV1, const Vector3D& rkV2, const Vector3D& rkV3, double afBary[4]) const;
+
+      // Gram-Schmidt orthonormalization.  Take linearly independent vectors
+      // U, V, and W and compute an orthonormal set (unit length, mutually
+      // perpendicular).
+      static void Orthonormalize (Vector3D& rkU, Vector3D& rkV, Vector3D& rkW);
+      static void Orthonormalize (Vector3D* akV);
+
+      // Input W must be initialized to a nonzero vector, output is {U,V,W},
+      // an orthonormal basis.  A hint is provided about whether or not W
+      // is already unit length.
+      static void GenerateOrthonormalBasis (Vector3D& rkU, Vector3D& rkV, Vector3D& rkW, bool bUnitLengthW);
+
+      // special vectors
+      static const Vector3D ZERO;
+      static const Vector3D UNIT_X1;
+      static const Vector3D UNIT_X2;
+      static const Vector3D UNIT_X3;
+
+   #ifdef CAB_RCF
+         template<class Archive>
+         void serialize(Archive & ar, const unsigned int version)
+         {
+            ar & m_afTuple;
+         }
+   #endif //CAB_RCF
+
+   protected:
+      // support for comparisons
+      int CompareArrays (const Vector3D& rkV) const;
+
+      double m_afTuple[3];
+   };
+   
+   //globaler multiplaktor mit skalar
+   Vector3D operator*(const double& fScalar, const Vector3D& rkV);
+   std::ostream& operator<<(std::ostream& os, const Vector3D& rkV);
+
+   //////////////////////////////////////////////////////////////////////////
+   //
+   //constants
+   //
+   //////////////////////////////////////////////////////////////////////////
+   static const double c8o27=8./27.;
+   static const double c2o27=2./27.;
+   static const double c1o54=1./54.;
+   static const double c1o216=1./216.;
+   static const double c9o2=9./2.;
+   static const double c3o9=3./9.;
+   static const double c3o54=3./54.;
+   static const double c3o216=3./216.;
+
+   static const double c1o27=1./27.;
+
+   static const double c1o72  = 1./72.;          //0.01388888
+   static const double c1o36  = 1./36.;          //0.02777777
+   static const double c1o48  = 1./48.;          //0.02083333
+   static const double c1o32  = 1./32.;          //0.03125
+   static const double c1o24  = 1./24.;          //0.04166666
+   static const double c1o20  = 1./20.;          //0.05
+   static const double c1o18  = 1./18.;          //0.05555555
+   static const double c1o16  = 1./16.;          //0.0625
+   static const double c1o12  = 1./12.;          //0.08333333
+   static const double c1o9   = 1./9.;           //0.11111111
+   static const double c1o8   = 1./8.;           //0.125
+   static const double c1o6   = 1./6.;           //0.16666666
+   static const double c1o5   = 1./5.;           //0.2
+   static const double c1o4   = 1./4.;           //0.25
+   static const double c5o16  = 5./16.;          //0.3125
+   static const double c1o3   = 1./3.;           //0.33333333
+   static const double c3o8   = 3./8.;           //0.375
+   static const double c4o9   = 4./9.;           //0.44444444
+   static const double c1o2   = 1./2.;           //0.5
+   static const double c9o16  = 9./16.;          //0.5625
+   static const double c2o3   = 2./3.;           //0.66666666
+   static const double c3o4   = 3./4.;           //0.75
+   static const double c3o2   = 3./2.;           //1.5
+   static const double c4o3   = 4./3.;           //1.33333333
+   static const double c5o3   = 5./3.;           //1.66666666
+   static const double c9o5   = 9./5.;           //1.8
+   static const double c2o9   = 2./9.;           //0.22222222
+   static const double one_over_sqrt2 =  1.0/sqrt(2.0); //0.707106781
+   static const double one_over_sqrt3 =  1.0/sqrt(3.0); //0.577350269
+   static const double sqrt2  = sqrt(2.0); //1.4142135
+   static const double sqrt3  = sqrt(3.0); //1.7320508
+}
+
+#endif
diff --git a/source/ThirdParty/Library/basics/utilities/UbNupsTimer.h b/source/ThirdParty/Library/basics/utilities/UbNupsTimer.h
new file mode 100644
index 0000000000000000000000000000000000000000..8320aa7de8c5e465edaa032a1816f016e6133bc7
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbNupsTimer.h
@@ -0,0 +1,93 @@
+#ifndef UBNUPSTIMER_H
+#define UBNUPSTIMER_H
+
+#include <basics/utilities/UbTiming.h>
+#include <sstream>
+#include <vector>
+
+
+/*=========================================================================*/
+/*  UbNupsTimer                                                             */
+/*                                                                         */
+/**
+This Class provides the base for ...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 01.11.04
+*/ 
+class UbNupsTimer : public UbTiming
+{
+public:
+   UbNupsTimer() : UbTiming()
+   {
+      mTempNodes = 0.0;
+      mNofNodes.resize(0);
+      mDurations.resize(0);
+   }
+   /*==========================================================*/
+   UbNupsTimer(std::string name) : UbTiming(name)
+   {
+      mNofNodes.resize(0);
+      mDurations.resize(0);
+      mTempNodes = 0.0;
+   }
+   /*==========================================================*/
+   void initTiming()
+   {
+      UbTiming::initTiming();
+      mNofNodes.resize(0);
+      mDurations.resize(0);
+      mTempNodes   = 0.0;
+   }
+   /*==========================================================*/
+   void startTiming(double nofNodes)
+   {
+      mTempNodes=nofNodes;
+      UbTiming::startTiming();
+   }
+   /*==========================================================*/
+   void endTiming()
+   {
+      UbTiming::endTiming();
+      //save #node and time informations
+      mNofNodes.push_back(mTempNodes);
+      mDurations.push_back(UbTiming::getDuration());
+      //reset internal timecounter
+      UbTiming::initTiming();
+   }
+   /*==========================================================*/
+   double getAverageNups()
+   { 
+      double averageNups = 0.0;
+      for(int i=0;i<(int)mNofNodes.size();i++)
+         averageNups+=mNofNodes.at(i)/mDurations.at(i);
+      
+      return averageNups/(double)mNofNodes.size(); 
+   }
+   /*==========================================================*/
+   double getSumOfDuration()
+   {
+      double duration = 0.0;
+      for(int i=0;i<(int)mDurations.size();i++) duration+=mDurations.at(i);
+      return duration;
+   }
+   /*==========================================================*/
+   std::string getNupsString()
+   {
+      std::stringstream ss;
+      ss<<"saved nups informations"<<std::endl;
+      for(int i=0;i<(int)mNofNodes.size();i++)
+         ss<<mNofNodes.at(i)<<"nodes/"<<mDurations.at(i)<<"sec="<<mNofNodes.at(i)/mDurations.at(i)<<"nups\n";
+      return ss.str();
+   }
+
+protected:
+
+private:
+   std::vector<double> mNofNodes;
+   std::vector<double> mDurations;
+   
+   double mTempNodes;
+};
+
+#endif
diff --git a/source/ThirdParty/Library/basics/utilities/UbObservable.h b/source/ThirdParty/Library/basics/utilities/UbObservable.h
new file mode 100644
index 0000000000000000000000000000000000000000..a1ab9cafbe4443680dc728d1f8907a1ba34c1462
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbObservable.h
@@ -0,0 +1,259 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBOBSERVABLE_H
+#define UBOBSERVABLE_H
+
+#include <list>               
+#include <iostream>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <basics/utilities/UbObserver.h>
+
+class UbObserver;
+
+/*=========================================================================*/
+/*  Beobachtbares Objekt                                                   */
+/*                                                                         */
+/**
+  This class provides Observables. The Observeres which observe this
+  Observable are stored in an observerlist.
+  IMPORTANT: objectWillBeDeleted is called at UbObserver::~UbObserver
+             this destructor is called AFTER the destructor of the
+             child classes. if you down_cast the pointer sent with the
+             objectWillBeDeleted(UbObserver* objpointer) then have to go this:
+               
+               if(dynamic_cast<UbObserver*>(observedObj)==objpointer) 
+                     (e.g.) observedObj=NULL;
+   example: see end of file
+
+   a copy of an UbservableObject will NOT copy the observerList
+  <UL>
+    <LI><B>Extending:</B> This UbObservable is the observable object itself. Extending should be used
+	where object types can be extended from UbObservable.
+    <LI><B>Associating:</B> Initialization is done via the constructor <tt>UbObservable(ObservableObject)</tt>.
+	Associating may be used, where object types to be observed could not be extended from UbObservable.
+  </UL>
+  <BR><BR><HR>        
+  @author <A HREF="mailto:geller@cab.bau.tu-bs.de">S. Geller</A>
+  @author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+  @version 1.2 - 13.07.05
+  @see UbObserver
+*/
+
+class UbObservable 
+{
+protected:
+   /*======================================================================*/
+   /*  Konstruktoren                                                       */
+   /*                                                                      */
+   /**
+     Creates a UbObservable itself to be the object to be observed.
+     Usually this constructor is used in extended classes.
+   */
+   UbObservable()
+   {
+   }
+   
+   UbObservable(const UbObservable& src)
+   {
+      //no copy of observers !!!
+   }
+   
+   //falls irgendein schlaumeier den =operator von UbObservable aufrufen sollte,
+   //dann macht diesr auch keine kopie! (Allg: zuweisungsoperatoren werden nie vererbt
+   UbObservable& operator=(const UbObservable& src)
+   {
+      return *this;
+   }
+   
+   //   /**
+   //     Creates a UbObservable for the specified Object to be observed.
+   //     Usually this constructor is used in associating UbObservable.
+   //     @param object Object to be observed
+   //   */
+public:
+   /*======================================================================*/
+   /*  Destruktor                                                          */
+   /*                                                                      */
+   /**
+   */
+   virtual ~UbObservable()
+   {
+      this->notifyObserversObjectWillBeDeleted();
+   } 
+
+   /*======================================================================*/
+   /*  methods                                                            */
+   /*                                                                      */
+   
+   /**
+   Adds an UbObserver to the observerlist.
+   @param observer the observer to add to this observable (note that an observer may observe one observable more than once)
+   */
+   virtual void addObserver(UbObserver* observer)
+   {
+      if(!observer) return;
+      for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();++pos)
+      {
+         if(*pos == observer) return;
+      }
+      this->mObserverList.push_back(observer);
+   }
+   /**
+   Deletes an UbObserver from the observerlist.
+   @param observer the observer to remove from this observable (note that all observers identical are deleted)
+   ( delete means delete Heap... but here we're only removing a pointer)
+   */
+   virtual void removeObserver(UbObserver* observer)
+   {
+      if(!observer) return;
+      this->mObserverList.remove(observer);
+
+   }
+   /**
+   Deletes all Observers from the observerlist.
+   ( delete means delete Heap... but here we're only removing a pointer)
+   */
+   virtual void removeAllObservers()
+   {
+      this->mObserverList.clear();
+   }
+   
+   /**
+     Checks whether the specified UbObserver observes this observable.
+     @param observer the observer to remove from this observable (note that all observers identical are deleted)
+     @return true if the specified observer observes this observable
+   */
+   virtual bool isObservedBy(UbObserver* observer)
+   {
+      if(!observer) return false;
+      for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();++pos)
+      {
+         if(*pos == observer) return true;
+      }
+      return false;
+   }
+   /**
+     Notifies all of its observers that something happened. Does nothing, if the observed object is null.
+     Calls the Method UbObserver.objectChanged(Object) with the object of this observable as parameter.
+     The Method UbObserver.objectChanged(Object) must be defined
+     by each class implementing the interface TiObserver
+   */
+   virtual void notifyObserversObjectChanged()
+   {
+      std::list<UbObserver*>::iterator tmp_pos; //es kann sein, dass der aktuelle observer waehrend
+                                           //objectChanged() removed wird...
+      for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();)
+      {
+        //cout<<"in notifyObserversObjectChanged\n";
+        //cout<<this->mObserverList.size()<<endl;
+
+         tmp_pos = pos++; // erst tmp_pos=pos und dann pos++
+         (*tmp_pos)->objectChanged(this);
+      }
+   }
+
+   std::list<UbObserver*>* getObserverList() { return &mObserverList;}
+
+   virtual std::string toString() { return "UbObservable - toString()"; }
+
+#ifdef CAB_RCF
+   template<typename Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      //do nothing!
+   }
+#endif //CAB_RCF
+
+private:
+   /**
+     Notifies all of its observers that something happened. Does nothing, if the observed object is null.
+     Calls the Method UbObserver.objectChanged(Object) with the object of this observable as parameter.
+     The Method UbObserver.objectChanged(Object) must be defined
+     by each class implementing the interface TiObserver
+   */
+   virtual void notifyObserversObjectWillBeDeleted()
+   {
+      std::list<UbObserver*>::iterator tmp_pos; //es kann sein, dass der aktuelle observer waehrend
+                                          //objectWillBeDeleted() removed wird...
+      for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();)
+      {
+         //cout<<"in notifyObserversObjectWillBeDeleted\n";
+         //cout<<this->mObserverList.size()<<endl;
+
+         tmp_pos = pos++;
+         (*tmp_pos)->objectWillBeDeleted(this);
+      }
+   }
+
+   std::list<UbObserver*> mObserverList;
+};
+/*=========================================================================*/
+
+
+#ifdef RCF_USE_SF_SERIALIZATION
+   SF_NO_CTOR(UbObservable);
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
+
+////  E X A M P L E 
+////===================
+//class Point : public UbObservable
+//{
+//public:
+//   Point(){x=y=0;}
+//   ~Point(){}
+//   void setXCorrdinates(int x,int y)
+//   {
+//     this->x = x; this->y = y;
+//     this->notifyObserverObjectChanged();
+//   }
+//private:
+//   int x,y;
+//};
+//class VisPoint : public UbObserver
+//{
+//public:
+//   VisPoint(Point* point)
+//   { 
+//      this->point = point;
+//      this->point->addObserver(this);
+//   }
+//   ~VisPoint()
+//   {
+//      if(this->point) point->removeObserver(this);
+//   }
+//   void update() { /* do some actualisation stuff */ }
+//   void objectChanged(UbObservable* changedObject)
+//   {
+//      Point* point = dynamic_cast<Point*>(changedObject);
+//      if( !this->point || this->point != point ) return;
+//      this->repaint();
+//   }
+//   void objectWillBeDeleted(UbObservable* objectForDeletion)
+//   {
+//      if(!this->point) return;
+//      UbObservable* obsobjet = dynamic_cast<UbObservable*>(this->point);
+//      if(obsobjet == objectForDeletion) this->point = NULL;
+//      ///////////////////////////////////////////////////////////////////
+//      //*********************************************************************//
+//      //INGEGEN erster annahmen nicht verwenden, da es nicht immer funktioniert
+//      //z.B. bei mehrfachvererbung haut es nicht hin!
+//      ////      Point* point = reinterpret_cast<point*>(objectForDeletion);
+//      ////if(!this->point || objectForDeletion != this->point) return;
+//      ////this->point = NULL;
+//      //*********************************************************************//
+//      //was hingegen immer moeglich sein sollte:
+//      //if(dynamic_cast<void*>(objectForDeletion)==dynamic_cast<void*>(this->point))
+//   }
+//private:
+//   Point* point;
+//};
diff --git a/source/ThirdParty/Library/basics/utilities/UbObserver.h b/source/ThirdParty/Library/basics/utilities/UbObserver.h
new file mode 100644
index 0000000000000000000000000000000000000000..6008481f65fffca2853ab6409d492ac7f9183050
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbObserver.h
@@ -0,0 +1,55 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBOBSERVER_H
+#define UBOBSERVER_H
+
+class UbObservable;
+/*=========================================================================*/
+/*  Observer                                                               */
+/*                                                                         */
+/**
+This interface must be implemented by classes which want to
+observe other objects.
+IMPORTANT: if you delete an observer, ensure to remove Observer from
+           all his oberved observable objects before!!!
+example: see end of UbObservable.h-file
+<BR><BR><HR>
+@author <A HREF="mailto:geller@cab.bau.tu-bs.de">S. Geller</A>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.1 - 20.11.04
+*/
+
+class UbObserver 
+{
+protected:
+
+   UbObserver(){}
+
+public:
+
+   virtual ~UbObserver(){}
+
+   /*======================================================================*/
+   /*  Methoden                                                            */
+   /*                                                                      */
+   /**
+   This function is called when the observable indicated that an object
+   has changed.
+   @param changedObject Object which has changed
+   */
+   virtual void objectChanged(UbObservable* changedObject)=0;
+   /**
+   This function is called when the observable indicated that an object
+   should be deleted.
+   @param objectForDeletion Object which should be deleted
+   */
+   virtual void objectWillBeDeleted(UbObservable* objectForDeletion)=0;
+};
+
+#endif
+
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbPointerWrapper.h b/source/ThirdParty/Library/basics/utilities/UbPointerWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..3fcf0b599c3f87971bbd9f4ee316cb26a9a55275
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbPointerWrapper.h
@@ -0,0 +1,36 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBPOINTERWRAPPER_H
+#define UBPOINTERWRAPPER_H
+
+//kappselt dynamische Objekte zur remote uebetragung
+//bei RCF werden z.B. aufgrund GC alle lokalen Objekte und 
+//"nackte" Pointer die automatisch als shared_ptr initialisert 
+//werde nach Methoden-Aufruf zerstoert
+//hierfuer kann man dann den UbPointerWrapper verwenden
+
+template<typename T>
+class UbPointerWrapper
+{
+public:
+	UbPointerWrapper() : pointer(NULL) {}
+	
+	UbPointerWrapper(T* pointer) : pointer(pointer) {}
+
+   T* get() { return pointer; }
+
+   template<class Archive>
+	void serialize(Archive& ar, const unsigned int version) 
+   {
+		ar & pointer;
+	}
+
+private:
+   T* pointer;
+};
+
+#endif //UBPOINTERWRAPPER_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbRandom.h b/source/ThirdParty/Library/basics/utilities/UbRandom.h
new file mode 100644
index 0000000000000000000000000000000000000000..b4429579eeb94f7a0381bc0f0a19d24845bd3e36
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbRandom.h
@@ -0,0 +1,60 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBRANDOM_H 
+#define UBRANDOM_H 
+
+#include <cstdlib> 
+#include <ctime> 
+#include <cassert> 
+#include <cmath> 
+
+/*=========================================================================*/
+/*  UbRandom                                                             */
+/*                                                                         */
+/**
+generates a random number
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 04.10.2007
+*/ 
+/*
+usage: 
+   int main() 
+   { 
+      char* hand[] = {"Schere", "Stein", "Papier"}; 
+      for (unsigned u = 0; u < 20; u++) 
+      { 
+         cout << hand[UbRandom::rand(0, 2, 1)] << endl; 
+      } 
+
+      return 0; 
+   } 
+*/
+
+class UbRandom 
+{ 
+private: 
+   UbRandom() { std::srand(static_cast<int>(std::time(NULL)));  } 
+
+public: 
+   //returns arbitrary int value element of [min ; max]
+   static inline int rand(const int& min, const int& max) 
+   { 
+      static UbRandom dummy; 
+      assert(max - min < RAND_MAX); 
+      return ( min + std::rand() % (max - min + 1) ); 
+   } 
+   //returns arbitrary float value element of "( (max - min) / gran ) * [min ; max]"
+   //with other words: val = min+n*(max-min)/gran, n=0..gran-1
+   static inline double rand(const double& min, const double& max, const double& gran)
+   {
+      static UbRandom dummy; 
+      return (min + std::floor( std::rand() / (1.0 + RAND_MAX) * gran)* (max - min) / gran);
+   }
+}; 
+
+#endif //UBRANDOM_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbScheduler.h b/source/ThirdParty/Library/basics/utilities/UbScheduler.h
new file mode 100644
index 0000000000000000000000000000000000000000..493b567c8c7fbbdaeadda18711b1cc1a1ca14bab
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbScheduler.h
@@ -0,0 +1,414 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBSCHEDULER_H
+#define UBSCHEDULER_H
+
+#include <iostream>
+#include <string>
+#include <limits>
+#include <cassert> 
+#include <sstream>
+#include <iomanip>
+#include <algorithm>
+
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbInfinity.h>
+#include <basics/utilities/UbComparators.h>
+#include <basics/utilities/UbFileOutput.h>
+#include <basics/utilities/UbFileInput.h>
+
+#include <boost/serialization/serialization.hpp>
+
+
+/*=========================================================================*/
+/*  UbScheduler                                                            */
+/*                                                                         */
+/**
+namespace for global system-functions
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@author <A HREF="mailto:hegewald@cab.bau.tu-bs.de">J. Hegewald</A>
+@version 1.0 - 06.09.06
+@version 1.1 - 09.09.06
+@version 1.2 - 03.07.08 - nun auch isDue(t) mehrmals fuer dasselbe t moeglich
+                          isDue(t) auch fuer t < lastUsedT
+                          bug entfernt, der bei Schedule (5,0,500) auch 505 als Due zurückgibt!
+*/ 
+
+/*
+usage: ...
+*/
+
+// this class is not thread save
+//
+#include <boost/smart_ptr.hpp>
+class UbScheduler;
+typedef boost::shared_ptr<UbScheduler> UbSchedulerPtr;
+
+class UbScheduler
+{
+public:
+   class UbSchedule
+   {
+      friend class UbScheduler;
+   public:
+      UbSchedule() :  step(Ub::inf), begin(Ub::inf), end(Ub::inf) { }
+      UbSchedule(const double& step, const double& begin=0.0, const double& end=Ub::inf) 
+         : step(step), begin(begin), end(end) 
+      {  
+      }
+      double getStep()  const { return this->step;  }
+      double getBegin() const { return this->begin; }
+      double getEnd()   const { return this->end;   }
+      
+      /*==========================================================*/
+      std::string toString() { std::stringstream text; text<<*this; return text.str(); }
+      /*==========================================================*/
+      friend inline std::ostream& operator << (std::ostream& os, const UbSchedule& schedule) 
+      {
+         os<<"Schedule[start,end,step]=["<<schedule.begin<<", "<<schedule.end<<", "<<schedule.step<<"]";
+         return os;
+      }
+
+      //------------- implements CAB serialization ----- start
+      virtual void write(UbFileOutput* out)
+      {
+         out->writeDouble( begin );
+         out->writeDouble( end );
+         out->writeDouble( step );
+      }
+      virtual void read(UbFileInput* in)
+      {
+         begin = in->readDouble();
+         end   = in->readDouble();
+         step  = in->readDouble();
+      }
+      //------------- implements boost serialization ----- end
+
+   private:
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & begin; 
+         ar & end; 
+         ar & step;
+      }
+   
+
+   private:
+      double step, begin, end;
+   };
+
+public:
+   UbScheduler() 
+   {
+      this->initVals();
+   }
+   /*==========================================================*/                         
+   UbScheduler(const double& step,const double& begin=0, const double& end=Ub::inf ) 
+   {
+      this->initVals();
+      this->addSchedule(step,begin,end);
+   }
+   /*==========================================================*/
+   UbScheduler(const UbSchedule& schedule) 
+   {
+      this->initVals();
+      this->addSchedule(schedule);
+   }
+   /*==========================================================*/
+   virtual ~UbScheduler() {}
+   /*==========================================================*/
+   inline void addSchedule(const UbSchedule& schedule)
+   {
+      this->addSchedule(schedule.step, schedule.begin, schedule.end);
+   }
+   /*==========================================================*/
+   bool addSchedule(const double& step, const double& begin, double end)
+   {
+      if( UbMath::zero(step) || begin>end )
+      { 
+         std::cerr<<"UbScheduler::addSchedule - invalid Schedule:\n\t"<<UbSchedule(step, begin, end)<<std::endl;
+         return false; 
+      }
+      
+      if( UbMath::less( end, (double)Ub::inf )  )
+      {
+         //es kann vorkommen, dass man mit dem intervall nicht genau auf den letzten wert kommt
+         //(z.B. step=2; start=0; end=9; -> ende wird angepasst)
+         //also wenn end-begin>Ub::inf ist, dann geht es halt nicht.. ein cast in long double half hier nichts
+         double multiplier=0.0;
+         double fractpart =  modf( (end-begin)/step, &multiplier);
+         if( !UbMath::zero(fractpart) )
+         {
+            //tmp-speicherung (fuer cerr)
+            fractpart = end;
+            //neues ende
+            end = begin+multiplier*step;
+            
+            std::cerr<<"Warning: UbScheduler::addSchedule - "
+                      <<"end of schedule was adapted to intervall \n\t"
+                      <<"from "<< UbSchedule(step, begin, fractpart) <<" to "<< UbSchedule(step, begin, end) <<std::endl;
+         }
+      }
+
+      //nu aber:
+      schedules.push_back(UbSchedule(step, begin, end));
+
+      if( end>maxT ) maxT = end;
+
+      double potentialDueTime;
+      if(   calcNextDueTimeForSchedule(schedules.back(), lastUsedT, potentialDueTime)
+         && potentialDueTime < nextDueTime   )
+      {
+         nextDueTime = potentialDueTime;
+      }
+
+      return true;
+   }
+   /*==========================================================*/
+   //returns true if scheduler contains schedules
+   bool   hasSchedules() const { return !schedules.empty(); }
+   /*==========================================================*/
+   //time bei dem das letzte mal isDue(time) true war
+   double getLastDueTime() const { return lastDueTime; }
+   /*==========================================================*/
+   //time bei dem das naechste mal isDue(time) true ergibt
+   double getNextDueTime() const { return nextDueTime; }
+   /*==========================================================*/
+   //maxDueTime (maxTime der Schedules!
+   double getMaxDueTime()  const { return this->maxT; }
+   /*==========================================================*/
+   bool isDue(const double& t)
+   {
+      lastUsedT = t;
+      if( UbMath::greaterEqual(t,nextDueTime) ) 
+      {
+         //groesser maxT is nicht
+         if( UbMath::greater(t,maxT) )  return false;
+         
+         //temp var
+         double actDueTime = nextDueTime;
+
+         //um Suche nach nextDueTime bei "Zukunfts-t" zu optimieren, setzt man die "start"-suchzeit auf "t-1":
+         nextDueTime = t-1; //t-1 deshlab, damit falls z.B. while Schleife nicht durchlaufen wird
+                            //die folgende if Abfrage nicht faelschlicher Weise true ist!
+         while( UbMath::greaterEqual(t,nextDueTime) && !UbMath::equal(nextDueTime, maxT) )
+         {
+            double tmpNextDueTime = maxT, potentialDueTime=-1.0;
+            for(std::size_t i=0; i<schedules.size(); i++)
+            {
+               if(   calcNextDueTimeForSchedule(schedules[i], nextDueTime, potentialDueTime)
+                  && potentialDueTime < tmpNextDueTime                 )
+               {
+                  assert( nextDueTime < potentialDueTime );
+                  tmpNextDueTime = potentialDueTime;
+               }
+            }
+            actDueTime  = nextDueTime;
+            nextDueTime = tmpNextDueTime;
+         } 
+
+         //wenn t = der aktuuellen oder gar schon der nächstmöglichen ist (hierbei wurde
+         //zuvor actDueTime und nextDueTime ggf. angepasst)
+         //Bsp.: nextDuTime war 5, aber für t=400 gilt andere schedule -> Bsp actDue=350 und nextDue 405
+         if(    UbMath::equal(t,actDueTime)    
+             || UbMath::equal(t,nextDueTime) ) 
+         {
+            lastDueTime = t;
+            return true;
+         }
+      }
+      else if( UbMath::lessEqual(t, lastDueTime) ) 
+      {
+         if(UbMath::equal(t, lastDueTime) ) return true; //braucht man, wenn man für dasselbe t isDue(t) aufruft
+         else  
+         {
+            //Fall: Zeit liegt faktisch in der Vergangenheit -> neu initialsisieren
+            double tmpNextDueTime = maxT, potentialDueTime=-1.0;
+            for(size_t i=0; i<schedules.size(); i++)
+            {
+               if(   calcNextDueTimeForSchedule(schedules[i], t-1, potentialDueTime)
+                  && potentialDueTime < tmpNextDueTime                 )
+               {
+                  tmpNextDueTime = potentialDueTime;
+               }
+            }
+            nextDueTime = tmpNextDueTime;
+
+            return UbMath::equal(t, nextDueTime);
+         }
+      }
+
+      return false;
+   }
+   /*==========================================================*/
+   inline double getMinBegin( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getBegin) )->getBegin();
+   }
+   /*==========================================================*/
+   inline double getMaxBegin( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getBegin) )->getBegin();
+   }
+   /*==========================================================*/
+   inline double getMinEnd( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getEnd) )->getEnd();
+   }
+   /*==========================================================*/
+   inline double getMaxEnd( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getEnd) )->getEnd();
+   }
+   /*==========================================================*/
+   inline double getMinStep( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getStep) )->getStep();
+   }
+   /*==========================================================*/
+   inline double getMaxStep( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getStep) )->getStep();
+   }
+   /*==========================================================*/
+   inline std::string toString() const
+   {
+      std::stringstream text;
+      text<<*this;
+      return text.str();
+   }
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const UbScheduler& scheduler) 
+   {
+      os<<"UbScheduler\n";
+      os<<"Schedule |       start       |        end        |     intervall     "<<std::endl;
+      for(std::size_t i=0; i<scheduler.schedules.size(); i++)
+         os<<std::setw(9)<<i<<"|"
+           <<std::setw(19)<<scheduler.schedules[i].getBegin()<<"|"
+           <<std::setw(19)<<scheduler.schedules[i].getEnd()  <<"|"
+           <<std::setw(19)<<scheduler.schedules[i].getStep() <<std::endl;
+      return os;
+   }
+
+   //------------- implements CAB serialization ----- start
+   virtual void write(UbFileOutput* out)
+   {
+      out->writeSize_t( schedules.size() );
+      
+      for(std::size_t i=0; i<schedules.size(); i++)
+         schedules[i].write(out);
+   }
+   virtual void read(UbFileInput* in)
+   {
+      this->initVals();
+
+      std::size_t nofSchedules = in->readSize_t();
+      for(std::size_t i=0; i<nofSchedules; i++)
+      {
+         UbSchedule schedule;
+         schedule.read(in);
+         this->addSchedule(schedule);
+      }
+   }
+   //------------- implements boost serialization ----- end
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & lastUsedT;
+      ar & lastDueTime; 
+      ar & nextDueTime; 
+      ar & maxT; 
+      ar & schedules;
+   }
+
+protected:
+   /*==========================================================*/
+   void initVals()
+   {
+      lastUsedT   = -Ub::inf; 
+      lastDueTime = -Ub::inf;
+      nextDueTime =  Ub::inf;
+      maxT        = -Ub::inf;
+   }
+   /*==========================================================*/
+   // calculates next due time for a schedule 
+   // with  nextDueTime > searchStart
+   bool calcNextDueTimeForSchedule(const UbSchedule& schedule, const double& searchStart, double& nextDueTime )
+   {
+      if     ( UbMath::greater(searchStart, schedule.end  ) ) return false;
+      else if( UbMath::less(   searchStart, schedule.begin) ) nextDueTime = schedule.begin;
+      else                            
+      {
+         nextDueTime = schedule.begin + ((int)((searchStart-schedule.begin)/schedule.step)+1)*schedule.step;
+         if(   UbMath::less(   nextDueTime, searchStart )
+            || UbMath::greater(nextDueTime, schedule.end) ) 
+         {
+            return false;
+         }
+      }
+      return true;
+   }
+
+protected:
+   double lastUsedT;
+   double lastDueTime;
+   double nextDueTime;
+   double maxT;
+   
+   std::vector<UbSchedule> schedules;
+};
+
+typedef UbScheduler::UbSchedule UbSchedule;
+// inline std::ostream& operator<<( std::ostream& os, const UbScheduler& scheduler )
+// {
+//    os<<"UbScheduler\n";
+//    os<<"Schedule |       start       |        end        |     intervall     "<<std::endl;
+//    for(std::size_t i=0; i<scheduler.schedules.size(); i++)
+//       os<<std::setw(9)<<i<<"|"
+//         <<std::setw(19)<<scheduler.schedules[i].getBegin()<<"|"
+//         <<std::setw(19)<<scheduler.schedules[i].getEnd()  <<"|"
+//         <<std::setw(19)<<scheduler.schedules[i].getStep() <<std::endl;
+//    return os;
+// }
+
+#endif //UBSCHEDULER_H
+
+
+
+//int main(int argc, char** argv)            
+//{   
+//	UbScheduler writeSchedule;
+////	writeSchedule.addSchedule(0,2000,100);
+////	writeSchedule.addSchedule(3005,4500,300);
+////	writeSchedule.addSchedule(0,10,1);
+////	writeSchedule.addSchedule(0,100001,100);
+//	writeSchedule.addSchedule(0,2,1);
+//	writeSchedule.addSchedule(0,100001,200);
+//
+//	for(int t = 0; t < 1001; t++)
+//	{
+//		if(writeSchedule.isDue(t))
+//		{
+//			cout<<"due@ "<<t<<endl;
+//		}
+//	}
+//	return 0;
+//}
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbStaticPathMap.cpp b/source/ThirdParty/Library/basics/utilities/UbStaticPathMap.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7772fc5d822487033d53af7caeb49b956ba7a201
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbStaticPathMap.cpp
@@ -0,0 +1,4 @@
+#include <basics/utilities/UbStaticPathMap.h>
+
+UbStaticPathMap::PathMap UbStaticPathMap::pathMap;
+const std::string UbStaticPathMap::GLOBAL = "UbStaticPathMap::GLOBAL";
diff --git a/source/ThirdParty/Library/basics/utilities/UbStaticPathMap.h b/source/ThirdParty/Library/basics/utilities/UbStaticPathMap.h
new file mode 100644
index 0000000000000000000000000000000000000000..20e5b7e8fb294ba8da532aac010d8f85a878fd1c
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbStaticPathMap.h
@@ -0,0 +1,71 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBSTATICPATHMAP_H
+#define UBSTATICPATHMAP_H
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <basics/utilities/UbSystem.h>
+
+/*=========================================================================*/
+/*  UbStaticPathMap                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 12.10.2007
+*/ 
+
+/*
+stores pathnames for pathIDs (e.g. on different processes different paths with same pathID)
+adding an path autom. changes "\" to "/" and removed last "/" if exists
+
+*/
+
+class UbStaticPathMap
+{
+   typedef std::map< std::string, std::string > PathMap;
+public:
+   static const std::string GLOBAL;
+public:
+
+   static std::string addAndMakePath(const std::string& id, const std::string& path)
+   {
+      std::string tmpPath = UbStaticPathMap::addPath(id,path);
+      if( !tmpPath.empty() ) UbSystem::makeDirectory(tmpPath,20);
+      return tmpPath;
+   }
+   static std::string addPath(const std::string& id, const std::string& path)
+   {
+      std::string tmpPath = UbSystem::replaceInString(path,"\\","/");
+      if(tmpPath.rfind("/") == tmpPath.size()-1) tmpPath.resize(tmpPath.size()-1);
+      pathMap[id] = tmpPath;   
+      return tmpPath;
+   }
+   static std::string getPath(const std::string& id)
+   {
+      PathMap::iterator it = pathMap.find(id);
+      if(it == pathMap.end()) return "";
+      return it->second;
+   }
+   static void removePath(const std::string& id)
+   {
+      pathMap.erase(id);
+   }
+
+protected:
+   static PathMap pathMap;
+
+private:
+   UbStaticPathMap() {}
+   UbStaticPathMap(const UbStaticPathMap&) {}
+};
+
+#endif //UBSTATICPATHMAP_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbString.h b/source/ThirdParty/Library/basics/utilities/UbString.h
new file mode 100644
index 0000000000000000000000000000000000000000..516ee76ea90d44d33983fa3a1a531f98211e3dd1
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbString.h
@@ -0,0 +1,24 @@
+//unnoetig: UbSystem::toString() verwenden,... andere Richtung: stringTo... oder am besten boost::lexical_cast
+
+
+//#ifndef UBSTRING_H
+//#define UBSTRING_H
+//#include <string>
+//#include <sstream>
+//
+//using namespace std;
+//
+//class UbString
+//{
+//public:
+//   static void IntToString(int i, string& res)
+//   {
+//      ostringstream temp;
+//      temp << i;
+//      res = temp.str();
+//   }
+//protected:
+//private:
+//};
+//
+//#endif //end UBSTRING_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbStringInputASCII.cpp b/source/ThirdParty/Library/basics/utilities/UbStringInputASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cf104b9fd8c182621b67975e9693f8cd78d91b84
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbStringInputASCII.cpp
@@ -0,0 +1,211 @@
+#include <basics/utilities/UbStringInputASCII.h>
+#include <cstring>
+
+using namespace std;
+
+
+UbStringInputASCII::UbStringInputASCII(string inputString) : UbFileInputASCII("")
+{
+	instream.str(inputString);
+	
+	
+//	this->filename         = filename;
+//   this->commentindicator = 'C'; 
+//   
+//   infile.open(filename.c_str());
+
+}
+/*==========================================================*/
+int UbStringInputASCII::readInteger()				
+{
+	int dummy;
+	instream>>dummy;
+	return dummy;
+}
+/*==========================================================*/
+std::size_t UbStringInputASCII::readSize_t()				
+{
+   std::size_t dummy;
+   instream>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+string UbStringInputASCII::getFileName()				
+{
+	return this->filename;
+}
+
+/*==========================================================*/
+void UbStringInputASCII::skipLine()				
+{
+	string dummy;
+	getline(instream, dummy);
+}
+/*==========================================================*/
+void UbStringInputASCII::readLine()				
+{
+	string dummy;
+	getline(instream, dummy);
+}
+/*==========================================================*/
+string UbStringInputASCII::readStringLine()				
+{
+   string dummy;
+   getline(instream, dummy);
+   return dummy;
+}
+/*==========================================================*/
+string UbStringInputASCII::readLineTill(char stop)				
+{
+	string dummy;
+	getline(instream, dummy, stop);
+	return dummy;
+}
+/*==========================================================*/
+string UbStringInputASCII::parseString()				
+{
+	string dummy;
+	getline(instream, dummy, ' ');
+	return dummy;
+}
+/*==========================================================*/
+double UbStringInputASCII::readDouble()	
+{
+   double dummy;
+   instream>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+float UbStringInputASCII::readFloat()	
+{
+   float dummy;
+   instream>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+char UbStringInputASCII::readChar()	
+{
+   char dummy;
+   instream>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+string UbStringInputASCII::readString()	
+{
+	string dummy;
+	instream>>dummy;
+	return dummy;
+}
+/*==========================================================*/
+bool UbStringInputASCII::containsString(string var)
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+   char line[512];								
+   do
+   { 
+      instream.getline(line,512);
+      if(instream.eof()) return false;
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+   
+   return true;
+}
+/*==========================================================*/
+void UbStringInputASCII::setPosAfterLineWithString(string var)
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+   char line[512];								
+   do
+   { 
+      instream.getline(line,512);
+      if(instream.eof()) UB_THROW( UbException(UB_EXARGS,var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+}
+/*==========================================================*/
+int UbStringInputASCII::readIntegerAfterString(string var)
+// last change [10.3.2004] at [9:46] 
+//suchts in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. timesteps 9
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];								
+
+   do
+   { 
+      instream.getline(line,512);
+      if(instream.eof()) UB_THROW( UbException(UB_EXARGS,var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+
+   strcpy (line, (line+strlen(var.c_str())));	    // zeile um "varname" kuerzen 
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   return(atoi(line));						// Umwandlung in int 					
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46] 
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+double UbStringInputASCII::readDoubleAfterString(string var)	
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];								
+
+   do
+   { 
+      instream.getline(line,512);
+      if(instream.eof()) UB_THROW( UbException(UB_EXARGS,var+" wasn't found in "+this->filename) );
+   }while (/*!strncmp(varname,line,sizeof(varname))==0*/strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+
+
+   strcpy (line, (line+strlen(var.c_str())));	    // zeile um "varname" kuerzen 
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   return (atof(line));			// Umwandlung in double 					
+}
+/*==========================================================*/
+//  [9.9.2002]
+// liefert sring-Wert der hinter dem uebergebenen char feld in der datei instream steht
+// zudem wird der wert in die uebergebene variable value uebertragen (falls man das ergebniss als char benoetig)
+string UbStringInputASCII::readStringAfterString(string var)	
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];								
+   //string line_copy[512];
+
+   do{ 
+      instream.getline(line,512);
+      if(instream.eof()) UB_THROW( UbException(UB_EXARGS,var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+
+   strcpy (line, (line+strlen(var.c_str())));										// zeile um "varname" kuerzen 
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   char *p;
+   p=strtok(line," "); //schneidet alles "ab und inklusive space " nach namen ab
+   p=strtok(line,"\t");//schneidet alles "ab und inklusive tab   " nach namen ab
+
+   return (string)p;			// Umwandlung in string					
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46] 
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+bool UbStringInputASCII::readBoolAfterString(string var)	
+{
+   if(this->readStringAfterString(var.c_str())      == "true" ) return true;
+   else if(this->readStringAfterString(var.c_str()) == "false") return false;
+   else UB_THROW( UbException(UB_EXARGS,var+" is not equal to 'true' or 'false' in "+this->filename) );
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46] 
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+bool UbStringInputASCII::readBool()	
+{
+   string tmp = this->readString();
+   if(     tmp == "true" ) return true;
+   else if(tmp == "false") return false;
+   else UB_THROW( UbException(UB_EXARGS,"expression is not equal to 'true' or 'false' in "+this->filename) );
+}
diff --git a/source/ThirdParty/Library/basics/utilities/UbStringInputASCII.h b/source/ThirdParty/Library/basics/utilities/UbStringInputASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..787048e071daf501e988d2baf9ebd861f04bf6cf
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbStringInputASCII.h
@@ -0,0 +1,55 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBSTRINGINPUTASCII_H
+#define UBSTRINGINPUTASCII_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+
+#include <basics/utilities/UbFileInputASCII.h>
+
+class UbStringInputASCII : public UbFileInputASCII
+{                               
+public:
+	UbStringInputASCII(std::string inputString);
+	
+	std::string getFileName();				
+	void	      skipLine();					   // Springt zur naechsten Zeile
+
+   void        readLine();		 
+   std::string readStringLine();				
+   std::size_t readSize_t();				
+   int		   readInteger();				   // Liest einen Int-Wert ein
+   double	   readDouble();				   // Liest einen double-Wert ein
+	float 	   readFloat();				   // Liest einen float-Wert ein
+	bool  	   readBool();				      // Liest einen bool-Wert ein
+   char        readChar();                // Liest einen char-Wert ein
+   std::string	readString();				   // Liest ein Wort ein
+	std::string	readLineTill(char stop);	// Liest gesamte Zeile ein bis zu einem bestimmten Zeichen
+	std::string	parseString();	
+
+   bool        containsString(std::string var);
+   void        setPosAfterLineWithString(std::string var);
+   int		   readIntegerAfterString(std::string var);
+   double	   readDoubleAfterString(std::string var);
+   bool        readBoolAfterString(std::string var);
+   std::string readStringAfterString(std::string var);
+
+   FILETYPE getFileType() { return ASCII; }
+
+private:
+	std::istringstream instream;
+};
+
+
+#endif
+
+
diff --git a/source/ThirdParty/Library/basics/utilities/UbSystem.h b/source/ThirdParty/Library/basics/utilities/UbSystem.h
new file mode 100644
index 0000000000000000000000000000000000000000..4178ff2c02342837c0638c8fdac4406caab30d7e
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbSystem.h
@@ -0,0 +1,534 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBSYSTEM_H
+#define UBSYSTEM_H
+
+#if defined(_WIN32) || defined(_WIN64)
+   #define UBSYSTEM_WINDOWS
+   #include <process.h>
+   #include <io.h>
+   #include <direct.h>
+   //#ifndef _WINSOCK2API_  //ansonsten gibt es mecker bei #include "Windows.h" und ::Sleep()
+   //   #define _WINSOCK2API_
+   //   #include<WinSock2.h> 
+   //#endif
+  #include <windows.h>
+  //#include <Windows.h>
+  //#include <tchar.h>
+#elif defined(__APPLE__)
+   #define UBSYSTEM_APPLE
+   #include "dirent.h"
+   #include "sys/stat.h"
+   #include <sys/syscall.h>
+   #include <sys/stat.h>
+#elif (defined(__amd64) || defined(__amd64__) || defined(__unix__) || defined(__CYGWIN__)) && !defined(__AIX__) 
+   #define UBSYSTEM_LINUX
+   #include "dirent.h"
+   #include "sys/stat.h"
+   #include <sys/syscall.h>
+   #include <sys/stat.h>
+   #include <unistd.h>
+#elif defined(__AIX__)
+   #define UBSYSTEM_AIX
+   #include "dirent.h"
+   #include <unistd.h>
+   #include <sys/stat.h>
+   #include <sys/types.h>
+#else
+   #error "UbSystem::UnknownMachine"
+#endif
+
+
+
+#if defined(min) || defined(max) //daruch kann man sich spaeter #undef min; #undef max erparen
+#   error add NOMINMAX to preprocessor defines
+#endif
+
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <algorithm>
+#include <typeinfo>
+#include <cctype> //for toupper
+#include <ctime>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbLogger.h>
+
+#if defined(CAB_BOOST)
+#include <boost/thread.hpp>
+#endif // CAB_BOOST
+
+//DEFINE TO STRING
+//e.g. #define FOO hallo
+//     -> QUOTEME(FOO) == "hallo"
+#define _QUOTEME(x) #x
+#define QUOTEME(x) _QUOTEME(x)
+
+//allg.:
+//const int * C1        -> C1 is variable pointer to a constant integer
+//int const * C2        -> C2 is variable pointer to a constant integer (same as above)
+//int * const C3        -> C3 is constant pointer to a variable integer
+//int const * const C4  -> C4 is constant pointer to a constant integer
+
+//////////////////////////////////////////////////////////////////////////
+//UbSystem
+//////////////////////////////////////////////////////////////////////////
+namespace UbSystem
+{
+   template<bool> struct ub_static_assert;     //deklaration (ub_xxx da static_assert in C++0x ein keyword werden wird)
+   template<> struct ub_static_assert<true>{}; //deklaration + definition der spezialisierung fuer "true"
+                                               //ub_static_assert<false> fuehrt zu compiler fehler, da dafuer
+                                               //keine implementierung vorhanden!  //UB_STATIC_ASSERT(false)
+
+   /*==========================================================*/
+   inline void sleepMs(const unsigned int& msec)
+   {
+      #if defined UBSYSTEM_WINDOWS
+         ::Sleep(  (msec==0) ? 1 : msec );  // +1 here causes a context switch if SleepMSec(0) is called
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         ::usleep(1000*msec);
+      #else
+         #error "UbSystem::sleepMSec - UnknownMachine"
+      #endif
+   }
+   /*==========================================================*/
+   inline void sleepS(const unsigned int& sec)
+   {
+      #if defined UBSYSTEM_WINDOWS
+         ::Sleep( (sec==0) ? 1 : sec*1000 );  // +1 here causes a context switch if sleepS(0) is called
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         ::sleep(sec);
+      #else
+         #error "UbSystem::sleepS - UnknownMachine"
+      #endif
+   }
+   /*==========================================================*/
+   //checks if the bits of bitmask are set in value
+   template<typename T>
+   inline bool bitCheck(const T& value, const T& bitmask)
+   {
+      return  ( (value & bitmask) == bitmask);
+   }
+   /*==========================================================*/
+   //checks if the bits of bitmask are set in value
+   template<typename T>
+   inline void setBit(T& value, const T& bitmask)
+   {
+      value |= bitmask;
+   }
+   /*==========================================================*/
+   template<typename T>
+   inline void unsetBit(T& value, const T& bitmask)
+   {
+      value &= ~bitmask;
+   }
+   /*==========================================================*/
+   //returns bitmask as string e.g. 0001 0100 1101
+   template<typename T>
+   inline std::string getBitString(const T& value)
+   {
+      std::stringstream text;
+      for(int i=sizeof(value)*8-1/*8 bits per byte*/; i>=0; i--)
+      {
+         text<<(char) ( ((value>>i) & 1) + '0');
+         if(i%4 == 0 && i>0) text<<' ';
+      }
+      return text.str();
+   }
+   /*==========================================================*/
+   //converts string to type T
+   // usage: int x = stringTo<int>("123");
+   template<typename T>
+   inline T stringTo(const std::string& s)
+   {
+     std::istringstream iss(s);
+     T x;
+     iss >> x;
+     if(!iss)
+        UB_THROW( UbException(UB_EXARGS," cannot convert \""+s+"\" to type <"+static_cast<std::string>(typeid(x).name())+">") );
+
+     return x;
+   }
+   /*==========================================================*/
+   // usage: string s = toString(x);
+   template<typename T>
+   inline std::string toString(const T& x, int precision=15)
+   {
+     std::ostringstream oss;
+     oss<<std::setprecision(precision);
+     oss<<x;
+     return oss.str();
+   }
+   /*==========================================================*/
+   //e.g. str="iHcsnW" -> "IHCSNW"
+   inline std::string toUpperString(const std::string& str)
+   {
+      std::string tmp(str);
+      std::transform(tmp.begin(),tmp.end(),tmp.begin(), static_cast<int (*)(int)>(std::toupper));
+
+      return tmp;
+   }
+   /*==========================================================*/
+   //e.g. str="iHcsnW" -> "ihcsnw"
+   inline std::string toLowerString(const std::string& str)
+   {
+      std::string tmp(str);
+      std::transform(tmp.begin(),tmp.end(),tmp.begin(), static_cast<int (*)(int)>(std::tolower));
+
+      return tmp;
+   }
+   /*==========================================================*/
+   // usage: std::string s = replaceInString(str,"\\","/");
+   //        std::string s = replaceInString(str,"ich","du");
+   static std::string replaceInString(std::string original, const std::string& replace, const std::string& replaceWith )
+   {
+      size_t pos=0;
+      while( (pos=original.find(replace,pos))!=std::string::npos )
+      {
+         original.replace(pos,replace.size(),replaceWith);
+         pos+=replaceWith.size();
+      }
+      return original;
+   }
+   /*==========================================================*/
+   //returns content of an enviroment variable
+   inline std::string getEnv(const std::string& var)
+   {
+      char* str = getenv( var.c_str());
+      if(  str == NULL  ) 
+      {
+         return std::string("");
+      }
+      
+      return static_cast<std::string>( str );
+   }
+   /*==========================================================*/
+   inline bool isDirectory(const std::string& dir, const unsigned& attemptions = 3)
+   {
+      if( dir.empty() ) 
+         UB_THROW( UbException(UB_EXARGS,"dir is empty") );
+      
+      std::string path = UbSystem::replaceInString(dir,"\\","/");
+
+      #if defined UBSYSTEM_WINDOWS
+         #ifndef _UNICODE 
+            if( _access(path.c_str(), 0  ) == -1 ) return false;
+         #else
+            if( _waccess(path.c_str(), 0 ) == -1 ) return false;
+         #endif
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         struct stat stFileInfo;
+         if( stat(path.c_str(),&stFileInfo) != 0) 
+         {
+            return false;
+         } 
+      #endif
+      
+      return true;
+   }
+   /*==========================================================*/
+   // usage:  makeDirectory("c:/temp");
+   //         makeDirectory("c:/temp/");
+   // return: true  -> successful
+   //         false -> failed
+   #if defined(CAB_BOOST) 
+      static boost::mutex mtx_makeDirectory;
+   #endif
+   inline bool makeDirectory(const std::string& dir, const unsigned& attemptions = 3)
+   {
+      UBLOG(logDEBUG5,"UbSystem::makeDirectory - start, dir="<<dir<<" #attemptions="<<attemptions);
+
+      if( dir.empty() ) UB_THROW( UbException(UB_EXARGS,"dir is empty") );
+      std::string path = UbSystem::replaceInString(dir,"\\","/");
+
+      bool dirCreated = true;
+      #if defined UBSYSTEM_WINDOWS
+         if(path[path.size()-1] != '/') path+="/";
+         size_t  pos = 0;
+         while( ( pos=path.find("/",pos+1) ) != std::string::npos )
+         {
+            std::string tmpdir = path.substr(0,pos);
+            #if defined(CAB_BOOST) 
+            boost::mutex::scoped_lock lock(mtx_makeDirectory);
+            #endif
+            if( 
+                #ifndef _UNICODE 
+                 _access(tmpdir.c_str(), 0 ) == -1 && _mkdir(tmpdir.c_str() ) == -1
+                #else
+                 _waccess(tmpdir.c_str(), 0) == -1 && _wmkdir(tmpdir.c_str()) == -1
+                #endif
+               )
+               {
+                  UBLOG(logDEBUG5,"UbSystem::makeDirectory-  dir=\""<<tmpdir<<"\" doesn't exit or makedir failed");
+                  dirCreated = false;
+                  break;
+               }
+         }
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         std::string command = "mkdir -p \""+path+"\"";
+         {
+            #if defined(CAB_BOOST) 
+               boost::mutex::scoped_lock lock(mtx_makeDirectory);
+            #endif
+            if(system(command.c_str())!=0)
+            {
+               UBLOG(logDEBUG5,"UbSystem::makeDirectory-  dir=\""<<path<<"\" doesn't exit or makedir failed");
+               dirCreated = false;
+            }
+         }
+      #else
+         #error "UbSystem::makeDirectory - UnknownMachine"
+      #endif
+
+      if(!dirCreated && attemptions > 1)
+      {
+         UBLOG(logDEBUG5,"UbSystem::makeDirectory - internal call of UbSystem::makeDirectory");
+         UbSystem::sleepMs(500);
+         dirCreated = UbSystem::makeDirectory(path, attemptions-1);
+      }
+      
+      UBLOG(logDEBUG5,"UbSystem::makeDirectory - end (success="<<dirCreated<<", attemptions = "<<attemptions<<")");
+      return dirCreated;
+   }
+   /*==========================================================*/
+#if defined(CAB_BOOST) 
+   static boost::mutex mtx_removeDirectory;
+#endif
+   inline int removeDirectory(const std::string& dir)
+   {
+      #if defined(CAB_BOOST) 
+         boost::mutex::scoped_lock lock(mtx_removeDirectory);
+      #endif
+      std::string command = "rmdir \""+dir+"\"";
+      return std::system(command.c_str());
+   }
+   /*==========================================================*/
+   // usage  : getPathFromString("c:/temp/foo.txt");
+   //returns: "c:/temp"
+   // usage  : getPathFromString("c:\\temp\\foo.txt");
+   //returns: "c:/temp"
+   // usage  : getPathFromString("foo.txt");
+   // returns: ""
+   inline std::string getPathFromString(const std::string& fileStringWithPath)
+   {
+      std::string tmp = UbSystem::replaceInString(fileStringWithPath,"\\","/");
+      std::size_t last = tmp.rfind("/");
+      if(last!=std::string::npos) tmp.resize(last);
+      else                        tmp = "";
+      return tmp;
+   }
+   /*==========================================================*/
+   // usage  : getFilenameFromString("c:/temp/foo.txt");
+   // returns: "foo.txt"
+   // usage  : getFilenameFromString("c:/temp/foo.txt",false);
+   // returns: "foo"
+   // usage  : getFilenameFromString("c:/temp/");
+   // returns: ""
+   inline std::string getFilenameFromString(const std::string& fileStringWithPath, bool withExtension = true)
+   {
+      std::string tmp = UbSystem::replaceInString(fileStringWithPath,"\\","/");
+      
+      //remove path
+      std::size_t last = tmp.rfind("/");
+      if(last!=std::string::npos && (last+1)<tmp.size()) tmp.erase(0,last+1);
+      
+      //remove extension
+      if(!withExtension)
+      {
+         last = tmp.rfind(".");
+         if(last!=std::string::npos) tmp.erase(last);
+      }
+
+      return tmp;
+   }
+   /*==========================================================*/
+   inline int getProcessID()
+   {
+      #if defined UBSYSTEM_WINDOWS
+         return _getpid();
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         return getpid();
+      #else
+         #error "int UbSystem::getProcessID() - UnknownMachine"
+      #endif
+   }
+   /*==========================================================*/
+   inline unsigned long getCurrentThreadID()
+   {
+      #if defined UBSYSTEM_WINDOWS
+         return (unsigned long)GetCurrentThreadId();
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE)
+         return (unsigned long)syscall(SYS_gettid);
+      #elif defined(UBSYSTEM_AIX)
+         return (unsigned long) getpid(); //WORKAROUND for IBM (for get thread id is another function necessary) 
+      #else
+         #error "unsigned long UbSystem::getCurrentThreadID() - UnknownMachine"
+      #endif
+   }
+   /*==========================================================*/
+   inline bool isBigEndian()
+   {
+      short word = 0x4321;
+      if((*(char*)& word) != 0x21 ) return true;
+      else                           return false;
+   }
+   /*==========================================================*/
+   inline bool isLittleEndian()
+   {
+      return !isBigEndian();
+   }
+   /*==========================================================*/
+   inline std::string getTimeStamp()
+   {
+      time_t t = time(NULL);
+      tm* localTime = localtime(&t); 	
+      
+      std::stringstream tmp;
+      tmp.fill('0');
+      
+      tmp << localTime->tm_year+1900 
+          << "." << std::setw(2) <<localTime->tm_mon+1
+          << "." << std::setw(2) << localTime->tm_mday 
+          << "@" << std::setw(2) << localTime->tm_hour  
+          << "." << std::setw(2) << localTime->tm_min   
+          << "." << std::setw(2) << localTime->tm_sec  ;
+
+      return tmp.str();
+   }
+   /*==========================================================*/
+   //swap Byte Order
+   //usage: int test = 8;
+   //       swapByteOrder((unsigned char*)& test, sizeof(int))
+   //#define ByteSwap5(x) ByteSwap((unsigned char *) &x,sizeof(x))
+   inline void swapByteOrder(unsigned char* toSwap, int length)
+   {
+      register int i = 0;
+      register int j = length-1;
+      while(i<j)
+      {
+         std::swap(toSwap[i], toSwap[j]);
+         i++, j--;
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //get host name
+   inline std::string getMachineName()
+   {
+      char Name[150];
+      int i = 0;
+
+#ifdef UBSYSTEM_WINDOWS
+      TCHAR infoBuf[150];
+      DWORD bufCharCount = 150;
+      memset(Name, 0, 150);
+      if (GetComputerName(infoBuf, &bufCharCount))
+      {
+         for (i = 0; i<150; i++)
+         {
+            Name[i] = infoBuf[i];
+         }
+      }
+      else
+      {
+         strcpy(Name, "Unknown_Host_Name");
+      }
+#else
+      memset(Name, 0, 150);
+      gethostname(Name, 150);
+#endif
+      return std::string(Name);
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   // generic IfThenElse - start
+   //////////////////////////////////////////////////////////////////////////
+   // primary template: yield second or third argument depending on first argument
+   template<bool C, typename Ta, typename Tb>
+   class IfThenElse;
+
+   // partial specialization: true yields second argument
+   template<typename Ta, typename Tb>
+   class IfThenElse<true, Ta, Tb> {
+   public:
+      typedef Ta ResultT;
+   };
+
+   // partial specialization: false yields third argument
+   template<typename Ta, typename Tb>
+   class IfThenElse<false, Ta, Tb> {
+   public:
+      typedef Tb ResultT;
+   };
+   //////////////////////////////////////////////////////////////////////////
+   // generic IfThenElse - end
+   //////////////////////////////////////////////////////////////////////////
+
+   //////////////////////////////////////////////////////////////////////////
+   //help struct for overloading methods in template classes for specific types
+   //////////////////////////////////////////////////////////////////////////
+   template< typename T>
+   struct type2type
+   {
+      typedef T type;
+   };
+
+
+   //////////////////////////////////////////////////////////////////////////
+   // pair selector
+   //////////////////////////////////////////////////////////////////////////
+   template <typename Pair>
+   struct select1st
+   {
+      typedef Pair argument_type ;
+      typedef typename Pair::first_type result_type ;
+
+      const result_type&  operator()(const argument_type &p) const
+      {
+         return p.first ;
+      }
+   };
+
+   template <typename Pair>
+   struct select2nd
+   {
+      typedef Pair argument_type ;
+      typedef typename Pair::second_type result_type ;
+
+      const result_type& operator()(const argument_type &p) const
+      {
+         return p.second ;
+      }
+   };
+
+};
+
+#define UB_STATIC_ASSERT(expr) static_cast<void>(sizeof( UbSystem::ub_static_assert<expr> ));
+//zum ueberpruefen von STATISCHEN ausdruecken waehrend der compile-zeit
+//--> Ausdruecke muessen schon ZUR compilerzeit auswertbar sein !!!
+//Anwendung z.B. zur Ueberpruefung von Funktionalitaeten, wie z.B. bei UbMath::getNegativeInfinity<double>();
+//
+//Grund fuer macro ist einfach, dass es besser anzuwenden ist in der praxis!
+//ansonsten würde es so aussehen:
+//     UbSystem::ub_static_assert< aaa == 1 > test();
+//    da ist  UB_STATIC_ASSERT(aaa == 1); schoener
+//
+//um das zu vermeiden machtman hier diesen static_cast<void>(sizeof(...) )
+//Code-Snippet:
+// struct Test { const static bool m_const_bool = true; bool m_bool; };
+// int main() {
+//  UB_STATIC_ASSERT( Test::m_const_bool == true );
+//  --> okay, assert bestanden
+//  UB_STATIC_ASSERT( Test::m_const_bool == false); //:
+//  --> assert nicht bestanden z.B. error C2027: use of undefined type 'UbSystem::ub_static_assert<__formal> with __formal = false --> funzt nicht. fehler im code
+//  UB_STATIC_ASSERT( Test::m_bool == true );
+//  --> nicht erlaubt, da m_bool nicht statisch und nicht const ist.
+//}
+
+#endif //UBSYSTEM_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbTableModel.cpp b/source/ThirdParty/Library/basics/utilities/UbTableModel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eca533129a77a21e3515939b72f848e8f611c9d4
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbTableModel.cpp
@@ -0,0 +1,20 @@
+#include <basics/utilities/UbTableModel.h>
+
+UbTableModel::UbTableModel()
+{
+}
+
+UbTableModel::~UbTableModel()
+{
+	//this->notifyObserversObjectWillBeDeleted();
+}
+
+//void UbTableModel::objectChanged(UbObservable* changedObject)
+//{
+//	this->notifyObserversObjectChanged();	
+//}
+//
+//void UbTableModel::objectWillBeDeleted(UbObservable* objectForDeletion)
+//{
+//	objectForDeletion->removeObserver(this);
+//}
diff --git a/source/ThirdParty/Library/basics/utilities/UbTableModel.h b/source/ThirdParty/Library/basics/utilities/UbTableModel.h
new file mode 100644
index 0000000000000000000000000000000000000000..4a12d63b3881238daeb261b35b599ccbb7b64890
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbTableModel.h
@@ -0,0 +1,37 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBTABLEMODEL_H
+#define UBTABLEMODEL_H
+
+#include <iostream>
+
+class UbTableModel 
+{
+public:
+   const static int COL_TYPE_STRING  = 1;
+   const static int COL_TYPE_BOOL    = 2;
+   const static int COL_TYPE_INTEGER = 3;
+   const static int COL_TYPE_DOUBLE  = 4;
+
+	UbTableModel();
+	virtual ~UbTableModel();
+
+	//////////////////////////////////////////////////////////////////////////
+	//void objectChanged(UbObservable*);
+	//void objectWillBeDeleted(UbObservable*);
+
+	virtual int getColumnNumber() = 0;
+	virtual int getRowNumber()    = 0;
+   virtual std::string getColumnLabel(int column) = 0;
+	virtual int getColumnType(int column) = 0;
+	virtual std::string getStringValue(int row, int col) = 0;
+   virtual void setStringValue(int row, int col, std::string str) = 0;
+	virtual int getSelectedRowIndex() = 0;
+	//virtual bool GetBoolValue(int row, int col) = 0;
+};
+
+#endif //UBTABLEMODEL_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbTiming.h b/source/ThirdParty/Library/basics/utilities/UbTiming.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f768fea3d98129f7359f1576c46032ea42cf763
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbTiming.h
@@ -0,0 +1,429 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBTIMING_H
+#define UBTIMING_H
+
+#include <string>
+#include <limits>
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <ctime>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#ifdef VF_MPI
+   #include <mpi.h>
+   #include <basics/parallel/PbMpi.h>
+#endif //VF_MPI
+
+/*=========================================================================*/
+//  UbTiming - Time Measuring                                              
+//                                                                         
+//
+//
+//This Class provides the base for ...
+//<BR><BR>
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@author <A HREF="mailto:geller@cab.bau.tu-bs.de">S. Geller</A>
+//@version 1.1 - 14.02.06
+// 
+
+class UbTiming
+{
+public:
+	UbTiming()
+   {
+      this->duration		= 0.0;
+      this->deltaT		= 0.0;
+      this->startTime	= 0;
+      this->name        = "noname";
+   }
+   /*==========================================================*/
+   UbTiming(const std::string& name)
+   {
+      this->duration		= 0.0;
+      this->deltaT		= 0.0;
+      this->startTime	= 0;
+      this->name        = name;
+   }
+   /*==========================================================*/
+   virtual ~UbTiming() {}  
+   /*==========================================================*/
+   virtual void initTiming()
+   {
+      this->duration = 0.0;	
+   }
+   /*==========================================================*/
+   virtual void startTiming()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->startTime = PbMpi::Wtime();
+      #else
+         this->startTime = (double)clock();	
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   virtual void initAndStartTiming()
+   {
+      this->initTiming();
+      this->startTiming();
+   }
+   /*==========================================================*/
+   virtual void endTiming()
+   {
+      this->stopTiming();
+   }
+   /*==========================================================*/
+   virtual void stopTiming()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+            this->deltaT   = PbMpi::Wtime()-this->startTime;
+      #else
+         this->deltaT   = ((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+
+      this->duration += this->deltaT;
+   }
+   /*==========================================================*/
+   virtual double getDuration() const
+   {
+      return this->duration;
+   }
+   /*==========================================================*/
+   virtual void setName(const std::string& name)
+   {
+      this->name = name;
+   }
+   /*==========================================================*/
+   virtual std::string getName() const
+   { 
+      return this->name; 
+   }
+   /*==========================================================*/
+   void start()
+   {
+      this->duration = 0.0;
+
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->startTime = PbMpi::Wtime();
+      #else
+         this->startTime = (double)clock();
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   void pause()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->duration += PbMpi::Wtime()-this->startTime;
+      #else
+         this->duration +=((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   void unpause()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->startTime   = PbMpi::Wtime();
+      #else
+         this->startTime = (double)clock();
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   void stop()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->duration += PbMpi::Wtime()-this->startTime;
+      #else
+         this->duration +=((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   double getTicks() const            
+   { 
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         return PbMpi::Wtick();
+      #else
+         return double(1.0)/double(CLOCKS_PER_SEC);
+      #endif  //VF_MPI 
+   }
+
+protected:
+   std::string name;
+
+   double startTime;
+   double duration;
+	double deltaT;
+};
+
+/*=========================================================================*/
+//  UbTimer - Time Measuring                                              
+//                                                                         
+//
+//
+//This Class provides the base for ...
+//<BR><BR>
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@version 1.0 - 16.08.2007
+// 
+#include <basics/utilities/UbSystem.h> //for definitons of system/OS type
+
+#ifdef UBSYSTEM_APPLE   //Apple hack
+   #include <mach/mach_time.h>  
+   #include <time.h>  
+   #include <stdio.h> 
+   inline void mach_absolute_difference(const uint64_t& end, const uint64_t& start, struct timespec *tp) 
+   {  
+         uint64_t difference = end - start;  
+         static mach_timebase_info_data_t info = {0,0};  
+   
+         if (info.denom == 0)  
+                 mach_timebase_info(&info);  
+   
+         uint64_t elapsednano = difference * (info.numer / info.denom);  
+   
+         tp->tv_sec = elapsednano * 1e-9;  
+         tp->tv_nsec = elapsednano - (tp->tv_sec * 1e9);  
+   } 
+#elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
+   #include <ctime>
+   #include <unistd.h> // for sysconf
+   #include <pthread.h>
+#endif
+
+//example:
+//t=0  start 
+//t=1 
+//t=2  stop  -> return 2; getLapTime=2; getTotalTime 2; getLapTimes:  2
+//t=3 
+//t=4 
+//t=5  stop  -> return 3; getLapTime=3; getTotalTime 5; getLapTimes:  2,3
+//t=6  stop  -> return 1; getLapTime=1; getTotalTime 6; getLapTimes:  2,3,1
+//t=7  
+//t=8  start ->no consideration of time 7 and 8 
+//t=9  
+//t=10 stop  -> return 2; getLapTime=2; getTotalTime 8; getLapTimes:  2,3,1,2
+//t=11 resetAndStart timer wird zurueckgestellt und neu gestaret
+//t=12
+//t=13 
+//t=14 stop  -> return 3; getLapTime=3; getTotalTime 3; getLapTimes:  3
+
+class UbTimer
+{
+public:
+   UbTimer(const bool& storeLapTimes = false) 
+      :  name("unamed"), isMeasuring(false), storeLapTimes(storeLapTimes)
+       , startTime(0.0), totalTime(0.0), lapTime(0.0)
+   {
+
+   }
+   /*==========================================================*/
+   UbTimer(const std::string& name, const bool& storeLapTimes = false) 
+      :  name(name), isMeasuring(false), storeLapTimes(storeLapTimes)
+       , startTime(0.0), totalTime(0.0), lapTime(0.0)
+   {
+
+   }
+   /*==========================================================*/
+   virtual ~UbTimer() {}  
+   /*==========================================================*/
+   double              getLapTime() const               { return this->lapTime;  }
+   std::vector<double> getLapTimes() const              { return this->lapTimes; }
+   void                setName(const std::string& name) { this->name = name;     }
+   std::string         getName() const                  { return this->name;     }
+   bool                isRunning() const                { return isMeasuring;    }
+   bool                isStoringLapTimes() const        { return storeLapTimes;  }
+   /*==========================================================*/
+   void setStoreLapTimes(const bool& storeLapTimes) { this->storeLapTimes = storeLapTimes; }
+   /*==========================================================*/
+   void start()
+   {
+      this->isMeasuring = true;
+
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+          this->startTime = PbMpi::Wtime();
+      #elif defined(UBSYSTEM_APPLE)
+    	 this->startTime = mach_absolute_time();  
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
+         timespec tp;
+         clock_gettime(CLOCK_REALTIME,&tp);
+         this->startTime = (double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec);
+      #else
+         this->startTime = (double)clock();
+      #endif //VF_MPI
+   }
+   /*==========================================================*/
+   void resetAndStart() { this->reset(); this->start(); }
+   /*==========================================================*/
+   //stop: - stops the calculation and returns the time elapsed since last start/stop
+   //      - timing continues
+   double stop()
+   {
+      //if start() was never activated before:
+      if(!isMeasuring) return 0.0; 
+      
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         double actTime = PbMpi::Wtime();
+         this->lapTime  = actTime-this->startTime;
+      #elif defined(UBSYSTEM_APPLE)
+    	 double actTime = mach_absolute_time();  
+         timespec tp;  
+         mach_absolute_difference(actTime, this->startTime, &tp);
+         this->lapTime  =  tp.tv_sec + tp.tv_nsec*1e-9;
+	  #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
+         timespec tp;
+         clock_gettime(CLOCK_REALTIME,&tp);
+         double actTime = (double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec);
+         this->lapTime  = (actTime-this->startTime)*1.0e-9;
+      #else
+         double actTime = (double)clock();
+         this->lapTime  = (actTime-this->startTime)/(double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+      
+      this->startTime  = actTime;
+      this->totalTime += this->lapTime;
+      if(storeLapTimes) lapTimes.push_back(this->lapTime);
+
+      return lapTime;
+   }
+   /*==========================================================*/
+   void reset()
+   {
+      this->isMeasuring = false;
+      
+      this->startTime   = 0.0;
+      this->totalTime   = 0.0;
+      this->lapTime     = 0.0;
+
+      lapTimes.resize(0);
+   }
+   /*==========================================================*/
+   double getCurrentLapTime() const
+   {
+     //if start() was never activated before:
+      if(!isMeasuring) return 0.0; 
+      
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         return PbMpi::Wtime() - this->startTime;
+      #elif defined(UBSYSTEM_APPLE)
+         timespec tp;  
+         mach_absolute_difference(mach_absolute_time(), this->startTime, &tp);
+         return tp.tv_sec + tp.tv_nsec*1e-9;
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
+         timespec tp;
+         clock_gettime(CLOCK_REALTIME,&tp);
+         return ((double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec) - this->startTime)*1.0e-9;
+      #else
+         return ( (double)clock() - this->startTime ) / (double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+      
+   }
+   /*==========================================================*/
+   double getTotalTime() const
+   {
+      return this->totalTime;
+   }
+   /*==========================================================*/
+   std::string toString()
+   {
+      std::stringstream text;
+      text<<*this;
+      return text.str();
+   }
+
+   //ueberladene Operatoren
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const UbTimer& timer) 
+   {
+       os<<"UbTimer[totalTime="<<timer.totalTime<<"sec, lapTimes(";
+       for(std::size_t i=0; i<timer.lapTimes.size(); i++) os<<timer.lapTimes[i]<<",";
+       os<<")]";
+       return os;
+   }
+
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      ar & name;
+      ar & isMeasuring;
+      ar & startTime;
+      ar & totalTime;
+      ar & lapTime;
+      ar & lapTimes;
+      ar & storeLapTimes;
+   }
+#endif //CAB_RCF
+
+protected:
+   std::string name;
+   bool        isMeasuring;
+   bool        storeLapTimes;
+
+   double      startTime;
+   double      totalTime;
+   double      lapTime;
+   
+   std::vector<double> lapTimes;
+};
+
+
+/*=========================================================================*/
+//  UbProgressTimer - Time Measuring                                              
+//                                                                         
+//
+//
+//UbProressTimer misst die Zeit von seiner Instantiierung bis zur Zerstörung
+//und gib die verstrichene Zeit auf "os" in [s] aus
+//example:
+// {
+//    UbProgressTimer timer;
+//    UbSystem::sleepS(10);
+// } //--> 10s
+//<BR><BR>
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@version 1.0 - 10.03.2008
+// 
+class UbProgressTimer : public UbTimer
+{
+private:
+	UbProgressTimer(const UbProgressTimer& rhs);
+public:
+  explicit UbProgressTimer( std::ostream & os = std::cout )
+     : UbTimer(),os(os) 
+  {
+  	  this->start();
+  }
+  /*==========================================================*/
+  ~UbProgressTimer()
+  {
+  //  A) Throwing an exception from a destructor is a Bad Thing.
+  //  B) The progress_timer destructor does output which may throw.
+  //  C) A progress_timer is usually not critical to the application.
+  //  Therefore, wrap the I/O in a try block, catch and ignore all exceptions.
+    try
+    {
+      // use istream instead of ios_base to workaround GNU problem (Greg Chicares)
+      std::istream::fmtflags old_flags = os.setf( std::istream::fixed,
+                                                  std::istream::floatfield );
+      std::streamsize old_prec = os.precision( 2 );
+      os << stop() << " s" << std::endl;
+      os.flags( old_flags );
+      os.precision( old_prec );
+    }
+    catch (...) {} // eat any exceptions
+  } 
+
+private:
+  std::ostream & os;
+};
+
+
+#endif //UBTIMING_H
diff --git a/source/ThirdParty/Library/basics/utilities/UbTuple.h b/source/ThirdParty/Library/basics/utilities/UbTuple.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb711c9dc9c3b91922a1252f78b1f00208d5ccc7
--- /dev/null
+++ b/source/ThirdParty/Library/basics/utilities/UbTuple.h
@@ -0,0 +1,1138 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBTUPLE_H
+#define UBTUPLE_H
+
+#include <iostream>
+#include <string>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+/*=========================================================================*/
+/*  UbTuple                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.10.06
+*/ 
+
+/*
+usage: ...
+////Advanced UbTuple
+//Bsp:
+//// create and use tuple with only one field
+//UbTuple<int,int,int,int,int> t1;
+//val<1>(t1) += 42;
+//std::cout << t1.v1() << std::endl;
+
+//// create and use duo
+//UbTuple<bool,int> t2;
+//std::cout << val<1>(t2) << ", ";
+//std::cout << t2.v1() << std::endl;
+
+//// create and use triple
+//UbTuple<bool,int,double> t3;
+//val<1>(t3) = true;  // new values via: val< pos >(triple) = ...
+//val<2>(t3) = 42;
+//val<3>(t3) = 0.2;
+//t3 = makeUbTuple(false, 23, 13.13);
+
+//std::cout << val<1>(t3) << ", ";
+//std::cout << val<2>(t3) << ", ";
+//std::cout << val<3>(t3) << std::endl;
+
+//// create and use quadruple
+//UbType<bool,int,float,double> t4(true,42,13,1.95583);
+//std::cout << val<4>(t4) << std::endl;        //<- option 2 (std)
+//std::cout << t4.v2().v2().v2() << std::endl; //<- option 2
+*/
+
+//typeop.h
+// primary template
+/**********************************
+* typeop1.hpp:
+**********************************/
+template <typename T>
+class UbTypeOp    // primary template
+{           
+public:
+   typedef T         ArgT;
+   typedef T         BareT;
+   typedef T const   ConstT;
+   typedef T &       RefT;
+   typedef T &       RefBareT;
+   typedef T const & RefConstT;
+};
+/**** end of typeop1.hpp ****/
+
+// partial specialization for const
+/**********************************
+* typeop2.hpp:
+**********************************/
+template <typename T>
+class UbTypeOp <T const>  // partial specialization for const types
+{
+ public:
+   typedef T const   ArgT;
+   typedef T         BareT;
+   typedef T const   ConstT;
+   typedef T const & RefT;
+   typedef T &       RefBareT;
+   typedef T const & RefConstT;
+};
+/**** end of typeop2.hpp ****/
+
+// partial specialization for references
+/**********************************
+* typeop3.hpp:
+**********************************/
+template <typename T>
+class UbTypeOp <T&>        // partial specialization for references
+{
+public:
+   typedef T &                           ArgT;
+   typedef typename UbTypeOp<T>::BareT   BareT;
+   typedef T const                       ConstT;
+   typedef T &                           RefT;
+   typedef typename UbTypeOp<T>::BareT & RefBareT;
+   typedef T const &                     RefConstT;
+};
+/**** end of typeop3.hpp ****/
+
+// full specialization for void
+/**********************************
+* typeop4.hpp:
+**********************************/
+template<>
+class UbTypeOp <void>      // full specialization for void
+{
+public:
+   typedef void       ArgT;
+   typedef void       BareT;
+   typedef void const ConstT;
+   typedef void       RefT;
+   typedef void       RefBareT;
+   typedef void       RefConstT;
+};
+/**** end of typeop4.hpp ****/
+
+//duo1.hpp
+template <typename T1, typename T2>
+class UbDuo 
+{
+public:
+   typedef T1 Type1;  // type of first field
+   typedef T2 Type2;  // type of second field
+   enum { N = 2 };    // number of fields
+
+public:
+   // constructors
+   UbDuo() : value1(), value2() {  }
+   UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b)  {  }
+
+   // for implicit type conversion during construction
+   template <typename U1, typename U2>
+   UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) {  }
+
+   // for implicit type conversion during assignments
+   template <typename U1, typename U2>
+   UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d) 
+   {
+      value1 = d.v1();//value1;
+      value2 = d.v2();//value2;
+      return *this;
+   }
+
+   // field access
+   T1& v1()             { return value1; }
+   T1 const& v1() const { return value1; }
+
+   T2& v2()             { return value2; }
+   T2 const& v2() const { return value2; }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive& ar, const unsigned int version)
+   {
+      ar & value1;
+      ar & value2;
+   }
+#endif //CAB_RCF
+
+private:
+   T1 value1;         // value of first field
+   T2 value2;         // value of second field
+};
+
+// comparison operators (allow mixed types):
+template <typename T1, typename T2,typename U1, typename U2>
+inline bool operator == (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+{
+   return d1.v1()==d2.v1() && d1.v2()==d2.v2();
+}
+
+template <typename T1, typename T2,typename U1, typename U2>
+inline bool operator != (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+{
+   return !(d1==d2);
+}
+
+template <typename T1, typename T2,typename U1, typename U2>
+inline bool operator < (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+{
+   if     (d1.v1() <  d2.v1() ) return true;
+   else if(d1.v1() == d2.v1() ) return d1.v2() < d2.v2();
+
+   return false;
+}
+
+// convenience function for creation and initialization
+template <typename T1, typename T2> 
+inline UbDuo<T1,T2> makeUbDuo(T1 const & a, T2 const & b)
+{
+   return UbDuo<T1,T2>(a,b);
+}
+
+//duo2.hpp
+template <typename A, typename B, typename C>
+class UbDuo<A, UbDuo<B,C> > 
+{
+public:
+   typedef A          T1;           // type of first field
+   typedef UbDuo<B,C> T2;           // type of second field
+   enum { N = UbDuo<B,C>::N + 1 };  // number of fields
+ 
+public:
+   // constructors
+   UbDuo() : value1(), value2() { }
+   UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b) { }
+
+   // for implicit type conversion during construction
+   template <typename U1, typename U2>
+   UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) { }
+
+   // for implicit type conversion during assignments
+   template <typename U1, typename U2>
+   UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d) 
+   { 
+      value1 = d.v1();//value1;     
+      value2 = d.v2();//value2;
+      return *this;
+   }
+
+   // field access
+   T1& v1()             { return value1; }
+   T1 const& v1() const { return value1; }
+
+   T2& v2()             { return value2; }
+   T2 const& v2() const { return value2; }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & value1;
+      ar & value2;
+   }
+#endif //CAB_RCF
+
+private:
+   T1 value1;         // value of first field
+   T2 value2;         // value of second field
+};
+
+//duo3.hpp
+// primary template for type of Nth field of (duo) T
+template <int N, typename T>
+class UbDuoT 
+{
+public:
+   typedef void ResultT;    // in general, the result type is void
+};
+
+// specialization for 1st field of a plain duo
+template <typename A, typename B>
+class UbDuoT<1, UbDuo<A,B> > 
+{
+public:
+   typedef A ResultT;
+};
+
+// specialization for 2nd field of a plain duo
+template <typename A, typename B>
+class UbDuoT<2, UbDuo<A,B> > 
+{
+public:
+   typedef B ResultT;
+};
+
+// specialization for Nth field of a recursive duo
+template <int N, typename A, typename B, typename C>
+class UbDuoT<N, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   typedef typename UbDuoT<N-1, UbDuo<B,C> >::ResultT ResultT;
+};
+
+// specialization for 1st field of a recursive duo
+template <typename A, typename B, typename C>
+class UbDuoT<1, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   typedef A ResultT;
+};
+
+// specialization for 2nd field of a recursive duo
+template <typename A, typename B, typename C>
+class UbDuoT<2, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   typedef B ResultT;
+};
+
+//duo4.hpp
+// primary template for value of Nth field of (duo) T
+template <int N, typename T>
+class DuoValue 
+{
+public:
+   static void get(T&) {  }      // in general, we have no value
+   static void get(T const&) { }
+};
+
+// specialization for 1st field of a plain duo
+template <typename A, typename B>
+class DuoValue<1, UbDuo<A, B> > 
+{
+public:
+   static A& get(UbDuo<A, B> &d)             { return d.v1(); }
+   static A const& get(UbDuo<A, B> const &d) { return d.v1(); }
+};
+
+// specialization for 2nd field of a plain duo
+template <typename A, typename B>
+class DuoValue<2, UbDuo<A, B> > 
+{
+public:
+   static B& get(UbDuo<A, B> &d)             { return d.v2(); }
+   static B const& get(UbDuo<A, B> const &d) { return d.v2(); }
+};
+
+// specialization for Nth field of recursive duo
+template <int N, typename A, typename B, typename C>
+struct DuoValue<N, UbDuo<A, UbDuo<B,C> > >
+{
+   static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefT  get(UbDuo<A, UbDuo<B,C> > &d)
+   { 
+      return DuoValue<N-1, UbDuo<B,C> >::get(d.v2()); 
+   }
+   static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefConstT  get(UbDuo<A, UbDuo<B,C> > const &d)
+   { 
+      return DuoValue<N-1, UbDuo<B,C> >::get(d.v2()); 
+   }
+};
+
+// specialization for 1st field of recursive duo
+template <typename A, typename B, typename C>
+class DuoValue<1, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   static A& get(UbDuo<A, UbDuo<B,C> > &d)             { return d.v1(); }
+   static A const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v1(); }
+};
+
+// specialization for 2nd field of recursive duo
+template <typename A, typename B, typename C>
+class DuoValue<2, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   static B& get(UbDuo<A, UbDuo<B,C> > &d)             { return d.v2().v1(); }
+   static B const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v2().v1(); }
+};
+
+//duo5.hpp
+// return Nth value of variable duo
+template <int N, typename A, typename B> 
+inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefT val(UbDuo<A, B>& d)
+{
+   return DuoValue<N, UbDuo<A, B> >::get(d);
+}
+
+// return Nth value of constant duo
+template <int N, typename A, typename B> 
+inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefConstT val(UbDuo<A, B> const& d)
+{
+   return DuoValue<N, UbDuo<A, B> >::get(d);
+}
+
+//duo6.hpp
+// partial specialization for UbDuo<> with only one field
+template <typename A>
+struct UbDuo<A,void> 
+{
+public:
+   typedef A    T1;  // type of first field
+   typedef void T2;  // type of second field
+   enum { N = 1 };   // number of fields
+
+private:
+   T1 value1;        // value of first field
+
+public:
+   // constructors
+   UbDuo() : value1() { }
+   UbDuo (T1 const & a) : value1(a) { }
+
+   // field access
+   T1& v1()             { return value1; }
+   T1 const& v1() const { return value1; }
+
+   void v2() { }
+   void v2() const { }
+
+   #ifdef CAB_RCF
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & value1;
+      }
+   #endif
+};
+
+//tupel1.hpp
+// type that represents unused type parameters
+class UbNullT 
+{
+};
+
+// UbTuple<> in general derives from UbTuple<> with one more UbNullT
+template <typename P1,
+          typename P2 = UbNullT,
+          typename P3 = UbNullT,
+          typename P4 = UbNullT,
+          typename P5 = UbNullT,
+          typename P6 = UbNullT,
+          typename P7 = UbNullT,
+          typename P8 = UbNullT >
+class UbTuple : public UbDuo<P1, typename UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>::BaseT> 
+{
+public:
+   typedef UbDuo<P1, typename UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>::BaseT>  BaseT;
+
+   // constructor:
+   UbTuple() {}
+   UbTuple( typename UbTypeOp<P1>::RefConstT a1,
+            typename UbTypeOp<P2>::RefConstT a2,
+            typename UbTypeOp<P3>::RefConstT a3 = UbNullT(),
+            typename UbTypeOp<P4>::RefConstT a4 = UbNullT(),
+            typename UbTypeOp<P5>::RefConstT a5 = UbNullT(),
+            typename UbTypeOp<P6>::RefConstT a6 = UbNullT(),
+            typename UbTypeOp<P7>::RefConstT a7 = UbNullT(),
+            typename UbTypeOp<P8>::RefConstT a8 = UbNullT() )
+      : BaseT(a1, UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>(a2,a3,a4,a5,a6,a7,a8))
+   {
+   }
+
+   // for implicit type conversion during assignments
+   template <typename U1,typename U2, typename U3, typename U4, typename U5, typename U6, typename U7, typename U8 >
+   UbTuple<P1,P2,P3,P4,P5,P6,P7,P8>& operator = ( const UbTuple<U1,U2,U3,U4,U5,U6,U7,U8>& rhs)
+   {
+      this->BaseT::operator=( typename UbTuple<U1,U2,U3,U4,U5,U6,U7,U8>::BaseT(rhs) );
+      return *this;
+   }
+
+};
+
+// specialization to end deriving recursion
+template <typename P1, typename P2>
+class UbTuple<P1,P2,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,P2> {
+public:
+   typedef UbDuo<P1,P2> BaseT;
+   
+   // constructor:
+   UbTuple() {}
+   UbTuple( typename UbTypeOp<P1>::RefConstT a1,
+            typename UbTypeOp<P2>::RefConstT a2,
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT() )
+      : BaseT(a1, a2) 
+   {
+   }
+
+   // for implicit type conversion during assignments
+   template <typename U1,typename U2 >
+   UbTuple<P1,P2>& operator = ( const UbTuple<U1,U2>& rhs)
+   {
+      this->BaseT::operator=( typename UbTuple<U1,U2>::BaseT(rhs) );
+      return *this;
+   }
+
+};
+
+// specialization for singletons
+template <typename P1>
+class UbTuple<P1,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,void>
+{
+public:
+   typedef UbDuo<P1,void> BaseT;
+
+   // constructor:
+   UbTuple() {}
+   UbTuple( typename UbTypeOp<P1>::RefConstT a1,
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT() )
+      : BaseT(a1) 
+   {
+   }
+
+   // for implicit type conversion during assignments
+   template <typename U1 >
+   UbTuple<P1>& operator = ( const UbTuple<U1>& rhs)
+   {
+      this->v1() = rhs.v1();
+      return *this;
+   }
+
+};
+
+// convenience function for 1 argument
+template <typename T1> 
+inline UbTuple<T1> makeUbTuple(T1 const &a1)
+{
+   return UbTuple<T1>(a1);
+}
+
+// convenience function for 2 arguments
+template <typename T1, typename T2>
+inline UbTuple<T1,T2> makeUbTuple(T1 const &a1, T2 const &a2)
+{
+   return UbTuple<T1,T2>(a1,a2);
+}
+
+// convenience function for 3 arguments
+template <typename T1, typename T2, typename T3>
+inline UbTuple<T1,T2,T3> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3)
+{
+   return UbTuple<T1,T2,T3>(a1,a2,a3);
+}
+
+// convenience function for 4 arguments
+template <typename T1, typename T2, typename T3, typename T4>
+inline UbTuple<T1,T2,T3,T4> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4)
+{
+   return UbTuple<T1,T2,T3,T4>(a1,a2,a3,a4);
+}
+
+// convenience function for 5 arguments
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline UbTuple<T1,T2,T3,T4,T5> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4,T5 const &a5)
+{
+   return UbTuple<T1,T2,T3,T4,T5>(a1,a2,a3,a4,a5);
+}
+
+// convenience function for 6 arguments
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+inline UbTuple<T1,T2,T3,T4,T5,T6> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6)
+{
+   return UbTuple<T1,T2,T3,T4,T5,T6>(a1,a2,a3,a4,a5,a6);
+}
+
+// convenience function for 7 arguments
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+inline UbTuple<T1,T2,T3,T4,T5,T6,T7> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6, T7 const &a7)
+{
+   return UbTuple<T1,T2,T3,T4,T5,T6,T7>(a1,a2,a3,a4,a5,a6,a7);
+}
+
+// convenience function for 8 arguments
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
+inline UbTuple<T1,T2,T3,T4,T5,T6,T7,T8> makeUbTuple(T1 const &a1, T2 const &a2,T3 const &a3, T4 const &a4,T5 const &a5, T6 const &a6,T7 const &a7, T8 const &a8 )
+{
+   return UbTuple<T1,T2,T3,T4,T5,T6,T7,T8>(a1,a2,a3,a4,a5,a6,a7,a8);
+}
+
+//some typedefs
+typedef UbTuple<float,float>                               UbTupleFloat2;
+typedef UbTuple<float,float,float>                         UbTupleFloat3;
+typedef UbTuple<int,int>                                   UbTupleInt2;
+typedef UbTuple<int,int,int>                               UbTupleInt3;
+typedef UbTuple<int,int,int,int>                           UbTupleInt4;
+typedef UbTuple<int,int,int,int,int>                       UbTupleInt5;
+typedef UbTuple<int,int,int,int,int,int>                   UbTupleInt6;
+typedef UbTuple<int,int,int,int,int,int,int,int>           UbTupleInt8;
+typedef UbTuple<double,double>                             UbTupleDouble2;
+typedef UbTuple<double,double,double>                      UbTupleDouble3;
+typedef UbTuple<double,double,double,double>               UbTupleDouble4;
+typedef UbTuple<double,double,double,double,double,double> UbTupleDouble6;
+typedef UbTuple<std::string,double,double>                 UbTupleStringDouble2;
+typedef UbTuple<std::string,double,double,double>          UbTupleStringDouble3;
+typedef UbTuple<std::string,int,int,int>                   UbTupleStringInt3;
+typedef UbTuple<short,short,short,short>                   UbTupleShort4;
+typedef UbTuple<bool,bool,bool>                            UbTupleBool3;
+typedef UbTuple<int,double,double>                         UbTupleIntDouble2;
+typedef UbTuple<int, bool>                                 UbTupleIntBool;
+
+
+// class UbTupleWrapper
+// {
+// public:
+//    UbTuple<int, int> a;
+// 
+// #ifdef CAB_RCF
+//    template<class Archive>
+//    void serialize(Archive & ar, const unsigned int version)
+//    {
+//       ar & a;
+//    }
+//    void tuWas()
+//    {
+//       std::cout<<val<1>(a)<<std::endl;
+// 
+//       std::cout<<val<2>(a)<<std::endl;
+//    }
+// 
+// #endif
+// 
+// };
+
+
+#endif //UBTUPLE_H
+
+
+//#ifndef AAAAAAAAAAAAAAAAAAAAAAAAAAAAA //UBTUPLE_H
+//#define AAAAAAAAAAAAAAAAAAAAAAAAAAAAA //UBTUPLE_H
+//class UbTuble;
+//#include <iostream>
+//#include <string>
+//#include <algorithm> 
+//
+//
+//// a helper traits to make the make_tuple functions shorter (Vesa Karvonen's suggestion)
+//struct UbNullType{};
+//
+//template < class T0 = UbNullType, class T1 = UbNullType, class T2 = UbNullType,
+//class T3 = UbNullType, class T4 = UbNullType, class T5 = UbNullType,
+//class T6 = UbNullType, class T7 = UbNullType, class T8 = UbNullType >
+//class UbSimpleTuple
+//{
+//public:  
+//   UbSimpleTuple() {}
+//   UbSimpleTuple(T0 t0) {}
+//   UbSimpleTuple( const T0& t0) 
+//      : t0(t0) {}
+//   UbSimpleTuple( const T0& t0,  const T1& t1)
+//      : t0(t0), t1(t1){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2) 
+//      : t0(t0), t1(t1), t2(t2) {}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3)
+//      : t0(t0), t1(t1), t2(t2), t3(t3){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4,  const T5& t5) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), t5(t5){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4,  const T5& t5,  const T6& t6) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), t5(t5), t6(t6){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4,  const T5& t5,  const T6& t6,  const T7& t7) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), t5(t5), t6(t6), t7(t7){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4,  const T5& t5,  const T6& t6,  const T7& t7, const T8& t8) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), t5(t5), t6(t6), t7(t7), t8(t8){}
+//
+//   T0 t0;
+//   T1 t1;
+//   T2 t2;
+//   T3 t3;
+//   T4 t4;
+//   T5 t5;
+//   T6 t6;
+//   T7 t7;
+//   T8 t8;
+//};
+// 
+//
+//UbSimpleTuple<> 
+//inline makeUbSimpleTuple() { return UbSimpleTuple<>(); }
+//
+//template<class T0>
+//inline UbSimpleTuple<T0> makeUbSimpleTuple(const T0& t0) { return UbSimpleTuple<T0>(t0); }
+//
+//template<class T0, class T1>
+//inline UbSimpleTuple<T0,T1> makeUbSimpleTuple(const T0& t0, const T1& t1)  { return UbSimpleTuple<T0,T1>(t0,t1); }
+//
+//template<class T0, class T1, class T2>
+//inline UbSimpleTuple<T0,T1,T2> makeUbSimpleTuple(const T0& t0, const T1& t1, const T2& t2)  { return UbSimpleTuple<T0,T1,T2>(t0,t1,t2); }
+//
+//template<class T0, class T1, class T2, class T3>
+//inline UbSimpleTuple<T0,T1,T2,T3> makeUbSimpleTuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3)  { return UbSimpleTuple<T0,T1,T2,T3>(t0,t1,t2,t2); }
+//
+////////////////////////////////////////////////////////////////////////////
+////Advanced UbTuple
+////Bsp:
+// //// create and use tuple with only one field
+// //UbTuple<int,int,int,int,int> t1;
+// //val<1>(t1) += 42;
+// //std::cout << t1.v1() << std::endl;
+//
+// //UbTuple<int,double,double> ttt3;
+// //val<3>(t3);
+// //
+// //// create and use duo
+// //UbType<bool,int> t2;
+// //std::cout << val<1>(t2) << ", ";
+// //std::cout << t2.v1() << std::endl;
+//
+// //// create and use triple
+// //UbType<bool,int,double> t3;
+// //val<1>(t3) = true;
+// //val<2>(t3) = 42;
+// //val<3>(t3) = 0.2;
+//
+// //std::cout << val<1>(t3) << ", ";
+// //std::cout << val<2>(t3) << ", ";
+// //std::cout << val<3>(t3) << std::endl;
+//
+// //t3 = make_tuple(false, 23, 13.13);
+//
+// //std::cout << val<1>(t3) << ", ";
+// //std::cout << val<2>(t3) << ", ";
+// //std::cout << val<3>(t3) << std::endl;
+//
+// //// create and use quadruple
+// //UbType<bool,int,float,double> t4(true,42,13,1.95583);
+// //std::cout << val<4>(t4) << std::endl;
+// //std::cout << t4.v2().v2().v2() << std::endl;
+//
+////typeop.hpp
+//// primary template
+///**********************************
+//* typeop1.hpp:
+//**********************************/
+//template <typename T>
+//class UbTypeOp             // primary template
+//{
+//public:
+//   typedef T         ArgT;
+//   typedef T         BareT;
+//   typedef T const   ConstT;
+//   typedef T &       RefT;
+//   typedef T &       RefBareT;
+//   typedef T const & RefConstT;
+//};
+///**** end of typeop1.hpp ****/
+//
+//// partial specialization for const
+///**********************************
+//* typeop2.hpp:
+//**********************************/
+//template <typename T>
+//class UbTypeOp <T const>   // partial specialization for const types
+//{
+//   public:
+//   typedef T const   ArgT;
+//   typedef T         BareT;
+//   typedef T const   ConstT;
+//   typedef T const & RefT;
+//   typedef T &       RefBareT;
+//   typedef T const & RefConstT;
+//};
+///**** end of typeop2.hpp ****/
+//
+//// partial specialization for references
+///**********************************
+//* typeop3.hpp:
+//**********************************/
+//template <typename T>
+//class UbTypeOp <T&>        // partial specialization for references
+//{
+//public:
+//   typedef T &                         ArgT;
+//   typedef typename UbTypeOp<T>::BareT   BareT;
+//   typedef T const                     ConstT;
+//   typedef T &                         RefT;
+//   typedef typename UbTypeOp<T>::BareT & RefBareT;
+//   typedef T const &                   RefConstT;
+//};
+///**** end of typeop3.hpp ****/
+//
+//// full specialization for void
+///**********************************
+//* typeop4.hpp:
+//**********************************/
+//template<>
+//class UbTypeOp <void>      // full specialization for void
+//{
+//public:
+//   typedef void       ArgT;
+//   typedef void       BareT;
+//   typedef void const ConstT;
+//   typedef void       RefT;
+//   typedef void       RefBareT;
+//   typedef void       RefConstT;
+//};
+///**** end of typeop4.hpp ****/
+//
+////duo1.hpp
+//template <typename T1, typename T2>
+//class UbDuo 
+//{
+//public:
+//   typedef T1 Type1;  // type of first field
+//   typedef T2 Type2;  // type of second field
+//   enum { N = 2 };    // number of fields
+//
+//private:
+//   T1 value1;         // value of first field
+//   T2 value2;         // value of second field
+//
+//public:
+//   // constructors
+//   UbDuo() : value1(), value2() { }
+//   UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b) { }
+//
+//   // for implicit type conversion during construction
+//   template <typename U1, typename U2>
+//   UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) { }
+//
+//   // for implicit type conversion during assignments
+//   template <typename U1, typename U2>
+//   UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d)
+//   {
+//      value1 = d.value1;
+//      value2 = d.value2;
+//      return *this;
+//   }
+//
+//   // field access
+//   T1& v1() { return value1; }
+//   T1 const& v1() const { return value1; }
+//
+//   T2& v2() { return value2; }
+//   T2 const& v2() const { return value2; }
+//};
+//
+//// comparison operators (allow mixed types):
+//template <typename T1, typename T2,
+//typename U1, typename U2>
+//inline bool operator == (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+//{
+//   return d1.v1()==d2.v1() && d1.v2()==d2.v2();
+//}
+//
+//template <typename T1, typename T2,
+//typename U1, typename U2>
+//inline bool operator != (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+//{
+//   return !(d1==d2);
+//}
+//
+//// convenience function for creation and initialization
+//template <typename T1, typename T2> 
+//inline UbDuo<T1,T2> makeUbDuo(T1 const & a, T2 const & b)
+//{
+//   return UbDuo<T1,T2>(a,b);
+//}
+//
+////duo2.hpp
+//template <typename A, typename B, typename C>
+//class UbDuo<A, UbDuo<B,C> >
+//{
+//public:
+//   typedef A          T1;           // type of first field
+//   typedef UbDuo<B,C> T2;           // type of second field
+//   enum { N = UbDuo<B,C>::N + 1 };  // number of fields
+//
+//private:
+//   T1 value1;         // value of first field
+//   T2 value2;         // value of second field
+//
+//public:
+//   // constructors
+//   UbDuo() : value1(), value2() {}
+//   UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b) { }
+//
+//   // for implicit type conversion during construction
+//   template <typename U1, typename U2>
+//   UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) { }
+//
+//   // for implicit type conversion during assignments
+//   template <typename U1, typename U2>
+//   UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d) 
+//   {
+//      value1 = d.value1;
+//      value2 = d.value2;
+//      return *this;
+//   }
+//
+//   // field access
+//   T1& v1() { return value1; }
+//   T1 const& v1() const { return value1; }
+//
+//   T2& v2() { return value2; }
+//   T2 const& v2() const { return value2; }
+//};
+//
+////duo3.hpp
+//// primary template for type of Nth field of (duo) T
+//template <int N, typename T>
+//class UbDuoT 
+//{
+//public:
+//   typedef void ResultT;    // in general, the result type is void
+//};
+//
+//// specialization for 1st field of a plain duo
+//template <typename A, typename B>
+//class UbDuoT<1, UbDuo<A,B> > 
+//{
+//public:
+//   typedef A ResultT;
+//};
+//
+//// specialization for 2nd field of a plain duo
+//template <typename A, typename B>
+//class UbDuoT<2, UbDuo<A,B> > 
+//{
+//public:
+//   typedef B ResultT;
+//};
+//
+//// specialization for Nth field of a recursive duo
+//template <int N, typename A, typename B, typename C>
+//class UbDuoT<N, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   typedef typename UbDuoT<N-1, UbDuo<B,C> >::ResultT ResultT;
+//};
+//
+//// specialization for 1st field of a recursive duo
+//template <typename A, typename B, typename C>
+//class UbDuoT<1, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   typedef A ResultT;
+//};
+//
+//// specialization for 2nd field of a recursive duo
+//template <typename A, typename B, typename C>
+//class UbDuoT<2, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   typedef B ResultT;
+//};
+//
+////duo4.hpp
+//// primary template for value of Nth field of (duo) T
+//template <int N, typename T>
+//class UbDuoValue 
+//{
+//public:
+//   static void get(T&) { }       // in general, we have no value
+//   static void get(T const&) { }
+//};
+//
+//// specialization for 1st field of a plain duo
+//template <typename A, typename B>
+//class UbDuoValue<1, UbDuo<A, B> > 
+//{
+//public:
+//   static A& get(UbDuo<A, B> &d) { return d.v1(); }
+//   static A const& get(UbDuo<A, B> const &d) { return d.v1();}
+//};
+//
+//// specialization for 2nd field of a plain duo
+//template <typename A, typename B>
+//class UbDuoValue<2, UbDuo<A, B> > 
+//{
+//public:
+//   static B& get(UbDuo<A, B> &d) 
+//   { 
+//      return d.v2(); 
+//   }
+//   static B const& get(UbDuo<A, B> const &d) { return d.v2(); }
+//};
+//
+//// specialization for Nth field of recursive duo
+//template <int N, typename A, typename B, typename C>
+//struct UbDuoValue<N, UbDuo<A, UbDuo<B,C> > > 
+//{
+//   static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefT
+//   get(UbDuo<A, UbDuo<B,C> > &d) { return UbDuoValue<N-1, UbDuo<B,C> >::get(d.v2()); }
+//
+//   static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefConstT
+//   get(UbDuo<A, UbDuo<B,C> > const &d) { return UbDuoValue<N-1, UbDuo<B,C> >::get(d.v2()); }
+//};
+//
+//// specialization for 1st field of recursive duo
+//template <typename A, typename B, typename C>
+//class UbDuoValue<1, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   static A& get(UbDuo<A, UbDuo<B,C> > &d) { return d.v1(); }
+//   static A const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v1(); }
+//};
+//
+//// specialization for 2nd field of recursive duo
+//template <typename A, typename B, typename C>
+//class UbDuoValue<2, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   static B& get(UbDuo<A, UbDuo<B,C> > &d) { return d.v2().v1(); }
+//   static B const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v2().v1(); }
+//};
+//
+////duo5.hpp
+//// return Nth value of variable duo
+//template <int N, typename A, typename B> 
+//inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefT
+//val(UbDuo<A, B>& d)
+//{
+//   return UbDuoValue<N, UbDuo<A, B> >::get(d);
+//}
+//
+//// return Nth value of constant duo
+//template <int N, typename A, typename B> 
+//inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefConstT
+//val(UbDuo<A, B> const& d)
+//{
+//   return UbDuoValue<N, UbDuo<A, B> >::get(d);
+//}
+//
+////duo6.hpp
+//// partial specialization for UbDuo<> with only one field
+//template <typename A>
+//struct UbDuo<A,void> 
+//{
+//public:
+//   typedef A    T1;  // type of first field
+//   typedef void T2;  // type of second field
+//   enum { N = 1 };   // number of fields
+//
+//private:
+//   T1 value1;        // value of first field
+//
+//public:
+//   // constructors
+//   UbDuo() : value1() { }
+//   UbDuo (T1 const & a) : value1(a) { }
+//
+//   // field access
+//   T1& v1() { return value1; }
+//   T1 const& v1() const { return value1; }
+//
+//   void v2() { }
+//   void v2() const { }
+//   //...
+//};
+//
+////tuple1.hpp
+//// a helper traits to make the make_tuple functions shorter (Vesa Karvonen's suggestion)
+//struct UbNullT{};
+//
+//// UbType<> in general derives from UbType<> with one more UbNullT
+//template <typename P1,
+//          typename P2 = UbNullT,
+//          typename P3 = UbNullT,
+//          typename P4 = UbNullT,
+//          typename P5 = UbNullT>
+//class UbType : public UbDuo<P1, typename UbType<P2,P3,P4,P5,UbNullT>::BaseT> 
+//{
+//public:
+//   typedef UbDuo<P1, typename UbType<P2,P3,P4,P5,UbNullT>::BaseT> BaseT;
+//
+//   // constructors:
+//   UbType() {}
+//   UbType(typename UbTypeOp<P1>::RefConstT a1,
+//          typename UbTypeOp<P2>::RefConstT a2,
+//          typename UbTypeOp<P3>::RefConstT a3 = UbNullT(),
+//          typename UbTypeOp<P4>::RefConstT a4 = UbNullT(),
+//          typename UbTypeOp<P5>::RefConstT a5 = UbNullT() ) : BaseT(a1, UbType<P2,P3,P4,P5,UbNullT>(a2,a3,a4,a5)) 
+//   {
+//   }
+//};
+//
+//// specialization to end deriving recursion
+//template <typename P1, typename P2>
+//class UbType<P1,P2,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,P2> 
+//{
+//public:
+//   typedef UbDuo<P1,P2> BaseT;
+//   UbType() {}
+//   UbType(typename UbTypeOp<P1>::RefConstT a1,
+//          typename UbTypeOp<P2>::RefConstT a2,
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT() ) : BaseT(a1, a2) 
+//   {
+//   }
+//};
+//
+//// specialization for singletons
+//template <typename P1>
+//class UbType<P1,UbNullT,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,void> 
+//{
+//public:
+//   typedef UbDuo<P1,void> BaseT;
+//   UbType() {}
+//   UbType(typename UbTypeOp<P1>::RefConstT a1,
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT() ) : BaseT(a1) 
+//   {
+//   }
+//};
+//
+//// convenience function for 1 argument
+//template <typename T1>
+//inline UbType<T1> makeUbTuple(T1 const &a1)
+//{
+//   return UbType<T1>(a1);
+//}
+//
+//// convenience function for 2 arguments
+//template <typename T1, typename T2>
+//inline UbType<T1,T2> makeUbTuple(T1 const &a1, T2 const &a2)
+//{
+//   return UbType<T1,T2>(a1,a2);
+//}
+//
+//// convenience function for 3 arguments
+//template <typename T1, typename T2, typename T3>
+//inline UbType<T1,T2,T3> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3)
+//{
+//   return UbType<T1,T2,T3>(a1,a2,a3);
+//}
+//
+//// convenience function for 4 arguments
+//template <typename T1, typename T2, typename T3, typename T4>
+//inline UbType<T1,T2,T3,T4> make_tuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4)
+//{
+//   return UbType<T1,T2,T3,T4>(a1,a2,a3,a4);
+//}
+//
+//// convenience function for 5 arguments
+//template <typename T1, typename T2, typename T3,
+//typename T4, typename T5>
+//inline UbType<T1,T2,T3,T4,T5> make_tuple(T1 const &a1, T2 const &a2,T3 const &a3, T4 const &a4,T5 const &a5)
+//{
+//   return UbType<T1,T2,T3,T4,T5>(a1,a2,a3,a4,a5);
+//}
+//
+//#endif
+
diff --git a/source/ThirdParty/Library/basics/writer/CMakePackage.txt b/source/ThirdParty/Library/basics/writer/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1222f87f3fb0a45838379cdf4345e3d11a06e575
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/CMakePackage.txt
@@ -0,0 +1,3 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
+
diff --git a/source/ThirdParty/Library/basics/writer/WbWriter.h b/source/ThirdParty/Library/basics/writer/WbWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..77869d11876747e42811a0c0659233804353a5a0
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriter.h
@@ -0,0 +1,183 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITER_H
+#define WBWRITER_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+
+#include <vector>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <map>
+
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbPointerWrapper.h>
+#include <basics/utilities/UbAutoRun.hpp>
+#include <basics/objects/ObFactory.h>
+
+#include <boost/serialization/serialization.hpp>
+
+class WbWriter
+{
+public:
+   OBCREATOR_EXT(WbWriter)
+
+   //////////////////////////////////////////////////////////////////////////
+   virtual ~WbWriter() 
+   {
+
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //rein virtuelle Methoden
+   virtual std::string getFileExtension() = 0;
+
+   //////////////////////////////////////////////////////////////////////////
+   //nodes
+   virtual std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   virtual std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                     2
+   //                      
+   //                  0 === 1
+   //nodenumbering must start with 0!
+   virtual std::string writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+   //////////////////////////////////////////////////////////////////////////
+   //quads
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   virtual std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                                     std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                                     std::vector< std::vector< double > >& celldata                                                                                       ){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   virtual std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+
+   }
+};
+
+
+#ifdef CAB_RCF
+//serialize von singletons muss hier etwas anders erfolgen ;-)
+template<class Archive>
+inline bool serializeWbWriter(Archive &ar, WbWriter*& writer)
+{
+   std::string writerID;
+
+   if( ArchiveTools::isReading(ar) )
+   {                                                                  
+      ar & writerID;
+      if(writerID!="no_WbWriter") writer = ObFactory<WbWriter>::getInstance()->createObject(writerID);
+      else                        writer = NULL;
+   }                                                                  
+   else /* if (ar.isWrite())) if(Archive::is_saving())*/                                      
+   {                                                                   
+      if(writer) writerID = writer->getClassObjectTypeID(); 
+      else       writerID = "no_WbWriter";
+      ar & writerID;
+   } 
+   return true;
+}
+//////////////////
+template<class Archive, class STL_container>
+inline bool serializeWbWriter(Archive &ar, STL_container& writers)
+{
+   int       nofCounter;
+   std::string    writerID;
+   WbWriter* dummy;
+
+   if( ArchiveTools::isReading(ar) )
+   {                                                                  
+      ar & nofCounter;
+      for(int i=0; i<nofCounter; i++)
+      {
+         serializeWbWriter(ar, dummy);
+         writers.push_back(dummy);
+      }
+   }                                                                  
+   else                                 
+   {                                                                   
+      nofCounter = (int)writers.size();
+      ar & nofCounter;
+      typename STL_container::iterator pos;
+      for(pos=writers.begin(); pos!=writers.end(); ++pos)
+         serializeWbWriter(ar, *pos);
+   }                                                                   
+
+   return true;
+}
+//////////////////////////////////////////////////////////////////////////
+// Spezialisierung des UbPointerWrappers fuer WbWriter... 
+// da man bei singletons keine serializemethode einbauen kann...
+template< >
+class UbPointerWrapper< WbWriter > 
+{
+public:
+   UbPointerWrapper() : pointer(NULL) {}
+
+   UbPointerWrapper(WbWriter* pointer) : pointer(pointer) {}
+
+   WbWriter* get() { return pointer; }
+
+   template<class Archive>
+   void serialize(Archive& ar, const unsigned int version) 
+   {
+      serializeWbWriter(ar, pointer);
+   }
+
+private:
+   WbWriter* pointer;
+};
+
+
+#endif //CAB_RCF
+
+
+#endif //WBWRITER_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterAvsASCII.cpp b/source/ThirdParty/Library/basics/writer/WbWriterAvsASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a9616fd73b6ee250b1e11ac266d8bea77e478b2
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterAvsASCII.cpp
@@ -0,0 +1,896 @@
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+std::string WbWriterAvsASCII::writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuads to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+avsfilename);
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuads to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOcts to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden "+avsfilename);
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 7; //=hex
+   int nofNodesPerCell = 8; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOcts to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithNodeData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write UCD File "+avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)datanames.size();
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) 
+      { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithNodeData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithCellData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File  "+avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = (int)datanames.size();
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   fdummy=0.0;
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //CELL DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofCellData-1; ++d) { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofCellData-1].c_str()); 
+
+   for(int d=0; d<nofCellData-1; ++d) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofCellData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofCellData; ++d)
+      for(int n=0; n<(int)celldata[d].size(); n++)
+         { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithCellData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames, vector< vector< double > >& celldata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithNodeAndCellData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File  "+avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)nodedatanames.size();
+   int nofCellData     = (int)celldatanames.size();
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char nodelabels[1024];
+   char nodeunits[1024];
+   strcpy(nodelabels, "");
+   strcpy(nodeunits, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) { strcat(nodelabels, nodedatanames[d].c_str() ); strcat(nodelabels,"."); }
+   strcat(nodelabels, nodedatanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(nodeunits, "no_unit.");
+   strcat(nodeunits, "no_unit");
+
+   out.write((char*)&nodelabels,sizeof(nodelabels));
+   out.write((char*)&nodeunits,sizeof(nodeunits));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //CELL DATA
+   char celllabels[1024];
+   char cellunits[1024];
+   strcpy(celllabels, "");
+   strcpy(cellunits, "");
+
+   for(int d=0; d<nofCellData-1; ++d) { strcat(celllabels, celldatanames[d].c_str() ); strcat(celllabels,"."); }
+   strcat(celllabels, celldatanames[nofCellData-1].c_str()); 
+
+   for(int d=0; d<nofCellData-1; ++d) strcat(cellunits, "no_unit.");
+   strcat(cellunits, "no_unit");
+
+   out.write((char*)&celllabels,sizeof(celllabels));
+   out.write((char*)&cellunits,sizeof(cellunits));
+
+   //nof and type of data
+   idummy = nofCellData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofCellData; ++d)
+      for(int n=0; n<(int)celldata[d].size(); n++)
+      { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithNodeAndCellData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeLines to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+   
+   out<<"# UCD-File created by WbWriterAvsASCII\n";
+   out<<nofNodes<<" "<<nofLines<<" 0 0 0 "<<endl;
+
+   for(int n=0; n<nofNodes; n++)
+      out<<n+1<<" "<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n])<<" \n";
+
+   for(int l=0; l<nofLines; l++)
+       out<<l+1<<" 2 line "<< val<1>(lines[l])+1 <<" "<< val<2>(lines[l])+1 <<" "<<endl;
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeLines to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeTriangles to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out);}
+      if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden "+avsfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofTrian = (int)triangles.size(); 
+
+   out<<"# UCD-File created by WbWriterAvsASCII\n";
+   out<<nofNodes<<" "<<nofTrian<<" 0 0 0 "<<endl;
+
+   for(int n=0; n<nofNodes; n++)
+   out<<n+1<<" "<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n])<<" \n";
+
+   for(int l=0; l<nofTrian; l++)
+   out<<l+1<<" 2 tri "<< val<1>(triangles[l])+1 <<" "<< val<2>(triangles[l])+1 <<" "<< val<3>(triangles[l])+1 <<" "<<endl;
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeTriangles to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeTrianglesWithNodeData to "<<avsfilename<<" - end");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File "+avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)datanames.size();
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 2; //triangle
+   int nofNodesPerCell = 3; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) 
+   { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+      fdummy = 1.;
+      for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeTrianglesWithNodeData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata)
+{
+    string avsfilename = filename+getFileExtension();
+    UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOctsWithCellData to "<<avsfilename<<" - start");
+
+    ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+    if(!out)
+    { 
+       out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+       string path = UbSystem::getPathFromString(avsfilename);
+       if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+       if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden "+avsfilename);
+    }
+
+    char magic = (char)7;
+    int   idummy;
+    float fdummy;
+
+    int nofNodes = (int)nodes.size();
+    int nofCells = (int)cells.size();
+
+    int nofNodeData     = 0;
+    int nofCellData     = (int)datanames.size();
+    int nofModelData    = 0;
+    int cellType        = 7; //=hex
+    int nofNodesPerCell = 8; 
+
+    out.write((char*)&magic,sizeof(char));      
+    out.write((char*)&nofNodes,sizeof(int));    
+    out.write((char*)&nofCells,sizeof(int));    
+    out.write((char*)&nofNodeData,sizeof(int)); 
+    out.write((char*)&nofCellData,sizeof(int)); 
+    out.write((char*)&nofModelData,sizeof(int));
+
+    idummy = (int)nofCells*nofNodesPerCell;
+    out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+       idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+       idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+       idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+    }
+    //knotennummern der einzelnen zellen
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+    }
+
+    //coords
+    //x1-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x2-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x3-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //out<<"\n";
+
+    //CELL DATA
+    char labels[1024];
+    char units[1024];
+    strcpy(labels, "");
+    strcpy(units, "");
+
+    for(int d=0; d<nofCellData-1; ++d) { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+    strcat(labels, datanames[nofCellData-1].c_str()); 
+
+    for(int d=0; d<nofCellData-1; ++d) strcat(units, "no_unit.");
+    strcat(units, "no_unit");
+
+    out.write((char*)&labels,sizeof(labels));
+    out.write((char*)&units,sizeof(units));
+
+    //nof and type of data
+    idummy = nofCellData;
+    out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+    idummy = 1;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+    //min and max of data
+    fdummy = 0.0;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+    fdummy = 1.0;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    //daten ins file schreiben
+    for(int d=0; d<nofCellData; ++d)
+    for(int n=0; n<(int)celldata[d].size(); n++)
+    { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+    fdummy = 1.;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    out.close(); 
+    UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOctsWithCellData to "<<avsfilename<<" - end");
+
+    return avsfilename;
+ }
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+    string avsfilename = filename+getFileExtension();
+    UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOctsWithNodeData to "<<avsfilename<<" - start");
+
+    ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+    if(!out)
+    { 
+       out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+       string path = UbSystem::getPathFromString(avsfilename);
+       if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+       if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden "+avsfilename);
+    }
+
+    if((int)nodedata.size()==0) throw UbException(UB_EXARGS,"no nodedata!!!");
+    if(nodes.size()!=nodedata[0].size()) throw UbException(UB_EXARGS,"nodedata != nofNodes!!!");
+
+    char magic = (char)7;
+    int   idummy;
+    float fdummy;
+
+    int nofNodes = (int)nodes.size();
+    int nofCells = (int)cells.size();
+
+    int nofNodeData     = (int)datanames.size();
+    int nofCellData     = 0;
+    int nofModelData    = 0;
+    int cellType        = 7; //=hex
+    int nofNodesPerCell = 8; 
+
+    out.write((char*)&magic,sizeof(char));      
+    out.write((char*)&nofNodes,sizeof(int));    
+    out.write((char*)&nofCells,sizeof(int));    
+    out.write((char*)&nofNodeData,sizeof(int)); 
+    out.write((char*)&nofCellData,sizeof(int)); 
+    out.write((char*)&nofModelData,sizeof(int));
+
+    idummy = (int)nofCells*nofNodesPerCell;
+    out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+       idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+       idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+       idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+    }
+    //knotennummern der einzelnen zellen
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+    }
+
+    //coords
+    //x1-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x2-coords
+    for(int n=0; n<nofNodes; n++)
+       { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x3-coords
+    for(int n=0; n<nofNodes; n++)
+       { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+
+    //NODE DATA
+    char labels[1024];
+    char units[1024];
+    strcpy(labels, "");
+    strcpy(units, "");
+
+    for(int d=0; d<nofNodeData-1; ++d) 
+    { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+    strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+    for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+    strcat(units, "no_unit");
+
+    out.write((char*)&labels,sizeof(labels));
+    out.write((char*)&units,sizeof(units));
+
+    //nof and type of data
+    idummy = nofNodeData;
+    out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+    idummy = 1;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+    //min and max of data
+    fdummy = 0.0;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+    fdummy = 1.0;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    //daten ins file schreiben
+    for(int d=0; d<nofNodeData; ++d)
+       for(int n=0; n<(int)nodedata[d].size(); n++)
+       { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+    fdummy = 1.;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    out.close(); 
+    UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOctsWithNodeData to "<<avsfilename<<" - end");
+
+    return avsfilename;
+ }
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterAvsASCII.h b/source/ThirdParty/Library/basics/writer/WbWriterAvsASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c65e1683d3de61a6322be303be76bdfd7f5a677
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterAvsASCII.h
@@ -0,0 +1,76 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITERAVSASCII_H
+#define WBWRITERAVSASCII_H
+
+#include <basics/writer/WbWriter.h>
+      
+class WbWriterAvsASCII : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterAvsASCII )
+
+   static WbWriterAvsASCII* getInstance()
+   {
+      static WbWriterAvsASCII instance;
+      return &instance;
+   }
+
+private:
+   WbWriterAvsASCII() : WbWriter() {}                            
+   WbWriterAvsASCII( const WbWriterAvsASCII& );                  //no copy allowed 
+   const WbWriterAvsASCII& operator=( const WbWriterAvsASCII& ); //no copy allowed
+
+public:
+   std::string getFileExtension() { return ".ascii.inp"; }
+   
+   ///////////////////virtual std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells) = 0;
+   ///////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                    2
+   //                       
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTuple<int,int,int> >& triangles);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //quads
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames, std::vector< std::vector< double > >& celldata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector< std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector< std::vector<double > >& nodedata);
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterAvsASCII ,WbWriter>::getInstance()), CAB_WbWriterAvsASCII);
+
+#endif //WBWRITERAVSASCII_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterAvsBinary.cpp b/source/ThirdParty/Library/basics/writer/WbWriterAvsBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..34d1d3415cf6ca738b0343b334a9d158d783012a
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterAvsBinary.cpp
@@ -0,0 +1,975 @@
+#include <basics/writer/WbWriterAvsBinary.h>
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+std::string WbWriterAvsBinary::writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeLines to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary); }
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)lines.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 1; //line
+   int nofNodesPerCell = 2; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(lines[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(lines[c])+1; out.write((char*)&idummy,sizeof(int)); 
+     
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   fdummy=0.0;
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeLines to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTuple<int,int,int> >& triangles)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeTriangles to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)triangles.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 2; //triangle
+   int nofNodesPerCell = 3; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(triangles[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(triangles[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(triangles[c])+1; out.write((char*)&idummy,sizeof(int)); 
+
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   fdummy=0.0;
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeTriangles to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuads to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+  
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuads to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOcts to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 7; //=hex
+   int nofNodesPerCell = 8; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOcts to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeTrianglesWithNodeData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File "+avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)datanames.size();
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 2; //triangle
+   int nofNodesPerCell = 3; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) 
+      { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeTrianglesWithNodeData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithNodeData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File "+avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)datanames.size();
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) 
+      { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithNodeData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithCellData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = (int)datanames.size();
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   fdummy=0.0;
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //CELL DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofCellData-1; ++d) { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofCellData-1].c_str()); 
+
+   for(int d=0; d<nofCellData-1; ++d) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofCellData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofCellData; ++d)
+      for(int n=0; n<(int)celldata[d].size(); n++)
+         { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithCellData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames, vector< vector< double > >& celldata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithNodeAndCellData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)nodedatanames.size();
+   int nofCellData     = (int)celldatanames.size();
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char nodelabels[1024];
+   char nodeunits[1024];
+   strcpy(nodelabels, "");
+   strcpy(nodeunits, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) { strcat(nodelabels, nodedatanames[d].c_str() ); strcat(nodelabels,"."); }
+   strcat(nodelabels, nodedatanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(nodeunits, "no_unit.");
+   strcat(nodeunits, "no_unit");
+
+   out.write((char*)&nodelabels,sizeof(nodelabels));
+   out.write((char*)&nodeunits,sizeof(nodeunits));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //CELL DATA
+   char celllabels[1024];
+   char cellunits[1024];
+   strcpy(celllabels, "");
+   strcpy(cellunits, "");
+
+   for(int d=0; d<nofCellData-1; ++d) { strcat(celllabels, celldatanames[d].c_str() ); strcat(celllabels,"."); }
+   strcat(celllabels, celldatanames[nofCellData-1].c_str()); 
+
+   for(int d=0; d<nofCellData-1; ++d) strcat(cellunits, "no_unit.");
+   strcat(cellunits, "no_unit");
+
+   out.write((char*)&celllabels,sizeof(celllabels));
+   out.write((char*)&cellunits,sizeof(cellunits));
+
+   //nof and type of data
+   idummy = nofCellData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofCellData; ++d)
+      for(int n=0; n<(int)celldata[d].size(); n++)
+      { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithNodeAndCellData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata)
+{
+    string avsfilename = filename+getFileExtension();
+    UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOctsWithCellData to "<<avsfilename<<" - start");
+
+    ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+    if(!out)
+    { 
+       out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+       string path = UbSystem::getPathFromString(avsfilename);
+       if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+       if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden");
+    }
+
+    char magic = (char)7;
+    int   idummy;
+    float fdummy;
+
+    int nofNodes = (int)nodes.size();
+    int nofCells = (int)cells.size();
+
+    int nofNodeData     = 0;
+    int nofCellData     = (int)datanames.size();
+    int nofModelData    = 0;
+    int cellType        = 7; //=hex
+    int nofNodesPerCell = 8; 
+
+    out.write((char*)&magic,sizeof(char));      
+    out.write((char*)&nofNodes,sizeof(int));    
+    out.write((char*)&nofCells,sizeof(int));    
+    out.write((char*)&nofNodeData,sizeof(int)); 
+    out.write((char*)&nofCellData,sizeof(int)); 
+    out.write((char*)&nofModelData,sizeof(int));
+
+    idummy = (int)nofCells*nofNodesPerCell;
+    out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+       idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+       idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+       idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+    }
+    //knotennummern der einzelnen zellen
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+    }
+
+    //coords
+    //x1-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x2-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x3-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //out<<"\n";
+
+    //CELL DATA
+    char labels[1024];
+    char units[1024];
+    strcpy(labels, "");
+    strcpy(units, "");
+
+    for(int d=0; d<nofCellData-1; ++d) { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+    strcat(labels, datanames[nofCellData-1].c_str()); 
+
+    for(int d=0; d<nofCellData-1; ++d) strcat(units, "no_unit.");
+    strcat(units, "no_unit");
+
+    out.write((char*)&labels,sizeof(labels));
+    out.write((char*)&units,sizeof(units));
+
+    //nof and type of data
+    idummy = nofCellData;
+    out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+    idummy = 1;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+    //min and max of data
+    fdummy = 0.0;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+    fdummy = 1.0;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    //daten ins file schreiben
+    for(int d=0; d<nofCellData; ++d)
+    for(int n=0; n<(int)celldata[d].size(); n++)
+    { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+    fdummy = 1.;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    out.close(); 
+    UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOctsWithCellData to "<<avsfilename<<" - end");
+
+    return avsfilename;
+ }
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+    string avsfilename = filename+getFileExtension();
+    UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOctsWithNodeData to "<<avsfilename<<" - start");
+
+    ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+    if(!out)
+    { 
+       out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+       string path = UbSystem::getPathFromString(avsfilename);
+       if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+       if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden");
+    }
+
+    if((int)nodedata.size()==0) throw UbException(UB_EXARGS,"no nodedata!!!");
+    if(nodes.size()!=nodedata[0].size()) throw UbException(UB_EXARGS,"nodedata != nofNodes!!!");
+
+    char magic = (char)7;
+    int   idummy;
+    float fdummy;
+
+    int nofNodes = (int)nodes.size();
+    int nofCells = (int)cells.size();
+
+    int nofNodeData     = (int)datanames.size();
+    int nofCellData     = 0;
+    int nofModelData    = 0;
+    int cellType        = 7; //=hex
+    int nofNodesPerCell = 8; 
+
+    out.write((char*)&magic,sizeof(char));      
+    out.write((char*)&nofNodes,sizeof(int));    
+    out.write((char*)&nofCells,sizeof(int));    
+    out.write((char*)&nofNodeData,sizeof(int)); 
+    out.write((char*)&nofCellData,sizeof(int)); 
+    out.write((char*)&nofModelData,sizeof(int));
+
+    idummy = (int)nofCells*nofNodesPerCell;
+    out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+       idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+       idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+       idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+    }
+    //knotennummern der einzelnen zellen
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+    }
+
+    //coords
+    //x1-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x2-coords
+    for(int n=0; n<nofNodes; n++)
+       { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x3-coords
+    for(int n=0; n<nofNodes; n++)
+       { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+
+    //NODE DATA
+    char labels[1024];
+    char units[1024];
+    strcpy(labels, "");
+    strcpy(units, "");
+
+    for(int d=0; d<nofNodeData-1; ++d) 
+    { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+    strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+    for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+    strcat(units, "no_unit");
+
+    out.write((char*)&labels,sizeof(labels));
+    out.write((char*)&units,sizeof(units));
+
+    //nof and type of data
+    idummy = nofNodeData;
+    out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+    idummy = 1;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+    //min and max of data
+    fdummy = 0.0;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+    fdummy = 1.0;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    //daten ins file schreiben
+    for(int d=0; d<nofNodeData; ++d)
+       for(int n=0; n<(int)nodedata[d].size(); n++)
+       { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+    fdummy = 1.;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    out.close(); 
+    UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOctsWithNodeData to "<<avsfilename<<" - end");
+
+    return avsfilename;
+ }
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterAvsBinary.h b/source/ThirdParty/Library/basics/writer/WbWriterAvsBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..39a5019e92568ea529aacb257253fc5274a4ae2e
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterAvsBinary.h
@@ -0,0 +1,74 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITERAVSBINARY_H
+#define WBWRITERAVSBINARY_H
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterAvsBinary : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterAvsBinary )
+
+   static WbWriterAvsBinary* getInstance()
+   {
+      static WbWriterAvsBinary instance;
+      return &instance;
+   }
+private:
+   WbWriterAvsBinary() : WbWriter() {}                             
+   WbWriterAvsBinary( const WbWriterAvsBinary& );                  //no copy allowed 
+   const WbWriterAvsBinary& operator=( const WbWriterAvsBinary& ); //no copy allowed
+
+public:
+   std::string getFileExtension() { return ".bin.inp"; }
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                    2
+   //                      
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTuple<int,int,int> >& triangles);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   
+   //////////////////////////////////////////////////////////////////////////
+   //quads
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames, std::vector< std::vector< double > >& celldata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector< std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector< std::vector<double > >& nodedata);
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterAvsBinary ,WbWriter>::getInstance()), CAB_WbWriterAvsBinary);
+
+#endif //WBWRITERAVSBINARY_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterBOBJ.cpp b/source/ThirdParty/Library/basics/writer/WbWriterBOBJ.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..20b1774de592e73bd0bb95d52cffeeacd1431345
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterBOBJ.cpp
@@ -0,0 +1,79 @@
+#ifdef CAB_ZLIB
+   #include <basics/writer/WbWriterBOBJ.h>
+   #include <basics/utilities/UbLogger.h>
+   #include <cstring>
+
+   #include <zlib.h>
+
+
+   using namespace std;
+   /*===============================================================================*/
+   std::string WbWriterBOBJ::writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles)
+   {
+      string bobjFilename=filename+getFileExtension();
+      UBLOG(logDEBUG1,"WbWriterBOBJ::writeTriangles to "<<bobjFilename<<" - start");
+
+      gzFile gzf = gzopen( bobjFilename.c_str(), "wb1" );
+      
+      size_t nofNodes     = nodes.size(); 
+      size_t nofTriangles = triangles.size(); 
+
+      //write to file
+      size_t numVerts;
+      //double v[3];
+      if(sizeof(numVerts)!=4) { throw UbException(UB_EXARGS,"danger..."); }
+      numVerts = nofNodes;
+      gzwrite(gzf, &numVerts, sizeof(numVerts));
+
+      for(size_t k=0; k<nofNodes; k++) {
+         float vertp = val<1>(nodes[k]);
+         gzwrite(gzf, &vertp, sizeof(vertp));
+         vertp       = val<2>(nodes[k]);
+         gzwrite(gzf, &vertp, sizeof(vertp));
+         vertp       = val<3>(nodes[k]);
+         gzwrite(gzf, &vertp, sizeof(vertp));
+      }
+
+      //NORMAL VECTOR
+      //double n[3];
+      gzwrite(gzf, &numVerts, sizeof(numVerts));
+      for(size_t k=0; k<nofNodes; k++) {
+         //poly->GetPointData()->GetNormals()->GetTuple(k, n);
+         float normp = 0.0;//n[0];
+         gzwrite(gzf, &normp, sizeof(normp));
+         normp = 0.0;//n[1];
+         gzwrite(gzf, &normp, sizeof(normp));
+         normp = 0.0;//n[2];
+         gzwrite(gzf, &normp, sizeof(normp));
+      }
+
+      //vtkIdType npts = 3;
+      //vtkIdType* pts;
+      size_t numTris = nofTriangles;
+      gzwrite(gzf, &numTris, sizeof(numTris));
+      for(size_t k=0; k<nofTriangles/*(size_t)poly->GetNumberOfPolys()*/; k++) {
+         //poly->GetPolys()->GetNextCell(npts, pts);
+         //int triIndex = *pts;
+         //gzwrite(gzf, &triIndex, sizeof(triIndex)); 
+         //triIndex = *(pts+1);
+         //gzwrite(gzf, &triIndex, sizeof(triIndex)); 
+         //triIndex = *(pts+2);
+         //gzwrite(gzf, &triIndex, sizeof(triIndex));
+         //poly->GetPolys()->GetNextCell(npts, pts);
+         int triIndex = val<1>(triangles[k]);//*pts;
+         gzwrite(gzf, &triIndex, sizeof(triIndex)); 
+         triIndex     = val<2>(triangles[k]);//*(pts+1);
+         gzwrite(gzf, &triIndex, sizeof(triIndex)); 
+         triIndex     = val<3>(triangles[k]);//*(pts+2);
+         gzwrite(gzf, &triIndex, sizeof(triIndex));
+      }
+
+      gzclose( gzf );
+
+      UBLOG(logDEBUG1,"WbWriterBOBJ::writeTriangles to "<<bobjFilename<<" - end");
+
+      return bobjFilename;
+   }
+   /*===============================================================================*/
+
+#endif //CAB_ZLIB
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterBOBJ.h b/source/ThirdParty/Library/basics/writer/WbWriterBOBJ.h
new file mode 100644
index 0000000000000000000000000000000000000000..fec3454c3d4cbafb5d360c37f99a3a847f052dec
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterBOBJ.h
@@ -0,0 +1,40 @@
+#ifdef CAB_ZLIB
+   #ifndef WBWRITERBOBJ_H
+   #define WBWRITERBOBJ_H
+
+   #include <string>
+   #include <basics/writer/WbWriter.h>
+
+   class WbWriterBOBJ  : public WbWriter
+   {
+   public:
+      OBCREATOR_EXT( WbWriterBOBJ )
+
+         static WbWriterBOBJ* getInstance()
+      {
+         static WbWriterBOBJ instance;
+         return &instance;
+      }
+   private:
+      WbWriterBOBJ() : WbWriter() 
+      {
+         if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+         if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+         if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+      }
+      WbWriterBOBJ( const WbWriterBOBJ& );                  //no copy allowed 
+      const WbWriterBOBJ& operator=( const WbWriterBOBJ& ); //no copy allowed
+
+      static std::string  pvdEndTag;
+
+   public:
+      std::string getFileExtension()  { return "BOBJ.gz"; }
+
+      std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+   };
+
+   UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterBOBJ ,WbWriter>::getInstance()), CAB_WbWriterVtkXmlASCII);
+
+   #endif //WBWRITERBOBJ_H
+
+#endif //CAB_ZLIB
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterSunflow.cpp b/source/ThirdParty/Library/basics/writer/WbWriterSunflow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4fa1a6381babc0837a2f3c65c576cfe76b75431c
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterSunflow.cpp
@@ -0,0 +1,112 @@
+#include <basics/writer/WbWriterSunflow.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+/*===============================================================================*/
+std::string WbWriterSunflow::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string sunflowFilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterSunflow::writeTriangles to "<<sunflowFilename<<" - start");
+
+   std::ofstream out(sunflowFilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(sunflowFilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(sunflowFilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+sunflowFilename);
+   }
+
+   // General part
+
+   // Image details
+   out<<"image {"              <<endl;
+   out<<"   resolution 640 480"<<endl;
+   out<<"   aa 0 1"            <<endl;
+   out<<"   filter mitchell"   <<endl;
+   out<<"}"                    <<endl<<endl;
+
+   // Camera position
+   out<<"camera {"                 <<endl;
+   out<<"   type pinhole"          <<endl;
+   out<<"   eye    -0.25 -0.3 0.13"<<endl;
+   out<<"   target -0.1 0.1 0.13"  <<endl;
+   out<<"   up     0 0 1"          <<endl;
+   out<<"   fov    60"             <<endl;
+   out<<"   aspect 1.333333"       <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   // Light
+   out<<"light {"                  <<endl;
+   out<<"   type ibl"              <<endl;
+   out<<"   image sky_small.hdr"   <<endl;
+   out<<"   center 0 -1 0"         <<endl;
+   out<<"   up 0 0 1"              <<endl;
+   out<<"   lock true"             <<endl;
+   out<<"   samples 200"           <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   // Shaders
+   out<<"shader {"                 <<endl;
+   out<<"   name default-shader"   <<endl;
+   out<<"   type diffuse"          <<endl;
+   out<<"   diff 0.25 0.25 0.25"   <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   out<<"shader {"                 <<endl;
+   out<<"   name Glass"            <<endl;
+   out<<"   type glass"            <<endl;
+   out<<"   eta 1.333"             <<endl;
+   out<<"   color 0.1 0.3 0.8"     <<endl;
+   out<<"}"                        <<endl<<endl;
+                                   
+   out<<"shader {"                 <<endl;
+   out<<"   name Mirror"           <<endl;
+   out<<"   type mirror"           <<endl;
+   out<<"   refl 0.7 0.7 0.7"      <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   // Objects
+   // a) Ground plane
+   out<<"object {"                 <<endl;
+   out<<"   shader default-shader" <<endl;
+   out<<"   type plane"            <<endl;
+   out<<"   p 0 0 0"               <<endl;
+   out<<"   n 0 0 1"               <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   // b) Mesh
+   out<<"object {"                 <<endl;
+   out<<"   shader Glass"          <<endl;
+   out<<"   transform {"           <<endl;
+   out<<"      rotatey 270.0"      <<endl;
+   out<<"   }"                     <<endl;
+   out<<"   type generic-mesh"     <<endl;
+   out<<"      name polySurfac"    <<endl<<endl;
+
+
+   // POINTS SECTION
+   int nofNodes = (int)nodes.size(); 
+   out<<"   points "<<nofNodes<<endl;
+   for(int n=0; n<nofNodes; n++)
+      out<<"      "<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<endl;
+
+   // TRIANGLES SECTION
+   int nofTriangles= (int)triangles.size(); 
+   out<<"   triangles "<<nofTriangles<<endl;
+   for(int c=0; c<nofTriangles; c++)
+      out<<"      "<<val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<endl;
+
+   // FOOTER
+   out<<"   normals none" << endl;
+   out<<"   uvs none"     << endl;
+   out<<"}"               << endl;
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterSunflow::writeTriangles to "<<sunflowFilename<<" - end");
+
+   return sunflowFilename;
+}
+/*===============================================================================*/
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterSunflow.h b/source/ThirdParty/Library/basics/writer/WbWriterSunflow.h
new file mode 100644
index 0000000000000000000000000000000000000000..5681eac73dc63a24c703120bb58821312aab2090
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterSunflow.h
@@ -0,0 +1,38 @@
+#ifndef WbWriterSunflow_H
+#define WbWriterSunflow_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterSunflow  : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterSunflow )
+
+   static WbWriterSunflow* getInstance()
+   {
+      static WbWriterSunflow instance;
+      return &instance;
+   }
+private:
+   WbWriterSunflow() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+   }
+   WbWriterSunflow( const WbWriterSunflow& );                  //no copy allowed 
+   const WbWriterSunflow& operator=( const WbWriterSunflow& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+
+public:
+   std::string getFileExtension()  { return "ascii.sunflow"; }
+
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterSunflow ,WbWriter>::getInstance()), CAB_WbWriterSunflow);
+
+#endif //WbWriterSunflow_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterTecPlotASCII.cpp b/source/ThirdParty/Library/basics/writer/WbWriterTecPlotASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b2f83ef59c09e5d9b00b15b90c3d166042444f6a
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterTecPlotASCII.cpp
@@ -0,0 +1,68 @@
+#include <basics/writer/WbWriterTecPlotASCII.h>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+
+/*===============================================================================*/
+string WbWriterTecPlotASCII::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+   string tecplotfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterTecPlotASCII::writeOctsWithNodeData to "<<tecplotfilename<<" - start");
+
+   ofstream out(tecplotfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(tecplotfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(tecplotfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+tecplotfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"TITLE = VirtualFluids OctGrid from "<<UbSystem::getTimeStamp()<<endl;
+
+   out<<"VARIABLES = \"X\", \"Y\", \"Z\"";
+   for(size_t d=0; d<datanames.size(); d++)   
+      out<<", \""<<datanames[d]<<"\"";
+   out<<endl;
+
+   out<<"ZONE NODES="<<nofNodes<<", ELEMENTS="<<nofCells<<", DATAPACKING=POINT, ZONETYPE=FEBRICK"<<endl;
+   for(size_t n=0; n<nodes.size(); n++)   
+   {
+      UbTupleFloat3& coords = nodes[n];
+      out<<val<1>(coords)<<" "
+         <<val<2>(coords)<<" "
+         <<val<3>(coords);
+      for(size_t d=0; d<datanames.size(); d++)   
+         out<<" "<<nodedata[d][n];
+      out<<endl;
+   }
+
+   for(size_t c=0; c<cells.size(); c++)   
+   {
+      UbTupleInt8& cell = cells[c];
+      out<<val<1>(cell)<<" "
+         <<val<2>(cell)<<" "
+         <<val<3>(cell)<<" "
+         <<val<4>(cell)<<" "
+         <<val<5>(cell)<<" "
+         <<val<6>(cell)<<" "
+         <<val<7>(cell)<<" "
+         <<val<8>(cell)<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterTecPlotASCII::writeOctsWithNodeData to "<<tecplotfilename<<" - end");
+
+   return tecplotfilename;
+}
+/*===============================================================================*/
+string WbWriterTecPlotASCII::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   vector<string > datanames;
+   vector<vector<double > > nodedata;
+   return writeOctsWithNodeData(filename,nodes,cells,datanames,nodedata);
+}
+/*===============================================================================*/
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterTecPlotASCII.h b/source/ThirdParty/Library/basics/writer/WbWriterTecPlotASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff50c9c928d3636c0a894a77c5e2d523fb88be86
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterTecPlotASCII.h
@@ -0,0 +1,95 @@
+#ifndef WBWRITERTECPLOTASCII_H
+#define WBWRITERTECPLOTASCII_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterTecPlotASCII  : public WbWriter
+{
+public:
+   #ifndef SWIG
+   OBCREATOR_EXT( WbWriterTecPlotASCII )
+   #endif
+
+   static WbWriterTecPlotASCII* getInstance()
+   {
+      static WbWriterTecPlotASCII instance;
+      return &instance;
+   }
+private:
+   WbWriterTecPlotASCII() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"machine error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"machine error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"machine error float type mismatch");
+   }
+
+   WbWriterTecPlotASCII( const WbWriterTecPlotASCII& );                  //no copy allowed 
+   const WbWriterTecPlotASCII& operator=( const WbWriterTecPlotASCII& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+public:
+   std::string getFileExtension() { return ".ascii.dat";   }
+
+   //write a metafile 
+//    std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+//    std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+//    std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames);
+
+   //////////////////////////////////////////////////////////////////////////
+   //nodes
+//    std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes);
+//    std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+//    std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+//    std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+// 
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+//    std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+//    std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+
+//    std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+//    std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+//    std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+//    std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+//                                              std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+//                                              std::vector< std::vector< double > >& celldata                                                                    );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   //std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+   
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterTecPlotASCII ,WbWriter>::getInstance()), CAB_WbWriterTecPlotASCII);
+#endif
+
+#endif //WBWRITERTECPLOTASCII_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterVtkASCII.cpp b/source/ThirdParty/Library/basics/writer/WbWriterVtkASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0356f38fa155525ac929c81a7117acba2ffbd0bc
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterVtkASCII.cpp
@@ -0,0 +1,601 @@
+#include <basics/writer/WbWriterVtkASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+std::string WbWriterVtkASCII::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuads to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+   
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<5*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"4 "
+         << val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"8"<<endl;
+   out<<endl;
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuads to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+ 
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<5*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"4 "
+      << val<1>(cells[c]) <<" "
+      << val<2>(cells[c]) <<" "
+      << val<4>(cells[c]) <<" "
+      << val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"8"<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<"\n";
+      
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<5*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"4 "
+      << val<1>(cells[c]) <<" "
+      << val<2>(cells[c]) <<" "
+      << val<4>(cells[c]) <<" "
+      << val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"8"<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                            vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                            vector< vector< double > >& celldata                                                                       )
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<5*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"4 "
+         << val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"8"<<endl;
+   out<<endl;
+
+   //write node data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)nodedatanames.size(); ++s)
+   {
+      out<<"SCALARS "<<nodedatanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   //write cell data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)celldatanames.size(); ++s)
+   {
+      out<<"SCALARS "<<celldatanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines) 
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeLines to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+   
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n])<<" \n";
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofLines<<" "<<3*nofLines<<"\n";
+   int nr = 0;
+   for(int l=0; l<nofLines; l++)
+   {
+      int el = nr+1;	
+      out<<"2 "<< val<1>(lines[l]) <<" "<< val<2>(lines[l]) <<" "<<endl;
+      nr=el+1;
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofLines<<"\n";
+   for(int l=0; l<nofLines; l++) out<<"3"<<endl;
+   out<<endl;
+
+   out.close();
+   
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeLines to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeTriangles to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes     = (int)nodes.size(); 
+   int nofTriangles = (int)triangles.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n])<<" \n";
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofTriangles<<" "<<4*nofTriangles<<"\n";
+   int nr = 0;
+   for(int t=0; t<nofTriangles; t++)
+   {
+      int el = nr+1;	
+      out<<"3 "<< val<1>(triangles[t]) <<" "<< val<2>(triangles[t]) <<" "<< val<3>(triangles[t]) <<" "<<endl;
+      nr=el+1;
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofTriangles<<"\n";
+   for(int l=0; l<nofTriangles; l++) out<<"5"<<endl;
+   out<<endl;
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeTriangles to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeTrianglesWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt3 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<4*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"3 "<< val<1>(cells[c]) <<" "<< val<2>(cells[c]) <<" "<< val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"5"<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeOctsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOctsWithCellData to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<9*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+   {   out<<"8 "
+         << val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<" \n";
+   }
+
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"11 "<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOctsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeOctsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<9*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+   {   out<<"8 "
+         << val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<" \n";
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"11"<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOcts to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<9*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"8 "
+      << val<1>(cells[c]) <<" "
+      << val<2>(cells[c]) <<" "
+      << val<4>(cells[c]) <<" "
+      << val<3>(cells[c]) <<" "
+      << val<5>(cells[c]) <<" "
+      << val<6>(cells[c]) <<" "
+      << val<8>(cells[c]) <<" "
+      << val<7>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"11"<<endl;
+   out<<endl;
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOcts to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterVtkASCII.h b/source/ThirdParty/Library/basics/writer/WbWriterVtkASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..914ab2cab9a37ace767e9fd389c79401d12c5a8a
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterVtkASCII.h
@@ -0,0 +1,78 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITERVTKASCII_H
+#define WBWRITERVTKASCII_H
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterVtkASCII : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterVtkASCII )
+
+   static WbWriterVtkASCII* getInstance()
+   {
+      static WbWriterVtkASCII instance;
+      return &instance;
+   }
+private:
+   WbWriterVtkASCII() : WbWriter() {}                            
+   WbWriterVtkASCII( const WbWriterVtkASCII& );                  //no copy allowed 
+   const WbWriterVtkASCII& operator=( const WbWriterVtkASCII& ); //no copy allowed
+
+public:
+   std::string getFileExtension()  { return ".ascii.vtk"; }
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                             std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                             std::vector< std::vector< double > >& celldata                                                                       );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsBinary(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterVtkASCII,WbWriter>::getInstance()), CAB_WbWriterVtkASCII);
+
+#endif //WBWRITERVTKASCII_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterVtkBinary.cpp b/source/ThirdParty/Library/basics/writer/WbWriterVtkBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f766fa402236f3fa47a218a54e3187fb3b3a9fb0
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterVtkBinary.cpp
@@ -0,0 +1,747 @@
+#include <basics/writer/WbWriterVtkBinary.h>
+#include <basics/writer/WbWriterVtkASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+std::string WbWriterVtkBinary::writeLines(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines)
+{
+   return WbWriterVtkASCII::getInstance()->writeLines(filename,nodes,lines);
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells)
+{
+   return WbWriterVtkASCII::getInstance()->writeTriangles(filename,nodes,cells);
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   return WbWriterVtkASCII::getInstance()->writeTrianglesWithNodeData(filename,nodes,cells,datanames,nodedata);
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuads to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //HEADER-SECTION
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*5<<"\n";
+
+   int nodesPerCellDummy = 4;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int SW = val<1>(cells[c]); 
+      int SE = val<2>(cells[c]); 
+      int NE = val<3>(cells[c]);
+      int NW = val<4>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&SW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&SE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&SW,sizeof(int));
+      out.write((char*)&SE,sizeof(int));
+      out.write((char*)&NW,sizeof(int));
+      out.write((char*)&NE,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 8;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuads to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*5<<"\n";
+
+   int nodesPerCellDummy = 4;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int SW = val<1>(cells[c]); 
+      int SE = val<2>(cells[c]); 
+      int NE = val<3>(cells[c]);
+      int NW = val<4>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&SW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&SE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&SW,sizeof(int));
+      out.write((char*)&SE,sizeof(int));
+      out.write((char*)&NW,sizeof(int));
+      out.write((char*)&NE,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 8;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //DATA SECTION
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      if((int)nodedata[s].size() != nofNodes) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      { 
+         float dummy = (float)nodedata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   //HEADER-SECTION
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*5<<"\n";
+
+   int nodesPerCellDummy = 4;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int SW = val<1>(cells[c]); 
+      int SE = val<2>(cells[c]); 
+      int NE = val<3>(cells[c]);
+      int NW = val<4>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&SW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&SE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&SW,sizeof(int));
+      out.write((char*)&SE,sizeof(int));
+      out.write((char*)&NW,sizeof(int));
+      out.write((char*)&NE,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 8;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //DATA SECTION
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      if((int)celldata[s].size() != nofCells) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+      { 
+         float dummy = (float)celldata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                             vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                             vector< vector< double > >& celldata                                                                    )
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //HEADER-SECTION
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]);  
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*5<<"\n";
+
+   int nodesPerCellDummy = 4;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int SW = val<1>(cells[c]); 
+      int SE = val<2>(cells[c]); 
+      int NE = val<3>(cells[c]);
+      int NW = val<4>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&SW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&SE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&SW,sizeof(int));
+      out.write((char*)&SE,sizeof(int));
+      out.write((char*)&NW,sizeof(int));
+      out.write((char*)&NE,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 8;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //NODE DATA SECTION
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)nodedatanames.size(); ++s)
+   {
+      if((int)nodedata[s].size() != nofNodes) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<nodedatanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      { 
+         float dummy = (float)nodedata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+   
+   //CELL DATA SECTION
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)celldatanames.size(); ++s)
+   {
+      if((int)celldata[s].size() != nofCells) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<celldatanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+      { 
+         float dummy = (float)celldata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata)
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOctsWithCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //HEADER-SECTION
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]);
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*9<<"\n";
+
+   int nodesPerCellDummy = 8;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int BSW = val<1>(cells[c]);  int TSW = val<5>(cells[c]);
+      int BSE = val<2>(cells[c]);  int TSE = val<6>(cells[c]);
+      int BNW = val<3>(cells[c]);  int TNW = val<7>(cells[c]);
+      int BNE = val<4>(cells[c]);  int TNE = val<8>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&BSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&BSW,sizeof(int));
+      out.write((char*)&BSE,sizeof(int));
+      out.write((char*)&BNE,sizeof(int));
+      out.write((char*)&BNW,sizeof(int));
+      out.write((char*)&TSW,sizeof(int));
+      out.write((char*)&TSE,sizeof(int));
+      out.write((char*)&TNE,sizeof(int));
+      out.write((char*)&TNW,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 11;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //CELL DATA SECTION
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      if((int)celldata[s].size() != nofCells) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+      { 
+         float dummy = (float)celldata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOctsWithCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+   //HEADER-SECTION
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = val<1>(nodes[n]); 
+      float x2 = val<2>(nodes[n]); 
+      float x3 = val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*9<<"\n";
+
+   int nodesPerCellDummy = 8;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int BSW = val<1>(cells[c]);  int TSW = val<5>(cells[c]);
+      int BSE = val<2>(cells[c]);  int TSE = val<6>(cells[c]);
+      int BNW = val<3>(cells[c]);  int TNW = val<7>(cells[c]);
+      int BNE = val<4>(cells[c]);  int TNE = val<8>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&BSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&BSW,sizeof(int));
+      out.write((char*)&BSE,sizeof(int));
+      out.write((char*)&BNE,sizeof(int));
+      out.write((char*)&BNW,sizeof(int));
+      out.write((char*)&TSW,sizeof(int));
+      out.write((char*)&TSE,sizeof(int));
+      out.write((char*)&TNE,sizeof(int));
+      out.write((char*)&TNW,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 11;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //NODE DATA SECTION
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      if((int)nodedata[s].size() != nofNodes) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      { 
+         float dummy = (float)nodedata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOcts to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //HEADER-SECTION
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = val<1>(nodes[n]); 
+      float x2 = val<2>(nodes[n]); 
+      float x3 = val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*9<<"\n";
+
+   int nodesPerCellDummy = 8;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int BSW = val<1>(cells[c]);  int TSW = val<5>(cells[c]);
+      int BSE = val<2>(cells[c]);  int TSE = val<6>(cells[c]);
+      int BNW = val<3>(cells[c]);  int TNW = val<7>(cells[c]);
+      int BNE = val<4>(cells[c]);  int TNE = val<8>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&BSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNE,sizeof(int));
+      }
+
+       out.write((char*)&nodesPerCellDummy,sizeof(int));
+       out.write((char*)&BSW,sizeof(int));
+       out.write((char*)&BSE,sizeof(int));
+       out.write((char*)&BNE,sizeof(int));
+       out.write((char*)&BNW,sizeof(int));
+       out.write((char*)&TSW,sizeof(int));
+       out.write((char*)&TSE,sizeof(int));
+       out.write((char*)&TNE,sizeof(int));
+       out.write((char*)&TNW,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 11;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOcts to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterVtkBinary.h b/source/ThirdParty/Library/basics/writer/WbWriterVtkBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..dca3567d3505e0bea3c549ab601cb478c0bb17ed
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterVtkBinary.h
@@ -0,0 +1,77 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITERVTKBINARY_H
+#define WBWRITERVTKBINARY_H
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterVtkBinary : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterVtkBinary )
+
+   static WbWriterVtkBinary* getInstance()
+   {
+      static WbWriterVtkBinary instance;
+      return &instance;
+   }
+private:
+   WbWriterVtkBinary() : WbWriter() {}                             
+   WbWriterVtkBinary( const WbWriterVtkBinary& );                  //no copy allowed 
+   const WbWriterVtkBinary& operator=( const WbWriterVtkBinary& ); //no copy allowed
+
+public:
+   std::string getFileExtension() { return ".bin.vtk"; }
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                             std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                             std::vector< std::vector< double > >& celldata                                                                    );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterVtkBinary ,WbWriter>::getInstance()), CAB_WbWriterVtkBinary);
+
+#endif //WBWRITERVTKBINARY_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlASCII.cpp b/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a5e5fdf7cf9d5550046fb66dfc0250de23a797d0
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlASCII.cpp
@@ -0,0 +1,1188 @@
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::pvdEndTag ="   </Collection>\n</VTKFile>";
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   std::string vtkfilename=filename+".pvd";
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   std::string endian;
+   if(UbSystem::isLittleEndian()) endian = "LittleEndian";
+   else                           endian = "BigEndian";
+   out<<"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\""<<endian<<"\" >\n";
+   out<<"   <Collection>"<<endl;
+   
+   int group = 0, part=0;
+   for(std::size_t i=0; i<filenames.size(); i++)
+   {
+      out<<"       <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<part<<"\" file=\""<<filenames[i]<<"\"/>\n";
+      if(sepGroups) group++;
+      else          part++;
+   }
+   out<<pvdEndTag;
+   out.close();
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   std::string vtkfilename=filename;
+   std::fstream test(vtkfilename.c_str(), ios::in);
+   if(!test)
+   {
+      test.clear();
+      vtkfilename += ".pvd";
+      test.open(vtkfilename.c_str(), ios::in);
+      if(!test) return this->writeCollection(filename,filenames,timeStep,sepGroups);
+   }
+
+   std::fstream out(vtkfilename.c_str(), ios::in | ios::out);
+   out.seekp(-(int)pvdEndTag.size()-1, ios_base::end);
+
+   int group = 0;
+   for(std::size_t i=0; i<filenames.size(); i++)
+   {
+      out<<"       <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<i<<"\" file=\""<<filenames[i]<<"\"/>\n";
+      if(sepGroups) group++;
+   }
+   out<<pvdEndTag;
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeParallelFile(const string& filename,vector<string>& pieceSources, vector<string>& pointDataNames, vector<string>& cellDataNames)
+{
+   string vtkfilename=filename+".pvtu";
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeParallelFile to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //VTK FILE
+   out<<"<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
+   out<<"  <PUnstructuredGrid GhostLevel=\"0\">\n";
+   out<<"    <PPoints>\n"; 
+   out<<"      <PDataArray type=\"Float32\" NumberOfComponents=\"3\"/>\n";
+   out<<"    </PPoints>\n";
+   out<<"    <PPointData>\n";
+   for(size_t s=0; s<pointDataNames.size(); s++)
+      out<< "      <PDataArray type=\"Float32\" Name=\""<< pointDataNames[s] <<"\"/>\n";
+   out<<"    </PPointData>\n";
+   if (cellDataNames.size() > 0)
+   {
+      out<<"    <PCellData>\n";
+      for(size_t s=0; s<cellDataNames.size(); s++)
+         out<< "      <PDataArray type=\"Float32\" Name=\""<< cellDataNames[s] <<"\"/>\n";
+      out<<"    </PCellData>\n";
+   }
+
+   for(size_t s=0; s<pieceSources.size(); s++)
+      out<<"    <Piece Source=\""<<pieceSources[s]<<"\"/>\n";
+   out<<"  </PUnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeParallelFile to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuads to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*4<<" " ;
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"8 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuads to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*4<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"8 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+    }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*4<<" " ;
+
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"8 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <CellData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </CellData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                          vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                          vector< vector< double > >& celldata                                                                       )
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*4<<" " ;
+
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"8 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+   
+   //write PointData section
+   out<<"         <PointData Scalars=\"PScalars\"> \n";
+   for(int s=0; s<(int)nodedatanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< nodedatanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+
+   //write celldata section
+   out<<"         <CellData Scalars=\"CScalars\"> \n";
+   for(int s=0; s<(int)celldatanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< celldatanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </CellData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines) 
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofLines<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofLines; c++)
+      out<< val<1>(lines[c]) <<" "<< val<2>(lines[c])<<"  ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int c=1; c<=nofLines; c++)
+      out<<c*2<<" " ;
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofLines; c++)
+      out<<"3 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeLinesWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLinesWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofLines<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofLines; c++)
+      out<< val<1>(lines[c]) <<" "<< val<2>(lines[c])<<"  ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int c=1; c<=nofLines; c++)
+      out<<c*2<<" " ;
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofLines; c++)
+      out<<"3 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLinesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTriangles to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofTriangles= (int)triangles.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofTriangles<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofTriangles; c++)
+      out<< val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<"  ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int c=1; c<nofTriangles+1; c++)
+      out<<c*3<<" " ;
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofTriangles; c++)
+      out<<"5 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTriangles to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "<< val<2>(cells[c]) <<" "<< val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*3<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"5 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeOctsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<"  ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*8<<" " ;
+
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"11 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+   
+
+   //write data section
+   out<<"         <CellData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </CellData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeOctsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<<val<1>(nodes[n])<<" "<<val<2>(nodes[n])<<" "<<val<3>(nodes[n])<<" ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<"  ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*8<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"11 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write PointData section
+   out<<"         <PointData Scalars=\"PScalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\">";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      {
+         //out<<base64_encode((unsigned char*)(&nodedata[s][d]),sizeof(float));
+         //out.write((char*)&nodedata[s][d],sizeof(float));
+         out<<nodedata[s][d]<<" ";
+      }
+      out<<"</DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOcts to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*8<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"11 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOcts to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbWriterVtkXmlASCII::writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofNodes<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< n << "  ";
+   out<<"\n";
+
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int n=1; n<=nofNodes; n++)
+      out << n << " ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int n=0; n<nofNodes; n++)
+      out<<"1 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbWriterVtkXmlASCII::writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofNodes<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofNodes; c++)
+      out << c <<"   ";
+   out<<"\n";
+
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofNodes+1; c++)
+      out<<c<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+   for(int c=0; c<nofNodes; c++)
+      out<<"1 ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+
+//////////////////////////////////////////////////////////////////////////
+std::string WbWriterVtkXmlASCII::writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   out.precision (std::numeric_limits<double>::digits10 + 1);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofNodes<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofNodes; c++)
+      out << c <<"   ";
+   out<<"\n";
+
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int64\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofNodes+1; c++)
+      out<<c<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+   for(int c=0; c<nofNodes; c++)
+      out<<"1 ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float64\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlASCII.h b/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..84212bd509f14768427a5792717b907e4e90601c
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlASCII.h
@@ -0,0 +1,101 @@
+#ifndef WBWRITERVTKXMLASCII_H
+#define WBWRITERVTKXMLASCII_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+#include <boost/serialization/base_object.hpp>
+
+class WbWriterVtkXmlASCII  : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterVtkXmlASCII )
+
+   static WbWriterVtkXmlASCII* getInstance()
+   {
+      static WbWriterVtkXmlASCII instance;
+      return &instance;
+   }
+private:
+   WbWriterVtkXmlASCII() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+   }
+   WbWriterVtkXmlASCII( const WbWriterVtkXmlASCII& );                  //no copy allowed 
+   const WbWriterVtkXmlASCII& operator=( const WbWriterVtkXmlASCII& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+
+public:
+   std::string getFileExtension()  { return ".ascii.vtu"; }
+
+   //write a metafile 
+   std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timesteps, const bool& sepGroups);//std::vector<double>& groups, std::vector<double>& parts);
+   std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+   std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames);
+
+   //////////////////////////////////////////////////////////////////////////
+   //nodes
+   std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes);
+   std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+   std::string writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+   std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                             std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                             std::vector< std::vector< double > >& celldata                                                                       );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<WbWriter>(*this);
+   }
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterVtkXmlASCII ,WbWriter>::getInstance()), CAB_WbWriterVtkXmlASCII);
+
+#endif //WBWRITERVTKXMLASCII_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlBinary.cpp b/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d3d9dbf790dee6b6eca2eeb78135fcf877961f3
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlBinary.cpp
@@ -0,0 +1,1582 @@
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::pvdEndTag ="   </Collection>\n</VTKFile>";
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeCollection(const string& filename, const vector<string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   string vtkfilename=filename+".pvd";
+   ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   string endian;
+   if(UbSystem::isLittleEndian()) endian = "LittleEndian";
+   else                           endian = "BigEndian";
+   out<<"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\""<<endian<<"\" >"<<endl;
+   out<<"   <Collection>"<<endl;
+   
+   int group = 0, part=0;
+   for(size_t i=0; i<filenames.size(); i++)
+   {
+      out<<"       <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<part<<"\" file=\""<<filenames[i]<<"\"/>"<<endl;
+      if(sepGroups) group++;
+      else          part++;
+   }
+   out<<pvdEndTag;
+   out.close();
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::addFilesToCollection(const string& filename, const vector<string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   string vtkfilename=filename;
+   fstream test(vtkfilename.c_str(), ios::in);
+   if(!test)
+   {
+      test.clear();
+      vtkfilename += ".pvd";
+      test.open(vtkfilename.c_str(), ios::in);
+      if(!test) return this->writeCollection(filename,filenames,timeStep,sepGroups);
+   }
+ 
+   fstream out(vtkfilename.c_str(), ios::in | ios::out);
+   out.seekp(-(int)pvdEndTag.size()-1, ios_base::end);
+
+   int group = 0;
+   for(size_t i=0; i<filenames.size(); i++)
+   {
+      out<<"       <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<i<<"\" file=\""<<filenames[i]<<"\"/>"<<endl;
+      if(sepGroups) group++;
+   }
+   out<<pvdEndTag;
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeParallelFile(const string& filename,vector<string>& pieceSources, vector<string>& pointDataNames, vector<string>& cellDataNames)
+{
+   string vtkfilename=filename+".pvtu";
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeParallelFile to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //VTK FILE
+   out<<"<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">"<<"\n";
+   out<<"  <PUnstructuredGrid GhostLevel=\"0\">"<<"\n";
+   out<<"    <PPoints>\n"; 
+   out<<"      <PDataArray type=\"Float32\" NumberOfComponents=\"3\"/>\n";
+   out<<"    </PPoints>\n";
+   out<<"    <PPointData>\n";
+   for(size_t s=0; s<pointDataNames.size(); s++)
+      out<< "      <PDataArray type=\"Float32\" Name=\""<< pointDataNames[s] <<"\"/>\n";
+   out<<"    </PPointData>\n";
+   if (cellDataNames.size() > 0)
+   {
+      out<<"    <PCellData>\n";
+      for(size_t s=0; s<cellDataNames.size(); s++)
+         out<< "      <PDataArray type=\"Float32\" Name=\""<< cellDataNames[s] <<"\"/>\n";
+      out<<"    </PCellData>\n";
+   }
+
+   for(size_t s=0; s<pieceSources.size(); s++)
+      out<<"    <Piece Source=\""<<pieceSources[s]<<"\"/>\n";
+   out<<"  </PUnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeParallelFile to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLines to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)lines.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 2 /*nodes per line */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per line */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of line */ * nofCells * sizeof(unsigned char);
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(lines[c]), sizeof(int) );
+      out.write( (char*)&val<2>(lines[c]), sizeof(int) );
+      
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 2 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 3;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLines to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlBinary::writeLinesWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLinesWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)lines.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 2 /*nodes per line  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per line */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of line    */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(lines[c]), sizeof(int) );
+      out.write( (char*)&val<2>(lines[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 3 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 5;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLinesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTriangles to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)triangles.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3 - coord    */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 3 /*nodes per triangle  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per triangle */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of triangle    */ * nofCells * sizeof(unsigned char);
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(triangles[c]), sizeof(int) );
+      out.write( (char*)&val<2>(triangles[c]), sizeof(int) );
+      out.write( (char*)&val<3>(triangles[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 3 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 5;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out<<flush;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTriangles to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeTrianglesWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt3 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTrianglesWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 3 /*nodes per tri   */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per tri  */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of tri     */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float); 
+   
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 3 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 5;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTrianglesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuads to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 4 /*nodes per quad  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
+  
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 4 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 8;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out<<flush;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuads to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 4 /*nodes per quad  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 4 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 8;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 4 /*nodes per quad  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar          */ * nofCells * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <CellData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </CellData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 4 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 8;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<celldata[s].size(); ++d)
+      {
+         //loake kopie machen, da in celldata "doubles" sind
+         float tmp = (float)celldata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+
+   out<<"\n</AppendedData>\n";
+
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                                vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                                vector< vector< double > >& celldata                                                                    )
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 4 /*nodes per quad  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
+   int bytesScalarDataPoint = 1 /*scalar          */ * nofNodes * sizeof(float); 
+   int bytesScalarDataCell  = 1 /*scalar          */ * nofCells * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   // Point DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<nodedatanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< nodedatanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarDataPoint);
+   }
+   out<<"         </PointData>\n";
+
+
+   // Cell DATA SECTION
+   out<<"         <CellData>\n";
+   for(size_t s=0; s<celldatanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< celldatanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarDataCell);
+   }
+   out<<"         </CellData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 4 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 8;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //Point DATA SECTION
+   //scalarData
+   for(size_t s=0; s<nodedatanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarDataPoint,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   //Cell DATA SECTION
+   //scalarData
+   for(size_t s=0; s<celldatanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarDataCell,bytesPerByteVal);
+      for(size_t d=0; d<celldata[s].size(); ++d)
+      {
+         //loake kopie machen, da in celldata "doubles" sind
+         float tmp = (float)celldata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3      */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per oct*/ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of oct   */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar        */ * nofCells * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <CellData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </CellData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<5>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<6>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<8>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<7>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 8 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 11;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<celldata[s].size(); ++d)
+      {
+         //loake kopie machen, da in celldata "doubles" sind
+         float tmp = (float)celldata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3      */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per oct*/ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of oct   */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar        */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<5>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<6>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<8>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<7>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 8 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 11;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOcts to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3      */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per oct*/ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of oct   */ * nofCells * sizeof(unsigned char);
+   //int bytesScalarData      = 1 /*scalar        */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<5>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<6>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<8>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<7>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 8 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 11;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOcts to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbWriterVtkXmlBinary::writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodes to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 1 /*nodes per cell  */ * nofNodes * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per cell */ * nofNodes * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of line    */ * nofNodes * sizeof(unsigned char);
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofNodes; c++) 
+      out.write( (char*)&c, sizeof(int) );
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   for(int c=1; c<=nofNodes; c++)
+      out.write( (char*)&c, sizeof(int) );
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 1;
+   for(int c=0; c<nofNodes; c++)
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodes to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbWriterVtkXmlBinary::writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodesWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3       */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 1 /*nodes per cell */ * nofNodes * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per cell*/ * nofNodes * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of oct    */ * nofNodes * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar         */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofNodes; c++) 
+      out.write( (char*)&c, sizeof(int) );
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   for(int c=1; c<=nofNodes; c++)
+      out.write( (char*)&c, sizeof(int) );
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 1;
+   for(int c=0; c<nofNodes; c++)
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+
+}
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlBinary.h b/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..b00157fed2b38826b31375e6ffa459eda1b1483b
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterVtkXmlBinary.h
@@ -0,0 +1,104 @@
+#ifndef WBWRITERVTKXMLBINARY_H
+#define WBWRITERVTKXMLBINARY_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+#include <boost/serialization/base_object.hpp>
+
+class WbWriterVtkXmlBinary  : public WbWriter
+{
+public:
+#ifndef SWIG
+   OBCREATOR_EXT( WbWriterVtkXmlBinary )
+#endif
+
+   static WbWriterVtkXmlBinary* getInstance()
+   {
+      static WbWriterVtkXmlBinary instance;
+      return &instance;
+   }
+private:
+   WbWriterVtkXmlBinary() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"machine error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"machine error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"machine error float type mismatch");
+   }
+
+   WbWriterVtkXmlBinary( const WbWriterVtkXmlBinary& );                  //no copy allowed 
+   const WbWriterVtkXmlBinary& operator=( const WbWriterVtkXmlBinary& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+public:
+   std::string getFileExtension() { return ".bin.vtu";   }
+
+   //write a metafile 
+   std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+   std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+   std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames);
+
+   //////////////////////////////////////////////////////////////////////////
+   //nodes
+   std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes);
+   std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+   std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                             std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                             std::vector< std::vector< double > >& celldata                                                                    );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+   
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<WbWriter>(*this);
+   }
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterVtkXmlBinary ,WbWriter>::getInstance()), CAB_WbWriterVtkXmlBinary);
+#endif
+
+#endif //WBWRITERVTKXMLBINARY_H
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterX3D.cpp b/source/ThirdParty/Library/basics/writer/WbWriterX3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..68eee613779233c44dbb0cf6c501c564a0bfdab2
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterX3D.cpp
@@ -0,0 +1,152 @@
+#include <basics/writer/WbWriterX3D.h>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+
+/*===============================================================================*/
+std::string WbWriterX3D::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string X3DFilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterX3D::writeTriangles to "<<X3DFilename<<" - start");
+
+   std::ofstream out(X3DFilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(X3DFilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(X3DFilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+X3DFilename);
+   }
+
+   // General part
+
+   //Root Element
+   out<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"																																 	   <<endl;
+   out<<"<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.1//EN\"   \"http://www.web3d.org/specifications/x3d-3.1.dtd\">"																	   <<endl;
+   out<<"<X3D profile='Interchange' version='3.1' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation=' http://www.web3d.org/specifications/x3d-3.1.xsd '>"<<endl<<endl;
+
+   //Head
+   out<<"<head>"										 <<endl;
+   out<<"<meta content='Simple X3D Writer for blender'/>"<<endl;
+   out<<"</head>"										 <<endl<<endl;
+
+	//Scene, Shape beginn 
+   out<<"<Scene>"            <<endl;
+   out<<"<Shape>"            <<endl;
+
+	//IndexedFaceSet => Polylinien der Dreiecke
+	out<<"<IndexedFaceSet  coordIndex=\""<<endl;
+
+	// TRIANGLES Ponits SECTION
+	int nofTriangles= (int)triangles.size(); 
+	//out<<"   triangles "<<nofTriangles<<endl;
+	for(int c=0; c<nofTriangles; c++)
+		out<<"      "<<val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<" -1"<<endl;
+	out<<"\">"            <<endl;
+    
+	//Coordinates
+	out<<"<Coordinate  point=\""    <<endl;
+
+	// Coordinates SECTION
+	int nofNodes = (int)nodes.size(); 
+	//out<<"   points "<<nofNodes<<endl;
+	for(int n=0; n<nofNodes; n++)
+		out<<"      "<< val<1>(nodes[n]) <<", "<< val<2>(nodes[n]) <<", "<< val<3>(nodes[n])<<", "<<endl;
+   out<<"\"/>"            <<endl;
+
+	//Footer
+	out<<"</IndexedFaceSet>"<< endl;
+	out<<"</Shape>"			<< endl;
+	out<<"</Scene>"         << endl;
+	out<<"</X3D>"           << endl;
+   
+
+   //// Image details
+   //out<<"image {"              <<endl;
+   //out<<"   resolution 640 480"<<endl;
+   //out<<"   aa 0 1"            <<endl;
+   //out<<"   filter mitchell"   <<endl;
+   //out<<"}"                    <<endl<<endl;
+
+   //// Camera position
+   //out<<"camera {"                 <<endl;
+   //out<<"   type pinhole"          <<endl;
+   //out<<"   eye    -0.25 -0.3 0.13"<<endl;
+   //out<<"   target -0.1 0.1 0.13"  <<endl;
+   //out<<"   up     0 0 1"          <<endl;
+   //out<<"   fov    60"             <<endl;
+   //out<<"   aspect 1.333333"       <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //// Light
+   //out<<"light {"                  <<endl;
+   //out<<"   type ibl"              <<endl;
+   //out<<"   image sky_small.hdr"   <<endl;
+   //out<<"   center 0 -1 0"         <<endl;
+   //out<<"   up 0 0 1"              <<endl;
+   //out<<"   lock true"             <<endl;
+   //out<<"   samples 200"           <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //// Shaders
+   //out<<"shader {"                 <<endl;
+   //out<<"   name default-shader"   <<endl;
+   //out<<"   type diffuse"          <<endl;
+   //out<<"   diff 0.25 0.25 0.25"   <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //out<<"shader {"                 <<endl;
+   //out<<"   name Glass"            <<endl;
+   //out<<"   type glass"            <<endl;
+   //out<<"   eta 1.333"             <<endl;
+   //out<<"   color 0.1 0.3 0.8"     <<endl;
+   //out<<"}"                        <<endl<<endl;
+   //                                
+   //out<<"shader {"                 <<endl;
+   //out<<"   name Mirror"           <<endl;
+   //out<<"   type mirror"           <<endl;
+   //out<<"   refl 0.7 0.7 0.7"      <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //// Objects
+   //// a) Ground plane
+   //out<<"object {"                 <<endl;
+   //out<<"   shader default-shader" <<endl;
+   //out<<"   type plane"            <<endl;
+   //out<<"   p 0 0 0"               <<endl;
+   //out<<"   n 0 0 1"               <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //// b) Mesh
+   //out<<"object {"                 <<endl;
+   //out<<"   shader Glass"          <<endl;
+   //out<<"   transform {"           <<endl;
+   //out<<"      rotatey 270.0"      <<endl;
+   //out<<"   }"                     <<endl;
+   //out<<"   type generic-mesh"     <<endl;
+   //out<<"      name polySurfac"    <<endl<<endl;
+
+
+   //// POINTS SECTION
+   //int nofNodes = (int)nodes.size(); 
+   //out<<"   points "<<nofNodes<<endl;
+   //for(int n=0; n<nofNodes; n++)
+   //   out<<"      "<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<endl;
+
+   //// TRIANGLES SECTION
+   //int nofTriangles= (int)triangles.size(); 
+   //out<<"   triangles "<<nofTriangles<<endl;
+   //for(int c=0; c<nofTriangles; c++)
+   //   out<<"      "<<val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<endl;
+
+   //// FOOTER
+   //out<<"   normals none" << endl;
+   //out<<"   uvs none"     << endl;
+   //out<<"}"               << endl;
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterX3D::writeTriangles to "<<X3DFilename<<" - end");
+
+   return X3DFilename;
+}
+/*===============================================================================*/
diff --git a/source/ThirdParty/Library/basics/writer/WbWriterX3D.h b/source/ThirdParty/Library/basics/writer/WbWriterX3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9c708c1215bb897d6ff58e5e30367b4b54505ae
--- /dev/null
+++ b/source/ThirdParty/Library/basics/writer/WbWriterX3D.h
@@ -0,0 +1,38 @@
+#ifndef WBWRITERX3D_H
+#define WBWRITERX3D_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterX3D  : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterX3D )
+
+   static WbWriterX3D* getInstance()
+   {
+      static WbWriterX3D instance;
+      return &instance;
+   }
+private:
+   WbWriterX3D() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+   }
+   WbWriterX3D( const WbWriterX3D& );                  //no copy allowed 
+   const WbWriterX3D& operator=( const WbWriterX3D& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+
+public:
+   std::string getFileExtension()  { return "ascii.X3D"; }
+
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterX3D ,WbWriter>::getInstance()), CAB_WbWriterX3D);
+
+#endif //WBWRITERX3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/CMakePackage.txt b/source/ThirdParty/Library/numerics/geometry3d/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de1dc5a88225180b8e40c6cf46f4a6fbb102778f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
\ No newline at end of file
diff --git a/source/ThirdParty/Library/numerics/geometry3d/CoordinateTransformation3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/CoordinateTransformation3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0d20dadd41c1c4ad2f93eea2f8ddc7dc3fb5de67
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/CoordinateTransformation3D.cpp
@@ -0,0 +1,254 @@
+#include <numerics/geometry3d/CoordinateTransformation3D.h>
+#include <basics/utilities/UbMath.h>
+
+using namespace std;
+
+CoordinateTransformation3D::CoordinateTransformation3D()
+{
+   this->setTransformationValues(0.0,0.0,0.0,1.0,1.0,1.0,0.0,0.0,0.0);
+}
+/*======================================================*/
+CoordinateTransformation3D::CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma) 
+{
+   this->setTransformationValues(originX1, originX2, originX3, dx1, dx2, dx3, alpha, beta, gamma);
+}
+/*======================================================*/
+CoordinateTransformation3D::CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3) 
+{
+   this->setTransformationValues(originX1, originX2, originX3, dx1, dx2, dx3, 0.0, 0.0, 0.0);
+}
+/*======================================================*/
+CoordinateTransformation3D::CoordinateTransformation3D(CoordinateTransformation3D* transformation)
+{
+   this->setTransformationValues(transformation->Tx1 , transformation->Tx2 , transformation->Tx3 , transformation->Sx1 , transformation->Sx2 , transformation->Sx3, transformation->alpha, transformation->beta, transformation->gamma);
+}
+/*======================================================*/
+// void CoordinateTransformation3D::init()
+// {
+//    this->Tx1   = 0.0;      this->Tx2   = 0.0;	this->Tx3   = 0.0;
+//    this->Sx1   = 1.0;      this->Sx2   = 1.0;	this->Sx3   = 1.0;
+//    this->alpha = 0.0;		this->beta = 0.0;		this->gamma = 0.0;
+// 
+//    this->toX1factorX1   = 1.0; this->toX1factorX2   = 0.0; this->toX1factorX3   = 0.0;
+//    this->toX2factorX1   = 0.0; this->toX2factorX2   = 1.0; this->toX2factorX3   = 0.0;
+//    this->toX3factorX1   = 0.0; this->toX3factorX2   = 0.0; this->toX3factorX3   = 1.0;
+//    this->toX1delta      = 0.0; this->toX2delta      = 0.0; this->toX3delta      = 0.0;
+//    this->fromX1factorX1 = 1.0; this->fromX1factorX2 = 0.0; this->fromX1factorX3 = 0.0;
+//    this->fromX2factorX1 = 0.0; this->fromX2factorX2 = 1.0; this->fromX2factorX3 = 0.0;
+//    this->fromX3factorX1 = 0.0; this->fromX3factorX2 = 0.0; this->fromX3factorX3 = 1.0;
+//    
+//    this->active         = false;
+//    this->transformation = false;
+// }
+/*======================================================*/
+
+/**====  Set transformation values
+@param a     transformed coordinate system x0 (in global coordinates)
+@param b     transformed coordinate system y0 (in global coordinates)
+@param c     transformed coordinate system z0 (in global coordinates)
+@param dx1    x coordinate scaling       (dx_transformed/dx_global)
+@param dx2    y coordinate scaling       (dy_transformed/dy_global)
+@param dx3    z coordinate scaling       (dz_transformed/dz_global)
+@param alpha rotation around z angle    (positive FROM global TO transformed coordinate system)
+@param beta  rotation around y angle            
+@param gamma rotation around x angle            
+@exception IllegalArgumentException if one of the scale values is between -1.0E-8 and 1.0E-8
+**/
+
+void CoordinateTransformation3D::setTransformationValues(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma)
+{
+   if(UbMath::zero(dx1) || UbMath::zero(dx2) || UbMath::zero(dx3))
+      throw UbException(UB_EXARGS,"error: at least one delta==0.0");
+   
+   this->Tx1   = originX1; this->Tx2  = originX2; this->Tx3   = originX3;
+   this->Sx1   = dx1;	   this->Sx2  = dx2;	     this->Sx3   = dx3;
+   this->alpha = alpha;	   this->beta = beta;     this->gamma = gamma;
+
+   double ra   = UbMath::PI*alpha/180.0;
+   double cosA = cos(ra);
+   double sinA = sin(ra);
+   double rb   = UbMath::PI*beta/180.0;
+   double cosB = cos(rb);
+   double sinB = sin(rb);
+   double rg   = UbMath::PI*gamma/180.0;
+   double cosG = cos(rg);
+   double sinG = sin(rg);
+
+   //Matrix-Werte von T_invers  (indizes: 12 = spalte 1 zeile 2)
+   double divisor = (Sx1*Sx2*Sx3);
+   
+   this->toX1factorX1 = +cosB*cosA*Sx2*Sx3/divisor;
+   this->toX1factorX2 = -cosB*sinA*Sx1*Sx3/divisor;
+   this->toX1factorX3 = +sinB*Sx1*Sx2/divisor;
+   this->toX1delta    = (-Tx3*Sx1*Sx2*sinB       
+                         +Tx2*Sx1*Sx3*sinA*cosB  
+                         -Tx1*Sx2*Sx3*cosB*cosA)/divisor;
+   
+   this->toX2factorX1 = Sx2*Sx3*(sinG*sinB*cosA+cosG*sinA)/divisor;
+   this->toX2factorX2 = Sx1*Sx3*(-sinG*sinB*sinA+cosG*cosA)/divisor;
+   this->toX2factorX3 = -Sx1*Sx2*cosB*sinG/divisor;
+   this->toX2delta    = (-Tx2*Sx1*Sx3*cosG*cosA
+                         +Tx3*Sx1*Sx2*sinG*cosB
+                         +Tx2*Sx1*Sx3*sinG*sinA*sinB
+                         -Tx1*Sx2*Sx3*cosG*sinA
+                         -Tx1*Sx2*Sx3*sinB*sinG*cosA   )/divisor;
+   
+
+   this->toX3factorX1 = Sx2*Sx3*(-cosG*sinB*cosA+sinG*sinA)/divisor;
+   this->toX3factorX2 = Sx1*Sx3*(sinB*cosG*sinA+sinG*cosA)/divisor;
+   this->toX3factorX3 = Sx1*Sx2*cosB*cosG/divisor;
+   this->toX3delta    = (-Tx2*Sx1*Sx3*sinG*cosA
+                         -Tx3*Sx1*Sx2*cosG*cosB
+                         -Tx2*Sx1*Sx3*cosG*sinA*sinB
+                         -Tx1*Sx2*Sx3*sinG*sinA
+                         +Tx1*Sx2*Sx3*sinB*cosG*cosA  )/divisor;
+                        
+   //Matrix-Werte von T_invers  (indizes: 12 = spalte 1 zeile 2)
+   this->fromX1factorX1 =  cosB*cosA*Sx1;
+   this->fromX1factorX2 =  (sinG*sinB*cosA+cosG*sinA)*Sx1;
+   this->fromX1factorX3 =  (-cosG*sinB*cosA+sinG*sinA)*Sx1;
+   this->fromX1delta    =  Tx1;
+
+   this->fromX2factorX1 =  -cosB*sinA*Sx2;
+   this->fromX2factorX2 =  -(sinG*sinB*sinA-cosG*cosA)*Sx2;
+   this->fromX2factorX3 =  (cosG*sinB*sinA+sinG*cosA)*Sx2;
+   this->fromX2delta    =  Tx2;
+   
+   this->fromX3factorX1 =  sinB*Sx3;
+   this->fromX3factorX2 =  -sinG*cosB*Sx3;
+   this->fromX3factorX3 =  cosG*cosB*Sx3;
+   this->fromX3delta    =  Tx3;
+
+   this->active         =  true;
+   
+   this->transformation =  true;
+}
+/*======================================================*/
+/**
+Set transformation active state (if this IS a transformation)
+@param active true to be active, false otherwise
+**/
+void CoordinateTransformation3D::setActive(const bool& active)
+{
+   if(this->active == active) return;
+   if(this->transformation)   this->active = active;
+}
+/*======================================================*/
+/**
+Transform FROM global coordinates TO transformed coordinates.
+@param x1  the global x coordinate
+@param x2  the global y coordinate
+@param x3  the global z coordinate
+**/
+double CoordinateTransformation3D::transformForwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->toX1factorX1*x1 + this->toX1factorX2*x2 + this->toX1factorX3*x3 + this->toX1delta;
+   else             return x1;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformForwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->toX2factorX1*x1 + this->toX2factorX2*x2 + this->toX2factorX3*x3 + this->toX2delta;
+   else             return x2;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformForwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->toX3factorX1*x1 + this->toX3factorX2*x2 + this->toX3factorX3*x3 + this->toX3delta;
+   else             return x3;
+}
+/*======================================================*/
+/**
+Transform FROM global coordinates TO transformed coordinates (ignoring rotation).
+@param x1  the global x coordinate
+**/
+double CoordinateTransformation3D::transformForwardToX1CoordinateIgnoringRotation(const double& x1) const
+{
+   if(this->active) return (x1-this->Tx1)/this->Sx1;
+   else             return x1;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformForwardToX2CoordinateIgnoringRotation(const double& x2) const
+{
+   if(this->active) return (x2-this->Tx2)/this->Sx2;
+   else             return x2;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformForwardToX3CoordinateIgnoringRotation(const double& x3) const
+{
+   if(this->active) return (x3-this->Tx3)/this->Sx3;
+   else             return x3;
+}
+/*======================================================*/
+/**
+Transform FROM transformed coordinates TO global coordinates.
+@param x1  the transformed x coordinate
+@param x2  the transformed y coordinate
+@param x3  the transformed z coordinate
+**/
+double CoordinateTransformation3D::transformBackwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->fromX1factorX1*x1 + this->fromX1factorX2*x2 + this->fromX1factorX3*x3 + this->fromX1delta;
+   else             return x1;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformBackwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->fromX2factorX1*x1 + this->fromX2factorX2*x2 + this->fromX2factorX3*x3 + this->fromX2delta;
+   else             return x2;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformBackwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->fromX3factorX1*x1 + this->fromX3factorX2*x2 + this->fromX3factorX3*x3 + this->fromX3delta;
+   else             return x3;
+}
+/*======================================================*/
+/**
+Transform FROM transformed coordinates TO global coordinates (ignoring rotation).
+@param x1  the transformed x coordinate
+**/
+double CoordinateTransformation3D::transformBackwardToX1CoordinateIgnoringRotation(const double& x1) const
+{
+   if(this->active) return x1*this->Sx1+this->Tx1;
+   else             return x1;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformBackwardToX2CoordinateIgnoringRotation(const double& x2) const
+{
+   if(this->active) return x2*this->Sx2+this->Tx2;
+   else             return x2;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformBackwardToX3CoordinateIgnoringRotation(const double& x3) const
+{
+   if(this->active) return x3*this->Sx3+this->Tx3;
+   else             return x3;
+}
+/*======================================================*/
+/**
+Returns a string representation of this transformation.
+@return a string representation of this transformation
+**/
+string CoordinateTransformation3D::toString() const
+{
+   stringstream ss;
+    ss<<" CoordinateTransformation3D\n";
+//    ss<<"[isTransformation="<<this->transformation;
+//    ss<<", isActive="<<this->active<<endl;
+    ss<<" ,a="<<this->Tx1<<", b="<<this->Tx2<<", c="<<this->Tx3<<endl;
+    ss<<" , dx1="<<this->Sx1<<", dx2="<<this->Sx2<<", dx2="<<this->Sx3<<endl;
+//    ss<<" , alpha="<<this->alpha<<", beta="<<this->beta<endl;
+//    ss<<"]";
+//    ss<<"[to11="<<this->to11<<", to12="<<this->to12<<", to13="<<this->to13;
+//    ss<<", to21="<<this->to21<<", to22="<<this->to22<<", to23="<<this->to23;
+//    ss<<", to31="<<this->to31<<", to32="<<this->to32<<", to33="<<this->to33;
+//    ss<<", toA="<<this->toA<<", toB="<<this->toB<<", toC="<<this->toC;
+//    ss<<", from11="<<this->from11<<", from12="<<this->from12<<", from13="<<this->from13;
+//    ss<<", from21="<<this->from21<<", from22="<<this->from22<<", from23="<<this->from23;
+//    ss<<", from31="<<this->from31<<", from32="<<this->from32<<", from33="<<this->from33;
+//    ss<<", fromA="<<this->fromA; ss<<", fromB="<<this->fromB; ss<<", fromC="<<this->fromC;
+//    ss<<"]}";
+   return ss.str();
+}
+                                     
diff --git a/source/ThirdParty/Library/numerics/geometry3d/CoordinateTransformation3D.h b/source/ThirdParty/Library/numerics/geometry3d/CoordinateTransformation3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b0b83dec47590765f0d99e2cb37565d78b5cafd
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/CoordinateTransformation3D.h
@@ -0,0 +1,178 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef COORDINATETRANSFORMATION3D_H
+#define COORDINATETRANSFORMATION3D_H
+
+#ifdef RCF_USE_BOOST_SERIALIZATION
+   #include <boost/archive/text_oarchive.hpp>
+   #include <boost/archive/text_iarchive.hpp>	
+#endif //RCF_USE_BOOST_SERIALIZATION
+
+#include <cmath>
+#include <string>
+#include <sstream>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+#include <basics/utilities/UbFileOutput.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class CoordinateTransformation3D;
+typedef VFSharedPtr<CoordinateTransformation3D> CoordinateTransformation3DPtr;
+
+#include <boost/serialization/serialization.hpp>
+
+//description:     x1/x2/x3 = alt, x1*/x2*/x3* = neu
+//   x2      
+//   ^             x*
+//   |            /
+//   |           2*
+//   4          /
+//   |         /
+//   3        1*                     => neues coordsys ist um originX1=originX2=originX3=2 verschoben
+//   |       /                          neues dx1=dx2=dx2=2 -> skalierung um 2 in x1-,x2- und x3-richtung
+//   2      /                           ERST verdrehung um alpha um "x1" achse
+//   |       \                          DANN verdrehung um beta  um "x2" achse
+//   1         \                        DANN verdrehung um gamma um "x3" achse
+//   |           x1*
+//   |--1--2--3--4--5------------- > x1
+//
+// Bemerkung: kann sein, dass die Verdrehung um x1 und x3 vertauschst sind 
+//            - muss mal einer prüfen ...
+
+
+
+class CoordinateTransformation3D
+{
+public:
+   CoordinateTransformation3D();
+   CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma);
+   CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3);
+   CoordinateTransformation3D(CoordinateTransformation3D* transformation);
+   
+   void setTransformationValues(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma);
+   double getX1CoordinateOffset()  const { return this->Tx1;   }   //Translation
+   double getX2CoordinateOffset()  const { return this->Tx2;   }
+   double getX3CoordinateOffset()  const { return this->Tx3;   }
+   double getX1CoordinateScaling() const { return this->Sx1;   }	 //Scaling
+   double getX2CoordinateScaling() const { return this->Sx2;   }
+   double getX3CoordinateScaling() const { return this->Sx3;   }
+   double getRotationX1Angle()     const { return this->alpha; }
+   double getRotationX2Angle()     const { return this->beta;  }
+   double getRotationX3Angle()     const { return this->gamma; }	 //Rotation
+
+   //Achtung die Winkel passen nicht überein -siehe setTransformationValues 
+   void setRotationX1Angle(double alpha) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, alpha, this->beta, this->gamma); }
+   void setRotationX2Angle(double beta ) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, this->alpha, beta, this->gamma); }
+   void setRotationX3Angle(double gamma) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, this->alpha, this->beta, gamma); }
+
+   void setActive(const bool& active);
+   bool isActive()          const { return this->active; }
+   bool isTransformation()  const { return this->transformation; }
+
+   double transformForwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformForwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformForwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformForwardToX1CoordinateIgnoringRotation(const double& x1) const;
+   double transformForwardToX2CoordinateIgnoringRotation(const double& x2) const;
+   double transformForwardToX3CoordinateIgnoringRotation(const double& x3) const;
+   double transformBackwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformBackwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformBackwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformBackwardToX1CoordinateIgnoringRotation(const double& x1) const;
+   double transformBackwardToX2CoordinateIgnoringRotation(const double& x2) const;
+   double transformBackwardToX3CoordinateIgnoringRotation(const double& x3) const;
+   std::string toString() const;
+
+   //------------- implements CAB serialization ----- start
+   void write(UbFileOutput* out) const
+   {
+      out->writeString("Coordtransfomartion3D");
+      out->writeDouble(this->Tx1);
+      out->writeDouble(this->Tx2);
+      out->writeDouble(this->Tx3);
+      out->writeDouble(this->Sx1);
+      out->writeDouble(this->Sx2);
+      out->writeDouble(this->Sx3);
+      out->writeDouble(this->alpha);
+      out->writeDouble(this->beta );
+      out->writeDouble(this->gamma);
+   }
+   void read(UbFileInput* in)
+   {
+      in->readString();
+      this->Tx1   = in->readDouble();
+      this->Tx2   = in->readDouble();
+      this->Tx3   = in->readDouble();
+      this->Sx1   = in->readDouble();
+      this->Sx2   = in->readDouble();
+      this->Sx3   = in->readDouble();
+      this->alpha = in->readDouble();
+      this->beta  = in->readDouble();
+      this->gamma = in->readDouble();
+
+      this->setTransformationValues(Tx1,Tx2,Tx3,Sx1,Sx2,Sx3,alpha,beta,gamma);
+   }
+   //------------- implements CAB serialization ----- end
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      ar & Tx1;   ar & Tx2; ar & Tx3; 
+      ar & Sx1;   ar & Sx2; ar & Sx3; 
+      ar & alpha; ar & beta; ar & gamma;
+      
+      ar & toX1factorX1; ar & toX1factorX2; ar & toX1factorX3; ar & toX1delta;
+      ar & toX2factorX1; ar & toX2factorX2; ar & toX2factorX3; ar & toX2delta;
+      ar & toX3factorX1; ar & toX3factorX2; ar & toX3factorX3; ar & toX3delta;
+
+      ar & fromX1factorX1; ar & fromX1factorX2; ar & fromX1factorX3; ar & fromX1delta;
+      ar & fromX2factorX1; ar & fromX2factorX2; ar & fromX2factorX3; ar & fromX2delta;
+      ar & fromX3factorX1; ar & fromX3factorX2; ar & fromX3factorX3; ar & fromX3delta;
+
+      ar & active;
+      ar & transformation;
+   }
+#endif //CAB_RCF
+
+private:
+   double Tx1, Tx2, Tx3, Sx1, Sx2, Sx3, alpha, beta, gamma;
+
+   double toX1factorX1, toX1factorX2, toX1factorX3, toX1delta;
+   double toX2factorX1, toX2factorX2, toX2factorX3, toX2delta;
+   double toX3factorX1, toX3factorX2, toX3factorX3, toX3delta;
+
+   double fromX1factorX1, fromX1factorX2, fromX1factorX3, fromX1delta;
+   double fromX2factorX1, fromX2factorX2, fromX2factorX3, fromX2delta;
+   double fromX3factorX1, fromX3factorX2, fromX3factorX3, fromX3delta;
+
+   bool   active;
+   bool   transformation;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & Tx1;   ar & Tx2; ar & Tx3; 
+      ar & Sx1;   ar & Sx2; ar & Sx3; 
+      ar & alpha; ar & beta; ar & gamma;
+
+      ar & toX1factorX1; ar & toX1factorX2; ar & toX1factorX3; ar & toX1delta;
+      ar & toX2factorX1; ar & toX2factorX2; ar & toX2factorX3; ar & toX2delta;
+      ar & toX3factorX1; ar & toX3factorX2; ar & toX3factorX3; ar & toX3delta;
+
+      ar & fromX1factorX1; ar & fromX1factorX2; ar & fromX1factorX3; ar & fromX1delta;
+      ar & fromX2factorX1; ar & fromX2factorX2; ar & fromX2factorX3; ar & fromX2delta;
+      ar & fromX3factorX1; ar & fromX3factorX2; ar & fromX3factorX3; ar & fromX3delta;
+
+      ar & active;
+      ar & transformation;
+   }
+};
+
+#endif //COORDINATETRANSFORMATION3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbCuboid3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbCuboid3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eae8f331512e53ec99aefd73bc55d9dadbc9aed3
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbCuboid3D.cpp
@@ -0,0 +1,633 @@
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/creator/GbCuboid3DCreator.h>
+
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+using namespace std;
+
+/*=======================================================*/
+ObObjectCreator* GbCuboid3D::getCreator()
+{
+   return GbCuboid3DCreator::getInstance();
+}
+/*=======================================================*/
+// Konstruktor
+GbCuboid3D::GbCuboid3D() : GbObject3D()
+{
+   this->setName("cuboid");
+   this->p1 = new GbPoint3D(0.0, 0.0, 0.0);
+   this->p2 = new GbPoint3D(0.0, 0.0, 0.0);
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+}
+/*=======================================================*/
+GbCuboid3D::GbCuboid3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b):GbObject3D()
+{
+   this->setName("cuboid");
+   this->p1 = new GbPoint3D(x1a, x2a, x3a);
+   this->p1->addObserver(this);
+	this->p2 = new GbPoint3D(x1b, x2b, x3b);     
+   this->p2->addObserver(this);
+}
+/*=======================================================*/
+GbCuboid3D::GbCuboid3D(GbPoint3D* p1, GbPoint3D* p2) : GbObject3D()
+{
+   this->setName("cuboid");
+	if(!p1 || !p2) throw UbException(UB_EXARGS,"one point ==NULL");
+   this->p1 = p1;
+   this->p1->addObserver(this);
+   this->p2 = p2;
+   this->p2->addObserver(this);
+}
+/*=======================================================*/
+GbCuboid3D::GbCuboid3D(GbCuboid3D* cuboid) : GbObject3D()
+{
+   this->setName("cuboid");
+   if(!cuboid->getPoint1() || !cuboid->getPoint2()) throw UbException(UB_EXARGS,"cuboid ==NULL");
+   this->p1 = cuboid->getPoint1()->clone();
+   this->p1->addObserver(this);
+   this->p2 = cuboid->getPoint2()->clone();
+   this->p2->addObserver(this);
+}
+/*=======================================================*/
+// Destruktor
+GbCuboid3D::~GbCuboid3D()
+{
+   //cout<<"~GbCuboid3D()"<<endl;
+   if(this->p1) this->p1->removeObserver(this);
+   if(this->p2) this->p2->removeObserver(this);
+}
+/*=======================================================*/
+void GbCuboid3D::finalize() 
+{ 
+   if(this->p1) 
+   {
+      this->p1->removeObserver(this);
+      this->p1->finalize();
+      delete this->p1; 
+      this->p1=NULL;
+   } 
+   if(this->p2)
+   {
+      this->p2->removeObserver(this);
+      this->p2->finalize();
+      delete this->p2; 
+      this->p2=NULL;
+   }
+}
+/*=======================================================*/
+void GbCuboid3D::setPoint1(GbPoint3D* point1)
+{ 
+   if(this->p1) this->p1->removeObserver(this);
+   this->p1 = point1;  
+   this->p1->addObserver(this);
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCuboid3D::setPoint2(GbPoint3D* point2)
+{ 
+   if(this->p2) this->p2->removeObserver(this);
+   this->p2 = point2;  
+   this->p2->addObserver(this);
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCuboid3D::setPoints(GbPoint3D* point1, GbPoint3D* point2)
+{ 
+   if(this->p1) this->p1->removeObserver(this);
+   if(this->p2) this->p2->removeObserver(this);
+
+   this->p1 = point1; 
+   this->p2 = point2;
+
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCuboid3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3) 
+{
+   this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() );
+}
+/*=======================================================*/
+double GbCuboid3D::getX1Centroid()
+{
+   return (0.5*(p1->x1 + p2->x1)); 
+}
+/*=======================================================*/
+double GbCuboid3D::getX1Minimum()   
+{
+	return (this->p1->x1 < this->p2->x1 ? this->p1->x1 : this->p2->x1);
+}
+/*=======================================================*/
+double GbCuboid3D::getX1Maximum()   
+{
+	return (this->p1->x1 > this->p2->x1 ? this->p1->x1 : this->p2->x1);
+}
+/*=======================================================*/
+double GbCuboid3D::getX2Centroid()
+{
+   return (0.5*(p1->x2 + p2->x2)); 
+}
+/*=======================================================*/
+double GbCuboid3D::getX2Minimum()   
+{
+	return (this->p1->x2 < this->p2->x2 ? this->p1->x2 : this->p2->x2);
+}	
+/*=======================================================*/
+double GbCuboid3D::getX2Maximum()   
+{
+	return ( this->p1->x2 > this->p2->x2 ? this->p1->x2 : this->p2->x2);
+}
+/*=======================================================*/
+double GbCuboid3D::getX3Centroid()
+{
+   return (0.5*(p1->x3 + p2->x3)); 
+}
+/*=======================================================*/
+double GbCuboid3D::getX3Minimum()   
+{	
+	return (this->p1->x3 < this->p2->x3 ? this->p1->x3 : this->p2->x3);
+}	
+/*=======================================================*/
+double GbCuboid3D::getX3Maximum()   
+{
+	return (this->p1->x3 > this->p2->x3 ? this->p1->x3 : this->p2->x3);
+}
+/*=======================================================*/
+double GbCuboid3D::getLengthX1() 
+{ 
+   return (this->getX1Maximum() - this->getX1Minimum() ); 
+}
+/*=======================================================*/
+double GbCuboid3D::getLengthX2() 
+{ 
+   return (this->getX2Maximum() - this->getX2Minimum());  
+}
+/*=======================================================*/
+double GbCuboid3D::getLengthX3() 
+{ 
+   return (this->getX3Maximum() - this->getX3Minimum()); 
+}
+/*=======================================================*/
+bool GbCuboid3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   //true, wenn 'in Object' oder 'auf Boundary'!
+   if     (UbMath::less(x1p,this->getX1Minimum()))    return false;
+   else if(UbMath::less(x2p,this->getX2Minimum()))    return false;
+   else if(UbMath::less(x3p,this->getX3Minimum()))    return false;
+   else if(UbMath::greater(x1p,this->getX1Maximum())) return false;
+   else if(UbMath::greater(x2p,this->getX2Maximum())) return false;
+   else if(UbMath::greater(x3p,this->getX3Maximum())) return false;
+
+   return true;
+}
+/*=======================================================*/
+bool GbCuboid3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   pointIsOnBoundary = false;
+   
+   //true, wenn 'in Object' oder 'auf Boundary'!
+   if     (UbMath::less(x1p,this->getX1Minimum()))    return false;
+	else if(UbMath::less(x2p,this->getX2Minimum()))    return false;
+	else if(UbMath::less(x3p,this->getX3Minimum()))    return false;
+	else if(UbMath::greater(x1p,this->getX1Maximum())) return false;
+	else if(UbMath::greater(x2p,this->getX2Maximum())) return false;
+	else if(UbMath::greater(x3p,this->getX3Maximum())) return false;
+	
+   if     (UbMath::equal(x1p,this->getX1Minimum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x2p,this->getX2Minimum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x3p,this->getX3Minimum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x1p,this->getX1Maximum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x2p,this->getX2Maximum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x3p,this->getX3Maximum())) pointIsOnBoundary = true;
+   
+   return true;
+}
+/*=======================================================*/
+bool GbCuboid3D::isCellInsideGbObject3D(const double& x1p1,const double& x2p1,const double& x3p1,const double& x1p2,const double& x2p2,const double& x3p2)
+{
+   if     ( UbMath::less   (x1p1, this->getX1Minimum() ) ) return false;
+   else if( UbMath::less   (x2p1, this->getX2Minimum() ) ) return false;
+   else if( UbMath::less   (x3p1, this->getX3Minimum() ) ) return false;
+   else if( UbMath::greater(x1p2, this->getX1Maximum() ) ) return false;
+   else if( UbMath::greater(x2p2, this->getX2Maximum() ) ) return false;
+   else if( UbMath::greater(x3p2, this->getX3Maximum() ) ) return false;
+
+   return true;
+}
+/*=======================================================*/
+bool GbCuboid3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der CuboidUmrandung
+//returns true:
+//  - cell cuts  cuboid3D
+//  - cell boxes cuboid3D
+//returns false:
+//  - cell completely inside cuboid3D ( = cuboid3D boxes cell)
+//  - cell und cuboid3D haben kein gemeinsames Volumen
+{
+   //erstmal die dumm Loesung
+   if(   !this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) 
+      && this->isCellInsideOrCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )
+   {
+      return true;
+   }
+
+   return false;
+
+   //GbCuboid3D* cube = GbSystem3D::clipRectangle3D(*this->p1, *this->p2, x1a,x2a,x3a,x1b,x2b,x3b);
+   //if(cube) 
+   //{
+   //   cube->finalize();
+   //   delete cube;
+   //   return true;
+   //}
+
+   //return false;
+}
+/*=======================================================*/
+bool GbCuboid3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//returns true:
+//  - cell completely inside cuboid3D ( = cuboid3D boxes cell)
+//  - cell cuts  cuboid3D
+//  - cell boxes cuboid3D
+//returns false:
+//  - cell und cuboid3D haben kein gemeinsames Volumen
+{
+    //simpler check, da unser GbCuboid3D ein AABB is:
+   //  anfA        midA         endA             anfB    midB    endB
+   //   |            x<-- dxA -->|                 |<-dxB->x       |
+   //                |<----------------- T --------------->|
+   //ist |T| <= dxA + dxB -> overlap!
+
+   if(     UbMath::lessEqual(  std::fabs( this->getX1Centroid() - 0.5*(x1b+x1a)      /*Tx1*/      )
+                             , 0.5*( this->getLengthX1()        + std::fabs(x1b-x1a) /*dx1A+dx1B*/) )
+
+        && UbMath::lessEqual(  std::fabs( this->getX2Centroid() - 0.5*(x2b+x2a)      /*Tx2*/      )
+                             , 0.5*( this->getLengthX2()        + std::fabs(x2b-x2a) /*dx2A+dx2B*/) )
+
+        && UbMath::lessEqual(  std::fabs( this->getX3Centroid() - 0.5*(x3b+x3a)      /*Tx3*/      )
+                             , 0.5*( this->getLengthX3()        + std::fabs(x3b-x3a) /*dx3A+dx3B*/) ) )
+    {
+       return true;
+    }
+
+    return false;
+
+    // if(   this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)
+   //    || this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) ) return true;
+   //
+   //return false;
+}
+/*=======================================================*/
+vector<GbTriangle3D*> GbCuboid3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles;
+   GbPoint3D p1(getX1Minimum(),getX2Minimum(),getX3Minimum());
+   GbPoint3D p2(getX1Maximum(),getX2Minimum(),getX3Minimum());
+   GbPoint3D p3(getX1Maximum(),getX2Maximum(),getX3Minimum());
+   GbPoint3D p4(getX1Minimum(),getX2Maximum(),getX3Minimum());
+   GbPoint3D p5(getX1Minimum(),getX2Minimum(),getX3Maximum());
+   GbPoint3D p6(getX1Maximum(),getX2Minimum(),getX3Maximum());
+   GbPoint3D p7(getX1Maximum(),getX2Maximum(),getX3Maximum());
+   GbPoint3D p8(getX1Minimum(),getX2Maximum(),getX3Maximum());
+
+   GbPoint3D pUnten(getX1Centroid(),getX2Centroid(),getX3Minimum());
+   GbPoint3D pOben(getX1Centroid(),getX2Centroid(),getX3Maximum());
+   GbPoint3D pLinks(getX1Minimum(), getX2Centroid(),getX3Centroid());
+   GbPoint3D pRechts(getX1Maximum(), getX2Centroid(),getX3Centroid());
+   GbPoint3D pVorne(getX1Centroid(),getX2Minimum(),getX3Centroid());
+   GbPoint3D pHinten(getX1Centroid(),getX2Maximum(),getX3Centroid());
+
+   //"unten"
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(pUnten),new GbPoint3D(p3)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(p1),new GbPoint3D(pUnten)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(pUnten),new GbPoint3D(p4)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p4),new GbPoint3D(pUnten)));
+   //"oben"
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p5),new GbPoint3D(p6),new GbPoint3D(pOben)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p6),new GbPoint3D(p7),new GbPoint3D(pOben)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p5),new GbPoint3D(pOben),new GbPoint3D(p8)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pOben),new GbPoint3D(p7),new GbPoint3D(p8)));
+   //"links"
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p4),new GbPoint3D(p1),new GbPoint3D(pLinks)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p4),new GbPoint3D(pLinks),new GbPoint3D(p8)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p8),new GbPoint3D(pLinks),new GbPoint3D(p5)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pLinks),new GbPoint3D(p1),new GbPoint3D(p5)));
+   //"rechts"                                                               
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(p3),new GbPoint3D(pRechts)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pRechts),new GbPoint3D(p3),new GbPoint3D(p7)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(pRechts),new GbPoint3D(p6)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pRechts),new GbPoint3D(p7),new GbPoint3D(p6)));
+   //"hinten"                                                                       
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(p4),new GbPoint3D(pHinten)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(pHinten),new GbPoint3D(p7)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p7),new GbPoint3D(pHinten),new GbPoint3D(p8)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pHinten),new GbPoint3D(p4),new GbPoint3D(p8)));
+   //"vorne"                                                                        
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p2),new GbPoint3D(pVorne)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pVorne),new GbPoint3D(p2),new GbPoint3D(p6)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(pVorne),new GbPoint3D(p5)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pVorne),new GbPoint3D(p6),new GbPoint3D(p5)));
+   return triangles;
+}
+/*=======================================================*/
+void GbCuboid3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+   /*0*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Minimum(),(float)getX3Minimum()));
+   /*1*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Minimum(),(float)getX3Minimum()));
+   /*2*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Maximum(),(float)getX3Minimum()));
+   /*3*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Maximum(),(float)getX3Minimum()));
+   
+   /*4*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Minimum(),(float)getX3Maximum()));
+   /*5*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Minimum(),(float)getX3Maximum()));
+   /*6*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Maximum(),(float)getX3Maximum()));
+   /*7*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Maximum(),(float)getX3Maximum()));
+
+   //"unten"
+   triangles.push_back( makeUbTuple( 0, 1, 2) );
+   triangles.push_back( makeUbTuple( 0, 2, 3) );
+   //"oben"
+   triangles.push_back( makeUbTuple( 4, 5, 6) );
+   triangles.push_back( makeUbTuple( 4, 6, 7) );
+   //"links"
+   triangles.push_back( makeUbTuple( 0, 3, 7) );
+   triangles.push_back( makeUbTuple( 0, 7, 4) );
+   //"rechts"                                                               
+   triangles.push_back( makeUbTuple( 1, 2, 6) );
+   triangles.push_back( makeUbTuple( 1, 6, 5) );
+   //"hinten"                                                                       
+   triangles.push_back( makeUbTuple( 3, 2, 7) );  
+   triangles.push_back( makeUbTuple( 2, 7, 6) );
+   //"vorne"                                                                        
+   triangles.push_back( makeUbTuple( 0, 1, 5) );
+   triangles.push_back( makeUbTuple( 0, 5, 4) );
+}
+/*=======================================================*/
+string GbCuboid3D::toString() 
+{
+   stringstream ss;
+   ss<<"GbCuboid3D[";
+   ss<<"p1="<<this->p1->toString();
+   ss<<", p2="<<this->p2->toString();
+   ss<<"]";
+   return ss.str();
+}
+/*=======================================================*/
+GbPoint3D* GbCuboid3D::calculateInterSectionPoint3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"not correct implemented");
+}
+/*=======================================================*/
+GbLine3D* GbCuboid3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   return GbSystem3D::createClipLine3D(point1, point2,
+                                       p1->getX1Coordinate(),p1->getX2Coordinate(),p1->getX3Coordinate(),
+                                       p2->getX1Coordinate(),p2->getX2Coordinate(),p2->getX3Coordinate() );
+}
+/*==========================================================*/
+void GbCuboid3D::objectChanged(UbObservable* changedObject)
+{
+   GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject);
+   if(!point || (this->p1!=point && this->p2!=point)) return;
+
+   this->notifyObserversObjectChanged();
+}
+/*==========================================================*/
+void GbCuboid3D::objectWillBeDeleted(UbObservable* objectForDeletion)
+{
+   if(this->p1)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p1);
+      if(objectForDeletion == observedObj) { this->p1 = NULL; }
+   }
+   if(this->p2)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p2);
+      if(objectForDeletion == observedObj) { this->p2 = NULL; }
+   }
+   //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo
+}
+/*=======================================================*/
+void GbCuboid3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   p1->write(out);
+   p2->write(out);
+}
+/*=======================================================*/
+void GbCuboid3D::read(UbFileInput* in) 
+{  
+   in->readString();                                    
+   this->p1 = new GbPoint3D;
+   p1->read(in);
+   in->readString();                                    
+   this->p2 = new GbPoint3D;
+   p2->read(in);
+}
+/*=======================================================*/
+void GbCuboid3D::translate(const double& tx1, const double& tx2, const double& tx3)
+{  
+   this->p1->translate(tx1, tx2, tx3);
+   this->p2->translate(tx1, tx2, tx3);
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCuboid3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{  
+   double lenX1 = this->getLengthX1();
+   double lenX2 = this->getLengthX2();
+   double lenX3 = this->getLengthX3();
+
+   double deltaX1 = lenX1*sx1 - lenX1;
+   double deltaX2 = lenX2*sx2 - lenX2;
+   double deltaX3 = lenX3*sx3 - lenX3;
+
+   double p1X1 = this->p1->getX1Coordinate();
+   double p1X2 = this->p1->getX2Coordinate();
+   double p1X3 = this->p1->getX3Coordinate();
+
+   double p2X1 = this->p2->getX1Coordinate();
+   double p2X2 = this->p2->getX2Coordinate();
+   double p2X3 = this->p2->getX3Coordinate();
+
+   this->p1->setCoordinates(p1X1 - 0.5*deltaX1
+                           ,p1X2 - 0.5*deltaX2
+                           ,p1X3 - 0.5*deltaX3);
+
+   this->p2->setCoordinates(p2X1 + 0.5*deltaX1
+                           ,p2X2 + 0.5*deltaX2
+                           ,p2X3 + 0.5*deltaX3);
+}
+/*==========================================================*/
+double GbCuboid3D::getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   if( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )       return 1.0*(x1b-x1a)*(x2b-x2a)*(x3b-x3a);
+   if( !(this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)) )   return 0.0;
+
+   GbCuboid3D* cube = GbSystem3D::clipRectangle3D(*this->p1, *this->p2, x1a,x2a,x3a,x1b,x2b,x3b);
+
+   if(cube) 
+   {
+      double eps;
+      eps  = (cube->getLengthX1())*(cube->getLengthX2())*(cube->getLengthX3());
+      cube->finalize();
+      delete cube;
+      return eps;
+   }
+   return 0.0;
+}
+/*==========================================================*/
+double GbCuboid3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   double minB[3]   = { this->getX1Minimum(), this->getX2Minimum(), this->getX3Minimum() };
+   double maxB[3]   = { this->getX1Maximum(), this->getX2Maximum(), this->getX3Maximum() };
+   double origin[3] = { x1,  x2,  x3  }; //point
+   double dir[3]    = { rx1, rx2, rx3 }; //ray 
+
+   bool inside = true;
+   char quadrant[3];
+   int  whichPlane;
+   double maxT[3];
+   double candidatePlane[3];
+
+   /* Find candidate planes; this loop can be avoided if
+   rays cast all from the eye(assume perpsective view) */
+   for(int i=0; i<3; i++)
+   {
+      if(origin[i] < minB[i])
+      {
+         quadrant[i] = 1/*LEFT*/;
+         candidatePlane[i] = minB[i];
+         inside = false;
+      }
+      else if(origin[i] > maxB[i]) 
+      {
+         quadrant[i] = 0/*RIGHT*/;
+         candidatePlane[i] = maxB[i];
+         inside = false;
+      }
+      else	
+      {
+         quadrant[i] = 2/*MIDDLE*/;
+      }
+   }
+   /* Ray origin inside bounding box */
+   if(inside)
+   {
+      //throw UbException(UB_EXARGS,"not done");
+      return 0.0;
+   }
+
+   /* Calculate T distances to candidate planes */
+   for(int i=0; i<3; i++)
+   {
+      if( quadrant[i]!=2/*MIDDLE*/ && fabs(dir[i])>1.E-10 )
+      {
+         maxT[i] = (candidatePlane[i]-origin[i])/dir[i];
+      }
+      else maxT[i] = -1.0;
+   }
+
+   /* Get largest of the maxT's for final choice of intersection */
+   whichPlane = 0;
+   for(int i=1; i<3; i++)
+      if (maxT[whichPlane] < maxT[i])
+            whichPlane = i;
+   
+   /* Check final candidate actually inside box */
+   if(maxT[whichPlane]< -1.E-10) return -1.0;
+   double dummy;
+   for(int i= 0; i<3; i++)
+   {
+      if( whichPlane!= i) 
+      {
+         dummy = origin[i] + maxT[whichPlane]*dir[i];
+         if(dummy < minB[i] || dummy > maxB[i])
+            return -1.0;
+      } 
+   }
+
+   return maxT[whichPlane] ;				/* ray hits box */
+}	
+// /*==========================================================*/
+// double GbCuboid3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+// {
+//     double absX,absMaxX,absY,absMaxY,absZ,absMaxZ;
+//  
+//     if(rx1<0.0)     absX    = this->getX1Maximum() - x1;
+//     else            absX    = this->getX1Minimum() - x1;
+//     if(1-(rx1<0.0)) absMaxX = this->getX1Maximum() - x1;
+//     else            absMaxX = this->getX1Minimum() - x1;
+//  
+//     if(rx2<0.0)     absY    = this->getX2Maximum() - x2;
+//     else            absY    = this->getX2Minimum() - x2;
+//     if(1-(rx2<0.0)) absMaxY = this->getX2Maximum() - x2;
+//     else            absMaxY = this->getX2Minimum() - x2;
+//  
+//     if(rx3<0.0)     absZ    = this->getX3Maximum() - x3;
+//     else            absZ    = this->getX3Minimum() - x3;
+//     if(1-(rx3<0.0)) absMaxZ = this->getX3Maximum() - x3;
+//     else            absMaxZ = this->getX3Minimum() - x3;
+//  
+//     
+//     //tmin ist die verschneidung des Gerade (Ray) durch die naehere Gerade (MinX oder MaxX)
+//     //tmax ist die verschneidung des Gerade (Ray) durch die weiteste Gerade (MinX oder MaxX)
+//     //analog fuer tymin und tymax 
+//     double tmin, tymin, tzmin, tmax, tymax, tzmax;
+// 
+//     if(!UbMath::zero(rx1)) tmin  = tmax  = 1.0/rx1;     
+//     else if(rx1<0.0)       tmin  = tmax  = -UbMath::getPositiveInfinity<double>();
+//     else                   tmin  = tmax  = UbMath::getPositiveInfinity<double>();
+// 
+//     if(!UbMath::zero(rx2)) tymin = tymax = 1.0/rx2;     
+//     else if(rx2<0.0)       tymin = tymax = -UbMath::getPositiveInfinity<double>();
+//     else                   tymin = tymax = UbMath::getPositiveInfinity<double>();
+// 
+//     if(!UbMath::zero(rx3)) tzmin = tzmax = 1.0/rx3;     
+//     else if(rx1<0.0)       tzmin = tzmax = -UbMath::getPositiveInfinity<double>();
+//     else                   tzmin = tzmax = UbMath::getPositiveInfinity<double>();
+// 
+//     //tmin  *= absX;
+//     //tmax  *= absMaxX;
+//     //tymin *= absY;
+//     //tymax *= absMaxY;
+//     //tzmin *= absZ;
+//     //tzmax *= absMaxZ;
+//  
+//     //0 * 1/0  vermeiden, da es ein Undefined wert produziert 
+//     if( !UbMath::zero(absX) || !UbMath::zero(rx1) ) tmin *= absX;
+//     else                                            tmin  = tymin;
+// 
+//     if( !UbMath::zero(absY) || !UbMath::zero(rx2))    tymin *= absY;
+//     else                                              tymin  = tmin;
+//     
+//     if( !UbMath::zero(absZ) || !UbMath::zero(rx3))    tzmin *= absZ;
+//     else                                              tzmin  = tymin;
+//  
+//     if( !UbMath::zero(absMaxX) || !UbMath::zero(rx1)) tmax *= absMaxX;
+//     else                                              tmax  = tymax;
+//     
+//     if( !UbMath::zero(absMaxY) || !UbMath::zero(rx2)) tymax *= absMaxY;
+//     else                                              tymax  = tmax;
+//     
+//     if( !UbMath::zero(absMaxZ) || !UbMath::zero(rx3)) tzmax *= absMaxZ;
+//     else                                              tzmax = tymax;
+//  
+//     //in dieser Fall gibt es keine Verschneidung
+//     if( (tmin > tymax) || (tymin > tmax) ) return -1;
+// 
+//     tmin = UbMath::max3(tmin,tymin,tzmin);
+//     tmax = UbMath::min3(tmax,tymax,tzmax);
+//  
+//     if( (tmin > tzmax) || (tzmin > tmax) ) return -1;
+//     if(tmin >= 0.0) return tmin ;
+//  
+//     return tmax;
+//}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbCuboid3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbCuboid3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cce923fcc1db37136465b323d3a8cc471a6404c
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbCuboid3D.h
@@ -0,0 +1,144 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBCUBOID3D_H
+#define GBCUBOID3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <basics/utilities/UbObserver.h>
+#include <basics/utilities/UbMath.h>
+
+class GbLine3D;
+class GbObject3DCreator;
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbCuboid3D;
+typedef VFSharedPtr<GbCuboid3D> GbCuboid3DPtr;
+
+
+class GbCuboid3D : public GbObject3D, public UbObserver
+{
+public:              
+   GbCuboid3D();
+   GbCuboid3D(const double& minX1,const double& minX2, const double& minX3, const double& maxX1,const double& maxX2, const double& maxX3);
+   GbCuboid3D(GbPoint3D *p1, GbPoint3D *p2);
+   GbCuboid3D(GbCuboid3D *cuboid);
+   ~GbCuboid3D();   
+
+   GbCuboid3D* clone()    { return new GbCuboid3D(this); }
+   void finalize();
+
+   GbPoint3D* getPoint1() { return this->p1; }
+   GbPoint3D* getPoint2() { return this->p2; }
+
+   void setPoint1(GbPoint3D* point1);
+   void setPoint2(GbPoint3D* point2);
+   void setPoints(GbPoint3D* point1, GbPoint3D* point2);
+
+   double getX1Centroid();
+   double getX1Minimum();
+   double getX1Maximum();
+   double getX2Centroid();
+   double getX2Minimum();
+   double getX2Maximum();
+   double getX3Centroid();
+   double getX3Minimum();
+   double getX3Maximum();
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+
+   void translate(const double& x1, const double& x2, const double& x3);
+   void rotate(const double& rx1, const double& rx2, const double& rx3) {}
+   void scale(const double& sx1, const double& sx2, const double& sx3);
+
+   double getLengthX1();
+   double getLengthX2();
+   double getLengthX3();
+
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary);
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); 
+   bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+   GbPoint3D*  calculateInterSectionPoint3D(GbPoint3D& point1, GbPoint3D &point2);
+   //GbCuboid3D* createClippedRectangle3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   GbLine3D*   createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+
+   double getDistance(GbPoint3D* p)
+   {
+      return this->getDistance( p->getX1Coordinate(), p->getX2Coordinate(), p->getX3Coordinate() );
+   } 
+   double getDistance(const double& x1p, const double& x2p, const double& x3p)
+   {
+      throw UbException( UB_EXARGS, "not implemented" );
+
+      // falls punkt innerhalt ist: minimalen abstand ausrechnen
+      if( this->isPointInGbObject3D(x1p,x2p,x3p) )
+      {
+         double x1Dist = UbMath::min( std::abs(x1p-this->getX1Minimum()),std::abs(x1p-this->getX1Maximum()) );
+         double x2Dist = UbMath::min( std::abs(x2p-this->getX2Minimum()),std::abs(x2p-this->getX2Maximum()) );
+         double x3Dist = UbMath::min( std::abs(x3p-this->getX3Minimum()),std::abs(x3p-this->getX3Maximum()) );
+
+         return UbMath::min( x1Dist, x2Dist, x3Dist );
+      }
+      else
+      {
+
+      }
+   }
+
+   std::string toString();
+
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject);
+   void objectWillBeDeleted(UbObservable* objectForDeletion);
+
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & p1;
+      ar & p2;
+   }
+#endif //CAB_RCF
+
+protected:
+   GbPoint3D* p1;
+   GbPoint3D* p2;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbCuboid3D>("GbCuboid3D")             , SF_GbCuboid3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbCuboid3D >()), SF_GbCuboid3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbCuboid3D>() ), SF_GbCuboid3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbCylinder3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbCylinder3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e439a52966dc20ca95cdc965da9d890ccd8a01e8
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbCylinder3D.cpp
@@ -0,0 +1,1262 @@
+#include <numerics/geometry3d/GbCylinder3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <basics/utilities/UbInfinity.h>
+
+#include <numerics/geometry3d/creator/GbCylinder3DCreator.h>
+
+using namespace std;
+
+/*=======================================================*/
+ObObjectCreator* GbCylinder3D::getCreator()
+{
+   return GbCylinder3DCreator::getInstance();
+}
+// Konstruktor
+/*==========================================================*/
+GbCylinder3D::GbCylinder3D()
+   : minX1(0.0)   , minX2(0.0)   , minX3(0.0)
+   , maxX1(0.0)   , maxX2(0.0)   , maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   GbPoint3D* p1 = new GbPoint3D();
+   GbPoint3D* p2 = new GbPoint3D();
+   mLine = new GbLine3D(p1,p2);
+   this->mLine->addObserver(this);
+   mRad = 0.0;
+   cylinderType = GbCylinder3D::NOTPARALLELTOAXIS;
+   this->mLine->addObserver(this);
+   this->calculateValues();
+}
+/*=======================================================*/
+GbCylinder3D::GbCylinder3D(GbCylinder3D* cylinder)
+   : minX1(0.0)   , minX2(0.0)   , minX3(0.0)
+   , maxX1(0.0)   , maxX2(0.0)   , maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   mRad         = cylinder->getRadius();
+   cylinderType = cylinder->cylinderType;
+   mLine        = cylinder->getLine()->clone();
+
+   this->mLine->addObserver(this);
+   this->calculateValues();
+}
+/*==========================================================*/
+GbCylinder3D::GbCylinder3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b, const double& rad)
+   : minX1(0.0)   , minX2(0.0)   , minX3(0.0)
+   , maxX1(0.0)   , maxX2(0.0)   , maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   mLine = new GbLine3D;
+   //Min/Max, damit gewaehrleistet ist, dass Startpunkt immer der "Achs-Minimale" ist
+   //Anm.: bin nich tsicher ob weiter unten irgendwelche Algos drauf beruhen...
+   //      geht nat nur solange, zylinder achs-parallel, aber das ist erzeit so!!!
+   mLine->setPoints( new GbPoint3D(min(x1a,x1b), min(x2a,x2b), min(x3a,x3b))
+	                 ,new GbPoint3D(max(x1a,x1b), max(x2a,x2b), max(x3a,x3b)));
+   //mLine->setPoints( new GbPoint3D(x1a,x2a,x3a),new GbPoint3D(x1b, x2b ,x3b ));
+   this->mLine->addObserver(this);
+   mRad = fabs(rad);
+
+   this->calculateValues();
+}
+/*==========================================================*/
+GbCylinder3D::GbCylinder3D(GbPoint3D* p1, GbPoint3D* p2, const double& rad)
+   : minX1(0.0), minX2(0.0), minX3(0.0)
+   , maxX1(0.0), maxX2(0.0), maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   mRad = rad;
+
+   mLine = new GbLine3D(p1,p2);
+   this->mLine->addObserver(this);
+   this->calculateValues();
+}
+/*==========================================================*/
+GbCylinder3D::GbCylinder3D(GbLine3D* line, const double& rad)
+   : minX1(0.0), minX2(0.0), minX3(0.0)
+   , maxX1(0.0), maxX2(0.0), maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   mRad = rad;
+
+   this->mLine = line;
+   this->mLine->addObserver(this);
+
+   this->calculateValues();
+}
+/*==========================================================*/
+// Destruktor
+GbCylinder3D::~GbCylinder3D()
+{
+   if(mLine) this->mLine->removeObserver(this);
+   mLine = NULL;
+}
+/*=======================================================*/
+void GbCylinder3D::calculateValues()
+{
+   double x1a = mLine->getPoint1()->x1;    double x1b = mLine->getPoint2()->x1;
+   double x2a = mLine->getPoint1()->x2;    double x2b = mLine->getPoint2()->x2;
+   double x3a = mLine->getPoint1()->x3;    double x3b = mLine->getPoint2()->x3;
+
+   if     (x1a!=x1b && x2a==x2b && x3a==x3b)  this->cylinderType = X1PARALLEL;
+   else if(x2a!=x2b && x1a==x1b && x3a==x3b)  this->cylinderType = X2PARALLEL;
+   else if(x3a!=x3b && x1a==x1b && x2a==x2b)  this->cylinderType = X3PARALLEL;
+   // nach dem serialisieren ruft er den Standardkonstruktor auf wo alles 0 ist und bricht sonst hier ab
+   else if(x3a==x3b && x1a==x1b && x2a==x2b)  this->cylinderType = X1PARALLEL; 
+   else                                       this->cylinderType = NOTPARALLELTOAXIS;
+
+   if((this->cylinderType & NOTPARALLELTOAXIS)==NOTPARALLELTOAXIS)
+      throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Zylinder erlaubt... isPointInObject3D funzt sonst ned");
+
+   if(this->isParallelToX1Axis())
+   {
+      minX1 = mLine->getX1Minimum();
+      maxX1 = mLine->getX1Maximum();
+      minX2 = mLine->getX2Centroid()-mRad; 
+      maxX2 = mLine->getX2Centroid()+mRad;
+      minX3 = mLine->getX3Centroid()-mRad; 
+      maxX3 = mLine->getX3Centroid()+mRad;
+   }
+   else if(this->isParallelToX2Axis()) 
+   {
+      minX1 = mLine->getX1Centroid()-mRad;
+      maxX1 = mLine->getX1Centroid()+mRad;
+      minX2 = mLine->getX2Minimum();   
+      maxX2 = mLine->getX2Maximum();
+      minX3 = mLine->getX3Centroid()-mRad;
+      maxX3 = mLine->getX3Centroid()+mRad;
+   }
+   else if(this->isParallelToX3Axis()) 
+   {
+      minX1 = mLine->getX1Centroid()-mRad;  
+      maxX1 = mLine->getX1Centroid()+mRad;
+      minX2 = mLine->getX2Centroid()-mRad;
+      maxX2 = mLine->getX2Centroid()+mRad;
+      minX3 = mLine->getX3Minimum();
+      maxX3 = mLine->getX3Maximum();
+   }
+
+   centerX1 = mLine->getX1Centroid();
+   centerX2 = mLine->getX2Centroid();
+   centerX3 = mLine->getX3Centroid();
+}
+ 
+/*=======================================================*/
+void GbCylinder3D::finalize()
+{
+   if(this->mLine)
+   {
+      mLine->finalize();
+      delete mLine;
+      mLine=NULL;
+   }
+}
+/*=======================================================*/
+double GbCylinder3D::getHeight()
+{
+   if(mLine) return mLine->getLength(); return 0.0;
+}
+/*=======================================================*/
+GbPoint3D* GbCylinder3D::getPoint1()
+{
+   if(this->mLine) return this->mLine->getPoint1();
+   return NULL;
+}
+/*=======================================================*/
+GbPoint3D* GbCylinder3D::getPoint2()
+{
+   if(this->mLine) return this->mLine->getPoint2();
+   return NULL;
+}
+/*=======================================================*/
+void GbCylinder3D::setRadius(const double& radius)
+{
+   this->mRad = std::fabs(radius);
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCylinder3D::setLine(GbLine3D* line)
+{
+   if(this->mLine) this->mLine->removeObserver(this);
+   this->mLine = line;
+   this->mLine->addObserver(this);
+   this->calculateValues();
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCylinder3D::setPoint1(const double& x1, const double& x2, const double& x3)
+{
+   if(!mLine->getPoint1()) throw UbException(UB_EXARGS,"line has no point1");
+   mLine->getPoint1()->setCoordinates(x1,x2,x3);
+   this->calculateValues();
+
+   //this->notifyObserversObjectChanged(); //wird automatisch aufgerufen, da der point (this) benachrichtigt...
+}
+/*=======================================================*/
+void GbCylinder3D::setPoint2(const double& x1, const double& x2, const double& x3)
+{
+   if(!mLine->getPoint2()) throw UbException(UB_EXARGS,"line has no point2");
+   mLine->getPoint2()->setCoordinates(x1,x2,x3);
+   this->calculateValues();
+
+   //this->notifyObserversObjectChanged(); //wird automatisch aufgerufen, da der point (this) benachrichtigt...
+}
+/*==========================================================*/
+bool GbCylinder3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   //true, wenn 'in Object' oder 'auf Boundary'!
+   if     ( this->isParallelToX1Axis() && (UbMath::less(x1p,minX1) || UbMath::greater(x1p,maxX1)))  return false;
+   else if( this->isParallelToX2Axis() && (UbMath::less(x2p,minX2) || UbMath::greater(x2p,maxX2)))  return false;
+   else if( this->isParallelToX3Axis() && (UbMath::less(x3p,minX3) || UbMath::greater(x3p,maxX3)))  return false;
+   else if( this->isNotParallelToAxis() ) throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Zylinder erlaubt... isPointInObject3D funzt sonst ned");
+
+   return UbMath::lessEqual(fabs(mLine->getDistance(x1p,x2p,x3p)),fabs(mRad));
+}
+/*==========================================================*/
+bool GbCylinder3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   //funzt derzeit nur bei achsparallelen cylindern
+   pointIsOnBoundary = false;
+
+   if     ( this->isParallelToX1Axis() && (UbMath::less(x1p,minX1) || UbMath::greater(x1p,maxX1)))  return false;
+   else if( this->isParallelToX2Axis() && (UbMath::less(x2p,minX2) || UbMath::greater(x2p,maxX2)))  return false;
+   else if( this->isParallelToX3Axis() && (UbMath::less(x3p,minX3) || UbMath::greater(x3p,maxX3)))  return false;
+   else if( this->isNotParallelToAxis() ) throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Zylinder erlaubt... isPointInObject3D funzt sonst ned");
+
+   //true, wenn 'in Object' oder 'auf Boundary'!
+
+   double dis = mLine->getDistance(x1p,x2p,x3p);
+
+   if(UbMath::equal(dis,mRad)) pointIsOnBoundary = true;
+ 
+   if     (this->isParallelToX1Axis() && (UbMath::equal(x1p,minX1) || UbMath::equal(x1p,maxX1))) pointIsOnBoundary = true;
+   else if(this->isParallelToX2Axis() && (UbMath::equal(x2p,minX2) || UbMath::equal(x2p,maxX2))) pointIsOnBoundary = true;
+   else if(this->isParallelToX3Axis() && (UbMath::equal(x3p,minX3) || UbMath::equal(x3p,maxX3))) pointIsOnBoundary = true;
+
+   return UbMath::lessEqual(dis,mRad);
+}
+/*==========================================================*/
+string GbCylinder3D::toString()
+{
+	stringstream ss;
+	ss<<"GbCylinder3D[";
+	ss<<"line="<<this->mLine->toString();
+   ss<<", r="<<this->mRad;
+   ss<<"]";
+   return(ss.str());
+}
+/*=======================================================*/
+bool GbCylinder3D::isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   if(   this->isPointInGbObject3D(x1a, x2a, x3a)
+      && this->isPointInGbObject3D(x1b, x2a, x3a)
+      && this->isPointInGbObject3D(x1b, x2b, x3a)
+      && this->isPointInGbObject3D(x1a, x2b, x3a)
+      && this->isPointInGbObject3D(x1a, x2a, x3b)
+      && this->isPointInGbObject3D(x1b, x2a, x3b)
+      && this->isPointInGbObject3D(x1b, x2b, x3b)
+      && this->isPointInGbObject3D(x1a, x2b, x3b))
+   {
+      return true;
+   }
+   return false;
+}
+/*==========================================================*/
+bool GbCylinder3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der CuboidUmrandung
+//returns true:
+//  - cell cuts  cylinder3D
+//  - cell boxes cylinder3D
+//returns false:
+//  - cell completely inside cylinder3D ( = cylinder3D boxes cell)
+//  - cell und cylinder3D haben kein gemeinsames Volumen
+{
+   //erstmal wieder die dumm Loesung
+   if(   this->isCellInsideOrCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)
+      && !this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )
+   {
+      return true;
+   }
+
+   return false;
+}
+/*==========================================================*/
+bool GbCylinder3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//returns true:
+//  - cell completely inside cylinder3D ( = cylinder3D boxes cell)
+//  - cell cuts  cylinder3D
+//  - cell boxes cylinder3D
+//returns false:
+//  - cell und cylinder3D haben kein gemeinsames Volumen
+{
+   double dmin   = 0.0;
+
+   if(this->isParallelToX1Axis())
+   {
+      //check liegt Cell komplett !x1-ausserhalb"?
+      if(  UbMath::less   (x1a,minX1) && UbMath::less   (x1b,minX1) ) return false;
+      if(  UbMath::greater(x1a,maxX1) && UbMath::greater(x1b,maxX1) ) return false;
+
+      //mittelpunkt kreis-querschnitt
+      double& midX2 = mLine->getPoint1()->x2;
+      double& midX3 = mLine->getPoint1()->x3;
+      if     ( UbMath::less   ( midX2, x2a ) ) dmin += std::pow( midX2 - x2a, 2.0 ); 
+      else if( UbMath::greater( midX2, x2b ) ) dmin += std::pow( midX2 - x2b, 2.0 );     
+      if     ( UbMath::less   ( midX3, x3a ) ) dmin += std::pow( midX3 - x3a, 2.0 ); 
+      else if( UbMath::greater( midX3, x3b ) ) dmin += std::pow( midX3 - x3b, 2.0 );     
+      if( UbMath::lessEqual( dmin, mRad*mRad) ) return true;
+
+      return false;
+   }
+   else if(this->isParallelToX2Axis())
+   {
+      //check liegt Cell komplett !x2-ausserhalb"?
+      if(  UbMath::less   (x2a,minX2)   && UbMath::less   (x2b,minX2) ) return false;
+      if(  UbMath::greater(x2a,maxX2  ) && UbMath::greater(x2b,maxX2) ) return false;
+
+      //mittelpunkt kreis-querschnitt
+      double& midX1 = mLine->getPoint1()->x1;
+      double& midX3 = mLine->getPoint1()->x3;
+      if     ( UbMath::less   ( midX1, x1a ) ) dmin += std::pow( midX1 - x1a, 2.0 ); 
+      else if( UbMath::greater( midX1, x1b ) ) dmin += std::pow( midX1 - x1b, 2.0 );     
+      if     ( UbMath::less   ( midX3, x3a ) ) dmin += std::pow( midX3 - x3a, 2.0 ); 
+      else if( UbMath::greater( midX3, x3b ) ) dmin += std::pow( midX3 - x3b, 2.0 );     
+      if( UbMath::lessEqual( dmin, mRad*mRad ) ) return true;
+
+   }
+   else if(this->isParallelToX3Axis())
+   {
+      //check liegt Cell komplett !x3-ausserhalb"?
+      if(  UbMath::less   (x3a,minX3) && UbMath::less   (x3b,minX3) ) return false;
+      if(  UbMath::greater(x3a,maxX3) && UbMath::greater(x3b,maxX3) ) return false;
+
+      //mittelpunkt kreis-querschnitt
+      double& midX1 = mLine->getPoint1()->x1;
+      double& midX2 = mLine->getPoint1()->x2;
+      if     ( UbMath::less   ( midX1, x1a ) ) dmin += std::pow( midX1 - x1a, 2.0 ); 
+      else if( UbMath::greater( midX1, x1b ) ) dmin += std::pow( midX1 - x1b, 2.0 );     
+      if     ( UbMath::less   ( midX2, x2a ) ) dmin += std::pow( midX2 - x2a, 2.0 ); 
+      else if( UbMath::greater( midX2, x2b ) ) dmin += std::pow( midX2 - x2b, 2.0 );     
+      if( UbMath::lessEqual( dmin, mRad*mRad ) ) return true;
+   }
+
+   return false;
+}
+/*==========================================================*/
+GbLine3D* GbCylinder3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   //liefert immer "innere" linie, also der teil, der vom Zylinder "abgeschnitten" wurde!
+   //funktioniert derzeit nur mit achsenparallelen Zylindern!
+   vector<GbPoint3D*> schnittpunkte;
+
+   double xa,ya,za,xb,yb,zb,xm,ym,zStart,zEnd,t1,t2;
+
+   if(this->isParallelToX1Axis())
+   {
+      xa     = point1.getX2Coordinate();
+      ya     = point1.getX3Coordinate();
+      za     = point1.getX1Coordinate();
+      xb     = point2.getX2Coordinate();
+      yb     = point2.getX3Coordinate();
+      zb     = point2.getX1Coordinate();
+      xm     = mLine->getPoint1()->getX2Coordinate();
+      ym     = mLine->getPoint1()->getX3Coordinate();
+      zStart = mLine->getPoint1()->getX1Coordinate();
+      zEnd   = mLine->getPoint2()->getX1Coordinate();
+   }
+   else if(this->isParallelToX2Axis())
+   {
+      xa     = point1.getX1Coordinate();
+      ya     = point1.getX3Coordinate();
+      za     = point1.getX2Coordinate();
+      xb     = point2.getX1Coordinate();
+      yb     = point2.getX3Coordinate();
+      zb     = point2.getX2Coordinate();
+      xm     = mLine->getPoint1()->getX1Coordinate();
+      ym     = mLine->getPoint1()->getX3Coordinate();
+      zStart = mLine->getPoint1()->getX2Coordinate();
+      zEnd   = mLine->getPoint2()->getX2Coordinate();
+   }
+   else if(this->isParallelToX3Axis())
+   {
+      xa     = point1.getX1Coordinate();
+      ya     = point1.getX2Coordinate();
+      za     = point1.getX3Coordinate();
+      xb     = point2.getX1Coordinate();
+      yb     = point2.getX2Coordinate();
+      zb     = point2.getX3Coordinate();
+      xm     = mLine->getPoint1()->getX1Coordinate();
+      ym     = mLine->getPoint1()->getX2Coordinate();
+      zStart = mLine->getPoint1()->getX3Coordinate();
+      zEnd   = mLine->getPoint2()->getX3Coordinate();
+   }
+   else throw UbException(UB_EXARGS,"funktioniert derzeit nur mit achsenparallelen Zylindern");
+
+   //Bestimmung des Schnittpunktes mit unendlich ausgedehntem Zylinder
+   double r   = mRad;
+   double r2  = r*r;
+   double xa2 = xa*xa;
+   double xb2 = xb*xb;
+   double ya2 = ya*ya;
+   double yb2 = yb*yb;
+   double xm2 = xm*xm;
+   double ym2 = ym*ym;
+
+   double wurzel  = 2.0*xa*xm*yb2+2.0*ya*ym*xb2-2.0*xa*xb*r2+2.0*xa*xb*ym2-2.0*ya*yb*r2+2.0*xa2*yb*ym
+                   +2.0*xa*xm*ya*ym-2.0*xa*xm*yb*ym-2.0*ya*ym*xb*xm+2.0*xb*xm*yb*ym+2.0*ya*yb*xa*xb
+                   -2.0*ya*yb*xa*xm-2.0*ya*yb*xb*xm-2.0*xa*xb*ya*ym-2.0*xa*xb*yb*ym+2.0*xb*xm*ya2
+                   +2.0*ya*yb*xm2-xa2*yb2-xb2*ya2+xa2*r2-xa2*ym2+xb2*r2-xb2*ym2+ya2*r2-ya2*xm2+yb2*r2-yb2*xm2;
+   double nenner  = -2.0*(ya*yb+xa*xb)+xa2+xb2+ya2+yb2;
+   double zaehler =  2.0*(-xa*xm+xb*xm-ya*ym+yb*ym)+xa2-xb2+ya2-yb2;
+
+   if(UbMath::greaterEqual(wurzel,0.0) && !UbMath::zero(nenner) )//fabs(nenner)>1.E-13)
+   {
+      t1 = (zaehler+2.0*sqrt(wurzel))/nenner;
+      t2 = (zaehler-2.0*sqrt(wurzel))/nenner;
+
+      if(UbMath::inClosedInterval(t1, -1.0, 1.0)) //Schnittpunkt innerhalb der Strecke
+      {
+         double x = xa*(0.5-0.5*t1)+xb*(0.5+0.5*t1);
+         double y = ya*(0.5-0.5*t1)+yb*(0.5+0.5*t1);
+         double z = za*(0.5-0.5*t1)+zb*(0.5+0.5*t1);
+
+         if(UbMath::inClosedInterval(z,zStart,zEnd)) //zWert muss sich innerhal der cylinderlaenge befinden
+         {
+            if     (this->isParallelToX1Axis()) schnittpunkte.push_back(new GbPoint3D(z,x,y));
+            else if(this->isParallelToX2Axis()) schnittpunkte.push_back(new GbPoint3D(x,z,y));
+            else if(this->isParallelToX3Axis()) schnittpunkte.push_back(new GbPoint3D(x,y,z));
+         }
+      }
+      if(fabs(t2-t1)>1.E-13 && UbMath::inClosedInterval(t2, -1.0, 1.0)) //Schnittpunkt innerhalb der Strecke
+      {
+         double x = xa*(0.5-0.5*t2)+xb*(0.5+0.5*t2);
+         double y = ya*(0.5-0.5*t2)+yb*(0.5+0.5*t2);
+         double z = za*(0.5-0.5*t2)+zb*(0.5+0.5*t2);
+
+         if(UbMath::inClosedInterval(z,zStart,zEnd)) //zWert muss sich innerhal der cylinderlaenge befinden
+         {
+            if     (this->isParallelToX1Axis()) schnittpunkte.push_back(new GbPoint3D(z,x,y));
+            else if(this->isParallelToX2Axis()) schnittpunkte.push_back(new GbPoint3D(x,z,y));
+            else if(this->isParallelToX3Axis()) schnittpunkte.push_back(new GbPoint3D(x,y,z));
+         }
+      }
+   }
+   //wenn nenner==0 -> Strecke parallel zu Zylinder! Es muss noch auf Schnittpunkt mit "Deckeln" geprueft werden
+
+   //Schnittpunkt mit Seitenflaechen bestimmen
+   //hierzu wird der schnittpunkt der gegebnen strecke mit den seitenflaechenberechnet
+   //als erstes "schaut man seitlich auf den Zylinder" --> kreisflaechen wird als strecke darsgestellt
+   //mit diesen "strecken" berechnet man Schnittpunkte.
+   //anschliessend wird geprueft, ob der berechnete Schnittpunkt ueberhaupt im kreis liegt
+   //falls ja --> Schnittpunkt vorhanden
+
+   double x1a,y1a,z1a,x1b,y1b,z1b, //uebergebene Strecke
+          x2a,y2a,x2b,y2b,         //erste "Kreisstrecke"
+          x3a,y3a,x3b,y3b,         //zweite "Kreisstrecke"
+          y2m,z2m,y3m,z3m;
+   double nenner1ab;
+
+   if(this->isParallelToX1Axis())
+   {
+      x1a=point1.getX1Coordinate();
+      y1a=point1.getX2Coordinate();
+      z1a=point1.getX3Coordinate();
+      x1b=point2.getX1Coordinate();
+      y1b=point2.getX2Coordinate();
+      z1b=point2.getX3Coordinate();
+
+      x2a=mLine->getPoint1()->getX1Coordinate();
+      y2m=mLine->getPoint1()->getX2Coordinate();
+      z2m=mLine->getPoint1()->getX3Coordinate();
+      y2a=y2m+mRad;
+      x2b=mLine->getPoint1()->getX1Coordinate();
+      y2b=y2m-mRad;
+
+      x3a=mLine->getPoint2()->getX1Coordinate(); //
+      y3m=mLine->getPoint2()->getX2Coordinate();
+      z3m=mLine->getPoint2()->getX3Coordinate();
+      y3a=y3m+mRad;
+      x3b=mLine->getPoint2()->getX1Coordinate();
+      y3b=y3m-mRad;
+   }
+   else if(this->isParallelToX2Axis())
+   {
+      x1a=point1.getX2Coordinate();
+      y1a=point1.getX3Coordinate();
+      z1a=point1.getX1Coordinate();
+      x1b=point2.getX2Coordinate();
+      y1b=point2.getX3Coordinate();
+      z1b=point2.getX1Coordinate();
+
+      x2a=mLine->getPoint1()->getX2Coordinate();
+      y2m=mLine->getPoint1()->getX3Coordinate();
+      z2m=mLine->getPoint1()->getX1Coordinate();
+      y2a=y2m+mRad;
+      x2b=mLine->getPoint1()->getX2Coordinate();
+      y2b=y2m-mRad;
+
+      x3a=mLine->getPoint2()->getX2Coordinate(); //
+      y3m=mLine->getPoint2()->getX3Coordinate();
+      z3m=mLine->getPoint2()->getX1Coordinate();
+      y3a=y3m+mRad;
+      x3b=mLine->getPoint2()->getX2Coordinate();
+      y3b=y3m-mRad;
+   }
+   else if(this->isParallelToX3Axis())
+   {
+      x1a=point1.getX3Coordinate();
+      y1a=point1.getX2Coordinate();
+      z1a=point1.getX1Coordinate();
+      x1b=point2.getX3Coordinate();
+      y1b=point2.getX2Coordinate();
+      z1b=point2.getX1Coordinate();
+
+      x2a=mLine->getPoint1()->getX3Coordinate();
+      y2m=mLine->getPoint1()->getX2Coordinate();
+      z2m=mLine->getPoint1()->getX1Coordinate();
+      y2a=y2m+mRad;
+      x2b=mLine->getPoint1()->getX3Coordinate();
+      y2b=y2m-mRad;
+
+      x3a=mLine->getPoint2()->getX3Coordinate(); //
+      y3m=mLine->getPoint2()->getX2Coordinate();
+      z3m=mLine->getPoint2()->getX1Coordinate();
+      y3a=y3m+mRad;
+      x3b=mLine->getPoint2()->getX3Coordinate();
+      y3b=y3m-mRad;
+   }
+   else throw UbException(UB_EXARGS,"funktioniert derzeit nur mit achsenparallelen Zylindern");
+
+   nenner1ab = -y1a*x2a+y1a*x2b+y1b*x2a-y1b*x2b+x1a*y2a-x1a*y2b-x1b*y2a+x1b*y2b;
+   //double nenner2 = x1a*y2a-x1a*y2b-x1b*y2a+x1b*y2b-y1a*x2a+y1a*x2b+y1b*x2a-y1b*x2b;
+   if(fabs(nenner1ab)>1.E-13) //andernfalls sind die beiden Strecken parallel
+   {
+      //tStrecke ist fuer gegebene Strecke!
+      double t1ab = (-y1a*x2a+y1a*x2b-2.0*y2a*x2b+x1a*y2a-x1a*y2b-x1b*y2b+2.0*y2b*x2a+x1b*y2a-y1b*x2a+y1b*x2b)/nenner1ab;
+      //double tStrecke = -(-x1a*y2a+x1a*y2b+2.0*y2a*x2b+y1a*x2a-2.0*x2a*y2b-y1a*x2b+y1b*x2a-y1b*x2b-x1b*y2a+x1b*y2b)/nenner2;
+      //wenn -1 <= t2 <= +1 -> SP mit strecke
+      if(UbMath::inClosedInterval(t1ab, -1.0, 1.0)) //Schnittpunkt innerhalb der Strecke
+      {
+         double x,y,z,abstand_ist;
+         if     (this->isParallelToX1Axis())
+         {
+            x = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            y = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            z = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-y)*(y3m-y)+(z3m-z)*(z3m-z));
+         }
+         else if(this->isParallelToX2Axis())
+         {
+            y = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            z = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            x = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-z)*(y3m-z)+(z3m-x)*(z3m-x));
+         }
+         else if(this->isParallelToX3Axis())
+         {
+            z = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            y = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            x = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-y)*(y3m-y)+(z3m-x)*(z3m-x));
+         }
+         else throw UbException(UB_EXARGS,"funktioniert derzeit nur mit achsenparallelen Zylindern");
+         
+         //pruefen, ob Punkt Element von Kreisflaeche
+         //double abstand_ist=sqrt((y2m-y)*(y2m-y)+(z2m-z)*(z2m-z));
+         if(UbMath::lessEqual(abstand_ist,mRad))  //Punkt ist Schnittpunkt
+         {
+            bool exists = false;
+            for(int pos=0;pos<(int)schnittpunkte.size();++pos)
+            {
+               if(    fabs(schnittpunkte[pos]->getX1Coordinate()-x)<1.E-13
+                   && fabs(schnittpunkte[pos]->getX2Coordinate()-y)<1.E-13
+                   && fabs(schnittpunkte[pos]->getX3Coordinate()-z)<1.E-13 ) exists=true;
+            }
+
+            if(!exists) schnittpunkte.push_back(new GbPoint3D(x,y,z));
+         }
+      }
+   }
+
+   nenner1ab = -y1a*x3a+y1a*x3b+y1b*x3a-y1b*x3b+x1a*y3a-x1a*y3b-x1b*y3a+x1b*y3b;
+
+   if(fabs(nenner1ab)>1.E-13) //andernfalls sind die beiden Strecken parallel
+   {
+      //tStrecke ist fuer gegebene Strecke!
+      double t1ab = (-y1a*x3a+y1a*x3b-x1b*y3b-2.0*y3a*x3b-x1a*y3b+2.0*y3b*x3a+x1a*y3a+x1b*y3a-y1b*x3a+y1b*x3b)/nenner1ab;
+
+      if(UbMath::inClosedInterval(t1ab, -1.0, 1.0)) //Schnittpunkt innerhalb der Strecke
+      {
+         double x,y,z,abstand_ist;
+         if     (this->isParallelToX1Axis())
+         {
+            x = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            y = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            z = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-y)*(y3m-y)+(z3m-z)*(z3m-z));
+         }
+         else if(this->isParallelToX2Axis())
+         {
+            y = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            z = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            x = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-z)*(y3m-z)+(z3m-x)*(z3m-x));
+         }
+         else if(this->isParallelToX3Axis())
+         {
+            z = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            y = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            x = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-y)*(y3m-y)+(z3m-x)*(z3m-x));
+         }
+         else throw UbException(UB_EXARGS,"cylinder must be parallel to one axis");
+
+         //pruefen, ob Punkt Element von Kreisflaeche
+         //double abstand_ist=sqrt((y2m-y)*(y2m-y)+(z2m-z)*(z2m-z));
+
+         if(UbMath::lessEqual(abstand_ist,mRad))  //Punkt ist Schnittpunkt
+         {
+            bool exists = false;
+            for(int pos=0;pos<(int)schnittpunkte.size();++pos)
+            {
+               if(   fabs(schnittpunkte[pos]->getX1Coordinate()-x)<1.E-13
+                  && fabs(schnittpunkte[pos]->getX2Coordinate()-y)<1.E-13
+                  && fabs(schnittpunkte[pos]->getX3Coordinate()-z)<1.E-13 ) exists=true;
+            }
+
+            if(!exists) schnittpunkte.push_back(new GbPoint3D(x,y,z));
+         }
+      }
+   }
+
+   int nofSchnittpunkte = (int)schnittpunkte.size();
+   if     (nofSchnittpunkte==0) return NULL;
+   else if(nofSchnittpunkte >2) throw UbException(UB_EXARGS,"more than three intersection points - not possible");
+   else if(nofSchnittpunkte==2) return new GbLine3D(schnittpunkte[0],schnittpunkte[1]);
+   else if(nofSchnittpunkte==1)
+   {
+      if     (this->isPointInGbObject3D(&point1)) return new GbLine3D(schnittpunkte[0],new GbPoint3D(point1));
+      else if(this->isPointInGbObject3D(&point2)) return new GbLine3D(schnittpunkte[0],new GbPoint3D(point2));
+      else  return new GbLine3D(schnittpunkte[0],new GbPoint3D(*(schnittpunkte[0]))); //strecke beruehrt clippedLine reduziert sich auf einen Punkt!!!
+   }
+
+   return NULL;
+}
+/*==========================================================*/
+vector<GbTriangle3D*> GbCylinder3D::getSurfaceTriangleSet()
+{
+   double x1ma,x1mb,x2m,x3m;
+   if( this->isParallelToX1Axis() )
+   {
+      x1ma = this->getX1Minimum();
+      x1mb = this->getX1Maximum();
+      x2m  = this->getX2Centroid();
+      x3m  = this->getX3Centroid();
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      x1ma = this->getX2Minimum();
+      x1mb = this->getX2Maximum();
+      x2m  = this->getX1Centroid();
+      x3m  = this->getX3Centroid();
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      x1ma = this->getX3Minimum();
+      x1mb = this->getX3Maximum();
+      x2m  = this->getX2Centroid();
+      x3m  = this->getX1Centroid();
+   }
+   else throw UbException(UB_EXARGS,"cylinder not axis prallel");
+
+   vector<GbTriangle3D*> triangles;
+
+   int segmentsCircle  = 20;
+   double deltaPhi = UbMath::PI/(double)segmentsCircle;
+
+   double phiX1a,phiX1b;
+   double x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+
+   double dXCylinder =  fabs((x1mb-x1ma))/(double)segmentsCircle;
+   int segmentsCylinder = (int)(fabs(x1mb-x1ma)/dXCylinder);
+   for(int segCyl = 0; segCyl<segmentsCylinder; segCyl++)
+   {
+      x1a = x1d = x1ma+segCyl*dXCylinder;
+      x1b = x1c = x1a+dXCylinder;
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  x2m+mRad*std::sin(phiX1a);
+         x3a =  x3m+mRad*std::cos(phiX1a);
+         x2b =  x2m+mRad*std::sin(phiX1b);
+         x3b =  x3m+mRad*std::cos(phiX1b);
+
+         if( this->isParallelToX1Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1b,x2b,x3b),new GbPoint3D(x1b,x2a,x3a),new GbPoint3D(x1a,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1a,x2a,x3a),new GbPoint3D(x1a,x2b,x3b),new GbPoint3D(x1b,x2b,x3b)));
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2b,x1b,x3b),new GbPoint3D(x2a,x1b,x3a),new GbPoint3D(x2a,x1a,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2a,x1a,x3a),new GbPoint3D(x2b,x1a,x3b),new GbPoint3D(x2b,x1b,x3b)));
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3b,x2b,x1b),new GbPoint3D(x3a,x2a,x1b),new GbPoint3D(x3a,x2a,x1a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3a,x2a,x1a),new GbPoint3D(x3b,x2b,x1a),new GbPoint3D(x3b,x2b,x1b)));
+         }
+
+      }
+   }
+
+   int segmentsSide = (int)(mRad/dXCylinder);
+   double radius0, radius1;
+   for(int segCyl = 0; segCyl<segmentsSide; segCyl++)
+   {
+      radius0 = segCyl*dXCylinder;
+      radius1 = radius0+dXCylinder;
+      if(segCyl==segmentsSide-1) radius1=mRad;
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  x2m+radius0*std::sin(phiX1a);
+         x3a =  x3m+radius0*std::cos(phiX1a);
+         x2b =  x2m+radius0*std::sin(phiX1b);
+         x3b =  x3m+radius0*std::cos(phiX1b);
+         x2c =  x2m+radius1*std::sin(phiX1b);
+         x3c =  x3m+radius1*std::cos(phiX1b);
+         x2d =  x2m+radius1*std::sin(phiX1a);
+         x3d =  x3m+radius1*std::cos(phiX1a);
+
+         if( this->isParallelToX1Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1ma,x2a,x3a),new GbPoint3D(x1ma,x2b,x3b),new GbPoint3D(x1ma,x2c,x3c)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1ma,x2c,x3c),new GbPoint3D(x1ma,x2d,x3d),new GbPoint3D(x1ma,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1mb,x2c,x3c),new GbPoint3D(x1mb,x2b,x3b),new GbPoint3D(x1mb,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1mb,x2a,x3a),new GbPoint3D(x1mb,x2d,x3d),new GbPoint3D(x1mb,x2c,x3c)));
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2a,x1ma,x3a),new GbPoint3D(x2b,x1ma,x3b),new GbPoint3D(x2c,x1ma,x3c)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2c,x1ma,x3c),new GbPoint3D(x2d,x1ma,x3d),new GbPoint3D(x2a,x1ma,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2c,x1mb,x3c),new GbPoint3D(x2b,x1mb,x3b),new GbPoint3D(x2a,x1mb,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2a,x1mb,x3a),new GbPoint3D(x2d,x1mb,x3d),new GbPoint3D(x2c,x1mb,x3c)));
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3a,x2a,x1ma),new GbPoint3D(x3b,x2b,x1ma),new GbPoint3D(x3c,x2c,x1ma)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3c,x2c,x1ma),new GbPoint3D(x3d,x2d,x1ma),new GbPoint3D(x3a,x2a,x1ma)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3c,x2c,x1mb),new GbPoint3D(x3b,x2b,x1mb),new GbPoint3D(x3a,x2a,x1mb)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3a,x2a,x1mb),new GbPoint3D(x3d,x2d,x1mb),new GbPoint3D(x3c,x2c,x1mb)));
+         }
+      }
+   }
+
+   return triangles;
+}
+/*==========================================================*/
+void GbCylinder3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+   float x1ma,x1mb,x2m,x3m;
+   if( this->isParallelToX1Axis() )
+   {
+      x1ma = (float)this->getX1Minimum();
+      x1mb = (float)this->getX1Maximum();
+      x2m  = (float)this->getX2Centroid();
+      x3m  = (float)this->getX3Centroid();
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      x1ma = (float)this->getX2Minimum();
+      x1mb = (float)this->getX2Maximum();
+      x2m  = (float)this->getX1Centroid();
+      x3m  = (float)this->getX3Centroid();
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      x1ma = (float)this->getX3Minimum();
+      x1mb = (float)this->getX3Maximum();
+      x2m  = (float)this->getX2Centroid();
+      x3m  = (float)this->getX1Centroid();
+   }
+   else throw UbException(UB_EXARGS,"cylinder not axis prallel");
+
+   int segmentsCircle  = 20;
+   double deltaPhi = UbMath::PI/(double)segmentsCircle;
+
+   double phiX1a,phiX1b;
+   float x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+
+   double dXCylinder =  fabs((x1mb-x1ma))/(double)segmentsCircle;
+   int segmentsCylinder = (int)(fabs(x1mb-x1ma)/dXCylinder);
+   int nodenr = 0;
+   for(int segCyl = 0; segCyl<segmentsCylinder; segCyl++)
+   {
+      x1a = x1d = (float)(x1ma+segCyl*dXCylinder);
+      x1b = x1c = (float)(x1a+dXCylinder);
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  (float)(x2m+mRad*std::sin(phiX1a));
+         x3a =  (float)(x3m+mRad*std::cos(phiX1a));
+         x2b =  (float)(x2m+mRad*std::sin(phiX1b));
+         x3b =  (float)(x3m+mRad*std::cos(phiX1b));
+
+         if( this->isParallelToX1Axis() )
+         {
+            nodes.push_back( makeUbTuple(x1b,x2b,x3b) ); nodes.push_back( makeUbTuple(x1b,x2a,x3a) ); nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1a,x2a,x3a) ); nodes.push_back( makeUbTuple(x1a,x2b,x3b) ); nodes.push_back( makeUbTuple(x1b,x2b,x3b) );
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            nodes.push_back( makeUbTuple(x2b,x1b,x3b) ); nodes.push_back( makeUbTuple(x2a,x1b,x3a) ); nodes.push_back( makeUbTuple(x2a,x1a,x3a) );
+            nodes.push_back( makeUbTuple(x2a,x1a,x3a) ); nodes.push_back( makeUbTuple(x2b,x1a,x3b) ); nodes.push_back( makeUbTuple(x2b,x1b,x3b) );
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            nodes.push_back( makeUbTuple(x3b,x2b,x1b) ); nodes.push_back( makeUbTuple(x3a,x2a,x1b) ); nodes.push_back( makeUbTuple(x3a,x2a,x1a) );
+            nodes.push_back( makeUbTuple(x3a,x2a,x1a) ); nodes.push_back( makeUbTuple(x3b,x2b,x1a) ); nodes.push_back( makeUbTuple(x3b,x2b,x1b) );
+         }
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+      }
+   }
+
+   int segmentsSide = (int)(mRad/dXCylinder);
+   double radius0, radius1;
+   for(int segCyl = 0; segCyl<segmentsSide; segCyl++)
+   {
+      radius0 = segCyl*dXCylinder;
+      radius1 = radius0+dXCylinder;
+      if(segCyl==segmentsSide-1) radius1=mRad;
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a = x2m+(float)(radius0*std::sin(phiX1a));
+         x3a = x3m+(float)(radius0*std::cos(phiX1a));
+         x2b = x2m+(float)(radius0*std::sin(phiX1b));
+         x3b = x3m+(float)(radius0*std::cos(phiX1b));
+         x2c = x2m+(float)(radius1*std::sin(phiX1b));
+         x3c = x3m+(float)(radius1*std::cos(phiX1b));
+         x2d = x2m+(float)(radius1*std::sin(phiX1a));
+         x3d = x3m+(float)(radius1*std::cos(phiX1a));
+
+         if( this->isParallelToX1Axis() )
+         {
+            nodes.push_back( makeUbTuple(x1ma,x2a,x3a) ); nodes.push_back( makeUbTuple(x1ma,x2b,x3b) ); nodes.push_back( makeUbTuple(x1ma,x2c,x3c) );
+            nodes.push_back( makeUbTuple(x1ma,x2c,x3c) ); nodes.push_back( makeUbTuple(x1ma,x2d,x3d) ); nodes.push_back( makeUbTuple(x1ma,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1mb,x2c,x3c) ); nodes.push_back( makeUbTuple(x1mb,x2b,x3b) ); nodes.push_back( makeUbTuple(x1mb,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1mb,x2a,x3a) ); nodes.push_back( makeUbTuple(x1mb,x2d,x3d) ); nodes.push_back( makeUbTuple(x1mb,x2c,x3c) );
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            nodes.push_back( makeUbTuple(x2a,x1ma,x3a) ); nodes.push_back( makeUbTuple(x2b,x1ma,x3b) ); nodes.push_back( makeUbTuple(x2c,x1ma,x3c) );
+            nodes.push_back( makeUbTuple(x2c,x1ma,x3c) ); nodes.push_back( makeUbTuple(x2d,x1ma,x3d) ); nodes.push_back( makeUbTuple(x2a,x1ma,x3a) );
+            nodes.push_back( makeUbTuple(x2c,x1mb,x3c) ); nodes.push_back( makeUbTuple(x2b,x1mb,x3b) ); nodes.push_back( makeUbTuple(x2a,x1mb,x3a) );
+            nodes.push_back( makeUbTuple(x2a,x1mb,x3a) ); nodes.push_back( makeUbTuple(x2d,x1mb,x3d) ); nodes.push_back( makeUbTuple(x2c,x1mb,x3c) );
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            nodes.push_back( makeUbTuple(x3a,x2a,x1ma) ); nodes.push_back( makeUbTuple(x3b,x2b,x1ma) ); nodes.push_back( makeUbTuple(x3c,x2c,x1ma) );
+            nodes.push_back( makeUbTuple(x3c,x2c,x1ma) ); nodes.push_back( makeUbTuple(x3d,x2d,x1ma) ); nodes.push_back( makeUbTuple(x3a,x2a,x1ma) );
+            nodes.push_back( makeUbTuple(x3c,x2c,x1mb) ); nodes.push_back( makeUbTuple(x3b,x2b,x1mb) ); nodes.push_back( makeUbTuple(x3a,x2a,x1mb) );
+            nodes.push_back( makeUbTuple(x3a,x2a,x1mb) ); nodes.push_back( makeUbTuple(x3d,x2d,x1mb) ); nodes.push_back( makeUbTuple(x3c,x2c,x1mb) );
+         }
+
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+      }
+   }
+}
+/*==========================================================*/
+void GbCylinder3D::addSurfaceTriangleSetSegments(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles, int segmentsRound, int segmentsHeight )
+{
+   float x1ma,x1mb,x2m,x3m;
+   if( this->isParallelToX1Axis() )
+   {
+      x1ma = (float)this->getX1Minimum();
+      x1mb = (float)this->getX1Maximum();
+      x2m  = (float)this->getX2Centroid();
+      x3m  = (float)this->getX3Centroid();
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      x1ma = (float)this->getX2Minimum();
+      x1mb = (float)this->getX2Maximum();
+      x2m  = (float)this->getX1Centroid();
+      x3m  = (float)this->getX3Centroid();
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      x1ma = (float)this->getX3Minimum();
+      x1mb = (float)this->getX3Maximum();
+      x2m  = (float)this->getX2Centroid();
+      x3m  = (float)this->getX1Centroid();
+   }
+   else throw UbException(UB_EXARGS,"cylinder not axis prallel");
+
+   int segmentsCircle  = segmentsRound;
+   double deltaPhi = UbMath::PI/(double)segmentsCircle;
+
+   double phiX1a,phiX1b;
+   float x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+
+   double dXCylinder =  fabs((x1mb-x1ma))/(double)segmentsHeight; //hier evtl. segmentsheight
+   int segmentsCylinder = (int)(fabs(x1mb-x1ma)/dXCylinder);
+   int nodenr = 0;
+   for(int segCyl = 0; segCyl<segmentsCylinder; segCyl++)
+   {
+      x1a = x1d = (float)(x1ma+segCyl*dXCylinder);
+      x1b = x1c = (float)(x1a+dXCylinder);
+
+      //for(phiX1a=2.0*UbMath::PI; phiX1a>0.0; phiX1a-=deltaPhi)
+      for(phiX1a=0.0; phiX1a<2.0*UbMath::PI-0.5*deltaPhi; phiX1a+=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  (float)(x2m+mRad*std::sin(phiX1a));
+         x3a =  (float)(x3m+mRad*std::cos(phiX1a));
+         x2b =  (float)(x2m+mRad*std::sin(phiX1b));
+         x3b =  (float)(x3m+mRad*std::cos(phiX1b));
+
+         if( this->isParallelToX1Axis() )
+         {
+            nodes.push_back( makeUbTuple(x1b,x2b,x3b) ); nodes.push_back( makeUbTuple(x1b,x2a,x3a) ); nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1a,x2a,x3a) ); nodes.push_back( makeUbTuple(x1a,x2b,x3b) ); nodes.push_back( makeUbTuple(x1b,x2b,x3b) );
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            nodes.push_back( makeUbTuple(x2b,x1b,x3b) ); nodes.push_back( makeUbTuple(x2a,x1b,x3a) ); nodes.push_back( makeUbTuple(x2a,x1a,x3a) );
+            nodes.push_back( makeUbTuple(x2a,x1a,x3a) ); nodes.push_back( makeUbTuple(x2b,x1a,x3b) ); nodes.push_back( makeUbTuple(x2b,x1b,x3b) );
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            nodes.push_back( makeUbTuple(x3b,x2b,x1b) ); nodes.push_back( makeUbTuple(x3a,x2a,x1b) ); nodes.push_back( makeUbTuple(x3a,x2a,x1a) );
+            nodes.push_back( makeUbTuple(x3a,x2a,x1a) ); nodes.push_back( makeUbTuple(x3b,x2b,x1a) ); nodes.push_back( makeUbTuple(x3b,x2b,x1b) );
+         }
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+      }
+   }
+
+   int segmentsSide = (int)(mRad/dXCylinder);
+   double radius0, radius1;
+   for(int segCyl = 0; segCyl<segmentsSide; segCyl++)
+   {
+      radius0 = segCyl*dXCylinder;
+      radius1 = radius0+dXCylinder;
+      if(segCyl==segmentsSide-1) radius1=mRad;
+
+      //for(phiX1a=2.0*UbMath::PI; phiX1a>0.0; phiX1a-=deltaPhi)
+      for(phiX1a=0.0; phiX1a<2.0*UbMath::PI-0.5*deltaPhi; phiX1a+=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a = x2m+(float)(radius0*std::sin(phiX1a));
+         x3a = x3m+(float)(radius0*std::cos(phiX1a));
+         x2b = x2m+(float)(radius0*std::sin(phiX1b));
+         x3b = x3m+(float)(radius0*std::cos(phiX1b));
+         x2c = x2m+(float)(radius1*std::sin(phiX1b));
+         x3c = x3m+(float)(radius1*std::cos(phiX1b));
+         x2d = x2m+(float)(radius1*std::sin(phiX1a));
+         x3d = x3m+(float)(radius1*std::cos(phiX1a));
+
+         if( this->isParallelToX1Axis() )
+         {
+            nodes.push_back( makeUbTuple(x1ma,x2a,x3a) ); nodes.push_back( makeUbTuple(x1ma,x2b,x3b) ); nodes.push_back( makeUbTuple(x1ma,x2c,x3c) );
+            nodes.push_back( makeUbTuple(x1ma,x2c,x3c) ); nodes.push_back( makeUbTuple(x1ma,x2d,x3d) ); nodes.push_back( makeUbTuple(x1ma,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1mb,x2c,x3c) ); nodes.push_back( makeUbTuple(x1mb,x2b,x3b) ); nodes.push_back( makeUbTuple(x1mb,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1mb,x2a,x3a) ); nodes.push_back( makeUbTuple(x1mb,x2d,x3d) ); nodes.push_back( makeUbTuple(x1mb,x2c,x3c) );
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            nodes.push_back( makeUbTuple(x2a,x1ma,x3a) ); nodes.push_back( makeUbTuple(x2b,x1ma,x3b) ); nodes.push_back( makeUbTuple(x2c,x1ma,x3c) );
+            nodes.push_back( makeUbTuple(x2c,x1ma,x3c) ); nodes.push_back( makeUbTuple(x2d,x1ma,x3d) ); nodes.push_back( makeUbTuple(x2a,x1ma,x3a) );
+            nodes.push_back( makeUbTuple(x2c,x1mb,x3c) ); nodes.push_back( makeUbTuple(x2b,x1mb,x3b) ); nodes.push_back( makeUbTuple(x2a,x1mb,x3a) );
+            nodes.push_back( makeUbTuple(x2a,x1mb,x3a) ); nodes.push_back( makeUbTuple(x2d,x1mb,x3d) ); nodes.push_back( makeUbTuple(x2c,x1mb,x3c) );
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            nodes.push_back( makeUbTuple(x3a,x2a,x1ma) ); nodes.push_back( makeUbTuple(x3b,x2b,x1ma) ); nodes.push_back( makeUbTuple(x3c,x2c,x1ma) );
+            nodes.push_back( makeUbTuple(x3c,x2c,x1ma) ); nodes.push_back( makeUbTuple(x3d,x2d,x1ma) ); nodes.push_back( makeUbTuple(x3a,x2a,x1ma) );
+            nodes.push_back( makeUbTuple(x3c,x2c,x1mb) ); nodes.push_back( makeUbTuple(x3b,x2b,x1mb) ); nodes.push_back( makeUbTuple(x3a,x2a,x1mb) );
+            nodes.push_back( makeUbTuple(x3a,x2a,x1mb) ); nodes.push_back( makeUbTuple(x3d,x2d,x1mb) ); nodes.push_back( makeUbTuple(x3c,x2c,x1mb) );
+         }
+
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+      }
+   }
+}
+
+/*==========================================================*/
+void GbCylinder3D::objectChanged(UbObservable* changedObject)
+{
+   GbLine3D* line = dynamic_cast<GbLine3D*>(changedObject);
+   if(!line || this->mLine!=line) return;
+
+   this->notifyObserversObjectChanged();
+}
+/*==========================================================*/
+void GbCylinder3D::objectWillBeDeleted(UbObservable* objectForDeletion)
+{
+   if(this->mLine)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->mLine);
+      if(objectForDeletion == observedObj) { this->mLine = NULL; }
+   }
+}
+/*=======================================================*/
+void GbCylinder3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{
+   if( this->isParallelToX1Axis() )
+   {
+      if(!UbMath::equal(sx2,sx3)) throw UbException(UB_EXARGS,"|| to x1 -> different scaling sx2 and sx3 not possible");
+      this->mRad*=sx2;
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      if(!UbMath::equal(sx1,sx3)) throw UbException(UB_EXARGS,"|| to x2 -> different scaling sx1 and sx3 not possible");
+      this->mRad*=sx1;
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      if(!UbMath::equal(sx1,sx2)) throw UbException(UB_EXARGS,"|| to x3 -> different scaling sx1 and sx2 not possible");
+      this->mRad*=sx1;
+   }
+   else throw UbException(UB_EXARGS,"unknown direction");
+
+   this->mLine->scale(sx1,sx2,sx3);
+   //notify observer wird automatisch aufgerufen
+}
+/*==========================================================*/
+void GbCylinder3D::write(UbFileOutput* out)
+{
+   out->writeString(this->getCreator()->getTypeID());
+   mLine->write(out);
+   out->writeDouble(mRad);
+   out->writeInteger(cylinderType);
+}
+/*==========================================================*/
+void GbCylinder3D::read(UbFileInput* in)
+{
+   in->readString();
+   mLine = new GbLine3D;
+   mLine->read(in);
+   mRad         = in->readDouble();
+   cylinderType = in->readInteger();
+}
+/*==========================================================*/
+double GbCylinder3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   /*
+   Distance D of the intersection between a Ray((ox1,ox2,ox3),(dx1,dx2,dx3)) and a Plane P: ax+by+cz+d=0
+   dc = a*dx1 + b*dx2 + c*dx3
+   dw = a*ox1 + b*ox2 + c*ox3 + d
+   D =   - dw / dc
+   */
+   double px1, px2, px3;
+   double d = Ub::inf; // Distance to Min or Max Plane of the Zylinder
+                       // final distance should be less that d
+
+   if( this->isParallelToX1Axis() )
+   {
+      if     (UbMath::equal(x1 ,minX1) && UbMath::negative(rx1))    return -1.0;
+      else if(UbMath::equal(x1 ,maxX1) && UbMath::positive(rx1))    return -1.0;
+
+      //falls die Linie nicht parallel zu den Seitenflaechen ist
+      if( x1< minX1  ||  x1 > maxX1 ) //nur fuer punkte links und rechts des cylinders
+      {
+         px1 = (x1 < minX1 ? minX1 : maxX1);
+         //falls die Linie nicht parallel zu den Seitenflaechen ist
+         if( !UbMath::zero(rx1) )
+         {
+            // Plane a= 0, b= 1, c=0 d= -1*px2
+            d   = -1.0*(x1 - px1) / rx1;
+            px2 = x2 + d*rx2;
+            px3 = x3 + d*rx3;
+
+            if(UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad))
+            {
+               if     (x1 < minX1 && rx1>0.0 ) d = Ub::inf;  //punkt liegt "links" vom cylinder und strahl hat evtl weiteren SP auf oberflaeche
+               else if(x1 > maxX1 && rx1<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else
+      {
+         //if     (UbMath::negative(rx1)) d = -1.0 * (x1 - minX1) / rx1;
+         //else if(UbMath::positive(rx1)) d = -1.0 * (x1 - maxX1) / rx1;
+         if     (UbMath::negative(rx1)) d = -1.0 * (x1 - maxX1) / rx1;
+         else if(UbMath::positive(rx1)) d = -1.0 * (x1 - minX1) / rx1;
+      }
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      if     (UbMath::equal(x2 ,minX2) && UbMath::negative(rx2))    return -1;
+      else if(UbMath::equal(x2 ,maxX2) && UbMath::positive(rx2))    return -1;
+
+      if( minX2 > x2  ||  x2 > maxX2 )
+      {
+         px2 = (x2 < minX2 ? minX2 : maxX2);
+         //falls die Linie nicht parallel zu den Seitenflaechen ist
+         if( !UbMath::zero(rx2) )
+         {
+            // Plane a= 0, b= 1, c=0 d= -1*px2
+            d   = -1*(x2 - px2) / rx2;
+            px1 = x1 + d*rx1;
+            px3 = x3 + d*rx3;
+
+            if (UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad))
+            {
+               if     (x2 < minX2 && rx2>0.0 ) d = Ub::inf;  //punkt liegt "links oberhalb" vom cylinder und strahl mit pos x1 hat evtl weiteren SP auf oberflaeche
+               else if(x2 > maxX2 && rx2<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else
+      {
+         if     (UbMath::negative(rx2)) d = -1.0 * (x2 - minX2) / rx2;
+         else if(UbMath::positive(rx2)) d = -1.0 * (x2 - maxX2) / rx2;
+      }
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      if     (UbMath::equal(x3, minX3) && UbMath::negative(rx3)) return -1.0;
+      else if(UbMath::equal(x3, maxX3) && UbMath::positive(rx3)) return -1.0;
+
+      if(minX3 > x3  ||  x3 > maxX3 )
+      {
+         px3 = (x3 < minX3 ? minX3 : maxX3);
+         //falls die Linie nicht parallel zu den Seitenflaechen ist
+         if (!UbMath::zero(rx3))
+         {
+            // Plane a= 0, b= 0, c=1 d= -1*px3
+            d   = -1.0*(x3 - px3) / rx3;
+            px2 = x2 + d*rx2;
+            px1 = x1 + d*rx1;
+            if( UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad) )
+            {
+               if     (x3 < minX3 && rx3>0.0 ) d = Ub::inf;
+               else if(x3 > maxX3 && rx3<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else
+      {
+         if     (UbMath::negative(rx3)) d = -1.0 * (x3 - minX3) / rx3;
+         else if(UbMath::positive(rx3)) d = -1.0 * (x3 - maxX3) / rx3;
+      }
+   }
+   else throw UbException(UB_EXARGS,"funzt nur bei achsen parallelem cylinder");
+   //////////////////////////////////////////////////////////////////////////
+   //Q berechnen fuer Infinity Zylinder
+   double axisX1 = mLine->getPoint2()->x1 - mLine->getPoint1()->x1;  /* Axis of the cylinder   */
+   double axisX2 = mLine->getPoint2()->x2 - mLine->getPoint1()->x2;  /* mit p1 als base of cylinder */
+   double axisX3 = mLine->getPoint2()->x3 - mLine->getPoint1()->x3;
+
+   //double dirlen = mLine->getLength();
+   //double abs, t, s;
+
+   double RCx1 = x1 - mLine->getPoint1()->x1;
+   double RCx2 = x2 - mLine->getPoint1()->x2;
+   double RCx3 = x3 - mLine->getPoint1()->x3;
+
+   //n = ray x axis
+   double nx1 = rx2*axisX3 - rx3*axisX2;
+   double nx2 = rx3*axisX1 - rx1*axisX3;
+   double nx3 = rx1*axisX2 - rx2*axisX1;
+   double nLength = nx1*nx1 + nx2*nx2 + nx3*nx3;
+
+   double abs;
+   if( UbMath::zero( nLength ) )
+   {  /* ray parallel to cyl  */
+      //abs = RC dot axis
+      double tmpabs = RCx1*axisX1 + RCx2*axisX2 + RCx3*axisX3;
+      double dx1 = RCx1 - tmpabs*axisX1;
+      double dx2 = RCx2 - tmpabs*axisX2;
+      double dx3 = RCx3 - tmpabs*axisX3;
+      if( UbMath::greater( dx1*dx1 + dx2*dx2 + dx3*dx3 , mRad*mRad) )
+         return -1.0;
+   }
+
+   //normalize "n"
+   nLength = std::sqrt(nLength);
+   double invnLength = 1.0/nLength;
+   nx1*=invnLength;
+   nx2*=invnLength;
+   nx3*=invnLength;
+
+   //shortest distance  = fabs( RC dot n )
+   abs = std::fabs( RCx1*nx1 + RCx2*nx2 + RCx3*nx3 );
+
+   if( UbMath::lessEqual(abs, mRad) )
+   {                    /* if ray hits cylinder */
+      //Ox1 = RC x axis
+      double Ox1 = RCx2*axisX3 - RCx3*axisX2;
+      double Ox2 = RCx3*axisX1 - RCx1*axisX3;
+      double Ox3 = RCx1*axisX2 - RCx2*axisX1;
+      //t = - O dot n / nLength;
+      double t = - (Ox1*nx1 + Ox2*nx2 + Ox3*nx3) / nLength;
+
+      //O = n x axis;
+      Ox1 = nx2*axisX3 - nx3*axisX2;
+      Ox2 = nx3*axisX1 - nx1*axisX3;
+      Ox3 = nx1*axisX2 - nx2*axisX1;
+
+      //normalize O
+      invnLength = 1.0/std::sqrt(Ox1*Ox1 + Ox2*Ox2 + Ox3*Ox3);
+      Ox1*=invnLength;
+      Ox2*=invnLength;
+      Ox3*=invnLength;
+
+      double s = std::fabs( sqrt(mRad*mRad - abs*abs) / (rx1*Ox1 + rx2*Ox2 + rx3*Ox3) );
+
+      //Wert a) t-s: entering distance
+      //     b) t+s: exiting  distance
+      //
+      // -> we only consider factors in ray-dir -> means positive values!
+      //    (s is always positive)
+
+      if(t>s)
+      {
+         return UbMath::min( t-s, d );
+      }
+      else if( (t+s) > 0 )
+      {
+         return UbMath::min( t+s, d );
+      }
+   }
+
+   return -1.0;
+}
+/*==========================================================*/
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbCylinder3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbCylinder3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0e5425c9c77a6681f7b1321afa80299e0b9b931
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbCylinder3D.h
@@ -0,0 +1,153 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBCYLINDER3D_H
+#define GBCYLINDER3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <basics/utilities/UbObserver.h>
+
+class GbPoint3D;
+class GbLine3D;
+class GbTriangle3D;
+
+class GbObject3DCreator;
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbCylinder3D;
+typedef VFSharedPtr<GbCylinder3D> GbCylinder3DPtr;
+
+
+class GbCylinder3D : public GbObject3D , public UbObserver 
+{
+public:
+   GbCylinder3D();
+	GbCylinder3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b, const double& radius);
+	GbCylinder3D(GbPoint3D* p1, GbPoint3D* p2, const double& radius);
+	GbCylinder3D(GbLine3D* line, const double& rad);
+	GbCylinder3D(GbCylinder3D* cylinder);
+	~GbCylinder3D();    
+
+	GbCylinder3D* clone() { return new GbCylinder3D(this); }
+	void finalize();
+
+	double     getRadius() { return this->mRad; };
+	GbLine3D*  getLine() {return mLine;}
+	GbPoint3D* getPoint1();
+	GbPoint3D* getPoint2();
+
+	void setRadius(const double& radius);
+	void setLine(GbLine3D* line);
+	void setPoint1(const double& x1, const double& x2, const double& x3);
+	void setPoint2(const double& x1, const double& x2, const double& x3);
+
+	bool isParallelToX1Axis() { return((this->cylinderType & X1PARALLEL        )    ==  X1PARALLEL        );}
+	bool isParallelToX2Axis() { return((this->cylinderType & X2PARALLEL        )    ==  X2PARALLEL        );}
+	bool isParallelToX3Axis() { return((this->cylinderType & X3PARALLEL        )    ==  X3PARALLEL        );}
+	bool isNotParallelToAxis(){ return((this->cylinderType & NOTPARALLELTOAXIS )    ==  NOTPARALLELTOAXIS );}
+
+	double getHeight(); 
+
+	void scale(const double& sx1, const double& sx2, const double& sx3);
+
+   void translate(const double& x1, const double& x2, const double& x3) 
+   {
+      this->mLine->translate( x1, x2, x3 );
+      this->calculateValues();
+      //this->notifyObserversObjectChanged();
+   }
+
+   double getX1Centroid() { return centerX1; }
+   double getX1Minimum()  { return minX1;    }
+	double getX1Maximum()  { return maxX1;    }
+	double getX2Centroid() { return centerX2; }
+	double getX2Minimum()  { return minX2;    }
+	double getX2Maximum()  { return maxX2;    }
+	double getX3Centroid() { return centerX3; }
+	double getX3Minimum()  { return minX3;    }
+	double getX3Maximum()  { return maxX3;    }
+
+	bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); 
+	bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary); 
+   bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+	GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+   
+   //SG ausdokumentieren, da der nur unendlcihe Zylinder macht ...
+   //bool hasRaytracing() { return true; }
+   bool hasRaytracing() { return false; }
+   bool raytracingSupportsPointsInside() { return true; }
+   
+   
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+	std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+   void addSurfaceTriangleSetSegments(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles, int segmentsRound, int segmentsHeight );
+
+	std::string toString();
+	ObObjectCreator* getCreator();
+	void write(UbFileOutput* out);
+	void read(UbFileInput* in);
+
+	//virtuelle Methoden von UbObserver
+	void objectChanged(UbObservable* changedObject);
+	void objectWillBeDeleted(UbObservable* objectForDeletion);
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & mLine;
+      ar & mRad;
+      ar & cylinderType;
+      
+      if( ArchiveTools::isReading(ar) )
+         this->calculateValues();
+   }
+#endif //CAB_RCF
+   
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+
+protected:
+   void calculateValues();
+
+   GbLine3D* mLine;
+	double    mRad;
+
+   double minX1, minX2, minX3;
+   double maxX1, maxX2, maxX3;
+   double centerX1, centerX2, centerX3;
+
+	int cylinderType;
+
+	//void berechneQuerschnittsWerte();
+   static const int NOTPARALLELTOAXIS  = (1<<0); //1
+   static const int X1PARALLEL         = (1<<1); //2
+   static const int X2PARALLEL         = (1<<2); //4
+   static const int X3PARALLEL         = (1<<3); //8
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbCylinder3D >("GbCylinder3D")           , SF_GbCylinder3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbCylinder3D >() ), SF_GbCylinder3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbCylinder3D>()  ), SF_GbCylinder3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpace3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpace3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0d1072db51f301511642803e076dcd5afd63a925
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpace3D.cpp
@@ -0,0 +1,99 @@
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+
+using namespace std;
+
+/*==========================================================*/
+GbHalfSpace3D::GbHalfSpace3D(GbTriangle3D* triangle)
+{
+   GbPoint3D* PointA = triangle->getPoint1();
+   GbPoint3D* PointB = triangle->getPoint2();
+   GbPoint3D* PointC = triangle->getPoint3();
+          
+   GbVector3D A(PointA->x1, PointA->x2, PointA->x3 );
+   GbVector3D BA(PointB->x1-PointA->x1, PointB->x2-PointA->x2, PointB->x3-PointA->x3 );
+   GbVector3D CA(PointC->x1-PointA->x1, PointC->x2-PointA->x2, PointC->x3-PointA->x3 );
+   GbVector3D BACA = BA.Cross(CA);
+   //this->Normal = PointB->subtract(PointA)->cross(PointC->subtract(PointA))->normalize();
+   BACA.Normalize(); 
+   //this->Normal = BACA; 
+   normalX = BACA[0];
+   normalY = BACA[1]; 
+   normalZ = BACA[2]; 
+   //this->d = this->Normal.Dot(A);
+   this->d = normalX*A[0] + normalY*A[1] + normalZ*A[2] ;
+}
+/*==========================================================*/
+GbHalfSpace3D::GbHalfSpace3D(GbPoint3D* PointA, GbPoint3D* PointB, GbPoint3D* PointC)
+{
+   GbVector3D A(PointA->x1, PointA->x2, PointA->x3 );
+   GbVector3D BA(PointB->x1-PointA->x1, PointB->x2-PointA->x2, PointB->x3-PointA->x3 );
+   GbVector3D CA(PointC->x1-PointA->x1, PointC->x2-PointA->x2, PointC->x3-PointA->x3 );
+   GbVector3D BACA = BA.Cross(CA);
+	//this->Normal = PointB->subtract(PointA)->cross(PointC->subtract(PointA))->normalize();
+   BACA.Normalize(); 
+	//this->Normal = BACA; 
+   normalX = BACA[0];
+   normalY = BACA[1]; 
+   normalZ = BACA[2]; 
+   //this->d = this->Normal.Dot(A);
+   this->d = normalX*A[0] + normalY*A[1] + normalZ*A[2] ;
+}
+/*==========================================================*/
+GbHalfSpace3D::GbHalfSpace3D(GbPoint3D* PointA, GbPoint3D* PointB)
+{
+   GbVector3D A(PointA->x1, PointA->x2, PointA->x3 );
+   GbVector3D B(PointB->x1, PointB->x2, PointB->x3 );
+	GbVector3D K(0.0,0.0,0.99); // the vector from PointA - third point
+   
+	GbVector3D PointBA = B-A;
+	GbVector3D PointBAK = PointBA.Cross(K);
+   PointBAK.Normalize();
+	
+   //this->Normal = PointBAK;
+   normalX = PointBAK[0];
+   normalY = PointBAK[1]; 
+   normalZ = PointBAK[2]; 
+   
+   //this->d = this->Normal.Dot(A);
+   this->d = normalX*PointA->x1 + normalY*PointA->x2 + normalZ*PointA->x3;
+}
+/*==========================================================*/
+GbHalfSpace3D::GbHalfSpace3D(  const double& p1x, const double& p1y, const double& p1z
+                             , const double& p2x, const double& p2y, const double& p2z
+                             , const double& p3x, const double& p3y, const double& p3z )
+{
+   double p2minusP1x = p2x-p1x;
+   double p2minusP1y = p2y-p1y;
+   double p2minusP1z = p2z-p1z;
+   
+   double P3minusP1x = p3x-p1x;
+   double P3minusP1y = p3y-p1y;
+   double P3minusP1z = p3z-p1z;
+   
+   //normal = BA x CA
+   normalX = p2minusP1y*P3minusP1z - p2minusP1z*P3minusP1y;
+   normalY = p2minusP1z*P3minusP1x - p2minusP1x*P3minusP1z;
+   normalZ = p2minusP1x*P3minusP1y - p2minusP1y*P3minusP1x;
+   
+   //normalize BACA
+   double oneOverNormalLength = 1.0 / ( std::sqrt( normalX*normalX + normalY*normalY + normalZ*normalZ ) );
+   normalX *= oneOverNormalLength;
+   normalY *= oneOverNormalLength;
+   normalZ *= oneOverNormalLength;
+
+   //d = normal * p1
+   this->d = normalX*p1x + normalY*p1y + normalZ*p1z;
+}
+/*==========================================================*/
+GbHalfSpace3D::GbHalfSpace3D( const double& p1x, const double& p1y, const double& p1z,
+                              const double& nx, const double& ny, const double& nz)
+{
+	//normal = BA x CA
+	normalX =nx;
+	normalY =ny;
+	normalZ =nz;
+
+	//d = normal * p1
+	this->d = nx*p1x + ny*p1y + nz*p1z;
+}
+/*==========================================================*/
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpace3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpace3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..8dfea3e74f4d7ce3745a3eadc9410061eae9b0f7
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpace3D.h
@@ -0,0 +1,86 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBHALFSPACE3D_H
+#define GBHALFSPACE3D_H
+
+#include <sstream>
+#include <iostream>
+
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/GbVector3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbHalfSpace3D;
+typedef VFSharedPtr<GbHalfSpace3D> GbHalfSpace3DPtr;
+
+
+/*=========================================================================*/
+/* GbHalfSpace3D                                                             */
+/*                                                                         */
+/**
+* This Class helps in performing some operations on a halfspace defined by 2 or 3 points
+*/
+
+class GbHalfSpace3D                            
+{
+public:
+   GbHalfSpace3D(GbTriangle3D* triangle);
+
+   GbHalfSpace3D(GbPoint3D* PointA, GbPoint3D* PointB, GbPoint3D* PointC);
+
+   GbHalfSpace3D(GbPoint3D* PointA, GbPoint3D* PointB);
+
+   GbHalfSpace3D(  const double& p1x, const double& p1y, const double& p1z
+                 , const double& p2x, const double& p2y, const double& p2z
+                 , const double& p3x, const double& p3y, const double& p3z );
+   GbHalfSpace3D( const double& p1x, const double& p1y, const double& p1z,
+                  const double& nx, const double& ny, const double& nz);
+
+   /*=======================================================*/
+   std::string getTypeID() {return "GbHalfSpace3D"; }
+   /*=============================================*/
+   bool ptInside(const double& x, const double& y, const double& z)
+   {
+      return UbMath::greaterEqual( normalX*x + normalY*y + normalZ*z, this->d );
+   }
+   /*=============================================*/
+   bool ptInside(GbPoint3D* pointX)
+   {
+      //GbVector3D X(PointX->x1, PointX->x2, PointX->x3 );
+      //return UbMath::greaterEqual(this->Normal.Dot(X), this->d);      
+      return UbMath::greaterEqual(  normalX*pointX->x1 + normalY*pointX->x2 + normalZ*pointX->x3, this->d );
+   }
+   /*=============================================*/
+   bool ptInside(GbVector3D& x)
+   {
+      //return UbMath::greaterEqual(this->Normal.Dot(X), this->d);
+      return UbMath::greaterEqual(  normalX*x[0] + normalY*x[1] + normalZ*x[2], this->d );
+   }
+   /*=============================================*/
+   double getDistance(const double& x1p, const double& x2p, const double& x3p)
+   {
+      return (normalX*x1p + normalY*x2p + normalZ*x3p) - this->d;
+   }
+
+   const double& getNormalX() { return this->normalX; }
+   const double& getNormalY() { return this->normalY; }
+   const double& getNormalZ() { return this->normalZ; }
+   const double& getD()       { return this->d;       }
+
+private:
+   //GbVector3D Normal;
+   double normalX;
+   double normalY;
+   double normalZ;
+   double d;
+};
+/*=========================================================================*/
+
+#endif //GBHALFSPACE3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpaceKrischan3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpaceKrischan3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0cfb68ce2b7b38091c63869cbf78107798318b70
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpaceKrischan3D.cpp
@@ -0,0 +1,267 @@
+#include <numerics/geometry3d/GbHalfSpaceKrischan3D.h>
+
+using namespace std;
+
+/*==========================================================*/
+GbHalfSpaceKrischan3D::GbHalfSpaceKrischan3D(GbTriangle3D* triangle)
+{
+   GbPoint3D* PointA = triangle->getPoint1();
+   GbPoint3D* PointB = triangle->getPoint2();
+   GbPoint3D* PointC = triangle->getPoint3();
+          
+   GbVector3D A(PointA->x1, PointA->x2, PointA->x3 );
+   GbVector3D BA(PointB->x1-PointA->x1, PointB->x2-PointA->x2, PointB->x3-PointA->x3 );
+   GbVector3D CA(PointC->x1-PointA->x1, PointC->x2-PointA->x2, PointC->x3-PointA->x3 );
+   GbVector3D BACA = BA.Cross(CA);
+   //this->Normal = PointB->subtract(PointA)->cross(PointC->subtract(PointA))->normalize();
+   BACA.Normalize(); 
+   this->Normal = BACA; 
+   this->d = this->Normal.Dot(A);
+}
+/*==========================================================*/
+GbHalfSpaceKrischan3D::GbHalfSpaceKrischan3D(GbPoint3D* PointA, GbPoint3D* PointB, GbPoint3D* PointC)
+{
+   GbVector3D A(PointA->x1, PointA->x2, PointA->x3 );
+   GbVector3D BA(PointB->x1-PointA->x1, PointB->x2-PointA->x2, PointB->x3-PointA->x3 );
+   GbVector3D CA(PointC->x1-PointA->x1, PointC->x2-PointA->x2, PointC->x3-PointA->x3 );
+   GbVector3D BACA = BA.Cross(CA);
+	//this->Normal = PointB->subtract(PointA)->cross(PointC->subtract(PointA))->normalize();
+   BACA.Normalize(); 
+	this->Normal = BACA; 
+	this->d = this->Normal.Dot(A);
+}
+/*==========================================================*/
+GbHalfSpaceKrischan3D::GbHalfSpaceKrischan3D(GbPoint3D* PointA, GbPoint3D* PointB)
+{
+   GbVector3D A(PointA->x1, PointA->x2, PointA->x3 );
+   GbVector3D B(PointB->x1, PointB->x2, PointB->x3 );
+	GbVector3D K(0.0,0.0,0.99); // the vector from PointA - third point
+   
+	GbVector3D PointBA = B-A;
+	GbVector3D PointBAK = PointBA.Cross(K);
+   PointBAK.Normalize();
+	this->Normal = PointBAK;
+	this->d = this->Normal.Dot(A);
+}
+/*==========================================================*/
+GbHalfSpaceKrischan3D::GbHalfSpaceKrischan3D(  const double& p1x, const double& p1y, const double& p1z
+                             , const double& p2x, const double& p2y, const double& p2z
+                             , const double& p3x, const double& p3y, const double& p3z )
+{
+   GbVector3D A( p1x, p1y, p1z );
+   GbVector3D BA(p2x-p1x, p2y-p1y, p2z-p1z );
+   GbVector3D CA(p3x-p1x, p3y-p1y, p3z-p1z );
+   GbVector3D BACA = BA.Cross(CA);
+
+   BACA.Normalize(); 
+   this->Normal = BACA; 
+   this->d = this->Normal.Dot(A);
+}
+/*==========================================================*/
+GbHalfSpaceKrischan3D::GbHalfSpaceKrischan3D(double nx, double ny, double nz, double dist)
+{
+   this->Normal = GbVector3D(nx,ny,nz);
+   this->Normal.Normalize();
+   this->d = dist;
+}
+/*==========================================================*/
+double GbHalfSpaceKrischan3D::getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+
+	double x1 = x1b-x1a;
+   double x2 = x2b-x2a;
+   double x3 = x3b-x3a;
+
+   if( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )       return 1.0*x1*x2*x3;
+   if( !(this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)) )   return 0.0;
+
+   double alpha=0.0;
+   double internX1,internX2,internX3;
+
+   for(int x1vers=0;x1vers<2;x1vers++){
+      for(int x2vers=0;x2vers<2;x2vers++){
+         for(int x3vers=0;x3vers<2;x3vers++){
+            internX1 = x1a + (x1b-x1a)*x1vers;
+            internX2 = x2a + (x2b-x2a)*x2vers;
+            internX3 = x3a + (x3b-x3a)*x3vers;
+
+            // if point is INSIDE the halfspace, distance is smaller than zero
+            // --> loop determines the minimum alpha...i.e. the alpha with maximum absolute value for all points INSIDE the halfspace
+            if( UbMath::lessEqual( this->getDistance(internX1,internX2,internX3) , alpha ) )
+               alpha = this->getDistance(internX1,internX2,internX3);
+            //cout<<zelltyp<<" "<<kugel->getDistance(internX1,internX2,internX3)<<" "<<alpha<<endl;
+         }//end first for
+      }//end second for
+   }//end third for
+
+   // PLIC needs alphas > 0.0
+   alpha = (-1)*alpha;
+
+
+
+   double n[3];
+   n[0] = this->Normal[0];
+   n[1] = this->Normal[1];
+   n[2] = this->Normal[2];
+
+   //cout << "Koordinaten:  "<<x1<<" "<<x2<<" "<<x3<<endl;
+   //cout << "Deltas:       "<<deltaX1<<" "<<deltaX2<<" "<<deltaX3<<endl;
+   //cout << "Halbe Zelle:  "<<halfcelldelta<<endl;
+
+   //cout<<"Centroid:  "<<kugel->getX1Centroid()<<" "<<kugel->getX2Centroid()<<" "<<kugel->getX3Centroid()<<endl;
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double normLength;
+   normLength = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
+   n[0] /= normLength;
+   n[1] /= normLength;
+   n[2] /= normLength;
+
+   if( UbMath::less(n[0],0.0) ) n[0] = -n[0];
+   if( UbMath::less(n[1],0.0) ) n[1] = -n[1];
+   if( UbMath::less(n[2],0.0) ) n[2] = -n[2];
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double dummy;
+   if( UbMath::greater(n[0],n[1])) {dummy=n[1]; n[1]=n[0]; n[0]=dummy;}
+   if( UbMath::greater(n[1],n[2])) {dummy=n[2]; n[2]=n[1]; n[1]=dummy;}
+   if( UbMath::greater(n[0],n[1])) {dummy=n[1]; n[1]=n[0]; n[0]=dummy;}
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double n1,n2,n3;
+   n1=n[0];
+   n2=n[1];
+   n3=n[2];
+
+   double preresult=0.0,result=0.0;
+
+   // 1D Check
+   if ( UbMath::lessEqual(n1,0.00001)&&UbMath::lessEqual(n2,0.00001) )
+   {
+      result = alpha * x1 * x2;
+   }                  
+   // 2D Check
+   else if ( UbMath::lessEqual(n1,0.00001) )
+   {
+      preresult = (2*n2*n3);
+      result = (alpha*alpha)/preresult;
+
+      if( UbMath::greater(alpha,n2*x2) )
+      {
+         result += -(alpha-n2*x2)*(alpha-n2*x2)/preresult;
+      }
+      if( UbMath::greater(alpha,n3*x3) )
+      {
+         result += -(alpha-n3*x3)*(alpha-n3*x3)/preresult;
+      }
+      if( UbMath::greater(alpha,n2*x2+n3*x3) )
+      {
+         result += (alpha-n2*x2-n3*x3)*(alpha-n2*x2-n3*x3)/preresult;
+      }
+
+      // tiefenrichtung mit einmultiplizieren...
+      result *= x1;
+   }	
+   // 3D Check
+   else	
+   { 	
+      preresult =6*n1*n2*n3;
+
+      result = alpha*alpha*alpha/preresult;
+
+      if ( UbMath::greater (alpha,n1*x1))
+      {
+         result+=-((alpha-n1*x1)*(alpha-n1*x1)*(alpha-n1*x1))/preresult;
+      }
+      if (UbMath::greater(alpha,n2*x2))
+      {
+         result+=-((alpha-n2*x2)*(alpha-n2*x2)*(alpha-n2*x2))/preresult;
+      }
+      if (UbMath::greater(alpha,n3*x3))
+      {
+         result+=-((alpha-n3*x3)*(alpha-n3*x3)*(alpha-n3*x3))/preresult;
+      }
+      if (UbMath::greater(alpha,(n1*x1+n2*x2)))
+      {
+         result+=((alpha-(n1*x1+n2*x2))*(alpha-(n1*x1+n2*x2))*(alpha-(n1*x1+n2*x2)))/preresult;
+      }
+      if (UbMath::greater(alpha,(n1*x1+n3*x3)))
+      {
+         result+=((alpha-(n1*x1+n3*x3))*(alpha-(n1*x1+n3*x3))*(alpha-(n1*x1+n3*x3)))/preresult;
+      }
+      if (UbMath::greater(alpha,(n2*x2+n3*x3)))
+      {
+         result+=((alpha-(n2*x2+n3*x3))*(alpha-(n2*x2+n3*x3))*(alpha-(n2*x2+n3*x3)))/preresult;
+      }
+
+      //NEW
+      if (UbMath::greater(alpha,(n1*x1+n2*x2+n3*x3)))
+      {
+         result+= -((alpha-(n1*x1+n2*x2+n3*x3))*(alpha-(n1*x1+n2*x2+n3*x3))*(alpha-(n1*x1+n2*x2+n3*x3)))/preresult;
+      }
+
+   }
+
+   if( !UbMath::inClosedInterval( result/ (x1*x2*x3), -0.01, 1.01) )
+   {
+      stringstream errMsg;
+
+      errMsg << "Danger...Fuellstand "<<result<<" nicht im Interfall [0.0..1.0]" << endl;
+      errMsg << "NormVec: " << n1 << " " << n2 << " " << n3 << endl;
+      errMsg << "Cell:    " << x1 << " " << x2 << " " << x3 << endl;
+      errMsg << "Alpha:   " << alpha << endl;
+ 
+
+      throw UbException( UB_EXARGS, errMsg.str() );
+   }
+
+   return result;
+
+
+   //double eps=0.0;
+   //if( UbMath::equal(n1,0.0) && UbMath::equal(n2,0.0) )
+   //{
+   //   eps = alpha/n3;
+   //}
+   //else if( UbMath::equal(n1,0.0) )
+   //{
+   //   double dim1,dim2;
+   //   dim1 = alpha/n2;
+   //   dim2 = alpha/n3;
+
+   //   eps = 0.5*dim1*dim2;
+   //   if( UbMath::greater(dim1,1.0) )   eps -= 0.5*(dim1-1.0)*dim2/dim1*(dim1-1.0);
+   //   if( UbMath::greater(dim2,1.0) )   eps -= 0.5*(dim2-1.0)*dim1/dim2*(dim2-1.0);
+   //}
+   //else
+   //{
+   //   eps = alpha*alpha*alpha;
+   //   if( UbMath::greater(alpha,n1) )
+   //      eps -= (alpha-n1)*(alpha-n1)*(alpha-n1);
+   //   if( UbMath::greater(alpha,n2) )
+   //      eps -= (alpha-n2)*(alpha-n2)*(alpha-n2);
+   //   if( UbMath::greater(alpha,n3) )
+   //      eps -= (alpha-n3)*(alpha-n3)*(alpha-n3);
+
+   //   if( UbMath::greater(alpha,n1+n2) )
+   //      eps += (alpha-n1-n2)*(alpha-n1-n2)*(alpha-n1-n2);
+   //   if( UbMath::greater(alpha,n1+n3) )
+   //      eps += (alpha-n1-n3)*(alpha-n1-n3)*(alpha-n1-n3);
+   //   if( UbMath::greater(alpha,n2+n3) )
+   //      eps += (alpha-n2-n3)*(alpha-n2-n3)*(alpha-n2-n3);
+
+   //   //attention: use without delta_i
+   //   eps = eps / (6*n[0]*n[1]*n[2]);
+
+   //   eps = eps / (deltaX1*deltaX2*deltaX3);
+   //}
+
+
+   //return(eps) ;
+   //cout << "alpha ist " << alpha << endl;
+   //cout << "fillLevel ist " << eps << endl;
+}
+/*==========================================================*/
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpaceKrischan3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpaceKrischan3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..1765eec1ede944576cd22fdc57d054c4a4cee12f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbHalfSpaceKrischan3D.h
@@ -0,0 +1,205 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GbHalfSpaceKrischan3D_H
+#define GbHalfSpaceKrischan3D_H
+
+#include <sstream>
+#include <iostream>
+
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/GbVector3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+
+/*=========================================================================*/
+/* GbHalfSpaceKrischan3D                                                             */
+/*                                                                         */
+/**
+* This Class helps in performing some operations on a halfspace defined by 2 or 3 points
+*/
+
+class GbHalfSpaceKrischan3D : public GbObject3D , public UbObserver                           
+{
+public:
+   GbHalfSpaceKrischan3D(GbTriangle3D* triangle);
+
+   GbHalfSpaceKrischan3D(GbPoint3D* PointA, GbPoint3D* PointB, GbPoint3D* PointC);
+   
+   GbHalfSpaceKrischan3D(double nx, double ny, double nz, double dist);
+
+   GbHalfSpaceKrischan3D(GbPoint3D* PointA, GbPoint3D* PointB);
+
+   GbHalfSpaceKrischan3D(  const double& p1x, const double& p1y, const double& p1z
+                 , const double& p2x, const double& p2y, const double& p2z
+                 , const double& p3x, const double& p3y, const double& p3z );
+
+   /*=======================================================*/
+   virtual ~GbHalfSpaceKrischan3D() { }
+   /*=======================================================*/
+   std::string getTypeID() {return "GbHalfSpaceKrischan3D"; }
+   /*=============================================*/
+   bool ptInside(const double& x, const double& y, const double& z)
+   {
+      return UbMath::lessEqual(Normal[0]*x+Normal[1]*y+Normal[2]*z, this->d);
+   }
+   /*=============================================*/
+   bool ptInside(GbPoint3D* PointX)
+   {
+      GbVector3D X(PointX->x1, PointX->x2, PointX->x3 );
+      return UbMath::lessEqual(this->Normal.Dot(X), this->d);      
+   }
+   /*=============================================*/
+   bool ptInside(GbVector3D &X)
+   {
+      return UbMath::lessEqual(this->Normal.Dot(X), this->d);
+   }
+
+   /*=====================================================*/
+   //true, wenn 'in Object' oder 'auf Boundary'!
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+   {
+      return (ptInside(x1p,x2p,x3p));
+   }
+   /*=====================================================*/
+   //true, wenn 'in Object' oder 'auf Boundary'!
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+   {
+      return (ptInside(x1p,x2p,x3p));
+   }
+
+   void finalize(){}
+   ObObjectCreator* getCreator(){ return NULL; }
+
+   double getX1Centroid(){ return      0.0; }
+   double getX1Minimum() { return -99999.0; }
+   double getX1Maximum() { return  99999.0; }
+   double getX2Centroid(){ return      0.0; }
+   double getX2Minimum() { return -99999.0; }
+   double getX2Maximum() { return  99999.0; }
+   double getX3Centroid(){ return      0.0; }
+   double getX3Minimum() { return -99999.0; }
+   double getX3Maximum() { return  99999.0; }
+
+   void write(UbFileOutput* out){}
+   void read(UbFileInput* in){}
+
+   GbLine3D* createClippedLine3D (GbPoint3D &point1, GbPoint3D &point2)
+   {
+	   GbPoint3D *p1 = new GbPoint3D(point1);
+	   GbPoint3D *p2 = new GbPoint3D(point2);
+
+	   GbVector3D p1p2( p2->x1-p1->x1, p2->x2-p1->x2, p2->x3-p1->x3);
+
+	   double dist1 = getDistance( p1->x1,p1->x2,p1->x3 );
+	   double dist2 = getDistance( p2->x1,p2->x2,p2->x3 );
+		   
+	   double totalDist = std::abs(dist1) + std::abs(dist2);
+
+	   // Falls erster Punkt nicht drinliegt
+	   if( !ptInside(p1) )
+	   {
+		   if( !ptInside(p2) ) return NULL;
+
+		   // distance ausrechnen (groesser null)
+		   if( UbMath::less( dist1, 0.0 ) )   throw UbException( UB_EXARGS, "Punkt ausserhalb, aber Distanz kleiner null???" );
+
+		   p1->x1 = p1->x1 + dist1/totalDist*p1p2[0];
+		   p1->x2 = p1->x2 + dist1/totalDist*p1p2[1];
+		   p1->x3 = p1->x3 + dist1/totalDist*p1p2[2];	   
+	   }
+	   // Falls zweiter Punkt nicht drinliegt
+	   if( !ptInside(p2) )
+	   {
+		   if( !ptInside(p1) ) return NULL;
+
+		   // distance ausrechnen (groesser null)
+		   if( UbMath::less( dist2, 0.0 ) )   throw UbException( UB_EXARGS, "Punkt ausserhalb, aber Distanz kleiner null???" );
+
+		   p2->x1 = p2->x1 - dist2/totalDist*p1p2[0];
+		   p2->x2 = p2->x2 - dist2/totalDist*p1p2[1];
+		   p2->x3 = p2->x3 - dist2/totalDist*p1p2[2];	   
+	   }
+
+	   return new GbLine3D(p1,p2);
+   }
+ 
+
+   double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+   double getDistance(const double& x1p, const double& x2p, const double& x3p)
+   {
+      return (Normal[0]*x1p + Normal[1]*x2p + Normal[2]*x3p) - this->d;
+   }
+
+   void getNormal( double& n1, double& n2, double& n3 )
+   {
+      n1 = this->Normal[0];
+      n2 = this->Normal[1];
+      n3 = this->Normal[2];
+   }
+
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles)
+   {
+	   std::cout << " addSurfaceTriangleSet(): TO BE DONE AND CHECKED ... " << std::endl;
+   }
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet()
+   {
+      std::vector<GbTriangle3D*> triangles;
+      GbPoint3D p1( 0.0,0.0,0.0 );
+      GbPoint3D p2( 1.0,0.0,0.0 );
+      GbPoint3D p3( 0.0,1.0,0.0 );
+
+      triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p2),new GbPoint3D(p3)));
+
+      return triangles;
+   }
+
+   void objectChanged(UbObservable* changedObject)
+   {
+      return;
+      
+      //GbLine3D* line = dynamic_cast<GbLine3D*>(changedObject);
+      //if(!line || this->mLine!=line) return;
+      //this->notifyObserversObjectChanged();
+   }
+   /*==========================================================*/
+   void objectWillBeDeleted(UbObservable* objectForDeletion)
+   {
+      return;
+      //if(this->mLine)
+      //{
+      //   UbObservable* observedObj = dynamic_cast<UbObservable*>(this->mLine);
+      //   if(objectForDeletion == observedObj) { this->mLine = NULL; }
+      //}
+   }
+
+   ObObject*   clone(){ return NULL; };
+
+   std::string toString()
+   { 
+	   std::stringstream temp;
+
+	   temp << "GbHalfSpaceKrischan3D:   ";
+	   temp << " Distance   " << this->d;
+	   temp << " Norm vec   " << this->Normal[0];
+	   temp << " " << this->Normal[1];
+	   temp << " " << this->Normal[2];
+	   
+	   
+	   return temp.str();
+   };
+
+private:
+   GbVector3D Normal;
+   double d;
+};
+/*=========================================================================*/
+
+#endif //GbHalfSpaceKrischan3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbLine3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbLine3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7cd729d8aca94749f3c92c49c5aec9a8e806f858
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbLine3D.cpp
@@ -0,0 +1,240 @@
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/creator/GbLine3DCreator.h>
+
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+using namespace std;
+
+ObObjectCreator* GbLine3D::getCreator()
+{
+   return GbLine3DCreator::getInstance();
+}
+/*=======================================================*/
+GbLine3D::GbLine3D()
+{
+   p1     = NULL;
+   p2     = NULL;                       
+   length = 0.0;
+}
+/*=======================================================*/
+GbLine3D::GbLine3D(GbPoint3D* point1, GbPoint3D* point2)
+{
+   this->p1 = point1;
+   this->p2 = point2;
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+   this->calculateValues();
+}
+/*=======================================================*/
+GbLine3D::GbLine3D(GbLine3D* line)
+{
+   this->p1 = line->p1->clone();            
+   this->p2 = line->p2->clone();
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+   this->calculateValues();
+}
+/*=======================================================*/
+GbLine3D::~GbLine3D() 
+{
+   if(this->p1) this->p1->removeObserver(this);
+   if(this->p2) this->p2->removeObserver(this);
+}
+/*=======================================================*/
+void GbLine3D::finalize() 
+{
+   if(this->p1) 
+   {
+      this->p1->removeObserver(this);
+      this->p1->finalize();
+      delete this->p1;
+      this->p1 = NULL;
+   }
+   if(this->p2)
+   {
+      this->p2->removeObserver(this);
+      this->p2->finalize();
+      delete this->p2;
+      this->p2 = NULL;
+   }
+}
+/*=======================================================*/
+vector<GbTriangle3D*> GbLine3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles;
+   GbPoint3D p1(getX1Minimum(),getX2Minimum(),getX3Minimum());
+   GbPoint3D p2(getX1Centroid(),getX2Centroid(),getX3Centroid());
+   GbPoint3D p3(getX1Maximum(),getX2Maximum(),getX3Maximum());
+ 
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p2),new GbPoint3D(p3)));
+   
+   return triangles;
+}
+/*=======================================================*/
+void GbLine3D::setPoint1(GbPoint3D* point1)
+{ 
+   if(this->p1) this->p1->removeObserver(this);
+   this->p1 = point1;  
+   this->p1->addObserver(this);
+
+   if(this->p1 && this->p2) this->calculateValues(); 
+}
+/*=======================================================*/
+void GbLine3D::setPoint2(GbPoint3D* point2)
+{ 
+   if(this->p2) this->p2->removeObserver(this);
+   this->p2 = point2;  
+   this->p2->addObserver(this);
+
+   if(this->p1 && this->p2) this->calculateValues(); 
+}
+/*=======================================================*/
+void GbLine3D::setPoints(GbPoint3D* point1, GbPoint3D* point2)
+{ 
+   if(this->p1) this->p1->removeObserver(this);
+   if(this->p2) this->p2->removeObserver(this);
+
+   this->p1 = point1; 
+   this->p2 = point2;
+
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+
+   this->calculateValues(); 
+}
+/*=======================================================*/
+string GbLine3D::toString()
+{
+   stringstream ss;
+   ss<<"GbLine3D[p1=";
+   ss<<this->p1->toString()<<",p2="<<this->p2->toString()<<",l="<<this->getLength()<<"]";
+   return(ss.str());
+}
+/*=======================================================*/
+GbPoint3D* GbLine3D::calculateIntersectionPoint3D(GbLine3D* line)
+{
+   throw UbException(UB_EXARGS," not implemented");
+   //return(GbSystem::calculateIntersectionPoint3D(*this->p1, *this->p2, *line->p1, *line->p2));
+}
+/*======================================================================*/
+GbLine3D* GbLine3D::createClippedLine3D(GbCuboid3D* cuboid)
+{
+   return GbSystem3D::createClipLine3D(*this->p1, *this->p2, cuboid->getPoint1()->x1, cuboid->getPoint1()->x2, cuboid->getPoint1()->x3, cuboid->getPoint2()->x1, cuboid->getPoint2()->x2, cuboid->getPoint2()->x3);
+}                           
+/*======================================================================*/
+GbLine3D* GbLine3D::createClippedLine3D(GbPoint3D* pA, GbPoint3D* pE)
+{
+   return GbSystem3D::createClipLine3D(*this->p1, *this->p2, pA->x1, pA->x2, pA->x3, pE->x1, pE->x2, pE->x3);
+}
+/*======================================================================*/
+double GbLine3D::getDistance(const GbPoint3D& point)
+{
+   return this->getDistance(point.x1,point.x2,point.x3);
+}
+/*======================================================================*/
+double GbLine3D::getDistance(const double& x1,const double& x2,const double& x3)
+{
+   double dx1 = this->p2->x1 - this->p1->x1;
+   double dx2 = this->p2->x2 - this->p1->x2;
+   double dx3 = this->p2->x3 - this->p1->x3;
+
+   //double vec[3];
+   double a0 = x1 - p1->x1;
+   double a1 = x2 - p1->x2;
+   double a2 = x3 - p1->x3;
+
+   double kreuzProd0 = a1 * dx3 - a2 * dx2;
+   double kreuzProd1 = a2 * dx1 - a0 * dx3;
+   double kreuzProd2 = a0 * dx2 - a1 * dx1;
+
+   return (std::sqrt(kreuzProd0*kreuzProd0+kreuzProd1*kreuzProd1+kreuzProd2*kreuzProd2))/length;
+}
+/*=======================================================*/
+void GbLine3D::calculateValues()
+{
+   double dx1 = this->p2->x1 - this->p1->x1;
+   double dx2 = this->p2->x2 - this->p1->x2;
+   double dx3 = this->p2->x3 - this->p1->x3;
+   this->length = std::sqrt(dx1*dx1+dx2*dx2+dx3*dx3);
+}
+/*==========================================================*/
+void GbLine3D::objectChanged(UbObservable* changedObject)
+{
+   GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject);
+   if(!point || (this->p1!=point && this->p2!=point)) return;
+
+   this->calculateValues();
+}
+/*==========================================================*/
+void GbLine3D::objectWillBeDeleted(UbObservable* objectForDeletion)
+{
+   if(this->p1)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p1);
+      if(objectForDeletion == observedObj) { this->p1 = NULL; length = 0.0; }
+   }
+   if(this->p2)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p2);
+      if(objectForDeletion == observedObj) { this->p2 = NULL; length = 0.0; }
+   }
+   //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo
+}
+/*==========================================================*/
+void GbLine3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   p1->write(out);
+   p2->write(out);
+}
+/*==========================================================*/
+void GbLine3D::read(UbFileInput* in) 
+{  
+   p1 = new GbPoint3D;
+   p2 = new GbPoint3D;
+   in->readString();                                    
+   p1->read(in);
+   p1->addObserver(this);
+   in->readString();                                    
+   p2->read(in);
+   p2->addObserver(this);
+   this->calculateValues();
+}
+/*==========================================================*/
+void GbLine3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{  
+   double p1X1 = this->p1->getX1Coordinate();
+   double p1X2 = this->p1->getX2Coordinate();
+   double p1X3 = this->p1->getX3Coordinate();
+
+   double p2X1 = this->p2->getX1Coordinate();
+   double p2X2 = this->p2->getX2Coordinate();
+   double p2X3 = this->p2->getX3Coordinate();
+
+   double lenX1 = fabs( p1X1 - p2X1 );
+   double lenX2 = fabs( p1X2 - p2X2 );
+   double lenX3 = fabs( p1X3 - p2X3 );
+
+   double deltaX1 = lenX1*sx1 - lenX1;
+   double deltaX2 = lenX2*sx2 - lenX2;
+   double deltaX3 = lenX3*sx3 - lenX3;
+
+   if(p1X1<p2X1) { p1X1 -=  0.5*deltaX1;   p2X1 +=  0.5*deltaX1; }
+   else          { p1X1 +=  0.5*deltaX1;   p2X1 -=  0.5*deltaX1; }
+   if(p1X2<p2X2) { p1X2 -=  0.5*deltaX2;   p2X2 +=  0.5*deltaX2; }
+   else          { p1X2 +=  0.5*deltaX2;   p2X2 -=  0.5*deltaX2; }
+   if(p1X3<p2X3) { p1X3 -=  0.5*deltaX3;   p2X3 +=  0.5*deltaX3; }
+   else          { p1X3 +=  0.5*deltaX3;   p2X3 -=  0.5*deltaX3; }
+
+   this->p1->setCoordinates(p1X1,p1X2,p1X3);
+   this->p2->setCoordinates(p2X1,p2X2,p2X3);
+}
+/*=======================================================*/
+void GbLine3D::translate(const double& tx1, const double& tx2, const double& tx3)
+{  
+   this->p1->translate(tx1, tx2, tx3);
+   this->p2->translate(tx1, tx2, tx3);
+   //this->notifyObserversObjectChanged();
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbLine3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbLine3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..9267666ce804cc800c92f0c08ec56b11e75f2bb8
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbLine3D.h
@@ -0,0 +1,138 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBLINE3D_H
+#define GBLINE3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <sstream>
+#include <cmath>
+          
+#include <basics/utilities/UbObserver.h>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+class GbCuboid3D;
+class GbObject3DCreator;
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbLine3D;
+typedef VFSharedPtr<GbLine3D> GbLine3DPtr;
+
+
+/*=========================================================================*/
+/* GbLine3D                                                                */
+/*                                                                         */
+/**
+ * This Class provides basic 3D line objects.
+ * The describing points are observed by 3D line objects.
+ * <BR><BR><HR>
+*/
+
+class GbLine3D	: public GbObject3D , public UbObserver
+{
+public:
+   GbLine3D();
+	GbLine3D(GbPoint3D* point1, GbPoint3D* point2);
+	GbLine3D(GbLine3D* line);
+   ~GbLine3D(); 
+
+   GbLine3D* clone() { return new GbLine3D(this); }
+   void finalize();
+
+   void setPoint1(GbPoint3D* point1);
+   void setPoint2(GbPoint3D* point2);
+   void setPoints(GbPoint3D* point1, GbPoint3D* point2);
+
+   void deletePoint1() { if(this->p1) {this->p1->removeObserver(this); delete this->p1; this->p1=NULL;} }
+   void deletePoint2() { if(this->p2) {this->p2->removeObserver(this); delete this->p2; this->p2=NULL;} }
+   void deletePoints() { this->deletePoint1(); this->deletePoint2(); }
+
+   GbPoint3D* getPoint1() { return this->p1; }
+   GbPoint3D* getPoint2() { return this->p2; }    
+   
+   double getLength()     { return(this->length); }
+	
+   double getX1Centroid() { return((this->p1->x1+this->p2->x1)*0.5);}
+   double getX2Centroid() { return((this->p1->x2+this->p2->x2)*0.5); };
+   double getX3Centroid() { return((this->p1->x3+this->p2->x3)*0.5); }
+   
+   double getX1Minimum()  { return(this->p1->x1 < this->p2->x1 ? this->p1->x1 : this->p2->x1); }
+   double getX2Minimum()  { return(this->p1->x2 < this->p2->x2 ? this->p1->x2 : this->p2->x2); }
+   double getX3Minimum()  { return(this->p1->x3 < this->p2->x3 ? this->p1->x3 : this->p2->x3); }
+   
+   double getX1Maximum()  { return(this->p1->x1 > this->p2->x1 ? this->p1->x1 : this->p2->x1); }
+   double getX2Maximum()  { return(this->p1->x2 > this->p2->x2 ? this->p1->x2 : this->p2->x2); }
+   double getX3Maximum()  { return(this->p1->x3 > this->p2->x3 ? this->p1->x3 : this->p2->x3); }
+	                                               
+   void scale(const double& sx1, const double& sx2, const double& sx3);
+   void translate(const double& tx1, const double& tx2, const double& tx3);
+
+   GbPoint3D* calculateIntersectionPoint3D(GbLine3D* line);
+   GbLine3D*  createClippedLine3D(GbCuboid3D* cuboid);
+   GbLine3D*  createClippedLine3D(GbPoint3D* pA, GbPoint3D* pE);
+   
+   double     getDistance(const GbPoint3D& point);
+   double     getDistance(const double& x1,const double& x2,const double& x3);
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+   {
+      throw UbException(UB_EXARGS,"not implemented");
+   }
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+   {
+      throw UbException(UB_EXARGS,"not implemented");
+   }
+   bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x32) { return false; }
+
+   GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2)
+   {
+      throw UbException(UB_EXARGS,"not implemented");
+   }
+
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject);
+   void objectWillBeDeleted(UbObservable* objectForDeletion);
+
+   std::string toString();
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & p1;
+      ar & p2;
+      ar & length;
+      if( ArchiveTools::isReading(ar) ) this->calculateValues();
+   }
+#endif //CAB_RCF
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+protected:
+   GbPoint3D* p1;
+	GbPoint3D* p2;
+	double     length;
+
+private:
+   void calculateValues();
+};
+
+#ifdef RCF_USE_SF_SERIALIZATION
+    UB_AUTO_RUN_NAMED(   SF::registerType<GbLine3D>("GbLine3D"), SF_GbLine3D  );
+    UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbLine3D >()), SF_GbLine3D_BD1 );
+    UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbLine3D>() ), SF_GbLine3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbMeshTools3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbMeshTools3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5430ca9af27c461d2ac7eabb1f10c47b0f9917f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbMeshTools3D.h
@@ -0,0 +1,402 @@
+#ifndef GBMESHTOOLS3D_H
+#define GBMESHTOOLS3D_H
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+
+#include <basics/utilities/UbMath.h>
+
+namespace GbMeshTools3D
+{
+   inline int planeBoxOverlap(float normal[3], float vert[3], float maxbox[3])	// -NJMP-
+   {
+      int q;
+      float vmin[3],vmax[3],v;
+
+      for(q=0;q<=2;q++)
+      {
+         v=vert[q];					// -NJMP-
+         if(normal[q]>0.0f)
+         {
+            vmin[q]=-maxbox[q] - v;	// -NJMP-
+            vmax[q]= maxbox[q] - v;	// -NJMP-
+         }
+         else
+         {
+            vmin[q]= maxbox[q] - v;	// -NJMP-
+            vmax[q]=-maxbox[q] - v;	// -NJMP-
+         }
+      }
+      if(( normal[0]*vmin[0] + normal[1]*vmin[1] + normal[2]*vmin[2] )>0.0f ) return 0;	// -NJMP-
+      if(( normal[0]*vmax[0] + normal[1]*vmax[1] + normal[2]*vmax[2] )>=0.0f) return 1;	// -NJMP-
+      return 0;
+   }
+
+   //Testet auf schnittpunkt Box <-> Dreieck
+   //boxcenter   = Mittelpunkt der Box
+   //boxhalfsize = Halbe Laenge/Hoehe/Breite der Box
+   //triverts    = Koordinaten der Deickspunkte 
+   inline int triBoxOverlap(float boxcenter[3],float boxhalfsize[3],float triverts[3][3])
+   {
+      /*    use separating axis theorem to test overlap between triangle and box */
+      /*    need to test for overlap in these directions: */
+      /*    1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
+      /*       we do not even need to test these) */
+      /*    2) normal of the triangle */
+      /*    3) crossproduct(edge from tri, {x,y,z}-directin) */
+      /*       this gives 3x3=9 more tests */
+
+      float v0[3],v1[3],v2[3];
+
+      //   float axis[3];
+
+      float min,max,p0,p1,p2,rad,fex,fey,fez;		// -NJMP- "d" local variable removed
+      float normal[3],e0[3],e1[3],e2[3];
+
+      /* This is the fastest branch on Sun */
+      /* move everything so that the boxcenter is in (0,0,0) */
+      //SUB(v0,triverts[0],boxcenter);
+      //#define SUB(dest,v1,v2) 
+      v0[0]=triverts[0][0]-boxcenter[0]; 
+      v0[1]=triverts[0][1]-boxcenter[1]; 
+      v0[2]=triverts[0][2]-boxcenter[2]; 
+
+      //SUB(v1,triverts[1],boxcenter);
+      //#define SUB(dest,v1,v2) 
+      v1[0]=triverts[1][0]-boxcenter[0]; 
+      v1[1]=triverts[1][1]-boxcenter[1]; 
+      v1[2]=triverts[1][2]-boxcenter[2]; 
+
+      //SUB(v2,triverts[2],boxcenter);
+      //#define SUB(dest,v1,v2) 
+      v2[0]=triverts[2][0]-boxcenter[0]; 
+      v2[1]=triverts[2][1]-boxcenter[1]; 
+      v2[2]=triverts[2][2]-boxcenter[2]; 
+
+      /* compute triangle edges */
+      //SUB(e0,v1,v0);      /* tri edge 0 */
+      //#define SUB(dest,v1,v2) 
+      e0[0]=v1[0]-v0[0]; 
+      e0[1]=v1[1]-v0[1]; 
+      e0[2]=v1[2]-v0[2]; 
+
+      //SUB(e1,v2,v1);      /* tri edge 1 */
+      //#define SUB(dest,v1,v2) 
+      e1[0]=v2[0]-v1[0]; 
+      e1[1]=v2[1]-v1[1]; 
+      e1[2]=v2[2]-v1[2]; 
+
+      //SUB(e2,v0,v2);      /* tri edge 2 */
+      //#define SUB(dest,v1,v2) 
+      e2[0]=v0[0]-v2[0]; 
+      e2[1]=v0[1]-v2[1]; 
+      e2[2]=v0[2]-v2[2]; 
+
+      /* Bullet 3:  */
+      /*  test the 9 tests first (this was faster) */
+      fex = fabsf(e0[0]);
+      fey = fabsf(e0[1]);
+      fez = fabsf(e0[2]);
+
+      //AXISTEST_X01(e0[2], e0[1], fez, fey);
+      //#define AXISTEST_X01(a, b, fa, fb)			
+      p0 = e0[2]*v0[1] - e0[1]*v0[2];			       	   
+      p2 = e0[2]*v2[1] - e0[1]*v2[2];			       	   
+      if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} 
+      rad = fez * boxhalfsize[1] + fey * boxhalfsize[2];   
+      if(min>rad || max<-rad) return 0;
+
+      //AXISTEST_Y02(e0[2], e0[0], fez, fex);
+      //#define AXISTEST_Y02(a, b, fa, fb)			
+      p0 = -e0[2]*v0[0] + e0[0]*v0[2];		      	   
+      p2 = -e0[2]*v2[0] + e0[0]*v2[2];	       	       	   
+      if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} 
+      rad = fez * boxhalfsize[0] + fex * boxhalfsize[2];  
+      if(min>rad || max<-rad) return 0;
+
+      //AXISTEST_Z12(e0[1], e0[0], fey, fex);
+      //#define AXISTEST_Z12(a, b, fa, fb)		
+      p1 = e0[1]*v1[0] - e0[0]*v1[1];			           
+      p2 = e0[1]*v2[0] - e0[0]*v2[1];			       	   
+      if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} 
+      rad = fey * boxhalfsize[0] + fex * boxhalfsize[1];   
+      if(min>rad || max<-rad) return 0;
+      
+      fex = fabsf(e1[0]);
+      fey = fabsf(e1[1]);
+      fez = fabsf(e1[2]);
+
+      //AXISTEST_X01(e1[2], e1[1], fez, fey);
+      //#define AXISTEST_X01(a, b, fa, fb)			
+      p0 = e1[2]*v0[1] - e1[1]*v0[2];			       	   
+      p2 = e1[2]*v2[1] - e1[1]*v2[2];			       	   
+      if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} 
+      rad = fez * boxhalfsize[1] + fey * boxhalfsize[2];   
+      if(min>rad || max<-rad) return 0;
+      
+      //AXISTEST_Y02(e1[2], e1[0], fez, fex);
+      //#define AXISTEST_Y02(a, b, fa, fb)			
+      p0 = -e1[2]*v0[0] + e1[0]*v0[2];		      	   
+      p2 = -e1[2]*v2[0] + e1[0]*v2[2];	       	       	   
+      if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} 
+      rad = fez * boxhalfsize[0] + fex * boxhalfsize[2];   
+      if(min>rad || max<-rad) return 0;
+
+      //AXISTEST_Z0(e1[1], e1[0], fey, fex);
+      //#define AXISTEST_Z0(a, b, fa, fb)	
+      p0 = e1[1]*v0[0] - e1[0]*v0[1];				  
+      p1 = e1[1]*v1[0] - e1[0]*v1[1];			          
+      if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} 
+      rad = fey * boxhalfsize[0] + fex * boxhalfsize[2];   
+      if(min>rad || max<-rad) return 0;
+
+      fex = fabsf(e2[0]);
+      fey = fabsf(e2[1]);
+      fez = fabsf(e2[2]);
+      //AXISTEST_X2(e2[2], e2[1], fez, fey);
+      //#define AXISTEST_X2(a, b, fa, fb)			
+      p0 = e2[2]*v0[1] - e2[1]*v0[2];			           
+      p1 = e2[2]*v1[1] - e2[1]*v1[2];			       	   
+      if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} 
+      rad = fez * boxhalfsize[1] + fey * boxhalfsize[2];  
+      if(min>rad || max<-rad) return 0;
+      
+      //AXISTEST_Y1(e2[2], e2[0], fez, fex);
+      //#define AXISTEST_Y1(a, b, fa, fb)			
+      p0 = -e2[2]*v0[0] + e2[0]*v0[2];		      	  
+      p1 = -e2[2]*v1[0] + e2[0]*v1[2];	     	       	   
+      if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} 
+      rad = fez * boxhalfsize[0] + fex * boxhalfsize[2];   
+      if(min>rad || max<-rad) return 0;
+      
+      //AXISTEST_Z12(e2[1], e2[0], fey, fex);
+      //#define AXISTEST_Z12(a, b, fa, fb)		
+      p1 = e2[1]*v1[0] - e2[0]*v1[1];			           
+      p2 = e2[1]*v2[0] - e2[0]*v2[1];			       	   
+      if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} 
+      rad = fey * boxhalfsize[0] + fex * boxhalfsize[1];   
+      if(min>rad || max<-rad) return 0;
+   
+      /* Bullet 1: */
+      /*  first test overlap in the {x,y,z}-directions */
+      /*  find min, max of the triangle each direction, and test for overlap in */
+      /*  that direction -- this is equivalent to testing a minimal AABB around */
+      /*  the triangle against the AABB */
+      /* test in X-direction */
+      //FINDMINMAX(v0[0],v1[0],v2[0],min,max);
+      min = (float)UbMath::min(v0[0],v1[0],v2[0]);
+      max = (float)UbMath::max(v0[0],v1[0],v2[0]);
+      if(min>boxhalfsize[0] || max<-boxhalfsize[0]) return 0;
+
+      /* test in Y-direction */
+      //FINDMINMAX(v0[1],v1[1],v2[1],min,max);
+      min = (float)UbMath::min(v0[1],v1[1],v2[1]);
+      max = (float)UbMath::max(v0[1],v1[1],v2[1]);
+      if(min>boxhalfsize[1] || max<-boxhalfsize[1]) return 0;
+
+      /* test in Z-direction */
+      //FINDMINMAX(v0[2],v1[2],v2[2],min,max);
+      min = (float)UbMath::min(v0[2],v1[2],v2[2]);
+      max = (float)UbMath::max(v0[2],v1[2],v2[2]);
+
+      if(min>boxhalfsize[2] || max<-boxhalfsize[2]) return 0;
+
+      /* Bullet 2: */
+      /*  test if the box intersects the plane of the triangle */
+      /*  compute plane equation of triangle: normal*x+d=0 */
+      //CROSS(normal,e0,e1);
+      //#define CROSS(dest,v1,v2) 
+      normal[0]=e0[1]*e1[2]-e0[2]*e1[1]; 
+      normal[1]=e0[2]*e1[0]-e0[0]*e1[2]; 
+      normal[2]=e0[0]*e1[1]-e0[1]*e1[0]; 
+
+      // -NJMP- (line removed here)
+      if(!planeBoxOverlap(normal,v0,boxhalfsize)) return 0;	// -NJMP-
+      return 1;   /* box and triangle overlaps */
+   }
+
+
+ 
+};
+
+#endif
+
+//original - NICHT LOESCHEN - von kroete lynn
+
+//#define X 0
+//#define Y 1
+//#define Z 2
+//
+//#define CROSS(dest,v1,v2) 
+//   dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; 
+//   dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; 
+//   dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; 
+//
+//#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
+//
+//#define SUB(dest,v1,v2) 
+//   dest[0]=v1[0]-v2[0]; 
+//   dest[1]=v1[1]-v2[1]; 
+//   dest[2]=v1[2]-v2[2]; 
+//
+//#define FINDMINMAX(x0,x1,x2,min,max) 
+//   min = max = x0;   
+//   if(x1<min) min=x1;
+//   if(x1>max) max=x1;
+//   if(x2<min) min=x2;
+//   if(x2>max) max=x2;
+//
+//int planeBoxOverlap(float normal[3], float vert[3], float maxbox[3])	// -NJMP-
+//{
+//   int q;
+//   float vmin[3],vmax[3],v;
+//
+//   for(q=X;q<=Z;q++)
+//   {
+//      v=vert[q];					// -NJMP-
+//      if(normal[q]>0.0f)
+//      {
+//         vmin[q]=-maxbox[q] - v;	// -NJMP-
+//         vmax[q]= maxbox[q] - v;	// -NJMP-
+//      }
+//      else
+//      {
+//         vmin[q]= maxbox[q] - v;	// -NJMP-
+//         vmax[q]=-maxbox[q] - v;	// -NJMP-
+//      }
+//   }
+//   if(DOT(normal,vmin)>0.0f) return 0;	// -NJMP-
+//   if(DOT(normal,vmax)>=0.0f) return 1;	// -NJMP-
+//   return 0;
+//}
+//
+///*======================== X-tests ========================
+//
+//#define AXISTEST_X01(a, b, fa, fb)			   
+//   p0 = a*v0[Y] - b*v0[Z];			       	   
+//   p2 = a*v2[Y] - b*v2[Z];			       	   
+//      if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} 
+//   rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z];   
+//   if(min>rad || max<-rad) return 0;
+//
+//#define AXISTEST_X2(a, b, fa, fb)			   
+//   p0 = a*v0[Y] - b*v0[Z];			          
+//   p1 = a*v1[Y] - b*v1[Z];			       	   
+//      if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} 
+//   rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z];   
+//   if(min>rad || max<-rad) return 0;
+//
+//
+//
+///*======================== Y-tests ========================
+//
+//#define AXISTEST_Y02(a, b, fa, fb)			   
+//   p0 = -a*v0[X] + b*v0[Z];		      	   
+//   p2 = -a*v2[X] + b*v2[Z];	       	       	   
+//   if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} 
+//   rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z];   
+//   if(min>rad || max<-rad) return 0;
+//
+//#define AXISTEST_Y1(a, b, fa, fb)			   
+//   p0 = -a*v0[X] + b*v0[Z];		      	   
+//   p1 = -a*v1[X] + b*v1[Z];	     	       	   
+//      if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} 
+//   rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z];   
+//   if(min>rad || max<-rad) return 0;
+//
+//======================== Z-tests ========================
+//
+//#define AXISTEST_Z12(a, b, fa, fb)			   
+//   p1 = a*v1[X] - b*v1[Y];			           
+//   p2 = a*v2[X] - b*v2[Y];			       	   
+//      if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} 
+//   rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y];   
+//   if(min>rad || max<-rad) return 0;
+//
+//#define AXISTEST_Z0(a, b, fa, fb)			   
+//   p0 = a*v0[X] - b*v0[Y];				   
+//   p1 = a*v1[X] - b*v1[Y];			           
+//      if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;}
+//   rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y];   
+//   if(min>rad || max<-rad) return 0;
+//
+//int triBoxOverlap(float boxcenter[3],float boxhalfsize[3],float triverts[3][3])
+//{
+//      //use separating axis theorem to test overlap between triangle and box 
+//      //need to test for overlap in these directions: 
+//      //1) the {x,y,z}-directions (actually, since we use the AABB of the triangle 
+//      //   we do not even need to test these) 
+//      //2) normal of the triangle 
+//      //3) crossproduct(edge from tri, {x,y,z}-directin) 
+//      //   this gives 3x3=9 more tests 
+//
+//   float v0[3],v1[3],v2[3];
+//
+//   //   float axis[3];
+//
+//   float min,max,p0,p1,p2,rad,fex,fey,fez;		// -NJMP- "d" local variable removed
+//   float normal[3],e0[3],e1[3],e2[3];
+//
+//   /* This is the fastest branch on Sun */
+//   /* move everything so that the boxcenter is in (0,0,0) */
+//   SUB(v0,triverts[0],boxcenter);
+//   SUB(v1,triverts[1],boxcenter);
+//   SUB(v2,triverts[2],boxcenter);
+//
+//   /* compute triangle edges */
+//   SUB(e0,v1,v0);      /* tri edge 0 */
+//   SUB(e1,v2,v1);      /* tri edge 1 */
+//   SUB(e2,v0,v2);      /* tri edge 2 */
+//
+//   /* Bullet 3:  */
+//   /*  test the 9 tests first (this was faster) */
+//   fex = fabsf(e0[X]);
+//   fey = fabsf(e0[Y]);
+//   fez = fabsf(e0[Z]);
+//
+//   AXISTEST_X01(e0[Z], e0[Y], fez, fey);
+//   AXISTEST_Y02(e0[Z], e0[X], fez, fex);
+//   AXISTEST_Z12(e0[Y], e0[X], fey, fex);
+//   fex = fabsf(e1[X]);
+//   fey = fabsf(e1[Y]);
+//   fez = fabsf(e1[Z]);
+//
+//   AXISTEST_X01(e1[Z], e1[Y], fez, fey);
+//   AXISTEST_Y02(e1[Z], e1[X], fez, fex);
+//   AXISTEST_Z0(e1[Y], e1[X], fey, fex);
+//
+//   fex = fabsf(e2[X]);
+//   fey = fabsf(e2[Y]);
+//   fez = fabsf(e2[Z]);
+//   AXISTEST_X2(e2[Z], e2[Y], fez, fey);
+//   AXISTEST_Y1(e2[Z], e2[X], fez, fex);
+//   AXISTEST_Z12(e2[Y], e2[X], fey, fex);
+//
+//   /* Bullet 1: */
+//   /*  first test overlap in the {x,y,z}-directions */
+//   /*  find min, max of the triangle each direction, and test for overlap in */
+//   /*  that direction -- this is equivalent to testing a minimal AABB around */
+//   /*  the triangle against the AABB */
+//   /* test in X-direction */
+//   FINDMINMAX(v0[X],v1[X],v2[X],min,max);
+//   if(min>boxhalfsize[X] || max<-boxhalfsize[X]) return 0;
+//
+//   /* test in Y-direction */
+//   FINDMINMAX(v0[Y],v1[Y],v2[Y],min,max);
+//   if(min>boxhalfsize[Y] || max<-boxhalfsize[Y]) return 0;
+//
+//   /* test in Z-direction */
+//   FINDMINMAX(v0[Z],v1[Z],v2[Z],min,max);
+//   if(min>boxhalfsize[Z] || max<-boxhalfsize[Z]) return 0;
+//
+//   /* Bullet 2: */
+//   /*  test if the box intersects the plane of the triangle */
+//   /*  compute plane equation of triangle: normal*x+d=0 */
+//   CROSS(normal,e0,e1);
+//
+//   // -NJMP- (line removed here)
+//   if(!planeBoxOverlap(normal,v0,boxhalfsize)) return 0;	// -NJMP-
+//   return 1;   /* box and triangle overlaps */
+//}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbObject3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbObject3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..85f0332e1443d9c8cc593f78c9bf494f8b807af2
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbObject3D.cpp
@@ -0,0 +1,88 @@
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <basics/utilities/UbMath.h>                 
+
+using namespace std;
+
+string GbObject3D::getTypeID()
+{
+      return this->getCreator()->getTypeID();
+}
+/*======================================================================*/
+bool GbObject3D::isPointInGbObject3D(GbPoint3D* p)
+{
+   return this->isPointInGbObject3D(p->getX1Centroid(),p->getX2Coordinate(),p->getX3Coordinate());
+} 
+/*======================================================================*/
+bool GbObject3D::isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) 
+{
+
+   if(   this->isPointInGbObject3D(x1a, x2a, x3a) 
+      && this->isPointInGbObject3D(x1b, x2a, x3a) 
+      && this->isPointInGbObject3D(x1b, x2b, x3a)
+      && this->isPointInGbObject3D(x1a, x2b, x3a) 
+      && this->isPointInGbObject3D(x1a, x2a, x3b)
+      && this->isPointInGbObject3D(x1b, x2a, x3b)
+      && this->isPointInGbObject3D(x1b, x2b, x3b)
+      && this->isPointInGbObject3D(x1a, x2b, x3b))
+   {
+      return true;
+   }
+
+   return false;
+}
+/*======================================================================*/
+bool GbObject3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) 
+{
+   if(   this->isPointInGbObject3D(x1a, x2a, x3a)      
+      || this->isPointInGbObject3D(x1b, x2a, x3a)      
+      || this->isPointInGbObject3D(x1b, x2b, x3a)      
+      || this->isPointInGbObject3D(x1a, x2b, x3a)      
+      || this->isPointInGbObject3D(x1a, x2a, x3b)      
+      || this->isPointInGbObject3D(x1b, x2a, x3b)      
+      || this->isPointInGbObject3D(x1b, x2b, x3b)      
+      || this->isPointInGbObject3D(x1a, x2b, x3b) )    
+   {
+      if(   !this->isPointInGbObject3D(x1a, x2a, x3a) 
+         || !this->isPointInGbObject3D(x1b, x2a, x3a) 
+         || !this->isPointInGbObject3D(x1b, x2b, x3a) 
+         || !this->isPointInGbObject3D(x1a, x2b, x3a)
+         || !this->isPointInGbObject3D(x1a, x2a, x3b)
+         || !this->isPointInGbObject3D(x1b, x2a, x3b)
+         || !this->isPointInGbObject3D(x1b, x2b, x3b)
+         || !this->isPointInGbObject3D(x1a, x2b, x3b)) return true;
+   }
+   return false;
+}
+/*======================================================================*/
+bool GbObject3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   if(   this->isPointInGbObject3D(x1a, x2a, x3a)   
+      || this->isPointInGbObject3D(x1b, x2a, x3a)   
+      || this->isPointInGbObject3D(x1b, x2b, x3a)   
+      || this->isPointInGbObject3D(x1a, x2b, x3a)   
+      || this->isPointInGbObject3D(x1a, x2a, x3b)   
+      || this->isPointInGbObject3D(x1b, x2a, x3b)   
+      || this->isPointInGbObject3D(x1b, x2b, x3b)   
+      || this->isPointInGbObject3D(x1a, x2b, x3b))  
+   {
+      return true;
+   }
+
+   return false;
+}
+/*=======================================================*/
+bool GbObject3D::isInsideCell(const double& minX1,const double& minX2,const double& minX3,const double& maxX1,const double& maxX2,const double& maxX3)
+{
+   if(   UbMath::greaterEqual(this->getX1Minimum(),minX1)
+      && UbMath::greaterEqual(this->getX2Minimum(),minX2)
+      && UbMath::greaterEqual(this->getX3Minimum(),minX3)
+      && UbMath::lessEqual(this->getX1Maximum(),maxX1) 
+      && UbMath::lessEqual(this->getX2Maximum(),maxX2)   
+      && UbMath::lessEqual(this->getX2Maximum(),maxX3)     ) return true;
+
+   return false;
+}
+
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbObject3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbObject3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..48cb40af7f284f988f991d7a87ad2dc6802ac8b0
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbObject3D.h
@@ -0,0 +1,173 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBOBJECT3D_H
+#define GBOBJECT3D_H
+
+#include <string>
+#include <vector>
+
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+#include <basics/utilities/UbFileOutput.h>
+#include <basics/utilities/UbObservable.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/objects/ObObject.h>
+
+class GbPoint3D;
+class GbLine3D;
+class GbTriangle3D;
+class GbObject3DCreator;
+
+#ifdef CAB_CTL
+#include <ctl.h>
+#endif
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbObject3D;
+typedef VFSharedPtr<GbObject3D> GbObject3DPtr;
+
+
+/*=========================================================================*/
+/* GbObject3D                                                              */
+/*                                                                         */
+/**
+ * This Interface provides basic 3D geometry objects methods.
+ * <BR><BR><HR>
+ * @author <A HREF="mailto:geller@cab.bau.tu-bs.de">S. Geller</A>
+ * @author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+ * @version 1.0 - 02.02.05
+*/
+class GbObject3D : public ObObject
+{
+public:
+#ifdef CAB_CTL
+   virtual ctl::oStream &write(ctl::oStream &os) const
+   {
+      return os;
+   }
+   virtual ctl::iStream &read(ctl::iStream &is)
+   {
+      return is;
+   }
+#endif
+
+   virtual ~GbObject3D(){}
+
+   //ueberschriebene methode von ObObject
+   virtual std::string getTypeID();
+
+   //abstract Methods
+   virtual void finalize() =0 ; //detroys also all dynamic objects (e.g. GbPoints in GbLine)
+   virtual ObObjectCreator* getCreator()=0;
+
+   /**
+    * Returns the centroid x1 coordinate of this 3D object.
+    * @return the centroid x1 coordinate of this 3D object
+    */
+   virtual double getX1Centroid()=0;
+   /**
+    * Returns the minimum x1 coordinate of this 3D object.
+    * @return the minimum x1 coordinate of this 3D object
+    */
+   virtual double getX1Minimum()=0;
+   /**
+    * Returns the maximum x1 coordinate of this 3D object.
+    * @return the maximum x1 coordinate of this 3D object
+    */
+   virtual double getX1Maximum()=0;
+   /**
+    * Returns the centroid x2 coordinate of this 3D object.
+    * @return the centroid x2 coordinate of this 3D object
+    */
+   virtual double getX2Centroid()=0;
+   /**
+    * Returns the minimum x2 coordinate of this 3D object.
+    * @return the minimum x2 coordinate of this 3D object
+    */
+   virtual double getX2Minimum()=0;
+   /**
+    * Returns the maximum x2 coordinate of this 3D object.
+    * @return the maximum x2 coordinate of this 3D object
+    */
+   virtual double getX2Maximum()=0;
+
+	virtual double getX3Centroid()=0;
+   /**
+    * Returns the minimum x2 coordinate of this 3D object.
+    * @return the minimum x2 coordinate of this 3D object
+    */
+   virtual double getX3Minimum()=0;
+   /**
+    * Returns the maximum x2 coordinate of this 3D object.
+    * @return the maximum x2 coordinate of this 3D object
+    */
+   virtual double getX3Maximum()=0;
+
+   /*=======================================================*/
+   double getLengthX1() { return (getX1Maximum()-getX1Minimum()); }
+   double getLengthX2() { return (getX2Maximum()-getX2Minimum()); }
+   double getLengthX3() { return (getX3Maximum()-getX3Minimum()); }
+
+   virtual void setCenterX1Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void setCenterX2Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void setCenterX3Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void setCenterCoordinates(const double& x1, const double& x2, const double& x3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+
+   //Rotates the Point in relation to the origen.
+   //Parameters must be radian measure.
+   virtual void rotate(const double& rx1, const double& rx2, const double& rx3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void translate(const double& x1, const double& x2, const double& x3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void scale(const double& sx1, const double& sx2, const double& sx3)  { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+
+   virtual void write(UbFileOutput* out)=0;
+   virtual void read(UbFileInput* in)=0;
+
+   virtual bool isPointInGbObject3D(GbPoint3D* p);
+   virtual bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)=0;
+   virtual bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)=0;
+
+   virtual bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   virtual bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   virtual bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   virtual double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b){ return -1.0;};
+
+   virtual bool isInsideCell(const double& minX1,const double& minX2,const double& minX3,const double& maxX1,const double& maxX2,const double& maxX3);
+
+   virtual GbLine3D* createClippedLine3D (GbPoint3D &point1, GbPoint3D &point2)=0;
+   virtual std::vector<GbTriangle3D*> getSurfaceTriangleSet()=0;
+
+   virtual void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles) { throw UbException("GbObject3D::addSurfaceTriangleSet - not implemented for "+(std::string)typeid(*this).name()); }
+
+   virtual bool hasRaytracing() { return false; }
+   virtual bool raytracingSupportsPointsInside() { return false; }
+   //|r| must be 1! einheitsvector!!
+   //return negativ value oder zero if no intersection
+   virtual double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3) { throw UbException("GbObject3D::getIntersectionRaytraceFactor - not implemented"); }
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<ObObject>(ar, *this);
+   }
+#endif //CAB_RCF
+};
+/*=========================================================================*/
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   SF_NO_CTOR(GbObject3D);
+   UB_AUTO_RUN_NAMED(SF::registerType<GbObject3D>("GbObject3D") , SF_GbObject3D);
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived<ObObject, GbObject3D >() ), SF_GbObject3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbObject3DManager.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbObject3DManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..38fc910e8b5223295677abaf1e87c217f411da3d
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbObject3DManager.cpp
@@ -0,0 +1,285 @@
+#include <numerics/geometry3d/GbObject3DManager.h>      
+#include <numerics/geometry3d/GbObject3D.h>       
+#include <numerics/geometry3d/creator/GbObject3DFactory.h>
+
+using namespace std;
+
+GbObject3DEntry::GbObject3DEntry(GbObject3DManager *parent, GbObject3D *geoObject, bool active, string name):ObObjectEntry(parent, geoObject)
+{
+   //this->parent = parent;
+   //this->geoObject = geoObject;
+   this->active = active;
+   this->name = name;
+}
+
+/*======================================================*/
+/*==     nun halt der Manager                       ====*/
+/*======================================================*/
+
+GbObject3DManager::GbObject3DManager(): ObObjectManager()
+{
+   this->tableModel = new GbObject3DTableModel(this);
+}
+/*======================================================*/
+GbObject3DManager::~GbObject3DManager()
+{
+//   this->gbObject3DList.clear();
+}
+/*======================================================*/
+ObObjectFactory* GbObject3DManager::getObObjectFactory()
+{
+   return GbObject3DFactory::getInstance();
+}
+
+/*======================================================*/
+ObObjectEntry* GbObject3DManager::createNewObObjectEntry(ObObject *obj)
+{ 
+   GbObject3D *geoobject = dynamic_cast<GbObject3D*>(obj);
+   return new GbObject3DEntry(this, geoobject, true, geoobject->getTypeID()); 
+}
+
+/*======================================================*/
+//UbTableModel* GbObject3DManager::getTableModel()
+//{
+//   return this->tablemodel;
+//}
+
+/*======================================================*/
+//bool GbObject3DManager::addGbObject3D(GbObject3D *geoObject)
+//{
+//   return this->addGbObject3D(geoObject, true, "GeoObject");
+//}
+//
+///*======================================================*/
+bool GbObject3DManager::addGbObject3D(GbObject3D *geoObject, string name)
+{
+   GbObject3DEntry *entry = new GbObject3DEntry (this, geoObject, true, name);
+   return ObObjectManager::addObObjectEntry(entry);
+}
+//bool GbObject3DManager::addGbObject3D(GbObject3D *geoObject, bool active, string name)  
+//{
+//   GbObject3DEntry *entry = new GbObject3DEntry (this, geoObject, true, name);
+//   return ObObjectManager::addObObjectEntry(entry);
+//}
+//
+/*======================================================*/
+bool GbObject3DManager::removeGbObject3D(GbObject3D *geoObject)
+{
+   return ObObjectManager::removeObObject(geoObject);
+}
+/*======================================================*/
+bool GbObject3DManager::removeGbObject3D(int index)
+{
+   return ObObjectManager::removeObObject(index);
+}
+/*======================================================*/
+//void GbObject3DManager::removeAllGbObject3Ds() 
+//{  
+//    this->gbObject3DList.clear();
+//}
+/*======================================================*/
+int GbObject3DManager::getNumberOfGbObject3Ds()
+{ 
+   return GbObject3DManager::getNumberOfObObjects();
+}
+/*======================================================*/
+vector<GbObject3D*>* GbObject3DManager::getAllGbObject3Ds()  
+{ 
+   throw UbException(UB_EXARGS,"not implemented");
+   //vector<GbObject3D*> *geoVektor = new vector<GbObject3D*>;
+   //for(int u=0; u<(int)this->gbObject3DList.size();u++)
+   //{
+   //   GbObject3D* geoObject = dynamic_cast<GbObject3D*>((gbObject3DList)[u]->getObject());
+   //   geoVektor->push_back(geoObject);
+   //}
+   //return geoVektor;  
+}
+/*======================================================*/
+GbObject3D* GbObject3DManager::getGbObject3D(int index)
+{
+   if(index <  0)                            return NULL;
+   if(index >= this->getNumberOfObObjects()) return NULL;
+
+   GbObject3D* geoObject = dynamic_cast<GbObject3D*>(this->getObObject(index));
+   return(geoObject);
+}
+/*======================================================*/
+//GbObject3DEntry* GbObject3DManager::getGbObject3DEntry(int index)
+//{
+//   if(index <  0)                                 return NULL;
+//   if(index >= (int)this->gbObject3DList.size())  return NULL;
+//
+//   return((this->gbObject3DList)[index]);
+//}
+/*====================================================*/
+void GbObject3DManager::write(UbFileOutput *out) 
+{                    
+   int size = this->getNumberOfObObjects();
+   out->writeInteger(size);
+   out->writeString("// #GbObjects");
+
+   GbObject3D *geoObject;
+   for(int pos=0; pos<size; pos++)          
+   {
+      out->writeLine();
+      geoObject = dynamic_cast<GbObject3D*>(this->getObObject(pos));
+      cout<<pos<<".:"<<geoObject->toString()<<endl;
+      geoObject->write(out);
+   }
+}
+/*======================================================================*/
+void GbObject3DManager::read(UbFileInput *in) 
+{
+   this->removeAllObObjects();
+   
+   int n = in->readInteger();                          
+   
+   cout<<"GbObject3DManager::read "<<n<<" GbObject3Ds\n";
+   GbObject3D *geoObject;
+   for(int pos=1; pos<=n; pos++)
+   {
+      in->readLine();
+      cout<<" - GbObject3D "<<pos<<" ...";
+      geoObject = GbObject3DFactory::getInstance()->createGbObject3D(in);
+      
+      GbObject3DEntry *entry = new GbObject3DEntry(this, geoObject, true, "GeoObject");
+      this->addObObjectEntry(entry);
+      cout<<"done\n";
+   }
+}
+/*======================================================*/
+string GbObject3DManager::toString()
+{
+   stringstream ss; ss<<endl;
+   
+   int size = this->getNumberOfObObjects();
+   for(int pos=0; pos<size; pos++)          
+   {
+      ObObject* geoObject = this->getObObject(pos);
+      ss<<(pos+1)<<". "<<geoObject->toString()<<endl;
+   }
+   string back = ss.str();
+   return back;
+}
+
+/*======================================================*/
+/*======================================================*/
+/*======================================================*/
+
+GbObject3DTableModel::GbObject3DTableModel(GbObject3DManager* manager)
+{
+   this->objectManager = manager;
+}
+
+/*======================================================*/
+GbObject3DTableModel::~GbObject3DTableModel(void)
+{
+}
+
+/*======================================================*/
+//Gibt die Anzahl der Spalten zurueck.
+int GbObject3DTableModel::getColumnNumber()
+{
+   return 3;
+}
+
+/*======================================================*/
+std::string GbObject3DTableModel::getColumnLabel(int column)
+{
+   switch(column)
+   {
+   case COL_NAME: return "Name";
+   case COL_TYPE: return "Type";
+   case COL_ACTIVE: return "Active";
+   default: throw UbException(UB_EXARGS,"falscher Spaltenindex");
+   }
+}
+
+/*======================================================*/
+int GbObject3DTableModel::getRowNumber()
+{
+   return this->objectManager->getNumberOfGbObject3Ds();
+}
+/*======================================================*/
+int GbObject3DTableModel::getSelectedRowIndex()
+{
+   return 0;
+   //	return this->objectManager->getSelectedIndex();
+}
+
+/*======================================================*/
+int GbObject3DTableModel::getColumnType(int column)
+{
+   switch(column) {
+   case COL_NAME :
+      return UbTableModel::COL_TYPE_STRING;
+      break;
+   case COL_TYPE :
+      return UbTableModel::COL_TYPE_STRING;
+      break;
+   case COL_ACTIVE :
+      return UbTableModel::COL_TYPE_BOOL;
+      break;
+   }
+   return -1;
+}
+
+//Gibt den Eintag der Tabelle an der angegebenen Spalten- und 
+//Zeilenposition in Form eines String Werts zurueck.
+std::string GbObject3DTableModel::getStringValue(int row, int col)
+{
+   GbObject3DEntry* gbObjEntry = dynamic_cast<GbObject3DEntry*>(this->objectManager->getObObjectEntry(row));
+   switch(col) {
+   case COL_NAME:
+      return gbObjEntry->name;
+      break;
+   case COL_TYPE:
+      return gbObjEntry->getObject()->getTypeID();
+      break;
+   case COL_ACTIVE:
+      if ( gbObjEntry->active ) return "True";
+      return "False";
+      break;
+   }
+   return "Fehler";
+}
+
+/*======================================================*/
+//bool GbObject3DManager::selectGbObject3D(int index)
+//{
+//   cout<<"GbObject3DManager::selectGbObject3D(int index):"<<index<<endl;
+//   if (index > (int)this->gbObject3DList.size()-1 || index < 0) return false; 
+//   if ( this->selectedObject == this->getGbObject3D(index) ) return true;
+//   this->selectedObject = this->getGbObject3D(index);
+//   this->notifyObserversObjectChanged();
+//   return true;
+//}
+///*======================================================*/
+//bool GbObject3DManager::selectGbObject3D(GbObject3D* geoObject)
+//{
+//   for(int pos=0; pos<(int)this->gbObject3DList.size(); pos++)
+//   {
+//      if(this->gbObject3DList[pos]->geoObject==geoObject) 
+//      {
+//         return this->selectGbObject3D(pos);
+//      }
+//   }
+//   return false;
+//}
+///*======================================================*/
+//GbObject3D* GbObject3DManager::getSelectedGbObject3D()
+//{
+//   return this->selectedObject;
+//}
+///*======================================================*/
+//int GbObject3DManager::getSelectedIndex()
+//{
+//   for(int pos=0; pos<(int)this->gbObject3DList.size(); pos++)
+//   {
+//      if(this->gbObject3DList[pos]->geoObject==this->selectedObject) 
+//      {
+//         return pos;
+//      }
+//   }
+//   return -1;
+//}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbObject3DManager.h b/source/ThirdParty/Library/numerics/geometry3d/GbObject3DManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..c842ddaff866fa615da8393d80d8c728290e3ffd
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbObject3DManager.h
@@ -0,0 +1,122 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBOBJECT3DMANAGER_H
+#define GBOBJECT3DMANAGER_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+#include <basics/utilities/UbFileOutput.h>
+#include <basics/utilities/UbTableModel.h>
+#include <basics/objects/ObObjectManager.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbObject3DManager;
+typedef VFSharedPtr<GbObject3DManager> GbObject3DManagerPtr;
+
+                                                  
+class GbObject3D;   
+class GbObject3DManager;
+class GbObject3DTableModel;
+
+class GbObject3DEntry  : public ObObjectEntry
+{
+   friend class GbObject3DManager;
+   friend class GbObject3DTableModel;
+public:
+   std::string getName() { return this->name;}
+private:
+   //GbObject3DManager *parent;
+   //GbObject3D        *geoObject;
+   bool        active;
+   std::string name;
+   
+
+   GbObject3DEntry(GbObject3DManager* parent, GbObject3D* geoObject, bool active, std::string name);
+ 
+};
+
+
+class GbObject3DManager  : public ObObjectManager 
+{                                           
+public:
+   GbObject3DManager();
+   ~GbObject3DManager();
+
+   ObObjectEntry* createNewObObjectEntry(ObObject *obj);
+   ObObjectFactory* getObObjectFactory();
+
+
+   //bool addGbObject3D(GbObject3D *geoObject3D);  
+   bool addGbObject3D(GbObject3D *geoObject3D, std::string name);   
+   //bool addGbObject3D(GbObject3D *geoObject3D, bool active, std::string name);   
+
+   bool removeGbObject3D(GbObject3D *geoObject3D);
+   bool removeGbObject3D(int index);
+
+   int getNumberOfGbObject3Ds();                 
+   std::vector<GbObject3D*>* getAllGbObject3Ds();
+   GbObject3D* getGbObject3D(int index);
+
+   //keine Definition dafuer da ...
+   //void writeValidationAVSFile(string filename);
+   //void writeSurfaceAVSFile(string filename);
+
+   //public final OctConstructionDescriptor[] getAllActiveConstructions()
+   //public final OctSpecificConstructionInstrument getSpecificConstructionInstrumentInstance(int index)
+   //public final boolean isConstructionActive(int index)
+   //public final boolean isConstructionVisible(int index)
+   //public final void activateConstruction(int index, boolean active)
+   //public final void visibleConstruction(int index, boolean visible)
+  // UbTableModel* getTableModel();
+   //void objectChanged(UbObservable* observable);
+   //void objectWillBeDeleted(UbObservable* observable);
+
+
+   void read(UbFileInput *in);
+   void write(UbFileOutput *out); 
+
+   std::string toString();
+
+private:
+   //GbObject3DTableModel* tablemodel;
+  // GbObject3D* selectedObject;
+   //vector<GbObject3DEntry*> gbObject3DList;
+};
+
+class GbObject3DTableModel : public UbTableModel
+{
+public:
+
+   static const int COL_NAME   = 0;
+   static const int COL_TYPE   = 1;
+   static const int COL_ACTIVE = 2;
+
+   GbObject3DTableModel(GbObject3DManager* manager);
+   ~GbObject3DTableModel(void);
+
+   //////////////////////////////////////////////////////////////////////////
+   //Geerbt von CabTable
+   int getColumnNumber(void);
+   int getRowNumber();
+
+   std::string getColumnLabel(int column);
+
+   int getColumnType(int);
+   std::string getStringValue(int row, int col);
+   int getSelectedRowIndex();
+   //bool GetBoolValue(int row, int col);
+   void setStringValue(int row, int col, std::string str) { throw UbException(UB_EXARGS,"not implemented"); }
+
+protected:
+   GbObject3DManager* objectManager;
+};
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbObjectGroup3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbObjectGroup3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3e8c4087d537ae4c0bcf03155b032c459ade327f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbObjectGroup3D.cpp
@@ -0,0 +1,146 @@
+#include <numerics/geometry3d/GbObjectGroup3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+using namespace std;
+
+/*=====================================================*/
+GbObjectGroup3D::GbObjectGroup3D()
+{
+   this->setName("ObjectGroup");
+}
+/*=====================================================*/
+GbObjectGroup3D::~GbObjectGroup3D()
+{
+}
+/*=====================================================*/
+void GbObjectGroup3D::finalize()
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=======================================================*/
+void GbObjectGroup3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+double GbObjectGroup3D::getDistance(GbPoint3D* p)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+
+void GbObjectGroup3D::setCenterX1Coordinate(const double& value)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+void GbObjectGroup3D::setCenterX2Coordinate(const double& value)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+void GbObjectGroup3D::setCenterX3Coordinate(const double& value)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+void GbObjectGroup3D::setRadius(const double& radius)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+double GbObjectGroup3D::getDistance(const double& x1p, const double& x2p, const double& x3p)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+//true, wenn 'in Object' oder 'auf Boundary'!
+bool GbObjectGroup3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   return false;
+}
+/*=====================================================*/
+//true, wenn 'in Object' oder 'auf Boundary'!
+bool GbObjectGroup3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   return false;
+}
+/*=====================================================*/
+string GbObjectGroup3D::toString()
+{
+	stringstream ss;
+	ss<< "GbObjectGroup3D[";
+	ss <<"mid="<<midPoint->toString()<<", r="<<radius<<"]";
+	return ss.str();
+}
+/*=====================================================*/
+GbLine3D* GbObjectGroup3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   return NULL;
+}
+/*=========================================================================*/
+vector<GbTriangle3D*> GbObjectGroup3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> allTriangles;
+
+   //loop ueber alle objekte in der group
+   for( std::list< GbObject3D* >::iterator iter = this->geoobjects.begin();
+                                          iter != this->geoobjects.end();
+                                          iter++ )
+   {
+      vector<GbTriangle3D*> triangles;
+      triangles = (*iter)->getSurfaceTriangleSet();
+
+      for( size_t i=0;i<triangles.size(); i++ )
+      {
+         //kopieren...
+         allTriangles.push_back( triangles[i] );
+      }
+   }
+   return allTriangles;
+}
+/*=======================================================*/
+void GbObjectGroup3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+}
+/*=======================================================*/
+void GbObjectGroup3D::write(UbFileOutput* out)
+{
+   out->writeString(this->getCreator()->getTypeID());
+   midPoint->write(out);
+   out->writeDouble(radius);
+   out->writeInteger((int)triangulationMode);
+}
+/*=======================================================*/
+void GbObjectGroup3D::read(UbFileInput* in)
+{
+}
+/*=======================================================*/
+bool GbObjectGroup3D::hasIntersectionWithDirectedLine(GbPoint3D origin, GbPoint3D direction)
+{
+   return false;
+}
+/*=======================================================*/
+bool GbObjectGroup3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   return false;
+}
+/*=======================================================*/
+bool GbObjectGroup3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   return false;
+}
+/*==========================================================*/
+double GbObjectGroup3D::getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   return 0.0;
+}
+/*==========================================================*/
+double GbObjectGroup3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   return 0.0;
+}
+/*=======================================================*/
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbObjectGroup3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbObjectGroup3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..52ffdcf7c6ec5e0261d41ff9b38337b193c1e423
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbObjectGroup3D.h
@@ -0,0 +1,162 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBOBJECTGROUP3D_H
+#define GBOBJECTGROUP3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+#ifdef CAB_CTL
+   #include <ctl.h>
+#endif //CAB_CTL
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <basics/utilities/UbObserver.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbObjectGroup3D;
+typedef VFSharedPtr<GbObjectGroup3D> GbObjectGroup3DPtr;
+
+
+class GbLine3D;
+class GbTriangle3D;
+class GbObject3DCreator;
+
+class GbObjectGroup3D : public GbObject3D, public UbObserver
+{                                              
+public:
+   enum TRIANGULATIONMODE { CUBOIDPROJECTION ,RAYPROJECTION };
+   
+   //////////////////////////////////////////////////////////////////////////
+   // Konstruktoren
+   GbObjectGroup3D(); 
+   GbObjectGroup3D(GbObjectGroup3D *group){}; 
+   ~GbObjectGroup3D();
+
+   GbObjectGroup3D* clone() {return new GbObjectGroup3D(this);}
+   void finalize();
+
+   void addGbObject(GbObject3D* object)
+   {
+      this->geoobjects.push_back(object);
+   }
+
+   double getRadius() const	{	return this->radius;	}
+
+   double getX1Centroid()  { return midPoint->getX1Coordinate();}
+   double getX1Minimum()   { return midPoint->getX1Coordinate()-radius;}
+   double getX1Maximum()   { return midPoint->getX1Coordinate()+radius;}
+   double getX2Centroid()  { return midPoint->getX2Coordinate();}
+   double getX2Minimum()   { return midPoint->getX2Coordinate()-radius;}
+   double getX2Maximum()   { return midPoint->getX2Coordinate()+radius;}
+   double getX3Centroid()  { return midPoint->getX3Coordinate();}
+   double getX3Minimum()   { return midPoint->getX3Coordinate()-radius;}
+   double getX3Maximum()   { return midPoint->getX3Coordinate()+radius;}
+
+   void setCenterX1Coordinate(const double& value);
+   void setCenterX2Coordinate(const double& value);
+   void setCenterX3Coordinate(const double& value);
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+   void setRadius(const double& radius);
+
+   GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+   double getDistance(GbPoint3D* p); 
+   double getDistance(const double& x1p, const double& x2p, const double& x3p);
+
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary);
+
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+                                
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+   bool hasIntersectionWithDirectedLine(GbPoint3D origin, GbPoint3D direction);
+
+	std::string toString();
+
+   ObObjectCreator* getCreator(){ return NULL; };
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);       
+
+   void translate(const double& x1, const double& x2, const double& x3) 
+   {
+      this->midPoint->translate(x1, x2, x3); 
+      this->notifyObserversObjectChanged();
+   }
+   void rotate(const double& rx1, const double& rx2, const double& rx3) {/* rotation makes no sense*/ }
+   void scale(const double& sx1, const double& sx2, const double& sx3) { this->radius *= sx1; }
+
+   TRIANGULATIONMODE getTriangulationMode() {return triangulationMode;}
+   void setTriangulationMode(TRIANGULATIONMODE mode) { this->triangulationMode = mode; }
+   
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject)
+   {
+      this->notifyObserversObjectChanged();
+      //std::cout<<"GbSphere:objectChanged() - toDo-);";
+   }
+   void objectWillBeDeleted(UbObservable* objectForDeletion)
+   {
+	   std::cout<<"throw UbException(-GbObjectGroup3D::finalize() - toDo-);";
+   }
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere, weil man eine
+
+   std::list< GbObject3D* > getGbObject3DList() { return this->geoobjects; }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & midPoint;
+      ar & radius;
+      ar & triangulationMode;
+      ar & geoobjects;
+   }
+#endif //CAB_RCF
+#ifdef CAB_CTL
+   ctl::oStream &write(ctl::oStream &os) const
+   { 
+      midPoint->write(os);
+      return os<<radius; 
+   }
+   ctl::iStream &read(ctl::iStream &is) 
+   { 
+      midPoint->read(is);
+      return is>>radius;
+   }
+#endif //CAB_CTL
+
+private:
+   GbPoint3D* midPoint;
+   double radius;  // Radius des Kreises
+   TRIANGULATIONMODE triangulationMode;
+
+   std::list< GbObject3D* > geoobjects;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   #if defined(RCF_USE_SF_SERIALIZATION) && (CAB_RCF <= 903) 
+      SF_SERIALIZE_ENUM(GbObjectGroup3D::TRIANGULATIONMODE) //bei klassen ausserhalb der klasse;-)
+   #endif
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbObjectGroup3D>("GbObjectGroup3D")        , SF_GbObjectGroup3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbObjectGroup3D >()), SF_GbObjectGroup3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //GbObjectGroup3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbPoint3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbPoint3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..980fcf386f20cb0e64c56e0301bbc23995b269e4
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbPoint3D.cpp
@@ -0,0 +1,146 @@
+#include <numerics/geometry3d/GbPoint3D.h>
+//#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/creator/GbPoint3DCreator.h>
+
+using namespace std;
+
+/*=======================================================*/
+ObObjectCreator* GbPoint3D::getCreator()
+{
+   return GbPoint3DCreator::getInstance();
+}
+/*=======================================================*/
+GbPoint3D::GbPoint3D()
+{ 
+   this->x1=0.0; 
+   this->x2=0.0; 
+   this->x3=0.0;
+}                                             
+/*=======================================================*/
+GbPoint3D::GbPoint3D(const double& x1, const double& x2, const double& x3)
+{ 
+   this->x1=x1; 
+   this->x2=x2; 
+   this->x3=x3;
+}
+/*=======================================================*/
+GbPoint3D::GbPoint3D(GbPoint3D* point)
+{
+   this->x1 = point->x1;                                             
+   this->x2 = point->x2;
+   this->x3 = point->x3;
+} 
+/*=======================================================*/
+double GbPoint3D::getDistance(GbPoint3D* p)
+{
+   double dx1 = this->x1 - p->x1;
+   double dx2 = this->x2 - p->x2;
+   double dx3 = this->x3 - p->x3;
+   return std::sqrt(dx1*dx1 + dx2*dx2 + dx3*dx3);
+}
+/*=======================================================*/
+bool GbPoint3D::equals(const GbPoint3D* point) const
+{
+   if(fabs(this->x1-point->x1)>1.E-10) return false;
+   if(fabs(this->x2-point->x2)>1.E-10) return false;
+   if(fabs(this->x3-point->x3)>1.E-10) return false;
+
+   return true;
+}
+/*=======================================================*/
+void GbPoint3D::transform(const double matrix[4][4])
+{
+   double tempX1 = x1;
+   double tempX2 = x2;
+   double tempX3 = x3;
+   x1 = matrix[0][0] * tempX1 + matrix[0][1] * tempX2 + matrix[0][2] * tempX3 + matrix[0][3] * 1.;
+   x2 = matrix[1][0] * tempX1 + matrix[1][1] * tempX2 + matrix[1][2] * tempX3 + matrix[1][3] * 1.;
+   x3 = matrix[2][0] * tempX1 + matrix[2][1] * tempX2 + matrix[2][2] * tempX3 + matrix[2][3] * 1.;
+}
+/*=======================================================*/
+bool GbPoint3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+{
+   return (fabs(x1)<1.E-13 && fabs(x2)<1.E-13 && fabs(x3)<1.E-13 );
+}
+/*=======================================================*/
+bool GbPoint3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+{
+   pointIsOnBoundary = (fabs(x1)<1.E-13 && fabs(x2)<1.E-13 && fabs(x3)<1.E-13 );
+   return pointIsOnBoundary;
+}
+/*=======================================================*/
+vector<GbTriangle3D*> GbPoint3D::getSurfaceTriangleSet()
+{            
+   cout<<"GbPoint3D::getSurfaceTriangleSet() - test ... if no exception occurs, everything is fine\n";
+   vector<GbTriangle3D*> triangles;
+   return triangles; //<-empty vector! is okay!
+   
+   //old:
+   //to avoid unnecessary exceptions a point will generate a triangle with
+   //three point with same coordinates
+   //vector<GbTriangle3D*> triangles;
+   //GbPoint3D p1(getX1Coordinate(),getX2Coordinate(),getX3Coordinate());
+   //triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p1),new GbPoint3D(p1)));
+}
+/*=======================================================*/
+GbLine3D* GbPoint3D::createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"not implemented");
+} 
+/*=======================================================*/
+string GbPoint3D::toString()
+{
+   stringstream ss;
+   ss<<"GbPoint3D["<<this->x1<<","<<this->x2<<","<<this->x3<<"]";
+   return((ss.str()).c_str());
+}
+/*=======================================================*/
+void GbPoint3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   out->writeDouble(x1);
+   out->writeDouble(x2);
+   out->writeDouble(x3);
+}
+/*=======================================================*/
+void GbPoint3D::read(UbFileInput* in) 
+{  
+   x1=in->readDouble();
+   x2=in->readDouble();
+   x3=in->readDouble();
+}
+/*=======================================================*/
+void GbPoint3D::translate(const double& dx1, const double& dx2, const double& dx3)
+{  
+   this->x1 += dx1;
+   this->x2 += dx2;
+   this->x3 += dx3;
+  // wenn Notify hier dann nicht im Cuboid oder spher translate ?!
+   //sollte eigentlich!
+   //--> hier muss notify aufgerufen werden udn rekuriv dann z.B. Cuboid, etc 
+   
+   //aber da ist halt einfach daemlich, ich asse es auf gellers way... (erstmal)
+   this->notifyObserversObjectChanged(); 
+}
+/*=======================================================*/
+void GbPoint3D::rotate(const double& rx1, const double& rx2, const double& rx3)
+{  
+   double newX1 = cos(rx3)*cos(rx2)*x1-x2*sin(rx3)*cos(rx1)+x2*cos(rx3)*sin(rx2)*sin(rx1)+x3*sin(rx3)*sin(rx1)+x3*cos(rx3)*sin(rx2)*cos(rx1);
+   double newX2 =  sin(rx3)*cos(rx2)*x1+x2*cos(rx3)*cos(rx1)+x2*sin(rx3)*sin(rx2)*sin(rx1)-x3*cos(rx3)*sin(rx1)+x3*sin(rx3)*sin(rx2)*cos(rx1);
+   double newX3 = -sin(rx2)*x1+cos(rx2)*sin(rx1)*x2+cos(rx2)*cos(rx1)*x3;
+
+   this->x1 = newX1;
+   this->x2 = newX2;
+   this->x3 = newX3;
+   this->notifyObserversObjectChanged(); 
+}
+/*=======================================================*/
+void GbPoint3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{  
+   this->x1 *= sx1;
+   this->x2 *= sx2;
+   this->x3 *= sx3;
+   this->notifyObserversObjectChanged(); 
+}
+/*=======================================================*/
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbPoint3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbPoint3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..5cccbc1718b10321867742def359e18109afeb8d
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbPoint3D.h
@@ -0,0 +1,123 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBPOINT3D_H
+#define GBPOINT3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <string>
+#include <sstream>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbPoint3D;
+typedef VFSharedPtr<GbPoint3D> GbPoint3DPtr;
+
+
+class GbTriangle3D;
+class GbObject3DCreator;
+
+#ifdef CAB_CTL
+   #include <ctl.h>
+#endif
+
+class GbPoint3D : public GbObject3D
+{
+public:
+   GbPoint3D();
+   GbPoint3D(const double& x1, const double& x2, const double& x3);
+   GbPoint3D(GbPoint3D *point);                
+   ~GbPoint3D() {}
+
+   GbPoint3D* clone() {return new GbPoint3D(this);}
+   void finalize() {}
+
+   void setCoordinates(const double& x1, const double& x2, const double& x3)
+   {
+       this->x1=x1;
+       this->x2=x2;
+       this->x3=x3;
+       this->notifyObserversObjectChanged();
+   }
+   void setX1(const double& x1) { this->x1=x1; this->notifyObserversObjectChanged(); }
+   void setX2(const double& x2) { this->x2=x2; this->notifyObserversObjectChanged(); }
+   void setX3(const double& x3) { this->x3=x3; this->notifyObserversObjectChanged(); }
+
+   double getX1Coordinate() const  { return this->x1; }
+   double getX2Coordinate() const  { return this->x2; }
+   double getX3Coordinate() const  { return this->x3; }
+
+   void transform(const double matrix[4][4]);
+ 
+   double getX1Centroid()  { return this->x1; }
+   double getX1Minimum()   { return this->x1; }
+   double getX1Maximum()   { return this->x1; }
+   double getX2Centroid()  { return this->x2; }
+   double getX2Minimum()   { return this->x2; }
+   double getX2Maximum()   { return this->x2; }
+   double getX3Centroid()  { return this->x3; }
+   double getX3Minimum()   { return this->x3; }
+   double getX3Maximum()   { return this->x3; }        
+ 
+   void translate(const double& x1, const double& x2, const double& x3);
+   void rotate(const double& rx1, const double& rx2, const double& rx3);
+   void scale(const double& sx1, const double& sx2, const double& sx3);
+
+   double getDistance(GbPoint3D *p);
+   bool equals(const GbPoint3D* point) const;
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary);
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x23) { return false; }
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   GbLine3D* createClippedLine3D(GbPoint3D &point1, GbPoint3D &point2);
+   virtual std::string toString();
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren
+                                          //, welche sonst hier "ueberdeckt" waere,da es dieselbe methode mit anderen args gibt!
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & x1; 
+      ar & x2; 
+      ar & x3;
+   }
+#endif //CAB_RCF
+
+#ifdef CAB_CTL
+   ctl::oStream &write(ctl::oStream &os) const
+   { 
+      return os<<x1<<x2<<x3; 
+   }
+   ctl::iStream &read(ctl::iStream &is) 
+   { 
+      return is>>x1>>x2>>x3;
+   }
+#endif
+
+   //member
+   double x1;
+   double x2;
+   double x3;      
+};
+
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbPoint3D>("GbPoint3D")              , SF_GbPoint3D      );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbPoint3D >()), SF_GbPoint3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbPolygon3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbPolygon3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..879c6a9af274e551d306ccb99eb6a1998a7cd723
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbPolygon3D.cpp
@@ -0,0 +1,686 @@
+#include <numerics/geometry3d/GbPolygon3D.h>
+#include <numerics/geometry3d/creator/GbPolygon3DCreator.h>
+
+using namespace std;
+
+ObObjectCreator* GbPolygon3D::getCreator()
+{
+   return GbPolygon3DCreator::getInstance();
+}
+
+int GbPolygon3D::counter = 0;
+
+GbPolygon3D::GbPolygon3D()
+{
+   init();
+   counter++;
+   this->ps = new GbSystem3D::PointSet3(0);
+}
+void GbPolygon3D::init()
+{
+   x1s        = 0.0;
+   x2s        = 0.0;
+   x1min      = 0.0;
+   x1max      = 0.0;
+   x2min      = 0.0;
+   x2max      = 0.0;
+   //		points   = NULL;
+   consistent = false;
+   ps         = NULL;
+}
+
+/**
+* Creates an empty 3D polygon with the specified capacity.
+* @param capacity the initial capacity
+*/
+GbPolygon3D::GbPolygon3D(int capacity)
+{
+   init();
+   counter++;
+   this->ps = new GbSystem3D::PointSet3(capacity);
+   //     this.po = new PointObserver(this);
+}
+/**
+* Creates a 3D polygon with the specified points.
+* @param points the initial points of the polygon
+*/
+GbPolygon3D::GbPolygon3D(vector<GbPoint3D>& points)
+{
+   init();
+   counter++;
+   this->ps = new GbSystem3D::PointSet3((int)points.size());
+   this->addPoints(points);
+}
+/**
+* Creates a 3D polygon as clone of the specified 3D polygon.
+* @param polygon the 3D polygon to be cloned
+*/
+GbPolygon3D::GbPolygon3D(GbPolygon3D* polygon)
+{
+   this->init();
+   counter++;
+   this->ps = new GbSystem3D::PointSet3((int)polygon->size());
+   vector<GbPoint3D> temp = polygon->getPoints();
+   this->addPoints( temp  );
+}
+
+GbPolygon3D::~GbPolygon3D()
+{
+   counter--;
+   //if(points)
+   //for(unsigned u=0; u<points->size(); u++)
+   //{
+   //	delete (*points)[u];
+   //}
+   //		delete this->points;
+   delete this->ps;
+}
+
+/*======================================================================*/
+/**
+* Returns the number of points.
+* @return the number of points
+*/
+int GbPolygon3D::size()
+{
+   return(this->ps->size());
+}
+/**
+* Returns the number of times this 3D polygon contains the specified point.
+* @param point the point
+* @return the number of times this 3D polygon contains the specified point
+*/
+int GbPolygon3D::contains(GbPoint3D* point)
+{
+   return(this->ps->contains(point));
+}
+/**
+* Returns the number of times this 3D polygon contains a point equal to the specified point.
+* @param point the point
+* @return the number of times this 3D polygon contains a point equal to the specified point
+*/
+int GbPolygon3D::containsEqual(GbPoint3D* point)
+{
+   return(this->ps->containsEqual(point));
+}
+/**
+* Returns true, if this 3D polygon contains the specified line.
+* @param point1 the first point
+* @param point2 the second point
+* @return true, if this 3D polygon contains the specified line
+*/
+bool GbPolygon3D::containsLine(GbPoint3D* point1, GbPoint3D* point2)
+{
+   return(this->ps->containsLine(point1, point2));
+}
+/**
+* Returns true, if this 3D polygon contains the specified line.
+* @param line the line
+* @return true, if this 3D polygon contains the specified line
+*/
+bool GbPolygon3D::containsLine(GbLine3D* line)
+{
+   return(this->ps->containsLine(line->getPoint1(), line->getPoint2()));
+}
+/**
+* Returns the first point.
+* @return the first point
+*/
+GbPoint3D* GbPolygon3D::getFirstPoint()
+{
+   return(this->ps->getFirstPoint());
+}
+/**
+* Returns the last point.
+* @return the last point
+*/
+GbPoint3D* GbPolygon3D::getLastPoint()
+{
+   return(this->ps->getLastPoint());
+}
+/**
+* Returns the specified point.
+* @param index the index
+* @return the specified point
+* @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+*/
+GbPoint3D* GbPolygon3D::getPoint(const int& index) 
+{
+   if(index < 0 || index > this->ps->size()) throw UbException(UB_EXARGS,"ArrayIndexOutOfBoundsException-GbPolygon3D.getPoint()");
+   return(this->ps->getPoint(index));
+}
+/**
+* Returns the points.
+* @return the points
+*/
+vector<GbPoint3D> GbPolygon3D::getPoints()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->points);
+}
+/**
+* Returns the points within the specified rectangle.
+* @param p1 the 1st point of the rectangle
+* @param p2 the 2nd point of the rectangle
+* @return the points within the specified rectangle
+*/
+vector<GbPoint3D> GbPolygon3D::getPoints(GbPoint3D* p1, GbPoint3D* p2)
+{
+   return(this->getPoints(p1->x1, p1->x2, p1->x3, p2->x1, p2->x2, p2->x3));
+}
+/**
+* Returns the points within the specified rectangle.
+* @param p1x1 the 1st x1 coordinate of the rectangle
+* @param p1x2 the 1st x2 coordinate of the rectangle
+* @param p1x3 the 1st x3 coordinate of the rectangle
+* @param p2x1 the 2nd x1 coordinate of the rectangle
+* @param p2x2 the 2nd x2 coordinate of the rectangle
+* @param p2x3 the 2nd x3 coordinate of the rectangle
+* @return the points within the specified rectangle
+*/
+vector<GbPoint3D> GbPolygon3D::getPoints(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3)
+{
+   double x1min, x1max, x2min, x2max, x3min, x3max;
+
+   if(UbMath::less(p1x1, p2x1)) { x1min = p1x1; x1max = p2x1; }
+   else                           { x1min = p2x1; x1max = p1x1; }
+   if(UbMath::less(p1x2, p2x2)) { x2min = p1x2; x2max = p2x2; }
+   else                           { x2min = p2x2; x2max = p1x2; }
+   if(UbMath::less(p1x3, p2x3)) { x3min = p1x3; x3max = p2x3; }
+   else                           { x3min = p2x3; x3max = p1x3; }
+
+   GbSystem3D::PointSet3 *pts = new GbSystem3D::PointSet3(1);
+
+   if(!this->consistent) this->calculateValues();
+   for(int i=this->size()-1; i>=0; i--)
+   {
+      if(UbMath::lessEqual(x1min, (this->points)[i].x1) && UbMath::greaterEqual(x1max, (this->points)[i].x1) &&
+         UbMath::lessEqual(x2min, (this->points)[i].x2) && UbMath::greaterEqual(x2max, (this->points)[i].x2) &&
+         UbMath::lessEqual(x3min, (this->points)[i].x3) && UbMath::greaterEqual(x3max, (this->points)[i].x3))     pts->add((this->points)[i]);
+   }
+   return(pts->getPoints());
+}
+/**
+* Returns the area of this polygon.
+* The area is positive for positive ordered points, otherwise negative.
+* @return the area of this polygon
+*/
+//double getArea()
+//{
+//   if(!this.consistent) this.calculateValues();
+//   return(this.area);
+//}
+double GbPolygon3D::getX1Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1s);
+}
+double GbPolygon3D::getX1Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1min);
+}
+double GbPolygon3D::getX1Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1max);
+}
+double GbPolygon3D::getX2Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2s);
+}
+double GbPolygon3D::getX2Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2min);
+}
+double GbPolygon3D::getX2Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2max);
+}
+double GbPolygon3D::getX3Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3s);
+}
+double GbPolygon3D::getX3Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3min);
+}
+double GbPolygon3D::getX3Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3max);
+}
+
+/**
+* Adds a point to the end of this polygon. Notifies the observers of this 3D polygon.
+* @param point the point
+*/
+void GbPolygon3D::addPoint(GbPoint3D* point)
+{
+   //if((this instanceof GbPolygon3D) && !(point instanceof GbPoint3D)) throw new IllegalArgumentException("GbPolygon3D.addPoint(): points of 3D polygons have to be 3D points!");
+
+   this->ps->add(point);
+   //point.addObserver(this.po);
+   this->consistent = false;
+   //super.notifyObservers();
+}
+/**
+* Adds a number of points to the end of this polygon. Notifies the observers of this 3D polygon.
+* @param points the points
+*/
+void GbPolygon3D::addPoints(vector<GbPoint3D>& points)
+{
+   //if((this instanceof GbPolygon3D) && (points.getClass().getComponentType() != GbPoint3D.class)) throw new IllegalArgumentException("GbPolygon3D.addPoints(): points of 3D polygons have to be 3D points!");
+
+   this->ps->add(points);
+   //for(int i=0; i<points.length; i++) points[i].addObserver(this.po);
+   this->consistent = false;
+   //super.notifyObservers();
+}
+/**
+* Inserts a point at the specified position within this polygon. Notifies the observers of this 3D polygon.
+* @param point the point
+* @param index the index
+* @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+*/
+//public void insertPoint(GbPoint3D point, int index) throws ArrayIndexOutOfBoundsException
+//{
+//   if((this instanceof GbPolygon3D) && !(point instanceof GbPoint3D)) throw new IllegalArgumentException("GbPolygon3D.insertPoint(): points of 3D polygons have to be 3D points!");
+//   if(index < 0 || index > this.ps.size()) throw new ArrayIndexOutOfBoundsException("GbPolygon3D.insert(): invalid index specified: "+index);
+
+//   this.ps.insert(point, index);
+//   point.addObserver(this.po);
+//   this.consistent = false;
+//   super.notifyObservers();
+//}
+/**
+* Removes all points from this polygon identical to the specified one. Notifies the observers of this 3D polygon.
+* @param point the point
+*/
+//public void deletePoint(GbPoint3D point)
+//{
+//   this.ps.delete(point);
+//   point.removeObserver(this.po);
+//   this.consistent = false;
+//   super.notifyObservers();
+//}
+/**
+* Removes all points from this polygon equal to the specified one. Notifies the observers of this 3D polygon.
+* @param point the point
+*/
+//public void deleteEqualPoint(GbPoint3D point)
+//{
+//   this.ps.deleteEqual(point);
+//   point.removeObserver(this.po);
+//   this.consistent = false;
+//   super.notifyObservers();
+//}
+/**
+* Removes all points from this polygon. Notifies the observers of this 3D polygon.
+*/
+void GbPolygon3D::clear()
+{
+   //		delete this->points;
+   this->ps->clearAndTrim();
+   delete this->ps;
+
+   //for(int i=points.length-1; i>=0; i--) points[i].removeObserver(this.po);
+   this->consistent = false;
+   //super.notifyObservers();
+}
+
+/**
+* Returns true if this 3D polygon equals the specified object.
+* Two polygon are equal, if their points are equal.
+* <BR>Note that the order of points is recognized!
+* @return true if this 3D polygon equals the specified object
+* @see GbPoint3D#equals(java.lang.Object)
+*/
+// bool equals(Object object)
+// {
+//    try
+//    {
+//	GbPolygon2D polygon = (GbPolygon3D) object;
+//int         n       = this.size();
+
+//if(n != polygon.size()) return(false);
+//for(int i=0; i<n; i++) if(!this.getPoint(i).equals(polygon.getPoint(i))) return(false);
+//return(true);
+//    }
+//    catch(Exception e){ return(false); }
+// }
+/**
+* Returns a string representation of this 3D polygon.
+* @return a string representation of this 3D polygon
+*/
+string GbPolygon3D::toString()
+{
+   stringstream ss;
+   ss<<"GbPolygon3D[";
+   ss<<this->size()<<" points";
+
+   //    ss<<", x1s="<<this->x1s;
+   //    ss<<", x2s="<<this->x2s;
+   //ss<<", x3s="<<this->x3s;
+   //    ss<<", x1min="<<this->x1min;
+   //    ss<<", x1max="<<this->x1max;
+   //    ss<<", x2min="<<this->x2min;
+   //    ss<<", x2max="<<this->x2max;
+   //ss<<", x3min="<<this->x3min;
+   //    ss<<", x3max="<<this->x3max;
+   ss<<"]"<<endl;
+   for(int u=0; u<this->size(); u++)
+      ss<<this->ps->getPoint(u)->toString()<<endl;
+
+   return(ss.str());
+}
+/*======================================================================*/
+
+
+/*======================================================================*/
+/*  Calculation                                                         */
+/*                                                                      */
+/*
+* Returns the intersection points of this 3D polygon and the specified 3D line.
+* @param line the 3D line to intersect
+* @return the intersection points of this 3D polygon and the specified 3D line
+*/
+// public GbPoint3D[] calculateIntersectionPoints3D(GbLine3D line)
+// {
+//    GbSystem.PointSet pointSet = new GbSystem.PointSet(0);
+//    GbPoint3D         points[] = this.getPoints();
+//    GbPoint3D         pCrossed = null;
+//    int               n        = points.length;
+//    if(n < 2)         return(pointSet.getPoints());
+
+//    for(int i=1; i<n; i++)
+//    {
+//pCrossed = GbSystem.calculateIntersectionPoint3D(points[i-1], points[i], line.p1, line.p2);
+//if(pCrossed != null) pointSet.add(pCrossed);
+//    }
+//    pCrossed = GbSystem.calculateIntersectionPoint3D(points[n-1], points[0], line.p1, line.p2);
+//    if(pCrossed != null) pointSet.add(pCrossed);
+
+//    return(pointSet.getPoints());
+// }
+
+/*
+* Returns true if the specified 3D point lies within (or on the border of) this 3D polygon.
+* @param point the 3D point to check
+* @return true if the specified 3D point lies within (or on the border of) this 3D polygon
+*/
+// public boolean enclosesPoint3D(GbPoint3D point)
+// {
+//    if(GbSystem.less(point.x1, this.x1min))    return(false);
+//    if(GbSystem.less(point.x2, this.x2min))    return(false);
+//    if(GbSystem.greater(point.x1, this.x1max)) return(false);
+//    if(GbSystem.greater(point.x2, this.x2max)) return(false);
+//    if(this.containsEqual(point) > 0)          return(true);
+
+//    QbList    ltest    = new QbList(GbPoint2D.class, QbList.NOEQUALOBJECTS);
+//    GbPoint3D points[] = this.getPoints();
+//    GbPoint3D ptest;
+//    int       n        = points.length;
+//    if(n < 2) return(false);
+
+//    if(GbSystem.equal(point.x2, this.x2min)) ptest = new GbPoint3D(point.x1, this.x2min-1.0);
+//    else                                     ptest = new GbPoint3D(point.x1, this.x2max+1.0);
+
+//    for(int i=1; i<n; i++)
+//    {
+//try { ltest.append(GbSystem.calculateIntersectionPoint2D(points[i-1], points[i], point, ptest)); }
+//catch(Exception e){}
+//    }
+//    try { ltest.append(GbSystem.calculateIntersectionPoint3D(points[n-1], points[0], point, ptest)); }
+//    catch(Exception e){}
+//    return((ltest.size()%2)==1);
+// }
+
+/*
+* Returns a new 3D polygon clipped by the specified 3D rectangle (result may be null!).
+* @param rectangle the 3D rectangle
+* @return a new 3D polygon clipped by the specified 3D rectangle
+*/
+// GbPolygon3D *createClippedPolygon3D(GbCuboid3D *cube)
+// {
+//return(GbSystem::clipPolygon3D(this->getPoints(), cube->p1->x1, cube->p1->x2, cube->p1->x3, , cube->p2->x1, cube->p2->x2, cube->p2->x3));
+// }
+/*                                          
+* Returns a new 3D polygon clipped by the specified 3D rectangle (result may be null!).
+* @param p1 the 1st point of the rectangle
+* @param p2 the 2nd point of the rectangle
+* @return a new 3D polygon clipped by the specified 3D rectangle
+*/
+// GbPolygon3D *createClippedPolygon3D(GbPoint3D *p1, GbPoint3D *p2)
+// {
+//return(GbSystem::clipPolygon3D(this->getPoints(), p1->x1, p1->x2, p1->x3, p2->x1, p2->x2, p2->x3));
+// }
+/*
+* Returns a new 3D polygon clipped by the specified 3D rectangle (result may be null!).
+* @param p1x1 the 1st x1 coordinate of the rectangle
+* @param p1x2 the 1st x2 coordinate of the rectangle
+* @param p2x1 the 2nd x1 coordinate of the rectangle
+* @param p2x2 the 2nd x2 coordinate of the rectangle
+* @return a new 3D polygon clipped by the specified 3D rectangle
+*/
+// GbPolygon3D *createClippedPolygon3D(double p1x1, double p1x2, double p1x3, double p2x1, double p2x2, double p2x3)
+// {
+//return(GbSystem::clipPolygon3D(this.getPoints(), p1x1, p1x2, p1x3, p2x1, p2x2. p2x3));
+// }
+
+/*
+* Returns true if the specified 3D rectangle lies completely within this 3D polygon.
+* @param rectangle the 3D rectangle to check
+* @return true if the specified 3D rectangle lies completely within this 3D polygon
+*/
+//public boolean enclosesRectangle3D(GbRectangle3D rectangle)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), rectangle.getArea()));
+//}
+/*
+* Returns true if the specified 3D rectangle lies completely within this 3D polygon.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 3D rectangle lies completely within this 3D polygon
+*/
+//public boolean enclosesRectangle3D(GbPoint3D p1, GbPoint3D p2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+//}
+/*
+* Returns true if the specified 3D rectangle lies completely within this 3D polygon.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 3D rectangle lies completely within this 3D polygon
+*/
+//public boolean enclosesRectangle3D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+//}
+
+/*
+* Returns true if the specified 3D rectangle is crossed by this 3D polygon.
+* @param rectangle the 3D rectangle to check
+* @return true if the specified 3D rectangle is crossed by this 3D polygon
+*/
+//public boolean crossesRectangle3D(GbRectangle3D rectangle)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, rectangle.getArea()));
+//}
+/*
+* Returns true if the specified 3D rectangle is crossed by this 3D polygon.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 3D rectangle is crossed by this 3D polygon
+*/
+//public boolean crossesRectangle3D(GbPoint3D p1, GbPoint3D p2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+//}
+/*
+* Returns true if the specified 3D rectangle is crossed by this 3D polygon.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 3D rectangle is crossed by this 3D polygon
+*/
+//public boolean crossesRectangle3D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+//}
+
+/*
+* Returns true if the specified 3D rectangle lies (at least partly) within this 3D polygon.
+* @param rectangle the 3D rectangle to check
+* @return true if the specified 3D rectangle lies (at least partly) within this 3D polygon
+*/
+//public boolean enclosesOrCrossesRectangle3D(GbRectangle3D rectangle)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*
+* Returns true if the specified 3D rectangle lies (at least partly) within this 3D polygon.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 3D rectangle lies (at least partly) within this 3D polygon
+*/
+//public boolean enclosesOrCrossesRectangle3D(GbPoint3D p1, GbPoint3D p2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*
+* Returns true if the specified 3D rectangle lies (at least partly) within this 3D polygon.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 3D rectangle lies (at least partly) within this 3D polygon
+*/
+//public boolean enclosesOrCrossesRectangle3D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*======================================================================*/
+
+void GbPolygon3D::calculateValues()
+{
+   this->x1s        = 0.0;
+   this->x2s        = 0.0;
+   this->x3s        = 0.0;
+   this->x1min      = 0.0;
+   this->x1max      = 0.0;
+   this->x2min      = 0.0;
+   this->x2max      = 0.0;
+   this->x3min      = 0.0;
+   this->x3max      = 0.0;
+   throw UbException(UB_EXARGS,"should be implemented");
+
+   //this->consistent = true;
+
+   //this->points = this->ps->getPoints();
+
+   //int       n     = (int)this->points.size();
+   //if(n < 1) return;
+
+   //GbPoint3D p1 = (this->points)[0];
+   //GbPoint3D p2 = NULL;
+   //double    h1 = 0.0;
+   //double    h2 = 0.0;
+   //double    f=0.0;
+
+   //this->x1s   = p1.x1;
+   //this->x1min = p1.x1;
+   //this->x1max = p1.x1;
+   //this->x2s   = p1.x2;
+   //this->x2min = p1.x2;
+   //this->x2max = p1.x2;
+   //this->x3s   = p1.x2;
+   //this->x3min = p1.x2;
+   //this->x3max = p1.x2;
+
+   //std::cout<<"Should be implemented "<<endl;
+
+   //for(int i=1; i<n; i++)
+   //{
+   //  p2         = (this->points)[i];
+   //  f          = p1.x1*p2.x2 - p1.x2*p2.x1;
+   //  this->area += f;
+   //  h1        += f*(p1.x2 + p2.x2);
+   //  h2        += f*(p1.x1 + p2.x1);
+   //  p1         = p2;
+
+   //  if(p1.x1 < this->x1min) this->x1min = p1.x1;
+   //  if(p1.x1 > this->x1max) this->x1max = p1.x1;
+   //  if(p1.x2 < this->x2min) this->x2min = p1.x2;
+   //  if(p1.x2 > this->x2max) this->x2max = p1.x2;
+   //}
+   //p2         = (this->points)[0];
+   //f          = p1.x1*p2.x2 - p1.x2*p2.x1;
+   //this->area += f;
+   //h1        += f*(p1.x2 + p2.x2);
+   //h2        += f*(p1.x1 + p2.x1);
+
+   //this->area *= 0.5;
+   //h1        /= 6.0;
+   //h2        /= 6.0;
+
+   //if(n > 2)
+   //{
+   //   this->x1s = h2/this->area;
+   //   this->x2s = h1/this->area;
+   //}
+
+   //if(n < 3 || !GbSystem::inClosedInterval(this->x1s, this->x1min, this->x1max)) this->x1s = 0.5*(this->x1min+this->x1max);
+   //if(n < 3 || !GbSystem::inClosedInterval(this->x2s, this->x2min, this->x2max)) this->x2s = 0.5*(this->x2min+this->x2max);
+}
+/*======================================================================*/
+
+
+/*======================================================================*/
+// private class PointObserver implements TiObserver
+// {
+//    GbPolygon3D polygon = null;
+
+//    PointObserver(GbPolygon3D polygon)
+//    {
+//this.polygon = polygon;
+//    }
+
+//    public void objectChanged(Object object)
+//    {
+//if((object instanceof GbPoint3D) && this.polygon.contains((GbPoint3D)object)>0)
+//{
+//   this.polygon.consistent = false;
+//   this.polygon.notifyObservers();
+//}
+//    }
+// }
+/*=======================================================*/
+void GbPolygon3D::write(UbFileOutput* out) 
+{                                      
+   throw UbException(UB_EXARGS,"not implemented");
+}
+/*=======================================================*/
+void GbPolygon3D::read(UbFileInput* in) 
+{  
+   throw UbException(UB_EXARGS,"not implemented");
+}
+/*=======================================================*/
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbPolygon3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbPolygon3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..da383fb05530409a9626ae1a39062f9636d9951a
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbPolygon3D.h
@@ -0,0 +1,536 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBPOLYGON3D_H
+#define GBPOLYGON3D_H
+
+#include <sstream>
+#include <iostream>
+
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbPolygon3D;
+typedef VFSharedPtr<GbPolygon3D> GbPolygon3DPtr;
+
+
+class GbObject3DCreator;
+
+/*=========================================================================*/
+/* GbPolygon2D                                                             */
+/*                                                                         */
+/*
+* This Class provides basic 3D polygon objects.
+*/
+class GbPolygon3D : public GbObject3D
+{
+public:
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+private:
+   /*======================================================================*/
+   double            x1s  ;
+   double            x2s  ;
+   double            x3s  ;
+   double            x1min;
+   double            x1max;
+   double            x2min;
+   double            x2max;
+   double            x3min;
+   double            x3max;
+
+   std::vector<GbPoint3D> points;
+   bool                   consistent;
+
+   GbSystem3D::PointSet3 *ps;
+   //private PointObserver     po         = null;
+
+   void init();
+
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   /*  Konstruktoren                                                       */
+   /*                                                                      */
+   /*
+   * Creates an empty 2D polygon.
+   */
+public:
+   static int counter;
+   GbPolygon3D();
+   /*
+   * Creates an empty 2D polygon with the specified capacity.
+   * @param capacity the initial capacity
+   */
+   GbPolygon3D(int capacity);
+   /*
+   * Creates a 2D polygon with the specified points.
+   * @param points the initial points of the polygon
+   */
+   GbPolygon3D(std::vector<GbPoint3D> &points);
+   /*
+   * Creates a 2D polygon as clone of the specified 2D polygon.
+   * @param polygon the 2D polygon to be cloned
+   */
+   GbPolygon3D(GbPolygon3D *polygon);
+
+   ~GbPolygon3D();
+
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   /*  Methoden                                                            */
+   /*                                                                      */
+   /*
+   * Creates a 2D polygon as clone of this 2D polygon.
+   */
+   GbPolygon3D* clone() {   return(new GbPolygon3D(this)); }
+   void finalize()
+   {
+      throw UbException(UB_EXARGS,"toDo");
+   }
+
+   /*
+   * Returns the number of points.
+   * @return the number of points
+   */
+   int size();
+   /*
+   * Returns the number of times this 2D polygon contains the specified point.
+   * @param point the point
+   * @return the number of times this 2D polygon contains the specified point
+   */
+   int contains(GbPoint3D *point);
+   /*
+   * Returns the number of times this 2D polygon contains a point equal to the specified point.
+   * @param point the point
+   * @return the number of times this 2D polygon contains a point equal to the specified point
+   */
+   int containsEqual(GbPoint3D* point);
+   /*
+   * Returns true, if this 2D polygon contains the specified line.
+   * @param point1 the first point
+   * @param point2 the second point
+   * @return true, if this 2D polygon contains the specified line
+   */
+   bool containsLine(GbPoint3D* point1, GbPoint3D* point2);
+   /*
+   * Returns true, if this 2D polygon contains the specified line.
+   * @param line the line
+   * @return true, if this 2D polygon contains the specified line
+   */
+   bool containsLine(GbLine3D* line);
+   /*
+   * Returns the first point.
+   * @return the first point
+   */
+   GbPoint3D* getFirstPoint();
+   /*
+   * Returns the last point.
+   * @return the last point
+   */
+   GbPoint3D* getLastPoint();
+   /*
+   * Returns the specified point.
+   * @param index the index
+   * @return the specified point
+   * @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+   */
+   GbPoint3D* getPoint(const int& index);
+   /*
+   * Returns the points.
+   * @return the points
+   */
+   std::vector<GbPoint3D> getPoints();
+   /*
+   * Returns the points within the specified rectangle.
+   * @param rectangle the 2D rectangle
+   * @return the points within the specified rectangle
+   */
+   //public GbPoint2D[] getPoints(GbRectangle2D rectangle)
+   //{
+   //   return(this.getPoints(rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2));
+   //}
+   /*
+   * Returns the points within the specified rectangle.
+   * @param p1 the 1st point of the rectangle
+   * @param p2 the 2nd point of the rectangle
+   * @return the points within the specified rectangle
+   */
+   std::vector<GbPoint3D> getPoints(GbPoint3D* p1, GbPoint3D* p2);
+   /*
+   * Returns the points within the specified rectangle.
+   * @param p1x1 the 1st x1 coordinate of the rectangle
+   * @param p1x2 the 1st x2 coordinate of the rectangle
+   * @param p2x1 the 2nd x1 coordinate of the rectangle
+   * @param p2x2 the 2nd x2 coordinate of the rectangle
+   * @return the points within the specified rectangle
+   */
+   std::vector<GbPoint3D> getPoints(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3);
+   /*
+   * Returns the area of this polygon.
+   * The area is positive for positive ordered points, otherwise negative.
+   * @return the area of this polygon
+   */
+   //double getArea()
+   //{
+   //   if(!this.consistent) this.calculateValues();
+   //   return(this.area);
+   //}
+   double getX1Centroid();
+   double getX1Minimum();
+   double getX1Maximum();
+   double getX2Centroid();
+   double getX2Minimum();
+   double getX2Maximum();
+   double getX3Centroid();
+   double getX3Minimum();
+   double getX3Maximum();
+
+   /*
+   * Adds a point to the end of this polygon. Notifies the observers of this 2D polygon.
+   * @param point the point
+   */
+   void addPoint(GbPoint3D* point);
+   /*
+   * Adds a number of points to the end of this polygon. Notifies the observers of this 2D polygon.
+   * @param points the points
+   */
+   void addPoints(std::vector<GbPoint3D>& points);
+   /*
+   * Inserts a point at the specified position within this polygon. Notifies the observers of this 2D polygon.
+   * @param point the point
+   * @param index the index
+   * @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+   */
+   //public void insertPoint(GbPoint2D point, int index) throws ArrayIndexOutOfBoundsException
+   //{
+   //   if((this instanceof GbPolygon3D) && !(point instanceof GbPoint3D)) throw new IllegalArgumentException("GbPolygon2D.insertPoint(): points of 3D polygons have to be 3D points!");
+   //   if(index < 0 || index > this.ps.size()) throw new ArrayIndexOutOfBoundsException("GbPolygon2D.insert(): invalid index specified: "+index);
+
+   //   this.ps.insert(point, index);
+   //   point.addObserver(this.po);
+   //   this.consistent = false;
+   //   super.notifyObservers();
+   //}
+   /*
+   * Removes all points from this polygon identical to the specified one. Notifies the observers of this 2D polygon.
+   * @param point the point
+   */
+   //public void deletePoint(GbPoint2D point)
+   //{
+   //   this.ps.delete(point);
+   //   point.removeObserver(this.po);
+   //   this.consistent = false;
+   //   super.notifyObservers();
+   //}
+   /*
+   * Removes all points from this polygon equal to the specified one. Notifies the observers of this 2D polygon.
+   * @param point the point
+   */
+   //public void deleteEqualPoint(GbPoint2D point)
+   //{
+   //   this.ps.deleteEqual(point);
+   //   point.removeObserver(this.po);
+   //   this.consistent = false;
+   //   super.notifyObservers();
+   //}
+   /*
+   * Removes all points from this polygon. Notifies the observers of this 2D polygon.
+   */
+   void clear();
+
+   /*
+   * Returns true if this 2D polygon equals the specified object.
+   * Two polygon are equal, if their points are equal.
+   * <BR>Note that the order of points is recognized!
+   * @return true if this 2D polygon equals the specified object
+   * @see GbPoint2D#equals(java.lang.Object)
+   * @see GbPoint3D#equals(java.lang.Object)
+   */
+   // bool equals(Object object)
+   // {
+   //    try
+   //    {
+   //	GbPolygon2D polygon = (GbPolygon2D) object;
+   //int         n       = this.size();
+
+   //if(n != polygon.size()) return(false);
+   //for(int i=0; i<n; i++) if(!this.getPoint(i).equals(polygon.getPoint(i))) return(false);
+   //return(true);
+   //    }
+   //    catch(Exception e){ return(false); }
+   // }
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet()
+   {
+      std::cout<<"GbPolygon3D::getSurfaceTriangleSet() - not implemented\n";
+      std::vector<GbTriangle3D*> tmp;
+      return tmp;
+   }
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+   {
+      throw UbException(__FILE__, __LINE__, "GbPolygon3D::isPointInObject3D- not implemented");
+   }
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+   {
+      throw UbException(__FILE__, __LINE__, "GbPolygon3D::isPointInObject3D- not implemented");
+   }
+   bool isCellInsideGbObject3D(double x11,double x21,double x31,double x12,double x22,double x32) { return false; }
+
+   GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D &point2)
+   {
+      throw UbException(__FILE__, __LINE__, "GbPolygon3D::createClippedLine3D - not implemented");
+   }                        
+/*
+   * Returns a string representation of this 2D polygon.
+   * @return a string representation of this 2D polygon
+   */
+   std::string toString();
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   /*  Calculation                                                         */
+   /*                                                                      */
+   /*
+   * Returns the intersection points of this 2D polygon and the specified 2D line.
+   * @param line the 2D line to intersect
+   * @return the intersection points of this 2D polygon and the specified 2D line
+   */
+   // public GbPoint2D[] calculateIntersectionPoints2D(GbLine2D line)
+   // {
+   //    GbSystem.PointSet pointSet = new GbSystem.PointSet(0);
+   //    GbPoint2D         points[] = this.getPoints();
+   //    GbPoint2D         pCrossed = null;
+   //    int               n        = points.length;
+   //    if(n < 2)         return(pointSet.getPoints());
+
+   //    for(int i=1; i<n; i++)
+   //    {
+   //pCrossed = GbSystem.calculateIntersectionPoint2D(points[i-1], points[i], line.p1, line.p2);
+   //if(pCrossed != null) pointSet.add(pCrossed);
+   //    }
+   //    pCrossed = GbSystem.calculateIntersectionPoint2D(points[n-1], points[0], line.p1, line.p2);
+   //    if(pCrossed != null) pointSet.add(pCrossed);
+
+   //    return(pointSet.getPoints());
+   // }
+
+   /*
+   * Returns true if the specified 2D point lies within (or on the border of) this 2D polygon.
+   * @param point the 2D point to check
+   * @return true if the specified 2D point lies within (or on the border of) this 2D polygon
+   */
+   // public boolean enclosesPoint2D(GbPoint2D point)
+   // {
+   //    if(GbSystem.less(point.x1, this.x1min))    return(false);
+   //    if(GbSystem.less(point.x2, this.x2min))    return(false);
+   //    if(GbSystem.greater(point.x1, this.x1max)) return(false);
+   //    if(GbSystem.greater(point.x2, this.x2max)) return(false);
+   //    if(this.containsEqual(point) > 0)          return(true);
+
+   //    QbList    ltest    = new QbList(GbPoint2D.class, QbList.NOEQUALOBJECTS);
+   //    GbPoint2D points[] = this.getPoints();
+   //    GbPoint2D ptest;
+   //    int       n        = points.length;
+   //    if(n < 2) return(false);
+
+   //    if(GbSystem.equal(point.x2, this.x2min)) ptest = new GbPoint2D(point.x1, this.x2min-1.0);
+   //    else                                     ptest = new GbPoint2D(point.x1, this.x2max+1.0);
+
+   //    for(int i=1; i<n; i++)
+   //    {
+   //try { ltest.append(GbSystem.calculateIntersectionPoint2D(points[i-1], points[i], point, ptest)); }
+   //catch(Exception e){}
+   //    }
+   //    try { ltest.append(GbSystem.calculateIntersectionPoint2D(points[n-1], points[0], point, ptest)); }
+   //    catch(Exception e){}
+   //    return((ltest.size()%2)==1);
+   // }
+
+   /*
+   * Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+   * @param rectangle the 2D rectangle
+   * @return a new 2D polygon clipped by the specified 2D rectangle
+   */
+   // GbPolygon3D *createClippedPolygon3D(GbCuboid3D *cube)
+   // {
+   //return(GbSystem::clipPolygon3D(this->getPoints(), cube->p1->x1, cube->p1->x2, cube->p1->x3, , cube->p2->x1, cube->p2->x2, cube->p2->x3));
+   // };
+   /*
+   * Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+   * @param p1 the 1st point of the rectangle
+   * @param p2 the 2nd point of the rectangle
+   * @return a new 2D polygon clipped by the specified 2D rectangle
+   */
+   // GbPolygon3D *createClippedPolygon2D(GbPoint3D *p1, GbPoint3D *p2)
+   // {
+   //return(GbSystem::clipPolygon3D(this->getPoints(), p1->x1, p1->x2, p1->x3, p2->x1, p2->x2, p2->x3));
+   // };
+   /*
+   * Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+   * @param p1x1 the 1st x1 coordinate of the rectangle
+   * @param p1x2 the 1st x2 coordinate of the rectangle
+   * @param p2x1 the 2nd x1 coordinate of the rectangle
+   * @param p2x2 the 2nd x2 coordinate of the rectangle
+   * @return a new 2D polygon clipped by the specified 2D rectangle
+   */
+   // GbPolygon3D *createClippedPolygon3D(double p1x1, double p1x2, double p1x3, double p2x1, double p2x2, double p2x3)
+   // {
+   //return(GbSystem::clipPolygon3D(this.getPoints(), p1x1, p1x2, p1x3, p2x1, p2x2. p2x3));
+   // };
+
+   /*
+   * Returns true if the specified 2D rectangle lies completely within this 2D polygon.
+   * @param rectangle the 2D rectangle to check
+   * @return true if the specified 2D rectangle lies completely within this 2D polygon
+   */
+   //public boolean enclosesRectangle2D(GbRectangle2D rectangle)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+   //   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), rectangle.getArea()));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle lies completely within this 2D polygon.
+   * @param p1 the 1st point of the rectangle to check
+   * @param p2 the 2nd point of the rectangle to check
+   * @return true if the specified 2D rectangle lies completely within this 2D polygon
+   */
+   //public boolean enclosesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+   //   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle lies completely within this 2D polygon.
+   * @param p1x1 the 1st x1 coordinate of the rectangle to check
+   * @param p1x2 the 1st x2 coordinate of the rectangle to check
+   * @param p2x1 the 2nd x1 coordinate of the rectangle to check
+   * @param p2x2 the 2nd x2 coordinate of the rectangle to check
+   * @return true if the specified 2D rectangle lies completely within this 2D polygon
+   */
+   //public boolean enclosesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+   //   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+   //}
+
+   /*
+   * Returns true if the specified 2D rectangle is crossed by this 2D polygon.
+   * @param rectangle the 2D rectangle to check
+   * @return true if the specified 2D rectangle is crossed by this 2D polygon
+   */
+   //public boolean crossesRectangle2D(GbRectangle2D rectangle)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+   //   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, rectangle.getArea()));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle is crossed by this 2D polygon.
+   * @param p1 the 1st point of the rectangle to check
+   * @param p2 the 2nd point of the rectangle to check
+   * @return true if the specified 2D rectangle is crossed by this 2D polygon
+   */
+   //public boolean crossesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+   //   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle is crossed by this 2D polygon.
+   * @param p1x1 the 1st x1 coordinate of the rectangle to check
+   * @param p1x2 the 1st x2 coordinate of the rectangle to check
+   * @param p2x1 the 2nd x1 coordinate of the rectangle to check
+   * @param p2x2 the 2nd x2 coordinate of the rectangle to check
+   * @return true if the specified 2D rectangle is crossed by this 2D polygon
+   */
+   //public boolean crossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+   //   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+   //}
+
+   /*
+   * Returns true if the specified 2D rectangle lies (at least partly) within this 2D polygon.
+   * @param rectangle the 2D rectangle to check
+   * @return true if the specified 2D rectangle lies (at least partly) within this 2D polygon
+   */
+   //public boolean enclosesOrCrossesRectangle2D(GbRectangle2D rectangle)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+   //   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle lies (at least partly) within this 2D polygon.
+   * @param p1 the 1st point of the rectangle to check
+   * @param p2 the 2nd point of the rectangle to check
+   * @return true if the specified 2D rectangle lies (at least partly) within this 2D polygon
+   */
+   //public boolean enclosesOrCrossesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+   //   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle lies (at least partly) within this 2D polygon.
+   * @param p1x1 the 1st x1 coordinate of the rectangle to check
+   * @param p1x2 the 1st x2 coordinate of the rectangle to check
+   * @param p2x1 the 2nd x1 coordinate of the rectangle to check
+   * @param p2x2 the 2nd x2 coordinate of the rectangle to check
+   * @return true if the specified 2D rectangle lies (at least partly) within this 2D polygon
+   */
+   //public boolean enclosesOrCrossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+   //   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+   //}
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   /*  Private Methoden                                                    */
+   /*                                                                      */
+   void calculateValues();
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   // private class PointObserver implements TiObserver
+   // {
+   //    GbPolygon2D polygon = null;
+
+   //    PointObserver(GbPolygon2D polygon)
+   //    {
+   //this.polygon = polygon;
+   //    }
+
+   //    public void objectChanged(Object object)
+   //    {
+   //if((object instanceof GbPoint2D) && this.polygon.contains((GbPoint2D)object)>0)
+   //{
+   //   this.polygon.consistent = false;
+   //   this.polygon.notifyObservers();
+   //}
+   //    }
+   // }
+   /*======================================================================*/
+};
+/*=========================================================================*/
+#endif
+
+
+
+
+
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbQuadFaceMesh3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbQuadFaceMesh3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c6b8df7927fe730d7a1271cfec5b327c641d2173
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbQuadFaceMesh3D.cpp
@@ -0,0 +1,362 @@
+#include <numerics/geometry3d/GbQuadFaceMesh3D.h>
+#include <numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.h>
+
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+
+ 
+using namespace std;
+
+GbQuadFaceMesh3D::GbQuadFaceMesh3D() : GbObject3D()
+{
+   this->name             = "new GbMesh";
+   this->nodes            = new vector<Vertex>;           
+   this->quads            = new vector<QuadFace>;
+   this->consistent       = false;                                 
+}
+
+GbQuadFaceMesh3D::GbQuadFaceMesh3D(string name, vector<Vertex> *nodes, vector<QuadFace> *quads) : GbObject3D()
+{
+   if(name.size()==0 ) throw UbException(UB_EXARGS,"no name specified");
+   if(!nodes         ) throw UbException(UB_EXARGS,"no nodes specified");
+   if(!quads         ) throw UbException(UB_EXARGS,"no quads specified");
+                                                         
+   this->name             = name;
+   this->nodes            = nodes;           
+   this->quads            = quads;     
+   this->consistent       = false;                                 
+}
+/*=============================================================================================*/
+
+GbQuadFaceMesh3D::~GbQuadFaceMesh3D()
+{
+	if(nodes)
+	{
+	//	for(unsigned u=0; u<nodes->size(); u++) delete (*nodes)[u];
+      delete nodes;
+	}
+   if(quads)
+   {
+      delete quads;
+   }
+}
+/*======================================================================*/
+ObObjectCreator* GbQuadFaceMesh3D::getCreator()
+{
+   return GbQuadFaceMesh3DCreator::getInstance();
+}
+/*======================================================================*/
+
+void GbQuadFaceMesh3D::init()
+{
+   nodes      = NULL;
+   quads      = NULL;
+   x1min      = 0.0;
+   x1max      = 0.0;
+   x2min      = 0.0;
+   x2max      = 0.0;
+   x3min      = 0.0;
+   x3max      = 0.0;
+   consistent = false;
+}                                     
+   /**
+    * Returns a string representation of this triangular mesh.
+    * @return a string representation of this triangular mesh
+    */
+string GbQuadFaceMesh3D::toString()
+{
+	stringstream ss;
+	ss<<"GbQuadFaceMesh3D[";
+	ss<<(int)this->quads->size()<<"-Quadangles, "<<(int)this->nodes->size()<<"-Nodes, "<<endl;
+	//ss<<"\""<<this->name<<", Area=sollt mal berechnet werden ;-)"<<"\"";
+   //ss<<", x1min="<<this->x1min;
+   //ss<<", x1max="<<this->x1max;
+   //ss<<", x2min="<<this->x2min;
+   //ss<<", x2max="<<this->x2max;
+   //ss<<", x3min="<<this->x3min;
+   //ss<<", x3max="<<this->x3max;
+   ss<<"]";
+   return(ss.str());
+}
+/**
+ * Returns the name of this triangular mesh.
+ * @return the name of this triangular mesh
+ */
+string GbQuadFaceMesh3D::getName(){ return(this->name); }
+
+/**
+ * Returns the nodes of this triangular mesh.
+ * @return the nodes of this triangular mesh
+ */
+vector<GbQuadFaceMesh3D::Vertex>* GbQuadFaceMesh3D::getNodes()   {  return(this->nodes);   }
+/**
+ * Returns the quads of this triangular mesh.
+ * @return the quads of this triangular mesh
+ */
+vector<GbQuadFaceMesh3D::QuadFace>* GbQuadFaceMesh3D::getQuads()  { return(this->quads);  }
+/**
+ * Returns the center x1 coordinate of this triangular mesh.
+ * @return the center x1 coordinate of this triangular mesh
+ */
+double GbQuadFaceMesh3D::getX1Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(0.5*(this->x1min+this->x1max));
+}
+/**
+ * Returns the center x2 coordinate of this triangular mesh.
+ * @return the center x2 coordinate of this triangular mesh
+ */
+double GbQuadFaceMesh3D::getX2Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(0.5*(this->x2min+this->x2max));
+}
+/**
+* Returns the center x3 coordinate of this triangular mesh.
+	* @return the center x3 coordinate of this triangular mesh
+	*/
+double GbQuadFaceMesh3D::getX3Centroid()
+{
+	if(!this->consistent) this->calculateValues();
+	return(0.5*(this->x3min+this->x3max));
+}
+
+/**
+ * Returns the minimum x1 coordinate of this triangular mesh.
+ * @return the minimum x1 coordinate of this triangular mesh
+ */
+double GbQuadFaceMesh3D::getX1Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1min);
+}
+/**
+ * Returns the maximum x1 coordinate of this triangular mesh.
+ * @return the maximum x1 coordinate of this triangular mesh
+ */
+double GbQuadFaceMesh3D::getX1Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1max);
+}
+/**
+ * Returns the minimum x2 coordinate of this triangular mesh.
+ * @return the minimum x2 coordinate of this triangular mesh
+ */
+double GbQuadFaceMesh3D::getX2Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2min);
+}
+/**
+ * Returns the maximum x2 coordinate of this triangular mesh.
+ * @return the maximum x2 coordinate of this triangular mesh
+ */
+double GbQuadFaceMesh3D::getX2Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2max);
+}
+/**
+ * Returns the minimum x3 coordinate of this triangular mesh.
+ * @return the minimum x3 coordinate of this triangular mesh
+ */
+double GbQuadFaceMesh3D::getX3Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3min);
+}
+/**
+ * Returns the maximum x3 coordinate of this triangular mesh.
+ * @return the maximum x3 coordinate of this triangular mesh
+ */
+double GbQuadFaceMesh3D::getX3Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3max);
+}
+
+void GbQuadFaceMesh3D::calculateValues()
+{
+   double x1, x2, x3;
+
+	this->x1min = (*this->nodes)[0].x;
+   this->x1max = (*this->nodes)[0].x;
+   this->x2min = (*this->nodes)[0].y;
+   this->x2max = (*this->nodes)[0].y;
+   this->x3min = (*this->nodes)[0].z;
+   this->x3max = (*this->nodes)[0].z;
+
+   for(int i=1; i<(int)this->nodes->size(); i++)
+   {
+		x1 = (*this->nodes)[i].x;
+		x2 = (*this->nodes)[i].y;
+		x3 = (*this->nodes)[i].z;
+		if(x1 < this->x1min) this->x1min = x1;
+		if(x1 > this->x1max) this->x1max = x1;
+		if(x2 < this->x2min) this->x2min = x2;
+		if(x2 > this->x2max) this->x2max = x2;
+		if(x3 < this->x3min) this->x3min = x3;
+		if(x3 > this->x3max) this->x3max = x3;
+   }
+   this->consistent = true;
+}
+
+
+/*======================================================================*/
+vector<GbTriangle3D*> GbQuadFaceMesh3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles(0);
+   return triangles;
+	 //throw UbException(__FILE__, __LINE__, "GbQuadFaceMesh3D::getSurfaceTriangelSet - not implemented"); 
+}
+//vector<GbQuad3D*> GbQuadFaceMesh3D::getSurfaceQuadSet()
+//{
+//   throw UbException(__FILE__, __LINE__, "GbQuadFaceMesh3D::getSurfaceQuadSet - not implemented"); 
+//   //vector<GbQuadangle3D*> tris;
+//   //GbQuadangle3D* quad;
+//   //GbPoint3D* p1;
+//   //GbPoint3D* p2;
+//   //GbPoint3D* p3;
+//   //int size = (int)this->quads->size();
+//   //for(int u=0; u<size;u++)
+//   //{
+//   //   quad = (*this->quads)[u];
+//   //   p1 = new GbPoint3D(quad->getPoint1());
+//   //   p2 = new GbPoint3D(quad->getPoint2());
+//   //   p3 = new GbPoint3D(quad->getPoint3());
+//   //   tris.push_back(new GbQuadangle3D(p1, p2, p3));
+//   //}
+//   //return tris;
+//}
+/*======================================================================*/
+/*
+* Function to determine if the point is inside the polyhedron defined as a 3D object
+* using the Halfspace algorithm
+* @param xp the x-coordinate of the point
+* @param yp the y-coordinate of the point
+* @param zp the z-coordinate of the point
+* @return true if point is inside else return false
+*/
+bool GbQuadFaceMesh3D::isPointInObject3DHalfSpace(const double& xp, const double& yp, const double& zp)
+{ 
+   throw UbException(UB_EXARGS,"not implemented"); 
+   //vector<GbQuadangle3D*> *Quadangles = this->quads;
+   //int Quadanglesize = (int)Quadangles->size();
+   //GbPoint3D Point(xp,yp,zp);
+   //for (int i=0; i<Quadanglesize; i++)
+   //{
+   //   GbPoint3D* point1 = (*Quadangles)[i]->getPoint1();
+   //   GbPoint3D* point2 = (*Quadangles)[i]->getPoint2();
+   //   GbPoint3D* point3 = (*Quadangles)[i]->getPoint3();
+
+   //   GbHalfSpace3D halfspace(point1, point2, point3);
+   //   if (halfspace.ptInside(&Point)) return false;
+   //}
+   //return true;
+}
+/*======================================================================*/
+/*======================================================================*/
+bool GbQuadFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+{
+
+   double xmin=this->getX1Minimum();	double xmax=this->getX1Maximum();
+   double ymin=this->getX2Minimum();	double ymax=this->getX2Maximum();
+   double zmin=this->getX3Minimum();	double zmax=this->getX3Maximum();
+   double dX = (xmax-xmin)/100.;
+   double dY = (ymax-ymin)/100.;
+   double dZ = (zmax-zmin)/100.;
+   GbCuboid3D boundingCube(xmin-dX, ymin-dY, zmin-dZ, xmax+dX, ymax+dY, zmax+dZ);
+   if(!boundingCube.isPointInGbObject3D(x1, x2, x3)) 
+   {
+      boundingCube.finalize();
+      return false;
+   }
+   boundingCube.finalize();
+
+   // Halfspace algorithm, Area of spherical polygons algorithm or Ray crossing algorithm
+   GbVector3D bMin(boundingCube.getPoint1());
+   GbVector3D bMax(boundingCube.getPoint2());
+   bMin = bMax.Subtract(bMin);
+   //int radius = (int)bMin.Length();
+
+   //if(((GbQuadFaceMesh3D*)this->geoObject3D)->isPointInObject3DHalfSpace(x1,x2,x3) )
+   //if(((GbQuadFaceMesh3D*)this->geoObject3D)->isPointInObject3Darea(x11,x12,x13,numQuadangles))
+   //if(this->isPointInObject3DRayCrossing(x1,x2,x3,radius,(int)this->nodes->size(),(int)this->quads->size()))
+   //   return true;
+   //else 
+      return false;
+}
+/*======================================================================*/
+bool GbQuadFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+{
+    throw UbException(UB_EXARGS,"not implemented");
+}
+/*======================================================================*/
+GbLine3D* GbQuadFaceMesh3D::createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"not implemented");
+}
+
+/*======================================================================*/
+void GbQuadFaceMesh3D::writeAVSMesh(UbFileOutput *out, bool normals) 
+{
+   cout<<" - write_ucd ("<<out->getFileName()<<") -> ";
+   if(!out)
+   {
+      cout<<"GbQuadFaceMesh3D::writeAVSMesh() - File konnte nicht geschrieben werden: "<<endl;
+      return;
+   }
+   out->writeLine("# UCD-File created by GbQuadFaceMesh3D");
+
+   int quadsize = (int)this->quads->size();
+   int nodesize = (int)this->nodes->size();
+
+   out->writeInteger(nodesize);
+   out->writeInteger(quadsize);
+
+   out->writeInteger(0);
+   out->writeInteger(0);
+   out->writeInteger(0);
+   out->writeLine();
+   int nr=1;
+   Vertex node;
+   QuadFace face;
+   for(int i=0;i<nodesize; i++)
+   {
+    node = (*nodes)[i]; 
+    out->writeInteger(nr++);
+    out->writeDouble(node.x);
+    out->writeDouble(node.y);
+    out->writeDouble(node.z);
+    out->writeLine();
+   }
+
+   nr=1;
+   for(int i=0;i<quadsize; i++)
+   {
+      face = (*quads)[i]; 
+      out->writeInteger(nr++);
+      out->writeInteger(2);
+      out->writeString("quad");
+      out->writeInteger(face.vertex1+1);
+      out->writeInteger(face.vertex2+1);
+      out->writeInteger(face.vertex3+1);
+      out->writeInteger(face.vertex4+1);
+      out->writeLine();
+   }
+
+   //out->writeInteger(0);	out->writeInteger(1);	out->writeLine();
+   //out->writeInteger(1);	out->writeInteger(1);	out->writeLine();
+   //out->writeLine("TEST,no_unit");
+   //nr=1;
+   //for(int i=0;i<quadsize; i++)
+   //{
+   //	out->writeInteger(nr++);
+   //	out->writeInteger(10);
+   //	out->writeLine();
+   //}
+   cout<<"done\n";
+}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbQuadFaceMesh3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbQuadFaceMesh3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..43528dca68b8e4666612aa8f62ef60fefd1c90a8
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbQuadFaceMesh3D.h
@@ -0,0 +1,125 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBQUADFACEMESH3D_H
+#define GBQUADFACEMESH3D_H
+
+#include <sstream>
+#include <iostream>
+
+
+#include <numerics/geometry3d/GbObject3D.h>                
+#include <basics/utilities/UbException.h>  
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbQuadFaceMesh3D;
+typedef VFSharedPtr<GbQuadFaceMesh3D> GbQuadFaceMesh3DPtr;
+
+class UbFileOutput;
+class UbFileInput;
+/*=========================================================================*/
+/* GbQuadFaceMesh3D                                                                  */
+/*                                                                         */
+/**
+ * This Class provides the triangular meshes.
+ * Note, that up to now no methods for checking consistency are included.
+ * in this context this class describes facettes from an 3D-object !!!
+*/
+class GbQuadFaceMesh3D : public GbObject3D 
+{   
+public:
+  // nested class start
+   class Vertex
+   {
+   public:
+      Vertex(){}
+      Vertex(float x, float y, float z)
+      {
+         this->x=x;
+         this->y=y;
+         this->z=z;
+      }
+      float x, y, z;
+   };
+
+   class QuadFace
+   {
+   public:
+      QuadFace() {}
+      QuadFace(int v1, int v2, int v3, int v4)
+      {
+         this->vertex1=v1;
+         this->vertex2=v2;
+         this->vertex3=v3;
+         this->vertex4=v4;
+      }
+
+      int vertex1, vertex2, vertex3, vertex4;
+   };
+ // nested class end
+
+public:
+   GbQuadFaceMesh3D();
+	GbQuadFaceMesh3D(std::string name, std::vector<Vertex> *nodes, std::vector<QuadFace> *quads);
+	virtual ~GbQuadFaceMesh3D();   
+   GbQuadFaceMesh3D* clone() { throw UbException(UB_EXARGS,"clone() - not implemented"); }
+   void finalize()           { throw UbException(UB_EXARGS,"finalize() - not implemented");}
+
+   std::string toString();
+   std::string getName();
+   std::vector<Vertex>*  getNodes();
+   std::vector<QuadFace>* getQuads();
+   double getX1Centroid();
+   double getX2Centroid();
+   double getX3Centroid();
+   double getX1Minimum();
+   double getX1Maximum();
+   double getX2Minimum();
+   double getX2Maximum();
+   double getX3Minimum();
+   double getX3Maximum();
+   void calculateValues();
+
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary);
+
+   bool isPointInObject3DHalfSpace(const double& xp, const double& yp, const double& zp);    //based on Halfspace algorithm
+   //bool isPointInObject3DSpherical(const double& xp, const double& yp, const double& zp, int numQuads);    //based on Spherical polygon area method        
+   //bool isPointInObject3DRayCrossing(const double& xp, const double& yp, const double& zp, int radius, int numVertices, int numQuads);  //based on Ray tracing algorithm
+   
+   //char SegPlaneInt(GbQuad3D *quad, GbVector3D  &PointQ, GbVector3D &PointR, GbVector3D &Point, int *m);
+   //char SegQuadCross(GbQuad3D *quad, GbVector3D  &PointQ, GbVector3D &PointR);
+   //till here !!!
+
+   virtual GbLine3D* createClippedLine3D (GbPoint3D &point1,GbPoint3D &point2);
+   //virtual std::vector<GbQuad3D*> getSurfaceQuadSet();
+	virtual std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   virtual ObObjectCreator* getCreator();
+
+   virtual void write(UbFileOutput* out) { std::cout<<"GbQuadFaceMesh3D::write - sorry not implemented\n"; }
+   virtual void read(UbFileInput* in)    { std::cout<<"GbQuadFaceMesh3D::read  - sorry not implemented\n"; }
+
+   void writeAVSMesh(UbFileOutput *out, bool normals=false);
+
+   /*======================================================================*/
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+private:
+   void init();
+   /*======================================================================*/
+   std::string name;
+   std::vector<Vertex>   *nodes;
+   std::vector<QuadFace> *quads;
+   double      x1min;
+   double      x1max;
+   double      x2min;
+   double      x2max;
+   double      x3min;
+   double      x3max;
+   bool        consistent;
+};
+/*=========================================================================*/
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbSphere3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbSphere3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..064cc0cff91d812162489a34149a870e8fc23b75
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbSphere3D.cpp
@@ -0,0 +1,911 @@
+#include <numerics/geometry3d/GbSphere3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+#include <numerics/geometry3d/creator/GbSphere3DCreator.h>
+
+using namespace std;
+
+ObObjectCreator* GbSphere3D::getCreator()
+{
+   return GbSphere3DCreator::getInstance();
+}
+/*=====================================================*/
+GbSphere3D::GbSphere3D()
+  : GbObject3D(), UbObserver()
+{
+   this->setName("sphere");
+   radius=0;
+   midPoint=new GbPoint3D(0,0,0);
+}
+/*=====================================================*/
+GbSphere3D::GbSphere3D(const double& x1,const double& x2, const double& x3, const double& radius)
+  : GbObject3D(), UbObserver()
+{
+   this->setName("sphere");
+   midPoint = new GbPoint3D(x1,x2,x3);
+   midPoint->addObserver(this);
+
+   this->radius   = radius;
+   triangulationMode = RAYPROJECTION;
+   //triangulationMode = CUBOIDPROJECTION;
+}
+/*=====================================================*/
+GbSphere3D::GbSphere3D(const GbSphere3D& sphere)
+  : GbObject3D(), UbObserver()
+{
+   this->setName("sphere");
+
+   this->midPoint    = sphere.midPoint->clone();
+   this->radius      = sphere.radius;
+   triangulationMode = RAYPROJECTION;
+
+   this->midPoint->addObserver(this);
+}
+/*=====================================================*/
+GbSphere3D::GbSphere3D(GbSphere3D* sphere)
+   : GbObject3D(), UbObserver()
+{
+   this->setName(sphere->getName());
+   midPoint = sphere->midPoint->clone();
+   midPoint->addObserver(this);
+
+   this->radius   = sphere->getRadius();
+   triangulationMode = RAYPROJECTION;
+}
+/*=====================================================*/
+GbSphere3D::~GbSphere3D()
+{
+   if(this->midPoint) this->midPoint->removeObserver(this);
+}
+/*=====================================================*/
+void GbSphere3D::finalize()
+{
+   if(this->midPoint)
+   {
+      this->midPoint->removeObserver(this);
+      this->midPoint->finalize();
+      delete this->midPoint;
+      this->midPoint = NULL;
+   }
+
+   if(this->midPoint) this->midPoint->removeObserver(this);
+}
+/*=======================================================*/
+void GbSphere3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3)
+{
+   this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() );
+}
+/*=====================================================*/
+double GbSphere3D::getDistance(GbPoint3D* p)
+{
+   return this->getDistance(p->getX1Centroid(),p->getX2Coordinate(),p->getX3Coordinate());
+}
+/*=====================================================*/
+void GbSphere3D::setCenterX1Coordinate(const double& value)
+{
+   if(this->midPoint) this->midPoint->setX1(value);
+   else throw UbException(UB_EXARGS,"Sphere has no midPoint");
+   //kein notifyObserver(), da der knoten notifyObserver() ausfuehrt und die GbSphere dieses event
+   //abfaengt und dann selbst notifyObservers ausfuehrt ;-)
+}
+/*=====================================================*/
+void GbSphere3D::setCenterX2Coordinate(const double& value)
+{
+   if(this->midPoint) this->midPoint->setX2(value);
+   else  throw UbException(UB_EXARGS,"Sphere has no midPoint");
+   //kein notifyObserver(), da der knoten notifyObserver() ausfuehrt und die GbSphere dieses event
+   //abfaengt und dann selbst notifyObservers ausfuehrt ;-)
+}
+/*=====================================================*/
+void GbSphere3D::setCenterX3Coordinate(const double& value)
+{
+   if(this->midPoint) this->midPoint->setX3(value);
+   else  throw UbException(UB_EXARGS,"sphere has no midPoint");
+   //kein notifyObserver(), da der knoten notifyObserver() ausfuehrt und die GbSphere dieses event
+   //abfaengt und dann selbst notifyObservers ausfuehrt ;-)
+}
+/*=====================================================*/
+void GbSphere3D::setRadius(const double& radius)
+{
+   if (radius != this->radius)
+   {
+   this->radius=radius;
+   this->notifyObserversObjectChanged();
+}
+}
+/*=====================================================*/
+double GbSphere3D::getDistance(const double& x1p, const double& x2p, const double& x3p)
+{
+   double deltaX1 = x1p - midPoint->getX1Coordinate();
+   double deltaX2 = x2p - midPoint->getX2Coordinate();
+   double deltaX3 = x3p - midPoint->getX3Coordinate();
+   return sqrt(deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3)-this->radius;
+}
+/*=====================================================*/
+//true, wenn 'in Object' oder 'auf Boundary'!
+bool GbSphere3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   double deltaX1 = x1p - midPoint->getX1Coordinate();
+   double deltaX2 = x2p - midPoint->getX2Coordinate();
+   double deltaX3 = x3p - midPoint->getX3Coordinate();
+
+   return UbMath::lessEqual(deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3, this->radius*this->radius);
+}
+/*=====================================================*/
+//true, wenn 'in Object' oder 'auf Boundary'!
+bool GbSphere3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   double deltaX1 = x1p - midPoint->getX1Coordinate();
+   double deltaX2 = x2p - midPoint->getX2Coordinate();
+   double deltaX3 = x3p - midPoint->getX3Coordinate();
+
+   double distanceSquare = deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3;
+   double radiusSquare   = this->radius*this->radius;
+
+   pointIsOnBoundary = UbMath::equal(distanceSquare,radiusSquare);
+
+   return UbMath::lessEqual(distanceSquare,radiusSquare);
+}
+/*=====================================================*/
+//bool GbSphere3D::crossCellCrossSection(double x11,double x21,double x12,double x22, double ra)
+//{
+//   if(this->isPointInCrossection(x11, x12) || this->isPointInCrossection(x21, x22) || this->isPointInCrossection(x11, x22) || this->isPointInCrossection(x21, x12))
+//   {
+//		if(!this->isPointInCrossection(x11, x12) || !this->isPointInCrossection(x21, x22) || !this->isPointInCrossection(x11, x22) || !this->isPointInCrossection(x21, x12)) return true;
+//   }
+//   return false;
+//}
+//
+///*=====================================================*/
+//bool GbSphere3D::cellCrossAndInsideCrossSection(double x11,double x21,double x12,double x22, double ra)
+//{
+//   if(this->isPointInCrossection(x11, x12) || this->isPointInCrossection(x21, x22) || this->isPointInCrossection(x11, x22) || this->isPointInCrossection(x21, x12))  return true;
+//   return false;
+//}
+/*=====================================================*/
+string GbSphere3D::toString()
+{
+	stringstream ss;
+	ss<< "GbSphere3D[";
+	ss <<"mid="<<midPoint->toString()<<", r="<<radius<<"]";
+	return ss.str();
+}
+/*=====================================================*/
+GbLine3D* GbSphere3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   double factor = 100.0; //um rundungsfehler beim wurzelterm zu minimieren
+   double xa = factor*point1.getX1Coordinate();
+   double ya = factor*point1.getX2Coordinate();
+   double za = factor*point1.getX3Coordinate();
+   double xb = factor*point2.getX1Coordinate();
+   double yb = factor*point2.getX2Coordinate();
+   double zb = factor*point2.getX3Coordinate();
+   double xm = factor*this->midPoint->getX1Coordinate();
+   double ym = factor*this->midPoint->getX2Coordinate();
+   double zm = factor*this->midPoint->getX3Coordinate();
+   double r  = factor*this->radius;
+
+   double xa2 = xa*xa;
+   double ya2 = ya*ya;
+   double za2 = za*za;
+   double xb2 = xb*xb;
+   double yb2 = yb*yb;
+   double zb2 = zb*zb;
+   double xm2 = xm*xm;
+   double ym2 = ym*ym;
+   double zm2 = zm*zm;
+   double r2  = r*r;
+
+   double wurzel =   2.0*xa*xb*ym2-2.0*ya*yb*r2+2.0*ya*ym*xb2+2.0*yb*ym*za2
+                    +2.0*ya*ym*zb2+2.0*xb*xm*za2+2.0*za*zb*ym2+2.0*xb*xm*ya2+2.0*xa*xm*yb2
+                    +2.0*yb*ym*xa2+2.0*zb*zm*ya2+2.0*xa*xm*zb2+2.0*za*zm*xb2+2.0*za*zm*yb2
+                    +2.0*xa*xb*zm2-2.0*xa*xb*r2-2.0*za*zb*r2+2.0*za*zb*xm2-2.0*ya*yb*xa*xm
+                    +2.0*ya*yb*xa*xb+2.0*zb*zm*xa2-2.0*ya*yb*xb*xm+2.0*ya*yb*xm2-2.0*ya*yb*zb*zm
+                    +2.0*ya*yb*zm2+2.0*zb*zm*yb*ym-2.0*zb*zm*ya*ym+2.0*zb*zm*xb*xm-2.0*xa*xm*yb*ym
+                    +2.0*xa*xm*za*zm+2.0*xa*xm*ya*ym-2.0*yb*ym*za*zm+2.0*yb*ym*xb*xm+2.0*za*zm*ya*ym
+                    -2.0*za*zm*xb*xm-2.0*ya*ym*xb*xm+2.0*za*zb*xa*xb-2.0*za*zb*xa*xm-2.0*za*zb*xb*xm
+                    +2.0*za*zb*ya*yb-2.0*za*zb*ya*ym-2.0*za*zb*yb*ym-2.0*ya*yb*za*zm-xa2*zb2
+                    -xa2*yb2-zb2*ya2-za2*xb2-za2*yb2-xb2*ya2-2.0*zb*zm*xa*xm
+                    -2.0*xa*xb*za*zm-2.0*xa*xb*zb*zm-2.0*xa*xb*ya*ym-2.0*xa*xb*yb*ym+za2*r2
+                    -za2*xm2-za2*ym2+zb2*r2-zb2*xm2-zb2*ym2+xa2*r2-xa2*zm2
+                    -xa2*ym2+xb2*r2-xb2*zm2-xb2*ym2+ya2*r2-ya2*zm2-ya2*xm2
+                    +yb2*r2-yb2*zm2-yb2*xm2;
+   double nenner  = -2.0*za*zb-2.0*ya*yb-2.0*xa*xb+za2+zb2+xa2+xb2+ya2+yb2;
+   double zaehler =  2.0*zb*zm-2.0*xa*xm+2.0*yb*ym-2.0*za*zm+xa2-2.0*ya*ym
+                    +2.0*xb*xm-zb2+za2-xb2+ya2-yb2;
+
+   vector<GbPoint3D*> schnittpunkte;
+
+   if(fabs(nenner)>1.E-13 && UbMath::greaterEqual(wurzel,0.0))
+   {
+      double t1 = (zaehler+2.0*sqrt(wurzel))/nenner;
+      double t2 = (zaehler-2.0*sqrt(wurzel))/nenner;
+
+      if(UbMath::inClosedInterval(t1,-1.0,1.0))
+      {
+         double x = ( xa*(0.5-0.5*t1)+xb*(0.5+0.5*t1) )/factor;
+         double y = ( ya*(0.5-0.5*t1)+yb*(0.5+0.5*t1) )/factor;
+         double z = ( za*(0.5-0.5*t1)+zb*(0.5+0.5*t1) )/factor;
+
+         schnittpunkte.push_back(new GbPoint3D(x,y,z));
+      }
+      if(fabs(t2-t1)>1.E-13 && UbMath::inClosedInterval(t2,-1.0,1.0))
+      {
+         double x = ( xa*(0.5-0.5*t2)+xb*(0.5+0.5*t2) )/factor;
+         double y = ( ya*(0.5-0.5*t2)+yb*(0.5+0.5*t2) )/factor;
+         double z = ( za*(0.5-0.5*t2)+zb*(0.5+0.5*t2) )/factor;
+
+         schnittpunkte.push_back(new GbPoint3D(x,y,z));
+      }
+   }
+
+   int nofSchnittpunkte = (int)schnittpunkte.size();
+   if(nofSchnittpunkte==1)
+   {
+      if     (this->isPointInGbObject3D(&point1)) return new GbLine3D(schnittpunkte[0],new GbPoint3D(point1));
+      else if(this->isPointInGbObject3D(&point2)) return new GbLine3D(schnittpunkte[0],new GbPoint3D(point2));
+      else //line beruehrt kugel! -> clippedLine reduziert sich zu einem Punkt!
+      {
+         if(std::fabs(this->getDistance(schnittpunkte[0])-this->radius)<1.E-13)
+            throw UbException(UB_EXARGS,"Beide LinenPunkte ausserhalb des Kreises, der berechnete Punkt ist jedoch KEIN Beruhrungspunkt der Sphere...");
+         return new GbLine3D(schnittpunkte[0],new GbPoint3D(*(schnittpunkte[0])));
+      }
+   }
+   else if(nofSchnittpunkte==2) return new GbLine3D(schnittpunkte[0],schnittpunkte[1]);
+
+   return NULL;
+}
+/*=========================================================================*/
+vector<GbTriangle3D*> GbSphere3D::getSurfaceTriangleSet()
+{
+   if(triangulationMode==RAYPROJECTION)
+   {
+      double x1m = midPoint->getX1Coordinate();
+      double x2m = midPoint->getX2Coordinate();
+      double x3m = midPoint->getX3Coordinate();
+
+      vector<GbTriangle3D*> triangles;
+
+      int segments =30;
+      double deltaPhi = UbMath::PI/(double)segments;
+      double phiX1a,phiX1b,phiX3a,phiX3b;
+      double x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+
+      for(phiX3a=0.5*UbMath::PI; phiX3a>-1.5*UbMath::PI; phiX3a-=deltaPhi)
+      {
+         for(phiX1a=0.0; phiX1a<UbMath::PI; phiX1a+=deltaPhi)
+         {
+            phiX1b = phiX1a+deltaPhi;
+            phiX3b = phiX3a+deltaPhi;
+
+            x1a =  x1m+radius*cos(phiX3a)*std::cos(phiX1a);
+            x2a =  x2m+radius*cos(phiX3a)*std::sin(phiX1a);
+            x3a =  x3m+radius*sin(phiX3a);
+            x1b =  x1m+radius*cos(phiX3a)*std::cos(phiX1b);
+            x2b =  x2m+radius*cos(phiX3a)*std::sin(phiX1b);
+            x3b =  x3m+radius*sin(phiX3a);
+            x1c =  x1m+radius*cos(phiX3b)*std::cos(phiX1b);
+            x2c =  x2m+radius*cos(phiX3b)*std::sin(phiX1b);
+            x3c =  x3m+radius*sin(phiX3b);
+            x1d =  x1m+radius*cos(phiX3b)*std::cos(phiX1a);
+            x2d =  x2m+radius*cos(phiX3b)*std::sin(phiX1a);
+            x3d =  x3m+radius*sin(phiX3b);
+
+            if(UbMath::greater(phiX3b,-0.5*UbMath::PI)  && UbMath::less(phiX3a,0.5*UbMath::PI))
+            {
+               triangles.push_back(new GbTriangle3D(new GbPoint3D(x1a,x2a,x3a),new GbPoint3D(x1b,x2b,x3b),new GbPoint3D(x1c,x2c,x3c)));
+               triangles.push_back(new GbTriangle3D(new GbPoint3D(x1a,x2a,x3a),new GbPoint3D(x1c,x2c,x3c),new GbPoint3D(x1d,x2d,x3d)));
+            }
+            else
+            {
+               triangles.push_back(new GbTriangle3D(new GbPoint3D(x1d,x2d,x3d),new GbPoint3D(x1c,x2c,x3c),new GbPoint3D(x1a,x2a,x3a)));
+               triangles.push_back(new GbTriangle3D(new GbPoint3D(x1c,x2c,x3c),new GbPoint3D(x1b,x2b,x3b),new GbPoint3D(x1a,x2a,x3a)));
+            }
+         }
+      }
+      return triangles;
+   }
+   else if(triangulationMode==CUBOIDPROJECTION)
+   {
+      vector<GbTriangle3D*> triangles;
+      vector<GbPoint3D*>   points;
+      double x1min = this->getX1Minimum();
+      double x2min = this->getX2Minimum();
+      double x3min = this->getX3Minimum();
+      double x1max = this->getX1Maximum();
+      double x2max = this->getX2Maximum();
+      double x3max = this->getX3Maximum();
+      double ax1 = x1min;    double bx2 = x2min;   double cx1 = x1min;
+      double ax2 = x2min;    double bx3 = x3min;   double cx3 = x3min;
+
+      int anzahl = 20;
+      double dx1 = (x1max-x1min)/(double)(anzahl-1);
+      double dx2 = (x2max-x2min)/(double)(anzahl-1);
+      double dx3 = (x3max-x3min)/(double)(anzahl-1);
+
+      for (int u=0; u<anzahl; u++)
+      {
+         ax2 = x2min;
+         bx2 = x2min;
+         cx3 = x3min;
+         for (int v=0; v<anzahl; v++)
+         {
+            GbPoint3D p1 = GbPoint3D(ax1, ax2, x3max);
+            GbPoint3D p2 = GbPoint3D(ax1, ax2, x3min);
+            GbPoint3D p3 = GbPoint3D(cx1, x2min, cx3);
+            GbPoint3D p4 = GbPoint3D(cx1, x2max, cx3);
+            GbPoint3D p5 = GbPoint3D(x1min, bx2, bx3);
+            GbPoint3D p6 = GbPoint3D(x1max, bx2, bx3);
+
+            GbLine3D* clippedline1 = this->createClippedLine3D(*this->midPoint, p1);
+            GbLine3D* clippedline2 = this->createClippedLine3D(*this->midPoint, p2);
+            GbLine3D* clippedline3 = this->createClippedLine3D(*this->midPoint, p3);
+            GbLine3D* clippedline4 = this->createClippedLine3D(*this->midPoint, p4);
+            GbLine3D* clippedline5 = this->createClippedLine3D(*this->midPoint, p5);
+            GbLine3D* clippedline6 = this->createClippedLine3D(*this->midPoint, p6);
+            points.push_back(new GbPoint3D(clippedline1->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline2->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline3->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline4->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline5->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline6->getPoint1()));
+            clippedline1->deletePoints();    delete clippedline1;
+            clippedline2->deletePoints();    delete clippedline2;
+            clippedline3->deletePoints();    delete clippedline3;
+            clippedline4->deletePoints();    delete clippedline4;
+            clippedline5->deletePoints();    delete clippedline5;
+            clippedline6->deletePoints();    delete clippedline6;
+            ax2 +=dx2;
+            cx3 +=dx3;
+            bx2 +=dx2;
+         }
+         ax1 +=dx1;
+         cx1 +=dx1;
+         bx3 +=dx3;
+      }
+
+      int anz = anzahl*anzahl*6;
+      GbPoint3D* point1 = NULL;
+      GbPoint3D* point2 = NULL;
+      GbPoint3D* point3 = NULL;
+      int anzahl2 = anzahl*6;
+      int anzahl3 = anzahl2+6;
+      for (int u=0; u<anz-anzahl3; u++)
+      {
+         point1 = new GbPoint3D(points[u+6]);
+         point2 = new GbPoint3D(points[u]);
+         point3 = new GbPoint3D(points[u+anzahl2]);
+         if(u%2 == 0) triangles.push_back(new GbTriangle3D(point1, point2, point3));
+         else         triangles.push_back(new GbTriangle3D(point2, point1, point3));
+
+         point1 = new GbPoint3D(points[u+6]);
+         point2 = new GbPoint3D(points[u+anzahl2]);
+         point3 = new GbPoint3D(points[u+anzahl3]);
+         if(u%2 == 0) triangles.push_back(new GbTriangle3D(point1, point2, point3));
+         else         triangles.push_back(new GbTriangle3D(point2, point1, point3));
+      }
+      for (int u=0; u<anz; u++) delete points[u];
+
+      return triangles;
+   }
+   else throw UbException(UB_EXARGS,"undefined triangulationmode");
+}
+/*=======================================================*/
+void GbSphere3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+   //wenn ich viele Kugeln bei der PE rausschreibe sollten die vektoren nicht geresized werden
+   //nodes.resize(0);
+   //triangles.resize(0);
+
+   if(triangulationMode==RAYPROJECTION)
+   {
+      float x1m = (float)midPoint->getX1Coordinate();
+      float x2m = (float)midPoint->getX2Coordinate();
+      float x3m = (float)midPoint->getX3Coordinate();
+
+      int segments =30;
+      float deltaPhi = (float)UbMath::PI/(float)segments;
+      float phiX1a,phiX1b,phiX3a,phiX3b;
+      float x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+      int nodeNr = 0;
+      for(phiX3a=(float)(0.5*UbMath::PI); phiX3a > (float)(-1.5*UbMath::PI); phiX3a-=deltaPhi)
+      {
+         for(phiX1a=0.0; phiX1a<UbMath::PI; phiX1a+=deltaPhi)
+         {
+            phiX1b = phiX1a+deltaPhi;
+            phiX3b = phiX3a+deltaPhi;
+
+            x1a =  x1m+(float)(radius*cos(phiX3a)*std::cos(phiX1a));
+            x2a =  x2m+(float)(radius*cos(phiX3a)*std::sin(phiX1a));
+            x3a =  x3m+(float)(radius*sin(phiX3a));
+            x1b =  x1m+(float)(radius*cos(phiX3a)*std::cos(phiX1b));
+            x2b =  x2m+(float)(radius*cos(phiX3a)*std::sin(phiX1b));
+            x3b =  x3m+(float)(radius*sin(phiX3a));
+            x1c =  x1m+(float)(radius*cos(phiX3b)*std::cos(phiX1b));
+            x2c =  x2m+(float)(radius*cos(phiX3b)*std::sin(phiX1b));
+            x3c =  x3m+(float)(radius*sin(phiX3b));
+            x1d =  x1m+(float)(radius*cos(phiX3b)*std::cos(phiX1a));
+            x2d =  x2m+(float)(radius*cos(phiX3b)*std::sin(phiX1a));
+            x3d =  x3m+(float)(radius*sin(phiX3b));
+
+            if(UbMath::greater(phiX3b,-0.5*UbMath::PI) && UbMath::less(phiX3a,0.5*UbMath::PI))
+            {
+               nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+               nodes.push_back( makeUbTuple(x1b,x2b,x3b) );
+               nodes.push_back( makeUbTuple(x1c,x2c,x3c) );
+
+               nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+               nodes.push_back( makeUbTuple(x1c,x2c,x3c) );
+               nodes.push_back( makeUbTuple(x1d,x2d,x3d) );
+            }
+            else
+            {
+               nodes.push_back( makeUbTuple(x1d,x2d,x3d) );
+               nodes.push_back( makeUbTuple(x1c,x2c,x3c) );
+               nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+
+               nodes.push_back( makeUbTuple(x1c,x2c,x3c) );
+               nodes.push_back( makeUbTuple(x1b,x2b,x3b) );
+               nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+            }
+            triangles.push_back( makeUbTuple(nodeNr, nodeNr+1, nodeNr+2) );
+            triangles.push_back( makeUbTuple(nodeNr+3, nodeNr+4, nodeNr+5) );
+            nodeNr+=6;
+         }
+      }
+   }
+   else if(triangulationMode==CUBOIDPROJECTION)
+   {
+      vector<GbPoint3D*>   points;
+      double x1min = this->getX1Minimum();
+      double x2min = this->getX2Minimum();
+      double x3min = this->getX3Minimum();
+      double x1max = this->getX1Maximum();
+      double x2max = this->getX2Maximum();
+      double x3max = this->getX3Maximum();
+      double ax1 = x1min;    double bx2 = x2min;   double cx1 = x1min;
+      double ax2 = x2min;    double bx3 = x3min;   double cx3 = x3min;
+
+      int anzahl = 20;
+      double dx1 = (x1max-x1min)/(double)(anzahl-1);
+      double dx2 = (x2max-x2min)/(double)(anzahl-1);
+      double dx3 = (x3max-x3min)/(double)(anzahl-1);
+
+      for (int u=0; u<anzahl; u++)
+      {
+         ax2 = x2min;
+         bx2 = x2min;
+         cx3 = x3min;
+         for (int v=0; v<anzahl; v++)
+         {
+            GbPoint3D p1 = GbPoint3D(ax1, ax2, x3max);
+            GbPoint3D p2 = GbPoint3D(ax1, ax2, x3min);
+            GbPoint3D p3 = GbPoint3D(cx1, x2min, cx3);
+            GbPoint3D p4 = GbPoint3D(cx1, x2max, cx3);
+            GbPoint3D p5 = GbPoint3D(x1min, bx2, bx3);
+            GbPoint3D p6 = GbPoint3D(x1max, bx2, bx3);
+
+            GbLine3D* clippedline1 = this->createClippedLine3D(*this->midPoint, p1);
+            GbLine3D* clippedline2 = this->createClippedLine3D(*this->midPoint, p2);
+            GbLine3D* clippedline3 = this->createClippedLine3D(*this->midPoint, p3);
+            GbLine3D* clippedline4 = this->createClippedLine3D(*this->midPoint, p4);
+            GbLine3D* clippedline5 = this->createClippedLine3D(*this->midPoint, p5);
+            GbLine3D* clippedline6 = this->createClippedLine3D(*this->midPoint, p6);
+            points.push_back(new GbPoint3D(clippedline1->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline2->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline3->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline4->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline5->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline6->getPoint1()));
+            clippedline1->deletePoints();    delete clippedline1;
+            clippedline2->deletePoints();    delete clippedline2;
+            clippedline3->deletePoints();    delete clippedline3;
+            clippedline4->deletePoints();    delete clippedline4;
+            clippedline5->deletePoints();    delete clippedline5;
+            clippedline6->deletePoints();    delete clippedline6;
+            ax2 +=dx2;
+            cx3 +=dx3;
+            bx2 +=dx2;
+         }
+         ax1 +=dx1;
+         cx1 +=dx1;
+         bx3 +=dx3;
+      }
+
+      int anz = anzahl*anzahl*6;
+      int anzahl2 = anzahl*6;
+      int anzahl3 = anzahl2+6;
+      int nodeNr = 0;
+      for (int u=0; u<anz-anzahl3; u++)
+      {
+         nodes.push_back( makeUbTuple((float)points[u+6]->x1      , (float)points[u+6]->x2      , (float)points[u+6]->x3) );
+         nodes.push_back( makeUbTuple((float)points[u]->x1        , (float)points[u]->x2        , (float)points[u]->x3) );
+         nodes.push_back( makeUbTuple((float)points[u+anzahl2]->x1, (float)points[u+anzahl2]->x2, (float)points[u+anzahl2]->x3) );
+
+         if(u%2 == 0) triangles.push_back( makeUbTuple(nodeNr  , nodeNr+1, nodeNr+2) );
+         else         triangles.push_back( makeUbTuple(nodeNr  , nodeNr+1, nodeNr+2) );
+
+         nodes.push_back( makeUbTuple((float)points[u+6]->x1      , (float)points[u+6]->x2      , (float)points[u+6]->x3) );
+         nodes.push_back( makeUbTuple((float)points[u+anzahl2]->x1, (float)points[u+anzahl2]->x2, (float)points[u+anzahl2]->x3) );
+         nodes.push_back( makeUbTuple((float)points[u+anzahl3]->x1, (float)points[u+anzahl3]->x2, (float)points[u+anzahl3]->x3) );
+         if(u%2 == 0) triangles.push_back( makeUbTuple(nodeNr+3, nodeNr+4, nodeNr+5) );
+         else         triangles.push_back( makeUbTuple(nodeNr+3, nodeNr+4, nodeNr+5) );
+
+         nodeNr+=6;
+      }
+      for(int u=0; u<anz; u++) delete points[u];
+   }
+   else throw UbException(UB_EXARGS,"undefined triangulationmode");
+}
+/*=======================================================*/
+void GbSphere3D::transform(const double matrix[4][4])
+{
+   midPoint->transform(matrix);
+   this->setRadius(this->getRadius()*matrix[0][0]);
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbSphere3D::write(UbFileOutput* out)
+{
+   out->writeString(this->getCreator()->getTypeID());
+   midPoint->write(out);
+   out->writeDouble(radius);
+   out->writeInteger((int)triangulationMode);
+}
+/*=======================================================*/
+void GbSphere3D::read(UbFileInput* in)
+{
+   if(midPoint)
+   {
+      midPoint->removeObserver(this);
+      midPoint->finalize();
+      delete midPoint;
+   }
+   midPoint = new GbPoint3D;
+   in->readString();
+   midPoint->read(in);
+   midPoint->addObserver(this);
+   radius = in->readDouble();
+   triangulationMode = (TRIANGULATIONMODE)in->readInteger();
+}
+/*=======================================================*/
+bool GbSphere3D::hasIntersectionWithDirectedLine(GbPoint3D origin, GbPoint3D direction)
+{
+	GbVector3D vecOrigin(origin.getX1Coordinate(),origin.getX2Coordinate(), origin.getX3Coordinate()) ;
+	GbVector3D vecDirection(direction.getX1Coordinate(),direction.getX2Coordinate(), direction.getX3Coordinate());
+	GbVector3D vecSfereCenter(getX1Centroid(), getX2Centroid(), getX3Centroid());
+	GbVector3D diff = vecOrigin - vecSfereCenter;
+   float a = (float)(vecDirection.Dot(vecDirection));
+   float b = (float)(2.0 * vecDirection.Dot(diff));
+   float c = (float)(diff.Dot(diff) - this->getRadius()*this->getRadius());
+
+	// use 'abc'-formula for finding root t_1,2 = (-b +/- sqrt(b^2-4ac))/(2a)
+	float inRoot = (float)(b*b - 4.0*a*c);
+	if (inRoot < 0) return false;
+	float root = sqrt(inRoot);
+
+	float dist = (float)((-b - root)/(2.0*a));
+
+	double infinity = DBL_MAX;
+	double eps = 1E-4;
+
+   if (dist > infinity)
+		return false;
+
+	if (dist < eps)
+	{
+		dist = (float)((-b + root)/(2.0*a));
+		if (dist < eps || dist > infinity)
+			return false;
+	}
+	return true;
+}
+/*=======================================================*/
+bool GbSphere3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der SphereUmrandung
+//returns true:
+//  - cell cuts  sphere3D
+//  - cell boxes sphere3D
+//returns false:
+//  - cell completely inside sphere3D ( = sphere3D boxes cell)
+//  - cell und sphere3D haben kein gemeinsames Volumen
+{
+   double midX[] = {  this->getX1Centroid()
+                    , this->getX2Centroid()
+                    , this->getX3Centroid() };
+
+   double Bmin[] = {  UbMath::min(x1a, x1b)
+                    , UbMath::min(x2a, x2b)
+                    , UbMath::min(x3a, x3b) };
+
+   double Bmax[] = {  UbMath::max(x1a, x1b)
+                    , UbMath::max(x2a, x2b)
+                    , UbMath::max(x3a, x3b) };
+
+   /* Solid Box - Hollow Sphere */
+   double dmin = 0.0;
+   double dmax = 0.0;
+   double r2   = radius*radius;
+
+   for( int i=0; i<3; i++ )
+   {
+      double a = pow( midX[i] - Bmin[i], 2.0 );
+      double b = pow( midX[i] - Bmax[i], 2.0 );
+      dmax += UbMath::max( a, b );
+      if     ( UbMath::less   ( midX[i], Bmin[i] ) ) dmin += a;
+      else if( UbMath::greater( midX[i], Bmax[i] ) ) dmin += b;
+   }
+   if(   UbMath::lessEqual(dmin, r2   )
+      && UbMath::lessEqual(r2  , dmax ) )
+   {
+      return true;
+   }
+   return false;
+}
+/*=======================================================*/
+bool GbSphere3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//returns true:
+//  - cell completely inside sphere3D ( = sphere3D boxes cell)
+//  - cell cuts  sphere3D
+//  - cell boxes sphere3D
+//returns false:
+//  - cell und sphere3D haben kein gemeinsames Volumen
+{
+   //URL: http://tog.acm.org/GraphicsGems/gems/BoxSphere.c (mode=4, beides solids!!!)
+   // solid - solid
+   //this routine tests for intersection between an 3-dimensional
+   //axis-aligned box and an 3-dimensional sphere.
+
+   //true:
+   //  - wenn Schnitt
+   //  - Cell komplett innerhalb GbSphere3D
+   //  - Cell umhuellt GbSphere3D
+
+
+   double midX1 = this->getX1Centroid();
+   double midX2 = this->getX2Centroid();
+   double midX3 = this->getX3Centroid();
+
+   double dmin  = 0.0;
+
+   if     ( UbMath::less   ( midX1, x1a ) ) dmin += std::pow( midX1 - x1a, 2.0 );
+   else if( UbMath::greater( midX1, x1b ) ) dmin += std::pow( midX1 - x1b, 2.0 );
+
+   if     ( UbMath::less   ( midX2, x2a ) ) dmin += std::pow( midX2 - x2a, 2.0 );
+   else if( UbMath::greater( midX2, x2b ) ) dmin += std::pow( midX2 - x2b, 2.0 );
+
+   if     ( UbMath::less   ( midX3, x3a ) ) dmin += std::pow( midX3 - x3a, 2.0 );
+   else if( UbMath::greater( midX3, x3b ) ) dmin += std::pow( midX3 - x3b, 2.0 );
+
+   if( UbMath::lessEqual( dmin, radius*radius ) )
+   {
+      return true;
+   }
+
+   return false;
+}
+/*==========================================================*/
+double GbSphere3D::getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+	double deltaX1 = (x1b-x1a);
+	double deltaX2 = (x2b-x2a);
+	double deltaX3 = (x3b-x3a);
+	  
+	if( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )       return 1.0*deltaX1*deltaX2*deltaX3; 
+	if( !(this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)) )   return 0.0;
+
+	double tempResult = 0.0;
+
+	int iMax = 10;
+	int jMax = 10;
+	int kMax = 10;
+
+	for(         int i=0; i<iMax; i++){
+		for(     int j=0; j<jMax; j++){
+			for( int k=0; k<kMax; k++){
+				
+				tempResult += getCellVolumeInsideGbObject3DHelperFunction(
+					x1a+((double) i   )*deltaX1/((double)iMax), x2a+((double) j   )*deltaX2/((double)jMax), x3a+((double) k   )*deltaX3/((double)kMax),
+					x1a+((double)(i+1))*deltaX1/((double)iMax), x2a+((double)(j+1))*deltaX2/((double)jMax), x3a+((double)(k+1))*deltaX3/((double)kMax) );
+			}
+		}
+	}
+
+
+	double resultWithOneCell = getCellVolumeInsideGbObject3DHelperFunction( x1a, x2a, x3a, x1b, x2b, x3b );
+
+	//cout << tempResult << " vs. " << resultWithOneCell << endl;
+
+	return tempResult;
+
+}
+/*==========================================================*/
+double GbSphere3D::getCellVolumeInsideGbObject3DHelperFunction(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+
+	double deltaX1 = x1b-x1a;
+   double deltaX2 = x2b-x2a;
+   double deltaX3 = x3b-x3a;
+
+   if(   this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )     return 1.0*deltaX1*deltaX2*deltaX3;
+   if( !(this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)) )   return 0.0;
+
+   double alpha=0.0;
+   double internX1,internX2,internX3;
+
+   for(int x1vers=0;x1vers<2;x1vers++){
+      for(int x2vers=0;x2vers<2;x2vers++){
+         for(int x3vers=0;x3vers<2;x3vers++){
+            internX1 = x1a + (x1b-x1a)*x1vers;
+            internX2 = x2a + (x2b-x2a)*x2vers;
+            internX3 = x3a + (x3b-x3a)*x3vers;
+
+            if( UbMath::lessEqual(this->getDistance(internX1,internX2,internX3),alpha) )
+               alpha = this->getDistance(internX1,internX2,internX3);
+            //cout<<zelltyp<<" "<<kugel->getDistance(internX1,internX2,internX3)<<" "<<alpha<<endl;
+         }//end first for
+      }//end second for
+   }//end third for
+
+   alpha = (-1)*alpha;
+
+
+
+   double n[3];
+   n[0] = 0.5*(x1b+x1a) - this->getX1Centroid();
+   n[1] = 0.5*(x2b+x2a) - this->getX2Centroid();
+   n[2] = 0.5*(x3b+x3a) - this->getX3Centroid();
+
+   //cout << "Koordinaten:  "<<x1<<" "<<x2<<" "<<x3<<endl;
+   //cout << "Deltas:       "<<deltaX1<<" "<<deltaX2<<" "<<deltaX3<<endl;
+   //cout << "Halbe Zelle:  "<<halfcelldelta<<endl;
+
+   //cout<<"Centroid:  "<<kugel->getX1Centroid()<<" "<<kugel->getX2Centroid()<<" "<<kugel->getX3Centroid()<<endl;
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double normLength;
+   normLength = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
+   n[0] /= normLength;
+   n[1] /= normLength;
+   n[2] /= normLength;
+
+   if( UbMath::less(n[0],0.0) ) n[0] = -n[0];
+   if( UbMath::less(n[1],0.0) ) n[1] = -n[1];
+   if( UbMath::less(n[2],0.0) ) n[2] = -n[2];
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double dummy;
+   if( UbMath::greater(n[0],n[1])) {dummy=n[1]; n[1]=n[0]; n[0]=dummy;}
+   if( UbMath::greater(n[1],n[2])) {dummy=n[2]; n[2]=n[1]; n[1]=dummy;}
+   if( UbMath::greater(n[0],n[1])) {dummy=n[1]; n[1]=n[0]; n[0]=dummy;}
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double n1,n2,n3;
+   n1=n[0];
+   n2=n[1];
+   n3=n[2];
+
+	double maxVol =  deltaX1*deltaX2*deltaX3;
+
+	double result = 0.0, preresult = 0.0;
+
+   if( UbMath::lessEqual( maxVol, 0.000001 ) )
+      return 0.0;
+
+   // 1D Check
+   if ( UbMath::lessEqual(n1,0.001)&&UbMath::lessEqual(n2,0.001) )
+	{
+		result = alpha*deltaX1*deltaX2;
+   }
+   // 2D Check
+   else if ( UbMath::lessEqual(n1,0.001) )
+	{
+		preresult = (2*n2*n3);
+		result = (alpha*alpha)/preresult;
+		
+		if( UbMath::greater(alpha,n2*deltaX2) )
+		{
+			result += -(alpha-n2*deltaX2)*(alpha-n2*deltaX2)/preresult;
+		}
+		if( UbMath::greater(alpha,n3*deltaX3) )
+		{
+			result += -(alpha-n3*deltaX3)*(alpha-n3*deltaX3)/preresult;
+		}
+		if( UbMath::greater(alpha,n2*deltaX2+n3*deltaX3) )
+		{
+			result +=  (alpha-n2*deltaX2-n3*deltaX3)*(alpha-n2*deltaX2-n3*deltaX3)/preresult;
+		}
+
+		// tiefenrichtung mit einmultiplizieren...
+		result *= deltaX1;
+	}	
+   // 3D Check
+   else	
+	{ 	
+		preresult =6*n1*n2*n3;
+
+		result = alpha*alpha*alpha;
+
+		if ( UbMath::greaterEqual(alpha,n1*deltaX1))
+		{
+			result+=-((alpha-n1*deltaX1)*(alpha-n1*deltaX1)*(alpha-n1*deltaX1));
+		}
+		if (UbMath::greaterEqual(alpha,n2*deltaX2))
+		{
+			result+=-((alpha-n2*deltaX2)*(alpha-n2*deltaX2)*(alpha-n2*deltaX2));
+		}
+		if (UbMath::greaterEqual(alpha,n3*deltaX3))
+		{
+			result+=-((alpha-n3*deltaX3)*(alpha-n3*deltaX3)*(alpha-n3*deltaX3));
+		}
+		if (UbMath::greaterEqual(alpha,(n1*deltaX1+n2*deltaX2)))
+		{
+			result+=((alpha-(n1*deltaX1+n2*deltaX2))*(alpha-(n1*deltaX1+n2*deltaX2))*(alpha-(n1*deltaX1+n2*deltaX2)));
+		}
+		if (UbMath::greaterEqual(alpha,(n1*deltaX1+n3*deltaX3)))
+		{
+			result+=((alpha-(n1*deltaX1+n3*deltaX3))*(alpha-(n1*deltaX1+n3*deltaX3))*(alpha-(n1*deltaX1+n3*deltaX3)));
+		}
+		if (UbMath::greaterEqual(alpha,(n2*deltaX2+n3*deltaX3)))
+		{
+			result+=((alpha-(n2*deltaX2+n3*deltaX3))*(alpha-(n2*deltaX2+n3*deltaX3))*(alpha-(n2*deltaX2+n3*deltaX3)));
+		}
+
+		//NEW
+		if (UbMath::greaterEqual(alpha,(n1*deltaX1+n2*deltaX2+n3*deltaX3)))
+		{
+			result+= -((alpha-(n1*deltaX1+n2*deltaX2+n3*deltaX3))*(alpha-(n1*deltaX1+n2*deltaX2+n3*deltaX3))*(alpha-(n1*deltaX1+n2*deltaX2+n3*deltaX3)));
+		}
+
+		result = result / preresult;
+
+   }
+   return(result) ;
+
+   //cout << "alpha ist " << alpha << endl;
+   //cout << "fillLevel ist " << eps << endl;
+}
+/*==========================================================*/
+double GbSphere3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   double lx1  = midPoint->x1 - x1;
+   double lx2  = midPoint->x2 - x2;
+   double lx3  = midPoint->x3 - x3;
+   double l_sq = lx1*lx1 + lx2*lx2 + lx3*lx3;  //l = abstand Punkt(x1,x2,x3)<->kreismittelpunkt
+
+   double s    = lx1*rx1 + lx2*rx2 + lx3*rx3;  //s= l*ray_dir)
+   double r_sq = this->radius * this->radius;  // r² =r*r
+   //if (d<0 (fuer die Richtung falls sie gegen das Kreis dann haben wir ein negativer Zahl)
+   //     && l² > r² (point outside ))
+   //wenn s<0->Punkt liegt rechts vom mittelpunkt, wenn nun punkt ausserhalb des kreises liegt, kann es keinen SP mehr geben
+   if( s<-1.E-10 && l_sq>r_sq+1.E-10 )
+      return -1.0;
+   //Pythagor on Triangle Rectangle (point, center of the cercle, intersection of the direction on point and m)
+   // l² = m² + d²
+   double m_sq = l_sq - s*s;
+   // if (m² > r² (dann gibt es kein schnittpunt zwischen direction und circle))
+   if( m_sq > r_sq+1.E-10 )  return -1.0;
+   // Pythagoras on Triangle Rectangle in cercle (direction , m, r)
+   // r² = m² + h²
+
+   //patch: rundungsfehler bei kleinen delta!!!
+   //-> wenn wurzel minimal null->
+   double wurzelTerm = r_sq - m_sq;
+   if(wurzelTerm<0.0)
+   {
+      if(wurzelTerm<-1E-10) return -1.0; //definitiv kein SP
+      else                  return s;   //im rundungsfehler-bereich. SP liegt dierkt auf sphere umrandung
+   }
+
+   //if point outside of the circle
+   if(l_sq>r_sq) return s-sqrt(wurzelTerm);
+
+   return s+sqrt(wurzelTerm);
+}
+/*=======================================================*/
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbSphere3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbSphere3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9d4d86ea7fabe544e768f90e7ba2aefc2cabec6
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbSphere3D.h
@@ -0,0 +1,163 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBSPHERE3D_H
+#define GBSPHERE3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+#ifdef CAB_CTL
+   #include <ctl.h>
+#endif //CAB_CTL
+
+#include <vector>
+#include <cmath>
+
+#include <basics/utilities/UbObserver.h>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbSphere3D;
+typedef VFSharedPtr<GbSphere3D> GbSphere3DPtr;
+
+
+class GbLine3D;
+class GbTriangle3D;
+class GbObject3DCreator;
+
+class GbSphere3D : public GbObject3D, public UbObserver
+{                                              
+public:
+   enum TRIANGULATIONMODE { CUBOIDPROJECTION ,RAYPROJECTION };
+   
+   //////////////////////////////////////////////////////////////////////////
+   // Konstruktoren
+   GbSphere3D(); 
+   GbSphere3D(const double& x1,const double& x2, const double& x3, const double& radius);            
+   GbSphere3D(const GbSphere3D& sphere);            
+   GbSphere3D(GbSphere3D* sphere); //<-unschoen!
+   
+   ~GbSphere3D();
+
+   GbSphere3D* clone() { return new GbSphere3D(*this);}
+   void finalize();
+
+   double getRadius() const	{	return this->radius;	}
+
+   double getX1Centroid()  { return midPoint->getX1Coordinate();}
+   double getX1Minimum()   { return midPoint->getX1Coordinate()-radius;}
+   double getX1Maximum()   { return midPoint->getX1Coordinate()+radius;}
+   double getX2Centroid()  { return midPoint->getX2Coordinate();}
+   double getX2Minimum()   { return midPoint->getX2Coordinate()-radius;}
+   double getX2Maximum()   { return midPoint->getX2Coordinate()+radius;}
+   double getX3Centroid()  { return midPoint->getX3Coordinate();}
+   double getX3Minimum()   { return midPoint->getX3Coordinate()-radius;}
+   double getX3Maximum()   { return midPoint->getX3Coordinate()+radius;}
+
+   void setCenterX1Coordinate(const double& value);
+   void setCenterX2Coordinate(const double& value);
+   void setCenterX3Coordinate(const double& value);
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+   void setRadius(const double& radius);
+
+   GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+   double getDistance(GbPoint3D* p); 
+   double getDistance(const double& x1p, const double& x2p, const double& x3p);
+
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary);
+
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   double getCellVolumeInsideGbObject3DHelperFunction(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+   bool hasIntersectionWithDirectedLine(GbPoint3D origin, GbPoint3D direction);
+
+	std::string toString();
+
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);       
+
+   void translate(const double& x1, const double& x2, const double& x3) 
+   {
+      this->midPoint->translate(x1, x2, x3); 
+      this->notifyObserversObjectChanged();
+   }
+   void rotate(const double& rx1, const double& rx2, const double& rx3) {/* rotation makes no sense*/ }
+   void scale(const double& sx1, const double& sx2, const double& sx3) 
+   { 
+      this->radius *= sx1; 
+      this->notifyObserversObjectChanged();
+   }
+
+   void transform(const double matrix[4][4]);
+
+   TRIANGULATIONMODE getTriangulationMode() {return triangulationMode;}
+   void setTriangulationMode(TRIANGULATIONMODE mode) { this->triangulationMode = mode; }
+   
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject)
+   {
+      this->notifyObserversObjectChanged();
+      //std::cout<<"GbSphere:objectChanged() - toDo-);";
+   }
+   void objectWillBeDeleted(UbObservable* objectForDeletion)
+   {
+	   throw UbException(UB_EXARGS,"not implemented");
+   }
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere, weil man eine
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & midPoint;
+      ar & radius;
+      ar & triangulationMode;
+   }
+#endif //CAB_RCF
+#ifdef CAB_CTL
+   ctl::oStream &write(ctl::oStream &os) const
+   { 
+      midPoint->write(os);
+      return os<<radius; 
+   }
+   ctl::iStream &read(ctl::iStream &is) 
+   { 
+      midPoint->read(is);
+      return is>>radius;
+   }
+#endif //CAB_CTL
+
+private:
+   GbPoint3D* midPoint;
+   double radius;  // Radius des Kreises
+   TRIANGULATIONMODE triangulationMode;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   #if CAB_RCF <= 903 
+      SF_SERIALIZE_ENUM(GbSphere3D::TRIANGULATIONMODE) //bei klassen ausserhalb der klasse;-)
+   #endif
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbSphere3D>("GbSphere3D")             , SF_GbSphere3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbSphere3D >()), SF_GbSphere3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //GBSPHERE3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbSystem3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbSystem3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..529d3222c8b643631e6e33fe2499c5df873313e2
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbSystem3D.cpp
@@ -0,0 +1,1187 @@
+#include <numerics/geometry3d/GbSystem3D.h>
+
+#include <numerics/geometry3d/GbPolygon3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+
+using namespace std;
+
+double GbSystem3D::getDistance(const GbPoint3D& p11, const GbPoint3D& p12)
+{
+   double dx1 = p11.x1 - p12.x1;
+   double dx2 = p11.x2 - p12.x2;
+   double dx3 = p11.x3 - p12.x3;
+   return std::sqrt(dx1*dx1+dx2*dx2+dx3*dx3);
+}
+
+GbPoint3D* GbSystem3D::calculateIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22)
+{
+   if(UbMath::less2(p11.x1, p12.x1, p21.x1, p22.x1))    return NULL;
+   if(UbMath::less2(p11.x2, p12.x2, p21.x2, p22.x2))    return NULL;
+   if(UbMath::less2(p11.x3, p12.x3, p21.x3, p22.x3))    return NULL;
+   if(UbMath::greater2(p11.x1, p12.x1, p21.x1, p22.x1)) return NULL;
+   if(UbMath::greater2(p11.x2, p12.x2, p21.x2, p22.x2)) return NULL;
+   if(UbMath::greater2(p11.x3, p12.x3, p21.x3, p22.x3)) return NULL;
+
+   double a11 = p12.x1 - p11.x1;                       //..HOW PARAMETERS ARE USED.........
+   double a12 = p12.x2 - p11.x2;                       //
+   double a13 = p12.x3 - p11.x3;                       //  p11 and p12 represent line 1
+   double a21 = p21.x1 - p22.x1;                       //  p21 and p22 represent line 2
+   double a22 = p21.x2 - p22.x2;                       //
+   double a23 = p21.x3 - p22.x3;                       //..................................
+   double b1  = p21.x1 - p11.x1;
+   double b2  = p21.x2 - p11.x2;
+   double b3  = p21.x3 - p11.x3;
+   double d1  = a11*a22 - a12*a21;
+   double d2  = a11*a23 - a13*a21;
+   double d3  = a12*a23 - a13*a22;
+   double t;
+
+   if(UbMath::zero(d1) && UbMath::zero(d2) && UbMath::zero(d3)) return NULL;
+   if(UbMath::zero(d1))
+   {
+   	if(!UbMath::zero(d2)) t = (a23*b1-a21*b3)/d2;
+      else          t = (a23*b2-a22*b3)/d3;
+   }
+   else if(UbMath::zero(d2))
+   {
+   	if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1;
+      else          t = (a23*b2-a22*b3)/d3;
+   }
+   else if(UbMath::zero(d3))
+   {
+   	if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1;
+      else          t = (a23*b1-a21*b3)/d2;
+   }
+   else return NULL;
+
+   double x1 = p11.x1 + t*a11;
+   double x2 = p11.x2 + t*a12;
+   double x3 = p11.x3 + t*a13;
+
+   if(UbMath::inClosedInterval(x1, p11.x1, p12.x1) && UbMath::inClosedInterval(x1, p21.x1, p22.x1) &&
+      UbMath::inClosedInterval(x2, p11.x2, p12.x2) && UbMath::inClosedInterval(x2, p21.x2, p22.x2) &&
+      UbMath::inClosedInterval(x3, p11.x3, p12.x3) && UbMath::inClosedInterval(x3, p21.x3, p22.x3)    ) return new GbPoint3D(x1, x2, x3);
+
+   return NULL;
+}
+/*=================================================================*/
+//Line1: p11 -> p12 and Line2: p21 -> p22
+bool GbSystem3D::hasIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22)
+{
+   if(UbMath::less2(p11.x1, p12.x1, p21.x1, p22.x1))    return false; 
+   if(UbMath::less2(p11.x2, p12.x2, p21.x2, p22.x2))    return false; 
+   if(UbMath::less2(p11.x3, p12.x3, p21.x3, p22.x3))    return false; 
+   if(UbMath::greater2(p11.x1, p12.x1, p21.x1, p22.x1)) return false; 
+   if(UbMath::greater2(p11.x2, p12.x2, p21.x2, p22.x2)) return false; 
+   if(UbMath::greater2(p11.x3, p12.x3, p21.x3, p22.x3)) return false; 
+
+   double a11 = p12.x1 - p11.x1;                       //..HOW PARAMETERS ARE USED.........
+   double a12 = p12.x2 - p11.x2;                       //
+   double a13 = p12.x3 - p11.x3;                       //  p11 and p12 represent line 1
+   double a21 = p21.x1 - p22.x1;                       //  p21 and p22 represent line 2
+   double a22 = p21.x2 - p22.x2;                       //
+   double a23 = p21.x3 - p22.x3;                       //..................................
+   double b1  = p21.x1 - p11.x1;
+   double b2  = p21.x2 - p11.x2;
+   double b3  = p21.x3 - p11.x3;
+   double d1  = a11*a22 - a12*a21;
+   double d2  = a11*a23 - a13*a21;
+   double d3  = a12*a23 - a13*a22;
+   double t;
+
+   if(UbMath::zero(d1) && UbMath::zero(d2) && UbMath::zero(d3)) return false; 
+   if(UbMath::zero(d1))
+   {
+      if(!UbMath::zero(d2)) t = (a23*b1-a21*b3)/d2;
+      else          t = (a23*b2-a22*b3)/d3;
+   }
+   else if(UbMath::zero(d2))
+   {
+      if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1;
+	   else          t = (a23*b2-a22*b3)/d3;
+   }
+   else if(UbMath::zero(d3))
+   {
+      if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1;
+      else          t = (a23*b1-a21*b3)/d2;
+   }
+   else return false; 
+
+   double x1 = p11.x1 + t*a11;
+   double x2 = p11.x2 + t*a12;
+   double x3 = p11.x3 + t*a13;
+
+   if(UbMath::inClosedInterval(x1, p11.x1, p12.x1) && UbMath::inClosedInterval(x1, p21.x1, p22.x1) &&
+	   UbMath::inClosedInterval(x2, p11.x2, p12.x2) && UbMath::inClosedInterval(x2, p21.x2, p22.x2) &&
+	   UbMath::inClosedInterval(x3, p11.x3, p12.x3) && UbMath::inClosedInterval(x3, p21.x3, p22.x3)) return true; 
+   return false; 
+}
+ /*======================================================================*/
+//
+//
+//   /*======================================================================*/
+//   /*  Private Methoden (Parallelism)                                      */
+//   /*                                                                      */
+bool GbSystem3D::isParallelIn3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22)
+{
+   double a11 = p12.x1 - p11.x1;                       //..HOW PARAMETERS ARE USED.........
+   double a12 = p12.x2 - p11.x2;                       //
+   double a13 = p12.x3 - p11.x3;                       //  p11 and p12 represent line 1
+   double a21 = p21.x1 - p22.x1;                       //  p21 and p22 represent line 2
+   double a22 = p21.x2 - p22.x2;                       //
+   double a23 = p21.x3 - p22.x3;                       //..................................
+
+   return (UbMath::zero(a11*a22 - a12*a21) && UbMath::zero(a11*a23 - a13*a21) && UbMath::zero(a12*a23 - a13*a22));
+}
+/*======================================================================*/
+
+
+/*======================================================================*/
+/*  General Clipping Methods                                            */
+//......................................................................*/
+//
+//  Method       Parameters                                       Result      Remarks
+//  ---------    ---------------------------------------------    ---------   -------------------
+//  clip###2D   (2D objects to be clipped, 2+2 clipping values)   2D object   clipping x1, x2
+//  clip###3D   (3D objects to be clipped, 2+2 clipping values)   3D object   clipping x1, x2
+//  clip###3D   (3D objects to be clipped, 3+3 clipping values)   3D object   clipping x1, x2, x3
+//  clip###3D   (3D objects to be clipped, 1+1 clipping values)   3D object   clipping x3
+//
+/*======================================================================*/
+/*  Private Methoden (Clipping Lines)                                   */
+/*                                                                      */
+GbLine3D* GbSystem3D::createClipLine3D(GbPoint3D &pA, GbPoint3D &pB, double x1a, double x2a, double x3a, double x1b, double x2b, double x3b)
+{
+   GbPoint3D *p1 = new GbPoint3D(pA);
+   GbPoint3D *p2 = new GbPoint3D(pB);
+
+   if(UbMath::greater(x1a, x1b)) { double x1 = x1a; x1a = x1b; x1b = x1; }
+   if(UbMath::greater(x2a, x2b)) { double x2 = x2a; x2a = x2b; x2b = x2; }
+   if(UbMath::greater(x3a, x3b)) { double x3 = x3a; x3a = x3b; x3b = x3; }
+
+   double f;
+
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an vorderer Kante                                      */
+   /*                                                                   */
+   if(UbMath::less(p1->x3, x3a))
+   {
+      if(UbMath::less(p2->x3, x3a)) { delete p1; delete p2; return NULL; }
+
+      f       = (x3a-p1->x3)/(p1->x3-p2->x3);
+      p1->x1 += (p1->x1-p2->x1)*f;
+      p1->x2 += (p1->x2-p2->x2)*f;
+      p1->x3  = x3a;
+   }
+   else if(UbMath::less(p2->x3, x3a))
+   {
+      f      = (x3a-p2->x3)/(p2->x3-p1->x3);
+      p2->x1 += (p2->x1-p1->x1)*f;
+      p2->x2 += (p2->x2-p1->x2)*f;
+      p2->x3  = x3a;
+   }     
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an unterer Kante                                       */
+   /*                                                                   */
+   if(UbMath::less(p1->x2, x2a))
+   {
+      if(UbMath::less(p2->x2, x2a)) { delete p1; delete p2; return NULL;
+      }
+
+      f      = (x2a-p1->x2)/(p1->x2-p2->x2);
+      p1->x1 += (p1->x1-p2->x1)*f;
+      p1->x3 += (p1->x3-p2->x3)*f;
+      p1->x2  = x2a;
+   }
+   else if(UbMath::less(p2->x2, x2a))
+   {
+      f      = (x2a-p2->x2)/(p2->x2-p1->x2);
+      p2->x1 += (p2->x1-p1->x1)*f;
+      p2->x3 += (p2->x3-p1->x3)*f;
+      p2->x2  = x2a;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an rechter Kante                                       */
+   /*                                                                   */
+   if(UbMath::greater(p1->x1, x1b))
+   {
+      if(UbMath::greater(p2->x1, x1b))  { delete p1;delete p2; return NULL;}
+
+      f      = (x1b-p1->x1)/(p1->x1-p2->x1);
+      p1->x2 += (p1->x2-p2->x2)*f;
+      p1->x3 += (p1->x3-p2->x3)*f;
+      p1->x1  = x1b;
+   }
+   else if(UbMath::greater(p2->x1, x1b))
+   {
+      f      = (x1b-p2->x1)/(p2->x1-p1->x1);
+      p2->x2 += (p2->x2-p1->x2)*f;
+      p2->x3 += (p2->x3-p1->x3)*f;
+      p2->x1  = x1b;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an hinterer Kante                                      */
+   /*                                                                   */
+   if(UbMath::greater(p1->x3, x3b))
+   {
+      if(UbMath::greater(p2->x3, x3b))  { delete p1;delete p2; return NULL;}
+
+      f      = (x3b-p1->x3)/(p1->x3-p2->x3);
+      p1->x1 += (p1->x1-p2->x1)*f;
+      p1->x2 += (p1->x2-p2->x2)*f;
+      p1->x3  = x3b;
+   }
+   else if(UbMath::greater(p2->x3, x3b))
+   {
+      f      = (x3b-p2->x3)/(p2->x3-p1->x3);
+      p2->x1 += (p2->x1-p1->x1)*f;
+      p2->x2 += (p2->x2-p1->x2)*f;
+      p2->x3  = x3b;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an oberer Kante                                        */
+   /*                                                                   */
+   if(UbMath::greater(p1->x2, x2b))
+   {
+      if(UbMath::greater(p2->x2, x2b))  { delete p1;delete p2; return NULL;}
+
+      f      = (x2b-p1->x2)/(p1->x2-p2->x2);
+      p1->x1 += (p1->x1-p2->x1)*f;
+      p1->x3 += (p1->x3-p2->x3)*f;
+      p1->x2  = x2b;
+   }
+   else if(UbMath::greater(p2->x2, x2b))
+   {
+      f      = (x2b-p2->x2)/(p2->x2-p1->x2);
+      p2->x1 += (p2->x1-p1->x1)*f;
+      p2->x3 += (p2->x3-p1->x3)*f;
+      p2->x2  = x2b;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an linker Kante                                        */
+   /*                                                                   */
+   if(UbMath::less(p1->x1, x1a))
+   {
+      if(UbMath::less(p2->x1, x1a))  { delete p1;delete p2; return NULL;}
+
+      f      = (x1a-p1->x1)/(p1->x1-p2->x1);
+      p1->x2 += (p1->x2-p2->x2)*f;
+      p1->x3 += (p1->x3-p2->x3)*f;
+      p1->x1  = x1a;
+   }
+   else if(UbMath::less(p2->x1, x1a))
+   {
+      f      = (x1a-p2->x1)/(p2->x1-p1->x1);
+      p2->x2 += (p2->x2-p1->x2)*f;
+      p2->x3 += (p2->x3-p1->x3)*f;
+      p2->x1  = x1a;
+   }
+   /*-------------------------------------------------------------------*/
+   return new GbLine3D(p1, p2);
+}
+//   /*======================================================================*/
+//   /*  Private Methoden (Clipping Rectangles)                              */
+//   /*                                                                      */
+//   final static GbPolygon3D clipPolygon3D(GbPoint3D points[], double x11, double x12, double x21, double x22)
+//   {
+//      GbPoint3D last = null;
+//      PointSet3 ps   = new PointSet3(points);
+//      boolean   flag = false;
+//      int       n    = points.length;
+//      int       i;
+//      double    f;
+//
+//      if(n == 0)              return(null);
+//      if(greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; }
+//      if(greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; }
+//
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an unterer Kante                                       */
+//      /*                                                                   */
+//      if(less(ps.getX2Minimum(), x12))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(less((*points)[0]->x2, x12)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(less((*points)[i]->x2, x12))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x12-(*points)[i]->x2)/((*points)[i]->x2-last->x2);
+//	          ps.add(new GbPoint3D((*points)[i]->x1 + ((*points)[i]->x1-last->x1)*f, x12, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x12-(*points)[i]->x2)/((*points)[i]->x2-last->x2);
+//	          ps.add(new GbPoint3D((*points)[i]->x1 + ((*points)[i]->x1-last->x1)*f, x12, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f));
+//	       }
+//	       ps.add((*points)[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((less(points[0].x2, x12)) ^ flag))
+//	 {
+//	    f = (x12-points[0].x2)/(points[0].x2-last->x2);
+//	    ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last->x1)*f, x12, points[0].x3 + (points[0].x3-last->x3)*f));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an rechter Kante                                       */
+//      /*                                                                   */
+//      if(greater(ps.getX1Maximum(), x21))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(greater(points[0].x1, x21)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(greater((*points)[i]->x1, x21))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x21-(*points)[i]->x1)/((*points)[i]->x1-last->x1);
+//	          ps.add(new GbPoint3D(x21, (*points)[i]->x2 + ((*points)[i]->x2-last->x2)*f, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x21-(*points)[i]->x1)/((*points)[i]->x1-last->x1);
+//	          ps.add(new GbPoint3D(x21, (*points)[i]->x2 + ((*points)[i]->x2-last->x2)*f, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((greater(points[0].x1, x21)) ^ flag))
+//	 {
+//	    f = (x21-points[0].x1)/(points[0].x1-last.x1);
+//	    ps.add(new GbPoint3D(x21, points[0].x2 + (points[0].x2-last.x2)*f, points[0].x3 + (points[0].x3-last.x3)*f));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an oberer Kante                                        */
+//      /*                                                                   */
+//      if(greater(ps.getX2Maximum(), x22))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(greater(points[0].x2, x22)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(greater((*points)[i]->x2, x22))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x22-(*points)[i]->x2)/(points[i].x2-last.x2);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, x22, points[i].x3 + (points[i].x3-last.x3)*f));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x22-points[i].x2)/(points[i].x2-last.x2);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, x22, points[i].x3 + (points[i].x3-last.x3)*f));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((greater(points[0].x2, x22)) ^ flag))
+//	 {
+//	    f = (x22-points[0].x2)/(points[0].x2-last.x2);
+//	    ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, x22, points[0].x3 + (points[0].x3-last.x3)*f));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an linker Kante                                        */
+//      /*                                                                   */
+//      if(less(ps.getX1Minimum(), x11))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(less(points[0].x1, x11)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(less(points[i].x1, x11))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x11-points[i].x1)/(points[i].x1-last.x1);
+//	          ps.add(new GbPoint3D(x11, points[i].x2 + (points[i].x2-last.x2)*f, points[i].x3 + (points[i].x3-last.x3)*f));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x11-points[i].x1)/(points[i].x1-last.x1);
+//	          ps.add(new GbPoint3D(x11, points[i].x2 + (points[i].x2-last.x2)*f, points[i].x3 + (points[i].x3-last.x3)*f));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((less(points[0].x1, x11)) ^ flag))
+//	 {
+//	    f = (x11-points[0].x1)/(points[0].x1-last.x1);
+//	    ps.add(new GbPoint3D(x11, points[0].x2 + (points[0].x2-last.x2)*f, points[0].x3 + (points[0].x3-last.x3)*f));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      GbPolygon3D polygon = new GbPolygon3D(points);
+//
+//      if(n > 2)
+//      {
+//	 for(i=2; i<n; i++) if(zero(i_TA(points[i-2], points[i-1], points[i]))) polygon.deletePoint(points[i-1]);
+//	 if(zero(i_TA(points[n-2], points[n-1], points[0]))) polygon.deletePoint(points[n-1]);
+//	 if(zero(i_TA(points[n-1], points[0],   points[1]))) polygon.deletePoint(points[0]);
+//      }
+//      return(polygon);
+//   }
+//   final static GbPolygon3D clipPolygon3D(GbPoint3D points[], double x13, double x23)
+//   {
+//      GbPoint3D last = null;
+//      PointSet3 ps   = new PointSet3(points);
+//      boolean   flag = false;
+//      int       n    = points.length;
+//      int       i;
+//      double    f;
+//
+//      if(n == 0)              return(null);
+//      if(greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; }
+//
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an vorderer Kante                                      */
+//      /*                                                                   */
+//      if(less(ps.getX3Minimum(), x13))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(less(points[0].x3, x13)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(less(points[i].x3, x13))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x13-points[i].x3)/(points[i].x3-last.x3);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x13));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x13-points[i].x3)/(points[i].x3-last.x3);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x13));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((less(points[0].x3, x13)) ^ flag))
+//	 {
+//	    f = (x13-points[0].x3)/(points[0].x3-last.x3);
+//	    ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, points[0].x2 + (points[0].x2-last.x2)*f, x13));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an hinterer Kante                                      */
+//      /*                                                                   */
+//      if(greater(ps.getX3Maximum(), x23))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(greater(points[0].x3, x23)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(greater(points[i].x3, x23))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x23-points[i].x3)/(points[i].x3-last.x3);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x23));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x23-points[i].x3)/(points[i].x3-last.x3);
+//	          ps.add(new GbPoint3D(points[i].x1 + ((*points)[i]->x1-last.x1)*f, (*points)[i]->x2 + ((*points)[i]->x2-last.x2)*f, x23));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((greater(points[0].x3, x23)) ^ flag))
+//	 {
+//	    f = (x23-points[0].x3)/(points[0].x3-last.x3);
+//	    ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, points[0].x2 + (points[0].x2-last.x2)*f, x23));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      GbPolygon3D polygon = new GbPolygon3D(points);
+//
+//      return(polygon);
+//   }
+GbPolygon3D* GbSystem3D::clipPolygon3D(vector<GbPoint3D> points, double x11, double x12, double x13, double x21, double x22, double x23)
+{
+   GbPoint3D last;
+   PointSet3 ps(points);
+   bool   flag = false;
+   int    n    = (int)points.size();
+	int       i;
+   double    f;
+
+   if(n == 0)              return NULL;
+   if(UbMath::greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; }
+   if(UbMath::greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; }
+   if(UbMath::greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; }
+
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an vorderer Kante                                      */
+   /*                                                                   */
+   if(UbMath::less(ps.getX3Minimum(), x13))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::less((points)[0].x3, x13)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::less((points)[i].x3, x13))
+			{
+				if(flag)
+				{
+					f = (x13-(points)[i].x3)/((points)[i].x3-last.x3);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x13));
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x13-(points)[i].x3)/((points)[i].x3-last.x3);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x13));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::less((points)[0].x3, x13)) ^ flag))
+		{
+			f = (x13-(points)[0].x3)/((points)[0].x3-last.x3);
+			ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, (points)[0].x2 + ((points)[0].x2-last.x2)*f, x13));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+   }
+	
+	/*-------------------------------------------------------------------*/
+   /*  Schneiden an unterer Kante                                       */
+   /*                                                                   */
+   if(UbMath::less(ps.getX2Minimum(), x12))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::less((points)[0].x2, x12)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::less((points)[i].x2, x12))
+			{
+				if(flag)
+				{
+					f = (x12-(points)[i].x2)/((points)[i].x2-last.x2);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x12, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				flag = false;
+			}
+		   else
+			{
+				if(!flag)
+				{
+					f = (x12-(points)[i].x2)/((points)[i].x2-last.x2);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x12, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::less((points)[0].x2, x12)) ^ flag))
+		{
+			f = (x12-(points)[0].x2)/((points)[0].x2-last.x2);
+			ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, x12, (points)[0].x3 + ((points)[0].x3-last.x3)*f));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an rechter Kante                                       */
+   /*                                                                   */
+	
+	if(UbMath::greater(ps.getX1Maximum(), x21))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::greater((points)[0].x1, x21)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::greater((points)[i].x1, x21))
+			{
+				if(flag)
+				{
+					f = (x21-(points)[i].x1)/((points)[i].x1-last.x1);
+					ps.add(GbPoint3D(x21, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x21-(points)[i].x1)/((points)[i].x1-last.x1);
+					ps.add(GbPoint3D(x21, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::greater((points)[0].x1, x21)) ^ flag))
+		{
+			f = (x21-(points)[0].x1)/((points)[0].x1-last.x1);
+			ps.add(GbPoint3D(x21, (points)[0].x2 + ((points)[0].x2-last.x2)*f, (points)[0].x3 + ((points)[0].x3-last.x3)*f));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an hinterer Kante                                      */
+   /*                                                                   */
+   if(UbMath::greater(ps.getX3Maximum(), x23))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::greater((points)[0].x3, x23)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::greater((points)[i].x3, x23))
+			{
+				if(flag)
+				{
+					f = (x23-(points)[i].x3)/((points)[i].x3-last.x3);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x23));
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x23-(points)[i].x3)/((points)[i].x3-last.x3);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x23));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::greater((points)[0].x3, x23)) ^ flag))
+		{
+			f = (x23-(points)[0].x3)/((points)[0].x3-last.x3);
+			ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, (points)[0].x2 + ((points)[0].x2-last.x2)*f, x23));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+	}
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an oberer Kante                                        */
+   /*                                                                   */
+
+	if(UbMath::greater(ps.getX2Maximum(), x22))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::greater((points)[0].x2, x22)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::greater((points)[i].x2, x22))
+			{
+				if(flag)
+				{
+					f = (x22-(points)[i].x2)/((points)[i].x2-last.x2);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x22, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x22-(points)[i].x2)/((points)[i].x2-last.x2);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x22, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::greater((points)[0].x2, x22)) ^ flag))
+		{
+			f = (x22-(points)[0].x2)/((points)[0].x2-last.x2);
+			ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, x22, (points)[0].x3 + ((points)[0].x3-last.x3)*f));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an linker Kante                                        */
+   /*                                                                   */
+	if(UbMath::less(ps.getX1Minimum(), x11))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::less((points)[0].x1, x11)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::less((points)[i].x1, x11))
+			{
+				if(flag)
+				{
+					f = (x11-(points)[i].x1)/((points)[i].x1-last.x1);
+					ps.add(GbPoint3D(x11, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x11-(points)[i].x1)/((points)[i].x1-last.x1);
+					ps.add(GbPoint3D(x11, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::less((points)[0].x1, x11)) ^ flag))
+		{
+			f = (x11-(points)[0].x1)/((points)[0].x1-last.x1);
+			ps.add(GbPoint3D(x11, (points)[0].x2 + ((points)[0].x2-last.x2)*f, (points)[0].x3 + ((points)[0].x3-last.x3)*f));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+		
+		if(n == 0) return NULL;
+   }
+   /*-------------------------------------------------------------------*/
+	return new GbPolygon3D(points);
+}
+/*=========================================================================*/
+GbCuboid3D* GbSystem3D::clipRectangle3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23)
+{
+   double r11 = p1.x1;
+   double r12 = p1.x2;
+   double r13 = p1.x3;
+   double r21 = p2.x1;
+   double r22 = p2.x2;
+   double r23 = p2.x3;
+
+   if(UbMath::greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; }
+   if(UbMath::greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; }
+   if(UbMath::greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; }
+   if(UbMath::greater(r11, r21)) { double bx = r11; r11 = r21; r21 = bx; }
+   if(UbMath::greater(r12, r22)) { double by = r12; r12 = r22; r22 = by; }
+   if(UbMath::greater(r13, r23)) { double bz = r13; r13 = r23; r23 = bz; }
+
+   double m11 = UbMath::greater(x11, r11) ? x11 : r11;
+   double m12 = UbMath::greater(x12, r12) ? x12 : r12;
+   double m13 = UbMath::greater(x13, r13) ? x13 : r13;
+   double m21 = UbMath::greater(x21, r21) ? r21 : x21;
+   double m22 = UbMath::greater(x22, r22) ? r22 : x22;
+   double m23 = UbMath::greater(x23, r23) ? r23 : x23;
+
+   if(UbMath::lessEqual(m11, m21) && UbMath::lessEqual(m12, m22) && UbMath::lessEqual(m13, m23)) 
+      return(new GbCuboid3D(new GbPoint3D(m11, m12, m13), new GbPoint3D(m21, m22, m23)));
+   else  
+      return(NULL);
+}
+
+/*=========================================================================*/
+/*=========================================================================*/
+/*=========================================================================*/
+
+
+GbSystem3D::PointSet3::PointSet3(int n)
+{
+   this->init();
+   this->points.reserve(n); //reserves n elements! but the size of the vector ist still "0"
+}
+/*=======================================================*/
+GbSystem3D::PointSet3::PointSet3(const vector<GbPoint3D>& points)
+{
+   this->init();
+   this->add(points);
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::add(const GbPoint3D& point)
+{
+   //is point equal to last point in points then return
+   if(!this->points.empty() && point.equals(&this->points.back())) return;    //WHY???
+
+   //push point to vector
+   this->points.push_back(point);
+
+   this->consistent = false;
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::addUnequal(const GbPoint3D& point)
+{
+   if(this->containsEqual(point) > 0) return;
+   
+   this->points.push_back(point);
+   this->consistent = false;
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::add(const vector<GbPoint3D>& pointVector)
+{
+   for(int pos=0; pos<(int)pointVector.size(); pos++ )
+      this->points.push_back(pointVector[pos]);
+
+   this->consistent = false;
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::insert(const GbPoint3D& point, int index)
+{
+   if(index<0 || index>=(int)this->points.size()) 
+      throw UbException(UB_EXARGS,"index out of range");
+
+   //get iterator for index-position
+   vector<GbPoint3D>::iterator pos=this->points.begin();
+   for(int i=1; i<=index; i++) ++pos;
+
+   //insert point
+   this->points.insert(pos,point);
+
+   this->consistent    = false;
+}
+/*=======================================================*/
+//void delete(GbPoint3D point)
+//{
+//   for(int i=this.size-1; i>=0; i--) if(this.points[i] == point) this.delete(i);
+//}
+/*=======================================================*/
+//void delete(int index)
+//{
+//   int j = this.size - index - 1;
+//   if(j > 0) System.arraycopy(this.points, index + 1, this.points, index, j);
+//   this.consistent = false;
+//   this.size--;
+//}
+/*=======================================================*/
+void GbSystem3D::PointSet3::clear()
+{
+   //clears points (size==0 but capacity is the old one)
+   this->points.clear();
+   this->consistent = false;
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::clearAndTrim()
+{
+   //clears points (size==0 AND capacity==0)
+   this->points.resize(0);
+   this->consistent = false;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX1Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x1min;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX1Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x1max;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX2Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x2min;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX2Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x2max;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX3Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x3min;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX3Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x3max;
+}
+/*=======================================================*/
+int GbSystem3D::PointSet3::contains(GbPoint3D* point)
+{
+   //returns number of points which has the same adress (this should be 0 or 1!!!)
+   int n=0;
+
+   for(int pos=(int)this->points.size()-1; pos>=0; pos--) 
+      if(&this->points[pos]==point) n++;
+
+   return n;
+}
+/*=======================================================*/
+int GbSystem3D::PointSet3::containsEqual(const GbPoint3D& point)
+{
+   //returns number of points which have the same coordinates with point (could be 0,1 or even more)
+   int n=0;
+
+   for(int pos=(int)this->points.size()-1; pos>=0; pos--) 
+      if(this->points[pos].equals(&point)) n++;
+
+   return n;
+}
+/*=======================================================*/
+bool GbSystem3D::PointSet3::containsLine(GbPoint3D *point1, GbPoint3D *point2)
+{
+   //returns true if pointset has two in "this->points"vector  neighboured points 
+   //wich have the same adress as point1 or point2
+   vector<GbPoint3D>::iterator pos1=this->points.begin();
+   vector<GbPoint3D>::iterator pos2;
+
+   for(pos2=pos1++; pos2!=this->points.end(); ++pos2) 
+   {
+      if     (&(*pos1)==point1 && &(*pos2)==point2) return true;
+      else if(&(*pos1)==point2 && &(*pos2)==point1) return true;
+
+      pos1=pos2;
+   }
+
+   return false;
+}
+/*=======================================================*/
+bool GbSystem3D::PointSet3::containsEqualLine(const GbPoint3D& point1, const GbPoint3D& point2)
+{
+   //returns true if pointset has two in "this->points"vector  neighboured points 
+   //wich have the same coordinates as point1 or point2
+   vector<GbPoint3D>::iterator pos1=this->points.begin();
+   vector<GbPoint3D>::iterator pos2;
+
+   for(pos2=pos1++; pos2!=this->points.end(); ++pos2) 
+   {
+      if     ((*pos1).equals(&point1) && (*pos2).equals(&point2)) return true;
+      else if((*pos1).equals(&point2) && (*pos2).equals(&point1)) return true;
+
+      pos1=pos2;
+   }
+
+   return false;
+}
+/*=======================================================*/
+GbPoint3D* GbSystem3D::PointSet3::getPoint(int index)
+{
+   if(index<0 || index>=(int)this->points.size()) throw UbException(UB_EXARGS,"index out of range");
+   return &(this->points)[index];
+}
+/*=======================================================*/
+GbPoint3D* GbSystem3D::PointSet3::getFirstPoint()
+{
+   return &(this->points.front());
+}
+/*=======================================================*/
+GbPoint3D* GbSystem3D::PointSet3::getLastPoint() 
+{ 
+   return &(this->points.back()); 
+}
+/*=======================================================*/
+int GbSystem3D::PointSet3::size()
+{ 
+   return (int)this->points.size();      
+}
+/*=======================================================*/
+vector<GbPoint3D> GbSystem3D::PointSet3::getPoints()
+{
+   //is this right? it's another effect as at GbPoint3D* getNode(index)!!!
+   //or do we want to have the next uncommented getPoints() funktion
+   return this->points;
+}
+///*=======================================================*/
+//vector<GbPoint3D*> GbSystem3D::PointSet3::getPoints()
+//{
+//   vector<GbPoint3D*> tmp;
+//   for(int pos=0; pos<(int)this->points.size();pos++) tmp.push_back(&this->points[pos]);
+//   
+//   return tmp;
+//}
+/*=======================================================*/
+void GbSystem3D::PointSet3::calculateValues()
+{
+   if(this->points.empty()) 
+   {
+      this->x1min = this->x2min = this->x3min = 0.0;
+      this->x1max = this->x2max = this->x3max = 0.0;
+   }
+   else
+   {
+      this->x1min = (this->points)[0].x1;
+      this->x1max = (this->points)[0].x1;
+      this->x2min = (this->points)[0].x2;
+      this->x2max = (this->points)[0].x2;
+      this->x3min = (this->points)[0].x3;
+      this->x3max = (this->points)[0].x3;
+
+      for(int i=(int)this->points.size()-1; i>0; --i)
+      {
+         if((this->points)[i].x1 < this->x1min) this->x1min = (this->points)[i].x1;
+         if((this->points)[i].x1 > this->x1max) this->x1max = (this->points)[i].x1;
+         if((this->points)[i].x2 < this->x2min) this->x2min = (this->points)[i].x2;
+         if((this->points)[i].x2 > this->x2max) this->x2max = (this->points)[i].x2;
+         if((this->points)[i].x3 < this->x3min) this->x3min = (this->points)[i].x3;
+         if((this->points)[i].x3 > this->x3max) this->x3max = (this->points)[i].x3;
+      }
+   }
+   this->consistent = true;
+}
+
+
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbSystem3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbSystem3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3f579b282f16b5c74b4958688305081c09b7c29
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbSystem3D.h
@@ -0,0 +1,396 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBSYSTEM3D_H
+#define GBSYSTEM3D_H
+
+#include <iostream>
+#include <cmath>
+#include <vector>
+
+#include <basics/utilities/UbMath.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbObject3D.h>
+#include <basics/writer/WbWriter.h>
+
+class GbPolygon3D;
+class GbCuboid3D;
+class GbLine3D;
+
+namespace GbSystem3D
+{
+   extern double       getDistance(const GbPoint3D& p11, const GbPoint3D& p12);
+   extern GbPoint3D*   calculateIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22);
+   extern GbPolygon3D* clipPolygon3D(std::vector<GbPoint3D> points, double x11, double x12, double x13, double x21, double x22, double x23);
+   extern GbLine3D*    createClipLine3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23);
+   extern bool         hasIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22);
+   extern bool         isParallelIn3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22);
+   extern GbCuboid3D*  clipRectangle3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23);
+
+   /*========================================================================================*/
+   inline static std::string writeGeoObject(GbObject3D* gbobject, const std::string& filename, WbWriter* writer)
+   {
+      std::vector<UbTupleFloat3> nodes;
+      std::vector<UbTupleInt3>   triangles;
+      gbobject->addSurfaceTriangleSet(nodes, triangles);
+
+      std::string outFilename = writer->writeTriangles(filename,nodes,triangles);
+      return outFilename;
+   }
+   //the same as before
+   /*========================================================================================*/
+   inline static std::string writeGeoObject(GbObject3DPtr gbobject, const std::string& filename, WbWriter* writer)
+   {
+      std::vector<UbTupleFloat3> nodes;
+      std::vector<UbTupleInt3>   triangles;
+      gbobject->addSurfaceTriangleSet(nodes, triangles);
+
+      std::string outFilename = writer->writeTriangles(filename,nodes,triangles);
+      return outFilename;
+   }
+   /*========================================================================================*/
+   inline static std::vector< std::string > writeGeoObject(GbObject3D*  gbobject, const std::string& filename, std::vector< WbWriter* > writer )
+   {
+      std::vector<UbTupleFloat3> nodes;
+      std::vector<UbTupleInt3>   triangles;
+      gbobject->addSurfaceTriangleSet(nodes, triangles);
+
+      std::vector< std::string > outFilenames;
+      for(std::size_t i=0; i<writer.size(); ++i)
+         outFilenames.push_back( writer[i]->writeTriangles(filename,nodes,triangles) );
+      return outFilenames;
+   }
+   /*========================================================================================*/
+   inline static std::string writeGeoObjects(std::vector< GbObject3D* > gbobjects, const std::string& filename, WbWriter* writer)
+   {
+      std::vector<UbTupleFloat3> nodes;
+      std::vector<UbTupleInt3>   triangles;
+
+      for(std::size_t i=0; i<gbobjects.size(); ++i)
+      {
+         //std::cout<<i<<", "<<gbobjects[i]<<std::endl;
+         gbobjects[i]->addSurfaceTriangleSet(nodes, triangles);
+      }
+
+      std::string outFilename = writer->writeTriangles(filename,nodes,triangles);
+      return outFilename;
+   }
+   /*========================================================================================*/
+
+   //////////////////////////////////////////////////////////////////////////
+   class PointSet3
+   {
+   public:
+      PointSet3(int n);
+      PointSet3(const std::vector<GbPoint3D>& points);
+      ~PointSet3(){}
+      void   add(const GbPoint3D& point);
+      void   addUnequal(const GbPoint3D& point);
+      void   add(const std::vector<GbPoint3D>& p);
+      int    contains(GbPoint3D* point);
+      void   insert(const GbPoint3D& point, int index);
+      void   clear();
+      void   clearAndTrim();
+      int    containsEqual(const GbPoint3D& point);
+      bool   containsLine(GbPoint3D* point1, GbPoint3D* point2);
+      bool   containsEqualLine(const GbPoint3D& point1, const GbPoint3D& point2);
+      double getX1Minimum();
+      double getX1Maximum();
+      double getX2Minimum();
+      double getX2Maximum();
+      double getX3Minimum();
+      double getX3Maximum();
+      void   calculateValues();
+      int    size();
+      GbPoint3D* getPoint(int index);
+      GbPoint3D* getFirstPoint();
+      GbPoint3D* getLastPoint() ;
+      std::vector<GbPoint3D> getPoints();
+
+   private:
+      double    x1min;
+      double    x1max;
+      double    x2min;
+      double    x2max;
+      double    x3min;
+      double    x3max;
+      bool      consistent;
+      std::vector<GbPoint3D> points;
+
+      void init()
+      {
+         consistent = false;
+         x1min = x2min = x3min = 0.0;
+         x1max = x2max = x3max = 0.0;
+      }
+   };
+   /*=================================================================*/
+   class OldPointSet3
+   {
+   private:
+      int       sizet;
+      double    x1min;
+      double    x1max;
+      double    x2min;
+      double    x2max;
+      double    x3min;
+      double    x3max;
+      bool      consistent;
+      std::vector<GbPoint3D> points;
+
+      void init()
+      {
+         sizet      = 0;
+         x1min      = 0.0;
+         x1max      = 0.0;
+         x2min      = 0.0;
+         x2max      = 0.0;
+         x3min		  = 0.0;
+         x3max      = 0.0;
+         consistent = false;
+         //points   = NULL;
+      };
+
+   public:
+      OldPointSet3(int n)
+      {
+         this->init();
+         this->points.resize(n);
+      }
+      OldPointSet3(std::vector<GbPoint3D> &points)
+      {
+         this->init();
+         this->points.resize(0);//, NULL);
+         this->add(points);
+      };
+      ~OldPointSet3()
+      {
+         //			delete points;
+      };
+      void add(GbPoint3D point)
+         {
+            if(this->sizet>0 && point.equals(&(this->points)[this->sizet-1])) return;
+            if(this->sizet == (int)this->points.size())
+            {
+               std::vector<GbPoint3D> a;
+               a.resize(1+(this->sizet<<1));
+               for(int u=0; u<this->sizet; u++)  { (a)[u] = (points)[u];	}
+               this->points = a;
+            }
+            (this->points)[this->sizet] = point;
+            this->consistent				= false;
+            this->sizet++;
+         }
+         void addUnequal(GbPoint3D *point)
+         {
+            if(this->containsEqual(point) > 0) return;
+            if(this->sizet == (int)this->points.size())
+            {
+               std::vector<GbPoint3D> a;
+               a.resize(1+(this->sizet<<1));
+               for(int u=0; u<this->sizet; u++)  { (a)[u] = (points)[u];	}
+               this->points = a;
+            }
+            (this->points)[this->sizet] = point;
+            this->consistent        = false;
+            this->sizet++;
+         }
+         void add(std::vector<GbPoint3D> &p)
+         {
+            if(this->sizet+p.size() >= this->points.size())
+            {
+               std::vector<GbPoint3D> a;
+               a.resize(this->sizet+p.size());
+               for(int u=0; u<(int)this->points.size(); u++)  { (a)[u] = (this->points)[u];	}
+               this->points = a;
+            }
+            int u = this->sizet;// (int)this->points->size();
+            for(int b=0; b<(int)p.size(); b++)			(this->points)[u++] = (p)[b];
+            //u = this->sizet;
+            //for(int b=0; b<(int)p->size(); b++)
+            //	cout<<(this->points)[u++].toString()<<endl;
+            this->consistent  = false;
+            this->sizet      += (int)p.size();
+         };
+         //		void insert(GbPoint3D *point, int index)
+         //      {
+         //	 if(this.size == this.points.length)
+         //	 {
+         //	    GbPoint3D a[] = new GbPoint3D[1+(this.size<<1)];
+         //	    System.arraycopy(this.points, 0, a, 0, this.size);
+         //	    this.points = a;
+         //	 }
+         //	 System.arraycopy(this.points, index, this.points, index+1, this.size-index);
+         //	 this.points[index] = point;
+         //	 this.consistent    = false;
+         //	 this.size++;
+         //      }
+         //      void delete(GbPoint3D point)
+         //      {
+         //	 for(int i=this.size-1; i>=0; i--) if(this.points[i] == point) this.delete(i);
+         //      }
+         //      void delete(int index)
+         //      {
+         //	 int j = this.size - index - 1;
+         //	 if(j > 0) System.arraycopy(this.points, index + 1, this.points, index, j);
+         //	 this.consistent = false;
+         //	 this.size--;
+         //      }
+         void clear()
+         {
+            this->sizet    = 0;
+            this->consistent = false;
+         }
+         void clearAndTrim()
+         {
+            this->sizet       = 0;
+            this->points.resize(0);
+            this->consistent = false;
+         }
+
+         double getX1Minimum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x1min);
+         }
+         double getX1Maximum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x1max);
+         }
+         double getX2Minimum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x2min);
+         }
+         double getX2Maximum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x2max);
+         }
+         double getX3Minimum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x3min);
+         }
+         double getX3Maximum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x3max);
+         }
+         void calculateValues()
+         {
+            this->x1min      = 0.0;
+            this->x1max      = 0.0;
+            this->x2min      = 0.0;
+            this->x2max      = 0.0;
+            this->x3min      = 0.0;
+            this->x3max      = 0.0;
+            this->consistent = true;
+
+            if(this->sizet == 0) return;
+
+            this->x1min = (this->points)[0].x1;
+            this->x1max = (this->points)[0].x1;
+            this->x2min = (this->points)[0].x2;
+            this->x2max = (this->points)[0].x2;
+            this->x3min = (this->points)[0].x3;
+            this->x3max = (this->points)[0].x3;
+
+            for(int i=this->sizet-1; i>0; i--)
+            {
+               if((this->points)[i].x1 < this->x1min) this->x1min = (this->points)[i].x1;
+               if((this->points)[i].x1 > this->x1max) this->x1max = (this->points)[i].x1;
+               if((this->points)[i].x2 < this->x2min) this->x2min = (this->points)[i].x2;
+               if((this->points)[i].x2 > this->x2max) this->x2max = (this->points)[i].x2;
+               if((this->points)[i].x3 < this->x3min) this->x3min = (this->points)[i].x3;
+               if((this->points)[i].x3 > this->x3max) this->x3max = (this->points)[i].x3;
+            }
+         };
+
+         int contains(GbPoint3D *point)
+         {
+            int n = 0;
+            for(int i=this->sizet-1; i>=0; i--) if(&(this->points)[i] == point) n++;
+            return(n);
+         };
+         int containsEqual(GbPoint3D *point)
+         {
+            int n = 0;
+            for(int i=this->sizet-1; i>=0; i--) if((this->points)[i].equals(point)) n++;
+            return(n);
+         }
+         bool containsLine(GbPoint3D *point1, GbPoint3D *point2)
+         {
+            for(int i=this->sizet-1; i>=0; i--) if(&(this->points)[i] == point1)
+            {
+               if(i == 0)
+               {
+                  if(&(this->points)[i+1]           == point2) return(true);
+                  if(&(this->points)[this->sizet-1] == point2) return(true);
+               }
+               else if(i == this->sizet-1)
+               {
+                  if(&(this->points)[0]   == point2) return(true);
+                  if(&(this->points)[i-1] == point2) return(true);
+               }
+               else
+               {
+                  if(&(this->points)[i+1] == point2) return(true);
+                  if(&(this->points)[i-1] == point2) return(true);
+               }
+            }
+            return(false);
+         };
+         //      boolean containsEqualLine(GbPoint2D point1, GbPoint2D point2)
+         //      {
+         //	 for(int i=this.size-1; i>=0; i--) if(this.points[i].equals(point1))
+         //	 {
+         //	    if(i == 0)
+         //	    {
+         //	       if(this.points[i+1].equals(point2))         return(true);
+         //	       if(this.points[this.size-1].equals(point2)) return(true);
+         //	    }
+         //	    else if(i == this.size-1)
+         //	    {
+         //	       if(this.points[0].equals(point2))   return(true);
+         //	       if(this.points[i-1].equals(point2)) return(true);
+         //	    }
+         //	    else
+         //	    {
+         //	       if(this.points[i+1].equals(point2)) return(true);
+         //	       if(this.points[i-1].equals(point2)) return(true);
+         //	    }
+         //	 }
+         //	 return(false);
+         //      }
+         GbPoint3D *getPoint(int index)
+         {
+            return(&(this->points)[index]);
+         }
+         GbPoint3D *getFirstPoint()
+         {
+            return(&(this->points)[0]);
+         }
+         GbPoint3D *getLastPoint() { return(&(this->points)[this->sizet-1]); }
+         int size()                { return(this->sizet);      }
+         std::vector<GbPoint3D> getPoints()
+         {
+            points.resize(sizet);
+            return points;
+            //int l = this->sizet;
+            //if(l > 1 && (this->points)[0].equals(&(this->points)[l-1])) l--;
+
+            //vector<GbPoint3D*> *a = new vector<GbPoint3D*>;
+            //a->resize(l, NULL);
+            //for(int u=0; u<l; u++)  { (*a)[u] = &((points)[u]);	}
+            //return(a);
+         }
+      };
+      /*=================================================================*/
+}
+
+#endif //GBSYSTEM3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbTriFaceMesh3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbTriFaceMesh3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..70cc36cfd640cd6fe3f93fdfb05e7fd3ec81c58d
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbTriFaceMesh3D.cpp
@@ -0,0 +1,1146 @@
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+#include <numerics/geometry3d/CoordinateTransformation3D.h>
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+#include <basics/utilities/UbRandom.h>
+#include <basics/utilities/UbTiming.h>
+#include <basics/utilities/UbLogger.h>
+
+#include <numerics/geometry3d/KdTree/KdTree.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h>
+
+using namespace std;
+
+GbTriFaceMesh3D::GbTriFaceMesh3D() 
+   :   GbObject3D()
+     , buildVertTriRelationMap(false)
+     , kdTree(NULL)
+     , transX1(0.0)
+     , transX2(0.0)
+     , transX3(0.0)
+     , transferViaFilename(false)
+
+{
+   this->setName("CAB_GbTriFaceMesh3D");
+   this->nodes          = new vector<Vertex>;
+   this->triangles      = new vector<TriFace>;
+   this->consistent     = false;
+   this->kdtreeSplitAlg = KDTREE_SAHPLIT;
+}
+/*=======================================================================*/
+GbTriFaceMesh3D::GbTriFaceMesh3D(string name, vector<Vertex>* nodes, vector<TriFace>* triangles, KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+   :  GbObject3D()
+    , nodes(nodes)
+    , triangles(triangles)
+    , buildVertTriRelationMap(false)
+    , consistent(false)
+    , kdTree(NULL)
+    , kdtreeSplitAlg(splitAlg)
+    , transX1(0.0)
+    , transX2(0.0)
+    , transX3(0.0)
+    , transferViaFilename(false)
+{
+   if( name.empty() ) throw UbException(UB_EXARGS,"no name specified");
+   if( !nodes       ) throw UbException(UB_EXARGS,"no nodes specified");
+   if( !triangles   ) throw UbException(UB_EXARGS,"no triangles specified");
+
+   this->setName(name);
+
+   if(removeRedundantNodes)
+   {
+      this->deleteRedundantNodes(); //dort wird autoamtisch calculateValues() aufgerufen
+   }
+   else
+   {
+      this->calculateValues();
+   }
+}
+/*=======================================================================*/
+GbTriFaceMesh3D::~GbTriFaceMesh3D()
+{
+   if( nodes     ) { delete nodes;     nodes     = NULL; }
+   if( triangles ) { delete triangles; triangles = NULL; }
+   if( kdTree    ) { delete kdTree;    kdTree    = NULL; }
+}
+/*======================================================================*/
+ObObjectCreator* GbTriFaceMesh3D::getCreator()
+{
+   return GbTriFaceMesh3DCreator::getInstance();
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::init()
+{
+   nodes      = NULL;
+   triangles  = NULL;
+   x1min      = 0.0;
+   x1max      = 0.0;
+   x1center   = 0.0;
+   x2min      = 0.0;
+   x2max      = 0.0;
+   x2center   = 0.0;
+   x3min      = 0.0;
+   x3max      = 0.0;
+   x3center   = 0.0;
+   consistent = false;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3D::clone()
+{
+   vector<GbTriFaceMesh3D::Vertex>    *newNodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *newTriangles = new vector<GbTriFaceMesh3D::TriFace>;
+
+   int numberNodes = (int)this->nodes->size();
+
+   double x,y,z;
+   for(int u=0;u<numberNodes;u++)
+   {
+      x=(*nodes)[u].x;
+      y=(*nodes)[u].y;
+      z=(*nodes)[u].z;
+      newNodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+   }
+   int numberTris  = (int)this->triangles->size();
+   UBLOG(logDEBUG1,"numberTris:"<<numberTris);
+
+   int id1,id2,id3;
+   for(int u=0;u<numberTris;u++)
+   {
+      id1 = (*this->triangles)[u].v1;
+      id2 = (*this->triangles)[u].v2;
+      id3 = (*this->triangles)[u].v3;
+      newTriangles->push_back(GbTriFaceMesh3D::TriFace(id1,id2,id3));
+      //cout<<u<<" - id1,id2,id3:"<<id1<<","<<id2<<","<<id3<<endl;
+   }
+   UBLOG(logDEBUG1,"Tris gelesen");
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D("no name", newNodes, newTriangles);
+   UBLOG(logDEBUG1,"mesh cloned ...");
+
+   return mesh;
+}
+
+/*======================================================================*/
+//checks for doppelt nodes und fixed Dreicke die zweimal denselben Knoten haben
+void GbTriFaceMesh3D::deleteRedundantNodes()
+{
+    UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - Nodes before deleting redundant: "<<this->nodes->size());
+
+    map<Vertex,size_t/*new vecIndex*/> vertexMap;
+    map<Vertex,size_t/*new vecIndex*/>::iterator pos;
+    map<Vertex,size_t/*new vecIndex*/>::iterator it;
+    
+    vector<TriFace>& tris     = *this->triangles;
+    vector<Vertex>&  oldNodes = *this->nodes;
+    vector<Vertex>   newNodes;
+
+    for(size_t t=0; t<tris.size(); t++)
+    {
+       if(t%100==0) UBLOG(logDEBUG5,"GbTriFaceMesh3D::deleteRedundantNodes - tri: "<<(t)<<" von "<<tris.size());
+       TriFace& tri = tris[t];
+       //Knoten bereits in neuem node vector?
+       for(int v=0; v<=2; v++)
+       {
+          Vertex& vert = tri.getNode(v,oldNodes);
+          //pos=vertexMap.find( vert );
+          //if( pos==vertexMap.end() )
+          {
+             for(pos=vertexMap.begin();pos!=vertexMap.end();pos++)
+             {
+               Vertex rhs = pos->first;
+             //if(UbMath::inClosedInterval(vert.z,0.01999, 0.02001))
+               if ( fabs(vert.x-rhs.x)<1.E-5 && fabs(vert.y-rhs.y)<1.E-5 && fabs(vert.z-rhs.z)<1.E-5 )
+               {
+                  break;
+               }
+             }
+          }
+          if( pos!=vertexMap.end() ) tri.setNode(v, (int)pos->second);
+          else
+          {
+             newNodes.push_back(vert);
+             int index = (int)newNodes.size()-1;
+             vertexMap[vert] = index;                       
+             tri.setNode(v,index);
+          }
+       }
+    }
+
+    std::swap(*nodes,newNodes);
+
+    UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - Nodes after deleting redundant:"<<this->nodes->size());
+    //
+    //Das geht irgendwie nicht ...
+    //
+    //UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - checking for double triangles !!!");
+    //UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - Triangles before deleting redundant: "<<this->triangles->size());
+    //vector<TriFace> newSingleTris;
+    //newSingleTris.reserve( this->triangles->size() );
+    //for(size_t t=0; t<tris.size(); t++)
+    //{
+    //   Vertex& v1 = tris[t].getNode(0,*nodes); 
+    //   Vertex& v2 = tris[t].getNode(1,*nodes); 
+    //   Vertex& v3 = tris[t].getNode(2,*nodes); 
+
+    //   if(UbMath::greater(std::fabs(v1.x), 0.0634) && UbMath::inClosedInterval(v1.z, 0.01999, 0.02001))
+    //   {
+    //      UBLOG2(logINFO,std::cout, "V1:"<<v1.x<<" "<<v1.y<<" "<<v1.z);
+    //   }
+    //   if(UbMath::greater(std::fabs(v2.x), 0.0634) && UbMath::inClosedInterval(v2.z, 0.01999, 0.02001))
+    //   {
+    //      UBLOG2(logINFO,std::cout, "V2:"<<v2.x<<" "<<v2.y<<" "<<v2.z);
+    //   }
+    //   if(UbMath::greater(std::fabs(v3.x), 0.0634) && UbMath::inClosedInterval(v3.z, 0.01999, 0.02001))
+    //   {
+    //      UBLOG2(logINFO,std::cout, "V3:"<<v3.x<<" "<<v3.y<<" "<<v3.z);
+    //   }
+
+    //   bool inList = false;
+    //   for(size_t u=0; u<newSingleTris.size(); u++)
+    //   {
+    //      Vertex& vn1 = newSingleTris[t].getNode(0,*nodes); 
+    //      Vertex& vn2 = newSingleTris[t].getNode(1,*nodes); 
+    //      Vertex& vn3 = newSingleTris[t].getNode(2,*nodes); 
+
+    //      if(v1==vn1 && v2==vn2 && v3==vn3)      inList = true;
+    //      else if(v1==vn1 && v2==vn3 && v3==vn2) inList = true;
+    //      else if(v1==vn2 && v2==vn3 && v3==vn1) inList = true;
+    //      else if(v1==vn2 && v2==vn1 && v3==vn3) inList = true;
+    //      else if(v1==vn3 && v2==vn1 && v3==vn2) inList = true;
+    //      else if(v1==vn3 && v2==vn2 && v3==vn1) inList = true;
+    //   }
+    //   if(!inList) newSingleTris.push_back(tris[t]);
+    //   else 
+    //      UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - inList !!!!");
+    
+    //}
+    //swap(tris,newSingleTris);
+
+    //UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - Triangles after deleting redundant:"<<this->triangles->size());
+    UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - checking for triangles that have same node several times or are lines!!!");
+    int counter1 = 0;
+    int counter2 = 0;
+    vector<TriFace> newTris;
+    newTris.reserve( this->triangles->size() );
+    for(size_t t=0; t<tris.size(); t++)
+    {
+       Vertex& v1 = tris[t].getNode(0,*nodes); 
+       Vertex& v2 = tris[t].getNode(1,*nodes); 
+       Vertex& v3 = tris[t].getNode(2,*nodes); 
+       if( v1==v2 || v1==v3 || v2==v3 )
+       {
+          counter1++;
+       }
+       else if( tris[t].getArea(*nodes)<1.0E-8 )
+       {
+          counter2++;
+       }
+       else newTris.push_back(tris[t]);
+    }
+    if(counter1)
+    {
+       UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - ### Warning ###: found and removed  "<<counter1<<" triangle with double nodes!");
+    }
+    if(counter2)
+    {
+       UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - ### Warning ###: found and removed  "<<counter2<<" triangle that are lines!") ;
+    }
+    if(!counter1 && !counter2) { UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - alles gut... nix doppelt"); }
+    else swap(tris,newTris);
+    
+    UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - done" );
+    this->calculateValues();
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::setKdTreeSplitAlgorithm(KDTREE_SPLITAGORITHM mode) 
+{ 
+   if(kdTree && mode != this->kdtreeSplitAlg) { delete kdTree; kdTree = NULL; }
+   this->kdtreeSplitAlg = mode; 
+}
+/*======================================================================*/
+   /**
+    * Returns a string representation of this triangular mesh.
+    * @return a string representation of this triangular mesh
+    */
+string GbTriFaceMesh3D::toString()
+{
+	stringstream ss;
+	ss<<"GbTriFaceMesh3D[";
+	ss<<(int)this->triangles->size()<<"-Triangles, "<<(int)this->nodes->size()<<"-Nodes, "<<endl;
+   ss<<"]";
+   return(ss.str());
+}
+/**
+ * Returns the nodes of this triangular mesh.
+ * @return the nodes of this triangular mesh
+ */
+vector<GbTriFaceMesh3D::Vertex>* GbTriFaceMesh3D::getNodes()       {  return this->nodes;   }
+/**
+ * Returns the triangles of this triangular mesh.
+ * @return the triangles of this triangular mesh
+ */
+vector<GbTriFaceMesh3D::TriFace>* GbTriFaceMesh3D::getTriangles()  { return this->triangles;  }
+/**
+ * Returns the center x1 coordinate of this triangular mesh.
+ * @return the center x1 coordinate of this triangular mesh
+ */
+double GbTriFaceMesh3D::getVolume()
+{
+   vector<Vertex>&  vertices = *nodes;
+   vector<TriFace>& tris     = *triangles;
+
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3, G3i;
+   //double rSP1 = 0.0;double rSP2 = 0.0;double rSP3 = 0.0;
+   double volume = 0.0;
+   for(size_t t=0; t<tris.size(); t++)
+   {
+      TriFace& triangle = tris[t];
+      x1     = triangle.getV1x(vertices); y1 = triangle.getV1y(vertices); z1 = triangle.getV1z(vertices);
+      x2     = triangle.getV2x(vertices); y2 = triangle.getV2y(vertices); z2 = triangle.getV2z(vertices);
+      x3     = triangle.getV3x(vertices); y3 = triangle.getV3y(vertices); z3 = triangle.getV3z(vertices);
+      G3i    = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+   }
+   return volume;
+}
+/*===============================================*/
+UbTupleDouble3 GbTriFaceMesh3D::calculateCenterOfGravity()
+{
+   vector<Vertex>&  vertices = *nodes;
+   vector<TriFace>& tris     = *triangles;
+   
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3;
+   double G3i;
+   double rSP1 = 0.0, rSP2 = 0.0, rSP3 = 0.0, volume = 0.0;
+   
+   for(size_t t=0; t<tris.size(); t++)
+   {
+      TriFace& triangle = tris[t];
+      x1     = triangle.getV1x(vertices); y1 = triangle.getV1y(vertices); z1 = triangle.getV1z(vertices);
+      x2     = triangle.getV2x(vertices); y2 = triangle.getV2y(vertices); z2 = triangle.getV2z(vertices);
+      x3     = triangle.getV3x(vertices); y3 = triangle.getV3y(vertices); z3 = triangle.getV3z(vertices);
+      G3i    = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+      rSP1   = rSP1+G3i*(x1+x2+x3);
+      rSP2   = rSP2+G3i*(y1+y2+y3);
+      rSP3   = rSP3+G3i*(z1+z2+z3);
+   }
+   rSP1 = rSP1/(24.0*volume);
+   rSP2 = rSP2/(24.0*volume);
+   rSP3 = rSP3/(24.0*volume);
+
+   return UbTupleDouble3(rSP1, rSP2, rSP3);
+}
+/*===============================================*/
+UbTupleDouble6 GbTriFaceMesh3D::calculateMomentOfInertia(double rhoP)
+{
+   vector<Vertex>& vertices = *nodes;
+
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3;
+   double G3i;
+   double xx,yy,zz,xy,yz,zx;
+   double rSP1 = 0.0;double rSP2 = 0.0;double rSP3 = 0.0;
+   double volume = 0.0;
+   double top11 = 0.0;double top22 = 0.0;double top33 = 0.0;
+   double top12 = 0.0;double top23 = 0.0;double top13 = 0.0;
+   int size = (int)this->triangles->size();
+   for(int u=0; u<size;u++)
+   {
+      TriFace& triangle = (*this->triangles)[u];
+      x1 = triangle.getV1x(vertices); y1 = triangle.getV1y(vertices); z1 = triangle.getV1z(vertices);
+      x2 = triangle.getV2x(vertices); y2 = triangle.getV2y(vertices); z2 = triangle.getV2z(vertices);
+      x3 = triangle.getV3x(vertices); y3 = triangle.getV3y(vertices); z3 = triangle.getV3z(vertices);
+      G3i = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+      rSP1 = rSP1+G3i*(x1+x2+x3);
+      rSP2 = rSP2+G3i*(y1+y2+y3);
+      rSP3 = rSP3+G3i*(z1+z2+z3);
+   }
+   rSP1 = rSP1/(24.0*volume);
+   rSP2 = rSP2/(24.0*volume);
+   rSP3 = rSP3/(24.0*volume);
+
+   double x1s = 0.0;//rSP1;//0.0;//
+   double x2s = 0.0;//rSP2;//0.0;//
+   double x3s = 0.0;//rSP3;//0.0;//
+
+   for(int u=0; u<size;u++)
+   {
+      TriFace& triangle = (*this->triangles)[u];
+      x1 = triangle.getV1x(vertices)-x1s;
+      y1 = triangle.getV1y(vertices)-x2s;
+      z1 = triangle.getV1z(vertices)-x3s;
+      x2 = triangle.getV2x(vertices)-x1s;
+      y2 = triangle.getV2y(vertices)-x2s;
+      z2 = triangle.getV2z(vertices)-x3s;
+      x3 = triangle.getV3x(vertices)-x1s;
+      y3 = triangle.getV3y(vertices)-x2s;
+      z3 = triangle.getV3z(vertices)-x3s;
+      G3i = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      //rSP1 = rSP1+G3i*(x1+x2+x3)/(24.0*volume);
+      //rSP2 = rSP2+G3i*(y1+y2+y3)/(24.0*volume);
+      //rSP3 = rSP3+G3i*(z1+z2+z3)/(24.0*volume);
+      xx = x1*x1+x2*x2+x3*x3+x1*x2+x2*x3+x3*x1;
+      yy = y1*y1+y2*y2+y3*y3+y1*y2+y2*y3+y3*y1;
+      zz = z1*z1+z2*z2+z3*z3+z1*z2+z2*z3+z3*z1;
+      top11 = top11+(yy+zz)*rhoP*G3i/60.;
+      top22 = top22+(xx+zz)*rhoP*G3i/60.;
+      top33 = top33+(yy+xx)*rhoP*G3i/60.;
+      xy = 2.0*(x1*y1+x2*y2+x3*y3)+x2*y3+x3*y1+x1*y2+x3*y2+x1*y3+x2*y1;
+      yz = 2.0*(y1*z1+y2*z2+y3*z3)+y2*z3+y3*z1+y1*z2+y3*z2+y1*z3+y2*z1;
+      zx = 2.0*(z1*x1+z2*x2+z3*x3)+z2*x3+z3*x1+z1*x2+z3*x2+z1*x3+z2*x1;
+      top12 = top12-xy*rhoP*G3i/120.;
+      top23 = top23-yz*rhoP*G3i/120.;
+      top13 = top13-zx*rhoP*G3i/120.;
+   }
+   //Satz von Steiner ...
+   top11 = top11-rhoP*volume*(rSP2*rSP2+rSP3+rSP3);
+   top22 = top22-rhoP*volume*(rSP3*rSP3+rSP1*rSP1);
+   top33 = top33-rhoP*volume*(rSP1*rSP1+rSP2*rSP2);
+   top12 = top12+rhoP*volume*rSP1*rSP2;
+   top23 = top23+rhoP*volume*rSP2*rSP3;
+   top13 = top13+rhoP*volume*rSP3*rSP1;
+
+   cout<<"Volume:"<<volume<<"\n Traegheitsmomente:\n";
+   cout<<" top11:"<<top11<<" top22:"<<top22<<" top33:"<<top33<<endl;
+   cout<<" top12:"<<top12<<" top23:"<<top23<<" top13:"<<top13<<endl;
+
+   return UbTupleDouble6(top11,top22,top33,top12,top23,top13);
+}
+/*==============================================================*/
+void GbTriFaceMesh3D::calculateValues()
+{
+   relationVertTris.clear();
+
+   if( nodes->empty() )
+   {
+      x1min = x1max = x2min = x2max = x3min = x3max = 0.0;
+   }
+   else
+   {
+      Vertex& v = (*nodes)[0];
+      x1min = x1max = v.x;
+      x2min = x2max = v.y;
+      x3min = x3max = v.z;
+
+      for(size_t i=1; i<this->nodes->size(); i++)
+      {
+         Vertex& v1 = (*nodes)[i];
+         
+         x1min = UbMath::min<double>(x1min,v1.x);
+         x2min = UbMath::min<double>(x2min,v1.y);
+         x3min = UbMath::min<double>(x3min,v1.z);
+         
+         x1max = UbMath::max<double>(x1max,v1.x);
+         x2max = UbMath::max<double>(x2max,v1.y);
+         x3max = UbMath::max<double>(x3max,v1.z);
+      }
+      x1center = 0.5 * (x1min + x1max );
+      x2center = 0.5 * (x2min + x2max );
+      x3center = 0.5 * (x3min + x3max );
+      
+      vector<TriFace>& tris  = *this->triangles;
+      vector<Vertex>&  verts = *this->nodes;
+      for(size_t i=0; i<this->triangles->size(); i++)
+      {
+         tris[i].calculateNormal(verts);
+      }
+      //relation Vertex <-> Triangle ermitteln
+      if(buildVertTriRelationMap)
+      {
+         for(size_t t=0; t<tris.size(); t++)
+         {
+            TriFace& tri = tris[t];
+            relationVertTris.insert( make_pair( &verts[tri.v1], &tri) );
+            relationVertTris.insert( make_pair( &verts[tri.v2], &tri) );
+            relationVertTris.insert( make_pair( &verts[tri.v3], &tri) );
+         }
+      }
+   }
+   if(kdTree)
+   { 
+      delete kdTree; 
+      kdTree=NULL; 
+   }
+   
+   this->consistent = true;
+}
+/*=========================================================================*/
+std::vector<GbTriFaceMesh3D::TriFace*> GbTriFaceMesh3D::getTrianglesForVertex(Vertex* vertex)
+{
+   if(!buildVertTriRelationMap) { buildVertTriRelationMap=true; consistent = false;}
+   if(!consistent) this->calculateValues();
+
+   typedef std::multimap<Vertex*,TriFace*>::iterator Iterator;
+   pair<Iterator,Iterator> objRange = relationVertTris.equal_range(vertex);
+
+   std::vector<TriFace*> tmpTris;
+   for(Iterator pos=objRange.first; pos!=objRange.second; ++pos) 
+      tmpTris.push_back( pos->second );
+
+   return tmpTris;
+}
+/*=======================================================*/
+void GbTriFaceMesh3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3) 
+{
+   this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() );
+}
+
+/*======================================================================*/
+void GbTriFaceMesh3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{
+   CoordinateTransformation3D trafoForw(this->getX1Centroid(), this->getX2Centroid(), this->getX3Centroid(), 1.0, 1.0, 1.0, 0.0, 0.0, 0.0);
+   CoordinateTransformation3D trafoBack(this->getX1Centroid(), this->getX2Centroid(), this->getX3Centroid(), sx1, sx2, sx3, 0, 0, 0);
+
+   vector<Vertex>& vertices = *nodes;
+   for(size_t i=0; i<vertices.size(); i++)
+   {
+      Vertex& v = vertices[i];
+      double p1x1 = trafoForw.transformForwardToX1Coordinate(v.x, v.y, v.z);
+      double p1x2 = trafoForw.transformForwardToX2Coordinate(v.x, v.y, v.z);
+      double p1x3 = trafoForw.transformForwardToX3Coordinate(v.x, v.y, v.z);
+      v.x = (float)trafoBack.transformBackwardToX1Coordinate(p1x1, p1x2, p1x3);
+      v.y = (float)trafoBack.transformBackwardToX2Coordinate(p1x1, p1x2, p1x3);
+      v.z = (float)trafoBack.transformBackwardToX3Coordinate(p1x1, p1x2, p1x3);
+   }
+   this->calculateValues();
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::rotate(const double& alpha, const double& beta, const double& gamma)
+{
+   CoordinateTransformation3D trafoForw(this->getX1Centroid(), this->getX2Centroid(), this->getX3Centroid(), 1.0, 1.0, 1.0, 0.0, 0.0, 0.0);
+   CoordinateTransformation3D trafoBack(this->getX1Centroid(), this->getX2Centroid(), this->getX3Centroid(), 1.0, 1.0, 1.0, alpha, beta, gamma);
+
+   vector<Vertex>& vertices = *nodes;
+   for(size_t i=0; i<vertices.size(); i++)
+   {
+      Vertex& v = vertices[i];
+      double p1x1 = trafoForw.transformForwardToX1Coordinate(v.x, v.y, v.z);
+      double p1x2 = trafoForw.transformForwardToX2Coordinate(v.x, v.y, v.z);
+      double p1x3 = trafoForw.transformForwardToX3Coordinate(v.x, v.y, v.z);
+      v.x = (float)trafoBack.transformBackwardToX1Coordinate(p1x1, p1x2, p1x3);
+      v.y = (float)trafoBack.transformBackwardToX2Coordinate(p1x1, p1x2, p1x3);
+      v.z = (float)trafoBack.transformBackwardToX3Coordinate(p1x1, p1x2, p1x3);
+   }
+   this->calculateValues();
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::rotateAroundPoint(const double& px1, const double& px2, const double& px3, const double& alpha, const double& beta, const double& gamma)
+{
+   CoordinateTransformation3D trafoForw(px1, px2, px3, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0);
+   CoordinateTransformation3D trafoBack(px1, px2, px3, 1.0, 1.0, 1.0, alpha, beta, gamma);
+
+   vector<Vertex>& vertices = *nodes;
+   for(size_t i=0; i<vertices.size(); i++)
+   {
+      Vertex& v = vertices[i];
+      double p1x1 = trafoForw.transformForwardToX1Coordinate(v.x, v.y, v.z);
+      double p1x2 = trafoForw.transformForwardToX2Coordinate(v.x, v.y, v.z);
+      double p1x3 = trafoForw.transformForwardToX3Coordinate(v.x, v.y, v.z);
+      v.x = (float)trafoBack.transformBackwardToX1Coordinate(p1x1, p1x2, p1x3);
+      v.y = (float)trafoBack.transformBackwardToX2Coordinate(p1x1, p1x2, p1x3);
+      v.z = (float)trafoBack.transformBackwardToX3Coordinate(p1x1, p1x2, p1x3);
+   }
+   this->calculateValues();
+}
+
+
+/*======================================================================*/
+void GbTriFaceMesh3D::translate(const double& x1, const double& x2, const double& x3)
+{
+   vector<Vertex>& vertices = *nodes;
+   for(size_t i=0; i<vertices.size(); i++)
+   {
+      Vertex& v = vertices[i];
+      v.x += static_cast<float>(x1);
+      v.y += static_cast<float>(x2);
+      v.z += static_cast<float>(x3);
+   }
+   this->calculateValues();
+}
+/*======================================================================*/
+vector<GbTriangle3D*> GbTriFaceMesh3D::getSurfaceTriangleSet()
+{
+   //SirAnn: eine miese Speicherlochmethode
+   //        hier werden dynmamische Objekte angelegt 
+   //        mit sowas rechnet von aussen kein Mensch!!!
+   vector<GbTriangle3D*> tris( triangles->size() );
+
+   for(size_t i=0; i<this->triangles->size(); i++)
+   {
+      Vertex& v1 = (*nodes)[(*triangles)[i].v1];
+      Vertex& v2 = (*nodes)[(*triangles)[i].v2];
+      Vertex& v3 = (*nodes)[(*triangles)[i].v3];
+
+      tris[i] = new GbTriangle3D(  new GbPoint3D(v1.x,v1.y,v1.z)
+                                 , new GbPoint3D(v2.x,v2.y,v2.z)
+                                 , new GbPoint3D(v3.x,v3.y,v3.z) );
+   }
+   return tris;
+}
+/*=======================================================*/
+void GbTriFaceMesh3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& pts, vector<UbTupleInt3>& tris)
+{
+   for(int i=0; i<(int)this->triangles->size(); i++)
+   {
+      Vertex& v1 = (*nodes)[(*triangles)[i].v1];
+      Vertex& v2 = (*nodes)[(*triangles)[i].v2];
+      Vertex& v3 = (*nodes)[(*triangles)[i].v3];
+      pts.push_back( makeUbTuple(v1.x,v1.y,v1.z));
+      pts.push_back( makeUbTuple(v2.x,v2.y,v2.z));
+      pts.push_back( makeUbTuple(v3.x,v3.y,v3.z));
+
+      tris.push_back( makeUbTuple( 3*i, 3*i+1, 3*i+2) );
+   }
+}
+/*======================================================================*/
+//bool GbTriFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, int counter)
+//{
+//
+//
+//   if( !nodes->empty() )
+//   {
+//      //Baum erstellen, wen noch keiner vorhanden
+//      if( !kdTree)
+//      {
+//         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
+//         UbTimer timer; timer.start();
+//         if(kdtreeSplitAlg == KDTREE_SAHPLIT     ) 
+//         {
+//            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
+//            this->kdTree = new Kd::Tree<double>( *this, Kd::SAHSplit<double>()            );
+//         }
+//         else if(kdtreeSplitAlg == KDTREE_SPATIALSPLIT)
+//         {
+//            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SpatialMedianSplit");
+//            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() ); 
+//         }
+//         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
+//         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+//      }
+//
+//      //eigentlicher PIO-Test
+//      //int iSec;
+//      //for(int i=0; i<100; i++)
+//      //{
+//      //   Kd::Ray<double> ray(  x1, x2, x3  //, 1, 0 ,0 );
+//      //                        , ( x1 < x1center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+//      //                        , ( x2 < x2center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+//      //                        , ( x3 < x3center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) );
+//      //                        
+//      //   iSec = kdTree->intersectRay( ray, Kd::CountRayIntersectionHandler<double>() );
+//      //     
+//      //   if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+//      //   {
+//      //      if(iSec == Kd::Intersection::ON_BOUNDARY )
+//      //      {
+//      //         return true;
+//      //      }
+//      //      return (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+//      //   }
+//      //   UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+//      //}
+//      //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+//      int iSec1,iSec2;
+//         
+//      Kd::Ray<double> ray1(  x1, x2, x3, 1.0, 0.0 ,0.0 );
+//      iSec1 = kdTree->intersectRay( ray1, Kd::CountRayIntersectionHandler<double>() );
+//      Kd::Ray<double> ray2(  x1, x2, x3, -1.0, 0.0 ,0.0 );
+//      iSec2 = kdTree->intersectRay( ray2, Kd::CountRayIntersectionHandler<double>() );
+//
+//      if(iSec1 == Kd::Intersection::ON_BOUNDARY || iSec2 == Kd::Intersection::ON_BOUNDARY)
+//      {
+//         return true;
+//      }
+//      if( iSec1 == Kd::Intersection::INTERSECT_EDGE && iSec2 == Kd::Intersection::INTERSECT_EDGE) 
+//      {
+//         UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.INTERSECT_EDGE");
+//         double eps = UbMath::getEqualityEpsilon<float>()*1000.0;
+//         if (counter>100) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+//         return this->isPointInGbObject3D(x1+eps, x2+eps, x3+eps,(counter+1)); 
+//      }
+//      else if( iSec1 == Kd::Intersection::INTERSECT_EDGE)
+//      {
+//         return (iSec2&1);  
+//      }
+//      else if( iSec2 == Kd::Intersection::INTERSECT_EDGE)
+//      {
+//         return (iSec1&1);  
+//      }
+//      else
+//      {
+//         if((iSec1&1) != (iSec2&1))
+//         {
+//            UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.iSec1&1 != iSec2&1");
+//            double eps = UbMath::getEqualityEpsilon<float>()*1000.0;
+//            if (counter>100) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+//            return this->isPointInGbObject3D(x1+eps, x2+eps, x3+eps,(counter+1));
+//         }
+//         return iSec1&1;
+//      }
+//      //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+//
+//   }
+//   return false;
+//}
+bool GbTriFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, int counter)
+{
+
+
+   if( !nodes->empty() )
+   {
+      //Baum erstellen, wen noch keiner vorhanden
+      if( !kdTree)
+      {
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
+         UbTimer timer; timer.start();
+         if(kdtreeSplitAlg == KDTREE_SAHPLIT     ) 
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SAHSplit<double>()            );
+         }
+         else if(kdtreeSplitAlg == KDTREE_SPATIALSPLIT)
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SpatialMedianSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() ); 
+         }
+         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+      }
+
+      //eigentlicher PIO-Test
+      //int iSec;
+      //for(int i=0; i<100; i++)
+      //{
+      //   Kd::Ray<double> ray(  x1, x2, x3  //, 1, 0 ,0 );
+      //                        , ( x1 < x1center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+      //                        , ( x2 < x2center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+      //                        , ( x3 < x3center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) );
+      //                        
+      //   iSec = kdTree->intersectRay( ray, Kd::CountRayIntersectionHandler<double>() );
+      //     
+      //   if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+      //   {
+      //      if(iSec == Kd::Intersection::ON_BOUNDARY )
+      //      {
+      //         return true;
+      //      }
+      //      return (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+      //   }
+      //   UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+      //}
+      //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+      int iSec1,iSec2;
+      double eps = 0.05;        
+      Kd::Ray<double> ray1(  x1, x2, x3, 1.0+eps*((double)counter), eps*((double)counter) ,eps*((double)counter) );
+      iSec1 = kdTree->intersectRay( ray1, Kd::CountRayIntersectionHandler<double>() );
+      Kd::Ray<double> ray2(  x1, x2, x3, -1.0-eps*((double)counter), -eps*((double)counter) ,-eps*((double)counter) );
+ 
+      iSec2 = kdTree->intersectRay( ray2, Kd::CountRayIntersectionHandler<double>() );
+
+      if(iSec1 == Kd::Intersection::ON_BOUNDARY || iSec2 == Kd::Intersection::ON_BOUNDARY)
+      {
+         return true;
+      }
+      if( iSec1 == Kd::Intersection::INTERSECT_EDGE && iSec2 == Kd::Intersection::INTERSECT_EDGE) 
+      {
+         //UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.INTERSECT_EDGE");
+
+         if (counter>20) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+         return this->isPointInGbObject3D(x1, x2, x3,(counter+1)); 
+      }
+      else if( iSec1 == Kd::Intersection::INTERSECT_EDGE)
+      {
+         return (iSec2&1);  
+      }
+      else if( iSec2 == Kd::Intersection::INTERSECT_EDGE)
+      {
+         return (iSec1&1);  
+      }
+      else
+      {
+         if((iSec1&1) != (iSec2&1))
+         {
+            //UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.iSec1&1 != iSec2&1");
+
+            if (counter>20) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+            return this->isPointInGbObject3D(x1, x2, x3,(counter+1));
+         }
+         return iSec1&1;
+      }
+      //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+
+   }
+   return false;
+}
+/*======================================================================*/
+bool GbTriFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+{
+  int counter=0;
+
+   if( !nodes->empty() )
+   {
+      //Baum erstellen, wen noch keiner vorhanden
+      if( !kdTree)
+      {
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
+         UbTimer timer; timer.start();
+         if(kdtreeSplitAlg == KDTREE_SAHPLIT     ) 
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SAHSplit<double>()            );
+         }
+         else if(kdtreeSplitAlg == KDTREE_SPATIALSPLIT)
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SpatialMedianSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() ); 
+         }
+         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+      }
+
+      //eigentlicher PIO-Test
+      int iSec;
+      for(int i=0; i<100; i++)
+      {
+         Kd::Ray<double> ray(  x1, x2, x3  //, 1, 0 ,0 );
+                              , ( x1 < x1center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+                              , ( x2 < x2center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+                              , ( x3 < x3center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) );
+                              
+         iSec = kdTree->intersectRay( ray, Kd::CountRayIntersectionHandler<double>() );
+           
+         if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+         {
+            if(iSec == Kd::Intersection::ON_BOUNDARY )
+            {
+               return true;
+            }
+            return (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+         }
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+      }
+      throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+
+   //   int iSec1,iSec2;
+   //      
+   //   Kd::Ray<double> ray1(  x1, x2, x3, 1.0, 0.0 ,0.0 );
+   //   iSec1 = kdTree->intersectRay( ray1, Kd::CountRayIntersectionHandler<double>() );
+   //   Kd::Ray<double> ray2(  x1, x2, x3, -1.0, 0.0 ,0.0 );
+   //   iSec2 = kdTree->intersectRay( ray2, Kd::CountRayIntersectionHandler<double>() );
+
+   //   if(iSec1 == Kd::Intersection::ON_BOUNDARY || iSec2 == Kd::Intersection::ON_BOUNDARY)
+   //   {
+   //      return true;
+   //   }
+   //   if( iSec1 == Kd::Intersection::INTERSECT_EDGE && iSec2 == Kd::Intersection::INTERSECT_EDGE) 
+   //   {
+   //      //UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.INTERSECT_EDGE");
+   //      double eps = UbMath::getEqualityEpsilon<double>();
+   //      if (counter>100) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+   //      return this->isPointInGbObject3D(x1+eps, x2+eps, x3+eps,(counter+1)); 
+   //   }
+   //   else if( iSec1 == Kd::Intersection::INTERSECT_EDGE)
+   //   {
+   //      return (iSec2&1);  
+   //   }
+   //   else if( iSec2 == Kd::Intersection::INTERSECT_EDGE)
+   //   {
+   //      return (iSec1&1);  
+   //   }
+   //   else
+   //   {
+   //      if((iSec1&1) != (iSec2&1))
+   //      {
+   //         UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.iSec1&1 != iSec2&1");
+   //         double eps = UbMath::getEqualityEpsilon<double>();
+   //         if (counter>100) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+   //         return this->isPointInGbObject3D(x1+eps, x2+eps, x3+eps,(counter+1));
+   //      }
+   //      return iSec1&1;
+   //   }
+   //   //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+
+   }
+   return false;
+}
+/*======================================================================*/
+bool GbTriFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+{
+   if( !nodes->empty() )
+   {
+      //Baum erstellen, wen noch keiner vorhanden
+      if( !kdTree)
+      {
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
+         UbTimer timer; timer.start();
+         if(kdtreeSplitAlg == KDTREE_SAHPLIT     ) 
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SAHSplit<double>()            );
+         }
+         else if(kdtreeSplitAlg == KDTREE_SPATIALSPLIT)
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SpatialMedianSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() ); 
+         }
+         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+      }
+
+      //eigentlicher PIO-Test
+      int iSec;
+      for(int i=0; i<100; i++)
+      {
+         Kd::Ray<double> ray(  x1, x2, x3 
+                            , float( ( x1 < x1center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) )
+                            , float( ( x2 < x2center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) )
+                            , float( ( x3 < x3center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) ) );
+
+         iSec = kdTree->intersectRay( ray, Kd::CountRayIntersectionHandler<double>()    );
+
+         if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+         {
+            if(iSec == Kd::Intersection::ON_BOUNDARY )
+            {
+               pointIsOnBoundary = true;
+               return true;
+            }
+            pointIsOnBoundary = false;
+            return (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+         }
+      }
+
+      throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+   }
+   
+   return false;
+}
+/*======================================================================*/
+GbLine3D* GbTriFaceMesh3D::createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"not implemented");
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::write(UbFileOutput* out)
+{
+   out->writeString(this->getCreator()->getTypeID());
+   out->writeInteger((int)kdtreeSplitAlg);
+   out->writeBool(transferViaFilename);
+
+   if(!transferViaFilename)
+   {
+      //nodes
+      vector<Vertex>& vertices = *nodes;
+      out->writeSize_t( nodes->size() );
+      out->writeLine();
+      for(size_t i=0; i<vertices.size(); i++)
+      {
+         Vertex& v = vertices[i];
+         out->writeFloat(v.x);
+         out->writeFloat(v.y);
+         out->writeFloat(v.z);
+         out->writeLine();
+      }
+      
+      //triangles
+      vector<TriFace>& tris = *triangles;
+      out->writeSize_t( tris.size() );
+      out->writeLine();
+      for(size_t i=0; i<tris.size(); i++)
+      {
+         TriFace& t = tris[i];
+         out->writeInteger(t.v1);
+         out->writeInteger(t.v2);
+         out->writeInteger(t.v3);
+         out->writeLine();
+      }
+   }
+   else
+   {
+      out->writeString(filename);
+      out->writeLine();
+      out->writeDouble(transX1);
+      out->writeDouble(transX2);
+      out->writeDouble(transX3);
+
+   }
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::read(UbFileInput* in)
+{
+   kdtreeSplitAlg =  (KDTREE_SPLITAGORITHM)in->readInteger();
+   transferViaFilename = in->readBool();
+
+   if(!transferViaFilename)
+   {
+      if(!nodes) nodes = new vector<Vertex>;
+      //nodes
+      vector<Vertex>& vertices = *nodes;
+      vertices.resize( in->readSize_t( ) );
+      in->readLine();
+      for(size_t i=0; i<vertices.size(); i++)
+      {
+         Vertex& v = vertices[i];
+         v.x = in->readFloat();
+         v.y = in->readFloat();
+         v.z = in->readFloat();
+         in->readLine();
+      }
+
+      //triangles
+      if(!triangles) triangles = new vector<TriFace>;
+      vector<TriFace>& tris = *triangles;
+      tris.resize( in->readSize_t( ) );
+      in->readLine();
+      for(size_t i=0; i<tris.size(); i++)
+      {
+         TriFace& t = tris[i];
+         t.v1 = in->readInteger();
+         t.v2 = in->readInteger();
+         t.v3 = in->readInteger();
+         in->readLine();
+      }
+
+      this->calculateValues();
+   }
+   else
+   {
+      filename = in->readString();
+      in->readLine();
+      transX1 = in->readDouble();
+      transX2 = in->readDouble();
+      transX3 = in->readDouble();
+
+      this->readMeshFromSTLFile(filename, true);
+      this->translate(transX1,transX2,transX3);
+   }
+}
+/*======================================================================*/
+UbTuple<string, string> GbTriFaceMesh3D::writeMesh(string filename, WbWriter* writer, bool writeNormals, vector< string >* datanames, std::vector< std::vector < double > >* nodedata )
+{
+   UBLOG(logINFO, "GbTriFaceMesh3D::writeMesh ");
+
+   vector<UbTupleFloat3 > triNodes(nodes->size());
+   vector<UbTupleInt3 >   tris(triangles->size());
+
+   for(size_t i=0; i<nodes->size(); i++)
+      triNodes[i] = makeUbTuple( (*nodes)[i].x, (*nodes)[i].y, (*nodes)[i].z );
+
+   for(size_t i=0; i<triangles->size(); i++)
+      tris[i] = makeUbTuple( (*triangles)[i].v1, (*triangles)[i].v2, (*triangles)[i].v3 ) ;
+
+   UbTuple<string, string> filenames("","");
+
+   if( !datanames || datanames->empty() || !nodedata  )
+   {
+      val<1>(filenames) = writer->writeTriangles(filename,triNodes,tris);
+   }
+   else
+   {
+      val<1>(filenames) = writer->writeTrianglesWithNodeData(filename,triNodes,tris,*datanames,*nodedata);
+   }
+
+   if(writeNormals)
+   {
+      vector<UbTupleFloat3 > lineNodes(triangles->size()*2);
+      vector<UbTupleInt2 >   lines(triangles->size());
+      for(size_t i=0; i<triangles->size(); i++)
+      {
+         TriFace& triangle = (*triangles)[i];
+         lineNodes[i*2  ] = makeUbTuple( triangle.getX1Centroid(*nodes)
+                                        ,triangle.getX2Centroid(*nodes)
+                                        ,triangle.getX3Centroid(*nodes));
+
+         lineNodes[i*2+1] = makeUbTuple( (float)(triangle.getX1Centroid(*nodes)+1.0*triangle.nx)
+                                        ,(float)(triangle.getX2Centroid(*nodes)+1.0*triangle.ny)
+                                        ,(float)(triangle.getX3Centroid(*nodes)+1.0*triangle.nz));
+
+         lines[i] = makeUbTuple((int)i*2,(int)i*2+1);
+      }
+      val<2>(filenames) = writer->writeLines(filename+"_normals",lineNodes,lines);
+   }
+
+   return filenames;
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::writeMeshPly( const std::string& filename)
+{
+   ofstream out(filename.c_str() );
+   if( !out )
+      throw UbException(UB_EXARGS, "couldn't open " + filename);
+
+   out << "ply" << endl;
+   out << "format ascii 1.0" << endl;
+   out << "element vertex " << (int)nodes->size() << endl;
+   out << "property float x" << endl;
+   out << "property float y" << endl;
+   out << "property float z" << endl;
+   out << "element face " << (int)triangles->size() << endl;
+   out << "property list uchar int vertex_indices" << endl;
+   out << "end_header" << endl;
+
+   for(size_t i=0; i<nodes->size(); i++)
+      out << (*nodes)[i].x << " " << (*nodes)[i].y << " " << (*nodes)[i].z << endl;
+
+   for(size_t i=0; i<triangles->size(); i++)
+      out << "3 " << (*triangles)[i].v1 << " " << (*triangles)[i].v2 << " " << (*triangles)[i].v3 << endl;
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::readMeshFromSTLFile(string filename, bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator::readMeshFromSTLFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   UbFileInputASCII in(filename);
+   //this->nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   //this->triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   double x, y, z;
+   int nr=0;
+
+   in.readLine();
+   while(dummy!="endsolid")
+   {
+      in.readLine();
+      in.readLine();
+      dummy = in.readString();
+      if(dummy!="vertex") throw UbException(UB_EXARGS,"no vertex format");
+      x=in.readDouble();
+      y=in.readDouble();
+      z=in.readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in.readLine();
+      in.readString();
+      x=in.readDouble();
+      y=in.readDouble();
+      z=in.readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in.readLine();
+      in.readString();
+      x=in.readDouble();
+      y=in.readDouble();
+      z=in.readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      triangles->push_back(GbTriFaceMesh3D::TriFace(nr,nr+1,nr+2));
+      in.readLine();
+      in.readLine();
+      in.readLine();
+      dummy = in.readString();
+      nr+=3;
+   }
+   if(removeRedundantNodes)
+   {
+      this->deleteRedundantNodes(); //dort wird autoamtisch calculateValues() aufgerufen
+   }
+   else
+   {
+      this->calculateValues();
+   }
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbTriFaceMesh3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbTriFaceMesh3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..05c3635e95a5d983119a84c77e02eed2fc35856d
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbTriFaceMesh3D.h
@@ -0,0 +1,384 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBTRIFACEMESH3D_H
+#define GBTRIFACEMESH3D_H
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/writer/WbWriter.h>
+
+#include <basics/memory/MbSmartPtr.h>
+
+#include <numerics/geometry3d/GbPoint3D.h> 
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbTriFaceMesh3D;
+typedef VFSharedPtr<GbTriFaceMesh3D> GbTriFaceMesh3DPtr;
+
+
+namespace Kd 
+{ 
+   template< typename T>  class Tree; 
+   template< typename T > class SplitAlgorithm;
+   template< typename T > class RayIntersectionHandler;
+}
+
+
+/*=========================================================================*/
+/* GbTriFaceMesh3D                                                                  */
+/*                                                                         */
+/**
+ * This Class provides the triangular meshes.
+ * Note, that up to now no methods for checking consistency are included.
+ * in this context this class describes facettes from an 3D-object !!!
+*/
+class GbTriFaceMesh3D : public GbObject3D
+{
+public:
+  // nested class start
+   class Vertex
+   {
+   public:
+      Vertex() : x(0.0), y(0.0), z(0.0) { }
+      Vertex(const float& x, const float& y, const float& z) : x(x), y(y),z(z) { }
+      Vertex(Vertex* vert)
+      {
+         this->x = vert->x;
+         this->y = vert->y;
+         this->z = vert->z;
+      }
+      float operator[] (const int&i) const
+      {
+         if     (i==0) return x;
+         else if(i==1) return y;
+         else if(i==2) return z;
+
+         throw UbException(UB_EXARGS,"i not in [0;2]");
+      }
+      float& operator[] (const int& i)
+      {
+         if     (i==0) return x;
+         else if(i==1) return y;
+         else if(i==2) return z;
+
+         throw UbException(UB_EXARGS,"not in [0;2]");
+      }
+      bool operator== (const Vertex& rhs)
+      {
+         return ( fabs(x-rhs.x)<1.E-8 && fabs(y-rhs.y)<1.E-8 && fabs(z-rhs.z)<1.E-8 );
+      }
+      friend inline bool operator<(const Vertex & lhsVert,const Vertex & rhsVert)
+      {
+         if( lhsVert.x < rhsVert.x ) return true;
+         if( lhsVert.x > rhsVert.x ) return false;
+         if( lhsVert.y < rhsVert.y ) return true;
+         if( lhsVert.y > rhsVert.y ) return false;
+         if( lhsVert.z < rhsVert.z ) return true;
+
+         return false;
+      }
+      friend std::ostream& operator<<( std::ostream& os, const Vertex& node )
+      {
+         return os<<node.x<<","<<node.y<<","<<node.z;
+      }
+      Vertex* clone()
+      {
+         return(new Vertex(this));
+      }
+
+#ifdef CAB_RCF
+      template<class Archive>
+      void SF_SERIALIZE(Archive & ar)
+      {
+         ar & x; ar & y; ar & z;
+      }
+#endif //CAB_RCF
+
+   public:
+      float x, y, z;
+   };
+   //////////////////////////////////////////////////////////////////////////
+   class TriFace
+   {
+   public:
+      TriFace()
+         : v1(-1), v2(-1), v3(-1), nx(0.0), ny(0.0), nz(0.0)
+      {
+
+      }
+      TriFace(const int& v1, const int& v2, const int& v3)
+         : v1(v1), v2(v2), v3(v3), nx(0.0), ny(0.0), nz(0.0)
+      {
+      }
+
+      const int& getIndexVertex1() const { return v1; }
+      const int& getIndexVertex2() const { return v2; }
+      const int& getIndexVertex3() const { return v3; }
+
+      Vertex& getNode(const int& i, std::vector<Vertex>& nodes)
+      {
+         if(i==0) return nodes[v1];
+         if(i==1) return nodes[v2];
+         if(i==2) return nodes[v3];
+         throw UbException(UB_EXARGS,"invalid i - not in range [0;2]");
+      }
+      void setNode(const int& i, const int& index)
+      {
+         if     (i==0) v1=index;
+         else if(i==1) v2=index;
+         else if(i==2) v3=index;
+         else throw UbException(UB_EXARGS,"invalid i - not in range [0;2]");
+      }
+
+      int operator[] (int index)
+      { 
+         if(index==0) return v1;
+         if(index==1) return v2;
+         if(index==2) return v3;
+         throw UbException(UB_EXARGS,"invalid i - not in range [0;2]");
+      }
+
+      float& getV1x(std::vector<Vertex>& nodes) { return nodes[v1].x; }
+      float& getV1y(std::vector<Vertex>& nodes) { return nodes[v1].y; }
+      float& getV1z(std::vector<Vertex>& nodes) { return nodes[v1].z; }
+
+      float& getV2x(std::vector<Vertex>& nodes) { return nodes[v2].x; }
+      float& getV2y(std::vector<Vertex>& nodes) { return nodes[v2].y; }
+      float& getV2z(std::vector<Vertex>& nodes) { return nodes[v2].z; }
+
+      float& getV3x(std::vector<Vertex>& nodes) { return nodes[v3].x; }
+      float& getV3y(std::vector<Vertex>& nodes) { return nodes[v3].y; }
+      float& getV3z(std::vector<Vertex>& nodes) { return nodes[v3].z; }
+
+      float getMinX(std::vector<Vertex>& nodes) { return (float)UbMath::min(nodes[v1].x,nodes[v2].x,nodes[v3].x); }
+      float getMinY(std::vector<Vertex>& nodes) { return (float)UbMath::min(nodes[v1].y,nodes[v2].y,nodes[v3].y); }
+      float getMinZ(std::vector<Vertex>& nodes) { return (float)UbMath::min(nodes[v1].z,nodes[v2].z,nodes[v3].z); }
+
+      float getMaxX(std::vector<Vertex>& nodes) { return (float)UbMath::max(nodes[v1].x,nodes[v2].x,nodes[v3].x); }
+      float getMaxY(std::vector<Vertex>& nodes) { return (float)UbMath::max(nodes[v1].y,nodes[v2].y,nodes[v3].y); }
+      float getMaxZ(std::vector<Vertex>& nodes) { return (float)UbMath::max(nodes[v1].z,nodes[v2].z,nodes[v3].z); }
+
+      float getX1Centroid(std::vector<Vertex>& nodes) {return (float)UbMath::c1o3 * (getV1x(nodes)+getV2x(nodes)+getV3x(nodes)); }
+      float getX2Centroid(std::vector<Vertex>& nodes) {return (float)UbMath::c1o3 * (getV1y(nodes)+getV2y(nodes)+getV3y(nodes)); }
+      float getX3Centroid(std::vector<Vertex>& nodes) {return (float)UbMath::c1o3 * (getV1z(nodes)+getV2z(nodes)+getV3z(nodes)); }
+
+      double calculateDistanceToPoint3D(const double& x1, const double& x2, const double& x3, std::vector<Vertex>& nodes);
+
+      double getArea(std::vector<Vertex>& nodes)
+      {
+         //GbVector3D A(nodes[v1].x, nodes[v1].y, nodes[v1].z);
+         //GbVector3D B(nodes[v2].x, nodes[v2].y, nodes[v2].z);
+         //GbVector3D C(nodes[v3].x, nodes[v3].y, nodes[v3].z);
+         //GbVector3D AB = B-A;
+         //GbVector3D AC = C-A;
+         //GbVector3D N = AB.Cross(AC);
+         //return 0.5*N.Length();
+         UbMath::Vector3D A(nodes[v1].x, nodes[v1].y, nodes[v1].z);
+         UbMath::Vector3D B(nodes[v2].x, nodes[v2].y, nodes[v2].z);
+         UbMath::Vector3D C(nodes[v3].x, nodes[v3].y, nodes[v3].z);
+         UbMath::Vector3D AB = B-A;
+         UbMath::Vector3D AC = C-A;
+         UbMath::Vector3D N = AB.Cross(AC);
+         return 0.5*N.Length();
+      }
+      void calculateNormal(std::vector<Vertex>& nodes)
+      {
+         const float& v1x = nodes[v1].x; const float& v1y = nodes[v1].y; const float& v1z = nodes[v1].z;
+         const float& v2x = nodes[v2].x; const float& v2y = nodes[v2].y; const float& v2z = nodes[v2].z;
+         const float& v3x = nodes[v3].x; const float& v3y = nodes[v3].y; const float& v3z = nodes[v3].z;
+
+         nx = ( v3z - v1z) * ( v2y - v1y ) - ( v2z - v1z) * ( v3y - v1y );
+         ny = ( v2z - v1z) * ( v3x - v1x ) - ( v2x - v1x) * ( v3z - v1z );
+         nz = ( v2x - v1x) * ( v3y - v1y ) - ( v2y - v1y) * ( v3x - v1x );
+
+         float length = std::sqrt( nx*nx + ny*ny + nz*nz );
+         if(length>1.E-10)
+         {
+            length = 1.0f/length;
+            nx *= length;
+            ny *= length;
+            nz *= length;
+         }
+         else 
+         {
+            std::cerr<<"GbTriFaceMesh3D::TriFace - calculateNormal: nx=ny=nz=0 -> kann nich sein "
+                     <<"(dreieck hat evtl knoten doppelt oder ist ne Linie)"
+                     <<"->removeRedunantNodes"<<std::endl;
+         }
+      }
+   #ifdef CAB_RCF
+      template<class Archive>
+      void SF_SERIALIZE(Archive & ar)
+      {
+         ar & v1; ar & v2; ar & v3;
+      }
+   #endif //CAB_RCF
+
+   public:
+      int   v1, v2, v3;
+      float nx, ny, nz;
+   };
+
+public:
+  enum KDTREE_SPLITAGORITHM { KDTREE_SAHPLIT, KDTREE_SPATIALSPLIT };
+
+public:
+   GbTriFaceMesh3D();
+   GbTriFaceMesh3D(std::string name, std::vector<Vertex>* nodes, std::vector<TriFace>* triangles, KDTREE_SPLITAGORITHM splitAlg = KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+	~GbTriFaceMesh3D();
+
+   GbTriFaceMesh3D* clone();// { throw UbException(UB_EXARGS,"not implemented"); }
+   void finalize() {}
+
+   //void setRegardPointInPolyhedronTest(bool value) { this->regardPiO=value; }
+
+   std::string toString();
+
+   //std::string getName();
+   std::vector<Vertex>*  getNodes();
+   std::vector<TriFace>* getTriangles();
+   
+   void setTransferViaFilename(bool transferViaFilename, std::string filename, double transX1, double transX2, double transX3)
+   {
+      this->filename = filename;
+      this->transferViaFilename = transferViaFilename;
+      this->transX1 = transX1;
+      this->transX2 = transX2;
+      this->transX3 = transX3;
+   }
+   void readMeshFromSTLFile(std::string filename, bool removeRedundantNodes);
+
+   double getX1Minimum()  { if(!this->consistent) this->calculateValues(); return this->x1min;    }
+   double getX1Maximum()  { if(!this->consistent) this->calculateValues(); return this->x1max;    }
+   double getX1Centroid() { if(!this->consistent) this->calculateValues(); return this->x1center; }
+
+   double getX2Minimum()  { if(!this->consistent) this->calculateValues(); return this->x2min;    }
+   double getX2Maximum()  { if(!this->consistent) this->calculateValues(); return this->x2max;    }
+   double getX2Centroid() { if(!this->consistent) this->calculateValues(); return this->x2center; }
+   
+   double getX3Minimum()  { if(!this->consistent) this->calculateValues(); return this->x3min;    }
+   double getX3Centroid() { if(!this->consistent) this->calculateValues(); return this->x3center; }
+   double getX3Maximum()  { if(!this->consistent) this->calculateValues(); return this->x3max;    }
+
+   void   calculateValues();
+
+   double getVolume();
+   void   deleteRedundantNodes();
+
+   UbTupleDouble6 calculateMomentOfInertia(double rhoP);
+   UbTupleDouble3 calculateCenterOfGravity();
+
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+
+
+   void scale(const double& sx1, const double& sx2, const double& sx3);
+   void rotate(const double& alpha, const double& beta, const double& gamma);
+   void rotateAroundPoint(const double& px1, const double& px2, const double& px3, const double& alpha, const double& beta, const double& gamma);
+   void translate(const double& x1, const double& x2, const double& x3);
+   void reflectAcrossXYLine(const double& alpha);
+
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, int counter);
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary);
+
+   virtual GbLine3D* createClippedLine3D (GbPoint3D &point1,GbPoint3D &point2);
+
+   virtual std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+
+   std::vector<GbTriFaceMesh3D::TriFace*> getTrianglesForVertex(Vertex* vertex);
+
+   void setKdTreeSplitAlgorithm(KDTREE_SPLITAGORITHM mode); 
+   KDTREE_SPLITAGORITHM getKdTreeSplitAlgorithm() { return this->kdtreeSplitAlg; }
+   Kd::Tree<double>* getKdTree() { return this->kdTree; }
+
+   virtual ObObjectCreator* getCreator();
+
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);  
+
+   virtual UbTuple<std::string, std::string> writeMesh(std::string filename, WbWriter* writer, bool writeNormals=false, std::vector< std::string >* datanames=NULL, std::vector< std::vector < double > >* nodedata=NULL );
+   void writeMeshPly( const std::string& filename);
+
+   /*======================================================================*/
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & kdtreeSplitAlg;
+      ar & transferViaFilename;
+      if(!transferViaFilename)
+      {
+         ar & nodes;
+         ar & triangles;
+      }
+      else
+      {
+         ar & filename;
+         ar & transX1;
+         ar & transX2;
+         ar & transX3;
+         if(ArchiveTools::isReading(ar) ) 
+         {
+            this->readMeshFromSTLFile(filename, true);
+            this->translate(transX1,transX2,transX3);
+         }
+      }
+      
+      if(ArchiveTools::isReading(ar)) this->calculateValues();
+   }
+#endif //CAB_RCF
+
+protected:
+   KDTREE_SPLITAGORITHM kdtreeSplitAlg;
+   void init();
+
+   std::vector<Vertex>*  nodes;
+   std::vector<TriFace>* triangles;
+   //for transfer
+   std::string filename;
+   bool transferViaFilename;
+   double transX1;
+   double transX2;
+   double transX3;
+
+   double x1min;
+   double x1max;
+   double x2min;
+   double x2max;
+   double x3min;
+   double x3max;
+   double x1center;
+   double x2center;
+   double x3center;
+
+   bool   consistent;
+
+   bool buildVertTriRelationMap;
+   std::multimap<Vertex*,TriFace*> relationVertTris;
+
+   Kd::Tree< double >* kdTree;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbTriFaceMesh3D  >("GbTriFaceMesh3D  ")     , SF_GbTriFaceMesh3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbTriFaceMesh3D >() ), SF_GbTriFaceMesh3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //GBTRIFACEMESH3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbTriangle3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbTriangle3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f3edda2240522d65a212729acaf258da4fcc94e6
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbTriangle3D.cpp
@@ -0,0 +1,1229 @@
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/creator/GbTriangle3DCreator.h>
+
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+//#include <numerics/geometry3d/GbPolygon3D.h>                                  
+
+using namespace std;
+
+ObObjectCreator* GbTriangle3D::getCreator()
+{
+   return GbTriangle3DCreator::getInstance();
+}
+
+/*=========================================================================*/
+/* GbTriangle3D                                                            */
+/*                                                                         */
+/*
+* This Class provides basic 3D triangle objects.
+* The describing points are observed by 2D triangle objects.
+* <BR><BR><HR>
+* @version 1.0 - 24.01.05
+*/                                                                  
+
+GbTriangle3D::GbTriangle3D()
+{
+   this->init();
+   this->consistent = false;
+}
+/*======================================================================*/
+/*
+* Creates an empty 2D triangle with the specified points.
+* @param point1 the 1st point
+* @param point2 the 2nd point
+* @param point3 the 3nd point
+*/
+GbTriangle3D::GbTriangle3D(GbPoint3D* point1, GbPoint3D* point2, GbPoint3D* point3)
+{
+   this->init();
+   this->points[0] = point1;
+   this->points[1] = point2;
+   this->points[2] = point3;
+
+   this->calculateNormal();
+   this->consistent = false;
+
+   this->points[0]->addObserver(this);
+   this->points[1]->addObserver(this);
+   this->points[2]->addObserver(this);
+   
+   //this.po        = new PointObserver(this);
+   //this.points[0].addObserver(this.po);
+   //this.points[1].addObserver(this.po);
+   //this.points[2].addObserver(this.po);
+}
+/*======================================================================*/
+/*
+* Creates a 3D triangle as clone of the specified 2D triangle.
+* @param triangle the 3D triangle to be cloned
+*/
+GbTriangle3D::GbTriangle3D(GbTriangle3D* triangle)
+{
+   this->init();
+   this->points[0] = triangle->points[0]->clone();
+   this->points[1] = triangle->points[1]->clone();
+   this->points[2] = triangle->points[2]->clone();
+
+   this->consistent = false;
+   this->calculateNormal();
+   this->calculateValues();
+}
+/*======================================================================*/
+GbTriangle3D::~GbTriangle3D()
+{
+   if(this->points[0]) this->points[0]->removeObserver(this);
+   if(this->points[1]) this->points[1]->removeObserver(this);
+   if(this->points[2]) this->points[2]->removeObserver(this);
+}
+/*======================================================================*/
+void GbTriangle3D::deletePoints()
+{ 
+   if(points[0]) { delete points[0]; points[0]=NULL;}
+   if(points[1]) { delete points[1]; points[1]=NULL;}
+   if(points[2]) { delete points[2]; points[2]=NULL;}
+}
+
+/*======================================================================*/
+/*  Methoden                                                            */
+/*                                                                      */
+/*
+* Creates a 3D triangle as clone of this 3D triangle.
+*/
+GbTriangle3D* GbTriangle3D::clone()
+{
+   return(new GbTriangle3D(this));
+}
+/*======================================================================*/
+/*
+* Returns the number of times this 2D triangle contains the specified point.
+* @param point the point
+* @return the number of times this 2D triangle contains the specified point
+*/
+int GbTriangle3D::contains(GbPoint3D* point)
+{
+   int n = 0;
+   for(int i=0; i<3; i++) if(this->points[i]->equals(point)) n++;
+   return(n);
+}
+/*======================================================================*/
+/*
+* Returns the number of times this 2D triangle contains a point equal to the specified point.
+* @param point the point
+* @return the number of times this 2D triangle contains a point equal to the specified point
+*/
+int GbTriangle3D::containsEqual(GbPoint3D* point)
+{
+   int n = 0;
+   for(int i=0; i<3; i++) if(this->points[i]->equals(point)) n++;
+   return(n);
+}
+/*======================================================================*/
+/*
+* Returns the specified point.
+* @param index the index (must be 0, 1, or 2)
+* @return the specified point
+* @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+*/
+GbPoint3D* GbTriangle3D::getPoint(const int& index) 
+{
+   if(index < 0 || index > 2) throw UbException(UB_EXARGS,"invalid index specified: ");
+   return((this->points[index]));
+}
+/*======================================================================*/
+vector<GbPoint3D> GbTriangle3D::getPoints() 
+{
+   vector<GbPoint3D> p(3);
+   p[0] = *(points[0]);
+   p[1] = *(points[1]);
+   p[2] = *(points[2]);
+   return p;
+   //
+   //vector<GbPoint3D> p(3);// = new vector<GbPoint3D*>;
+   //p.resize(3);//, NULL);
+   //p[0] = this->points[0];
+   //p[1] = this->points[1];
+   //p[2] = this->points[2];
+   //return(p);
+}
+/*======================================================================*/
+/*
+* Returns the area of this triangle.
+* The area is positive for positive ordered points, otherwise negative.
+* @return the area of this triangle
+*/
+double GbTriangle3D::getArea()
+{
+   if(!this->consistent) this->calculateValues();
+   // throw UbException(UB_EXARGS,"not correct calculated ...");
+   return(this->area);
+}
+/*
+* Returns the centroid x1 coordinate of this triangle.
+* @return the centroid x1 coordinate of this triangle
+*/
+double GbTriangle3D::getX1Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1s);
+}
+/*
+* Returns the minimum x1 coordinate of this triangle.
+* @return the minimum x1 coordinate of this triangle
+*/
+double GbTriangle3D::getX1Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1min);
+}
+/*
+* Returns the maximum x1 coordinate of this triangle.
+* @return the maximum x1 coordinate of this triangle
+*/
+double GbTriangle3D::getX1Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1max);
+}
+/*
+* Returns the centroid x2 coordinate of this triangle.
+* @return the centroid x2 coordinate of this triangle
+*/
+double GbTriangle3D::getX2Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2s);
+}
+/*                                                         
+* Returns the minimum x2 coordinate of this triangle.
+* @return the minimum x2 coordinate of this triangle
+*/
+double GbTriangle3D::getX2Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2min);
+}
+/*
+* Returns the maximum x2 coordinate of this triangle.
+* @return the maximum x2 coordinate of this triangle
+*/
+double GbTriangle3D::getX2Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2max);
+}
+double GbTriangle3D::getX3Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3s);
+}
+double GbTriangle3D::getX3Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3min);
+}
+double GbTriangle3D::getX3Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3max);
+}
+
+/*
+* Sets the specified point.
+* @param point the point
+* @param index the index (must be 0, 1, or 2)
+* @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+*/
+void GbTriangle3D::setPoint(GbPoint3D* point, int index) 
+{
+   if(index < 0 || index > 2) throw UbException(UB_EXARGS,"invalid index specified: ");
+   this->points[index] = point;
+   this->consistent    = false;
+   this->calculateNormal();
+}
+
+/*
+* Returns true if this 2D triangle equals the specified object.
+* Two triangle are equal, if their points are equal.
+* <BR>Note that the order of points is not recognized!
+* @return true if this 2D triangle equals the specified object
+* @see GbPoint2D#equals(java.lang.Object)
+* @see GbPoint3D#equals(java.lang.Object)
+*/
+//bool equals(GbObject3D *object)
+//{
+//   try
+//   {
+//      GbTriangle3D *triangle = (GbTriangle3D*) object;
+
+//if(this.points[0].equals(triangle.points[0]))
+//{
+//   if(this.points[1].equals(triangle.points[1]) && this.points[2].equals(triangle.points[2])) return(true);
+//   if(this.points[1].equals(triangle.points[2]) && this.points[2].equals(triangle.points[1])) return(true);
+//   return(false);
+//}
+//else if(this.points[0].equals(triangle.points[1]))
+//{
+//   if(this.points[1].equals(triangle.points[0]) && this.points[2].equals(triangle.points[2])) return(true);
+//   if(this.points[1].equals(triangle.points[2]) && this.points[2].equals(triangle.points[0])) return(true);
+//   return(false);
+//}
+//else if(this.points[0].equals(triangle.points[2]))
+//{
+//   if(this.points[1].equals(triangle.points[0]) && this.points[2].equals(triangle.points[1])) return(true);
+//   if(this.points[1].equals(triangle.points[1]) && this.points[2].equals(triangle.points[0])) return(true);
+//   return(false);
+//}
+//return(false);
+//    }
+//    catch(Exception e){ return(false); }
+// }
+/*
+* Returns the surface triangle set with new nodes !!!
+* @returns the surface triangle set with new nodes !!!
+*/
+vector<GbTriangle3D*> GbTriangle3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles;
+   
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(getPoint1()),new GbPoint3D(getPoint2()),new GbPoint3D(getPoint3())));
+
+   return triangles;
+}
+
+
+/*
+* Returns the string representation of the triangle
+* @returns the string representation of the triangle
+*/
+
+string GbTriangle3D::toString()
+{
+   stringstream ss;
+   ss<<"GbTriangle3D[area=";
+   ss<<this->getArea();
+
+   ss<<", x1s="<<this->x1s;
+   ss<<", x2s="<<this->x2s;
+   ss<<", x3s="<<this->x3s;
+   ss<<", x1min="<<this->x1min;
+   ss<<", x1max="<<this->x1max;
+   ss<<", x2min="<<this->x2min;
+   ss<<", x2max="<<this->x2max;
+   ss<<", x3min="<<this->x3min;
+   ss<<", x3max="<<this->x3max;
+   ss<<", points1="<<this->points[0]->toString();
+   ss<<", points2="<<this->points[1]->toString();
+   ss<<", points3="<<this->points[2]->toString();
+   ss<<"]";
+   return((ss.str()).c_str());
+}
+/*======================================================================*/
+double GbTriangle3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   //e1 = v1 - v0
+   double e1x1 = this->points[1]->x1-this->points[0]->x1;
+   double e1x2 = this->points[1]->x2-this->points[0]->x2;
+   double e1x3 = this->points[1]->x3-this->points[0]->x3;  
+
+   //e2 = v2 - v0
+   double e2x1 = this->points[2]->x1-this->points[0]->x1;
+   double e2x2 = this->points[2]->x2-this->points[0]->x2;
+   double e2x3 = this->points[2]->x3-this->points[0]->x3;  
+
+   //p = d x e2
+   double px1 = rx2*e2x3 - rx3*e2x2;
+   double px2 = rx3*e2x1 - rx1*e2x3;
+   double px3 = rx1*e2x2 - rx2*e2x1;
+
+   //a = e1 dot p
+   double a = e1x1*px1 + e1x2*px2 + e1x3*px3;
+   if(fabs(a)<1.E-10) return -1.0;
+   double f = 1.0/a;
+
+   //s = o - v0
+   double sx1 = x1 - this->points[0]->x1;
+   double sx2 = x2 - this->points[0]->x2;
+   double sx3 = x3 - this->points[0]->x3;
+
+   //u = f * ( s dot p)
+   double u = f * ( sx1*px1 + sx2*px2 + sx3*px3 );
+   if(u<-1.E-10 || u>1.0+1.E-10) return -1.0;
+
+   //q = s x e1
+   double qx1 = sx2*e1x3 - sx3*e1x2;
+   double qx2 = sx3*e1x1 - sx1*e1x3;
+   double qx3 = sx1*e1x2 - sx2*e1x1;
+
+   //v = f*(e2 dot q)
+   double v = f * (rx1*qx1 + rx2*qx2 + rx3*qx3);
+   if(v<-1.E-10 || (u+v)>1.0+1.E-10) return -1.0;
+
+   //t = f * (e2 dot q)
+   return f * (e2x1*qx1 + e2x2*qx2 + e2x3*qx3);
+}
+
+/*======================================================================*/
+/*  Calculation                                                         */
+/*                                                                      */
+/*
+* Returns the intersection points of this 2D triangle and the specified 2D line.
+* @param line the 2D line to intersect
+* @return the intersection points of this 2D triangle and the specified 2D line
+*/
+/*
+vector<GbPoint3D> GbTriangle3D::calculateIntersectionPoints3D(GbLine3D *line)
+{
+//throw UbException(UB_EXARGS,"not yet implemented");	
+
+GbSystem::PointSet3 pointSet(0);
+GbPoint3D          *pCrossed = NULL;
+
+pCrossed = GbSystem::calculateIntersectionPoint3D(*this->points[0], *this->points[1], *line->getPoint1(), *line->getPoint2());
+if(pCrossed != NULL) pointSet.addUnequal(pCrossed);
+pCrossed = GbSystem::calculateIntersectionPoint3D(*this->points[1], *this->points[2], *line->getPoint1(), *line->getPoint2());
+if(pCrossed != NULL) pointSet.addUnequal(pCrossed);
+pCrossed = GbSystem::calculateIntersectionPoint3D(*this->points[2], *this->points[0], *line->getPoint1(), *line->getPoint2());
+if(pCrossed != NULL) pointSet.addUnequal(pCrossed);
+//vector<GbPoint3D> points = pointSet->getPoints();
+return(pointSet.getPoints());
+}
+*/
+/*===========================================================*/
+
+GbLine3D* GbTriangle3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   GbPoint3D *result = this->calculateIntersectionPoints3D(&point1, &point2);
+   if(!result) return NULL;
+
+   return new GbLine3D(result, new GbPoint3D(point2));
+
+   //return GbSystem::createClipLine3D(point1, point2,
+      //p1->getX1Coordinate(),p1->getX2Coordinate(),p1->getX3Coordinate(),
+      //p2->getX1Coordinate(),p2->getX2Coordinate(),p2->getX3Coordinate() );
+}
+
+//von Navodit ...
+/*===========================================================*/
+GbPoint3D* GbTriangle3D::calculateIntersectionPoints3D(GbLine3D* line)
+{
+   return this->calculateIntersectionPoints3D(line->getPoint1(), line->getPoint2());
+}
+/*===========================================================*/
+GbPoint3D* GbTriangle3D::calculateIntersectionPoints3D(GbPoint3D* linePoint1, GbPoint3D* linePoint2)
+{
+   GbVector3D Point1(linePoint1->x1, linePoint1->x2, linePoint1->x3);
+   GbVector3D Point2(linePoint2->x1, linePoint2->x2, linePoint2->x3);
+   GbVector3D direction = Point2-Point1;
+   GbVector3D GbPoint3D1(this->getPoint1()->x1,this->getPoint1()->x2,this->getPoint1()->x3);
+   GbVector3D GbPoint3D2(this->getPoint2()->x1,this->getPoint2()->x2,this->getPoint2()->x3);
+   GbVector3D GbPoint3D3(this->getPoint3()->x1,this->getPoint3()->x2,this->getPoint3()->x3);
+   GbVector3D V2V1 = GbPoint3D2-GbPoint3D1;
+   GbVector3D V3V1 = GbPoint3D3-GbPoint3D1;
+   GbVector3D V2V1V3V1 = V2V1.Cross(V3V1);
+   V2V1V3V1.Normalize();
+   GbVector3D Normal = V2V1V3V1;
+
+   double d = -Normal.Dot(GbPoint3D1);            
+   double denom = Normal.Dot(direction);       
+
+   if (UbMath::zero(denom)) return NULL;   //line does not intersect the plane of the triangle !
+   else
+   {
+      double mu = -1.*(d + Point1.Dot(Normal))/denom;            //mu = -(d+ Normal.Point1)/denom
+
+      //   GbVector3D p1 = Point2-Point1;
+      //   GbVector3D p2 = p1*mu;
+      //   GbVector3D p3 = Point1+p2;
+      GbVector3D point = Point1 + mu*(Point2 -Point1);
+
+      if (mu<0.0 || mu>1.0)    return NULL;     // Point of intersection of line and plane does not lie on the triangle   
+      else
+      {
+         //Test whether Point lies inside the triangle or not
+         bool test=true;
+         GbVector3D a = GbPoint3D1-point;
+         GbVector3D b = GbPoint3D2-point;
+         GbVector3D c = GbPoint3D3-point;
+         GbVector3D ab = a.Cross(b);
+         GbVector3D bc = b.Cross(c);
+         GbVector3D ca = c.Cross(a);
+         GbVector3D Q1 = ab*0.5;
+         GbVector3D Q2 = bc*0.5;
+         GbVector3D Q3 = ca*0.5;
+         GbVector3D Q1Q2 = Q1+Q2;
+         GbVector3D Q = Q1Q2+Q3;
+
+         if (UbMath::less(Q.Dot(Q1), 0.0)) test = false; 
+         if (UbMath::less(Q.Dot(Q2), 0.0)) test = false; 
+         if (UbMath::less(Q.Dot(Q3), 0.0)) test = false; 
+
+         if (test == true) return (new GbPoint3D(point.X1(), point.X2(), point.X3()));
+         else          return NULL;
+      }
+   }
+}
+
+/**
+* Returns the distance between the 3D triangle and the specified 3D Point                                                                      
+* @param point the 3D point from whom the distance is to be calculated
+* @return the distance of the specified point from the triangle
+*/
+double GbTriangle3D::calculateDistanceToPoint3D(GbPoint3D *point) 
+{
+   return this->calculateDistanceToPoint3D(point->x1, point->x2, point->x3);
+}
+/*=======================================================================*/
+double GbTriangle3D::calculateDistanceToPoint3D(const double& x1, const double& x2, const double& x3) 
+{
+   //
+   //throw UbException(UB_EXARGS,"Ich glaub GbTriangle3D::calculateDistanceToPoint3D(...) kann man so nicht nehmen,jedenfalls nicht fuer die q's");
+   cout<<"??? ch glaub GbTriangle3D::calculateDistanceToPoint3D(...) kann man so nicht nehmen,jedenfalls nicht fuer die q's"<<endl;
+   GbVector3D P0(x1, x2, x3);
+   GbVector3D P1(this->points[0]->x1, this->points[0]->x2, this->points[0]->x3);
+   GbVector3D P2(this->points[1]->x1, this->points[1]->x2, this->points[1]->x3);
+   GbVector3D P3(this->points[2]->x1, this->points[2]->x2, this->points[2]->x3);
+
+   //Determine normal to triangle
+   GbVector3D Normal = (P1-P2).Cross(P1-P3);
+   double alpha = UbMath::ACos((P1-P0).Dot(Normal)/((P1-P0).Length()*Normal.Length()));
+
+   double P0P0dash = (P0-P1).Length()*cos(alpha);
+   Normal.Normalize();
+   GbVector3D Projection = Normal*(-P0P0dash);
+
+   GbVector3D P0dash = P0+Projection;
+
+   //Check if point P0dash lies within the triangle P1P2P3.
+   bool test = false;
+   if ( ((P1-P0).Cross(P2-P0)).Dot(Normal) > 0 ) test = true;
+   if ( ((P2-P0).Cross(P3-P0)).Dot(Normal) > 0 ) test = true;
+   if ( ((P3-P0).Cross(P1-P0)).Dot(Normal) > 0 ) test = true;
+
+   if (test == true) return (P0-P0dash).Length();
+   else
+   // Determine the distance of point P0 from all edges and vertices and return the minimum distance
+   {
+      double dP0P1 = (P0-P1).Length(); //Distance of Point P0 from Point P1
+      double dP0P2 = (P0-P2).Length(); //Distance of Point P0 from Point P2
+      double dP0P3 = (P0-P3).Length(); //Distance of Point P0 from Point P3
+
+      GbVector3D MP1P2 = P2-P1;        //Direction vector for line P1P2
+      GbVector3D MP2P3 = P3-P2;        //Direction vector for line P2P3
+      GbVector3D MP3P1 = P1-P3;        //Direction vector for line P3P1
+
+      double tP1P2 = MP1P2.Dot(P0-P1) / MP1P2.Dot(MP1P2);
+      double tP2P3 = MP2P3.Dot(P0-P2) / MP2P3.Dot(MP2P3);
+      double tP3P1 = MP3P1.Dot(P0-P3) / MP3P1.Dot(MP3P1);
+
+      double dP1P2 = (P0-(P1+(MP1P2*tP1P2))).Length(); //Distance of Point P0 from line P1P2
+      double dP2P3 = (P0-(P2+(MP2P3*tP2P3))).Length(); //Distance of Point P0 from line P2P3
+      double dP3P1 = (P0-(P3+(MP3P1*tP3P1))).Length(); //Distance of Point P0 from line P3P1
+
+      double distanceP0[6]; //Array to store all the distances from Point P0
+      distanceP0[0] = dP0P1; 
+      distanceP0[1] = dP0P2; 
+      distanceP0[2] = dP0P3; 
+      distanceP0[3] = dP1P2; 
+      distanceP0[4] = dP2P3; 
+      distanceP0[5] = dP3P1; 
+
+      double d = 0.0;
+      //Find the minimum distance from Point P0
+      for (int i=0; i<6; i++)
+      {
+         if(distanceP0[i]<d) d = distanceP0[i];
+      }
+      return d;
+   }
+}
+/**
+* Returns the normalized distance between the 3D triangle and the specified 3D Point
+* copied from Benjamin A.
+* @param point the 3D point from whom the distance is to be calculated
+* @return the distance of the specified point from the triangle
+*/
+double GbTriangle3D::calculateNormalizedDistanceToPoint3D(const double& x1, const double& y1, const double& z1, 
+                                                          const double& x2, const double& y2, const double& z2)
+{
+    //face* pf
+    double xa, xb, xc, ya, yb, yc, za, zb, zc;
+    //double xp, yp, zp;
+    double tt=0, xi=0, eta=0;
+    double zaehler, nenner;
+    double wurzel3 = sqrt(3.);
+
+    //Weltkoordinaten der Dreiecke
+    xa = this->points[0]->x1;
+    xb = this->points[1]->x1;
+    xc = this->points[2]->x1;
+         
+    ya = this->points[0]->x2;
+    yb = this->points[1]->x2;
+    yc = this->points[2]->x2;
+
+    za = this->points[0]->x3;
+    zb = this->points[1]->x3;
+    zc = this->points[2]->x3;
+
+    //Shape-Funktionen zum Berechnen der Schnittpunkte
+    zaehler =
+       static_cast<double>(((-1.0*zc+zb)*ya+(yc-1.0*yb)*za+zc*yb-1.0*zb*yc)*x1
+       +((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y1+((-1.0*yc+yb)*xa
+       +(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z1+((-1.0*zc+zb)*ya+(yc-1.0*yb)*za
+       +zc*yb-1.0*zb*yc)*x2+((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2
+       +((-1.0*yc+yb)*xa+(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z2+(2.0*zb*yc-2.0*zc*yb)*xa
+       +(2.0*xb*zc-2.0*xc*zb)*ya+(-2.0*xb*yc+2.0*xc*yb)*za);
+    nenner  =
+       static_cast<double>((((-1.0*zc+zb)*ya+(yc-1.0*yb)*za+zc*yb-1.0*zb*yc)*x1
+       +((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y1+((-1.0*yc+yb)*xa
+       +(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z1+((-1.0*zb+zc)*ya+(-1.0*yc+yb)*za-1.0*zc*yb+zb*yc)
+       *x2+((-1.0*zc+zb)*xa+(-1.0*xb+xc)*za+xb*zc-1.0*xc*zb)*y2+((yc-1.0*yb)*xa+(xb
+       -1.0*xc)*ya+xc*yb-1.0*xb*yc)*z2));
+    if( UbMath::greater(nenner, 0.0) ) tt = zaehler/nenner;
+    else tt=-999.;
+
+    zaehler =
+       static_cast<double>(((-2.0*zc+za+zb)*y2+(-1.0*yb-1.0*ya+2.0*yc)*z2+zc*ya
+       -1.0*zb*yc+zc*yb-1.0*za*yc)*x1+((-1.0*za+2.0*zc-1.0*zb)*x2+(xa-2.0*xc+xb)*z2
+       -1.0*xa*zc-1.0*xb*zc+xc*za+xc*zb)*y1+((-2.0*yc+ya+yb)*x2+(-1.0*xa-1.0*xb+2.0*xc)
+       *y2-1.0*xc*yb+xa*yc+xb*yc-1.0*xc*ya)*z1+(zb*yc-1.0*zc*ya-1.0*zc*yb+za*yc)
+       *x2+(-1.0*xc*za+xb*zc+xa*zc-1.0*xc*zb)*y2+(xc*yb-1.0*xa*yc-1.0*xb*yc+xc*ya)*z2);
+    nenner  =
+       static_cast<double>((((zc-1.0*zb)*ya+(yb-1.0*yc)*za+zb*yc-1.0*zc*yb)*x1
+       +((zb-1.0*zc)*xa+(xc-1.0*xb)*za-1.0*xc*zb+xb*zc)*y1+((-1.0*yb+yc)*xa+(xb-1.0*xc)
+       *ya-1.0*xb*yc+xc*yb)*z1+((zb-1.0*zc)*ya+(-1.0*yb+yc)*za+zc*yb-1.0*zb*yc)*x2
+       +((zc-1.0*zb)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2+((yb-1.0*yc)*xa
+       +(xc-1.0*xb)*ya+xb*yc-1.0*xc*yb)*z2));
+    if( UbMath::greater(nenner, 0.0) ) xi = zaehler/nenner;
+    else xi=-999.;
+
+    zaehler =
+       static_cast<double>(((za-1.0*zb)*y2+(-1.0*ya+yb)*z2-1.0*za*yb+zb*ya)*x1+
+       ((-1.0*za+zb)*x2+(xa-1.0*xb)*z2-1.0*xa*zb+xb*za)*y1+((ya-1.0*yb)*x2+(xb-1.0*xa)
+       *y2+xa*yb-1.0*xb*ya)*z1+(-1.0*zb*ya+za*yb)*x2+(-1.0*xb*za+xa*zb)*y2
+       +(-1.0*xa*yb+xb*ya)*z2);
+    nenner  =
+       static_cast<double>((((zc-1.0*zb)*ya+(yb-1.0*yc)*za+zb*yc-1.0*zc*yb)*x1
+       +((zb-1.0*zc)*xa+(xc-1.0*xb)*za-1.0*xc*zb+xb*zc)*y1+((-1.0*yb+yc)*xa+(xb-1.0*xc)
+       *ya-1.0*xb*yc+xc*yb)*z1+((zb-1.0*zc)*ya+(-1.0*yb+yc)*za+zc*yb-1.0*zb*yc)*x2
+       +((zc-1.0*zb)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2+((yb-1.0*yc)*xa+(xc-1.0*xb)
+       *ya+xb*yc-1.0*xc*yb)*z2));
+    if ( UbMath::greater(nenner, 0.0) ) eta = static_cast<double>((zaehler/nenner)*wurzel3*-1.);
+    else eta=-999.;
+
+    if (tt >= -1.0-UbMath::Epsilon<double>::val() && tt <= 1.0){
+       if(xi >= -1.0+eta/wurzel3-UbMath::Epsilon<double>::val() && xi <=
+          1.0-eta/wurzel3+UbMath::Epsilon<double>::val()){
+             if (eta >= 0-UbMath::Epsilon<double>::val() && eta <= wurzel3+UbMath::Epsilon<double>::val()){
+                /*xp = x1*(0.5-tt/2)+x2*(0.5+tt/2);
+                yp = y1*(0.5-tt/2)+y2*(0.5+tt/2);
+                zp = z1*(0.5-tt/2)+z2*(0.5+tt/2);*/
+                return
+                   static_cast<double>((sqrt(pow((x1*(0.5-tt/2)+x2*(0.5+tt/2))-x1,2)
+                   +pow((y1*(0.5-tt/2)+y2*(0.5+tt/2))-y1,2)+pow((z1*(0.5-tt/2)+z2*(0.5+tt/2))-z1,2))));
+             }
+          }
+    }
+    return (-999.);
+}
+/*
+* Returns true if the specified 2D point lies within (or on the border of) this 2D triangle.
+* @param point the 2D point to check
+* @return true if the specified 2D point lies within (or on the border of) this 2D triangle
+*/
+ bool GbTriangle3D::enclosesPoint2D(double x1, double x2)
+ {
+	 int i=0;
+	 //Punkt(x1,x2) liegt auf einem der Eckpunkte
+    if(x1==this->getPoint(0)->getX1Coordinate() && x2 == this->getPoint(0)->getX2Coordinate())	return true;
+	 if(x1==this->getPoint(1)->getX1Coordinate() && x2 == this->getPoint(1)->getX2Coordinate())	return true;
+	 if(x1==this->getPoint(2)->getX1Coordinate() && x2 == this->getPoint(2)->getX2Coordinate())  return true;
+
+	 //Erste Grade aus dem zu pruefenden Punkt(x,y) und einem zweiten Punkt(x+0.333,y+2.333)
+	 GbPoint3D p1;		p1.setX1(x1);			p1.setX2(x2);			p1.setX3(0.0);
+	 GbPoint3D p2;		p2.setX1(x1+0.333);	p2.setX2(x2+3.333);	p2.setX3(0.0);
+	 //Punkte des Dreiecks auf 2D reduziert
+	 GbPoint3D dp1;	dp1.setX1(this->getPoint(0)->getX1Coordinate());	dp1.setX2(this->getPoint(0)->getX2Coordinate());	dp1.setX3(0.0);
+	 GbPoint3D dp2;	dp2.setX1(this->getPoint(1)->getX1Coordinate());	dp2.setX2(this->getPoint(1)->getX2Coordinate());	dp2.setX3(0.0);
+	 GbPoint3D dp3;	dp3.setX1(this->getPoint(2)->getX1Coordinate());	dp3.setX2(this->getPoint(2)->getX2Coordinate());	dp3.setX3(0.0);
+	 //ueberpruefen, ob der Punkt(x,y) innerhalt der Boundingbox des Dreiecks liegt
+	 if(	 x1<this->getX1Maximum() && x1>getX1Minimum()
+		 && x2<this->getX2Maximum() && x2>getX2Minimum())
+	 {
+		 GbPoint3D* dummy = NULL;
+		 //ueberpruefen, ob der Punkt innerhalb des Dreiecks liegt
+		 dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp1,dp2);
+		 if(dummy!=NULL)
+       {
+          if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate())	
+          {
+             delete dummy;
+             return true;
+          }
+			 else if(dummy->getX1Coordinate()>p1.getX1Coordinate())
+          {
+             i++;
+          }
+			 else
+          {
+             i--;
+          }
+       }
+       if(dummy)  delete dummy;
+
+       dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp2,dp3);
+		 if(dummy!=NULL)
+       {
+          if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate())
+          {
+             if(dummy)  delete dummy;
+             return true;
+          }
+			 else if(dummy->getX1Coordinate()>p1.getX1Coordinate())
+          {
+             i++;
+          }
+			 else
+          {
+             i--;
+          }
+       }
+       if(dummy)  delete dummy;
+
+		 dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp3,dp1);
+		 if(dummy!=NULL)
+       {
+          if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate())
+          {
+             if(dummy)  delete dummy;
+             return true;
+          }
+			 else if(dummy->getX1Coordinate()>p1.getX1Coordinate())
+          {
+             i++;
+          }
+          else
+          {
+             i--;
+          }
+       }
+       if(dummy)  delete dummy;
+	 }
+	 if(i==-1) return true;
+	 if(i==1 ) return true;
+	
+    return false;
+ }
+
+///*
+//* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+//* @param rectangle the 2D rectangle
+//* @return a new 2D polygon clipped by the specified 2D rectangle
+//*/
+GbPolygon3D* GbTriangle3D::createClippedPolygon3D(GbCuboid3D* cube)
+{
+   return(GbSystem3D::clipPolygon3D(this->getPoints(), cube->getPoint1()->getX1Coordinate(), cube->getPoint1()->getX2Coordinate(), cube->getPoint1()->getX3Coordinate(), cube->getPoint2()->getX1Coordinate(), cube->getPoint2()->getX2Coordinate(), cube->getPoint2()->getX3Coordinate()));
+}
+///*
+//* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+//* @param p1 the 1st point of the rectangle
+//* @param p2 the 2nd point of the rectangle
+//* @return a new 2D polygon clipped by the specified 2D rectangle
+//*/
+//public GbPolygon2D createClippedPolygon2D(GbPoint2D p1, GbPoint2D p2)
+//{
+//   return(GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2));
+//}
+/*
+* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+* @param p1x1 the 1st x1 coordinate of the rectangle
+* @param p1x2 the 1st x2 coordinate of the rectangle
+* @param p2x1 the 2nd x1 coordinate of the rectangle
+* @param p2x2 the 2nd x2 coordinate of the rectangle
+* @return a new 2D polygon clipped by the specified 2D rectangle
+*/
+GbPolygon3D* GbTriangle3D::createClippedPolygon3D(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3)
+{
+   return(GbSystem3D::clipPolygon3D(this->getPoints(), p1x1, p1x2, p1x3, p2x1, p2x2, p2x3));
+}
+
+/*
+* Returns true if the specified 2D rectangle lies completely within this 2D triangle.
+* @param rectangle the 2D rectangle to check
+* @return true if the specified 2D rectangle lies completely within this 2D triangle
+*/
+//bool enclosesRectangle2D(GbRectangle2D *rectangle)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), rectangle.getArea()));
+//}
+/*
+* Returns true if the specified 2D rectangle lies completely within this 2D triangle.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check                         triangle
+* @return true if the specified 2D rectangle lies completely within this 2D
+*/
+//public boolean enclosesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+//}
+/*
+* Returns true if the specified 2D rectangle lies completely within this 2D triangle.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 2D rectangle lies completely within this 2D triangle
+*/
+//public boolean enclosesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+//}
+
+/*
+* Returns true if the specified 2D rectangle is crossed by this 2D triangle.
+* @param rectangle the 2D rectangle to check
+* @return true if the specified 2D rectangle is crossed by this 2D triangle
+*/
+//public boolean crossesRectangle2D(GbRectangle2D rectangle)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, rectangle.getArea()));
+//}
+/*
+* Returns true if the specified 2D rectangle is crossed by this 2D triangle.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 2D rectangle is crossed by this 2D triangle
+*/
+//public boolean crossesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+//}
+/*
+* Returns true if the specified 2D rectangle is crossed by this 2D triangle.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 2D rectangle is crossed by this 2D triangle
+*/
+//public boolean crossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+//}
+
+/*
+* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle.
+* @param rectangle the 2D rectangle to check
+* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle
+*/
+//public boolean enclosesOrCrossesRectangle2D(GbRectangle2D rectangle)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*
+* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle
+*/
+//public boolean enclosesOrCrossesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*
+* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle
+*/
+//public boolean enclosesOrCrossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*======================================================================*/
+
+
+/*======================================================================*/
+/*  Private Methoden                                                    */
+/*                                                                      */
+void GbTriangle3D::calculateValues()
+{
+   this->x1min = this->points[0]->x1;
+   this->x1max = this->points[0]->x1;
+   this->x2min = this->points[0]->x2;
+   this->x2max = this->points[0]->x2;
+   this->x3min = this->points[0]->x3;
+   this->x3max = this->points[0]->x3;
+
+   if(this->points[1]->x1 < this->x1min) this->x1min = this->points[1]->x1;
+   if(this->points[1]->x1 > this->x1max) this->x1max = this->points[1]->x1;
+   if(this->points[1]->x2 < this->x2min) this->x2min = this->points[1]->x2;
+   if(this->points[1]->x2 > this->x2max) this->x2max = this->points[1]->x2;
+   if(this->points[1]->x3 < this->x3min) this->x3min = this->points[1]->x3;
+   if(this->points[1]->x3 > this->x3max) this->x3max = this->points[1]->x3;
+
+   if(this->points[2]->x1 < this->x1min) this->x1min = this->points[2]->x1;
+   if(this->points[2]->x1 > this->x1max) this->x1max = this->points[2]->x1;
+   if(this->points[2]->x2 < this->x2min) this->x2min = this->points[2]->x2;
+   if(this->points[2]->x2 > this->x2max) this->x2max = this->points[2]->x2;
+   if(this->points[2]->x3 < this->x3min) this->x3min = this->points[2]->x3;
+   if(this->points[2]->x3 > this->x3max) this->x3max = this->points[2]->x3;
+
+   this->x1s   = (this->points[0]->x1+this->points[1]->x1+this->points[2]->x1)/3.0;
+   this->x2s   = (this->points[0]->x2+this->points[1]->x2+this->points[2]->x2)/3.0;
+   this->x3s   = (this->points[0]->x3+this->points[1]->x3+this->points[2]->x3)/3.0;
+
+   GbVector3D A(points[0]->x1,points[0]->x2,points[0]->x3);
+   GbVector3D B(points[1]->x1,points[1]->x2,points[1]->x3);
+   GbVector3D C(points[2]->x1,points[2]->x2,points[2]->x3);
+   GbVector3D AB = B-A;
+   GbVector3D AC = C-A;
+   GbVector3D N = AB.Cross(AC);
+   this->area = 0.5*N.Length();
+   this->consistent = true;
+}
+/*======================================================================*/
+
+
+/*======================================================================*/
+//class PointObserver : public UbObserver
+//{
+//    GbTriangle3D *triangle;
+
+//    PointObserver(GbTriangle3D *triangle)
+//    {
+//      this->triangle = triangle;
+//    }
+
+//public:
+//   void objectChanged(GbObject3D *object)
+//    {
+//      if(object == this->triangle->points[0] || object == this->triangle->points[1]  || object == this->triangle->points[2])
+//      {
+//         this->triangle->consistent = false;
+//         this->triangle->notifyObservers();
+//      }
+//    }
+//};
+//bool GbTriangle3D::isPointOnEdge(GbVector3D& q)
+//{
+////cout<<"muss einer machen ...\n";
+//   return false;
+//}
+/*======================================================================*/
+GbVector3D GbTriangle3D::getNormal()
+{
+   this->calculateNormal();
+   return normal; 
+}
+/*======================================================================*/
+void GbTriangle3D::init()
+{
+   x1s        = 0.0;
+   x2s        = 0.0;
+   x3s        = 0.0;
+   x1min      = 0.0;
+   x1max      = 0.0;
+   x2min      = 0.0;
+   x2max      = 0.0;
+   area       = 0.0;
+   consistent = false;
+   points.resize(3,NULL);
+}
+/*=======================================================*/
+void GbTriangle3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   if(points[0]) points[0]->write(out);
+   else {GbPoint3D tmp; tmp.write(out);}
+   if(points[1]) points[1]->write(out);
+   else {GbPoint3D tmp; tmp.write(out);}
+   if(points[2]) points[2]->write(out);
+   else {GbPoint3D tmp; tmp.write(out);}
+}
+/*=======================================================*/
+void GbTriangle3D::read(UbFileInput* in) 
+{  
+   this->deletePoints();
+   points[0] = new GbPoint3D;
+   points[1] = new GbPoint3D;
+   points[2] = new GbPoint3D;
+   in->readString();                                    
+   points[0]->read(in);
+   in->readString();                                    
+   points[1]->read(in);
+   in->readString();                                    
+   points[2]->read(in);
+   consistent = false;
+}
+/*=======================================================*/
+void GbTriangle3D::calculateNormal()
+{
+   GbPoint3D*& a = points[0]; 
+   GbPoint3D*& b = points[1];
+   GbPoint3D*& c = points[2];
+   normal[0] = ( c->getX3Coordinate() - a->getX3Coordinate()) * ( b->getX2Coordinate() - a->getX2Coordinate() ) -
+               ( b->getX3Coordinate() - a->getX3Coordinate()) * ( c->getX2Coordinate() - a->getX2Coordinate() );
+   normal[1] = ( b->getX3Coordinate() - a->getX3Coordinate()) * ( c->getX1Coordinate() - a->getX1Coordinate() ) -
+               ( b->getX1Coordinate() - a->getX1Coordinate()) * ( c->getX3Coordinate() - a->getX3Coordinate() );
+   normal[2] = ( b->getX1Coordinate() - a->getX1Coordinate()) * ( c->getX2Coordinate() - a->getX2Coordinate() ) -
+               ( b->getX2Coordinate() - a->getX2Coordinate()) * ( c->getX1Coordinate() - a->getX1Coordinate() );
+   normal.Normalize();
+}
+/*=======================================================*/
+//toDo: 
+double GbTriangle3D::getDistanceFromPoint(GbVector3D punct)
+{
+	GbVector3D Point1(this->getPoint1()->getX1Coordinate(), this->getPoint1()->getX2Coordinate(), this->getPoint1()->getX3Coordinate());
+	GbVector3D Point2(this->getPoint2()->getX1Coordinate(), this->getPoint2()->getX2Coordinate(), this->getPoint2()->getX3Coordinate());
+	GbVector3D Point3(this->getPoint3()->getX1Coordinate(), this->getPoint3()->getX2Coordinate(), this->getPoint3()->getX3Coordinate());
+
+	GbVector3D kDiff = Point1 - punct;
+	GbVector3D kEdge0 = Point2 - Point1;
+	GbVector3D kEdge1 = Point3 - Point1;
+	double fA00 = kEdge0.SquaredLength();
+	double fA01 = kEdge0.Dot(kEdge1);
+	double fA11 = kEdge1.SquaredLength();
+	double fB0 = kDiff.Dot(kEdge0);
+	double fB1 = kDiff.Dot(kEdge1);
+	double fC = kDiff.SquaredLength();
+	double fDet = fabs(fA00*fA11-fA01*fA01);
+	double fS = fA01*fB1-fA11*fB0;
+	double fT = fA01*fB0-fA00*fB1;
+	double fSqrDistance;
+
+	if (fS + fT <= fDet)
+	{
+		if (fS < (double)0.0)
+		{
+			if (fT < (double)0.0)  // region 4
+			{
+				if (fB0 < (double)0.0)
+				{
+					fT = (double)0.0;
+					if (-fB0 >= fA00)
+					{
+						fS = (double)1.0;
+						fSqrDistance = fA00+((double)2.0)*fB0+fC;
+					}
+					else
+					{
+						fS = -fB0/fA00;
+						fSqrDistance = fB0*fS+fC;
+					}
+				}
+				else
+				{
+					fS = (double)0.0;
+					if (fB1 >= (double)0.0)
+					{
+						fT = (double)0.0;
+						fSqrDistance = fC;
+					}
+					else if (-fB1 >= fA11)
+					{
+						fT = (double)1.0;
+						fSqrDistance = fA11+((double)2.0)*fB1+fC;
+					}
+					else
+					{
+						fT = -fB1/fA11;
+						fSqrDistance = fB1*fT+fC;
+					}
+				}
+			}
+			else  // region 3
+			{
+				fS = (double)0.0;
+				if (fB1 >= (double)0.0)
+				{
+					fT = (double)0.0;
+					fSqrDistance = fC;
+				}
+				else if (-fB1 >= fA11)
+				{
+					fT = (double)1.0;
+					fSqrDistance = fA11+((double)2.0)*fB1+fC;
+				}
+				else
+				{
+					fT = -fB1/fA11;
+					fSqrDistance = fB1*fT+fC;
+				}
+			}
+		}
+		else if (fT < (double)0.0)  // region 5
+		{
+			fT = (double)0.0;
+			if (fB0 >= (double)0.0)
+			{
+				fS = (double)0.0;
+				fSqrDistance = fC;
+			}
+			else if (-fB0 >= fA00)
+			{
+				fS = (double)1.0;
+				fSqrDistance = fA00+((double)2.0)*fB0+fC;
+			}
+			else
+			{
+				fS = -fB0/fA00;
+				fSqrDistance = fB0*fS+fC;
+			}
+		}
+		else  // region 0
+		{
+			// minimum at interior point
+			double fInvDet = ((double)1.0)/fDet;
+			fS *= fInvDet;
+			fT *= fInvDet;
+			fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) +
+				fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC;
+		}
+	}
+	else
+	{
+		double fTmp0, fTmp1, fNumer, fDenom;
+
+		if (fS < (double)0.0)  // region 2
+		{
+			fTmp0 = fA01 + fB0;
+			fTmp1 = fA11 + fB1;
+			if (fTmp1 > fTmp0)
+			{
+				fNumer = fTmp1 - fTmp0;
+				fDenom = fA00-2.0f*fA01+fA11;
+				if (fNumer >= fDenom)
+				{
+					fS = (double)1.0;
+					fT = (double)0.0;
+					fSqrDistance = fA00+((double)2.0)*fB0+fC;
+				}
+				else
+				{
+					fS = fNumer/fDenom;
+					fT = (double)1.0 - fS;
+					fSqrDistance = fS*(fA00*fS+fA01*fT+2.0f*fB0) +
+						fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC;
+				}
+			}
+			else
+			{
+				fS = (double)0.0;
+				if (fTmp1 <= (double)0.0)
+				{
+					fT = (double)1.0;
+					fSqrDistance = fA11+((double)2.0)*fB1+fC;
+				}
+				else if (fB1 >= (double)0.0)
+				{
+					fT = (double)0.0;
+					fSqrDistance = fC;
+				}
+				else
+				{
+					fT = -fB1/fA11;
+					fSqrDistance = fB1*fT+fC;
+				}
+			}
+		}
+		else if (fT < (double)0.0)  // region 6
+		{
+			fTmp0 = fA01 + fB1;
+			fTmp1 = fA00 + fB0;
+			if (fTmp1 > fTmp0)
+			{
+				fNumer = fTmp1 - fTmp0;
+				fDenom = fA00-((double)2.0)*fA01+fA11;
+				if (fNumer >= fDenom)
+				{
+					fT = (double)1.0;
+					fS = (double)0.0;
+					fSqrDistance = fA11+((double)2.0)*fB1+fC;
+				}
+				else
+				{
+					fT = fNumer/fDenom;
+					fS = (double)1.0 - fT;
+					fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) +
+						fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC;
+				}
+			}
+			else
+			{
+				fT = (double)0.0;
+				if (fTmp1 <= (double)0.0)
+				{
+					fS = (double)1.0;
+					fSqrDistance = fA00+((double)2.0)*fB0+fC;
+				}
+				else if (fB0 >= (double)0.0)
+				{
+					fS = (double)0.0;
+					fSqrDistance = fC;
+				}
+				else
+				{
+					fS = -fB0/fA00;
+					fSqrDistance = fB0*fS+fC;
+				}
+			}
+		}
+		else  // region 1
+		{
+			fNumer = fA11 + fB1 - fA01 - fB0;
+			if (fNumer <= (double)0.0)
+			{
+				fS = (double)0.0;
+				fT = (double)1.0;
+				fSqrDistance = fA11+((double)2.0)*fB1+fC;
+			}
+			else
+			{
+				fDenom = fA00-2.0f*fA01+fA11;
+				if (fNumer >= fDenom)
+				{
+					fS = (double)1.0;
+					fT = (double)0.0;
+					fSqrDistance = fA00+((double)2.0)*fB0+fC;
+				}
+				else
+				{
+					fS = fNumer/fDenom;
+					fT = (double)1.0 - fS;
+					fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) +
+						fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC;
+				}
+			}
+		}
+	}
+
+	// account for numerical round-off error
+	if (fSqrDistance < (double)0.0)
+	{
+		fSqrDistance = (double)0.0;
+	}
+/*
+	m_kClosestPoint0 = punct;
+	m_kClosestPoint1 = m_rkTriangle.V[0] + fS*kEdge0 + fT*kEdge1;
+	m_afTriangleBary[1] = fS;
+	m_afTriangleBary[2] = fT;
+	m_afTriangleBary[0] = (double)1.0 - fS - fT;
+*/
+	return sqrt(fSqrDistance);
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbTriangle3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbTriangle3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..42072eb2d153ff473e634818add9da8f7194f133
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbTriangle3D.h
@@ -0,0 +1,248 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBTRIANGLE3D_H
+#define GBTRIANGLE3D_H
+
+#include <sstream>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbVector3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbTriangle3D;
+typedef VFSharedPtr<GbTriangle3D> GbTriangle3DPtr;
+
+
+class GbCuboid3D;
+class GbPolygon3D;
+class GbObject3DCreator;
+
+/*=========================================================================*/
+/* GbTriangle3D                                                            */
+/*                                                                         */
+/*                                                               
+* This Class provides basic 3D triangle objects.
+*/
+//class GbLine2D;
+
+class GbTriangle3D : public GbObject3D , public UbObserver
+{
+public:
+   /*======================================================================*/
+   /*  Konstruktoren                                                       */
+   /*                                                                      */
+   GbTriangle3D();
+   GbTriangle3D(GbPoint3D* point1, GbPoint3D* point2, GbPoint3D* point3);
+   GbTriangle3D(GbTriangle3D* triangle);
+   ~GbTriangle3D();
+   /*======================================================================*/
+   /*  Methoden                                                            */
+   /*                                                                      */
+   GbTriangle3D* clone();
+   void finalize()
+   {
+      this->deletePoints();
+   }
+
+   GbPoint3D* getPoint1()   { return this->points[0]; }
+   GbPoint3D* getPoint2()   { return this->points[1]; }
+   GbPoint3D* getPoint3()   { return this->points[2]; }
+
+   GbVector3D getNormal();
+   void       calculateNormal();
+
+   void deletePoints();
+
+   int contains(GbPoint3D* point);
+   int containsEqual(GbPoint3D* point);
+   GbPoint3D* getPoint(const int& index);
+   std::vector<GbPoint3D> getPoints();
+   double getArea();
+   double getX1Centroid();
+   double getX1Minimum();
+   double getX1Maximum();           
+   double getX2Centroid();
+   double getX2Minimum();
+   double getX2Maximum();
+   double getX3Centroid();
+   double getX3Minimum();
+   double getX3Maximum();
+
+   void setInconsistent() { this->consistent = false;}
+
+   void setPoint(GbPoint3D *point, int index);
+
+   //bool equals(GbObject3D *object)
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)   
+   {
+      //der einfachheit halber ... 
+      return false;
+      //throw UbException(__FILE__, __LINE__, "GbTriangle3D::isPointInObject3D- not implemented");
+   }
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)   
+   {
+      //der einfachheit halber ... 
+      pointIsOnBoundary = false;
+      return false;
+      //throw UbException(__FILE__, __LINE__, "GbTriangle3D::isPointInObject3D- not implemented");
+   }
+   bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x23) { return false; }
+
+
+   // get distance from a point to the triangle
+   //todo CHANGE...
+   double getDistanceFromPoint(GbVector3D punct);
+
+   std::string toString();
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+   /*======================================================================*/
+   /*  Calculation                                                         */
+   /*                                                                      */
+//   std::vector<GbPoint3D> calculateIntersectionPoints3D(GbLine3D *line);
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+//   bool isPointOnEdge(GbVector3D& q);
+   
+   GbPoint3D* calculateIntersectionPoints3D(GbLine3D* line);
+   GbPoint3D* calculateIntersectionPoints3D(GbPoint3D* linePoint1, GbPoint3D* linePoint2);
+   double calculateDistanceToPoint3D(GbPoint3D *point);
+   double calculateDistanceToPoint3D(const double& x1, const double& x2, const double& x3);      
+   double calculateNormalizedDistanceToPoint3D(const double& x1, const double& y1, const double& z1, const double& x2, const double& y2, const double& z2);
+
+   bool enclosesPoint2D(double x1, double x2);
+   GbPolygon3D* createClippedPolygon3D(GbCuboid3D* cube);   
+   GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2);
+   //public GbPolygon2D createClippedPolygon2D(GbPoint2D p1, GbPoint2D p2);
+   GbPolygon3D* createClippedPolygon3D(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3);
+   //bool enclosesRectangle2D(GbRectangle2D *rectangle);
+   //public boolean enclosesRectangle2D(GbPoint2D p1, GbPoint2D p2);
+   //public boolean enclosesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2);
+   //public boolean crossesRectangle2D(GbRectangle2D rectangle);
+   //public boolean crossesRectangle2D(GbPoint2D p1, GbPoint2D p2);
+   //public boolean crossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2);
+   //public boolean enclosesOrCrossesRectangle2D(GbRectangle2D rectangle);
+   //public boolean enclosesOrCrossesRectangle2D(GbPoint2D p1, GbPoint2D p2);
+   //public boolean enclosesOrCrossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2);
+   /*======================================================================*/
+   /*======================================================================*/
+   /*  Private Methoden                                                    */
+   /*                                                                      */
+   virtual void calculateValues();
+
+   /*======================================================================*/
+   //class PointObserver : public UbObserver
+   //{
+   //    GbTriangle3D *triangle;
+
+   //    PointObserver(GbTriangle3D *triangle)
+   //    {
+   //      this->triangle = triangle;
+   //    }
+
+   //public:
+   //   void objectChanged(GbObject3D *object)
+   //    {
+   //      if(object == this->triangle->points[0] || object == this->triangle->points[1]  || object == this->triangle->points[2])
+   //      {
+   //         this->triangle->consistent = false;
+   //         this->triangle->notifyObservers();
+   //      }
+   //    }
+   //};
+   /*======================================================================*/
+
+   //virtuelle Methoden von UbObserver
+   //!! quick and dirty von sirann !!
+   void objectChanged(UbObservable* changedObject)
+   {
+      GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject);
+      if(!point || (  this->points[0]!=point && this->points[1]!=point && this->points[2]!=point) ) 
+         return;
+      
+      this->consistent = false;
+   }
+   void objectWillBeDeleted(UbObservable* objectForDeletion)
+   {
+      if(this->points[0])
+      {
+         UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[0]);
+         if(objectForDeletion == observedObj) { this->points[0] = NULL; }
+      }
+      if(this->points[1])
+      {
+         UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[1]);
+         if(objectForDeletion == observedObj) { this->points[1] = NULL; }
+      }
+      if(this->points[2])
+      {
+         UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[2]);
+         if(objectForDeletion == observedObj) { this->points[2] = NULL; }
+      }
+      //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo
+   }
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & points;
+      ar & normal;
+      ar & x1s;
+      ar & x2s;
+      ar & x3s;
+      ar & x1min;
+      ar & x1max;
+      ar & x2min;
+      ar & x2max;
+      ar & x3min;
+      ar & x3max;
+      ar & area;
+      ar & consistent;
+      if( ArchiveTools::isReading(ar) ) this->calculateNormal();
+   }
+#endif //CAB_RCF
+
+protected:
+   bool   consistent;
+   double x1s;
+   double x2s;
+   double x3s;
+   double x1min;
+   double x1max;
+   double x2min;
+   double x2max;
+   double x3min;
+   double x3max;
+   double area;
+   
+   GbVector3D normal;
+   std::vector<GbPoint3D*> points;
+   
+private:
+   void init();
+};
+/*=========================================================================*/
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbTriangle3D  >("GbTriangle3D  ")        , SF_GbTriangle3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbTriangle3D >() ), SF_GbTriangle3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbTriangle3D>()  ), SF_GbTriangle3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbTriangularMesh3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbTriangularMesh3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b98dca0da97656d937c8ad6562b936b6e81c42a5
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbTriangularMesh3D.cpp
@@ -0,0 +1,1535 @@
+#include <numerics/geometry3d/GbTriangularMesh3D.h>
+#include <numerics/geometry3d/creator/GbTriangularMesh3DCreator.h>
+
+#include <map>
+
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/CoordinateTransformation3D.h>
+                         
+using namespace std;
+
+GbTriangularMesh3D::GbTriangularMesh3D() : GbObject3D()
+{
+   this->setName("new GbMesh");
+   this->nodes     = new vector<GbPoint3D*>;           
+   this->triangles = new vector<GbTriangle3D*>;
+   this->edges     = new vector<GbLine3D*>;
+   
+   this->pointinobjecttest = RAYCROSSING;
+
+   this->consistent = false;                                 
+   x1min = x1max = x2min = x2max = x3min = x3max = 0.0;
+}
+/*=============================================================================================*/
+GbTriangularMesh3D::GbTriangularMesh3D(string name, vector<GbPoint3D*> *nodes, vector<GbTriangle3D*> *triangles) : GbObject3D()
+{
+   if(name.size()==0 ) throw UbException(UB_EXARGS,"no name specified");
+   if(!nodes         ) throw UbException(UB_EXARGS,"no nodes specified");
+   if(!triangles     ) throw UbException(UB_EXARGS,"no triangles specified");
+                                                         
+   this->setName(name);
+   this->nodes      = nodes;           
+   this->triangles  = triangles;     
+   this->edges      = new vector<GbLine3D*>;
+   this->pointinobjecttest = RAYCROSSING;
+
+   this->consistent = false;                                 
+   x1min = x1max = x2min = x2max = x3min = x3max = 0.0;
+}
+/*=============================================================================================*/
+GbTriangularMesh3D::GbTriangularMesh3D(string name, vector<GbTriangle3D*> *tris) : GbObject3D()
+{
+   cout<<"Das Teil erzeugt seinen KnotenVector aus den Dreiecken ...\n Es sollte deleteRedundantNodes() aufgerufen werden \n";
+   if(name.size()==0 ) throw UbException(UB_EXARGS,"no name specified");
+   if(!tris          ) throw UbException(UB_EXARGS,"no triangles specified");
+
+   vector<GbPoint3D*> *points = new vector<GbPoint3D*>;
+   this->triangles = new vector<GbTriangle3D*>;
+   GbPoint3D* p1 = NULL;
+   GbPoint3D* p2 = NULL;
+   GbPoint3D* p3 = NULL;
+   for(int u=0;u<(int)tris->size();u++)
+   {
+      if(UbMath::zero((*tris)[u]->getArea()))
+      {
+         (*tris)[u]->finalize();
+         delete (*tris)[u];
+         (*tris)[u] = NULL;
+         continue;
+      }
+      this->triangles->push_back((*tris)[u]);
+      p1 = (*tris)[u]->getPoint1();
+      p2 = (*tris)[u]->getPoint2();
+      p3 = (*tris)[u]->getPoint3();
+      points->push_back(p1);
+      points->push_back(p2);
+      points->push_back(p3);
+   }
+
+   this->setName(name);
+   this->nodes            = points; 
+   //this->triangles        = triangles;     
+   this->edges = new vector<GbLine3D*>;
+   this->edges->resize(0, NULL);
+   this->pointinobjecttest = RAYCROSSING;
+   
+   this->consistent       = false;                                 
+   x1min = x1max = x2min = x2max = x3min = x3max = 0.0;
+}
+/*=============================================================================================*/
+GbTriangularMesh3D::GbTriangularMesh3D(string name, vector<GbPoint3D*> *nodes, vector<GbLine3D*> *edges, vector<GbTriangle3D*> *triangles) : GbObject3D()
+{
+   if(name.size()==0) throw UbException(UB_EXARGS,"no name specified");
+   if(!nodes        ) throw UbException(UB_EXARGS,"no nodes specified");
+   if(!triangles    ) throw UbException(UB_EXARGS,"no triangles specified");
+   if(!edges        ) throw UbException(UB_EXARGS,"no edges specified");
+
+   this->setName(name);
+   this->nodes            = nodes;
+   this->edges            = edges;
+   this->triangles        = triangles;                   
+   this->pointinobjecttest = RAYCROSSING;
+
+   this->consistent = false;                                 
+   x1min = x1max = x2min = x2max = x3min = x3max = 0.0;
+}
+/*=============================================================================================*/
+GbTriangularMesh3D::~GbTriangularMesh3D()
+{
+	if( this->nodes )
+	{
+		for(unsigned u=0; u<nodes->size(); u++) delete (*nodes)[u];
+      delete nodes;
+	}
+	if(triangles)
+	{
+		for(unsigned u=0; u<triangles->size(); u++)	delete (*triangles)[u];
+      delete triangles;
+	}
+}
+/*======================================================================*/
+ObObjectCreator* GbTriangularMesh3D::getCreator()
+{
+   return GbTriangularMesh3DCreator::getInstance();
+}
+/*======================================================================*/
+void GbTriangularMesh3D::deleteRedundantNodes()
+{
+   std::map<GbPoint3D*,GbTriangle3D*> pointTriMap;
+   GbPoint3D* p1 = NULL;
+   GbPoint3D* p2 = NULL;
+   GbPoint3D* p3 = NULL;
+   GbTriangle3D* tri = NULL;
+
+   for(int u=0;u<(int)this->triangles->size();u++)
+   {
+      tri = (*this->triangles)[u];
+      p1 = tri->getPoint1();
+      p2 = tri->getPoint2();
+      p3 = tri->getPoint3();
+      pointTriMap.insert(pair<GbPoint3D*,GbTriangle3D*>(p1,tri));
+      pointTriMap.insert(pair<GbPoint3D*,GbTriangle3D*>(p2,tri));
+      pointTriMap.insert(pair<GbPoint3D*,GbTriangle3D*>(p3,tri));
+   }
+
+   cout<<"Nodes before deleting redundant:"<<this->nodes->size()<<endl;
+   GbPoint3D* pA = NULL;
+   GbPoint3D* pB = NULL;
+   std::map<GbPoint3D*,GbTriangle3D*>::iterator mapIterator; 
+   for(int u=0;u<(int)this->nodes->size();u++)
+   {
+      //cout<<u<<" von "<<this->nodes->size()<<endl;
+      pA = (*this->nodes)[u];
+      if(pA==NULL) continue;
+      for(int w=u+1;w<(int)this->nodes->size();w++)
+      {
+      //   cout<<w<<" Wvon "<<this->nodes->size()<<endl;
+         pB = (*this->nodes)[w];
+         if(pB==NULL) continue;
+         if(pA->equals(pB))
+         {
+            //doppelter Knoten ...
+            mapIterator = pointTriMap.find(pB);
+            tri = dynamic_cast<GbTriangle3D*>(mapIterator->second);
+            if(!tri) throw UbException(UB_EXARGS,"triangle not found");
+            p1 = tri->getPoint1();
+            p2 = tri->getPoint2();
+            p3 = tri->getPoint3();
+            if(pB==p1) tri->setPoint(pA, 0);
+            else if(pB==p2) tri->setPoint(pA, 1);
+            else if(pB==p3) tri->setPoint(pA, 2);
+            else throw UbException(UB_EXARGS,"node should be there");
+            delete pB;
+            (*this->nodes)[w] = NULL;
+         }
+      }
+   }
+   vector<GbPoint3D*> *points = new vector<GbPoint3D*>;
+   for(int u=0;u<(int)this->nodes->size();u++)
+   {
+      pA = (*this->nodes)[u];
+      if(pA!=NULL) points->push_back(pA);
+   }
+   delete this->nodes;
+   this->nodes = points;
+   cout<<"Nodes after deleting redundant:"<<this->nodes->size()<<endl;   
+
+
+//nochmal kontrolle ...
+   pointTriMap.clear();
+   for(int u=0;u<(int)this->triangles->size();u++)
+   {
+      tri = (*this->triangles)[u];
+      p1 = tri->getPoint1();
+      p2 = tri->getPoint2();
+      p3 = tri->getPoint3();
+      pointTriMap.insert(pair<GbPoint3D*,GbTriangle3D*>(p1,tri));
+      pointTriMap.insert(pair<GbPoint3D*,GbTriangle3D*>(p2,tri));
+      pointTriMap.insert(pair<GbPoint3D*,GbTriangle3D*>(p3,tri));
+   }
+   for(int u=0;u<(int)this->nodes->size();u++)
+   {
+      pA = (*this->nodes)[u];
+      if(pA==NULL) throw UbException(UB_EXARGS,"sollte kein NULL pointer sein ...");
+      mapIterator = pointTriMap.find(pA);
+      tri = dynamic_cast<GbTriangle3D*>(mapIterator->second);
+      if(!tri) throw UbException(UB_EXARGS,"triangle not found");
+   }
+}
+/*======================================================================*/
+void GbTriangularMesh3D::translate(const double& x1, const double& x2, const double& x3) 
+{
+   GbPoint3D* pt;
+   for(int u=0;u<(int)this->nodes->size();u++)
+   {
+      pt = (*nodes)[u];
+      pt->setX1(pt->getX1Coordinate()+x1);
+      pt->setX2(pt->getX2Coordinate()+x2);
+      pt->setX3(pt->getX3Coordinate()+x3);
+   }
+   this->consistent = false;
+}
+/*======================================================================*/
+void GbTriangularMesh3D::rotate(const double& alpha, const double& beta, const double& gamma)
+{
+   if(!this->consistent) this->calculateValues();
+   double a1 = this->getX1Centroid();
+   double a2 = this->getX2Centroid();
+   double a3 = this->getX3Centroid();
+   CoordinateTransformation3D trafoFor(a1, a2, a3, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0);
+   CoordinateTransformation3D trafoBack(a1, a2, a3, 1.0, 1.0, 1.0, alpha, beta, gamma);
+
+   vector<GbPoint3D*> points;
+   GbPoint3D* p1 = NULL;
+   GbPoint3D* p2 = NULL;
+   GbPoint3D* p3 = NULL;
+   for(int u=0;u<(int)this->triangles->size();u++)
+   {
+      p1 = (*triangles)[u]->getPoint1();
+      p2 = (*triangles)[u]->getPoint2();
+      p3 = (*triangles)[u]->getPoint3();
+      double p1x1 = trafoFor.transformForwardToX1Coordinate(p1->x1, p1->x2, p1->x3);
+      double p1x2 = trafoFor.transformForwardToX2Coordinate(p1->x1, p1->x2, p1->x3);
+      double p1x3 = trafoFor.transformForwardToX3Coordinate(p1->x1, p1->x2, p1->x3);
+      double p2x1 = trafoFor.transformForwardToX1Coordinate(p2->x1, p2->x2, p2->x3);
+      double p2x2 = trafoFor.transformForwardToX2Coordinate(p2->x1, p2->x2, p2->x3);
+      double p2x3 = trafoFor.transformForwardToX3Coordinate(p2->x1, p2->x2, p2->x3);
+      double p3x1 = trafoFor.transformForwardToX1Coordinate(p3->x1, p3->x2, p3->x3);
+      double p3x2 = trafoFor.transformForwardToX2Coordinate(p3->x1, p3->x2, p3->x3);
+      double p3x3 = trafoFor.transformForwardToX3Coordinate(p3->x1, p3->x2, p3->x3);
+      p1->x1 = trafoBack.transformBackwardToX1Coordinate(p1x1, p1x2, p1x3);
+      p1->x2 = trafoBack.transformBackwardToX2Coordinate(p1x1, p1x2, p1x3);
+      p1->x3 = trafoBack.transformBackwardToX3Coordinate(p1x1, p1x2, p1x3);
+      p2->x1 = trafoBack.transformBackwardToX1Coordinate(p2x1, p2x2, p2x3);
+      p2->x2 = trafoBack.transformBackwardToX2Coordinate(p2x1, p2x2, p2x3);
+      p2->x3 = trafoBack.transformBackwardToX3Coordinate(p2x1, p2x2, p2x3);
+      p3->x1 = trafoBack.transformBackwardToX1Coordinate(p3x1, p3x2, p3x3);
+      p3->x2 = trafoBack.transformBackwardToX2Coordinate(p3x1, p3x2, p3x3);
+      p3->x3 = trafoBack.transformBackwardToX3Coordinate(p3x1, p3x2, p3x3);
+   }
+   this->calculateValues();
+}
+/*======================================================================*/
+   /**
+    * Returns a string representation of this triangular mesh.
+    * @return a string representation of this triangular mesh
+    */
+string GbTriangularMesh3D::toString()
+{
+	stringstream ss;
+	ss<<"GbTriangularMesh3D[";
+	ss<<(int)this->triangles->size()<<"-Triangles, "<<(int)this->nodes->size()<<"-Nodes, "<<(int)this->edges->size()<<"-Edges"<<endl;
+	//ss<<"\""<<this->name<<", Area=sollt mal berechnet werden ;-)"<<"\"";
+   //ss<<", x1min="<<this->x1min;
+   //ss<<", x1max="<<this->x1max;
+   //ss<<", x2min="<<this->x2min;
+   //ss<<", x2max="<<this->x2max;
+   //ss<<", x3min="<<this->x3min;
+   //ss<<", x3max="<<this->x3max;
+   ss<<"]";
+   return(ss.str());
+}
+/**
+ * Returns the name of this triangular mesh.
+ * @return the name of this triangular mesh
+ */
+//string GbTriangularMesh3D::getName(){ return(this->name); }
+
+/**
+ * Returns the nodes of this triangular mesh.
+ * @return the nodes of this triangular mesh
+ */
+vector<GbPoint3D*>* GbTriangularMesh3D::getNodes()   {  return(this->nodes);   }
+/**
+ * Returns the triangles of this triangular mesh.
+ * @return the triangles of this triangular mesh
+ */
+vector<GbTriangle3D*>* GbTriangularMesh3D::getTriangles()  { return(this->triangles);  }
+/**
+ * Returns the center x1 coordinate of this triangular mesh.
+ * @return the center x1 coordinate of this triangular mesh
+ */
+double GbTriangularMesh3D::getX1Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(0.5*(this->x1min+this->x1max));
+}
+/**
+ * Returns the center x2 coordinate of this triangular mesh.
+ * @return the center x2 coordinate of this triangular mesh
+ */
+double GbTriangularMesh3D::getX2Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(0.5*(this->x2min+this->x2max));
+}
+/**
+* Returns the center x3 coordinate of this triangular mesh.
+	* @return the center x3 coordinate of this triangular mesh
+	*/
+double GbTriangularMesh3D::getX3Centroid()
+{
+	if(!this->consistent) this->calculateValues();
+	return(0.5*(this->x3min+this->x3max));
+}
+
+/**
+ * Returns the minimum x1 coordinate of this triangular mesh.
+ * @return the minimum x1 coordinate of this triangular mesh
+ */
+double GbTriangularMesh3D::getX1Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1min);
+}
+/**
+ * Returns the maximum x1 coordinate of this triangular mesh.
+ * @return the maximum x1 coordinate of this triangular mesh
+ */
+double GbTriangularMesh3D::getX1Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1max);
+}
+/**
+ * Returns the minimum x2 coordinate of this triangular mesh.
+ * @return the minimum x2 coordinate of this triangular mesh
+ */
+double GbTriangularMesh3D::getX2Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2min);
+}
+/**
+ * Returns the maximum x2 coordinate of this triangular mesh.
+ * @return the maximum x2 coordinate of this triangular mesh
+ */
+double GbTriangularMesh3D::getX2Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2max);
+}
+/**
+ * Returns the minimum x3 coordinate of this triangular mesh.
+ * @return the minimum x3 coordinate of this triangular mesh
+ */
+double GbTriangularMesh3D::getX3Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3min);
+}
+/**
+ * Returns the maximum x3 coordinate of this triangular mesh.
+ * @return the maximum x3 coordinate of this triangular mesh
+ */
+double GbTriangularMesh3D::getX3Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3max);
+}
+
+void GbTriangularMesh3D::calculateValues()
+{
+   double x1, x2, x3;
+
+	this->x1min = (*this->nodes)[0]->getX1Coordinate();
+   this->x1max = (*this->nodes)[0]->getX1Coordinate();
+   this->x2min = (*this->nodes)[0]->getX2Coordinate();
+   this->x2max = (*this->nodes)[0]->getX2Coordinate();
+   this->x3min = (*this->nodes)[0]->getX3Coordinate();
+   this->x3max = (*this->nodes)[0]->getX3Coordinate();
+
+   for(int i=1; i<(int)this->nodes->size(); i++)
+   {
+		x1 = (*this->nodes)[i]->getX1Coordinate();
+		x2 = (*this->nodes)[i]->getX2Coordinate();
+		x3 = (*this->nodes)[i]->getX3Coordinate();
+		if(x1 < this->x1min) this->x1min = x1;
+		if(x1 > this->x1max) this->x1max = x1;
+		if(x2 < this->x2min) this->x2min = x2;
+		if(x2 > this->x2max) this->x2max = x2;
+		if(x3 < this->x3min) this->x3min = x3;
+		if(x3 > this->x3max) this->x3max = x3;
+   }
+   this->consistent = true;
+}
+
+/**
+ * Returns the total area of this triangular mesh.
+ * @return the total area of this triangular mesh
+ */
+double GbTriangularMesh3D::getArea()
+{
+   double area = 0.0;
+   for(int i=0; i<(int)this->triangles->size(); i++) area += (*this->triangles)[i]->getArea();
+   return(area);
+}
+/**
+ * Returns the total volume of this triangular mesh.
+ * @return the total volume of this triangular mesh
+  */
+double GbTriangularMesh3D::getVolume()
+{
+   GbTriangle3D* triangle;
+   GbPoint3D* p1;
+   GbPoint3D* p2;
+   GbPoint3D* p3;
+
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3;
+   double G3i;
+   double volume = 0.0;
+   int size = (int)this->triangles->size();
+   for(int u=0; u<size;u++)
+   {
+      triangle = (*this->triangles)[u];
+      p1 = triangle->getPoint1();
+      p2 = triangle->getPoint2();
+      p3 = triangle->getPoint3();
+      x1 = p1->getX1Coordinate(); y1 = p1->getX2Coordinate(); z1 = p1->getX3Coordinate();
+      x2 = p2->getX1Coordinate(); y2 = p2->getX2Coordinate(); z2 = p2->getX3Coordinate();
+      x3 = p3->getX1Coordinate(); y3 = p3->getX2Coordinate(); z3 = p3->getX3Coordinate();
+      G3i = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+   }
+   return volume;
+}
+/*===============================================*/
+UbTupleDouble3 GbTriangularMesh3D::calculateCenterOfGravity()
+{
+   GbTriangle3D* triangle;
+   GbPoint3D* p1;
+   GbPoint3D* p2;
+   GbPoint3D* p3;
+
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3;
+   double G3i;
+   double rSP1 = 0.0;double rSP2 = 0.0;double rSP3 = 0.0;
+   double volume = 0.0;
+   int size = (int)this->triangles->size();
+   for(int u=0; u<size;u++)
+   {
+      triangle = (*this->triangles)[u];
+      p1 = triangle->getPoint1();
+      p2 = triangle->getPoint2();
+      p3 = triangle->getPoint3();
+      x1 = p1->getX1Coordinate(); y1 = p1->getX2Coordinate(); z1 = p1->getX3Coordinate();
+      x2 = p2->getX1Coordinate(); y2 = p2->getX2Coordinate(); z2 = p2->getX3Coordinate();
+      x3 = p3->getX1Coordinate(); y3 = p3->getX2Coordinate(); z3 = p3->getX3Coordinate();
+      G3i = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+      rSP1 = rSP1+G3i*(x1+x2+x3);
+      rSP2 = rSP2+G3i*(y1+y2+y3);
+      rSP3 = rSP3+G3i*(z1+z2+z3);
+   }
+   rSP1 = rSP1/(24.0*volume);
+   rSP2 = rSP2/(24.0*volume);
+   rSP3 = rSP3/(24.0*volume);
+
+   return UbTupleDouble3(rSP1, rSP2, rSP3);
+}
+/*===============================================*/
+UbTupleDouble6 GbTriangularMesh3D::calculateMomentOfInertia(double rhoP)
+{
+   GbTriangle3D* triangle;
+   GbPoint3D* p1;
+   GbPoint3D* p2;
+   GbPoint3D* p3;
+   
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3;
+   double G3i;
+   double xx,yy,zz,xy,yz,zx;
+   double rSP1 = 0.0;double rSP2 = 0.0;double rSP3 = 0.0;
+   double volume = 0.0;
+   double top11 = 0.0;double top22 = 0.0;double top33 = 0.0;
+   double top12 = 0.0;double top23 = 0.0;double top13 = 0.0;
+   int size = (int)this->triangles->size();
+   for(int u=0; u<size;u++)
+   {
+      triangle = (*this->triangles)[u];
+      p1 = triangle->getPoint1();
+      p2 = triangle->getPoint2();
+      p3 = triangle->getPoint3();
+      x1 = p1->getX1Coordinate(); y1 = p1->getX2Coordinate(); z1 = p1->getX3Coordinate();
+      x2 = p2->getX1Coordinate(); y2 = p2->getX2Coordinate(); z2 = p2->getX3Coordinate();
+      x3 = p3->getX1Coordinate(); y3 = p3->getX2Coordinate(); z3 = p3->getX3Coordinate();
+      G3i = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+      rSP1 = rSP1+G3i*(x1+x2+x3);
+      rSP2 = rSP2+G3i*(y1+y2+y3);
+      rSP3 = rSP3+G3i*(z1+z2+z3);
+   }
+   rSP1 = rSP1/(24.0*volume);
+   rSP2 = rSP2/(24.0*volume);
+   rSP3 = rSP3/(24.0*volume);
+
+   double x1s = 0.0;//rSP1;//0.0;//
+   double x2s = 0.0;//rSP2;//0.0;//
+   double x3s = 0.0;//rSP3;//0.0;//
+
+   for(int u=0; u<size;u++)
+   {
+      triangle = (*this->triangles)[u];
+      p1 = triangle->getPoint1();
+      p2 = triangle->getPoint2();
+      p3 = triangle->getPoint3();
+      x1 = p1->getX1Coordinate()-x1s; 
+      y1 = p1->getX2Coordinate()-x2s; 
+      z1 = p1->getX3Coordinate()-x3s;
+      x2 = p2->getX1Coordinate()-x1s; 
+      y2 = p2->getX2Coordinate()-x2s; 
+      z2 = p2->getX3Coordinate()-x3s;
+      x3 = p3->getX1Coordinate()-x1s; 
+      y3 = p3->getX2Coordinate()-x2s; 
+      z3 = p3->getX3Coordinate()-x3s;
+      G3i = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      //rSP1 = rSP1+G3i*(x1+x2+x3)/(24.0*volume);
+      //rSP2 = rSP2+G3i*(y1+y2+y3)/(24.0*volume);
+      //rSP3 = rSP3+G3i*(z1+z2+z3)/(24.0*volume);
+      xx = x1*x1+x2*x2+x3*x3+x1*x2+x2*x3+x3*x1;
+      yy = y1*y1+y2*y2+y3*y3+y1*y2+y2*y3+y3*y1;
+      zz = z1*z1+z2*z2+z3*z3+z1*z2+z2*z3+z3*z1;
+      top11 = top11+(yy+zz)*rhoP*G3i/60.;
+      top22 = top22+(xx+zz)*rhoP*G3i/60.;
+      top33 = top33+(yy+xx)*rhoP*G3i/60.;
+      xy = 2.0*(x1*y1+x2*y2+x3*y3)+x2*y3+x3*y1+x1*y2+x3*y2+x1*y3+x2*y1;
+      yz = 2.0*(y1*z1+y2*z2+y3*z3)+y2*z3+y3*z1+y1*z2+y3*z2+y1*z3+y2*z1;
+      zx = 2.0*(z1*x1+z2*x2+z3*x3)+z2*x3+z3*x1+z1*x2+z3*x2+z1*x3+z2*x1;
+      top12 = top12-xy*rhoP*G3i/120.;
+      top23 = top23-yz*rhoP*G3i/120.;
+      top13 = top13-zx*rhoP*G3i/120.;
+   }
+   //Satz von Steiner ...
+   top11 = top11-rhoP*volume*(rSP2*rSP2+rSP3+rSP3);
+   top22 = top22-rhoP*volume*(rSP3*rSP3+rSP1*rSP1);
+   top33 = top33-rhoP*volume*(rSP1*rSP1+rSP2*rSP2);
+   top12 = top12+rhoP*volume*rSP1*rSP2;
+   top23 = top23+rhoP*volume*rSP2*rSP3;
+   top13 = top13+rhoP*volume*rSP3*rSP1;
+   
+   cout<<"Volume:"<<volume<<"\n Traegheitsmomente:\n";
+   cout<<" top11:"<<top11<<" top22:"<<top22<<" top33:"<<top33<<endl;
+   cout<<" top12:"<<top12<<" top23:"<<top23<<" top13:"<<top13<<endl;
+
+   return UbTupleDouble6(top11,top22,top33,top12,top23,top13);
+}
+
+ /**
+  * Returns the volume of this triangular mesh within the specified rectangle.
+  * @param p1x1 the 1st x1 coordinate of the rectangle
+  * @param p1x2 the 1st x2 coordinate of the rectangle
+  * @param p2x1 the 2nd x1 coordinate of the rectangle
+  * @param p2x2 the 2nd x2 coordinate of the rectangle
+  * @return the volume of this triangular mesh within the specified rectangle
+  * @exception NullPointerException if no triangles are found within the specified rectangle
+  */
+double GbTriangularMesh3D::getVolumeForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2) 
+{
+	throw UbException(UB_EXARGS,"not yet implemented");
+  //    GbPolygon2D polygon;
+  //    double      volume = 0.0;
+  //    double      area1 = Math.abs((p1x1-p2x1)*(p1x2-p2x2));
+  //    double      area2 = 0.0;
+  //    double      t1min, t1max, t2min, t2max;
+  //    double      x1, x2;
+  //    boolean     f = false;
+
+  //    for(int i=0; i<this.triangles.length; i++)
+  //    {
+		//	t1min = this.triangles[i].getX1Minimum();
+		//	t1max = this.triangles[i].getX1Maximum();
+		//	if(GbSystem.less2(t1min, t1max, p1x1, p2x1))    continue;
+		//	if(GbSystem.greater2(t1min, t1max, p1x1, p2x1)) continue;
+
+		//	t2min = this.triangles[i].getX2Minimum();
+		//	t2max = this.triangles[i].getX2Maximum();
+		//	if(GbSystem.less2(t2min, t2max, p1x2, p2x2))    continue;
+		//	if(GbSystem.greater2(t2min, t2max, p1x2, p2x2)) continue;
+
+		//	if(GbSystem.inOpenInterval(t1min, p1x1, p2x1) && GbSystem.inOpenInterval(t1max, p1x1, p2x1) &&
+		//		GbSystem.inOpenInterval(t2min, p1x2, p2x2) && GbSystem.inOpenInterval(t2max, p1x2, p2x2))
+		//	{
+		//		volume += this.triangles[i].getVolume();
+		//		area2  += this.triangles[i].getArea();
+		//		f       = true;
+		//	}
+		//	else
+		//	{
+		//		polygon = this.triangles[i].createClippedPolygon3D(p1x1, p1x2, p2x1, p2x2);
+
+		//		if(polygon != null && polygon.size() > 2)
+		//		{
+		//			try
+		//			{
+		//				x1      = polygon.getX1Centroid();
+		//				x2      = polygon.getX2Centroid();
+		//				volume += this.triangles[i].getX3Coordinate(x1, x2) * Math.abs(polygon.getArea());
+		//				area2  += Math.abs(polygon.getArea());
+		//				f       = true;
+		//			}
+		//			catch(Exception e){}
+		//		}
+		//	}
+		//	if(GbSystem.greaterEqual(area2, area1)) break;
+		//}
+  //    if(f) return(volume);
+  //    else  throw new NullPointerException();
+}
+
+/**
+ * Returns the triangles of this triangular mesh located within the specified rectangle (may be an empty array).
+ * @param p1x1 the 1st x1 coordinate of the rectangle
+ * @param p1x2 the 1st x2 coordinate of the rectangle
+ * @param p2x1 the 2nd x1 coordinate of the rectangle
+ * @param p2x2 the 2nd x2 coordinate of the rectangle
+ * @return the triangles of this triangular mesh located within the specified rectangle
+ */
+vector<GbTriangle3D*>* GbTriangularMesh3D::getTrianglesForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2)
+{
+	throw UbException(UB_EXARGS,"not yet implemented");
+  //    QbList      triangleList = new QbList(GbTriangle3D.class);
+  //    GbPolygon2D polygon;
+  //    double      t1min, t1max, t2min, t2max;
+  //    double      area1 = Math.abs((p1x1-p2x1)*(p1x2-p2x2));
+  //    double      area2 = 0.0;
+
+  //    for(int i=0; i<this.triangles.length; i++)
+  //    {
+		//	t1min = this.triangles[i].getX1Minimum();
+		//	t1max = this.triangles[i].getX1Maximum();
+		//	if(GbSystem.less2(t1min, t1max, p1x1, p2x1))    continue;
+		//	if(GbSystem.greater2(t1min, t1max, p1x1, p2x1)) continue;
+
+		//	t2min = this.triangles[i].getX2Minimum();
+		//	t2max = this.triangles[i].getX2Maximum();
+		//	if(GbSystem.less2(t2min, t2max, p1x2, p2x2))    continue;
+		//	if(GbSystem.greater2(t2min, t2max, p1x2, p2x2)) continue;
+
+		//	if(GbSystem.inOpenInterval(t1min, p1x1, p2x1) && GbSystem.inOpenInterval(t1max, p1x1, p2x1) &&
+		//		GbSystem.inOpenInterval(t2min, p1x2, p2x2) && GbSystem.inOpenInterval(t2max, p1x2, p2x2))
+		//	{
+		//		try { triangleList.append(this.triangles[i]); } catch(Exception e){}
+		//		area2 += this.triangles[i].getArea();
+		//	}
+		//	else
+		//	{
+		//		polygon = this.triangles[i].createClippedPolygon3D(p1x1, p1x2, p2x1, p2x2);
+		//		if(polygon != null && polygon.size() > 2)
+		//		{
+		//			try { triangleList.append(this.triangles[i]); } catch(Exception e){}
+		//			area2 += Math.abs(polygon.getArea());
+		//		}
+		//	}
+		//	if(GbSystem.greaterEqual(area2, area1)) break;
+		//}
+  //    return((GbTriangle3D[])triangleList.getObjectArray());
+}
+/**
+ * Returns the nodes of this triangular mesh located within the specified rectangle (may be an empty array).
+ * @param p1x1 the 1st x1 coordinate of the rectangle
+ * @param p1x2 the 1st x2 coordinate of the rectangle
+ * @param p2x1 the 2nd x1 coordinate of the rectangle
+ * @param p2x2 the 2nd x2 coordinate of the rectangle
+ * @return the nodes of this triangular mesh located within the specified rectangle
+ */
+vector<GbPoint3D*>* GbTriangularMesh3D::getNodesForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2)
+{
+	throw UbException(UB_EXARGS,"not implemented");
+//   QbList nodeList = new QbList(GbPoint3D.class);
+
+   //   for(int i=0; i<this.edges.length; i++)
+   //   {
+			//if(GbSystem.inClosedInterval(this.nodes[i].getX1Coordinate(), p1x1, p2x1) && GbSystem.inClosedInterval(this.nodes[i].getX2Coordinate(), p1x2, p2x2))
+			//{
+			//	try { nodeList.append(this.nodes[i]); } catch(Exception e){}
+			//}
+   //   }
+   //   return((GbPoint3D[])nodeList.getObjectArray());
+}
+
+/**
+ * Returns the difference of maximum and minimum x3 coordinates
+ * of this triangular mesh within the specified rectangle.
+ * @param p1x1 the 1st x1 coordinate of the rectangle
+ * @param p1x2 the 1st x2 coordinate of the rectangle
+ * @param p2x1 the 2nd x1 coordinate of the rectangle
+ * @param p2x2 the 2nd x2 coordinate of the rectangle
+ * @return the difference of maximum and minimum x3 coordinates of this triangular mesh within the specified rectangle
+ * @exception NullPointerException if no triangles are found within the specified rectangle
+ */
+double GbTriangularMesh3D::getX3RangeForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2) 
+{
+	throw UbException(UB_EXARGS,"not implemented");
+ //     GbPolygon3D polygon;
+ //     boolean     f     = false;
+ //     double      x3min = 0.0;
+ //     double      x3max = 0.0;
+ //     double      t1min, t1max, t2min, t2max;
+ //     double      area1 = Math.abs((p1x1-p2x1)*(p1x2-p2x2));
+ //     double      area2 = 0.0;
+
+ //     for(int i=0; i<this.triangles.length; i++)
+ //     {
+	// t1min = this.triangles[i].getX1Minimum();
+	// t1max = this.triangles[i].getX1Maximum();
+	// if(GbSystem.less2(t1min, t1max, p1x1, p2x1))    continue;
+	// if(GbSystem.greater2(t1min, t1max, p1x1, p2x1)) continue;
+
+	// t2min = this.triangles[i].getX2Minimum();
+	// t2max = this.triangles[i].getX2Maximum();
+	// if(GbSystem.less2(t2min, t2max, p1x2, p2x2))    continue;
+	// if(GbSystem.greater2(t2min, t2max, p1x2, p2x2)) continue;
+
+	// if(GbSystem.inOpenInterval(t1min, p1x1, p2x1) && GbSystem.inOpenInterval(t1max, p1x1, p2x1) &&
+	//    GbSystem.inOpenInterval(t2min, p1x2, p2x2) && GbSystem.inOpenInterval(t2max, p1x2, p2x2))
+	// {
+	//    if(f)
+	//    {
+	//       if(this.triangles[i].getX3Minimum() < x3min) x3min = this.triangles[i].getX3Minimum();
+	//       if(this.triangles[i].getX3Maximum() > x3max) x3max = this.triangles[i].getX3Maximum();
+	//    }
+	//    else
+	//    {
+	//       x3min = this.triangles[i].getX3Minimum();
+	//       x3max = this.triangles[i].getX3Maximum();
+	//       f     = true;
+	//    }
+	//    area2 += this.triangles[i].getArea();
+	//}
+	// else
+	// {
+	//    polygon = this.triangles[i].createClippedPolygon3D(p1x1, p1x2, p2x1, p2x2);
+
+	//    if(polygon != null && polygon.size() > 2)
+	//    {
+	//       if(f)
+	//       {
+	//          if(polygon.getX3Minimum() < x3min) x3min = polygon.getX3Minimum();
+	//          if(polygon.getX3Maximum() > x3max) x3max = polygon.getX3Maximum();
+	//       }
+	//       else
+	//       {
+	//          x3min = polygon.getX3Minimum();
+	//          x3max = polygon.getX3Maximum();
+	//          f     = true;
+	//       }
+	//       area2 += Math.abs(polygon.getArea());
+	//    }
+	// }
+	// if(GbSystem.greaterEqual(area2, area1)) break;
+ //     }
+ //     if(f) return(x3max-x3min);
+ //     else  throw new NullPointerException();
+}
+/**
+ * Returns the minimum x3 coordinates of this triangular mesh within the specified rectangle.
+ * @param p1x1 the 1st x1 coordinate of the rectangle
+ * @param p1x2 the 1st x2 coordinate of the rectangle
+ * @param p2x1 the 2nd x1 coordinate of the rectangle
+ * @param p2x2 the 2nd x2 coordinate of the rectangle
+ * @return the minimum x3 coordinates of this triangular mesh within the specified rectangle
+ * @exception NullPointerException if no triangles are found within the specified rectangle
+ */
+double GbTriangularMesh3D::getX3MinimumForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2) 
+{
+	throw UbException(UB_EXARGS,"not implemented");
+  //    GbPolygon3D polygon;
+  //    boolean     f     = false;
+  //    double      x3min = 0.0;
+  //    double      t1min, t1max, t2min, t2max;
+  //    double      area1 = Math.abs((p1x1-p2x1)*(p1x2-p2x2));
+  //    double      area2 = 0.0;
+
+  //    for(int i=0; i<this.triangles.length; i++)
+  //    {
+	 //t1min = this.triangles[i].getX1Minimum();
+	 //t1max = this.triangles[i].getX1Maximum();
+	 //if(GbSystem.less2(t1min, t1max, p1x1, p2x1))    continue;
+	 //if(GbSystem.greater2(t1min, t1max, p1x1, p2x1)) continue;
+
+	 //t2min = this.triangles[i].getX2Minimum();
+	 //t2max = this.triangles[i].getX2Maximum();
+	 //if(GbSystem.less2(t2min, t2max, p1x2, p2x2))    continue;
+	 //if(GbSystem.greater2(t2min, t2max, p1x2, p2x2)) continue;
+
+	 //if(GbSystem.inOpenInterval(t1min, p1x1, p2x1) && GbSystem.inOpenInterval(t1max, p1x1, p2x1) &&
+	 //   GbSystem.inOpenInterval(t2min, p1x2, p2x2) && GbSystem.inOpenInterval(t2max, p1x2, p2x2))
+	 //{
+	 //   if(f)
+	 //   {
+	 //      if(this.triangles[i].getX3Minimum() < x3min) x3min = this.triangles[i].getX3Minimum();
+	 //   }
+	 //   else
+	 //   {
+	 //      x3min = this.triangles[i].getX3Minimum();
+	 //      f     = true;
+	 //   }
+	 //   area2 += this.triangles[i].getArea();
+	 //}
+	 //else
+	 //{
+	 //   polygon = this.triangles[i].createClippedPolygon3D(p1x1, p1x2, p2x1, p2x2);
+
+	 //   if(polygon != null && polygon.size() > 2)
+	 //   {
+	 //      if(f)
+	 //      {
+	 //         if(polygon.getX3Minimum() < x3min) x3min = polygon.getX3Minimum();
+	 //      }
+	 //      else
+	 //      {
+	 //         x3min = polygon.getX3Minimum();
+	 //         f     = true;
+	 //      }
+	 //      area2 += Math.abs(polygon.getArea());
+	 //   }
+	 //}
+	 //if(GbSystem.greaterEqual(area2, area1)) break;
+  //    }
+  //    if(f) return(x3min);
+  //    else  throw new NullPointerException();
+}
+/**
+ * Returns the maximum x3 coordinates of this triangular mesh within the specified rectangle.
+ * @param p1x1 the 1st x1 coordinate of the rectangle
+ * @param p1x2 the 1st x2 coordinate of the rectangle
+ * @param p2x1 the 2nd x1 coordinate of the rectangle
+ * @param p2x2 the 2nd x2 coordinate of the rectangle
+ * @return the maximum x3 coordinates of this triangular mesh within the specified rectangle
+ * @exception NullPointerException if no triangles are found within the specified rectangle
+ */
+double GbTriangularMesh3D::getX3MaximumForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2) 
+{
+   throw UbException(UB_EXARGS,"not implemented");
+  //    GbPolygon3D polygon;
+  //    boolean     f     = false;
+  //    double      x3max = 0.0;
+  //    double      t1min, t1max, t2min, t2max;
+  //    double      area1 = Math.abs((p1x1-p2x1)*(p1x2-p2x2));
+  //    double      area2 = 0.0;
+
+  //    for(int i=0; i<this.triangles.length; i++)
+  //    {
+	 //t1min = this.triangles[i].getX1Minimum();
+	 //t1max = this.triangles[i].getX1Maximum();
+	 //if(GbSystem.less2(t1min, t1max, p1x1, p2x1))    continue;
+	 //if(GbSystem.greater2(t1min, t1max, p1x1, p2x1)) continue;
+
+	 //t2min = this.triangles[i].getX2Minimum();
+	 //t2max = this.triangles[i].getX2Maximum();
+	 //if(GbSystem.less2(t2min, t2max, p1x2, p2x2))    continue;
+	 //if(GbSystem.greater2(t2min, t2max, p1x2, p2x2)) continue;
+
+	 //if(GbSystem.inOpenInterval(t1min, p1x1, p2x1) && GbSystem.inOpenInterval(t1max, p1x1, p2x1) &&
+	 //   GbSystem.inOpenInterval(t2min, p1x2, p2x2) && GbSystem.inOpenInterval(t2max, p1x2, p2x2))
+	 //{
+	 //   if(f)
+	 //   {
+	 //      if(this.triangles[i].getX3Maximum() < x3max) x3max = this.triangles[i].getX3Maximum();
+	 //   }
+	 //   else
+	 //   {
+	 //      x3max = this.triangles[i].getX3Maximum();
+	 //      f     = true;
+	 //   }
+	 //   area2 += this.triangles[i].getArea();
+	 //}
+	 //else
+	 //{
+	 //   polygon = this.triangles[i].createClippedPolygon3D(p1x1, p1x2, p2x1, p2x2);
+
+	 //   if(polygon != null && polygon.size() > 2)
+	 //   {
+	 //      if(f)
+	 //      {
+	 //         if(polygon.getX3Maximum() < x3max) x3max = polygon.getX3Maximum();
+	 //      }
+	 //      else
+	 //      {
+	 //         x3max = polygon.getX3Maximum();
+	 //         f     = true;
+	 //      }
+	 //      area2 += Math.abs(polygon.getArea());
+	 //   }
+	 //}
+	 //if(GbSystem.greaterEqual(area2, area1)) break;
+  //    }
+  //    if(f) return(x3max);
+  //    else  throw new NullPointerException();
+}
+/*======================================================================*/
+vector<GbTriangle3D*> GbTriangularMesh3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> tris;
+   GbTriangle3D* triangle;
+   GbPoint3D* p1;
+   GbPoint3D* p2;
+   GbPoint3D* p3;
+   int size = (int)this->triangles->size();
+   for(int u=0; u<size;u++)
+   {
+      triangle = (*this->triangles)[u];
+      p1 = new GbPoint3D(triangle->getPoint1());
+      p2 = new GbPoint3D(triangle->getPoint2());
+      p3 = new GbPoint3D(triangle->getPoint3());
+      tris.push_back(new GbTriangle3D(p1, p2, p3));
+   }
+   return tris;
+}
+/*======================================================================*/
+/*
+* Function to determine if the point is inside the polyhedron defined as a 3D object
+* using the Halfspace algorithm
+* @param xp the x-coordinate of the point
+* @param yp the y-coordinate of the point
+* @param zp the z-coordinate of the point
+* @return true if point is inside else return false
+*/
+bool GbTriangularMesh3D::isPointInObject3DHalfSpace(const double& xp, const double& yp, const double& zp)
+{ 
+   vector<GbTriangle3D*> *Triangles = this->triangles;
+   int Trianglesize = (int)Triangles->size();
+   //GbPoint3D Point(xp,yp,zp);
+   for (int i=0; i<Trianglesize; i++)
+   {
+      //GbPoint3D* point1 = (*Triangles)[i]->getPoint1();
+      //GbPoint3D* point2 = (*Triangles)[i]->getPoint2();
+      //GbPoint3D* point3 = (*Triangles)[i]->getPoint3();
+
+      //GbHalfSpace3D halfspace(point1, point2, point3);
+      GbHalfSpace3D halfspace((*Triangles)[i]);
+      if (halfspace.ptInside(xp,yp,zp)) return false;
+   }
+   return true;
+}
+/*======================================================================*/
+bool GbTriangularMesh3D::isPointInObject3DRayCrossing(const double& xp, const double& yp, const double& zp, int radius, int numVertices, int numTriangles)
+{
+   GbVector3D point(xp,yp,zp);
+
+   if ( this->InPolyhedron(numTriangles, point, radius) ) return true;
+   else                                                   return false;
+   
+}
+/*======================================================================*/
+bool GbTriangularMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+{
+   double xmin=this->getX1Minimum();	double xmax=this->getX1Maximum();
+   double ymin=this->getX2Minimum();	double ymax=this->getX2Maximum();
+   double zmin=this->getX3Minimum();	double zmax=this->getX3Maximum();
+   double dX = (xmax-xmin)/100.;
+   double dY = (ymax-ymin)/100.;
+   double dZ = (zmax-zmin)/100.;
+   GbCuboid3D boundingCube(xmin-dX, ymin-dY, zmin-dZ, xmax+dX, ymax+dY, zmax+dZ);
+   if(!boundingCube.isPointInGbObject3D(x1, x2, x3)) { boundingCube.finalize(); return false; }
+
+   // Halfspace algorithm, Area of spherical polygons algorithm or Ray crossing algorithm
+   GbVector3D bMin(boundingCube.getPoint1());
+   GbVector3D bMax(boundingCube.getPoint2());
+
+   boundingCube.finalize();
+
+   bMin = bMax.Subtract(bMin);
+   int radius = (int)(bMin.Length()+1)+1;
+
+   if(this->pointinobjecttest == HALFSPACE)        return this->isPointInObject3DHalfSpace(x1,x2,x3);
+   else if(this->pointinobjecttest == RAYCROSSING) return this->isPointInObject3DRayCrossing(x1,x2,x3,radius,(int)this->nodes->size(),(int)this->triangles->size());
+   else throw UbException(UB_EXARGS,"no ptInObjTest");
+}
+/*======================================================================*/
+bool GbTriangularMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+{
+    throw UbException(UB_EXARGS,"not implemented");
+}
+/*======================================================================*/
+GbLine3D* GbTriangularMesh3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"not implemented");
+}
+/*======================================================================*/
+void GbTriangularMesh3D::writeMesh(string filename, WbWriter* writer, bool writeNormals) 
+{
+   vector<UbTupleFloat3 > nodes(triangles->size()*3);
+   vector<UbTupleInt3 >   tris(triangles->size());
+
+   for(size_t i=0; i<triangles->size(); i++)
+   {
+      GbTriangle3D&  tri = *((*triangles)[i]);
+      GbPoint3D&   node1 = *tri.getPoint(0);
+      GbPoint3D&   node2 = *tri.getPoint(1);
+      GbPoint3D&   node3 = *tri.getPoint(2);
+      
+      nodes[i*3  ] = makeUbTuple( (float)node1.getX1Coordinate()
+                                 ,(float)node1.getX2Coordinate()  
+                                 ,(float)node1.getX3Coordinate());
+      nodes[i*3+1] = makeUbTuple( (float)node2.getX1Coordinate()
+                                 ,(float)node2.getX2Coordinate()  
+                                 ,(float)node2.getX3Coordinate());
+      nodes[i*3+2] = makeUbTuple( (float)node3.getX1Coordinate()
+                                 ,(float)node3.getX2Coordinate()  
+                                 ,(float)node3.getX3Coordinate());
+
+      tris[i] = makeUbTuple((int)i*3,(int)i*3+1,(int)i*3+2);
+   }
+   writer->writeTriangles(filename,nodes,tris);
+   
+   if(writeNormals)
+   {
+      vector<UbTupleFloat3 > lineNodes(triangles->size()*2);
+      vector<UbTupleInt2 >   lines(triangles->size());
+      for(size_t i=0; i<triangles->size(); i++)
+      {
+         GbVector3D vec = (*triangles)[i]->getNormal();
+         lineNodes[i*2  ] = makeUbTuple( (float)(*triangles)[i]->getX1Centroid()
+                                        ,(float)(*triangles)[i]->getX2Centroid()  
+                                        ,(float)(*triangles)[i]->getX3Centroid());
+         lineNodes[i*2+1] = makeUbTuple( (float)((*triangles)[i]->getX1Centroid()+vec.X1())
+                                        ,(float)((*triangles)[i]->getX2Centroid()+vec.X2())  
+                                        ,(float)((*triangles)[i]->getX3Centroid()+vec.X3()));
+
+         lines[i] = makeUbTuple((int)i*2,(int)i*2+1);
+      }
+      writer->writeLines(filename+"_normals",lineNodes,lines);
+   }
+}
+/*======================================================================*/
+void GbTriangularMesh3D::writeAVSMesh(UbFileOutput *out, bool normals) 
+{
+   cout<<" - write_ucd ("<<out->getFileName()<<") -> ";
+   if(!out)
+   {
+      cout<<"GbTriangularMesh3D::writeAVSMesh() - File konnte nicht geschrieben werden: "<<endl;
+      return;
+   }
+   out->writeLine("# UCD-File created by GbTriangularMesh3D");
+   //vector<GbPoint3D*>     *nodes    = this->getNodes();
+   vector<GbTriangle3D*> *triangles = this->getTriangles();
+   //int nodesize     = (int)nodes->size();
+   int trianglesize = (int)triangles->size();
+   int nodesize     = trianglesize*3;
+   if(normals) 
+   {
+      out->writeInteger(nodesize+trianglesize*2);
+      out->writeInteger(trianglesize*2);
+   }
+   else
+   {
+      out->writeInteger(nodesize);
+      out->writeInteger(trianglesize);
+   }
+   out->writeInteger(0);
+   out->writeInteger(0);
+   out->writeInteger(0);
+   out->writeLine();
+   int nr=1;
+   GbPoint3D *node;
+   for(int i=0;i<trianglesize; i++)
+   {
+      node = (*triangles)[i]->getPoint(0); 
+      out->writeInteger(nr++);
+      out->writeDouble(node->getX1Coordinate());
+      out->writeDouble(node->getX2Coordinate());
+      out->writeDouble(node->getX3Coordinate());
+      out->writeLine();
+      node = (GbPoint3D*)(*triangles)[i]->getPoint(1); 
+      out->writeInteger(nr++);
+      out->writeDouble(node->getX1Coordinate());
+      out->writeDouble(node->getX2Coordinate());
+      out->writeDouble(node->getX3Coordinate());
+      out->writeLine();
+      node = (GbPoint3D*)(*triangles)[i]->getPoint(2); 
+      out->writeInteger(nr++);
+      out->writeDouble(node->getX1Coordinate());
+      out->writeDouble(node->getX2Coordinate());
+      out->writeDouble(node->getX3Coordinate());
+      out->writeLine();
+   }
+
+   if(normals) 
+   {
+      for(int i=0;i<trianglesize; i++)
+      {
+         GbVector3D vec = (*triangles)[i]->getNormal();
+         out->writeInteger(nr++);
+         out->writeDouble((*triangles)[i]->getX1Centroid());
+         out->writeDouble((*triangles)[i]->getX2Centroid());
+         out->writeDouble((*triangles)[i]->getX3Centroid());
+         out->writeLine();
+         out->writeInteger(nr++);
+         out->writeDouble((*triangles)[i]->getX1Centroid()+vec.X1());
+         out->writeDouble((*triangles)[i]->getX2Centroid()+vec.X2());
+         out->writeDouble((*triangles)[i]->getX3Centroid()+vec.X3());
+         out->writeLine();
+      }
+   }
+   nr=1;
+   int el=1;
+   for(int i=0;i<trianglesize; i++)
+   {
+      nr = 3*el-2;
+      out->writeInteger(el);
+      out->writeInteger(2);
+      out->writeString("tri");
+      out->writeInteger(nr);
+      out->writeInteger(nr+1);
+      out->writeInteger(nr+2);
+      out->writeLine();
+      el++;
+   }
+   if(normals)
+   {
+      nr = trianglesize*3+1;
+      for(int i=trianglesize;i<2*trianglesize; i++)
+      {
+         out->writeInteger(el);
+         out->writeInteger(2);
+         out->writeString("line");
+         out->writeInteger(nr++);
+         out->writeInteger(nr++);
+         out->writeLine();
+         el++;
+      }
+   }
+   cout<<"done\n";
+}
+
+/*======================================================================*/
+/*
+This function returns a char:
+'V': the query point a coincides with a Vertex of polyhedron P.
+'E': the query point a is in the relative interior of an Edge of polyhedron P.
+'F': the query point a is in the relative interior of a Face of polyhedron P.
+'i': the query point a is strictly interior to polyhedron P.
+'o': the query point a is strictly exterior to( or outside of) polyhedron P.
+*/
+bool GbTriangularMesh3D::InPolyhedron( int F, GbVector3D& q, int radius )
+{
+   GbVector3D r;  /* Ray endpoint. */
+   GbVector3D p;  /* Intersection point; not used. */
+   int f, k = 0, crossings = 0;
+   char code = '?';
+
+   while( k++ < F ) 
+   {
+      crossings = 0;
+
+      RandomRay( r, radius ); 
+      r = q.Add(r);
+      // printf("Ray endpoint: (%d,%d,%d)\n", r[0],r[1],r[2] );
+
+      for ( f = 0; f < F; f++ )  /* Begin check each face */
+      {
+          if( BoxTest( (*this->triangles)[f], q, r ) == false ) code = '0'; // printf("BoxTest = 0!\n");
+         else                                                  code = SegTriInt( (*this->triangles)[f], q, r, p );// printf( "Face = %d: BoxTest/SegTriInt returns %c\n\n", f, code );
+
+         /* If ray is degenerate, then goto outer while to generate another. */
+         if( code=='p' || code=='v' || code=='e' ) break; //goto LOOP; //printf("Degenerate ray\n");
+         /* If ray hits face at interior point, increment crossings. */
+         else if ( code=='f' ) crossings++; // printf( "crossings = %d\n", crossings );
+         /* If query endpoint q sits on a V/E/F, return that code. */
+         else if ( code=='V' || code=='E' || code=='F' ) return true;
+         /* If ray misses triangle, do nothing. */
+         else if ( code=='0' ) { /*nothing to do*/ }
+         else throw UbException(UB_EXARGS,"Error" );
+      } /* End check each face */
+
+      /* No degeneracies encountered: ray is generic, so finished. */
+      if(f>=F) break;
+   } /* End while loop */
+
+   //   printf( "Crossings = %d\n", crossings );
+   /* q strictly interior to polyhedron iff an odd number of crossings. */
+   if( (crossings%2) == 1 ) return true;
+   
+   return false;
+}
+
+/* Return a random ray endpoint */
+void GbTriangularMesh3D::RandomRay( GbVector3D& ray, int radius )
+{
+   double x, y, z, w, t;
+
+   double MAX_INT = 2147483647;
+   /* Generate a random point on a sphere of radius 1. */
+   /* the sphere is sliced at z, and a random point at angle t
+   generated on the circle of intersection. */
+   z = 2.0 * (double) rand() / MAX_INT - 1.0;
+   t = 2.0 * UbMath::PI * (double) rand() / MAX_INT;
+   w = sqrt( 1 - z*z );
+   x = w * cos( t );
+   y = w * sin( t );
+
+   ray[0] = radius * x;
+   ray[1] = radius * y;
+   ray[2] = radius * z;
+
+   /*printf( "RandomRay returns %6d %6d %6d\n", ray[X], ray[Y], ray[Z] );*/
+}
+
+/*---------------------------------------------------------------------
+'p': The segment lies wholly within the plane.
+'q': The q endpoint is on the plane (but not 'p').
+'r': The r endpoint is on the plane (but not 'p').
+'0': The segment lies strictly to one side or the other of the plane.
+'1': The segement intersects the plane, and 'p' does not hold.
+---------------------------------------------------------------------*/
+char	GbTriangularMesh3D::SegPlaneInt( GbTriangle3D* T, GbVector3D& q, GbVector3D& r, GbVector3D& p, int *m)
+{
+  // cout<<"SegPlaneInt..\n";
+   GbVector3D N; double D;
+   GbVector3D rq;
+   double num, denom, t;
+   int i;
+
+   *m = PlaneCoeff( T, N, &D );
+   /*printf("m=%d; plane=(%lf,%lf,%lf,%lf)\n", m, N[X],N[Y],N[Z],D);*/
+   num = D - q.Dot( N );
+   rq = r.Subtract( q );
+   denom = rq.Dot( N );
+   /*printf("SegPlaneInt: num=%lf, denom=%lf\n", num, denom );*/
+
+   if ( denom == 0.0 ) {  /* Segment is parallel to plane. */
+      if ( num == 0.0 )   /* q is on plane. */
+   //if (UbMath::zero(denom)) {  /* Segment is parallel to plane. */
+   //   if ( UbMath::zero(num))   /* q is on plane. */
+         return 'p';
+      else
+         return '0';
+   }
+   else
+      t = num / denom;
+   /*printf("SegPlaneInt: t=%lf \n", t );*/
+
+   for( i = 0; i < 3; i++ )
+      p[i] = q[i] + t * ( r[i] - q[i] );
+
+   if ( (0.0 < t) && (t < 1.0) )
+      return '1';
+   else if ( num == 0.0 )   /* t == 0 */
+      return 'q';
+   else if ( num == denom ) /* t == 1 */
+      return 'r';
+   else return '0';
+
+   //if ( (0.0 < t) && (t < 1.0) )
+   //   return '1';
+   //else if ( UbMath::zero(num))   /* t == 0 */
+   //   return 'q';
+   //else if ( UbMath::equal(num , denom) ) /* t == 1 */
+   //   return 'r';
+   //else return '0';
+
+}
+/*---------------------------------------------------------------------
+Computes N & D and returns index m of largest component.
+---------------------------------------------------------------------*/
+int	GbTriangularMesh3D::PlaneCoeff( GbTriangle3D* T, GbVector3D& N, double *D )
+{
+   int i;
+   double t;              /* Temp storage */
+   double biggest = 0.0;  /* Largest component of normal vector. */
+   int m = 0;             /* Index of largest component. */
+
+   N = T->getNormal();
+   /*printf("PlaneCoeff: N=(%lf,%lf,%lf)\n", N[X],N[Y],N[Z]);*/
+   GbVector3D a(T->getPoint1());
+
+   *D = a.Dot( N );
+
+   /* Find the largest component of N. */
+   for ( i = 0; i < 3; i++ )
+   {
+      t = std::fabs( N[i] );
+      if ( t > biggest ) 
+      {
+         biggest = t;
+         m = i;
+      }
+   }
+   return m;
+}
+
+/* Assumption: p lies in the plane containing T.
+Returns a char:
+'V': the query point p coincides with a Vertex of triangle T.
+'E': the query point p is in the relative interior of an Edge of triangle T.
+'F': the query point p is in the relative interior of a Face of triangle T.
+'0': the query point p does not intersect (misses) triangle T.
+*/
+
+char 	GbTriangularMesh3D::InTri3D( GbTriangle3D* T, int m, GbVector3D& p )
+{
+//   int i;           /* Index for X,Y,Z           */
+   int j;           /* Index for X,Y             */
+//   int k;           /* Index for triangle vertex */
+   GbVector3D pp;      /* projected p */
+   GbVector3D Tp[3];   /* projected T: three new vertices */
+
+   /* Project out coordinate m in both p and the triangular face */
+   //j = 0;
+   //for ( i = 0; i < 3; i++ ) {
+   //   if ( i != m ) {    /* skip largest coordinate */
+   //      pp[j] = p[i];
+   //      //for ( k = 0; k < 3; k++ )
+   //         std::cout<<"aachtung###############################################";
+   //      //            Tp[k][j] = Vertices[T[k]][i];
+   //      j++;
+   //   }
+   //}
+   j=0;
+   if(m!=0)
+   {
+      Tp[0][j] = T->getPoint1()->getX1Coordinate();
+      Tp[1][j] = T->getPoint2()->getX1Coordinate();
+      Tp[2][j] = T->getPoint3()->getX1Coordinate();
+      j++;
+   }
+   if(m!=1)
+   {
+      Tp[0][j] = T->getPoint1()->getX2Coordinate();
+      Tp[1][j] = T->getPoint2()->getX2Coordinate();
+      Tp[2][j] = T->getPoint3()->getX2Coordinate();
+      j++;
+   }
+   if(m!=2)
+   {
+      Tp[0][j] = T->getPoint1()->getX3Coordinate();
+      Tp[1][j] = T->getPoint2()->getX3Coordinate();
+      Tp[2][j] = T->getPoint3()->getX3Coordinate();
+      j++;
+   }
+
+   return( InTri2D( Tp, pp ) );
+}
+
+char 	GbTriangularMesh3D::InTri2D( GbVector3D Tp[3], GbVector3D& pp )
+{
+   double area0, area1, area2;
+
+   /* compute three AreaSign() values for pp w.r.t. each edge of the face in 2D */
+   area0 = AreaSign( pp, Tp[0], Tp[1] );
+   area1 = AreaSign( pp, Tp[1], Tp[2] );
+   area2 = AreaSign( pp, Tp[2], Tp[0] );
+ //  printf("area0=%f  area1=%f  area2=%f\n",area0,area1,area2);
+
+   if ( ( area0 == 0. ) && ( area1 > 0. ) && ( area2 > 0. ) ||
+      ( area1 == 0. ) && ( area0 > 0. ) && ( area2 > 0. ) ||
+      ( area2 == 0. ) && ( area0 > 0. ) && ( area1 > 0. ) ) 
+      return 'E';
+ 
+   if ( ( area0 == 0. ) && ( area1 < 0. ) && ( area2 < 0. ) ||
+      ( area1 == 0. ) && ( area0 < 0. ) && ( area2 < 0. ) ||
+      ( area2 == 0. ) && ( area0 < 0. ) && ( area1 < 0. ) )
+      return 'E';                 
+
+   if ( ( area0 >  0. ) && ( area1 > 0. ) && ( area2 > 0. ) ||
+      ( area0 <  0. ) && ( area1 < 0. ) && ( area2 < 0. ) )
+      return 'F';
+
+   if ( ( area0 == 0.0 ) && ( area1 == 0.0 ) && ( area2 == 0.0 ) )
+      fprintf( stderr, "Error in InTriD\n" ), exit(EXIT_FAILURE);
+
+   if ( ( area0 == 0. ) && ( area1 == 0. ) ||
+      ( area0 == 0. ) && ( area2 == 0. ) ||
+      ( area1 == 0. ) && ( area2 == 0. ) )
+      return 'V';
+
+   else  
+      return '0';  
+}
+
+double GbTriangularMesh3D::AreaSign( GbVector3D& a, GbVector3D& b, GbVector3D& c )  
+{
+   double area2;
+
+   area2 = ( b[0] - a[0] ) * ( c[1] - a[1] ) -
+           ( c[0] - a[0] ) * ( b[1] - a[1] );
+
+   return area2;
+   /* The area should be an integer. */
+   if      ( area2 >  0.5 ) return  1;
+   else if ( area2 < -0.5 ) return -1;
+   else                     return  0;
+}                            
+
+char    GbTriangularMesh3D::SegTriInt( GbTriangle3D* T, GbVector3D& q, GbVector3D& r, GbVector3D& p )
+{
+   int code = '?';
+   int m = -1;
+
+   code = SegPlaneInt( T, q, r, p, &m );
+   //  printf("SegPlaneInt code=%c, m=%d; p=(%lf,%lf,%lf)\n", code,m,p[0],p[1],p[2]);
+
+   if      ( code == '0')  return '0';
+   else if ( code == 'q')  return InTri3D( T, m, q );
+   else if ( code == 'r')  return InTri3D( T, m, r );
+   else if ( code == 'p' ) return InPlane( T, m, q, r, p );
+   else if ( code == '1' ) return SegTriCross( T, q, r );
+   else /* Error */        return code;
+}
+
+char	GbTriangularMesh3D::InPlane( GbTriangle3D* T, int m, GbVector3D& q, GbVector3D& r, GbVector3D& p)
+{
+  // cout<<"inplane\n";
+   /* NOT IMPLEMENTED */
+   return 'p';
+}
+
+/*---------------------------------------------------------------------
+The signed volumes of three tetrahedra are computed, determined
+by the segment qr, and each edge of the triangle.  
+Returns a char:
+'v': the open segment includes a vertex of T.
+'e': the open segment includes a point in the relative interior of an edge
+of T.
+'f': the open segment includes a point in the relative interior of a face
+of T.
+'0': the open segment does not intersect triangle T.
+---------------------------------------------------------------------*/
+
+char GbTriangularMesh3D::SegTriCross( GbTriangle3D* T, GbVector3D& q, GbVector3D& r )
+{
+  // cout<<"SegTriCross\n";
+   double vol0, vol1, vol2;
+   GbVector3D vert0(T->getPoint1());
+   GbVector3D vert1(T->getPoint2());
+   GbVector3D vert2(T->getPoint3());
+
+   vol0 = VolumeSign( q, vert0, vert1, r ); 
+   vol1 = VolumeSign( q, vert1, vert2, r ); 
+   vol2 = VolumeSign( q, vert2, vert0, r );
+
+   //  printf( "SegTriCross:  vol0 = %d; vol1 = %d; vol2 = %d\n", vol0, vol1, vol2 ); 
+
+   /* Same sign: segment intersects interior of triangle. */
+   if ( ( ( vol0 > 0. ) && ( vol1 > 0. ) && ( vol2 > 0. ) ) || 
+      ( ( vol0 < 0. ) && ( vol1 < 0. ) && ( vol2 < 0. ) ) )
+   //if ( ( UbMath::greater(vol0, 0. ) && UbMath::greater(vol1 , 0. ) && UbMath::greater(vol2 , 0. ) ) || 
+   //     ( UbMath::less(vol0, 0. ) && UbMath::less(vol1, 0. ) && UbMath::less(vol2, 0. ) ) )
+   {
+      return 'f';
+   }
+
+   /* Opposite sign: no intersection between segment and triangle */
+   if ( ( ( vol0 > 0. ) || ( vol1 > 0. ) || ( vol2 > 0. ) ) &&
+      ( ( vol0 < 0. ) || ( vol1 < 0. ) || ( vol2 < 0. ) ) )
+   {
+      return '0';
+   }
+   else if ( ( vol0 == 0.0 ) && ( vol1 == 0.0 ) && ( vol2 == 0.0 ) )
+   {
+      std::cout<<vol0<<" "<<vol1<<" "<<vol2<<std::endl;
+      fprintf( stderr, "Error 1 in SegTriCross\n" ), exit(EXIT_FAILURE);
+   }
+
+   /* Two zeros: segment intersects vertex. */
+   else if ( ( ( vol0 == 0. ) && ( vol1 == 0. ) ) || 
+      ( ( vol0 == 0. ) && ( vol2 == 0. ) ) || 
+      ( ( vol1 == 0. ) && ( vol2 == 0. ) ) )
+   {
+      return 'v';
+   }
+
+   /* One zero: segment intersects edge. */
+   else if ( ( vol0 == 0. ) || ( vol1 == 0. ) || ( vol2 == 0. ) )
+   {
+      return 'e';
+   }
+   
+   throw UbException(UB_EXARGS,"fprintf( stderr, Error 2 in SegTriCross\n ), exit(EXIT_FAILURE);");
+}
+
+
+double GbTriangularMesh3D::VolumeSign( GbVector3D& a, GbVector3D& b, GbVector3D& c, GbVector3D& d )
+{ 
+   double vol;
+   double ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz;
+   double bxdx, bydy, bzdz, cxdx, cydy, czdz;
+
+   ax = a[0];   ay = a[1];   az = a[2];
+   bx = b[0];   by = b[1];   bz = b[2];
+   cx = c[0];   cy = c[1];   cz = c[2];
+   dx = d[0];   dy = d[1];   dz = d[2];
+
+   bxdx=bx-dx;
+   bydy=by-dy;
+   bzdz=bz-dz;
+   cxdx=cx-dx;
+   cydy=cy-dy;
+   czdz=cz-dz;
+   vol = (az-dz) * (bxdx*cydy - bydy*cxdx)
+      + (ay-dy) * (bzdz*cxdx - bxdx*czdz)
+      + (ax-dx) * (bydy*czdz - bzdz*cydy);
+
+   //std::cout<< vol<<std::endl;
+   return vol;
+
+
+   /* The volume should be an integer. */
+   if      ( vol > 0.5 )   return  1;
+   else if ( vol < -0.5 )  return -1;
+   else                    return  0;
+}
+
+bool GbTriangularMesh3D::BoxTest(GbTriangle3D* triangle, GbVector3D& PointQ, GbVector3D& PointR)
+{
+   double minX1 = triangle->getX1Minimum();
+   double minX2 = triangle->getX2Minimum();
+   double minX3 = triangle->getX3Minimum();
+
+   double maxX1 = triangle->getX1Maximum();
+   double maxX2 = triangle->getX2Maximum();
+   double maxX3 = triangle->getX3Maximum();
+
+   if((PointQ.X1() < minX1) && (PointR.X1() < minX1)) return false;
+   if((PointQ.X2() < minX2) && (PointR.X2() < minX2)) return false;
+   if((PointQ.X3() < minX3) && (PointR.X3() < minX3)) return false;
+   if((PointQ.X1() > maxX1) && (PointR.X1() > maxX1)) return false;
+   if((PointQ.X2() > maxX2) && (PointR.X2() > maxX2)) return false;
+   if((PointQ.X3() > maxX3) && (PointR.X3() > maxX3)) return false;
+
+   return true;
+}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbTriangularMesh3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbTriangularMesh3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8185e6e4a415c221632edc20541d01f828e59dd
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbTriangularMesh3D.h
@@ -0,0 +1,183 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBTRIANGULARMESH_H
+#define GBTRIANGULARMESH_H
+
+#include <sstream>
+#include <iostream>
+
+
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>                
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/GbVector3D.h>
+
+#include <basics/writer/WbWriter.h>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbTriangularMesh3D;
+typedef VFSharedPtr<GbTriangularMesh3D> GbTriangularMesh3DPtr;
+
+
+
+/*=========================================================================*/
+/* GbTriangularMesh3D                                                                  */
+/*                                                                         */
+/**
+ * This Class provides the triangular meshes.
+ * Note, that up to now no methods for checking consistency are included.
+ * in this context this class describes facettes from an 3D-object !!!
+*/
+class GbTriangularMesh3D : public GbObject3D 
+{                             
+public:
+   enum POINTINOBJECTTEST { RAYCROSSING, HALFSPACE};
+
+   GbTriangularMesh3D();
+	GbTriangularMesh3D(std::string name, std::vector<GbPoint3D*> *nodes, std::vector<GbTriangle3D*> *triangles);
+   GbTriangularMesh3D(std::string name, std::vector<GbTriangle3D*> *triangles);
+   GbTriangularMesh3D(std::string name, std::vector<GbPoint3D*> *nodes, std::vector<GbLine3D*> *edges, std::vector<GbTriangle3D*> *triangles);
+	~GbTriangularMesh3D();   
+   GbTriangularMesh3D* clone() { throw UbException(UB_EXARGS,"not implemented"); }
+   void finalize()
+   {
+      throw UbException("GbTriangularMesh3D::finalize() - toDo");
+   }
+   void setPointInObjectTest(POINTINOBJECTTEST mode) { this->pointinobjecttest = mode; }
+
+   std::string getClassName() {return "GbTriangularMesh3D"; }
+
+   std::string toString();
+   //std::string getName();
+   std::vector<GbPoint3D*>*    getNodes();
+   std::vector<GbTriangle3D*>* getTriangles();
+   double getX1Centroid();
+   double getX2Centroid();
+	double getX3Centroid();
+   double getX1Minimum();
+   double getX1Maximum();
+   double getX2Minimum();
+   double getX2Maximum();
+   double getX3Minimum();
+   double getX3Maximum();
+
+   void rotate(const double& alpha, const double& beta, const double& gamma);
+   void translate(const double& x1, const double& x2, const double& x3);
+
+   void calculateValues();
+   void deleteRedundantNodes();
+   
+   UbTupleDouble6 calculateMomentOfInertia(double rhoP);
+   UbTupleDouble3 calculateCenterOfGravity();
+   
+   double getArea();
+   double getVolume();
+   double getVolumeForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2);
+   std::vector<GbTriangle3D*>* getTrianglesForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2);
+   std::vector<GbPoint3D*>* getNodesForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2);
+   double getX3RangeForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2);
+   double getX3MinimumForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2);
+   double getX3MaximumForRectangle(const double& p1x1, const double& p1x2, const double& p2x1, const double& p2x2); 
+
+   virtual bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary);
+
+   bool isPointInObject3DHalfSpace(const double& xp, const double& yp, const double& zp);    //based on Halfspace algorithm
+   bool isPointInObject3DSpherical(const double& xp, const double& yp, const double& zp, int numTriangles);    //based on Spherical polygon area method        
+
+   //should be checked !!!                       
+   bool isPointInObject3DRayCrossing(const double& xp, const double& yp, const double& zp, int radius, int numVertices, int numTriangles);  //based on Ray tracing algorithm
+
+   bool   InPolyhedron( int F, GbVector3D& q, int radius );
+   void   RandomRay( GbVector3D& ray, int radius );
+   char	 SegPlaneInt( GbTriangle3D* Tri, GbVector3D& q, GbVector3D& r, GbVector3D& p, int *m);
+   int	 PlaneCoeff( GbTriangle3D* Tri, GbVector3D& Normal, double *D );
+   char 	 InTri3D( GbTriangle3D* T, int m, GbVector3D& p );
+   char 	 InTri2D( GbVector3D Tp[3], GbVector3D& pp );
+   double AreaSign( GbVector3D& a, GbVector3D& b, GbVector3D& c );
+   char   SegTriInt(GbTriangle3D* Tri, GbVector3D& q, GbVector3D& r, GbVector3D& p );
+   char	 InPlane( GbTriangle3D* T, int m, GbVector3D& q, GbVector3D& r, GbVector3D& p);
+   char   SegTriCross( GbTriangle3D* T, GbVector3D& q, GbVector3D& r );
+   double VolumeSign( GbVector3D& a, GbVector3D& b, GbVector3D& c, GbVector3D& d );
+   bool   BoxTest ( GbTriangle3D* triangle, GbVector3D& PointQ, GbVector3D& PointR);
+   //till here !!!
+
+
+   virtual GbLine3D* createClippedLine3D (GbPoint3D &point1,GbPoint3D &point2);
+   virtual std::vector<GbTriangle3D*> getSurfaceTriangleSet();     
+   virtual ObObjectCreator* getCreator();
+
+   virtual void write(UbFileOutput* out) { std::cout<<"GbTriangularMesh3D::write - sorry not implemented\n"; }
+   virtual void read(UbFileInput* in)    { std::cout<<"GbTriangularMesh3D::read  - sorry not implemented\n"; }
+
+   void writeMesh(std::string filename, WbWriter* writer, bool writeNormals=false);
+   void writeAVSMesh(UbFileOutput* out, bool normals=false);
+
+   /*======================================================================*/
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & triangles;
+      if(ArchiveTools::isWriting(ar))
+      {
+         for(std::size_t t=0; t<triangles->size(); t++)
+         {
+            nodes->push_back((*triangles)[t]->getPoint(0));
+            nodes->push_back((*triangles)[t]->getPoint(1));
+            nodes->push_back((*triangles)[t]->getPoint(2));
+         }
+      }
+      //ar & nodes; //<- problem redundanz
+      //ar & edges;
+      ar & pointinobjecttest;
+      ar & x1min;
+      ar & x1max;
+      ar & x2min;
+      ar & x2max;
+      ar & x3min;
+      ar & x3max;
+      ar & consistent;
+   }
+#endif //CAB_RCF
+
+protected:
+   std::vector<GbPoint3D*>*    nodes;
+   std::vector<GbLine3D*>*     edges;
+   std::vector<GbTriangle3D*>* triangles;
+
+private:
+   POINTINOBJECTTEST pointinobjecttest;
+   void init();
+   /*======================================================================*/
+   double      x1min;
+   double      x1max;
+   double      x2min;
+   double      x2max;
+   double      x3min;
+   double      x3max;
+   bool        consistent;
+};
+/*=========================================================================*/
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   #if CAB_RCF <= 903 
+      SF_SERIALIZE_ENUM(GbTriangularMesh3D::POINTINOBJECTTEST) //bei klassen ausserhalb der klasse;-)
+   #endif
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbTriangularMesh3D >("GbTriangularMesh3D ")    , SF_GbTriangularMesh3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbTriangularMesh3D >() ), SF_GbTriangularMesh3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbVector3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbVector3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7012909d2376a91a0eb399711cb5b3f81c3f8ed0
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbVector3D.cpp
@@ -0,0 +1,643 @@
+#include <numerics/geometry3d/GbVector3D.h>
+
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbInfinity.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+                                
+using namespace std;
+
+
+const GbVector3D GbVector3D::ZERO(0.0,0.0,0.0);
+const GbVector3D GbVector3D::UNIT_X1(1.0,0.0,0.0);
+const GbVector3D GbVector3D::UNIT_X2(0.0,1.0,0.0);
+const GbVector3D GbVector3D::UNIT_X3(0.0,0.0,1.0);
+
+//----------------------------------------------------------------------------
+GbVector3D::GbVector3D () 
+{                                      
+   m_afTuple[0] = 0.0;
+   m_afTuple[1] = 0.0;
+   m_afTuple[2] = 0.0;
+}
+//----------------------------------------------------------------------------
+GbVector3D::GbVector3D (const double& fX, const double& fY, const double& fZ) 
+{
+   m_afTuple[0] = fX;
+   m_afTuple[1] = fY;
+   m_afTuple[2] = fZ;
+}
+//----------------------------------------------------------------------------
+GbVector3D::GbVector3D (const GbVector3D& rkV) 
+{
+   m_afTuple[0] = rkV.m_afTuple[0];
+   m_afTuple[1] = rkV.m_afTuple[1];
+   m_afTuple[2] = rkV.m_afTuple[2];
+}
+//----------------------------------------------------------------------------
+
+GbVector3D::GbVector3D (const GbPoint3D& point) 
+{
+   m_afTuple[0] = point.x1;
+   m_afTuple[1] = point.x2;
+   m_afTuple[2] = point.x3;
+}
+
+//----------------------------------------------------------------------------
+string GbVector3D::toString()
+{
+   std::stringstream ss;
+   ss<< "GbVector3D["<<m_afTuple[0]<<","<<m_afTuple[1]<<","<<m_afTuple[2]<<"]";
+   ss<<endl;
+   return((ss.str()).c_str());
+}
+//----------------------------------------------------------------------------
+GbVector3D::operator const double* () const
+{
+   return m_afTuple;
+}
+//----------------------------------------------------------------------------
+GbVector3D::operator double* ()
+{
+   return m_afTuple;
+}
+//----------------------------------------------------------------------------
+double GbVector3D::operator[] (int i) const
+{
+   assert( 0 <= i && i <= 2 );
+   if ( i < 0 )
+      i = 0;
+   else if ( i > 2 )
+      i = 2;
+
+   return m_afTuple[i];
+}
+//----------------------------------------------------------------------------
+double& GbVector3D::operator[] (int i)
+{
+   assert( 0 <= i && i <= 2 );
+   if ( i < 0 )
+      i = 0;
+   else if ( i > 2 )
+      i = 2;
+
+   return m_afTuple[i];
+}
+//----------------------------------------------------------------------------
+double GbVector3D::X1 () const
+{
+   return m_afTuple[0];
+}
+//----------------------------------------------------------------------------
+double& GbVector3D::X1 ()
+{
+   return m_afTuple[0];
+}
+//----------------------------------------------------------------------------
+double GbVector3D::X2 () const
+{
+   return m_afTuple[1];
+}
+//----------------------------------------------------------------------------
+double& GbVector3D::X2 ()
+{
+   return m_afTuple[1];
+}
+//----------------------------------------------------------------------------
+double GbVector3D::X3 () const
+{
+   return m_afTuple[2];
+}
+//----------------------------------------------------------------------------
+double& GbVector3D::X3 ()
+{
+   return m_afTuple[2];
+}
+//----------------------------------------------------------------------------
+GbVector3D& GbVector3D::operator= (const GbVector3D& rkV)
+{
+   m_afTuple[0] = rkV.m_afTuple[0];
+   m_afTuple[1] = rkV.m_afTuple[1];
+   m_afTuple[2] = rkV.m_afTuple[2];
+   return *this;
+}
+//----------------------------------------------------------------------------
+int GbVector3D::CompareArrays (const GbVector3D& rkV) const
+{
+   return memcmp(m_afTuple,rkV.m_afTuple,3*sizeof(double));
+}
+//----------------------------------------------------------------------------
+bool GbVector3D::operator== (const GbVector3D& rkV) const
+{
+   return CompareArrays(rkV) == 0;
+}
+//----------------------------------------------------------------------------
+bool GbVector3D::operator!= (const GbVector3D& rkV) const
+{
+   return CompareArrays(rkV) != 0;
+}
+//----------------------------------------------------------------------------
+bool GbVector3D::operator< (const GbVector3D& rkV) const
+{
+   return CompareArrays(rkV) < 0;
+}
+//----------------------------------------------------------------------------
+bool GbVector3D::operator<= (const GbVector3D& rkV) const
+{
+   return CompareArrays(rkV) <= 0;
+}
+//----------------------------------------------------------------------------
+bool GbVector3D::operator> (const GbVector3D& rkV) const
+{
+   return CompareArrays(rkV) > 0;
+}
+//----------------------------------------------------------------------------
+bool GbVector3D::operator>= (const GbVector3D& rkV) const
+{
+   return CompareArrays(rkV) >= 0;
+}
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::operator+ (const GbVector3D& rkV) const
+{
+   return GbVector3D(
+      m_afTuple[0]+rkV.m_afTuple[0],
+      m_afTuple[1]+rkV.m_afTuple[1],
+      m_afTuple[2]+rkV.m_afTuple[2]);
+}
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::Add(GbVector3D& vector)
+{
+   return GbVector3D(
+      m_afTuple[0]+vector.m_afTuple[0],
+      m_afTuple[1]+vector.m_afTuple[1],
+      m_afTuple[2]+vector.m_afTuple[2]);
+}
+
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::operator- (const GbVector3D& rkV) const
+{
+   return GbVector3D(
+      m_afTuple[0]-rkV.m_afTuple[0],
+      m_afTuple[1]-rkV.m_afTuple[1],
+      m_afTuple[2]-rkV.m_afTuple[2]);
+}
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::Subtract(GbVector3D& vector)
+{
+   return GbVector3D(
+      m_afTuple[0]-vector.m_afTuple[0],
+      m_afTuple[1]-vector.m_afTuple[1],
+      m_afTuple[2]-vector.m_afTuple[2]);
+}
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::operator* (const double& fScalar) const
+{
+   return GbVector3D( fScalar*m_afTuple[0],
+                      fScalar*m_afTuple[1],
+                      fScalar*m_afTuple[2]);
+}
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::operator/ (const double& fScalar) const
+{
+   GbVector3D kQuot;
+
+   if ( fScalar != 0.0 )
+   {
+      double fInvScalar = 1.0/fScalar;
+      kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0];
+      kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1];
+      kQuot.m_afTuple[2] = fInvScalar*m_afTuple[2];
+   }
+   else
+   {
+      kQuot.m_afTuple[0] = Ub::inf;
+      kQuot.m_afTuple[1] = Ub::inf;
+      kQuot.m_afTuple[2] = Ub::inf;
+   }
+
+   return kQuot;
+}
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::operator- () const
+{
+   return GbVector3D(
+      -m_afTuple[0],
+      -m_afTuple[1],
+      -m_afTuple[2]);
+}
+//----------------------------------------------------------------------------
+GbVector3D operator* (const double& fScalar, const GbVector3D& rkV)
+{
+   return GbVector3D(
+      fScalar*rkV[0],
+      fScalar*rkV[1],
+      fScalar*rkV[2]);
+}
+//----------------------------------------------------------------------------
+GbVector3D& GbVector3D::operator+= (const GbVector3D& rkV)
+{
+   m_afTuple[0] += rkV.m_afTuple[0];
+   m_afTuple[1] += rkV.m_afTuple[1];
+   m_afTuple[2] += rkV.m_afTuple[2];
+   return *this;
+}
+//----------------------------------------------------------------------------
+GbVector3D& GbVector3D::operator-= (const GbVector3D& rkV)
+{
+   m_afTuple[0] -= rkV.m_afTuple[0];
+   m_afTuple[1] -= rkV.m_afTuple[1];
+   m_afTuple[2] -= rkV.m_afTuple[2];
+   return *this;
+}
+//----------------------------------------------------------------------------
+GbVector3D& GbVector3D::operator*= (const double& fScalar)
+{
+   m_afTuple[0] *= fScalar;
+   m_afTuple[1] *= fScalar;
+   m_afTuple[2] *= fScalar;
+   return *this;
+}
+//----------------------------------------------------------------------------
+GbVector3D& GbVector3D::operator/= (const double& fScalar)
+{
+   if ( fScalar != (double)0.0 )
+   {
+      double fInvScalar = ((double)1.0)/fScalar;
+      m_afTuple[0] *= fInvScalar;
+      m_afTuple[1] *= fInvScalar;
+      m_afTuple[2] *= fInvScalar;
+   }
+   else
+   {
+      m_afTuple[0] = Ub::inf;
+      m_afTuple[1] = Ub::inf;
+      m_afTuple[2] = Ub::inf;
+   }
+
+   return *this;
+}
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::Scale(const double& x)
+{
+   GbVector3D PointA(0.0,0.0,0.0);
+   PointA.m_afTuple[0] = x * m_afTuple[0];
+   PointA.m_afTuple[1] = x * m_afTuple[1];
+   PointA.m_afTuple[2] = x * m_afTuple[2];
+   return PointA;	
+}
+
+//----------------------------------------------------------------------------
+double GbVector3D::Length () const
+{
+   return std::sqrt(
+      m_afTuple[0]*m_afTuple[0] +
+      m_afTuple[1]*m_afTuple[1] +
+      m_afTuple[2]*m_afTuple[2]);
+}
+//----------------------------------------------------------------------------
+double GbVector3D::SquaredLength () const
+{
+   return
+      m_afTuple[0]*m_afTuple[0] +
+      m_afTuple[1]*m_afTuple[1] +
+      m_afTuple[2]*m_afTuple[2];
+}
+//----------------------------------------------------------------------------
+double GbVector3D::Dot (const GbVector3D& rkV) const
+{
+   return
+      m_afTuple[0]*rkV.m_afTuple[0] +
+      m_afTuple[1]*rkV.m_afTuple[1] +
+      m_afTuple[2]*rkV.m_afTuple[2];
+}
+//----------------------------------------------------------------------------
+double GbVector3D::Normalize ()
+{
+   double fLength = Length();
+
+   if ( fLength > UbMath::Epsilon<double>::val() )
+   {
+      double fInvLength = ((double)1.0)/fLength;
+      m_afTuple[0] *= fInvLength;
+      m_afTuple[1] *= fInvLength;
+      m_afTuple[2] *= fInvLength;
+   }
+   else
+   {
+      fLength = 0.0;
+      m_afTuple[0] = 0.0;
+      m_afTuple[1] = 0.0;
+      m_afTuple[2] = 0.0;
+   }
+
+   return fLength;
+}
+//----------------------------------------------------------------------------
+GbVector3D GbVector3D::Cross (const GbVector3D& rkV) const
+{
+   return GbVector3D(
+      m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
+      m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
+      m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]);
+}
+
+//----------------------------------------------------------------------------
+
+GbVector3D GbVector3D::UnitCross (const GbVector3D& rkV) const
+{
+   GbVector3D kCross(
+      m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
+      m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
+      m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]);
+   kCross.Normalize();
+   return kCross;
+}
+//----------------------------------------------------------------------------
+void GbVector3D::GetBarycentrics (const GbVector3D& rkV0,
+                                  const GbVector3D& rkV1, const GbVector3D& rkV2,
+                                  const GbVector3D& rkV3, double afBary[4]) const
+{
+   // compute the vectors relative to V3 of the tetrahedron
+   GbVector3D akDiff[4] =
+   {
+      rkV0 - rkV3,
+         rkV1 - rkV3,
+         rkV2 - rkV3,
+         *this - rkV3
+   };
+
+   // If the vertices have large magnitude, the linear system of
+   // equations for computing barycentric coordinates can be
+   // ill-conditioned.  To avoid this, uniformly scale the tetrahedron
+   // edges to be of order 1.  The scaling of all differences does not
+   // change the barycentric coordinates.
+   double fMax = (double)0.0;
+   int i;
+   for (i = 0; i < 3; i++)
+   {
+      for (int j = 0; j < 3; j++)
+      {
+         double fValue = std::fabs(akDiff[i][j]);
+         if ( fValue > fMax )
+            fMax = fValue;
+      }
+   }
+
+   // scale down only large data
+   if ( fMax > (double)1.0 )
+   {
+      double fInvMax = ((double)1.0)/fMax;
+      for (i = 0; i < 4; i++)
+         akDiff[i] *= fInvMax;
+   }
+
+   double fDet = akDiff[0].Dot(akDiff[1].Cross(akDiff[2]));
+   GbVector3D kE1cE2 = akDiff[1].Cross(akDiff[2]);
+   GbVector3D kE2cE0 = akDiff[2].Cross(akDiff[0]);
+   GbVector3D kE0cE1 = akDiff[0].Cross(akDiff[1]);
+   if ( std::fabs(fDet) > UbMath::Epsilon<double>::val() )
+   {
+      double fInvDet = ((double)1.0)/fDet;
+      afBary[0] = akDiff[3].Dot(kE1cE2)*fInvDet;
+      afBary[1] = akDiff[3].Dot(kE2cE0)*fInvDet;
+      afBary[2] = akDiff[3].Dot(kE0cE1)*fInvDet;
+      afBary[3] = (double)1.0 - afBary[0] - afBary[1] - afBary[2];
+   }
+   else
+   {
+      // The tetrahedron is potentially flat.  Determine the face of
+      // maximum area and compute barycentric coordinates with respect
+      // to that face.
+      GbVector3D kE02 = rkV0 - rkV2;
+      GbVector3D kE12 = rkV1 - rkV2;
+      GbVector3D kE02cE12 = kE02.Cross(kE12);
+      double fMaxSqrArea = kE02cE12.SquaredLength();
+      int iMaxIndex = 3;
+      double fSqrArea = kE0cE1.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 0;
+         fMaxSqrArea = fSqrArea;
+      }
+      fSqrArea = kE1cE2.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 1;
+         fMaxSqrArea = fSqrArea;
+      }
+      fSqrArea = kE2cE0.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 2;
+         fMaxSqrArea = fSqrArea;
+      }
+
+      if ( fMaxSqrArea > UbMath::Epsilon<double>::val() )
+      {
+         double fInvSqrArea = ((double)1.0)/fMaxSqrArea;
+         GbVector3D kTmp;
+         if ( iMaxIndex == 0 )
+         {
+            kTmp = akDiff[3].Cross(akDiff[1]);
+            afBary[0] = kE0cE1.Dot(kTmp)*fInvSqrArea;
+            kTmp = akDiff[0].Cross(akDiff[3]);
+            afBary[1] = kE0cE1.Dot(kTmp)*fInvSqrArea;
+            afBary[2] = (double)0.0;
+            afBary[3] = (double)1.0 - afBary[0] - afBary[1];
+         }
+         else if ( iMaxIndex == 1 )
+         {
+            afBary[0] = (double)0.0;
+            kTmp = akDiff[3].Cross(akDiff[2]);
+            afBary[1] = kE1cE2.Dot(kTmp)*fInvSqrArea;
+            kTmp = akDiff[1].Cross(akDiff[3]);
+            afBary[2] = kE1cE2.Dot(kTmp)*fInvSqrArea;
+            afBary[3] = (double)1.0 - afBary[1] - afBary[2];
+         }
+         else if ( iMaxIndex == 2 )
+         {
+            kTmp = akDiff[2].Cross(akDiff[3]);
+            afBary[0] = kE2cE0.Dot(kTmp)*fInvSqrArea;
+            afBary[1] = (double)0.0;
+            kTmp = akDiff[3].Cross(akDiff[0]);
+            afBary[2] = kE2cE0.Dot(kTmp)*fInvSqrArea;
+            afBary[3] = (double)1.0 - afBary[0] - afBary[2];
+         }
+         else
+         {
+            akDiff[3] = *this - rkV2;
+            kTmp = akDiff[3].Cross(kE12);
+            afBary[0] = kE02cE12.Dot(kTmp)*fInvSqrArea;
+            kTmp = kE02.Cross(akDiff[3]);
+            afBary[1] = kE02cE12.Dot(kTmp)*fInvSqrArea;
+            afBary[2] = (double)1.0 - afBary[0] - afBary[1];
+            afBary[3] = (double)0.0;
+         }
+      }
+      else
+      {
+         // The tetrahedron is potentially a sliver.  Determine the edge of
+         // maximum length and compute barycentric coordinates with respect
+         // to that edge.
+         double fMaxSqrLength = akDiff[0].SquaredLength();
+         iMaxIndex = 0;  // <V0,V3>
+         double fSqrLength = akDiff[1].SquaredLength();
+         if ( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex = 1;  // <V1,V3>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = akDiff[2].SquaredLength();
+         if ( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex = 2;  // <V2,V3>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = kE02.SquaredLength();
+         if ( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex = 3;  // <V0,V2>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = kE12.SquaredLength();
+         if ( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex = 4;  // <V1,V2>
+            fMaxSqrLength = fSqrLength;
+         }
+         GbVector3D kE01 = rkV0 - rkV1;
+         fSqrLength = kE01.SquaredLength();
+         if ( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex = 5;  // <V0,V1>
+            fMaxSqrLength = fSqrLength;
+         }
+
+         if ( fMaxSqrLength > UbMath::Epsilon<double>::val() )
+         {
+            double fInvSqrLength = ((double)1.0)/fMaxSqrLength;
+            if ( iMaxIndex == 0 )
+            {
+               // P-V3 = t*(V0-V3)
+               afBary[0] = akDiff[3].Dot(akDiff[0])*fInvSqrLength;
+               afBary[1] = (double)0.0;
+               afBary[2] = (double)0.0;
+               afBary[3] = (double)1.0 - afBary[0];
+            }
+            else if ( iMaxIndex == 1 )
+            {
+               // P-V3 = t*(V1-V3)
+               afBary[0] = (double)0.0;
+               afBary[1] = akDiff[3].Dot(akDiff[1])*fInvSqrLength;
+               afBary[2] = (double)0.0;
+               afBary[3] = (double)1.0 - afBary[1];
+            }
+            else if ( iMaxIndex == 2 )
+            {
+               // P-V3 = t*(V2-V3)
+               afBary[0] = (double)0.0;
+               afBary[1] = (double)0.0;
+               afBary[2] = akDiff[3].Dot(akDiff[2])*fInvSqrLength;
+               afBary[3] = (double)1.0 - afBary[2];
+            }
+            else if ( iMaxIndex == 3 )
+            {
+               // P-V2 = t*(V0-V2)
+               akDiff[3] = *this - rkV2;
+               afBary[0] = akDiff[3].Dot(kE02)*fInvSqrLength;
+               afBary[1] = (double)0.0;
+               afBary[2] = (double)1.0 - afBary[0];
+               afBary[3] = (double)0.0;
+            }
+            else if ( iMaxIndex == 4 )
+            {
+               // P-V2 = t*(V1-V2)
+               akDiff[3] = *this - rkV2;
+               afBary[0] = (double)0.0;
+               afBary[1] = akDiff[3].Dot(kE12)*fInvSqrLength;
+               afBary[2] = (double)1.0 - afBary[1];
+               afBary[3] = (double)0.0;
+            }
+            else
+            {
+               // P-V1 = t*(V0-V1)
+               akDiff[3] = *this - rkV1;
+               afBary[0] = akDiff[3].Dot(kE01)*fInvSqrLength;
+               afBary[1] = (double)1.0 - afBary[0];
+               afBary[2] = (double)0.0;
+               afBary[3] = (double)0.0;
+            }
+         }
+         else
+         {
+            // tetrahedron is a nearly a point, just return equal weights
+            afBary[0] = (double)0.25;
+            afBary[1] = afBary[0];
+            afBary[2] = afBary[0];
+            afBary[3] = afBary[0];
+         }
+      }
+   }
+}
+//----------------------------------------------------------------------------
+void GbVector3D::Orthonormalize (GbVector3D& rkU, GbVector3D& rkV, GbVector3D& rkW)
+{
+   // If the input vectors are v0, v1, and v2, then the Gram-Schmidt
+   // orthonormalization produces vectors u0, u1, and u2 as follows,
+   //
+   //   u0 = v0/|v0|
+   //   u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
+   //   u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1|
+   //
+   // where |A| indicates length of vector A and A*B indicates dot
+   // product of vectors A and B.
+
+   // compute u0
+   rkU.Normalize();
+
+   // compute u1
+   double fDot0 = rkU.Dot(rkV); 
+   rkV -= fDot0*rkU;
+   rkV.Normalize();
+
+   // compute u2
+   double fDot1 = rkV.Dot(rkW);
+   fDot0 = rkU.Dot(rkW);
+   rkW -= fDot0*rkU + fDot1*rkV;
+   rkW.Normalize();
+}
+//----------------------------------------------------------------------------
+void GbVector3D::Orthonormalize (GbVector3D* akV)
+{
+   Orthonormalize(akV[0],akV[1],akV[2]);
+}
+//----------------------------------------------------------------------------
+void GbVector3D::GenerateOrthonormalBasis (GbVector3D& rkU, GbVector3D& rkV,
+                                           GbVector3D& rkW, bool bUnitLengthW)
+{
+   if ( !bUnitLengthW )
+      rkW.Normalize();
+
+   double fInvLength;
+
+   if ( std::fabs(rkW.m_afTuple[0]) >=
+      std::fabs(rkW.m_afTuple[1]) )
+   {
+      // W.x or W.z is the largest magnitude component, swap them
+      fInvLength = UbMath::invSqrt(rkW.m_afTuple[0]*rkW.m_afTuple[0] + rkW.m_afTuple[2]*rkW.m_afTuple[2]);
+      rkU.m_afTuple[0] = -rkW.m_afTuple[2]*fInvLength;
+      rkU.m_afTuple[1] = (double)0.0;
+      rkU.m_afTuple[2] = +rkW.m_afTuple[0]*fInvLength;
+   }
+   else
+   {
+      // W.y or W.z is the largest magnitude component, swap them
+      fInvLength = UbMath::invSqrt(rkW.m_afTuple[1]*rkW.m_afTuple[1] + rkW.m_afTuple[2]*rkW.m_afTuple[2]);
+      rkU.m_afTuple[0] = (double)0.0;
+      rkU.m_afTuple[1] = +rkW.m_afTuple[2]*fInvLength;
+      rkU.m_afTuple[2] = -rkW.m_afTuple[1]*fInvLength;
+   }
+
+   rkV = rkW.Cross(rkU);
+}
+//----------------------------------------------------------------------------
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbVector3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbVector3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..9fe4c2698e77ce7788d0a8a273ff5213724af08f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbVector3D.h
@@ -0,0 +1,135 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBVECTOR3D_H
+#define GBVECTOR3D_H
+                                                                   
+#include <cfloat>                               
+#include <cassert> 
+#include <string>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbVector3D;
+typedef VFSharedPtr<GbVector3D> GbVector3DPtr;
+
+
+class GbPoint3D;
+
+class GbVector3D 
+{
+public:
+   // construction
+    GbVector3D (); 
+    GbVector3D (const double& fX1, const double& fX2, const double& fX3);
+    GbVector3D (const GbVector3D& rkV);
+    GbVector3D (const GbPoint3D& rkV);
+
+    std::string toString();
+
+    // coordinate access
+    operator const double* () const;
+    operator double* ();
+    double operator[] (int i) const;
+    double& operator[] (int i);
+    double X1 () const;
+    double& X1 ();
+    double X2 () const;
+    double& X2 ();                                    
+    double X3 () const;
+    double& X3 ();
+
+    // assignment
+    GbVector3D& operator= (const GbVector3D& rkV);
+
+    // comparison
+    bool operator== (const GbVector3D& rkV) const;
+    bool operator!= (const GbVector3D& rkV) const;
+    bool operator<  (const GbVector3D& rkV) const;
+    bool operator<= (const GbVector3D& rkV) const;
+    bool operator>  (const GbVector3D& rkV) const;
+    bool operator>= (const GbVector3D& rkV) const;
+
+    // arithmetic operations
+    GbVector3D operator+ (const GbVector3D& rkV) const;
+    GbVector3D operator- (const GbVector3D& rkV) const;
+    GbVector3D operator* (const double& fScalar) const;
+    GbVector3D operator/ (const double& fScalar) const;
+    GbVector3D operator- () const;
+
+    // arithmetic updates
+    GbVector3D& operator+= (const GbVector3D& rkV);
+    GbVector3D& operator-= (const GbVector3D& rkV);
+    GbVector3D& operator*= (const double& fScalar);
+    GbVector3D& operator/= (const double& fScalar);
+
+    GbVector3D Add(GbVector3D& vector);
+    GbVector3D Subtract(GbVector3D& vector);
+    GbVector3D Scale(const double& x);
+
+    // vector operations
+    double Length () const;
+    double SquaredLength () const;
+    double Dot (const GbVector3D& rkV) const;
+    double Normalize ();
+
+    // The cross products are computed using the right-handed rule.  Be aware
+    // that some graphics APIs use a left-handed rule.  If you have to compute
+    // a cross product with these functions and send the result to the API
+    // that expects left-handed, you will need to change sign on the vector
+    // (replace each component value c by -c).
+    GbVector3D Cross (const GbVector3D& rkV) const;
+    GbVector3D UnitCross (const GbVector3D& rkV) const;
+
+    // Compute the barycentric coordinates of the point with respect to the
+    // tetrahedron <V0,V1,V2,V3>, P = b0*V0 + b1*V1 + b2*V2 + b3*V3, where
+    // b0 + b1 + b2 + b3 = 1.
+    void GetBarycentrics (const GbVector3D& rkV0,
+                          const GbVector3D& rkV1, const GbVector3D& rkV2,
+                          const GbVector3D& rkV3, double afBary[4]) const;
+
+    // Gram-Schmidt orthonormalization.  Take linearly independent vectors
+    // U, V, and W and compute an orthonormal set (unit length, mutually
+    // perpendicular).
+    static void Orthonormalize (GbVector3D& rkU, GbVector3D& rkV, GbVector3D& rkW);
+    static void Orthonormalize (GbVector3D* akV);
+
+    // Input W must be initialized to a nonzero vector, output is {U,V,W},
+    // an orthonormal basis.  A hint is provided about whether or not W
+    // is already unit length.
+    static void GenerateOrthonormalBasis (GbVector3D& rkU, GbVector3D& rkV,
+                                          GbVector3D& rkW, bool bUnitLengthW);
+
+    // special vectors
+    static const GbVector3D ZERO;
+    static const GbVector3D UNIT_X1;
+    static const GbVector3D UNIT_X2;
+    static const GbVector3D UNIT_X3;
+
+#ifdef CAB_RCF
+    template<class Archive>
+    void SF_SERIALIZE(Archive & ar)
+    {
+       ar & m_afTuple;
+    }
+#endif //CAB_RCF
+private:
+    // support for comparisons
+    int CompareArrays (const GbVector3D& rkV) const;
+
+    double m_afTuple[3];
+};
+
+GbVector3D operator* (const double& fScalar, const GbVector3D& rkV);
+
+#ifdef RCF_USE_SF_SERIALIZATION
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbVector3D  >("GbVector3D  "), SF_GbVector3D     );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //GBVECTOR3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbVoxelMatrix3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/GbVoxelMatrix3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..93fe1064aa945c3f5491c7fff9442a9efec62f86
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbVoxelMatrix3D.cpp
@@ -0,0 +1,1027 @@
+#include <numerics/geometry3d/GbVoxelMatrix3D.h>
+
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbFileInputASCII.h>
+#include <numerics/geometry3d/creator/GbVoxelMatrix3DCreator.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <numerics/geometry3d/CoordinateTransformation3D.h>
+
+#include <basics/utilities/UbSystem.h>
+
+#ifdef MC_CUBES
+   #include <3rdParty/MarchingCubes/MarchingCubes.h>
+#endif // MC_CUBES
+
+using namespace std;
+
+const float GbVoxelMatrix3D::SOLID = 1.0f;
+const float GbVoxelMatrix3D::FLUID = 0.0f;
+
+
+/*=======================================================*/
+ObObjectCreator* GbVoxelMatrix3D::getCreator()
+{
+   return GbVoxelMatrix3DCreator::getInstance();
+}
+/*=======================================================*/
+// Konstruktor
+GbVoxelMatrix3D::GbVoxelMatrix3D(int nx1, int nx2, int nx3, float initVal, double lowerThreshold, double upperThreshold)
+   : GbObject3D()
+   , minX1(0.0)
+   , minX2(0.0)
+   , minX3(0.0)
+   , lowerThreshold(lowerThreshold)
+   , upperThreshold(upperThreshold)
+   , nodesX1(nx1)
+   , nodesX2(nx2)
+   , nodesX3(nx3)
+   , deltaX1(1.0)
+   , deltaX2(1.0)
+   , deltaX3(1.0)
+   , transferViaFilename(false)
+   , addSurfaceTriangleSetFlag(true)
+   , voxelMatrix(Matrix3D(nx1, nx2, nx3, initVal))
+{
+   this->setName("VoxelMatrix3D");
+}
+/*=======================================================*/
+GbVoxelMatrix3D::GbVoxelMatrix3D() 
+  :   GbObject3D()
+    , minX1(0.0)
+    , minX2(0.0)
+    , minX3(0.0)
+    , nodesX1(0)
+    , nodesX2(0)
+    , nodesX3(0)
+    , lowerThreshold(0.0)
+    , upperThreshold(0.0)
+    , deltaX1(1.0)
+    , deltaX2(1.0)
+    , deltaX3(1.0)
+    , transferViaFilename(false)
+    , addSurfaceTriangleSetFlag(true)
+{
+   this->setName("VoxelMatrix3D");
+}
+/*=======================================================*/
+GbVoxelMatrix3D::GbVoxelMatrix3D(const Matrix3D& voxelMatrix, double lowerThreshold, double upperThreshold)
+  :   GbObject3D()
+    , minX1(0.0)
+    , minX2(0.0)
+    , minX3(0.0)
+    , nodesX1((int)voxelMatrix.getNX1())
+    , nodesX2((int)voxelMatrix.getNX2())
+    , nodesX3((int)voxelMatrix.getNX3())
+    , lowerThreshold(lowerThreshold)
+    , upperThreshold(upperThreshold)
+    , deltaX1(1.0)
+    , deltaX2(1.0)
+    , deltaX3(1.0)
+    , transferViaFilename(false)
+    , addSurfaceTriangleSetFlag(true)
+    , voxelMatrix(voxelMatrix)
+{
+   this->setName("VoxelMatrix3D");
+}
+/*=======================================================*/
+GbVoxelMatrix3D*  GbVoxelMatrix3D::clone()
+{
+   GbVoxelMatrix3D* vm = new GbVoxelMatrix3D(this->voxelMatrix, lowerThreshold, upperThreshold);
+   vm->setVoxelMatrixMininum(minX1, minX2, minX3);
+   vm->setVoxelMatrixDelta(deltaX1, deltaX2, deltaX3);
+   return  vm;
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3) 
+{
+   this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() );
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::translate(const double& tx1, const double& tx2, const double& tx3)
+{  
+   this->minX1 += tx1;
+   this->minX2 += tx2;
+   this->minX3 += tx3;
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::setClosedVoidSpaceToSolid()
+{
+   voxelMatrixTemp = Matrix3D(nodesX1, nodesX2, nodesX3, SOLID);
+   flagMatrix = CbArray3D<char>(nodesX1, nodesX2, nodesX3, 0);
+
+   for (int x3 = 0; x3<nodesX3; x3++)
+   {
+      for (int x2 = 0; x2<nodesX2; x2++)
+      {
+         for (int x1 = 0; x1<nodesX1; x1++)
+         {
+            if (voxelMatrix(x1, x2, x3)==FLUID)
+            {
+               UBLOG(logINFO, "setClosedVoidSpaceToSolid:start");
+               x1Nbr.push_back(x1);
+               x2Nbr.push_back(x2);
+               x3Nbr.push_back(x3);
+               int size = (int)x1Nbr.size();
+               while (size > 0)
+               {
+                  for (int i = 0; i < size; i++)
+                  {
+                     findFluidNeighbor(x1Nbr[i], x2Nbr[i], x3Nbr[i]);
+                  }
+
+                  swap(x1Nbr, x1NbrTemp);
+                  swap(x2Nbr, x2NbrTemp);
+                  swap(x3Nbr, x3NbrTemp);
+
+                  x1NbrTemp.clear();
+                  x2NbrTemp.clear();
+                  x3NbrTemp.clear();
+                  size = x1Nbr.size();
+               }
+               UBLOG(logINFO, "setClosedVoidSpaceToSolid:end");
+               voxelMatrix = voxelMatrixTemp;
+               return;
+            }
+
+         }
+      }
+   }
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::findFluidNeighbor(int x1, int x2, int x3)
+{
+   for (int k3 = -1; k3<=1; k3++)
+   {
+      for (int k2 = -1; k2<=1; k2++)
+      {
+         for (int k1 = -1; k1<=1; k1++)
+         {
+            int j1 = x1+k1;
+            int j2 = x2+k2;
+            int j3 = x3+k3;
+            if (j1>=0 && j1<nodesX1 && j2>=0 && j2<nodesX2 && j3>=0 && j3<nodesX3)
+            {
+               if (voxelMatrix(j1, j2, j3)==FLUID)
+               {
+                  if (flagMatrix(j1, j2, j3) == 0)
+                  {
+                     voxelMatrixTemp(j1, j2, j3) = FLUID;
+                     flagMatrix(j1, j2, j3) = 1;
+                     x1NbrTemp.push_back(j1);
+                     x2NbrTemp.push_back(j2);
+                     x3NbrTemp.push_back(j3);
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::calculateNumberOfSolidAndFluid()
+{
+   numberOfSolid = 0;
+
+   for (int x3 = 0; x3<nodesX3; x3++)
+      for (int x2 = 0; x2<nodesX2; x2++)
+         for (int x1 = 0; x1<nodesX1; x1++)
+         {
+            if (voxelMatrix(x1, x2, x3) == GbVoxelMatrix3D::SOLID)
+            {
+               numberOfSolid++;
+            }
+         }
+
+   numberOfFluid = (long)nodesX1*(long)nodesX2*(long)nodesX3 - numberOfSolid;
+}
+/*=======================================================*/
+long GbVoxelMatrix3D::getNumberOfSolid()
+{
+   return numberOfSolid;
+}
+/*=======================================================*/
+long GbVoxelMatrix3D::getNumberOfFluid()
+{
+   return numberOfFluid;
+}
+/*=======================================================*/
+double GbVoxelMatrix3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   if( !(    (UbMath::equal(rx1,0.0) || UbMath::equal(fabs(rx1),1.0) || UbMath::equal(fabs(rx1),UbMath::one_over_sqrt2) )
+          && (UbMath::equal(rx2,0.0) || UbMath::equal(fabs(rx2),1.0) || UbMath::equal(fabs(rx2),UbMath::one_over_sqrt2) )
+          && (UbMath::equal(rx3,0.0) || UbMath::equal(fabs(rx3),1.0) || UbMath::equal(fabs(rx3),UbMath::one_over_sqrt2) ) ) )
+   {
+      throw UbException(UB_EXARGS,"nur fuer diskrete Boltzmannrichungen implementiert!!!");
+   }
+
+   //nachbarindex ermitteln
+   int ndx1 = 0, ndx2 = 0, ndx3 = 0;
+   if (UbMath::greater(rx1, 0.0)) ndx1 = 1;
+   else if (UbMath::less(rx1, 0.0)) ndx1 = -1;
+   if (UbMath::greater(rx2, 0.0)) ndx2 = 1;
+   else if (UbMath::less(rx2, 0.0)) ndx2 = -1;
+   if (UbMath::greater(rx3, 0.0)) ndx3 = 1;
+   else if (UbMath::less(rx3, 0.0)) ndx3 = -1;
+
+   int nix1 = UbMath::integerRounding( (x1-minX1)/deltaX1 )+ndx1;
+   int nix2 = UbMath::integerRounding( (x2-minX2)/deltaX2 )+ndx2;
+   int nix3 = UbMath::integerRounding( (x3-minX3)/deltaX3 )+ndx3;
+
+   //test ob nachbar solid
+   if(    nix1>=0 
+       && nix2>=0 
+       && nix3>=0 
+       && nix1<voxelMatrix.getNX1()
+       && nix2<voxelMatrix.getNX2()
+       && nix3<voxelMatrix.getNX3() )
+   {
+      if( UbMath::equal(voxelMatrix(nix1,nix2,nix3), SOLID) )
+      {
+         //return halber abstand der beiden knoten
+         return 0.5*sqrt(  (ndx1*deltaX1)*(ndx1*deltaX1) 
+                         + (ndx2*deltaX2)*(ndx2*deltaX2)
+                         + (ndx3*deltaX3)*(ndx3*deltaX3) );
+      }
+   }
+
+   return 0.0;
+}	
+/*=======================================================*/
+bool GbVoxelMatrix3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   //index ermitteln
+   int ix1 = UbMath::integerRounding( (x1p-minX1)/deltaX1 );
+   int ix2 = UbMath::integerRounding( (x2p-minX2)/deltaX2 );
+   int ix3 = UbMath::integerRounding( (x3p-minX3)/deltaX3 );
+
+   if(    ix1>=0 
+       && ix2>=0 
+       && ix3>=0 
+       && ix1<voxelMatrix.getNX1() 
+       && ix2<voxelMatrix.getNX2()
+       && ix3<voxelMatrix.getNX3() )
+   {
+      if (UbMath::equal(voxelMatrix(ix1, ix2, ix3), SOLID)) return true;
+   }
+
+   return false;
+}
+/*=======================================================*/
+bool GbVoxelMatrix3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   pointIsOnBoundary = false;
+   
+   return isPointInGbObject3D(x1p,x2p,x3p);
+}
+/*=======================================================*/
+bool GbVoxelMatrix3D::isCellInsideGbObject3D(const double& x1p1,const double& x2p1,const double& x3p1,const double& x1p2,const double& x2p2,const double& x3p2)
+{
+   return false;
+//dass hängt von der Konfigration ab, aber meist ist der Block grösser wie etliche Poren ...
+
+   //indizes ermitteln
+   int startix1 = (int)std::floor( (x1p1-minX1)/deltaX1+1E-13 );
+   int startix2 = (int)std::floor( (x2p1-minX2)/deltaX2+1E-13 );
+   int startix3 = (int)std::floor( (x3p1-minX3)/deltaX3+1E-13 );
+
+   if(startix1<0 ) return false;
+   if(startix2<0 ) return false;
+   if(startix3<0 ) return false;
+
+   int maxiX1 = (int)voxelMatrix.getNX1()-1;
+   int maxiX2 = (int)voxelMatrix.getNX2()-1;
+   int maxiX3 = (int)voxelMatrix.getNX3()-1;
+
+   int endix1 = (int)std::ceil( (x1p2-minX1)/deltaX1-1E-13 );
+   int endix2 = (int)std::ceil( (x2p2-minX2)/deltaX2-1E-13 );
+   int endix3 = (int)std::ceil( (x3p2-minX3)/deltaX3-1E-13 );
+
+   if(endix1>maxiX1 ) return false;
+   if(endix2>maxiX2 ) return false;
+   if(endix3>maxiX3 ) return false;
+
+   for(int ix3=startix3; ix3<=endix3; ix3++)
+      for(int ix2=startix2; ix2<=endix2; ix2++)
+         for(int ix1=startix1; ix1<=endix1; ix1++)
+            if( UbMath::equal(voxelMatrix(ix1,ix2,ix3), FLUID ) ) 
+               return false;
+   return true;
+}
+/*=======================================================*/
+bool GbVoxelMatrix3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der CuboidUmrandung
+//returns true:
+//  - cell cuts  GbVoxelMatrix3D
+//  - cell boxes GbVoxelMatrix3D
+//returns false:
+//  - cell completely inside GbVoxelMatrix3D 
+//  - cell und cuboid3D haben kein gemeinsames Volumen
+{
+   //erstmal die dumm Loesung
+   if(  !( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )   
+      &&   this->isCellInsideOrCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )
+   {
+      return true;
+   }
+
+   return false;
+}
+/*=======================================================*/
+bool GbVoxelMatrix3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//returns true:
+//  - cell completely inside cuboid3D ( = cuboid3D boxes cell)
+//  - cell cuts  cuboid3D
+//  - cell boxes cuboid3D
+//returns false:
+//  - cell und cuboid3D haben kein gemeinsames Volumen
+{
+    //simpler check, da unser GbCuboid3D ein AABB is:
+   //  anfA        midA         endA             anfB    midB    endB
+   //   |            x<-- dxA -->|                 |<-dxB->x       |
+   //                |<----------------- T --------------->|
+   //ist |T| <= dxA + dxB -> overlap!
+
+   if(     UbMath::lessEqual(  std::fabs( this->getX1Centroid() - 0.5*(x1b+x1a)      /*Tx1*/      )
+                             , 0.5*( this->getLengthX1()        + std::fabs(x1b-x1a) /*dx1A+dx1B*/) )
+
+        && UbMath::lessEqual(  std::fabs( this->getX2Centroid() - 0.5*(x2b+x2a)      /*Tx2*/      )
+                             , 0.5*( this->getLengthX2()        + std::fabs(x2b-x2a) /*dx2A+dx2B*/) )
+
+        && UbMath::lessEqual(  std::fabs( this->getX3Centroid() - 0.5*(x3b+x3a)      /*Tx3*/      )
+                             , 0.5*( this->getLengthX3()        + std::fabs(x3b-x3a) /*dx3A+dx3B*/) ) )
+    {
+       return true;
+    }
+
+    return false;
+}
+/*=======================================================*/
+vector<GbTriangle3D*> GbVoxelMatrix3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles;
+   
+   #ifdef MC_CUBES
+      //MC
+      typedef McCubes::Matrix3DWrapper< Matrix3D >                McMatrixWrapper;
+      typedef McCubes::MarchingCubes< McMatrixWrapper >           McMarchingCubesGenerator;
+      typedef McMarchingCubesGenerator::Vertex                    McVertex;
+      typedef McMarchingCubesGenerator::Triangle                  McTriangle;
+
+      McMatrixWrapper wrapper(&voxelMatrix);//,0,0,0,voxelMatrix.getNX1()-1,voxelMatrix.getNX2()-1,voxelMatrix.getNX3()-1);
+      McMarchingCubesGenerator mc(wrapper);
+
+      mc.init_all();
+      mc.run(0.5);
+
+      //const int   nofVertices  = mc.nverts();
+      const int   nofTriangles = mc.ntrigs();
+
+      McVertex*   mcvertices   = mc.vertices();
+      McTriangle* mctriangles  = mc.triangles();
+
+      for(int t=0; t<nofTriangles; t++)
+      {
+         triangles.push_back(new GbTriangle3D( new GbPoint3D(  minX1 + deltaX1 * (mcvertices[mctriangles[t].v1].x /*-1*/)
+                                                             , minX2 + deltaX2 * (mcvertices[mctriangles[t].v1].y /*-1*/)
+                                                             , minX3 + deltaX3 * (mcvertices[mctriangles[t].v1].z /*-1*/) )
+                                              ,new GbPoint3D(  minX1 + deltaX1 * (mcvertices[mctriangles[t].v2].x /*-1*/)
+                                                             , minX2 + deltaX2 * (mcvertices[mctriangles[t].v2].y /*-1*/)
+                                                             , minX3 + deltaX3 * (mcvertices[mctriangles[t].v2].z /*-1*/) )
+                                              ,new GbPoint3D(  minX1 + deltaX1 * (mcvertices[mctriangles[t].v3].x /*-1*/)
+                                                             , minX2 + deltaX2 * (mcvertices[mctriangles[t].v3].y /*-1*/)
+                                                             , minX3 + deltaX3 * (mcvertices[mctriangles[t].v3].z /*-1*/) ) ) );
+      }
+   #else
+     cerr<<"vector<GbTriangle3D*> GbVoxelMatrix3D::getSurfaceTriangleSet() - benoetigt MARCHING_CUBE paket aus 3rdParty"<<endl;
+   #endif // MC_CUBES
+
+   return triangles;
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+   UBLOG(logINFO," GbVoxelMatrix3D addSurfaceTriangleSet start")
+   if(!this->addSurfaceTriangleSetFlag)
+   {
+      UBLOG(logINFO," GbVoxelMatrix3D addSurfaceTriangleSet end without TriangleSetCreation")
+      return;
+   }
+   #ifdef MC_CUBES
+      UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet MC defined")
+
+      typedef McCubes::Matrix3DWrapper< Matrix3D >                McMatrixWrapper;
+      typedef McCubes::MarchingCubes< McMatrixWrapper >           McMarchingCubesGenerator;
+      typedef McMarchingCubesGenerator::Vertex                    McVertex;
+      typedef McMarchingCubesGenerator::Triangle                  McTriangle;
+    
+      //MC
+      {  //standard( fuer voxelmatrix)
+         McMatrixWrapper wrapper(&voxelMatrix);
+         McMarchingCubesGenerator mc(wrapper);
+
+         UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet McMarchingCubesGenerator")
+
+         UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet mc.init")
+         mc.init_all();
+         UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet mc.run")
+         mc.run(0.5);
+         UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet mc.run done")
+
+         const int   nofVertices  = mc.nverts();
+         const int   nofTriangles = mc.ntrigs();
+
+         McVertex*   mcvertices   = mc.vertices();
+         McTriangle* mctriangles  = mc.triangles();
+
+UBLOG(logDEBUG1," GbVoxelMatrix3D node tuple")
+         for(int n=0; n<nofVertices; n++)
+            nodes.push_back( makeUbTuple( (float)(minX1 + deltaX1 * (mcvertices[n].x /*-1*/)),   //Anm: kein -1, da man durch manipulation der indices die dreiecke um eins versetzt bekommt
+                                          (float)(minX2 + deltaX2 * (mcvertices[n].y /*-1*/)),
+                                          (float)(minX3 + deltaX3 * (mcvertices[n].z /*-1*/)) ) );
+UBLOG(logDEBUG1," GbVoxelMatrix3D triangles tuple")
+         for(int t=0; t<nofTriangles; t++)
+            triangles.push_back( makeUbTuple( mctriangles[t].v1, mctriangles[t].v2, mctriangles[t].v3 ) );
+UBLOG(logDEBUG1," GbVoxelMatrix3D triangles tuple done")
+      }
+      
+      //false - das scheint probleme bei der asphaltprobe zu machen 1500x600x100
+      // da lief es bis C - evtl. memory voll
+      if(false)  //extension... um die raender koerrekt abzubilden muesste man eine dummy FLUID reihe um 
+      {         //die matrix legen( lsg1: temp matrix mit 2 reihen pro richtung mehr -> zuviel speicher, 500^3 = 500MB
+                // lsg2: fuer jede flaeche eine dummy matrix -> wie folgt:
+         int nx1 = (int)voxelMatrix.getNX1();
+         int nx2 = (int)voxelMatrix.getNX2();
+         int nx3 = (int)voxelMatrix.getNX3();
+UBLOG(logINFO," A ")
+         Matrix3D tmpX1Min( 2, nx2+2, nx3+2, FLUID );
+         Matrix3D tmpX1Max( 2, nx2+2, nx3+2, FLUID );
+         for(int x3=0; x3<nx3; x3++ )
+            for(int x2=0; x2<nx2; x2++ )
+            {
+               tmpX1Min(1, x2+1, x3+1) = voxelMatrix(0    , x2, x3);
+               tmpX1Max(0, x2+1, x3+1) = voxelMatrix(nx1-1, x2, x3);
+            }
+UBLOG(logINFO," B")
+         Matrix3D tmpX2Min(nx1+2, 2, nx3+2, FLUID );
+         Matrix3D tmpX2Max(nx1+2, 2, nx3+2, FLUID );
+         for(int x3=0; x3<nx3; x3++ )
+            for(int x1=0; x1<nx1; x1++ )
+            {
+               tmpX2Min(x1+1, 1, x3+1) = voxelMatrix(x1, 0    , x3);
+               tmpX2Max(x1+1, 0, x3+1) = voxelMatrix(x1, nx2-1, x3);
+            }
+UBLOG(logINFO," C ")
+         Matrix3D tmpX3Min(nx1+2, nx3+2, 2, FLUID );
+         Matrix3D tmpX3Max(nx1+2, nx3+2, 2, FLUID );
+         for(int x2=0; x2<nx2; x2++ )
+            for(int x1=0; x1<nx1; x1++ )
+            {
+               tmpX3Min(x1+1, x2+1, 1) = voxelMatrix(x1, x2, 0    );
+               tmpX3Max(x1+1, x2+1, 0) = voxelMatrix(x1, x2, nx3-1);
+            }
+UBLOG(logINFO," D")
+         Matrix3D* matrices[] = { &tmpX1Min, &tmpX1Max, &tmpX2Min, &tmpX2Max, &tmpX3Min, &tmpX3Max };
+         int            dx1[] = {        -1,     nx1-1,        -1,        -1,        -1,        -1 };
+         int            dx2[] = {        -1,        -1,        -1,     nx2-1,        -1,        -1 };
+         int            dx3[] = {        -1,        -1,        -1,        -1,        -1,     nx3-1 };
+UBLOG(logINFO," E")
+         for(int i=0; i<6; i++)
+         {
+            McMatrixWrapper wrapper(matrices[i]);
+            McMarchingCubesGenerator mc(wrapper);
+
+            mc.init_all();
+            mc.run(0.5);
+
+            McVertex*   mcvertices   = mc.vertices();
+            McTriangle* mctriangles  = mc.triangles();
+
+            int deltaNodeNr = (int)nodes.size();
+UBLOG(logINFO," GbVoxelMatrix3D node tuple")
+            for(int n=0; n<mc.nverts(); n++)
+               nodes.push_back( makeUbTuple( (float)(minX1 + deltaX1 * (mcvertices[n].x + dx1[i])),   //Anm: kein -1, da man durch manipulation der indices die dreiecke um eins versetzt bekommt
+                                             (float)(minX2 + deltaX2 * (mcvertices[n].y + dx2[i])),
+                                             (float)(minX3 + deltaX3 * (mcvertices[n].z + dx3[i])) ) );
+            for(int t=0; t<mc.ntrigs(); t++)
+               triangles.push_back( makeUbTuple( deltaNodeNr+mctriangles[t].v1, deltaNodeNr+mctriangles[t].v2, deltaNodeNr+mctriangles[t].v3 ) );
+         }
+      }
+   #else
+      cerr<<"void GbVoxelMatrix3D.addSurfaceTriangleSet  - benoetigt MARCHING_CUBE paket aus 3rdParty"<<endl;
+   #endif // MC_CUBES
+
+   UBLOG(logINFO," GbVoxelMatrix3D addSurfaceTriangleSet end")
+}
+/*=======================================================*/
+string GbVoxelMatrix3D::toString() 
+{
+   return "GbVoxelMatrix3D";
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   out->writeDouble(minX1);
+   out->writeDouble(minX2);
+   out->writeDouble(minX3);
+   out->writeDouble(deltaX1);
+   out->writeDouble(deltaX2);
+   out->writeDouble(deltaX3);
+   out->writeInteger(nodesX1);
+   out->writeInteger(nodesX2);
+   out->writeInteger(nodesX3);
+   out->writeDouble(lowerThreshold);
+   out->writeDouble(upperThreshold);
+   out->writeBool(addSurfaceTriangleSetFlag);
+   out->writeBool(transferViaFilename);
+   if(!transferViaFilename)
+   {
+      throw UbException(UB_EXARGS,"void GbVoxelMatrix3D::write(UbFileOutput* out)  - geht ned");
+   }
+   else
+   {
+      out->writeString(filename);
+   }
+
+   
+   //CbUniformMatrix3D<float> voxelMatrix;
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::read(UbFileInput* in) 
+{  
+#ifdef CAB_RCF
+   try
+   {
+#endif
+      //!!! den string nimmt er vorher um das Object zu erstellen
+      //in->readString();      
+      minX1   = in->readDouble();
+      minX2   = in->readDouble();
+      minX3   = in->readDouble();
+      deltaX1 = in->readDouble();
+      deltaX2 = in->readDouble();
+      deltaX3 = in->readDouble();
+      nodesX1 = in->readInteger();
+      nodesX2 = in->readInteger();
+      nodesX3 = in->readInteger();
+      lowerThreshold = in->readDouble();
+      upperThreshold = in->readDouble();
+      addSurfaceTriangleSetFlag = in->readBool();
+      transferViaFilename = in->readBool();
+      if(!transferViaFilename)
+      {
+         throw UbException(UB_EXARGS,"void GbVoxelMatrix3D::read(UbFileOutput* out)  - geht ned");
+      }
+      else
+      {
+         filename = in->readString();
+         this->readMatrixFromVtiASCIIFile(filename);
+      }
+#ifdef CAB_RCF
+   }
+   catch(std::exception& e) { UBLOGML(logERROR, UB_FUNCTION + (std::string)e.what());        throw RCF::Exception(1002, UB_FUNCTION + (std::string)e.what() );        }                                                                                       
+   catch(...)               { UBLOGML(logERROR, UB_FUNCTION + (std::string)"unknown error"); throw RCF::Exception(1002, UB_FUNCTION + (std::string)"unknown error" ); }
+#endif
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::readMatrixFromVtiASCIIFile(std::string filename)
+
+{
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+   UbFileInputASCII in(filename);
+   //ifstream in(filename.c_str(), ios::binary);
+   if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   in.readLine();
+
+   voxelMatrix = Matrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID);
+
+   UBLOG(logINFO,"  - init values");
+   int val;
+   int u=0;
+   for(int x3=0; x3<nodesX3; x3++)
+      for(int x2=0; x2<nodesX2; x2++)
+         for(int x1=0; x1<nodesX1; x1++)
+         {
+            val = in.readInteger();
+            //if( !UbMath::equal(val, 0.0f) ) 
+            //if( UbMath::greater(val, threshold) ) 
+            if( (double)val >= lowerThreshold && (double)val <= upperThreshold ) 
+            {
+               (voxelMatrix)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+            }
+         }
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D done");
+}
+
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundX(double cX1, double cX2, double cX3)
+{
+   double tempMinPunktX1 = minX1  - cX1;
+   double tempMinPunktX2 = minX2  - cX2;
+   double tempMinPunktX3 = getX3Maximum()  - cX3;
+
+   double tempMinPunktX1tf = tempMinPunktX1;
+   double tempMinPunktX2tf = -tempMinPunktX3;
+   double tempMinPunktX3tf = tempMinPunktX2;
+
+   double minX1_temp = tempMinPunktX1tf + cX1;
+   double minX2_temp = tempMinPunktX2tf + cX2;
+   double minX3_temp = tempMinPunktX3tf + cX3;
+
+   minX2 = minX2_temp;
+   minX3 = minX3_temp;
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nx1_new = nx1; 
+   int nx2_new = nx3;
+   int nx3_new = nx2;
+
+   double delta_temp = deltaX2;
+   deltaX2 = deltaX3;
+   deltaX3 = delta_temp;
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1_new, nx2_new, nx3_new);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(x1,nx3-x3-1,x2) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundX()
+{
+   double cX1 = this->getX1Centroid();
+   double cX2 = this->getX2Centroid();
+   double cX3 = this->getX3Centroid();
+
+   rotate90aroundX(cX1, cX2, cX3);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundY(double cX1, double cX2, double cX3)
+{
+   double tempMinPunktX1 = getX1Maximum()  - cX1;
+   double tempMinPunktX2 = minX2  - cX2;
+   double tempMinPunktX3 = minX3  - cX3;
+
+   double tempMinPunktX1tf = tempMinPunktX3;
+   double tempMinPunktX2tf = tempMinPunktX2;
+   double tempMinPunktX3tf = -tempMinPunktX1;
+
+   double minX1_temp = tempMinPunktX1tf + cX1;
+   double minX2_temp = tempMinPunktX2tf + cX2;
+   double minX3_temp = tempMinPunktX3tf + cX3;
+
+   minX1 = minX1_temp;
+   minX3 = minX3_temp;
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nx1_new = nx3; 
+   int nx2_new = nx2;
+   int nx3_new = nx1;
+
+   double delta_temp = deltaX1;
+   deltaX1 = deltaX3;
+   deltaX3 = delta_temp;
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1_new, nx2_new, nx3_new);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(x3,x2,nx1-x1-1) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundY()
+{
+   double cX1 = this->getX1Centroid();
+   double cX2 = this->getX2Centroid();
+   double cX3 = this->getX3Centroid();
+   
+   rotate90aroundY(cX1, cX2, cX3);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundZ(double cX1, double cX2, double cX3)
+{
+   double tempMinPunktX1 = minX1  - cX1;
+   double tempMinPunktX2 = getX2Maximum()  - cX2;
+   double tempMinPunktX3 = minX3  - cX3;
+
+   double tempMinPunktX1tf = -tempMinPunktX2;
+   double tempMinPunktX2tf = tempMinPunktX1;
+   double tempMinPunktX3tf = tempMinPunktX3;
+
+   double minX1_temp = tempMinPunktX1tf + cX1;
+   double minX2_temp = tempMinPunktX2tf + cX2;
+   double minX3_temp = tempMinPunktX3tf + cX3;
+
+   minX1 = minX1_temp;
+   minX2 = minX2_temp;
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nx1_new = nx2; 
+   int nx2_new = nx1;
+   int nx3_new = nx3;
+
+   double delta_temp = deltaX1;
+   deltaX1 = deltaX2;
+   deltaX2 = delta_temp;
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1_new, nx2_new, nx3_new);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(nx2-x2-1,x1,x3) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundZ()
+{
+   double cX1 = this->getX1Centroid();
+   double cX2 = this->getX2Centroid();
+   double cX3 = this->getX3Centroid();
+
+   rotate90aroundZ(cX1, cX2, cX3);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::mirrorX()
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1, nx2, nx3);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(nx1-x1-1,x2,x3) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::mirrorY()
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1, nx2, nx3);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(x1,nx2-x2-1,x3) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::mirrorZ()
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1, nx2, nx3);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(x1,x2,nx3-x3-1) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::writeToLegacyVTKASCII( const std::string& fileName )
+{
+   string fn = fileName +".ascii.vtk";
+
+   FILE *file; 
+   file = fopen(fn.c_str(),"w"); 
+
+   if (file == NULL)
+   {
+      std::string pathf = UbSystem::getPathFromString(fn);
+      if (fn.size()>0) { UbSystem::makeDirectory(pathf); file = fopen(fn.c_str(), "w"); }
+      if (file == NULL) throw UbException(UB_EXARGS, "can not open " + fn);
+   }
+
+   if(file == NULL)
+      throw UbException(UB_EXARGS,"can not open "+fn);
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nn = nx1*nx2*nx3;
+
+   fprintf(file,"# vtk DataFile Version 2.0\n");
+   fprintf(file,"vtk output\n");
+   fprintf(file,"ASCII\n");
+   fprintf(file,"DATASET STRUCTURED_POINTS\n");
+   fprintf(file,"DIMENSIONS %d %d %d\n", nx1, nx2, nx3);
+   fprintf(file,"ORIGIN %g %g %g\n", minX1, minX2, minX3);
+   fprintf(file,"SPACING %g %g %g\n", deltaX1, deltaX2, deltaX3);
+   fprintf(file,"POINT_DATA %d\n", nn);
+   fprintf(file,"SCALARS Geo float\n");
+   fprintf(file,"LOOKUP_TABLE default\n");
+
+   for(int k=0 ; k<nx3 ; k++){
+      for(int j=0 ; j<nx2 ; j++){
+         for(int i=0 ; i<nx1 ; i++){
+            fprintf(file,"%g ", voxelMatrix(i,j,k));
+         }
+      }
+   }
+
+   fprintf(file,"\n");
+
+   fclose(file);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::writeToLegacyVTKBinary( const std::string& fileName )
+{
+   string fn = fileName +".binary.vtk";
+  
+   FILE *file; 
+   file = fopen(fn.c_str(),"w"); 
+
+   if (file == NULL)
+   {
+      std::string pathf = UbSystem::getPathFromString(fn);
+      if (fn.size()>0) { UbSystem::makeDirectory(pathf); file = fopen(fn.c_str(), "w"); }
+      if (file == NULL) throw UbException(UB_EXARGS, "can not open " + fn);
+   }
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nn = nx1*nx2*nx3;
+
+   char LF = 0x0A;
+
+   fprintf(file,"# vtk DataFile Version 3.0\n");
+   fprintf(file,"vtk output\n");
+   fprintf(file,"BINARY\n");
+   fprintf(file,"DATASET STRUCTURED_POINTS\n");
+   fprintf(file,"DIMENSIONS %d %d %d\n", nx1, nx2, nx3);
+   fprintf(file,"ORIGIN %g %g %g\n", minX1, minX2, minX3);
+   fprintf(file,"SPACING %g %g %g\n", deltaX1, deltaX2, deltaX3);
+   fprintf(file,"POINT_DATA %d\n", nn);
+   fprintf(file,"SCALARS Geo float\n");
+   fprintf(file,"LOOKUP_TABLE default");
+   fclose(file);
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1, nx2, nx3);
+
+   if (UbSystem::isLittleEndian())
+   {
+      for (int x3=0; x3<nx3;x3++){
+         for (int x2=0; x2<nx2;x2++){
+            for(int x1=0; x1<nx1;x1++)
+            {
+               float tmp = this->voxelMatrix(x1,x2,x3);
+               UbSystem::swapByteOrder((unsigned char*)(&(tmp)), sizeof(float));
+               voxelMatrix_temp(x1,x2,x3) = tmp;
+            }
+         }
+      }
+   }
+
+   file = fopen(fn.c_str(), "ab");
+   
+   fwrite (&LF, sizeof(char), 1, file);
+   fwrite(voxelMatrix_temp.getStartAdressOfSortedArray(0,0,0), sizeof(float), voxelMatrix_temp.getDataVector().size(), file);
+   fwrite (&LF, sizeof(char), 1, file);
+   fclose(file);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::writeToVTKImageDataASCII( const std::string& fileName )
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   string fn = fileName +".ascii.vti";
+
+   FILE *file; 
+   file = fopen(fn.c_str(),"w"); 
+
+   if (file == NULL)
+   {
+      std::string pathf = UbSystem::getPathFromString(fn);
+      if (fn.size()>0) { UbSystem::makeDirectory(pathf); file = fopen(fn.c_str(), "w"); }
+      if (file == NULL) throw UbException(UB_EXARGS, "can not open " + fn);
+   }
+
+   fprintf(file,"<VTKFile type=\"ImageData\" version=\"1.0\" byte_order=\"LittleEndian\" header_type=\"UInt64\">\n"); //paraview 4.1
+   //fprintf(file,"<VTKFile type=\"ImageData\" version=\"0.1\" byte_order=\"LittleEndian\">\n"); //paraview 3.1
+   fprintf(file,"  <ImageData WholeExtent=\"%d %d %d %d %d %d\" Origin=\"%g %g %g\" Spacing=\"%g %g %g\">\n", 0, nx1-1, 0, nx2-1, 0, nx3-1, minX1, minX2, minX3, deltaX1, deltaX2, deltaX3);
+   fprintf(file,"  <Piece Extent=\"%d %d %d %d %d %d\">\n", 0, nx1-1, 0, nx2-1, 0, nx3-1);
+   fprintf(file,"    <PointData Scalars=\"VoxelMatrix\">\n");
+   fprintf(file,"      <DataArray type=\"Float32\" Name=\"VoxelMatrix\" format=\"ascii\" RangeMin=\"0\" RangeMax=\"1\">\n        "); 
+
+   for(int k=0 ; k<nx3 ; k++){
+      for(int j=0 ; j<nx2 ; j++){
+         for(int i=0 ; i<nx1 ; i++){
+            fprintf(file,"%g ",voxelMatrix(i,j,k));
+         }
+      }
+   }
+
+   fprintf(file,"\n      </DataArray>\n");
+   fprintf(file,"    </PointData>\n");
+   fprintf(file,"    <CellData>\n");
+   fprintf(file,"    </CellData>\n");
+   fprintf(file,"  </Piece>\n");
+   fprintf(file,"  </ImageData>\n");
+   fprintf(file,"</VTKFile>\n");
+
+   fclose(file); 
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::writeToVTKImageDataAppended( const std::string& fileName )
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   string fn = fileName +".appended.vti";
+
+   FILE *file; 
+   file = fopen(fn.c_str(),"w"); 
+
+   if (file == NULL)
+   {
+      std::string pathf = UbSystem::getPathFromString(fn);
+      if (fn.size()>0) { UbSystem::makeDirectory(pathf); file = fopen(fn.c_str(), "w"); }
+      if (file == NULL) throw UbException(UB_EXARGS, "can not open " + fn);
+   }
+
+   fprintf(file,"<VTKFile type=\"ImageData\" version=\"1.0\" byte_order=\"LittleEndian\" header_type=\"UInt64\">\n"); //paraview 4.1
+   fprintf(file,"  <ImageData WholeExtent=\"%d %d %d %d %d %d\" Origin=\"%g %g %g\" Spacing=\"%g %g %g\">\n", 0, nx1-1, 0, nx2-1, 0, nx3-1,  minX1, minX2, minX3, deltaX1, deltaX2, deltaX3);
+   fprintf(file,"  <Piece Extent=\"%d %d %d %d %d %d\">\n", 0, nx1-1, 0, nx2-1, 0, nx3-1);
+   fprintf(file,"    <PointData Scalars=\"VoxelMatrix\">\n");
+   fprintf(file,"      <DataArray type=\"Float32\" Name=\"VoxelMatrix\" format=\"appended\" RangeMin=\"0\" RangeMax=\"1\" offset=\"0\" />\n"); 
+   fprintf(file,"    </PointData>\n");
+   fprintf(file,"    <CellData>\n");
+   fprintf(file,"    </CellData>\n");
+   fprintf(file,"  </Piece>\n");
+   fprintf(file,"  </ImageData>\n");
+   fprintf(file,"  <AppendedData encoding=\"raw\">\n");
+   fprintf(file,"   _");
+   fclose(file);
+
+   file = fopen(fn.c_str(), "ab");
+   int size = (int)voxelMatrix.getDataVector().size() * sizeof(float);
+   fwrite (&size, sizeof(int), 1, file);
+   fwrite(voxelMatrix.getStartAdressOfSortedArray(0,0,0), sizeof(float), voxelMatrix.getDataVector().size(), file);
+   fclose(file);
+
+   file = fopen(fn.c_str(),"a");
+   fprintf(file,"\n");
+   fprintf(file,"  </AppendedData>\n");
+   fprintf(file,"</VTKFile>\n");
+   fclose(file); 
+}
+
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/GbVoxelMatrix3D.h b/source/ThirdParty/Library/numerics/geometry3d/GbVoxelMatrix3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c26ca05a2a6b008fe7391e8b27aed68803ee93b
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/GbVoxelMatrix3D.h
@@ -0,0 +1,340 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBVOXELMATRIX3D_H
+#define GBVOXELMATRIX3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <basics/utilities/UbObserver.h>
+#include <basics/container/CbArray3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbVoxelMatrix3D;
+typedef VFSharedPtr<GbVoxelMatrix3D> GbVoxelMatrix3DPtr;
+
+
+class GbLine3D;                    
+class GbTriangle3D;                    
+class GbObject3DCreator;
+
+class GbVoxelMatrix3D : public GbObject3D, public UbObserver
+{
+public:              
+   typedef CbArray3D<float> Matrix3D;
+   static const float SOLID; 
+   static const float FLUID; 
+   enum  Endian {BigEndian, LittleEndian};
+
+   GbVoxelMatrix3D();
+   GbVoxelMatrix3D(int nx1, int nx2, int nx3, float initVal, double lowerThreshold=0, double upperThreshold=0);
+   GbVoxelMatrix3D(const Matrix3D& voxelMatrix, double lowerThreshold=0, double upperThreshold=0);
+   ~GbVoxelMatrix3D() {}   
+
+   void finalize() {};
+   GbVoxelMatrix3D* clone(); 
+
+   /*=======================================================================*/
+   Matrix3D::reference operator() (const Matrix3D::size_type& x1, const Matrix3D::size_type& x2, const Matrix3D::size_type& x3)
+   {
+      return voxelMatrix(x1,x2,x3);
+   }
+   /*=======================================================================*/
+   Matrix3D::const_reference operator() (const Matrix3D::size_type& x1, const Matrix3D::size_type& x2, const Matrix3D::size_type& x3)	const
+   {
+      return voxelMatrix(x1,x2,x3);
+   }
+   /*=======================================================================*/
+   void setTransferViaFilename(bool transferViaFilename, std::string filename)
+   {
+      this->filename = filename;
+      this->transferViaFilename = transferViaFilename;
+   }
+   void setThreshold(double lowerThreshold, double upperThreshold) { this->lowerThreshold = lowerThreshold; this->upperThreshold = upperThreshold; }
+   void setAddSurfaceTriangleSetFlag(bool flag) { this->addSurfaceTriangleSetFlag = flag; }
+
+   /*=======================================================================*/
+   void setVoxelMatrixMininum(double minX1, double minX2, double minX3) { this->minX1 = minX1; this->minX2 = minX2; this->minX3 = minX3; }
+   void setVoxelMatrixMinX1(double minX1) { this->minX1 = minX1; }
+   void setVoxelMatrixMinX2(double minX2) { this->minX2 = minX2; }
+   void setVoxelMatrixMinX3(double minX3) { this->minX3 = minX3; }
+   
+   /*=======================================================================*/
+   void setVoxelMatrixDelta(double deltaX1, double deltaX2, double deltaX3) { this->deltaX1 = deltaX1; this->deltaX2 = deltaX2; this->deltaX3 = deltaX3; }
+   void setVoxelMatrixDeltaX1(double deltaX1) { this->deltaX1 = deltaX1; }
+   void setVoxelMatrixDeltaX2(double deltaX2) { this->deltaX2 = deltaX2; }
+   void setVoxelMatrixDeltaX3(double deltaX3) { this->deltaX3 = deltaX3; }
+
+   /*=======================================================================*/
+   double getX1Centroid() { return 0.5 * ( minX1 + this->getX1Maximum() ); } 
+   double getX1Minimum()  { return minX1; }
+   double getX1Maximum()  { return minX1 + deltaX1*voxelMatrix.getNX1(); }  
+
+   double getX2Centroid() { return 0.5 * ( minX2 + this->getX2Maximum() ); } 
+   double getX2Minimum()  { return minX2; }
+   double getX2Maximum()  { return minX2 + deltaX2*voxelMatrix.getNX2(); }  
+
+   double getX3Centroid() { return 0.5 * ( this->getX3Minimum() + this->getX3Maximum() ); } 
+   double getX3Minimum()  { return minX3; }
+   double getX3Maximum()  { return minX3 + deltaX3*voxelMatrix.getNX3(); }  
+
+   double getLengthX1() { return this->getX1Maximum() - minX1; }
+   double getLengthX2() { return this->getX2Maximum() - minX2; }
+   double getLengthX3() { return this->getX3Maximum() - minX3; }
+
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+   void translate(const double& tx1, const double& tx2, const double& tx3);
+
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary);
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); 
+   bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   //double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+   GbPoint3D*  calculateInterSectionPoint3D(GbPoint3D& point1, GbPoint3D &point2) { throw UbException(__FILE__,__LINE__, UB_FUNCTION,"not implemented");}
+   GbLine3D*   createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2){ throw UbException(__FILE__,__LINE__, UB_FUNCTION,"not implemented");}
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+   std::string toString();
+
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject) {}
+   void objectWillBeDeleted(UbObservable* objectForDeletion) {}
+
+   template <class T>
+   void readMatrixFromRawFile(std::string filename, GbVoxelMatrix3D::Endian endian);
+   template <class T>
+   void readBufferedMatrixFromRawFile(std::string filename, GbVoxelMatrix3D::Endian endian);
+   void readMatrixFromVtiASCIIFile(std::string filename);
+
+   void rotate90aroundX();
+   void rotate90aroundY();
+   void rotate90aroundZ();
+   void rotate90aroundX(double cX1, double cX2, double cX3);
+   void rotate90aroundY(double cX1, double cX2, double cX3);
+   void rotate90aroundZ(double cX1, double cX2, double cX3);
+   void mirrorX();
+   void mirrorY();
+   void mirrorZ();
+
+   void writeToLegacyVTKASCII(const std::string& fileName);
+   void writeToLegacyVTKBinary( const std::string& fileName );
+   void writeToVTKImageDataASCII(const std::string& fileName);
+   void writeToVTKImageDataAppended(const std::string& fileName);
+
+   void setClosedVoidSpaceToSolid();
+
+   void calculateNumberOfSolidAndFluid();
+   long getNumberOfSolid();
+   long getNumberOfFluid();
+
+protected:
+   void findFluidNeighbor(int cx1, int cx2, int cx3);
+   Matrix3D voxelMatrixTemp;
+   CbArray3D<char> flagMatrix;
+
+   std::vector<int> x1Nbr;
+   std::vector<int> x2Nbr;
+   std::vector<int> x3Nbr;
+
+   std::vector<int> x1NbrTemp;
+   std::vector<int> x2NbrTemp;
+   std::vector<int> x3NbrTemp;
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & minX1;
+      ar & minX2;
+      ar & minX3;
+      ar & deltaX1;
+      ar & deltaX2;
+      ar & deltaX3;
+      ar & nodesX1;
+      ar & nodesX2;
+      ar & nodesX3;
+      ar & threshold;
+      ar & transferViaFilename;
+      ar & addSurfaceTriangleSetFlag;
+      if(!transferViaFilename)
+      {
+         ar & voxelMatrix;
+      }
+      else
+      {
+         ar & filename;
+         if(ArchiveTools::isReading(ar) ) 
+         {
+            this->readMatrixFromVtiASCIIFile(filename);
+         }
+      }
+
+   }
+#endif //CAB_RCF
+
+protected:
+   //for transfer
+   std::string filename;
+   bool transferViaFilename;
+
+   bool addSurfaceTriangleSetFlag;
+
+   int nodesX1;
+   int nodesX2;
+   int nodesX3;
+   double lowerThreshold, upperThreshold;
+
+   double minX1;
+   double minX2;
+   double minX3;
+   double deltaX1;
+   double deltaX2;
+   double deltaX3;
+
+   Matrix3D voxelMatrix;
+
+   long numberOfSolid;
+   long numberOfFluid;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void GbVoxelMatrix3D::readMatrixFromRawFile(std::string filename, GbVoxelMatrix3D::Endian endian)
+{
+   using namespace std;
+   UBLOG(logINFO,"GbVoxelMatrix3D::readMatrixFromFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+   ifstream in(filename.c_str(), ios::binary);
+   if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+
+   in.seekg( 0, ios::end );     //Ende springen
+   fstream::off_type length = in.tellg(); //Position abfragen
+   in.seekg( 0, ios::beg );    //An den Anfang springen 
+
+   //UBLOG(logINFO,"number of nodes = "<<nodesX1*nodesX2*nodesX3*sizeof(T)<<" file size = "<<(long)length);
+   //if( (nodesX1*nodesX2*nodesX3)*sizeof(float) != (long)length )
+   unsigned long long nofn = nodesX1*nodesX2*nodesX3*sizeof(T);
+   if (nofn != (unsigned long long)length)
+   {
+      throw UbException(UB_EXARGS,"number of nodes("+UbSystem::toString(nofn)+") doesn't match file size("+UbSystem::toString((long)length)+")");
+   }
+
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+   //GbVoxelMatrix3D* voxelGeo = new GbVoxelMatrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID);
+   voxelMatrix = Matrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID);
+
+   UBLOG(logINFO,"  - init values");
+   //float val;
+   T val;
+   for(int x3=0; x3<nodesX3; x3++)
+      for(int x2=0; x2<nodesX2; x2++)
+         for(int x1=0; x1<nodesX1; x1++)
+         {
+            //in.read((char*)&val,sizeof(float));
+            in.read((char*)&val,sizeof(T));
+            if (endian == BigEndian)
+               UbSystem::swapByteOrder((unsigned char*)(&(val)), sizeof(T));
+            //if( UbMath::equal((double)val, threshold) ) 
+            //if( UbMath::greater((double)val, threshold) )
+            if( (double)val >= lowerThreshold && (double)val <= upperThreshold ) 
+            {
+               (voxelMatrix)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+            }
+            //(voxelMatrix)(x1, x2, x3) = (float)val;
+         }
+
+         UBLOG(logINFO,"GbVoxelMatrix3D::readMatrixFromFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void GbVoxelMatrix3D::readBufferedMatrixFromRawFile(std::string filename, GbVoxelMatrix3D::Endian endian)
+{
+   using namespace std;
+   UBLOG(logINFO, "GbVoxelMatrix3D::readMatrixFromRawFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+
+   FILE *file;
+   file = fopen(filename.c_str(), "rb");
+   if (file==NULL)
+   {
+      throw UbException(UB_EXARGS, "Could not open file "+filename);
+   }
+
+   // obtain file size:
+   fseek(file, 0, SEEK_END);
+   unsigned long int length = ftell(file);
+   rewind(file);
+
+   UBLOG(logINFO, "number of nodes = "<<(long)nodesX1*(long)nodesX2*(long)nodesX3<<" file size = "<<length);
+   
+   unsigned long int nofn = (long)nodesX1*(long)nodesX2*(long)nodesX3*(long)sizeof(T);
+   if (nofn != length)
+   {
+      //throw UbException(UB_EXARGS, "number of nodes("+UbSystem::toString(nofn)+") doesn't match file size("+UbSystem::toString(length)+")");
+   }
+
+   UBLOG(logINFO, "  - create GbVoxelMatrix3D");
+   voxelMatrix = Matrix3D(nodesX1, nodesX2, nodesX3, GbVoxelMatrix3D::FLUID);
+
+   CbArray3D<T> readMatrix(nodesX1, nodesX2, nodesX3);
+
+   UBLOG(logINFO, "  - read file to matrix");
+   fread(readMatrix.getStartAdressOfSortedArray(0, 0, 0), sizeof(T), readMatrix.getDataVector().size(), file);
+   fclose(file);
+
+   UBLOG(logINFO, "  - init values");
+
+   numberOfSolid = 0;
+   T val;
+   for (int x3 = 0; x3<nodesX3; x3++)
+      for (int x2 = 0; x2<nodesX2; x2++)
+         for (int x1 = 0; x1<nodesX1; x1++)
+         {
+            val = readMatrix(x1, x2, x3);
+
+            if (endian == BigEndian)
+            {
+               UbSystem::swapByteOrder((unsigned char*)(&(val)), sizeof(T));
+            }
+
+            if ((double)val >= lowerThreshold && (double)val <= upperThreshold)
+            {
+               voxelMatrix(x1, x2, x3) = GbVoxelMatrix3D::SOLID;
+            }
+         }
+
+   UBLOG(logINFO, "GbVoxelMatrix3D::readMatrixFromRawFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+}
+
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbVoxelMatrix3D>("GbVoxelMatrix3D")        , SF_GbVoxelMatrix3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbVoxelMatrix3D >()), SF_GbVoxelMatrix3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbVoxelMatrix3D>() ), SF_GbVoxelMatrix3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/CMakePackage.txt b/source/ThirdParty/Library/numerics/geometry3d/KdTree/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8d2943620ae0f1b9f1a22b47979b2a23b2523256
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/CMakePackage.txt
@@ -0,0 +1,4 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR}                      ALL_SOURCES)
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR}/splitalgorithms      ALL_SOURCES)
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR}/intersectionhandler ALL_SOURCES)
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdNode.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdNode.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b38011b10a124ad1962f39680479d3142249e5d
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdNode.h
@@ -0,0 +1,284 @@
+#ifndef KDNODE_H
+#define KDNODE_H
+
+#include <basics/memory/MbSmartPtr.h>
+
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbKeys.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/KdRay.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdRayIntersectionHandler.h>
+
+
+#include <vector>
+#include <string>
+
+namespace Kd
+{
+   template< typename T >
+   class Node 
+   {
+   public:
+      Node(  const T& x1, const T& y1, const T& z1
+           , const T& x2, const T& y2, const T& z2
+           , const MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFaces
+           , std::vector<GbTriFaceMesh3D::Vertex>* ptrNodes ) 
+         : child1(NULL)
+         , child2(NULL)
+         , triFaces(triFaces)
+         , ptrNodes(ptrNodes)
+      {
+         if( x1 < x2 ) { this->x[0] = x1; this->x[1] = x2; }
+         else          { this->x[0] = x2; this->x[1] = x1; }
+
+         if( y1 < y2 ) { this->y[0] = y1; this->y[1] = y2; }
+         else          { this->y[0] = y2; this->y[1] = y1; }
+
+         if( z1 < z2 ) { this->z[0] = z1; this->z[1] = z2; }
+         else          { this->z[0] = z2; this->z[1] = z1; }
+      }
+      /* ======================================================================================= */
+      ~Node()
+      {
+         if(child1) { delete child1; child1 = NULL;  }
+         if(child2) { delete child2; child2 = NULL;  }
+      }
+      /* ======================================================================================= */
+      bool isLeaf() 
+      {
+         return child1 == NULL && child2 == NULL;
+      }
+      /* ======================================================================================= */
+      void deleteTriFaces() 
+      {
+         triFaces = MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> >();
+      }
+      /* ======================================================================================= */
+      const MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> >& getTriFaces() 
+      {
+         return triFaces;
+      }
+      /* ======================================================================================= */
+      std::vector<GbTriFaceMesh3D::Vertex>& getNodes() 
+      {
+         if(!ptrNodes) throw UbException(UB_EXARGS,"ups,no nodes");
+         return *ptrNodes;
+      }
+
+      /* ======================================================================================= */
+      void buildTree(const int& level, const int& maxLevel, const SplitAlgorithm<T>& splitAlg) 
+      {
+         SplitCandidate<T> splitCandidate = splitAlg.findBestSplitCandidate(level, maxLevel, *this);
+
+         if( splitCandidate.isValid ) 
+         {
+
+            MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFacesForChild1( new std::vector<GbTriFaceMesh3D::TriFace> );
+            MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFacesForChild2( new std::vector<GbTriFaceMesh3D::TriFace> );
+
+            splitAlg.distributeTriFaces(splitCandidate, *triFacesForChild1, *triFacesForChild2, *this);
+
+            //////////////////////////////////////////////////////////////////////////
+            // calculate center points and edges of new child nodes
+            T x1_l = x[0], y1_l = y[0], z1_l = z[0];
+            T x2_l = x[1], y2_l = y[1], z2_l = z[1];
+            T x1_r = x[0], y1_r = y[0], z1_r = z[0];
+            T x2_r = x[1], y2_r = y[1], z2_r = z[1];
+
+            if (splitCandidate.axis == Axis::X) 
+            {
+               x2_l = splitCandidate.position;
+               x1_r = splitCandidate.position;
+            } 
+            else if (splitCandidate.axis == Axis::Y)
+            {
+               y2_l = splitCandidate.position;
+               y1_r = splitCandidate.position;
+            } 
+            else 
+            {
+               z2_l = splitCandidate.position;
+               z1_r = splitCandidate.position;
+            }
+            // ----------------------------------------------------------------------
+            // ----------------------------------------------------------------------
+
+            if (triFacesForChild1->size() > 0) 
+            {
+               if( this->child1 ) delete this->child1;
+               this->child1 = new Node(x1_l, y1_l, z1_l, x2_l, y2_l, z2_l, triFacesForChild1, ptrNodes);
+               this->child1->buildTree(level + 1, maxLevel, splitAlg);
+            }
+            
+            if (triFacesForChild2->size() > 0) 
+            {
+               if( this->child2 ) delete this->child2;
+               this->child2 = new Node(x1_r, y1_r, z1_r, x2_r, y2_r, z2_r, triFacesForChild2, ptrNodes);
+               this->child2->buildTree(level + 1, maxLevel, splitAlg);
+            }
+         }
+      }
+      /* ======================================================================================= */
+      int intersectLineBoundingBox(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2) 
+      {
+         const T& n1X = val<1>(n1);
+         const T& n1Y = val<2>(n1);
+         const T& n1Z = val<3>(n1);
+
+         const T& n2X = val<1>(n2);
+         const T& n2Y = val<2>(n2);
+         const T& n2Z = val<3>(n2);
+
+         double t_nah  = UbMath::max(  ( (n1X <= n2X ? x[0] : x[1]) - n1X) / (n2X - n1X)
+                                     , ( (n1Y <= n2Y ? y[0] : y[1]) - n1Y) / (n2Y - n1Y)
+                                     , ( (n1Z <= n2Z ? z[0] : z[1]) - n1Z) / (n2Z - n1Z) );
+
+         double t_fern = UbMath::min(  ( (n1X >  n2X ? x[0] : x[1]) - n1X) / (n2X - n1X)
+                                     , ( (n1Y >  n2Y ? y[0] : y[1]) - n1Y) / (n2Y - n1Y)
+                                     , ( (n1Z >  n2Z ? z[0] : z[1]) - n1Z) / (n2Z - n1Z) );
+
+         if ( UbMath::greater(  UbMath::max(  ( (n1X <= n2X ? x[0] : x[1]) - n1X) / (n2X - n1X)
+                                            , ( (n1Y <= n2Y ? y[0] : y[1]) - n1Y) / (n2Y - n1Y)
+                                            , ( (n1Z <= n2Z ? z[0] : z[1]) - n1Z) / (n2Z - n1Z) )
+                              , UbMath::min(  ( (n1X >  n2X ? x[0] : x[1]) - n1X) / (n2X - n1X)
+                                            , ( (n1Y >  n2Y ? y[0] : y[1]) - n1Y) / (n2Y - n1Y)
+                                            , ( (n1Z >  n2Z ? z[0] : z[1]) - n1Z) / (n2Z - n1Z) ) ) )
+         {
+            return Intersection::NO_INTERSECTION;
+         } 
+         else
+         {
+            return Intersection::INTERSECTION;
+         }
+      }
+      /* ======================================================================================= */
+      int intersectRayBoundingBox(const Ray<T>& ray) 
+      {
+         T tmin  = (x[  ray.signX] - ray.originX) * ray.inv_directionX;
+         T tmax  = (x[1-ray.signX] - ray.originX) * ray.inv_directionX;
+        
+         T tymin = (y[  ray.signY] - ray.originY) * ray.inv_directionY;
+         T tymax = (y[1-ray.signY] - ray.originY) * ray.inv_directionY;
+         
+         if( (tmin > tymax) || (tymin > tmax) ) 
+         {
+            return false;
+         }
+         if( tymin > tmin ) tmin = tymin;
+         if( tymax < tmax ) tmax = tymax;
+
+         T tzmin = (z[  ray.signZ] - ray.originZ) * ray.inv_directionZ;
+         T tzmax = (z[1-ray.signZ] - ray.originZ) * ray.inv_directionZ;
+         
+         //if( (UbMath::greater( tmin, tzmax) ) || ( UbMath::greater( tzmin, tmax) ) ) 
+         if( ( tmin > tzmax) || ( tzmin > tmax)  ) 
+         {
+            return false;
+         }
+         //if(tzmin > tmin) tmin = tzmin;
+         if(tzmax < tmax) tmax = tzmax;
+         
+         //return ( (tmin =< t1) && (tmax >= t0) );
+         if( UbMath::greaterEqual( tmax, T(0.0) ) )   
+         {
+            return Intersection::INTERSECTION;
+         }
+         else
+         {
+            return Intersection::NO_INTERSECTION;
+         }
+      }
+      /* ======================================================================================= */
+      bool intersectLine(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2, const LineIntersectionHandler<T>& iHandler) 
+      {
+         return iHandler.intersectLine(n1, n2, *this, child1, child2);
+      }
+      /* ======================================================================================= */
+      int intersectRay(const Ray<T>& ray, const RayIntersectionHandler<T>& iHandler, std::set< UbKeys::Key3<int> >& mailbox) 
+      {
+         return iHandler.intersectRay(ray, *this, child1, child2, mailbox);
+      }
+      /* ======================================================================================= */
+      int getNumOfTriFaces()
+      {
+         if(!child1 && !child2)
+         {  
+            if(triFaces) return (int)triFaces->size();
+            else         return 0;
+         } 
+         else 
+         {
+            int sum = 0;
+
+            if(child1) sum += child1->getNumOfTriFaces();
+            if(child2) sum += child2->getNumOfTriFaces();
+
+            return sum;
+         }
+      }
+      /* ======================================================================================= */
+      int getNumOfNodes()
+      {
+         if( !child1 && !child2) 
+         {
+            return 1;
+         } 
+         else
+         {
+            int sum = 0;
+            if(child1) sum += child1->getNumOfNodes();
+            if(child2) sum += child2->getNumOfNodes();
+
+            return 1 + sum;
+         }
+      }
+      /* ======================================================================================= */
+      std::string toString()
+      {
+         return "";//"[" + x1 + "," + y1 + "," + z1 + "]  -" + "  [" + x2 + "," + y2 + "," + z2 + "]";
+      }
+      /* ======================================================================================= */
+      void addCubeInfo(std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata)
+      {
+         nodes.push_back( makeUbTuple(float(x[0]), float(y[0]), float(z[0]) ) );
+         nodes.push_back( makeUbTuple(float(x[1]), float(y[0]), float(z[0]) ) );
+         nodes.push_back( makeUbTuple(float(x[1]), float(y[1]), float(z[0]) ) );
+         nodes.push_back( makeUbTuple(float(x[0]), float(y[1]), float(z[0]) ) );
+         
+         nodes.push_back( makeUbTuple(float(x[0]), float(y[0]), float(z[1]) ) );
+         nodes.push_back( makeUbTuple(float(x[1]), float(y[0]), float(z[1]) ) );
+         nodes.push_back( makeUbTuple(float(x[1]), float(y[1]), float(z[1]) ) );
+         nodes.push_back( makeUbTuple(float(x[0]), float(y[1]), float(z[1]) ) );
+
+         cells.push_back( makeUbTuple( int(nodes.size()-8), int(nodes.size()-7), int(nodes.size()-6), int(nodes.size()-5), 
+                                       int(nodes.size()-4), int(nodes.size()-3), int(nodes.size()-2), int(nodes.size()-1) ) );
+         datanames.resize(1);
+         datanames[0] = "childs";
+         celldata.resize( datanames.size() );
+         if     ( child1 && child2 ) celldata[0].push_back(2);
+         else if( child1 || child2 ) celldata[0].push_back(1);
+         else                        celldata[0].push_back(0);
+
+         if(child1) child1->addCubeInfo(nodes, cells, datanames, celldata);
+         if(child2) child2->addCubeInfo(nodes, cells, datanames, celldata);
+      }
+
+   public:
+      T x[2], y[2], z[2];
+
+   private:
+      Node* child1;
+      Node* child2;
+
+      MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFaces;
+      std::vector<GbTriFaceMesh3D::Vertex>*               ptrNodes;  //lediglich für Zugriff auf die Knoten!!!
+   };
+}
+#endif //KDNODE_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdRay.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdRay.h
new file mode 100644
index 0000000000000000000000000000000000000000..c53dfa93fc5b0b99f9adb40cd556cce5756433aa
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdRay.h
@@ -0,0 +1,69 @@
+#ifndef KDRAY_H
+#define KDRAY_H
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbMath.h>
+
+
+namespace Kd
+{
+   /*
+   * Ray class, for use with the optimized ray-box intersection test
+   * described in:
+   *
+   *      Amy Williams, Steve Barrus, R. Keith Morley, and Peter Shirley
+   *      "An Efficient and Robust Ray-Box Intersection Algorithm"
+   *      Journal of graphics tools, 10(1):49-54, 2005
+   * 
+   */
+   template< typename T>
+   class Ray 
+   {
+   public:
+      Ray(  const T& originX   , const T& originY   , const T& originZ
+          , const T& directionX, const T& directionY, const T& directionZ ) 
+      {
+         this->originX        = originX;
+         this->originY        = originY;
+         this->originZ        = originZ;
+
+         //normierung (fuer ray-triangle-intersection)
+         T oneOverLength = T(1.0/std::sqrt(  directionX*directionX 
+                                            + directionY*directionY 
+                                            + directionZ*directionZ ) );
+
+         this->directionX     = directionX*oneOverLength;
+         this->directionY     = directionY*oneOverLength;
+         this->directionZ     = directionZ*oneOverLength;
+
+         this->inv_directionX = T(1.0/this->directionX);   //ACHTUNG: BEWUSST KEINE ==0 Abfrage
+         this->inv_directionY = T(1.0/this->directionY);   //Alg verwendet exlitzit INF
+         this->inv_directionZ = T(1.0/this->directionZ);
+         
+         if(this->inv_directionX < 0.0) this->signX = 1;
+         else                           this->signX = 0;
+         if(this->inv_directionY < 0.0) this->signY = 1;
+         else                           this->signY = 0;
+         if(this->inv_directionZ < 0.0) this->signZ = 1;
+         else                           this->signZ = 0;
+      }
+
+      T   originX;
+      T   originY;
+      T   originZ;
+        
+      T   directionX;
+      T   directionY;
+      T   directionZ;
+        
+      T   inv_directionX;
+      T   inv_directionY;
+      T   inv_directionZ;
+      
+      int signX;
+      int signY;
+      int signZ;
+   };
+} //namespace Kd
+
+#endif //KDRAY_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdSplitCandidate.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdSplitCandidate.h
new file mode 100644
index 0000000000000000000000000000000000000000..361550555498cf4d5eae0ef00d68a720895055ab
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdSplitCandidate.h
@@ -0,0 +1,68 @@
+#ifndef KDSPLITCANDIDATE_H
+#define KDSPLITCANDIDATE_H
+
+#include <basics/utilities/UbMath.h>
+
+namespace Kd
+{
+   template< typename T >
+   class SplitCandidate   
+   {
+   public:
+      SplitCandidate() 
+         :  axis(0)
+          , position(0.0)
+          , starting(0)
+          , ending(0)
+          , np_left(false)
+          , np_right(false)
+          , Cn(0.0)
+          , nr(0)
+          , nl(0)  
+          , isValid(false)
+      {
+
+      }
+      /* ======================================================================================= */
+      SplitCandidate(const int& axis, const T& position, const int& starting, const int& ending, const int& insidePlane)
+         : np_left(false)
+         , np_right(false)
+         , axis(axis)
+         , position(position)
+         , starting(starting)
+         , ending(ending)
+         , np(insidePlane)
+         , Cn(0.0) 
+         , nr(0)  
+         , nl(0)  
+         , isValid(true)
+      {
+      }
+      /* ======================================================================================= */
+      bool operator!() const
+      {
+         return isValid; 
+      }
+      /* ======================================================================================= */
+      friend inline bool operator< (const SplitCandidate& lhs, const SplitCandidate& rhs)  
+      {
+         return  lhs.position < rhs.position;
+      }
+      /* ======================================================================================= */
+
+   public:
+      int     axis;
+      T       Cn;
+      T       position;
+      int     nl;
+      int     nr;
+      int     np;
+      int     starting;
+      int     ending;
+      bool    np_left;
+      bool    np_right;
+      bool    isValid;
+   };
+}
+
+#endif //KDSPLITCANDIDATE_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdSplitCandidateManager.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdSplitCandidateManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..0278807f8dd3b97e8303f0935205060852adc6d4
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdSplitCandidateManager.h
@@ -0,0 +1,75 @@
+#ifndef KDSPLITCANDIDATEMANAGER_H
+#define KDSPLITCANDIDATEMANAGER_H
+
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+
+#include <map>
+#include <vector>
+#include <algorithm>
+
+
+namespace Kd
+{
+   template< typename T >
+   class SplitCandidateManager  
+   {
+   public:
+      SplitCandidateManager()
+         : objects_starting_outside_left(0)
+         , objects_fully_outside_node(0)
+      {
+
+      }
+      /* ======================================================================================= */
+      SplitCandidate<T>& operator[] (const int& i) 
+      { 
+         #ifdef DEBUG
+            return splitCandidatesVec.at(i);
+         #else
+            return splitCandidatesVec[i];
+         #endif  
+      }
+      /* ======================================================================================= */
+      typename std::vector< SplitCandidate< T > >::size_type size()
+      { 
+         return splitCandidatesVec.size();
+      }
+      /* ======================================================================================= */
+      void add(const T& pos, const int& axis, const int& starting, const int& ending, const int& np)
+      {
+         typename std::map<T, SplitCandidate<T> >::iterator it = splitCandidates.find(pos); 
+         if ( it != splitCandidates.end() )   //split candidate is already available -> increase parameter (starting, ending and np)
+         {
+            SplitCandidate<T>& sc = it->second;
+            sc.np       += np;
+            sc.starting += starting;
+            sc.ending   += ending;
+         } 
+         else // split candidate is not available -> add new split candidate
+         {
+            this->splitCandidates[pos] = SplitCandidate<T>(axis, pos, starting, ending, np);
+         }
+      }
+      /* ======================================================================================= */
+      void createSortedArray()
+      {
+         splitCandidatesVec.clear();
+         typename std::map<T, SplitCandidate<T> >::iterator it;
+         for( it=splitCandidates.begin(); it!=splitCandidates.end(); ++it)
+            splitCandidatesVec.push_back(it->second);
+         splitCandidates.clear();
+         std::sort(splitCandidatesVec.begin(), splitCandidatesVec.end(), std::less< SplitCandidate<T> >() );
+      }
+      /* ======================================================================================= */
+
+   public:
+      int objects_starting_outside_left;
+      int objects_fully_outside_node;
+
+   private:
+      std::map<T, SplitCandidate<T> > splitCandidates;
+      std::vector< SplitCandidate<T> >    splitCandidatesVec;
+   };
+}
+
+#endif //KDSPLITCANDIDATEMANAGER_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdTree.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdTree.h
new file mode 100644
index 0000000000000000000000000000000000000000..83c33266cca0d38e5fbce8094bc2c30c07687f45
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdTree.h
@@ -0,0 +1,100 @@
+#ifndef KDTREE_H
+#define KDTREE_H
+
+#include <basics/memory/MbSmartPtr.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <basics/utilities/UbKeys.h>
+
+#include <numerics/geometry3d/KdTree/KdNode.h>
+#include <numerics/geometry3d/KdTree/KdRay.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+
+#include <string>
+
+namespace Kd
+{
+   template< typename T >
+   class Tree 
+   {
+   public:
+      /* ======================================================================================= */
+      Tree(GbTriFaceMesh3D& mesh, const SplitAlgorithm<T>& splitAlg) 
+         : rootNode(NULL)
+      {
+         this->buildTree(mesh, splitAlg);
+      }
+      /* ======================================================================================= */
+      ~Tree()
+      {
+         if(rootNode)  { delete rootNode; rootNode = NULL; }
+      }
+      /* ======================================================================================= */
+      // the IntersectionHandler specifies how to handle the intersection
+      bool intersectLine(const UbTuple< T, T, T >& n1, const UbTuple< T, T, T >& n2, const LineIntersectionHandler<T>& iHandler) 
+      {
+         return rootNode->intersectLine(n1, n2, iHandler);
+      }
+      /* ======================================================================================= */
+      // the IntersectionHandler specifies how to handle the intersection
+      int intersectRay(const Ray<T>& ray, const RayIntersectionHandler<T>& iHandler) 
+      {
+         std::set< UbKeys::Key3<int> > mailbox;
+         return rootNode->intersectRay(ray, iHandler, mailbox);
+      }
+      /* ======================================================================================= */
+      int getNumOfNodes() 
+      {                                               
+         if(rootNode) return rootNode->getNumOfNodes();
+         return 0;
+      }
+      /* ======================================================================================= */
+      int getNumOfTriFaces() 
+      {
+         if(rootNode) return rootNode->getNumOfTriFaces();
+         return 0;
+      }
+      /* ======================================================================================= */
+      std::string toString() 
+      {
+         return "";//Tree:: num of nodes: " + rootNode.getNumOfNodes() + ", primitives:" + rootNode.getNumOfPrimitives() + ", root_primitives:" + getNumOfPrimitives() + ", max_level:" + max_level;
+      }
+      /* ======================================================================================= */
+      void buildTree(GbTriFaceMesh3D& mesh, const SplitAlgorithm<T>& splitAlg ) 
+      {
+         if(rootNode) delete rootNode;
+          
+         // create a copy of triangles 
+         MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFaces(new std::vector<GbTriFaceMesh3D::TriFace>(*mesh.getTriangles() ) );
+         
+         int maxLevel = (int)(8.0 + 1.3 * std::log( (double)triFaces->size() ) + 0.5);
+
+         rootNode = new Node<T>(   T( mesh.getX1Minimum() )
+                                 , T( mesh.getX2Minimum() )
+                                 , T( mesh.getX3Minimum() )
+                                 , T( mesh.getX1Maximum() )
+                                 , T( mesh.getX2Maximum() )
+                                 , T( mesh.getX3Maximum() )
+                                 , triFaces, mesh.getNodes() );
+
+         rootNode->buildTree(0, maxLevel, splitAlg);
+      }
+      void writeTree(const std::string& filename, WbWriter* writer = WbWriterVtkXmlBinary::getInstance())
+      {
+         if(rootNode)
+         {
+            std::vector<UbTupleFloat3 >        nodes;
+            std::vector<UbTupleInt8 >          cubes;
+            std::vector<std::string >          datanames;
+            std::vector<std::vector<double > > cubesdata;
+            rootNode->addCubeInfo(nodes, cubes, datanames, cubesdata);
+            writer->writeOctsWithCellData(filename,nodes,cubes,datanames,cubesdata);
+         }
+      }
+   private:
+      Node<T>* rootNode;    
+   };
+}
+
+#endif //KDTREE_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdUtilities.cpp b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdUtilities.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..efbdd580caa25bb09f8278bec078da6b0c4fecfb
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdUtilities.cpp
@@ -0,0 +1,13 @@
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+
+namespace Kd
+{
+   const int Axis::X = 0;
+   const int Axis::Y = 1;
+   const int Axis::Z = 2;
+
+   const int Intersection::ON_BOUNDARY     = -2;
+   const int Intersection::INTERSECT_EDGE  = -1;
+   const int Intersection::INTERSECTION    =  1;
+const int Intersection::NO_INTERSECTION =  0;
+} //namespace Kd
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdUtilities.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdUtilities.h
new file mode 100644
index 0000000000000000000000000000000000000000..39a700cc4e216e6349f5d15ddc28c4b6f93c663e
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/KdUtilities.h
@@ -0,0 +1,164 @@
+#ifndef KDUTILIES_H
+#define KDUTILIES_H
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <algorithm>
+#include <vector>
+
+namespace Kd
+{
+   struct  Axis 
+   {
+      static const int X;// = 0;
+      static const int Y;// = 1;
+      static const int Z;// = 2;
+   };
+   /* ======================================================================================= */
+   struct Intersection 
+   {
+      static const int ON_BOUNDARY;    // = -2;
+      static const int INTERSECT_EDGE; // = -1;
+      static const int INTERSECTION;   // = 1;
+      static const int NO_INTERSECTION;// = 0;
+   };
+   /* ======================================================================================= */
+   template< typename T>
+   inline void project2Axis(GbTriFaceMesh3D::TriFace& triFace, std::vector<GbTriFaceMesh3D::Vertex>& nodes, const int& axis, std::vector<T>& projection) 
+   {
+      projection.resize(3);
+   
+      if(axis==Axis::X)
+      {
+         projection[0] = triFace.getV1x(nodes);
+         projection[1] = triFace.getV2x(nodes);
+         projection[2] = triFace.getV3x(nodes);
+      }
+      else if(axis==Axis::Y)
+      {
+         projection[0] = triFace.getV1y(nodes);
+         projection[1] = triFace.getV2y(nodes);
+         projection[2] = triFace.getV3y(nodes);
+      }
+      else if(axis==Axis::Z)
+      {
+         projection[0] = triFace.getV1z(nodes);
+         projection[1] = triFace.getV2z(nodes);
+         projection[2] = triFace.getV3z(nodes);
+      }
+      else throw UbException(UB_EXARGS,"unknown axis");
+      
+      std::sort( projection.begin(), projection.end(), std::less<double>() );
+   }
+   /* ======================================================================================= */
+   template< typename T>
+   inline bool isPointOnPlane(const T& px, const T& py, const T& pz, const T& precision, GbTriFaceMesh3D::Vertex& pointOfTriFace, GbTriFaceMesh3D::TriFace& triFace) 
+   {
+      return std::fabs( (px - pointOfTriFace.x) * triFace.nx + (py - pointOfTriFace.y) * triFace.ny + (pz - pointOfTriFace.z) * triFace.nz ) < precision;
+   }
+   /* ======================================================================================= */
+   template< typename T>
+   inline bool isPointOnTriangle( const T& px, const T& py, const T& pz, const T& precision
+                               , GbTriFaceMesh3D::Vertex& p1, GbTriFaceMesh3D::Vertex& p2, GbTriFaceMesh3D::Vertex& p3
+                               , GbTriFaceMesh3D::TriFace& triFace  ) 
+   {
+      if( Kd::isPointOnPlane(px, py, pz, precision, p1, triFace) ) 
+      {
+         T a_x = p1.x - px;
+         T a_y = p1.y - py;
+         T a_z = p1.z - pz;
+         T b_x = p2.x - px;
+         T b_y = p2.y - py;
+         T b_z = p2.z - pz;
+         T c_x = p3.x - px;
+         T c_y = p3.y - py;
+         T c_z = p3.z - pz;
+
+         const T factor = 0.5;
+         T Q1_x = (a_y * b_z - a_z * b_y) * factor;
+         T Q1_y = (a_z * b_x - a_x * b_z) * factor;
+         T Q1_z = (a_x * b_y - a_y * b_x) * factor;
+
+         T Q2_x = (b_y * c_z - b_z * c_y) * factor;
+         T Q2_y = (b_z * c_x - b_x * c_z) * factor;
+         T Q2_z = (b_x * c_y - b_y * c_x) * factor;
+
+         T Q3_x = (c_y * a_z - c_z * a_y) * factor;
+         T Q3_y = (c_z * a_x - c_x * a_z) * factor;
+         T Q3_z = (c_x * a_y - c_y * a_x) * factor;
+
+         T Q_x = Q1_x + Q2_x + Q3_x;
+         T Q_y = Q1_y + Q2_y + Q3_y;
+         T Q_z = Q1_z + Q2_z + Q3_z;
+
+
+         if     ( UbMath::zero(Q_x * Q1_x + Q_y * Q1_y + Q_z * Q1_z         ) ) return true;
+         else if( UbMath::zero(Q_x * Q2_x + Q_y * Q2_y + Q_z * Q2_z         ) ) return true;
+         else if( UbMath::zero(Q_x * Q3_x + Q_y * Q3_y + Q_z * Q3_z         ) ) return true;
+         else if( UbMath::less(Q_x * Q1_x + Q_y * Q1_y + Q_z * Q1_z, T(0.0) ) ) return false;
+         else if( UbMath::less(Q_x * Q2_x + Q_y * Q2_y + Q_z * Q2_z, T(0.0) ) ) return false;
+         else if( UbMath::less(Q_x * Q3_x + Q_y * Q3_y + Q_z * Q3_z, T(0.0) ) ) return false;
+
+         return true;
+      } 
+      
+      return false;
+   }
+   /* ======================================================================================= */
+   template< typename T>
+   inline bool intersectLine(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2, GbTriFaceMesh3D::TriFace& triFace, std::vector<GbTriFaceMesh3D::Vertex>& nodes) 
+   {
+      GbTriFaceMesh3D::Vertex& p0=triFace.getNode(0,nodes);
+      
+      const T& n1X = val<1>(n1);
+      const T& n1Y = val<2>(n1);
+      const T& n1Z = val<3>(n1);
+
+      const T& n2X = val<1>(n2);
+      const T& n2Y = val<2>(n2);
+      const T& n2Z = val<3>(n2);
+
+      //if(   Kd::isPointOnPlane(n1X, n1Y, n1Z, T(1.0E-6), p0, triFace) 
+      //   && Kd::isPointOnPlane(n2X, n2Y, n2Z, T(1.0E-6), p0, triFace)) 
+      //{
+      //   return true;
+      //}
+
+         T denom = ( n2X - n1X ) * triFace.nx + ( n2Y - n1Y ) * triFace.ny + ( n2Z - n1Z ) * triFace.nz;
+
+         if( UbMath::zero( denom ) )  //line does not intersect the plane of the triangle !
+         {
+         return false;
+         } 
+         else 
+         {
+            T d  = - triFace.nx * p0.x - triFace.ny * p0.y - triFace.nz * p0.z;
+            T mu = T(-1.0 * (d + n1X * triFace.nx + n1Y * triFace.ny + n1Z * triFace.nz ) / denom);
+
+            if( !UbMath::inClosedInterval( mu, T(0.0), T(1.0)) )  // Point of intersection of line and plane does not lie on the triangle
+            {
+            return false;
+            } 
+            else 
+            {
+               // intersection with plane
+ 
+               //Test whether Point lies inside the triangle or not
+            GbTriFaceMesh3D::Vertex& p1=triFace.getNode(1,nodes);
+            GbTriFaceMesh3D::Vertex& p2=triFace.getNode(2,nodes);
+               
+               return Kd::isPointOnTriangle(  n1X + ( (n2X - n1X) * mu )   //intersectionPointX
+                                            , n1Y + ( (n2Y - n1Y) * mu )   //intersectionPointY
+                                            , n1Z + ( (n2Z - n1Z) * mu )   //intersectionPointZ
+                                            , T(0.001)
+                                            , p0, p1, p2, triFace );
+            }
+         }
+      } 
+} //namespace Kd
+
+#endif //KDUTILIES_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/AdvancedPIOTests/CMakeLists.txt b/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/AdvancedPIOTests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1b2fd9ad9cd9a3ca227dce4499cb7d665289945a
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/AdvancedPIOTests/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(kdtree_pioTest)
+
+#################################################################
+# MACHINE_SPECIFIC CMAKE_CONFIG_FILE
+#################################################################
+INCLUDE("../../../../../CMake/CMakeCABMacros.txt")
+
+#################################################################
+###   PACKAGES                                               ###
+#################################################################
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/3rdParty/dirstream/CMakePackage.txt)
+
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/container/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/memory/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/objects/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/writer/CMakePackage.txt)
+
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/KdTree/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/fem/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/creator/CMakePackage.txt)
+
+#################################################################
+###   OWN DEFINES 						###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) 
+
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(z_main FILES ${SPECIFIC_FILES})
+
+#################################################################
+###  PROJECT ERSTELLEN                                        ###
+#################################################################
+CREATE_CAB_PROJECT(${PROJECT_NAME} BINARY)
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/AdvancedPIOTests/main.cpp b/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/AdvancedPIOTests/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0c0b9454745a3554ab32b7d81f6639749dd45545
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/AdvancedPIOTests/main.cpp
@@ -0,0 +1,542 @@
+#include <basics/utilities/UbTiming.h>
+#include <basics/utilities/UbRandom.h>
+#include <basics/utilities/UbTuple.h>
+
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/writer/WbWriterAvsBinary.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+
+#include <basics/container/CbUniformMatrix3D.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+
+#include <numerics/geometry3d/KdTree/KdTree.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h>
+
+#include <stack>
+#include <list>
+
+using namespace std;
+
+void createGrid(std::string meshfile, int maxNofPointsPerDir, Kd::SplitAlgorithm<float>& splitAlg, bool writeFiles = true, std::string outpath = "g:/temp");
+void recursiveGridFill(CbUniformMatrix3D<short>& grid, const short& xs, const short& ys, const short& zs, const short& type);
+void iterativeGridFill(CbUniformMatrix3D<short>& grid, const short& xs, const short& ys, const short& zs, const short& type);
+
+#include <3rdParty/dirstream/dirstream.h>
+#include <3rdParty/dirstream/filter_utils.h>  // enthält die Definiton der bool'schen Ops für Filter
+
+
+using namespace std;
+
+int main()
+{
+   try
+   {
+//       //////////////////////////////////////////////////////////////////////////
+//       //STL File auswaehlen
+//       //////////////////////////////////////////////////////////////////////////
+//       string pathname = "c:/temp";
+//       string stlPath = "c:/temp";
+//       dirstr::dirstream str(stlPath.c_str(), dirstr::op(dirstr::pattern_f("*.stl")) 
+//                            || dirstr::op(dirstr::pattern_f("*.ply"))  || dirstr::op(dirstr::pattern_f("*.inp"))
+//                            || dirstr::op(dirstr::pattern_f("*.mesh")));
+// 
+// //      UbLog::setReportingLevel(logDEBUG5);
+//       UbLog::setReportingLevel(logINFO);
+// 
+//       vector<string> filenames;
+//       for(string entry; str >> entry;)
+//       {
+//          GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(entry,"mesh");
+// 
+//          string fn = UbSystem::getFilenameFromString(entry);
+//          mesh->writeMeshPly(pathname+"/"+fn+".ply");
+// 
+//          delete mesh;
+//       }
+// 
+//       exit(0);
+
+      //createGrid("c:/temp/clumps.stl", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/50spheres.inp", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/Sphere5040.inp", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/cooling_2.inp", 400, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/NDR-Konzertsaal.inp", 100, Kd::SAHSplit<float>() , true, "g:/temp");
+      
+      //createGrid("c:/temp/Campus-Details-W3.inp", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/Boein707.mesh", 100, Kd::SAHSplit<float>() , true, "g:/temp");
+      
+      //createGrid("c:/temp/dolphin.mesh", 400, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/box.ply", 10, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/bodyRight.stl", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/flamingo.mesh", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      
+      //createGrid("c:/temp/torus.inp", 256, Kd::SAHSplit<float>() , true, "g:/temp");
+      createGrid("c:/temp/xzx_dragon.stl", 512, Kd::SAHSplit<float>() , true, "g:/temp");
+//       createGrid("c:/temp/bunny_ascii.ply", 256, Kd::SAHSplit<float>() , true, "g:/temp");
+//       createGrid("c:/temp/dragon_ascii.ply", 256, Kd::SAHSplit<float>() , true, "g:/temp");
+//       createGrid("c:/temp/budda_ascii.ply", 256, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGridWithLines("c:/temp/box.ply", 10, Kd::SAHSplit<float>() , true, "g:/temp");
+      
+//       createGrid("c:/temp/beatle.mesh",200, Kd::SAHSplit<float>(), true, "g:/temp");
+//       createGrid("c:/temp/atrium-30000tri.inp",200, Kd::SAHSplit<float>(), true, "g:/temp");
+//       createGrid("c:/temp/Buero.inp",200, Kd::SAHSplit<float>(), true, "g:/temp");
+//       createGrid("c:/temp/office_space.inp",200, Kd::SAHSplit<float>(), true, "g:/temp");
+
+      //createGrid("d:/meshes/50spheres.inp",200, Kd::SAHSplit<float>(), true, "d:/temp");
+
+      //createGrid("c:/temp/torus.inp",200, Kd::SAHSplit<float>(), true, "g:/temp");
+      //createGrid("c:/temp/bodyRight.stl", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+
+      //createGrid("c:/temp/jetta.stl", 200, GbTriFaceMesh3D::KDTREE_SPATIALSPLIT , true, "g:/temp");
+      //createGrid("c:/temp/jetta.stl", 200, Kd::SAHSplit<float>(), true, "g:/temp");
+      //createGrid("c:/temp/VW_body.ply", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/kugel.stl", 50, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/ship-2.mesh", 100, Kd::SAHSplit<float>() , true, "g:/temp/schiff2");                                                   
+   }
+   catch(const std::exception& e)
+   {
+      UBLOG2(  logERROR, std::cerr, "Caught exception:");
+      UBLOG2(  logERROR, std::cerr, "Type: " << typeid(e).name() );
+      UBLOG2ML(logERROR, std::cerr, "What: " << e.what() );
+   }
+   catch(...)
+   {
+      UBLOG2(logERROR, std::cerr, "unknown exception occurs in "<< UB_FUNCTION)
+   }
+}
+
+namespace Flag
+{
+   const short UNDEF = 2;
+   const short SOLID = 1;
+   const short FLUID = 0;
+}
+
+//////////////////////////////////////////////////////////////////////
+void createGrid(std::string meshfile, int maxNofPointsPerDir, Kd::SplitAlgorithm<float>& splitAlg, bool writeFiles, std::string outpath)
+{
+   UbLog::setReportingLevel(logDEBUG5);
+   std::string filename = UbSystem::getFilenameFromString(meshfile);
+
+   std::list< UbTuple<string, double> > timerVals;
+   UbTimer timer;
+   timer.start();
+   GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(meshfile,"mesh",GbTriFaceMesh3D::KDTREE_SAHPLIT);
+   timerVals.push_back( UbTuple<string, double>("mesh", timer.stop() ) );
+   UBLOG( logINFO, "read mesh in "<<val<2>(timerVals.back())<<"s" );
+   
+   timer.start();
+   Kd::Tree<float> kdTree( *mesh, splitAlg  );
+   timerVals.push_back( UbTuple<string, double>("kdTree", timer.stop() ) );
+   UBLOG( logINFO, "build tree in "<<val<2>(timerVals.back())<<"s" );
+
+   UBLOG(logINFO, "############################################################");
+   UBLOG(logINFO, "nodes of TriFaceMesh....... "<<mesh->getNodes()->size()      );
+   UBLOG(logINFO, "triFaces of TriFaceMesh.... "<<mesh->getTriangles()->size()  );
+   UBLOG(logINFO, "triFace copies in KdTree... "<<kdTree.getNumOfTriFaces()     );
+   UBLOG(logINFO, "nodes of kdNodes of KdTree. "<<kdTree.getNumOfNodes()        );
+   UBLOG(logINFO, "");
+
+   //////////////////////////////////////////////////////////////////////////
+   // Ausgangs 3-D_Feld erstellen
+   //////////////////////////////////////////////////////////////////////////
+   const float percentOverLap = 0.05f; //=5%
+   const float maxLength = (1.0f+percentOverLap)*(float)UbMath::max( mesh->getLengthX1(), mesh->getLengthX2(), mesh->getLengthX3() );
+   const float dx1 = maxLength/(maxNofPointsPerDir-1);
+   const float dx2 = dx1;
+   const float dx3 = dx1;
+
+   const int nx1 = 1 + int( std::ceil(mesh->getLengthX1()*(1.0f+percentOverLap)/dx1)+0.5 );
+   const int nx2 = 1 + int( std::ceil(mesh->getLengthX2()*(1.0f+percentOverLap)/dx2)+0.5 );
+   const int nx3 = 1 + int( std::ceil(mesh->getLengthX3()*(1.0f+percentOverLap)/dx3)+0.5 );
+
+   CbUniformMatrix3D<short> solids(nx1,nx2,nx3,Flag::UNDEF);
+
+   //////////////////////////////////////////////////////////////////////////
+   // Knoten typisieren
+   //////////////////////////////////////////////////////////////////////////
+   const float orgx1 = (float)( -0.5*percentOverLap*mesh->getLengthX1()+mesh->getX1Minimum() );
+   const float orgx2 = (float)( -0.5*percentOverLap*mesh->getLengthX2()+mesh->getX2Minimum() );
+   const float orgx3 = (float)( -0.5*percentOverLap*mesh->getLengthX3()+mesh->getX3Minimum() );
+
+   std::vector<GbTriFaceMesh3D::TriFace>& triFaces = *mesh->getTriangles();
+   std::vector<GbTriFaceMesh3D::Vertex>&  vertices = *mesh->getNodes();
+
+   float x1center = float( mesh->getX1Centroid() );
+   float x2center = float( mesh->getX2Centroid() );
+   float x3center = float( mesh->getX3Centroid() );
+
+   UBLOG( logINFO, "performing point-in-object(PIO)-tests");
+   long  counter1=0, counter2 = 0;
+   float x1w, x2w, x3w;
+   int   x1Min, x2Min, x3Min, x1Max, x2Max, x3Max;
+   float einflussBereichKnoten_sq = dx1*dx1+dx2*dx2+dx3*dx3;
+
+   timer.start();
+   for(size_t t=0; t<triFaces.size(); t++)   
+   {
+      GbTriFaceMesh3D::TriFace& triangle = triFaces[t];
+      GbTriFaceMesh3D::Vertex& v1 = vertices[triangle.v1];
+      GbTriFaceMesh3D::Vertex& v2 = vertices[triangle.v2];
+      GbTriFaceMesh3D::Vertex& v3 = vertices[triangle.v3];
+
+      //////////////////////////////////////////////////////////////////////////
+      // AABB riangle
+      //////////////////////////////////////////////////////////////////////////
+      x1Min = /*UbMath::integerRounding*/( std::floor( ( UbMath::min( v1.x, v2.x, v3.x ) - orgx1) / dx1 ) );
+      x2Min = /*UbMath::integerRounding*/( std::floor( ( UbMath::min( v1.y, v2.y, v3.y ) - orgx2) / dx2 ) );
+      x3Min = /*UbMath::integerRounding*/( std::floor( ( UbMath::min( v1.z, v2.z, v3.z ) - orgx3) / dx3 ) );
+
+      x1Max = /*UbMath::integerRounding*/( std::ceil(  ( UbMath::max( v1.x, v2.x, v3.x ) - orgx1) / dx1 ) );
+      x2Max = /*UbMath::integerRounding*/( std::ceil(  ( UbMath::max( v1.y, v2.y, v3.y ) - orgx2) / dx2 ) );
+      x3Max = /*UbMath::integerRounding*/( std::ceil(  ( UbMath::max( v1.z, v2.z, v3.z ) - orgx3) / dx3 ) );
+
+      GbHalfSpace3D halfSpace(  v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z );
+
+      for(int x3=x3Min; x3<=x3Max; x3++)
+      {
+         for(int x2=x2Min; x2<=x2Max; x2++)
+         {
+            for(int x1=x1Min; x1<=x1Max; x1++)
+            {
+               counter1++;
+               
+               short& solidVal = solids(x1,x2,x3);
+
+               if( solidVal != Flag::UNDEF )  //doppeltes Testen vermeiden
+               {
+                  continue;
+               }
+ 
+               counter2++;
+               
+               //Weltkoords
+               x1w = orgx1+x1*dx1;
+               x2w = orgx2+x2*dx2;
+               x3w = orgx3+x3*dx3;
+
+               float dist = (float)halfSpace.getDistance( x1w, x2w, x3w );
+               if( UbMath::greater( dist, 0.0f) )
+               {
+                  continue;
+               }
+               if( UbMath::greater(dist*dist, einflussBereichKnoten_sq))
+               {
+                  continue;
+               }
+               
+               //eigentlicher PIO-Test
+               bool testFailed = true;
+               for(int i=0; i<100; i++ )
+               {
+                  Kd::Ray<float> ray(  x1w, x2w, x3w  //, 1, 0 ,0 );
+                                     , ( x1w < x1center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                     , ( x2w < x2center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                     , ( x3w < x3center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) ) );
+
+                  int iSec = kdTree.intersectRay( ray, Kd::CountRayIntersectionHandler<float>() );
+                  
+                  if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+                  {
+                     if(iSec == Kd::Intersection::ON_BOUNDARY )
+                     {
+                        solidVal = Flag::SOLID;
+                     }
+                     else
+                     {
+                        solidVal = (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+                     }
+                     testFailed = false;
+                     break;
+                  }
+                  else
+                  {
+                     UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+                  }
+               }
+               if( testFailed ) throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+             }
+         }
+      }
+   }
+   timerVals.push_back( UbTuple<string, double>("PiO-Test", timer.stop() ) );
+   UBLOG( logINFO,counter2 <<" point-in-object(PIO)-tests done in "<<val<2>(timerVals.back())<<"s" );
+   UBLOG( logINFO,counter1-counter2 <<" point-in-object(PIO)-tests uebersprungen" );
+
+   //////////////////////////////////////////////////////////////////////////
+   // FLOOD FILL
+   //////////////////////////////////////////////////////////////////////////
+
+   if( false) //using just one seed point
+   {
+      //FUELL
+      bool foundSeedPoint         = false;
+      int  seedPointSearchCounter = 0;
+      int  seedX1 = Ub::inf;
+      int  seedX2 = Ub::inf;
+      int  seedX3 = Ub::inf;
+
+      timer.start();
+      for(size_t t=0; t<triFaces.size(); t++)   
+      {
+          GbTriFaceMesh3D::TriFace& triangle = triFaces[t];
+          
+          float& nx = triangle.nx;
+          float& ny = triangle.ny;
+          float& nz = triangle.nz;
+
+          float cx1 = triangle.getX1Centroid(vertices);
+          float cx2 = triangle.getX2Centroid(vertices);
+          float cx3 = triangle.getX3Centroid(vertices);
+
+          for(int k=0; k<5; k++) 
+          {
+             seedPointSearchCounter++;
+
+             cx1 -= nx * dx1;
+             cx2 -= ny * dx2;
+             cx3 -= nz * dx3;
+
+             int ix1 = UbMath::integerRounding( (cx1-orgx1)/dx1 );
+             int ix2 = UbMath::integerRounding( (cx2-orgx2)/dx2 );
+             int ix3 = UbMath::integerRounding( (cx3-orgx3)/dx3 );
+
+             if(   solids.indicesInRange(ix1,ix2,ix3)
+                && solids(ix1, ix2, ix3 ) == Flag::UNDEF )
+             {
+                x1w = orgx1+ix1*dx1;
+                x2w = orgx2+ix2*dx2;
+                x3w = orgx3+ix3*dx3;
+
+                Kd::Ray<float> ray(  x1w, x2w, x3w  //, 1, 0 ,0 );
+                                  , ( x1w < x1center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                  , ( x2w < x2center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                  , ( x3w < x3center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) ) );
+
+                int iSec = kdTree.intersectRay( ray, Kd::CountRayIntersectionHandler<float>() );
+
+                if( iSec>0 && (iSec&1) )
+                {
+                   seedX1 = ix1;
+                   seedX2 = ix2;
+                   seedX3 = ix3;
+                   foundSeedPoint = true;
+                   break;
+                }
+              }
+          }
+          if(foundSeedPoint) break;
+      }
+      if(!foundSeedPoint)
+         throw UbException(UB_EXARGS,"fuck no seed point found");
+      timerVals.push_back( UbTuple<string, double>("Seed found in", timer.stop() ) );
+      UBLOG( logINFO,"found seed Point in "<<val<2>(timerVals.back())<<"s with "<<seedPointSearchCounter << " tested points" );
+
+      cout<<nx1<<","<<nx2<<","<<nx3<<endl;
+      bool recursiveFloodFill = ( nx1*nx2*nx3 < 100*100*30 );
+      if(recursiveFloodFill)
+      {
+         timer.start();
+         recursiveGridFill(solids, seedX1, seedX2, seedX3, Flag::SOLID);
+         timerVals.push_back( UbTuple<string, double>("flood fill (r)", timer.stop() ) );
+         UBLOG( logINFO,"recursive flood fill in "<<val<2>(timerVals.back())<<"s with "<<seedPointSearchCounter << " tested points" );
+
+         CbUniformMatrix3D<short> solidsCpy(solids);
+         timer.start();
+         iterativeGridFill(solidsCpy, seedX1, seedX2, seedX3, Flag::SOLID);
+         timerVals.push_back( UbTuple<string, double>("flood fill (i)", timer.stop() ) );
+         UBLOG( logINFO,"iterative flood fill in "<<val<2>(timerVals.back())<<"s with "<<seedPointSearchCounter << " tested points" );
+      }
+      else
+      {
+         timer.start();
+         iterativeGridFill(solids, seedX1, seedX2, seedX3, Flag::SOLID);
+         timerVals.push_back( UbTuple<string, double>("flood fill (r)", timer.stop() ) );
+         UBLOG( logINFO,"recursive flood fill in "<<val<2>(timerVals.back())<<"s with "<<seedPointSearchCounter << " tested points" );
+      }
+      
+      UBLOG(logINFO, "############################################################");
+
+   }
+   else //verifying complete arry
+   {
+      bool recursiveFloodFill = ( nx1*nx2*nx3 < 100*100*30 );
+      int solidCounter  = 0;
+
+      timer.start();
+      for(int x3=0; x3<solids.getNX3(); x3++)
+         for(int x2=0; x2<solids.getNX2(); x2++)
+            for(int x1=0; x1<solids.getNX1(); x1++)
+            {
+               if( solids(x1  ,x2  ,x3 ) == Flag::UNDEF ) 
+               {
+                  x1w = orgx1+x1*dx1;
+                  x2w = orgx2+x2*dx2;
+                  x3w = orgx3+x3*dx3;
+
+                  int iSec = -1;
+                  do{
+                     Kd::Ray<float> ray(  x1w, x2w, x3w  //, 1, 0 ,0 );
+                                       , ( x1w < x1center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                       , ( x2w < x2center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                       , ( x3w < x3center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) ) );
+
+                     iSec = kdTree.intersectRay( ray, Kd::CountRayIntersectionHandler<float>() );
+                  }while(iSec<0);
+
+                  if( iSec&1 )
+                  {
+                     if(recursiveFloodFill) recursiveGridFill(solids,x1,x2,x3,Flag::SOLID);
+                     else                   iterativeGridFill(solids,x1,x2,x3,Flag::SOLID);
+                  }
+                  else
+                  {
+                     if(recursiveFloodFill) recursiveGridFill(solids,x1,x2,x3,Flag::FLUID);
+                     else                   iterativeGridFill(solids,x1,x2,x3,Flag::FLUID);
+                  }
+               }
+            }
+      if(recursiveFloodFill) timerVals.push_back( UbTuple<string, double>("flood fill (r)", timer.stop() ) );
+      else                   timerVals.push_back( UbTuple<string, double>("flood fill (i)", timer.stop() ) );
+      UBLOG( logINFO,"recursive flood fill in "<<val<2>(timerVals.back())<<"s " );
+   }
+
+   list< UbTuple< string, double > >::iterator iter;
+   for(iter = timerVals.begin(); iter!=timerVals.end(); ++iter)
+   {
+      UBLOG( logINFO, setw(16) << val<1>(*iter) << " in " << setw(8) << setprecision(8) << val<2>(*iter) << "s" );
+   }
+
+   int solidCounter  = 0;
+   for(int x3=0; x3<solids.getNX3(); x3++)
+      for(int x2=0; x2<solids.getNX2(); x2++)
+         for(int x1=0; x1<solids.getNX1(); x1++)
+         {
+            if( solids(x1  ,x2  ,x3 ) == Flag::SOLID ) 
+            {
+               solidCounter++;
+            }
+         }
+
+   UBLOG( logINFO, "SOLIDS = " <<solidCounter);
+   UBLOG( logINFO, "SOLIDS = " <<solidCounter);
+   UBLOG( logINFO, "SOLIDS = " <<solidCounter);
+   UBLOG( logINFO, "SOLIDS = " <<solidCounter);
+
+   /* ======================================================================================= */
+   if(writeFiles) 
+   {
+      UBLOG( logINFO, "writeFiles - start");
+      string subfiledir = outpath+"/"+filename+"_solid_node_files";
+      UbSystem::makeDirectory( subfiledir );
+
+      std::vector<UbTupleFloat3 > nodes;
+      std::vector<std::string > datanames(1,"data");
+      datanames[0] = "solid";
+
+      std::vector< std::string > outFilenames;
+
+      std::vector<std::vector<double > > nodedata( datanames.size() );
+
+      for(int x3=0; x3<solids.getNX3(); x3++)
+         for(int x2=0; x2<solids.getNX2(); x2++)
+            for(int x1=0; x1<solids.getNX1(); x1++)
+            {
+               if( solids(x1  ,x2  ,x3 ) == Flag::SOLID ) 
+               {
+                  nodes.push_back( makeUbTuple(  orgx1+x1*dx1, orgx2+x2*dx2, orgx3+x3*dx3 ) );
+                  nodedata[0].push_back( solids(x1  ,x2  ,x3 ) );
+               }          
+
+               if(    nodes.size() > 2000000  
+                   || ( x1==(solids.getNX1()-1) && x2==(solids.getNX2()-1) && x3==(solids.getNX3()-1) ) ) 
+               {
+                  outFilenames.push_back( WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(subfiledir+"/"+filename+"_solid_nodes_"+"_part"+UbSystem::toString(outFilenames.size()+1),nodes,datanames,nodedata) );
+                  nodes.clear();
+                  nodedata.clear();
+                  nodedata.resize( datanames.size() );
+               }
+            }
+   
+      WbWriterVtkXmlBinary::getInstance()->writeCollection(outpath+"/"+filename+"_solids_nodes",outFilenames,0,false);
+      
+      
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterVtkXmlBinary::getInstance());
+      kdTree.writeTree(outpath+"/"+filename+"_kdTree",WbWriterVtkXmlBinary::getInstance());
+
+      UBLOG( logINFO, "writeFiles - end")
+   }
+
+   delete mesh;
+}
+
+namespace Dirs
+{
+   const int X1[] = { 1, -1,  0,  0,  0,  0,  1, -1,  1, -1,  1, -1,  1, -1,  0,  0,  0,  0,  0 };
+   const int X2[] = { 0,  0,  1, -1,  0,  0,  1, -1, -1,  1,  0,  0,  0,  0,  1, -1,  1, -1,  0 };
+   const int X3[] = { 0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  1, -1, -1,  1,  1, -1, -1,  1,  0 };
+
+   const int START = 0;
+   const int END6  = 5;
+   const int END18 = 17;
+}
+/*==================================================================*/
+bool floodFillCheck(CbUniformMatrix3D<short>& grid, const short& x, const short& y, const short& z)
+{
+   return grid.indicesInRange( x, y, z ) && grid(x,y,z)==Flag::UNDEF;
+}
+int g_counter = 0;
+void recursiveGridFill(CbUniformMatrix3D<short>& grid, const short& xs, const short& ys, const short& zs, const short& type)
+{
+   // Algorithmus zum Füllen eines Polyeders, ausgehend vom Saatpunkt xs,ys,zs
+
+   //Saatknoten einfärben
+   short& val = grid(xs,ys,zs);
+   if( val==Flag::UNDEF )
+   {
+      val = type;
+   }
+   if(   floodFillCheck( grid, xs+1, ys  , zs   ) ) recursiveGridFill( grid, xs+1, ys  , zs  , type );
+   if(   floodFillCheck( grid, xs  , ys+1, zs   ) ) recursiveGridFill( grid, xs  , ys+1, zs  , type );
+   if(   floodFillCheck( grid, xs  , ys  , zs+1 ) ) recursiveGridFill( grid, xs  , ys  , zs+1, type );
+   if(   floodFillCheck( grid, xs-1, ys  , zs   ) ) recursiveGridFill( grid, xs-1, ys  , zs  , type );
+   if(   floodFillCheck( grid, xs  , ys-1, zs   ) ) recursiveGridFill( grid, xs  , ys-1, zs  , type );
+   if(   floodFillCheck( grid, xs  , ys  , zs-1 ) ) recursiveGridFill( grid, xs  , ys  , zs-1, type );
+}
+/*==================================================================*/
+void iterativeGridFill(CbUniformMatrix3D<short>& grid, const short& xs, const short& ys, const short& zs, const short& type)
+{
+   std::stack< UbTupleInt3 > stck;
+   stck.push( UbTupleInt3(xs,ys,zs) );
+
+   int x,y,z;
+
+   while( !stck.empty() )  
+   {
+      x = val<1>( stck.top() );
+      y = val<2>( stck.top() );
+      z = val<3>( stck.top() );
+      stck.pop();
+
+      short& flagType = grid( x, y, z );
+
+      if( flagType == Flag::UNDEF ) 
+      {     
+         flagType = type;
+
+         if ( grid.indicesInRange( x+1, y  , z   ) ) stck.push( UbTupleInt3( x+1, y  , z   ) );
+         if ( grid.indicesInRange( x  , y+1, z   ) ) stck.push( UbTupleInt3( x  , y+1, z   ) );
+         if ( grid.indicesInRange( x  , y  , z+1 ) ) stck.push( UbTupleInt3( x  , y  , z+1 ) );
+         if ( grid.indicesInRange( x-1, y  , z   ) ) stck.push( UbTupleInt3( x-1, y  , z   ) );
+         if ( grid.indicesInRange( x  , y-1, z   ) ) stck.push( UbTupleInt3( x  , y-1, z   ) );
+         if ( grid.indicesInRange( x  , y  , z-1 ) ) stck.push( UbTupleInt3( x  , y  , z-1 ) );
+      }
+   }
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/PIOTests/CMakeLists.txt b/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/PIOTests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..98a64d3548e709895dc9e1eb8bb0e6eaa378ce7c
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/PIOTests/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(kdtree_pioTest)
+
+#################################################################
+# MACHINE_SPECIFIC CMAKE_CONFIG_FILE
+#################################################################
+INCLUDE("../../../../../CMake/CMakeCABMacros.txt")
+
+#################################################################
+###   PACKAGES                                               ###
+#################################################################
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/container/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/memory/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/objects/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/writer/CMakePackage.txt)
+
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/KdTree/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/fem/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/creator/CMakePackage.txt)
+
+#################################################################
+###   OWN DEFINES 						###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) 
+
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(z_main FILES ${SPECIFIC_FILES})
+
+#################################################################
+###  PROJECT ERSTELLEN                                        ###
+#################################################################
+CREATE_CAB_PROJECT(${PROJECT_NAME} BINARY)
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/PIOTests/main.cpp b/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/PIOTests/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..265316c69c61c2c1265a4d4e6000a9f1397880cd
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/examples/PIOTests/main.cpp
@@ -0,0 +1,342 @@
+#include <basics/utilities/UbTiming.h>
+#include <basics/utilities/UbRandom.h>
+
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/writer/WbWriterAvsBinary.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+
+#include <basics/container/CbUniformMatrix4D.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+
+#include <numerics/geometry3d/KdTree/KdTree.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h>
+
+using namespace std;
+
+void KdTreeTest         (std::string meshfile, int maxNofPointsPerDir, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM pio, bool writeFiles = true, std::string outpath = "g:/temp");
+void KdTreeTestWithLines(std::string meshfile, int maxNofPointsPerDir, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM pio, bool writeFiles = true, std::string outpath = "g:/temp");
+
+int main()
+{
+   try
+   {
+      //KdTreeTest("c:/temp/clumps.stl", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/50spheres.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/Sphere5040.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/cooling_2.inp", 400, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/NDR-Konzertsaal.inp", 100, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      
+      //KdTreeTest("c:/temp/Campus-Details-W3.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/Boein707.mesh", 100, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      
+      //KdTreeTest("c:/temp/dolphin.mesh", 400, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/box.ply", 10, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/bodyRight.stl", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/flamingo.mesh", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      
+      //KdTreeTest("c:/temp/torus.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTestWithLines("c:/temp/box.ply", 10, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      
+      KdTreeTest("c:/temp/doppelwandbox.ply", 100, GbTriFaceMesh3D::KDTREE_SPATIALSPLIT, true, "g:/temp");
+      
+      //KdTreeTestWithLines("c:/temp/torus.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT, true, "g:/temp");
+
+      //KdTreeTestWithLines("c:/temp/bodyRight.stl", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+
+      //KdTreeTest("c:/temp/jetta.stl", 200, GbTriFaceMesh3D::KDTREE_SPATIALSPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/jetta.stl", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT, true, "g:/temp");
+      //KdTreeTest("c:/temp/VW_body.ply", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/kugel.stl", 50, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/ship-2.mesh", 100, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp/schiff2");                                                   
+   }
+   catch(const std::exception& e)
+   {
+      UBLOG2(  logERROR, std::cerr, "Caught exception:");
+      UBLOG2(  logERROR, std::cerr, "Type: " << typeid(e).name() );
+      UBLOG2ML(logERROR, std::cerr, "What: " << e.what() );
+   }
+   catch(...)
+   {
+      UBLOG2(logERROR, std::cerr, "unknown exception occurs in "<< UB_FUNCTION)
+   }
+
+
+
+  
+}
+
+//////////////////////////////////////////////////////////////////////
+void KdTreeTest(std::string meshfile, int maxNofPointsPerDir, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM pio, bool writeFiles, std::string outpath)
+{
+   UbLog::setReportingLevel(logDEBUG5);
+   std::string filename = UbSystem::getFilenameFromString(meshfile);
+
+   GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(meshfile,"mesh",pio);
+   mesh->scale(10000,10000,10000);
+   //dummy test, damit der baum erstellt wird
+   mesh->isPointInGbObject3D(0,0,0);
+
+   UBLOG(logINFO, "############################################################");
+   UBLOG(logINFO, "nodes of TriFaceMesh....... "<<mesh->getNodes()->size()              );
+   UBLOG(logINFO, "triFaces of TriFaceMesh.... "<<mesh->getTriangles()->size()          );
+   UBLOG(logINFO, "triFace copies in KdTree... "<<mesh->getKdTree()->getNumOfTriFaces() );
+   UBLOG(logINFO, "nodes of kdNodes of KdTree. "<<mesh->getKdTree()->getNumOfNodes()   );
+   UBLOG(logINFO, "");
+
+
+   const float percentOverLap = 0.05f; //=5%
+   const float maxLength = (1.0f+percentOverLap)*UbMath::max( mesh->getLengthX1(), mesh->getLengthX2(), mesh->getLengthX3() );
+   const float dx1 = maxLength/(maxNofPointsPerDir-1);
+   const float dx2 = dx1;
+   const float dx3 = dx1;
+
+   const int nx1 = 1 + int( std::ceil(mesh->getLengthX1()*(1.0f+percentOverLap)/dx1)+0.5 );
+   const int nx2 = 1 + int( std::ceil(mesh->getLengthX2()*(1.0f+percentOverLap)/dx2)+0.5 );
+   const int nx3 = 1 + int( std::ceil(mesh->getLengthX3()*(1.0f+percentOverLap)/dx3)+0.5 );
+
+   CbUniformMatrix4D<int> solids(nx1,nx2,nx3,1,0);
+
+   const float orgx1 = -0.5*percentOverLap*mesh->getLengthX1()+mesh->getX1Minimum();
+   const float orgx2 = -0.5*percentOverLap*mesh->getLengthX2()+mesh->getX2Minimum();
+   const float orgx3 = -0.5*percentOverLap*mesh->getLengthX3()+mesh->getX3Minimum();
+
+   const float outX1 = 2*mesh->getX1Maximum();
+   const float outX2 = 0;//2*mesh->getX2Maximum();
+   const float outX3 = 0;//2*mesh->getX3Maximum();
+
+   UBLOG( logINFO, "performing " << nx1*nx2*nx3  <<" point-in-object(PIO)-tests");
+   UbTimer ff;
+   ff.start();
+   for(int x3=0; x3<solids.getNX3(); x3++)
+      for(int x2=0; x2<solids.getNX2(); x2++)
+         for(int x1=0; x1<solids.getNX1(); x1++)
+         {
+            solids(x1,x2,x3,0) = mesh->isPointInGbObject3D(orgx1+x1*dx1, orgx2+x2*dx2, orgx3+x3*dx3);
+         }
+   UBLOG( logINFO, nx1*nx2*nx3 <<" point-in-object(PIO)-tests done in "<<ff.stop()<<"s" );
+   UBLOG(logINFO, "############################################################");
+
+
+   /* ======================================================================================= */
+   if(writeFiles) 
+   {
+      UBLOG( logINFO, "writeFiles - start");
+      string subfiledir = outpath+"/"+filename+"_solid_node_files";
+      UbSystem::makeDirectory( subfiledir );
+
+      std::vector<UbTupleFloat3 > nodes;
+      std::vector<std::string > datanames(solids.getNX4(),"data");
+      datanames[0] = "solid";
+      //datanames[1] = "solid";
+
+      std::vector< std::string > outFilenames;
+
+      std::vector<std::vector<double > > nodedata( datanames.size() );
+      for(int x3=0; x3<solids.getNX3(); x3++)
+         for(int x2=0; x2<solids.getNX2(); x2++)
+            for(int x1=0; x1<solids.getNX1(); x1++)
+            {
+               if( solids(x1  ,x2  ,x3  , 0)  ) 
+               {
+                  nodes.push_back( makeUbTuple(  orgx1+x1*dx1, orgx2+x2*dx2, orgx3+x3*dx3 ) );
+
+                  for(int i=0; i<solids.getNX4(); i++)
+                  {
+                     nodedata[i].push_back( solids(x1  ,x2  ,x3  ,i) );
+                  }
+               }          
+
+               if(    nodes.size() > 2000000  
+                   || ( x1==(solids.getNX1()-1) && x2==(solids.getNX2()-1) && x3==(solids.getNX3()-1) ) ) 
+               {
+                  outFilenames.push_back( WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(subfiledir+"/"+filename+"_solid_nodes_"+"_part"+UbSystem::toString(outFilenames.size()+1),nodes,datanames,nodedata) );
+                  nodes.clear();
+                  nodedata.clear();
+                  nodedata.resize( datanames.size() );
+               }
+            }
+            
+      WbWriterVtkXmlBinary::getInstance()->writeCollection(outpath+"/"+filename+"_solids_nodes",outFilenames,0,false);
+      
+      
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterVtkXmlBinary::getInstance(),true);
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterAvsASCII::getInstance(),true);
+      mesh->getKdTree()->writeTree(outpath+"/"+filename+"_kdTree",WbWriterVtkXmlBinary::getInstance());
+
+      UBLOG( logINFO, "writeFiles - end")
+   }
+}
+
+//////////////////////////////////////////////////////////////////////
+void KdTreeTestWithLines(std::string meshfile, int maxNofPointsPerDir, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM pio, bool writeFiles, std::string outpath)
+{
+   UbLog::setReportingLevel(logDEBUG5);
+   std::string filename = UbSystem::getFilenameFromString(meshfile);
+
+   GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(meshfile,"mesh",pio);
+
+   //dummy test, damit der baum erstellt wird
+   mesh->isPointInGbObject3D(0,0,0);
+
+   UBLOG(logINFO, "############################################################");
+   UBLOG(logINFO, "nodes of TriFaceMesh....... "<<mesh->getNodes()->size()              );
+   UBLOG(logINFO, "triFaces of TriFaceMesh.... "<<mesh->getTriangles()->size()          );
+   UBLOG(logINFO, "triFace copies in KdTree... "<<mesh->getKdTree()->getNumOfTriFaces() );
+   UBLOG(logINFO, "nodes of kdNodes of KdTree. "<<mesh->getKdTree()->getNumOfNodes()   );
+   UBLOG(logINFO, "");
+
+
+   const float percentOverLap = 0.05f; //=5%
+   const float maxLength = (1.0f+percentOverLap)*UbMath::max( mesh->getLengthX1(), mesh->getLengthX2(), mesh->getLengthX3() );
+   const float dx1 = maxLength/(maxNofPointsPerDir-1);
+   const float dx2 = dx1;
+   const float dx3 = dx1;
+
+   const int nx1 = 1 + /*UbMath::integerRounding*/( std::ceil(mesh->getLengthX1()*(1.0f+percentOverLap)/dx1) );
+   const int nx2 = 1 + /*UbMath::integerRounding*/( std::ceil(mesh->getLengthX2()*(1.0f+percentOverLap)/dx2) );
+   const int nx3 = 1 + /*UbMath::integerRounding*/( std::ceil(mesh->getLengthX3()*(1.0f+percentOverLap)/dx3) );
+
+   CbUniformMatrix4D<int> solids(nx1,nx2,nx3,2,0);
+
+   const float orgx1 = -0.5*percentOverLap*mesh->getLengthX1()+mesh->getX1Minimum();
+   const float orgx2 = -0.5*percentOverLap*mesh->getLengthX2()+mesh->getX2Minimum();
+   const float orgx3 = -0.5*percentOverLap*mesh->getLengthX3()+mesh->getX3Minimum();
+
+//    const float outX1 = 2*mesh->getX1Maximum();
+//    const float outX2 = 2*mesh->getX2Maximum();
+//    const float outX3 = 2*mesh->getX3Maximum();
+
+   
+   Kd::Tree<double>* kdTree = mesh->getKdTree();
+   
+   std::vector<GbTriFaceMesh3D::TriFace>& triFaces = *mesh->getTriangles();
+   std::vector<GbTriFaceMesh3D::Vertex>&  vertices = *mesh->getNodes();
+
+   float x1center = float( mesh->getX1Centroid() );
+   float x2center = float( mesh->getX2Centroid() );
+   float x3center = float( mesh->getX3Centroid() );
+
+   UBLOG( logINFO, "performing point-in-object(PIO)-tests");
+   UbTimer ff;
+   ff.start();
+   long counter1=0, counter2 = 0;
+   for(size_t t=0; t<triFaces.size(); t++)   
+   {
+      int x1Min = /*UbMath::integerRounding*/( std::floor( (triFaces[t].getMinX(vertices)-orgx1) / dx1 ) );
+      int x2Min = /*UbMath::integerRounding*/( std::floor( (triFaces[t].getMinY(vertices)-orgx2) / dx2 ) );
+      int x3Min = /*UbMath::integerRounding*/( std::floor( (triFaces[t].getMinZ(vertices)-orgx3) / dx3 ) );
+
+      int x1Max = /*UbMath::integerRounding*/( std::ceil(  (triFaces[t].getMaxX(vertices)-orgx1) / dx1 ) );
+      int x2Max = /*UbMath::integerRounding*/( std::ceil(  (triFaces[t].getMaxY(vertices)-orgx2) / dx2 ) );
+      int x3Max = /*UbMath::integerRounding*/( std::ceil(  (triFaces[t].getMaxZ(vertices)-orgx3) / dx3 ) );
+
+      for(int x3=x3Min; x3<=x3Max; x3++)
+         for(int x2=x2Min; x2<=x2Max; x2++)
+            for(int x1=x1Min; x1<=x1Max; x1++)
+            {
+               counter1++;
+               
+               if( !solids.indicesInRange(x1,x2,x3,0) 
+                  || solids(x1,x2,x3,1) == 1 )  //doppeltes Testeb vermeiden
+               {
+                  continue;
+               }
+
+               counter2++;
+               
+               double x1w = orgx1+x1*dx1;
+               double x2w = orgx2+x2*dx2;
+               double x3w = orgx3+x3*dx3;
+
+               //eigentlicher PIO-Test
+               bool testFailed = true;
+               for(int i=0; i<100; i++)
+               {
+                  UbTupleDouble3 n1(x1w, x2w, x3w);
+                  UbTupleDouble3 n2(  double( x1w < x1center ? mesh->getX1Minimum()-UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX1() : mesh->getX1Maximum()+UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX1() )
+                                    , double( x2w < x2center ? mesh->getX2Minimum()-UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX2() : mesh->getX2Maximum()+UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX2() )
+                                    , double( x3w < x3center ? mesh->getX3Minimum()-UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX3() : mesh->getX3Maximum()+UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX3() ) );
+
+                  int iSec = kdTree->intersectLine( n1, n2, Kd::CountLineIntersectionHandler<double>() );
+                  
+                  if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+                  {
+                     if(iSec == Kd::Intersection::ON_BOUNDARY )
+                     {
+                        solids(x1,x2,x3,0) = true;
+                     }
+                     else
+                     {
+                        solids(x1,x2,x3,0) = (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+                     }
+                     testFailed = false;
+                     break;
+                  }
+                  else
+                  {
+                     UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+                  }
+               }
+               if( testFailed ) throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+               solids(x1,x2,x3,1) = 1;
+             }
+   }
+   UBLOG( logINFO,counter2 <<" point-in-object(PIO)-tests done in "<<ff.stop()<<"s" );
+   UBLOG( logINFO,counter1-counter2 <<" point-in-object(PIO)-tests uebersprungen" );
+   UBLOG(logINFO, "############################################################");
+
+   /* ======================================================================================= */
+   if(writeFiles) 
+   {
+      UBLOG( logINFO, "writeFiles - start");
+      string subfiledir = outpath+"/"+filename+"_solid_node_files";
+      UbSystem::makeDirectory( subfiledir );
+
+      std::vector<UbTupleFloat3 > nodes;
+      std::vector<std::string > datanames(solids.getNX4(),"data");
+      datanames[0] = "solid";
+      //datanames[1] = "solid";
+
+      std::vector< std::string > outFilenames;
+
+      std::vector<std::vector<double > > nodedata( datanames.size() );
+      for(int x3=0; x3<solids.getNX3(); x3++)
+         for(int x2=0; x2<solids.getNX2(); x2++)
+            for(int x1=0; x1<solids.getNX1(); x1++)
+            {
+               if( solids(x1  ,x2  ,x3  , 0)  ) 
+               {
+                  nodes.push_back( makeUbTuple(  orgx1+x1*dx1, orgx2+x2*dx2, orgx3+x3*dx3 ) );
+
+                  for(int i=0; i<solids.getNX4(); i++)
+                  {
+                     nodedata[i].push_back( solids(x1  ,x2  ,x3  ,i) );
+                  }
+               }          
+
+               if(    nodes.size() > 2000000  
+                   || ( x1==(solids.getNX1()-1) && x2==(solids.getNX2()-1) && x3==(solids.getNX3()-1) ) ) 
+               {
+                  outFilenames.push_back( WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(subfiledir+"/"+filename+"_solid_nodes_"+"_part"+UbSystem::toString(outFilenames.size()+1),nodes,datanames,nodedata) );
+                  nodes.clear();
+                  nodedata.clear();
+                  nodedata.resize( datanames.size() );
+               }
+            }
+   
+      WbWriterVtkXmlBinary::getInstance()->writeCollection(outpath+"/"+filename+"_solids_nodes",outFilenames,0,false);
+      
+      
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterVtkXmlBinary::getInstance());
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterAvsASCII::getInstance());
+      mesh->getKdTree()->writeTree(outpath+"/"+filename+"_kdTree",WbWriterVtkXmlBinary::getInstance());
+
+      UBLOG( logINFO, "writeFiles - end")
+   }
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..eccfde3058e028c2239bcc81de1ebfe0f3306e99
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h
@@ -0,0 +1,56 @@
+#ifndef KDCOUNTLINEINTERSECTIONHANDLER_H
+#define KDCOUNTLINEINTERSECTIONHANDLER_H
+
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbKeys.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/KdTree/KdNode.h>
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdLineIntersectionHandler.h>
+
+#include <set>
+
+namespace Kd
+{
+   template< typename T >
+   class CountLineIntersectionHandler : public LineIntersectionHandler<T> 
+   {
+   public:
+      bool intersectLine(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2, Node<T>& parent, Node<T>*& child1, Node<T>*& child2) const
+      {
+         if( parent.intersectLineBoundingBox(n1, n2)  == Intersection::INTERSECTION)
+         {
+            if( parent.isLeaf() ) 
+            {
+               std::vector<GbTriFaceMesh3D::TriFace>& triFaces = *parent.getTriFaces();
+               std::vector<GbTriFaceMesh3D::Vertex>& nodes = parent.getNodes();
+
+         for( std::size_t i=0; i<triFaces.size(); i++ )
+         {
+            GbTriFaceMesh3D::TriFace& triFace = triFaces[i];
+
+                  if( Kd::intersectLine(n1, n2, triFace, nodes) ) return true;
+               }
+               return false;
+               }
+            else
+               {
+               if( child1 )
+               {
+                  if (child1->intersectLine(n1, n2, *this)) return true;
+               }
+               if( child2 ) 
+               {
+                  if (child2->intersectLine(n1, n2, *this)) return true;
+               }
+            }
+         }
+         return false;
+      }
+      /* ======================================================================================= */
+   };
+}
+
+#endif //KDCOUNTLINEINTERSECTIONHANDLER_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..b95fc676ad04008b43b0ddf6db785887f941e7e0
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h
@@ -0,0 +1,164 @@
+#ifndef KDCOUNTRAYINTERSECTIONHANDLER_H
+#define KDCOUNTRAYINTERSECTIONHANDLER_H
+
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbKeys.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/KdTree/KdNode.h>
+//#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdRayIntersectionHandler.h>
+
+#include <set>
+
+namespace Kd
+{
+   template< typename T >
+   class CountRayIntersectionHandler : public RayIntersectionHandler<T> 
+   {
+   public:
+      int intersectRay(const Ray<T>& ray, Node<T>& parent, Node<T>*& child1, Node<T>*& child2, std::set< UbKeys::Key3<int> >& mailbox) const
+      {
+         if( parent.intersectRayBoundingBox(ray)  == Intersection::INTERSECTION)
+         {
+            if( parent.isLeaf() ) 
+            {
+               return this->checkIntersectionWithTriFaces(ray, *parent.getTriFaces(), parent.getNodes(), mailbox);
+            } 
+            else
+            {
+               int sum = 0;
+               if( child1 )
+               {
+                  int erg = child1->intersectRay(ray, *this, mailbox);
+                  if(erg < 0)
+                  {
+                     return erg;
+                  }
+                  sum += erg;
+               }
+               if( child2 ) 
+               {
+                  int erg = child2->intersectRay(ray, *this, mailbox);
+                  if(erg < 0)
+                  {
+                     return erg;
+                  }
+                  sum += erg;
+               }
+               return sum;
+            }
+         } 
+         else 
+         {
+            return 0;
+         }
+      }
+      /* ======================================================================================= */
+
+   private:
+      int checkIntersectionWithTriFaces(const Ray<T>& ray, std::vector<GbTriFaceMesh3D::TriFace>& triFaces, std::vector<GbTriFaceMesh3D::Vertex>& nodes, std::set< UbKeys::Key3<int> >& mailbox) const
+      {
+         T e1x,e1y,e1z,e2x,e2y,e2z,px,py,pz,a,f,sx,sy,sz,u,qx,qy,qz,v,factor;
+
+         int counter = 0, iSec = 0;
+
+         for( std::size_t i=0; i<triFaces.size(); i++ )
+         {
+            GbTriFaceMesh3D::TriFace& triFace = triFaces[i];
+
+            if( mailbox.find( UbKeys::Key3<int>(triFace.getIndexVertex1(), triFace.getIndexVertex2(), triFace.getIndexVertex3() ) )==mailbox.end() ) 
+            {
+               mailbox.insert( UbKeys::Key3<int>(triFace.getIndexVertex1(), triFace.getIndexVertex2(), triFace.getIndexVertex3() ) ); //schon hier rein, ansonsten muss man es unten bei JEDEm continue und am ende des ifs machen
+
+               GbTriFaceMesh3D::Vertex& v1 = triFace.getNode(0, nodes);
+               GbTriFaceMesh3D::Vertex& v2 = triFace.getNode(1, nodes);
+               GbTriFaceMesh3D::Vertex& v3 = triFace.getNode(2, nodes);
+
+               //////////////////////////////////////////////////////////////////////////
+               //Raytracing - start(  Anm.: prüft NUR in Strahlrichtung
+               // Grundidee: Schnittpunkt in Baryzentrischen Koordinaten besimmten
+               // t(u,v,w) = w*v0 + u*v1 + v*v2 
+               // mit w = 1.0-u-v, da fuer alle Punkte (u,v,w) im Dreick gilt u+v+w = 1
+               // wenn u, v oder w == 0 -> Punkt liegt auf Kante
+               // wenn u, v oder w == 1 -> Punkt liegt auf Eckpunkt (-> die anderen Werte muessen 0 )
+               
+               //e1 = v1 - v0
+               e1x = v2.x-v1.x;
+               e1y = v2.y-v1.y;
+               e1z = v2.z-v1.z;
+
+               //e2 = v2 - v0
+               e2x = v3.x-v1.x;
+               e2y = v3.y-v1.y;
+               e2z = v3.z-v1.z;
+
+               //p = d x e2
+               px = ray.directionY*e2z - ray.directionZ*e2y;
+               py = ray.directionZ*e2x - ray.directionX*e2z;
+               pz = ray.directionX*e2y - ray.directionY*e2x;
+
+               //a = e1 dot p
+               a = e1x*px + e1y*py + e1z*pz;
+               //if( fabs(a)<1.E-10 ) continue;
+               if( fabs(a) < UbMath::Epsilon<T>::val() ) continue;
+               f = T(1.0/a);
+
+               //s = o - v0
+               sx = ray.originX - v1.x;
+               sy = ray.originY - v1.y;
+               sz = ray.originZ - v1.z;
+
+               //u = f * ( s dot p)
+               u = f * ( sx*px + sy*py + sz*pz );
+               
+               //u ist nur gueltig in [0;1] 
+               if( ( UbMath::less(   u, T(0.0) ) ) || ( UbMath::greater(u, T(1.0) ) ) ) 
+               {
+                  continue;
+               }
+
+               //q = s x e1
+               qx = sy*e1z - sz*e1y;
+               qy = sz*e1x - sx*e1z;
+               qz = sx*e1y - sy*e1x;
+
+               //v = f*(e2 dot q)
+               v = f * (ray.directionX*qx + ray.directionY*qy + ray.directionZ*qz);
+               
+               //v ist nur gueltig in [0;1] da aber v bereits gueltig ist -> u+v darf nicht > 1.0 sein ;-)
+               if(   ( UbMath::less(v, T(0.0) ) ) || ( UbMath::greater(u+v, T(1.0) ) ) ) 
+               {
+                  continue;
+               }
+
+               //t = f * (e2 dot q)
+               factor = f * (e2x*qx + e2y*qy + e2z*qz);
+               //Raytracing - end
+               //////////////////////////////////////////////////////////////////////////
+
+               if( UbMath::zero( factor ) ) 
+               {
+                  return Intersection::ON_BOUNDARY; //ray.Org liegt direkt auf einem dreieck --> boundary
+               }
+               if( factor < 0.0 )
+               {
+                  continue;  //Schnittpunkt liegt in entgegengesetzter Strahlrichtung
+               }
+
+               //edge tests
+               //wenn u, v oder w ==0 -> Punkt liegt auf Kante bzw. Eckpunkt
+               if( UbMath::zero(u)          )  return Intersection::INTERSECT_EDGE;
+               if( UbMath::zero(v)          )  return Intersection::INTERSECT_EDGE;
+               if( UbMath::zero(T(1.0)-u-v) )  return Intersection::INTERSECT_EDGE;
+
+               counter++;
+            }
+         }
+         return counter;
+      }
+   };
+}
+
+#endif //KDCOUNTRAYLINEINTERSECTIONHANDLER_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdLineIntersectionHandler.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdLineIntersectionHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..65f94876a94cffc6f6dd9615c4f77d7c73be9a02
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdLineIntersectionHandler.h
@@ -0,0 +1,30 @@
+#ifndef KDLINEINTERSECTIONHANDLER_H
+#define KDLINEINTERSECTIONHANDLER_H
+
+#include <basics/utilities/UbTuple.h>
+//#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <set>
+
+// #ifdef CAB_RCF
+// #  include <3rdParty/rcf/RcfSerializationIncludes.h>
+// #end
+namespace Kd
+{
+   template< typename T>
+   class Node;
+
+   template< typename T>
+   class LineIntersectionHandler 
+   {
+   public:
+      virtual bool intersectLine(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2, Node<T>& parent, Node<T>*& child1, Node<T>*& child2) const = 0;
+      virtual ~LineIntersectionHandler() {}
+   };
+}
+
+// #if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+//    SF_NO_CTOR(Kd::LineIntersectionHandler<float>);
+//    SF_NO_CTOR(Kd::LineIntersectionHandler<double>);
+// #endif //RCF_USE_SF_SERIALIZATI
+#endif //KDLINEINTERSECTIONHANDLER_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdRayIntersectionHandler.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdRayIntersectionHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..7578d9046a68fc2a2b310204379df37f2c758c84
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/intersectionhandler/KdRayIntersectionHandler.h
@@ -0,0 +1,20 @@
+#ifndef KDRAYINTERSECTIONHANDLER_H
+#define KDRAYINTERSECTIONHANDLER_H
+
+#include <basics/utilities/UbTuple.h>
+#include <numerics/geometry3d/KdTree/KdRay.h>
+
+#include <set>
+
+namespace Kd
+{
+   template< typename T>
+   class RayIntersectionHandler 
+   {
+   public:
+      virtual int intersectRay(const Ray<T>& ray, Node<T>& parent, Node<T>*& child1, Node<T>*& child2, std::set< UbKeys::Key3<int> >& mailbox) const = 0;
+      virtual ~RayIntersectionHandler() {}
+   };
+}
+
+#endif //KDRAYINTERSECTIONHANDLER_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.cpp b/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..da4ff27465d87a8a6fff032d8f84e427a278255d
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.cpp
@@ -0,0 +1,10 @@
+//#include <numerics/geometry3d/KdTree/SAHSplit.h>
+
+
+// namespace Kd
+// {
+//    const double SAHSplit::Ct = 3.0; //traversal cost
+//    const double SAHSplit::Ci = 4.0; //ray-patch-intersection-cost
+// }
+
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h
new file mode 100644
index 0000000000000000000000000000000000000000..52e73ea714969df05098d7fed82f826357beeca5
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h
@@ -0,0 +1,287 @@
+#ifndef KDSAHSPLIT_H
+#define KDSAHSPLIT_H
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbInfinity.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/KdTree/KdNode.h>
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidateManager.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+
+#include <vector>
+#include <cmath>
+
+namespace Kd
+{
+   template< typename T >
+   class SAHSplit : public SplitAlgorithm<T> 
+   {
+   public:
+      /* ======================================================================================= */
+      SplitCandidate<T> findBestSplitCandidate(const int& level, const int& maxLevel, Node<T>& node ) const
+      {
+         if( !node.getTriFaces() )  throw UbException(UB_EXARGS, "triFace NULL pointer");
+
+         if(   node.getTriFaces()->size() <= 1 //max triangles in node
+            || level >= maxLevel     )
+         {
+            return SplitCandidate<T>();
+         }
+
+         SplitCandidate<T> bestSplitCandidate;
+         T minCN = Ub::inf;
+
+         for(int splitAxis = 0; splitAxis < 3; splitAxis++) 
+         {
+            SplitCandidateManager<T> sc;
+            findPossibleSplitCandidates(splitAxis, node, sc);
+
+            // incremental sweep to find best split position
+            for( std::size_t i = 0; i < sc.size(); i++)
+            {
+               if (i == 0) 
+               {
+                  sc[i].nl = sc.objects_starting_outside_left + sc.objects_fully_outside_node;
+                  sc[i].nr = node.getTriFaces()->size() - sc[0].np - sc[0].ending;
+               } 
+               else 
+               {
+                  sc[i].nl = sc[i - 1].nl + sc[i - 1].starting + sc[i - 1].np;
+                  sc[i].nr = sc[i - 1].nr - sc[i    ].ending   - sc[i    ].np;
+               }
+
+               this->calcSAH(sc[i], node);
+
+               if (sc[i].Cn < minCN)
+               {
+                  minCN              = sc[i].Cn;
+                  bestSplitCandidate = sc[i];
+               }
+            }
+         }
+
+         // automatic termination criterion (SAH)
+         if ( bestSplitCandidate.isValid && bestSplitCandidate.Cn >= node.getTriFaces()->size() * Ci) 
+         {
+            return SplitCandidate<T>();
+         }
+
+         return bestSplitCandidate;
+      }
+      /* ======================================================================================= */
+      void distributeTriFaces(const SplitCandidate<T>& candidate, std::vector<GbTriFaceMesh3D::TriFace>& triFacesForChild1, std::vector<GbTriFaceMesh3D::TriFace>& triFacesForChild2, Node<T>& node) const
+      {  
+         if( !node.getTriFaces() )  throw UbException(UB_EXARGS, "null pointer at triface list");
+
+         std::vector<GbTriFaceMesh3D::TriFace>& srcTriFaces = *node.getTriFaces();
+         std::vector<GbTriFaceMesh3D::Vertex>&  srcNodes    = node.getNodes();
+         std::vector<T> projection;
+
+         for(std::size_t i=0; i<srcTriFaces.size(); i++) 
+         {
+            GbTriFaceMesh3D::TriFace& triFace = srcTriFaces[i];
+            Kd::project2Axis(triFace, srcNodes, candidate.axis, projection);
+
+            T& min = projection[0];
+            T& max = projection[2];
+            // --------------------------------------------------- //
+            // case 1 : object inside plane
+            if( UbMath::equal(min, max) )
+            {
+               if( UbMath::equal(min, candidate.position) ) 
+               {
+                  if(candidate.np_left)
+                  {
+                     triFacesForChild1.push_back(triFace);
+                  } 
+                  else if(candidate.np_right) 
+                  {
+                     triFacesForChild2.push_back(triFace);
+                  }
+               } 
+               else if( UbMath::less(min, candidate.position) )
+               {
+                  triFacesForChild1.push_back(triFace);
+               } 
+               else //if( UbMath::greater(min, candidate.position) 
+               {
+                  triFacesForChild2.push_back(triFace);
+               }
+            } //
+            // --------------------------------------------------- //
+            // case 2 : object on left side of plane
+            else if( UbMath::lessEqual(max,candidate.position) )
+            {
+               triFacesForChild1.push_back(triFace);
+            } // --------------------------------------------------- //
+            // case 3 : object on right side of plane
+            else if ( UbMath::greaterEqual( min, candidate.position) ) 
+            {
+               triFacesForChild2.push_back(triFace);
+            }//
+            // --------------------------------------------------- //
+            // case 4 : object in both nodes
+            else 
+            {
+               triFacesForChild1.push_back(triFace);
+               triFacesForChild2.push_back(triFace);
+            }//
+            // --------------------------------------------------- //
+         }
+
+         node.deleteTriFaces();
+      }
+
+
+   private:
+      /* ======================================================================================= */
+      // cost function
+      inline T calcCosts(const int& nl, const int& nr, const T& SA_VL, const T& SA_VR, const T& SA_V) const
+      {
+         return Ct + Ci * (nl * SA_VL / SA_V + nr * SA_VR / SA_V);
+      }
+      /* ======================================================================================= */
+      void findPossibleSplitCandidates(const int& splitAxis, Node<T>& node, SplitCandidateManager<T>& splitCandidateManager) const
+      {
+         T p1_node = (splitAxis == Axis::X ? node.x[0] : splitAxis == Axis::Y ? node.y[0] : node.z[0]);
+         T p2_node = (splitAxis == Axis::X ? node.x[1] : splitAxis == Axis::Y ? node.y[1] : node.z[1]);
+
+         if( !node.getTriFaces() )  throw UbException(UB_EXARGS, "null pointer");
+
+         std::vector<GbTriFaceMesh3D::TriFace>& srcTriFaces = *node.getTriFaces();
+         std::vector<GbTriFaceMesh3D::Vertex >& srcNodes    = node.getNodes();
+         std::vector<T> projection;
+
+         for(std::size_t i=0; i<srcTriFaces.size(); i++) 
+         {
+            GbTriFaceMesh3D::TriFace& triFace = srcTriFaces[i];
+
+            // project object to axis
+            Kd::project2Axis(triFace,srcNodes,splitAxis, projection);
+            // left point
+            T& p1 = projection[0];
+            // right point
+            T& p2 = projection[2];
+
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+            // case 1 : object is fully inside the current node
+            if(   UbMath::greaterEqual(p1, p1_node)   
+               && UbMath::lessEqual(p2, p2_node) )   
+            {
+               if( UbMath::equal(p1, p2) ) 
+               {
+                  // object is inside the plane
+                  splitCandidateManager.add(p1, splitAxis, 0, 0, 1);
+               } 
+               else 
+               {
+                  splitCandidateManager.add(p1, splitAxis, 1, 0, 0);
+                  splitCandidateManager.add(p2, splitAxis, 0, 1, 0);
+               }
+            } //
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+            // case 2 : just the right point (p2) is inside the current node
+            else if(    UbMath::less(p1, p1_node) 
+                     && UbMath::lessEqual(p2,p2_node)
+                     && UbMath::greaterEqual(p2, p1_node)   )
+            {
+               splitCandidateManager.add(p2, splitAxis, 0, 1, 0);
+               splitCandidateManager.objects_starting_outside_left++;
+            } //
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+            // case 3 : just the left point (p1) is inside the current node
+            else if(    UbMath::greaterEqual(p1, p1_node) 
+                     && UbMath::greater(p2, p2_node) 
+                     && UbMath::lessEqual(p1, p2_node)   ) 
+            {
+               splitCandidateManager.add(p1, splitAxis, 1, 0, 0);
+            } //
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+            // case 4 : left and right point are outside the current node
+            else if(   UbMath::less(p1, p1_node)
+                    && UbMath::greater(p2, p2_node) )
+            {
+               splitCandidateManager.objects_fully_outside_node++;
+            } //
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+         }
+
+         splitCandidateManager.createSortedArray();
+      }
+
+
+      /* ======================================================================================= */
+      // calculates the costs for a given splitCandidate based on the Surface Area Heuristic (SAH)
+      void calcSAH(SplitCandidate<T>& candidate, Node<T>& node) const 
+      {
+         T p1_node = (candidate.axis == Axis::X ? node.x[0] : candidate.axis == Axis::Y ? node.y[0] : node.z[0]);
+
+         // edges of (root) voxel
+         T dx = std::fabs(node.x[1] - node.x[0]);
+         T dy = std::fabs(node.y[1] - node.y[0]);
+         T dz = std::fabs(node.z[1] - node.z[0]);
+
+         // surface area (root) voxel
+         T SA_V = T((2.0 * dx * dy) + (2.0 * dx * dz) + (2.0 * dy * dz));
+
+         T delta = (candidate.axis == Axis::X ? dx : candidate.axis == Axis::Y ? dy : dz);
+         T deltaL = std::fabs(candidate.position - p1_node);
+         T deltaR = std::fabs(delta - deltaL);
+
+         // edges of sub voxel left
+         T dx_l = (candidate.axis == Axis::X ? deltaL : dx), dy_l = (candidate.axis == Axis::Y ? deltaL : dy), dz_l = (candidate.axis == Axis::Z ? deltaL : dz);
+
+         // surface area sub voxel left
+         T SA_VL = T( (2.0 * dx_l * dy_l) + (2.0 * dx_l * dz_l) + (2.0 * dy_l * dz_l) );
+
+         // edges of sub voxel right
+         T dx_r = (candidate.axis == Axis::X ? deltaR : dx), dy_r = (candidate.axis == Axis::Y ? deltaR : dy), dz_r = (candidate.axis == Axis::Z ? deltaR : dz);
+
+         // surface area sub voxel right
+         T SA_VR = T( (2.0 * dx_r * dy_r) + (2.0 * dx_r * dz_r) + (2.0 * dy_r * dz_r) );
+
+         if (candidate.np == 0) 
+         {
+            candidate.Cn = calcCosts(candidate.nl, candidate.nr, SA_VL, SA_VR, SA_V);
+            return;
+         }
+
+         // once putting np with nl, and once with nr - and select the one with lowest cost
+         // see: Wald, Havran: "On building fast kd-Trees for Ray Tracing, and doing that in O(N log N)", 2006
+         T CP_L = calcCosts(candidate.nl + candidate.np, candidate.nr               , SA_VL, SA_VR, SA_V);
+         T CP_R = calcCosts(candidate.nl               , candidate.nr + candidate.np, SA_VL, SA_VR, SA_V);
+         
+         if(CP_L < CP_R) 
+         {
+            candidate.Cn       = CP_L;
+            candidate.np_right = true;
+         } 
+         else 
+         {
+            candidate.Cn      = CP_R;
+            candidate.np_left = true;
+         }
+      }
+      /* ======================================================================================= */
+
+   protected:
+      static const T Ct;// = 3.0; traversal cost
+      static const T Ci;// = 4.0; ray-patch-intersection-cost
+   };
+
+   
+   template< typename T>
+   const T SAHSplit<T>::Ct = 3.0; //traversal cost
+   template< typename T>
+   const T SAHSplit<T>::Ci = 4.0; //ray-patch-intersection-cost
+}
+
+#endif //KDSAHSPLIT_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h
new file mode 100644
index 0000000000000000000000000000000000000000..b87c18b4817ab2c017cd76b66c220f5aa41ce90f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h
@@ -0,0 +1,90 @@
+#ifndef SPATIALLMEDIANSPLIT_H
+#define SPATIALLMEDIANSPLIT_H
+
+#include <basics/utilities/UbMath.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+
+namespace Kd
+{
+   template< typename T >
+   class SpatialMedianSplit : public SplitAlgorithm<T> 
+   {
+      /* ======================================================================================= */
+      SplitCandidate<T> findBestSplitCandidate(const int& level, const int& maxLevel, Node<T>& node )  const
+      {
+         if(   node.getTriFaces()->size() <= 24 //max triangles in node 
+            || level >= maxLevel        )
+         {
+            return SplitCandidate<T>();
+         }
+
+         T dx = std::fabs(node.x[1] - node.x[0]);
+         T dy = std::fabs(node.y[1] - node.y[0]);
+         T dz = std::fabs(node.z[1] - node.z[0]);
+
+         if     ( UbMath::equal(dx, UbMath::max(dx, dy, dz) ) ) return SplitCandidate<T>(Axis::X, node.x[0] + 0.5 * dx, 0, 0, 0);
+         else if( UbMath::equal(dy, UbMath::max(dy, dz    ) ) ) return SplitCandidate<T>(Axis::Y, node.y[0] + 0.5 * dy, 0, 0, 0);
+
+         return SplitCandidate<T>(Axis::Z, node.z[0] + 0.5 * dz, 0, 0, 0);
+
+      }
+      /* ======================================================================================= */
+      void distributeTriFaces(const SplitCandidate<T>& candidate, std::vector<GbTriFaceMesh3D::TriFace>& primitives_child1, std::vector<GbTriFaceMesh3D::TriFace>& primitives_child2, Node<T>& node) const
+      {
+         if( !node.getTriFaces() )  throw UbException(UB_EXARGS, "null pointer");
+
+         std::vector<GbTriFaceMesh3D::TriFace>& srcTriFaces = *node.getTriFaces();
+         std::vector<GbTriFaceMesh3D::Vertex>&  srcNodes    =  node.getNodes();
+         std::vector<T> projection;
+
+         for(std::size_t i=0; i<srcTriFaces.size(); i++) 
+         {
+            GbTriFaceMesh3D::TriFace& triFace = srcTriFaces[i];
+            Kd::project2Axis(triFace, srcNodes, candidate.axis, projection);
+
+            T& min = projection[0];
+            T& max = projection[2];
+         
+            // case 1 : object inside plane
+            if( UbMath::equal(min,max) )
+            {
+               if( UbMath::equal(min,candidate.position) ) 
+               {
+                  primitives_child1.push_back(triFace);
+                  primitives_child2.push_back(triFace);
+               }
+               else if( UbMath::less(min, candidate.position) )
+               {
+                  primitives_child1.push_back(triFace);
+               } 
+               else if( UbMath::greater(min, candidate.position) )
+               {
+                  primitives_child2.push_back(triFace);
+               }
+            } 
+            // case 2 : object on left side of plane
+            else if( UbMath::lessEqual(max, candidate.position) )
+            {
+               primitives_child1.push_back(triFace);
+            } 
+            // case 3 : object on right side of plane
+            else if( UbMath::greaterEqual(min, candidate.position) )
+            {
+               primitives_child2.push_back(triFace);
+            }
+            // case 4 : object in both nodes
+            else 
+            {
+               primitives_child1.push_back(triFace);
+               primitives_child2.push_back(triFace);
+            }
+         }
+
+         node.deleteTriFaces();
+      }
+   };
+}
+
+#endif //SPATIALLMEDIANSPLIT_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h b/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h
new file mode 100644
index 0000000000000000000000000000000000000000..16244300593b2de61738ade6f09cf8525504551f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h
@@ -0,0 +1,26 @@
+#ifndef KDSPLITALGORITHM_H
+#define KDSPLITALGORITHM_H
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+//#include <numerics/geometry3d/KdTree/Node.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+
+#include <vector>
+
+namespace Kd
+{
+   template< typename T >
+   class Node;
+
+   template< typename T >
+   class SplitAlgorithm 
+   {
+   public:
+      virtual SplitCandidate<T> findBestSplitCandidate(const int& level, const int& maxLevel, Node<T>& node ) const = 0;
+      virtual void distributeTriFaces(const SplitCandidate<T>& candidate, std::vector<GbTriFaceMesh3D::TriFace>& triFacesForChild1, std::vector<GbTriFaceMesh3D::TriFace>& triFacesForChild2, Node<T>& node) const=0;
+      virtual ~SplitAlgorithm() {}
+   };
+}
+
+
+#endif  //KDSPLITALGORITHM_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/CMakePackage.txt b/source/ThirdParty/Library/numerics/geometry3d/creator/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7fc2bbf84209dc05bd7aa85886b2250007c2a107
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/CMakePackage.txt
@@ -0,0 +1,12 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
+
+#SET(SUBDIRPATH numerics/geometry3d/creator) 
+#SET(OPTION_LABEL BUILD_GEOMETRY3DCREATOR)
+#
+#SET(CURRENT_DIR ${SOURCE_ROOT}/${SUBDIRPATH})
+#
+#OPTION(${OPTION_LABEL} "${CURRENT_DIR}" ON)
+#IF(${OPTION_LABEL})
+#   COLLECT_PACKAGE_DATA( ${CURRENT_DIR} ${SUBDIRPATH} ALL_SOURCES)
+#ENDIF(${OPTION_LABEL})
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbCuboid3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbCuboid3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b8478f8bdfaa680584e96e0f10b92a5b8726c3c
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbCuboid3DCreator.h
@@ -0,0 +1,77 @@
+#ifndef GBCUBOID3DCREATOR_H
+#define GBCUBOID3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbCuboid3D.h>     
+
+#ifdef CAB_QT 
+#include <numerics/geometry3d/presentation/QGbCuboid3DInstrument.h>
+#include <QtGui/QWidget>
+#include <QtGui/QDialog>
+#endif
+
+#ifdef CAB_VTK 
+#include <numerics/geometry3d/presentation/vtkGbCuboid3D.h>
+#endif
+
+class GbCuboid3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbCuboid3DCreator* getInstance()
+   {
+      static GbCuboid3DCreator instance;
+      return &instance;
+   }
+
+   GbCuboid3D* createGbObject3D() { return new GbCuboid3D(); }          
+
+   std::string getGbObject3DTypeID() { return "GbCuboid3D"; };
+   std::string toString()            { return "GbCuboid3DCreator"; }
+
+private:
+   GbCuboid3DCreator() : GbObject3DCreator() {}
+
+   GbCuboid3DCreator( const GbCuboid3DCreator& );                  //no copy allowed 
+   const GbCuboid3DCreator& operator=( const GbCuboid3DCreator& ); //no copy allowed
+
+#ifdef CAB_QT 
+public:
+   GbCuboid3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0)
+   {                                                              
+      GbCuboid3D* cuboid = this->createGbObject3D();
+      cuboid->getPoint2()->setX1(2.0);
+      cuboid->getPoint2()->setX2(2.0);
+      cuboid->getPoint2()->setX3(2.0);
+
+      QGbCuboid3DInstrument instrument(parent, flags);
+      instrument.setGbCuboid3D(cuboid);
+      if (instrument.exec()) { return cuboid; }
+      delete cuboid;
+
+      return NULL;
+   }
+
+   QDialog* getSpecificInstrument(QWidget* parent=0, Qt::WFlags flags=0) { return new QGbCuboid3DInstrument(parent, flags); }
+
+   void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      GbCuboid3D* cuboid = dynamic_cast<GbCuboid3D*>(gbObj);
+      if(!cuboid) throw UbException(UB_EXARGS,"selected object to edit is no GbCuboid3D!");
+
+      QGbCuboid3DInstrument instrument(parent, flags);
+      instrument.setGbCuboid3D(cuboid);
+      instrument.exec();
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbCuboid3D(dynamic_cast<GbCuboid3D*>(object)); }
+#endif
+
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbCuboid3DCreator::getInstance()), CAB_GbCuboid3DCreator);
+#endif
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbCylinder3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbCylinder3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca9614d7d50f5ba8f32f9a7cc134503a5d9cf49b
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbCylinder3DCreator.h
@@ -0,0 +1,81 @@
+#ifndef GBCYLINDER3DCREATOR_H
+#define GBCYLINDER3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbCylinder3D.h>
+
+#ifdef CAB_QT 
+#include <numerics/geometry3d/presentation/QGbCylinder3DInstrument.h>
+#include <QtGui/QWidget>
+#include <QtGui/QDialog>
+#endif
+
+#ifdef CAB_VTK
+#include <numerics/geometry3d/presentation/vtkGbCylinder3D.h>
+#endif
+
+
+class GbCylinder3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbCylinder3DCreator* getInstance()
+   {
+      static GbCylinder3DCreator instance;
+      return &instance;
+   }
+
+   GbCylinder3D* createGbObject3D() { return new GbCylinder3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "GbCylinder3D";        }
+   std::string toString()           { return "GbCylinder3DCreator"; }
+
+private:
+   GbCylinder3DCreator( const GbCylinder3DCreator& );                  //no copy allowed 
+   const GbCylinder3DCreator& operator=( const GbCylinder3DCreator& ); //no copy allowed
+GbCylinder3DCreator() : GbObject3DCreator() {}
+
+#ifdef CAB_QT
+public:
+
+   GbCylinder3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0)
+   {                                                              
+      GbCylinder3D* cylinder = this->createGbObject3D();
+      cylinder->setRadius(2.0);
+      cylinder->setPoint1(0.0, 0.0, 0.0);
+      cylinder->setPoint2(0.0, 5.0, 0.0);
+
+      QGbCylinder3DInstrument instrument(parent, flags);
+      instrument.setGbCylinder3D(cylinder);
+      if (instrument.exec()){ return cylinder; }
+      delete cylinder;
+
+      return NULL;
+   }
+
+   QDialog* getSpecificInstrument(QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      return new QGbCylinder3DInstrument(parent, flags);
+   }
+
+   void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      GbCylinder3D* cylinder = dynamic_cast<GbCylinder3D*>(gbObj);
+      if(!cylinder) throw UbException(UB_EXARGS,"selected object to edit is no GbCylinder3D!");
+
+      QGbCylinder3DInstrument instrument(parent, flags);
+      instrument.setGbCylinder3D(cylinder);
+      instrument.exec();
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbCylinder3D(dynamic_cast<GbCylinder3D*>(object)); }
+#endif
+
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbCylinder3DCreator::getInstance()), CAB_GbCylinder3DCreator);
+#endif
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbLine3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbLine3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..460613f8e3b65dbdad516a507501f7a035ccf13d
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbLine3DCreator.h
@@ -0,0 +1,31 @@
+#ifndef GBLINE3DCREATOR_H
+#define GBLINE3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbLine3D.h>
+
+class GbLine3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbLine3DCreator* getInstance()
+   {
+      static GbLine3DCreator instance;
+      return &instance;
+   }
+
+   GbLine3D* createGbObject3D() { return new GbLine3D(); }
+
+   std::string getGbObject3DTypeID(){ return "GbLine3D";        }
+   std::string toString()           { return "GbLine3DCreator"; }
+
+private:
+   GbLine3DCreator( const GbLine3DCreator& );                  //no copy allowed 
+   const GbLine3DCreator& operator=( const GbLine3DCreator& ); //no copy allowed
+   GbLine3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbLine3DCreator::getInstance()), CAB_GbLine3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1a8fd785fcc325ab78252f2034663d49df3c25c
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DCreator.h
@@ -0,0 +1,77 @@
+#ifndef GBOBJECT3DCREATOR_H
+#define GBOBJECT3DCREATOR_H
+
+#include <string>
+
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/utilities/UbAutoRun.hpp>
+
+#include <numerics/geometry3d/GbObject3D.h>
+
+#ifdef CAB_QT 
+#include <qdialog.h>
+#endif
+
+#ifdef CAB_VTK
+#include <userinterface/presentation/vtkPoElement3D.h>
+#endif
+
+#ifdef CAB_PARAVIEW 
+#include "vtkPVSource.h"
+#endif          
+
+class GbObject3DCreator : public ObObjectCreator                           
+{                                       
+protected:
+   GbObject3DCreator() {}
+private:
+   GbObject3DCreator( const GbObject3DCreator& );                  //no copy allowed !!!
+   const GbObject3DCreator& operator=( const GbObject3DCreator& ); //no copy allowed
+public:
+   virtual ~GbObject3DCreator(){}
+
+   virtual std::string getTypeID() { return getGbObject3DTypeID();}
+   virtual ObObject* createObObject()
+   {
+      return this->createGbObject3D();
+   }
+
+
+   virtual GbObject3D* createGbObject3D()=0;
+   virtual std::string getGbObject3DTypeID()=0;                       
+   virtual std::string toString() { return "GbObject3DCreator"; }     
+
+#ifdef CAB_QT 
+   virtual GbObject3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0) { throw UbException(UB_EXARGS,"Not implemented..."); }
+   virtual void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)  { throw UbException(UB_EXARGS,"Not implemented..."); }
+#endif
+   //die Teile von ObObjectCreator ...
+#ifdef CAB_QT 
+   void showSpecificInstrument(ObObject* object,QWidget* parent=0)
+   {
+      GbObject3D* geoObj = dynamic_cast<GbObject3D*>(object);
+      this->editGbObject3DwithQt(geoObj, parent);
+   }
+   virtual ObObject* createObObjectWithQt() { return this->createGbObject3DwithQt();}
+   virtual QObObjectSpecificInstrument* getSpecificInstrument() { throw UbException(UB_EXARGS,"not implemented"); }
+
+#endif
+#ifdef CAB_VTK 
+   virtual Presentator* createObjectPresentator(ObObject *object) { return NULL; }
+#endif
+
+
+#ifdef CAB_PARAVIEW 
+   virtual vtkPVSource* createPVSource(vtkPVWindow *Window) {  throw UbException(UB_EXARGS,"vtkPVSource* createPVSource"); }
+#endif
+
+
+};
+
+#include <numerics/geometry3d/creator/GbObject3DFactory.h>
+
+/*=========================================================================*/
+#endif
+
+
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DFactory.cpp b/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eacc1cc086e46e0e3599dd1a318698d7d5fa2332
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DFactory.cpp
@@ -0,0 +1,97 @@
+#include <numerics/geometry3d/creator/GbObject3DFactory.h>
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+//#include <numerics/geometry3d/creator/GbPoint3DCreator.h>
+// #include <numerics/geometry3d/creator/GbCuboid3DCreator.h>
+// #include <numerics/geometry3d/creator/GbSphere3DCreator.h>
+// #include <numerics/geometry3d/creator/GbCylinder3DCreator.h>
+// #include <numerics/geometry3d/creator/GbLine3DCreator.h>
+// #include <numerics/geometry3d/creator/GbPolygon3DCreator.h>
+// #include <numerics/geometry3d/creator/GbTriangle3DCreator.h>
+// #include <numerics/geometry3d/creator/GbTriangularMesh3DCreator.h>
+
+using namespace std;
+
+//GbObject3DFactory* GbObject3DFactory::instance = NULL;
+
+/*======================================================================*/
+GbObject3DFactory::GbObject3DFactory() 
+   : ObObjectFactory()
+{
+}
+/*======================================================================*/  
+GbObject3DFactory* GbObject3DFactory::getInstance()
+{
+   static GbObject3DFactory instance;
+   return &instance;
+}
+
+///*======================================================================*/
+//void GbObject3DFactory::addGbObject3DCreator(GbObject3DCreator* creator)
+//{
+//   //cout<<"Meth:"<<creator->toString()<<" Meth-ID:"<<creator->getGbObject3DTypeID()<<endl;
+//   creatorSet.insert(pair<string, GbObject3DCreator*>(creator->getGbObject3DTypeID(), creator));
+//}
+//
+//void GbObject3DFactory::deleteGbObject3DCreator(GbObject3DCreator* creator)
+//{
+//   throw UbException(UB_EXARGS,"GbObject3DFactory::deleteGbObject3DCreator not yet implemented");
+//   // this.creatorSet.delete(creator);
+//}
+
+/*======================================================================*/
+GbObject3D* GbObject3DFactory::createGbObject3D(UbFileInput *in) 
+{
+   string str = in->readString();
+   //cout<<"GbObject3DFactory::createGbObject3D:"<<str<<endl;
+
+   GbObject3D *gbObject3D = createEmptyGbObject3D(str);
+
+   if(!gbObject3D)
+      throw UbException(UB_EXARGS,"creator for type available");
+   
+   gbObject3D->read(in);
+
+   return gbObject3D;
+}
+/*======================================================================*/
+GbObject3D* GbObject3DFactory::createEmptyGbObject3D(string objectType)
+{
+   typedef std::map<string, ObObjectCreator*>::iterator CreatorIterator;
+   std::map<string, ObObjectCreator*>* creatorSet = this->getCreatorSet();
+   CreatorIterator creatorIterator = creatorSet->find(objectType);
+
+   if(creatorIterator == creatorSet->end()) 
+      throw UbException(UB_EXARGS,"factory has no creator for "+objectType);
+
+   GbObject3DCreator *creator = dynamic_cast<GbObject3DCreator*>(creatorIterator->second);
+
+   if(!creator) 
+      throw UbException(UB_EXARGS,"factory has no creator for "+objectType);
+
+   return creator->createGbObject3D();
+}
+/*======================================================================*/
+//GbObject3DCreator* GbObject3DFactory::getCreator(string objectType)
+//{
+//   CreatorIterator creatorIterator = creatorSet.find(objectType);
+//   if(creatorIterator == creatorSet.end()) throw UbException(UB_EXARGS,"factory has no creator for "+objectType);
+//   GbObject3DCreator *creator = creatorIterator->second;
+//   if(!creator) throw UbException(UB_EXARGS,"factory has no creator for "+objectType);
+//   return(creator);
+//}
+/*======================================================================*/
+string GbObject3DFactory::toString() 
+{
+   stringstream ss;
+   ss<<"GbObject2DFactory";
+   int a=1;
+   std::map<std::string, ObObjectCreator*>::iterator creatorIterator; 
+   std::map<std::string, ObObjectCreator*>* tmp = this->getCreatorSet();
+   for(creatorIterator=tmp->begin(); creatorIterator!=tmp->end(); creatorIterator++)
+   {
+      ss<<(a++)<<". ";
+      ss<<creatorIterator->second->getTypeID();
+      ss<<endl;
+   }
+   return(ss.str());
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DFactory.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..f01d1dd45f7c766a4703c3d22cf10747a394e53c
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbObject3DFactory.h
@@ -0,0 +1,43 @@
+#ifndef GBOBJECT3DFACTORY_H
+#define GBOBJECT3DFACTORY_H
+
+#include <string>
+#include <sstream>
+#include <map>
+
+#include <basics/objects/ObObjectFactory.h>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+
+class GbObject3D;
+class GbObject3DCreator;
+
+class GbObject3DFactory : public ObObjectFactory
+{
+private:
+   GbObject3DFactory();
+   GbObject3DFactory( const GbObject3DFactory& );                  //no copy allowed 
+   const GbObject3DFactory& operator=( const GbObject3DFactory& ); //no copy allowed
+public:
+   static GbObject3DFactory* getInstance();
+   
+   GbObject3D* createGbObject3D(UbFileInput* in);
+
+   //void addGbObject3DCreator(GbObject3DCreator* creator);
+   //void deleteGbObject3DCreator(GbObject3DCreator* creator);
+   //std::map<std::string, GbObject3DCreator*>* getCreatorSet() { return &creatorSet;   }
+
+   std::string toString();
+   GbObject3D* createEmptyGbObject3D(std::string objectType);
+   //GbObject3DCreator* getCreator(std::string objectTypeID);
+
+private:
+   
+   
+   //std::map<std::string, GbObject3DCreator*> creatorSet;
+   //typedef std::map<std::string, GbObject3DCreator*>::iterator CreatorIterator;
+};
+/*=========================================================================*/
+#endif
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbPoint3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbPoint3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..40bb5835c3d9899cd63d18447c953eaa7a85d0b2
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbPoint3DCreator.h
@@ -0,0 +1,31 @@
+#ifndef GBPOINT3DCREATOR_H
+#define GBPOINT3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+class GbPoint3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbPoint3DCreator* getInstance()
+   {
+      static GbPoint3DCreator instance;
+      return &instance;
+   }
+   
+   GbPoint3D* createGbObject3D() { return new GbPoint3D(); }
+   
+   std::string getGbObject3DTypeID() { return "GbPoint3D";        }
+   std::string toString()            { return "GbPoint3DCreator"; }
+
+private:
+   GbPoint3DCreator( const GbPoint3DCreator& );                  //no copy allowed 
+   const GbPoint3DCreator& operator=( const GbPoint3DCreator& ); //no copy allowed
+   GbPoint3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbPoint3DCreator::getInstance()), CAB_GbPoint3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbPolygon3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbPolygon3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..703397747d8caa917fd2af14b36059db9e79a9cc
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbPolygon3DCreator.h
@@ -0,0 +1,32 @@
+#ifndef GBPOLYGON3DCREATOR_H
+#define GBPOLYGON3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+class GbPolygon3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbPolygon3DCreator* getInstance()
+   {
+      static GbPolygon3DCreator instance;
+      return &instance;
+   }
+
+   GbPolygon3D* createGbObject3D() { return new GbPolygon3D(); }
+
+   std::string getGbObject3DTypeID() { return "GbPolygon3D";        }
+   std::string toString()            { return "GbPolygon3DCreator"; }
+
+private:
+   GbPolygon3DCreator( const GbPolygon3DCreator& );                  //no copy allowed 
+   const GbPolygon3DCreator& operator=( const GbPolygon3DCreator& ); //no copy allowed
+
+   GbPolygon3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbPolygon3DCreator::getInstance()), CAB_GbPolygon3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.cpp b/source/ThirdParty/Library/numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f0d818aa7263f0dbf5ddcdf33dc92fe067a23709
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.cpp
@@ -0,0 +1,66 @@
+#include <numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.h>
+#include <numerics/geometry3d/GbQuadFaceMesh3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+using namespace std;
+
+/***************************************************************************/
+GbObject3D* GbQuadFaceMesh3DCreator::createGbObject3D() 
+{ 
+   return new GbQuadFaceMesh3D(); 
+}
+/***************************************************************************/
+GbQuadFaceMesh3D* GbQuadFaceMesh3DCreator::createQuadMesh3D(int nodesX1, int nodesX2, float startX1, float startX2, double knotenabstandX1, double knotenabstandX2, float nullNiveau, string name)
+{
+   vector<GbQuadFaceMesh3D::Vertex> *vertices = new vector<GbQuadFaceMesh3D::Vertex>;
+   vector<GbQuadFaceMesh3D::QuadFace> *quads = new vector<GbQuadFaceMesh3D::QuadFace>;
+   for(int x1=0;x1<nodesX1;x1++)
+   {
+      for(int x2=0;x2<nodesX2;x2++)
+      {
+         vertices->push_back(GbQuadFaceMesh3D::Vertex((float)(x1*knotenabstandX1+startX1), (float)(x2*knotenabstandX2+startX2), nullNiveau));
+      }
+   }
+   for(int x1=0;x1<nodesX1-1;x1++)
+   {
+      for(int x2=0;x2<nodesX2-1;x2++)
+      {
+         int index = x1*nodesX2+x2;
+         quads->push_back(GbQuadFaceMesh3D::QuadFace(index, index+nodesX2, index+nodesX2+1, index+1));
+      }
+   }
+   
+   return (new GbQuadFaceMesh3D(name, vertices, quads));
+}
+
+/*============================================================*/
+
+#ifdef CAB_QT 
+
+GbQuadFaceMesh3D* GbQuadFaceMesh3DCreator::createGbObject3DwithQt()
+{
+   //QString s = QFileDialog::getOpenFileName(NULL,NULL,NULL,"open file dialog","Choose a STL file" );
+   //QString s = QFileDialog::getOpenFileName(NULL, "Choose a STL file", "/home", "*.stl");
+   //QFileDialog* fd = new QFileDialog( NULL );
+   //fd->setIconText(QString("Hallo"));
+   //fd->show();
+   //TODO: Open File Dialog einbauen.		
+   //UbFileInputASCII in( s.toAscii().data() );
+   //stringstream stream;
+   //stream <<"TriangularMesh3D ";//<<_objCount++;
+   //GbQuadFaceMesh3D *mesh = NULL;//GbQuadFaceMesh3DCreator::readMeshFromSTLFile(&in, stream.str() );
+   //return mesh;
+   return NULL;
+}
+//QDialog* getSpecificInstrument()  {  return 0;}
+void GbQuadFaceMesh3DCreator::editGbObject3DwithQt(GbObject3D* gbObj)
+{ 
+
+}
+#endif
+#ifdef CAB_VTK
+Presentator* GbQuadFaceMesh3DCreator::createObjectPresentator(ObObject *object) 
+{
+   return NULL;
+}
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..ac43dd4fe141e9b8b6c0150b8968d4ebf178377b
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.h
@@ -0,0 +1,52 @@
+#ifndef GBQUADFACEMESH3DCREATOR_H
+#define GBQUADFACEMESH3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+
+class GbQuadFaceMesh3D;
+
+#ifdef CAB_QT 
+
+#endif
+
+#ifdef CAB_VTK
+//#include <numerics/geometry3d/presentation/vtkGbQuadangularMesh3D.h>
+#endif
+
+class GbQuadFaceMesh3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbQuadFaceMesh3DCreator* getInstance()
+   {
+      static GbQuadFaceMesh3DCreator instance;
+      return &instance;
+   }
+   static GbQuadFaceMesh3D *createQuadMesh3D(int nodesX1, int nodesX2, float startX1, float startX2, double knotenabstandX1, double knotenabstandX2, float nullNiveau, std::string name);
+
+   GbObject3D* createGbObject3D();
+   
+   std::string getGbObject3DTypeID() { return "GbQuadFaceMesh3D";        }
+   std::string toString()            { return "GbQuadFaceMesh3DCreator"; }
+
+#ifdef CAB_QT 
+
+   GbQuadFaceMesh3D* createGbObject3DwithQt();
+   //QDialog* getSpecificInstrument()  {  return 0;}
+   void editGbObject3DwithQt(GbObject3D* gbObj);
+#endif
+#ifdef CAB_VTK
+   Presentator* createObjectPresentator(ObObject *object);
+#endif
+
+
+private:
+   GbQuadFaceMesh3DCreator( const GbQuadFaceMesh3DCreator& );                  //no copy allowed 
+   const GbQuadFaceMesh3DCreator& operator=( const GbQuadFaceMesh3DCreator& ); //no copy allowed
+   GbQuadFaceMesh3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbQuadFaceMesh3DCreator::getInstance()), CAB_GbQuadFaceMesh3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbSphere3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbSphere3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..81e70daf041d2c71fb090a0c2b0034552891ee4f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbSphere3DCreator.h
@@ -0,0 +1,126 @@
+#ifndef GBSPHERE3DCREATOR_H
+#define GBSPHERE3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbSphere3D.h>
+
+#ifdef CAB_QT 
+#include <numerics/geometry3d/presentation/QGbSphere3DInstrument.h>
+#include <QtGui/QWidget>
+#include <QtGui/QDialog>
+#endif
+
+#ifdef CAB_VTK
+#include <numerics/geometry3d/presentation/vtkGbSphere3D.h>
+#endif
+
+#ifdef CAB_PARAVIEW 
+#include "vtkSMSourceProxy.h"
+#include "vtkSMProperty.h"
+#include "vtkSMDoubleVectorProperty.h"
+#endif
+
+class GbSphere3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbSphere3DCreator* getInstance()
+   {
+      static GbSphere3DCreator instance;
+      return &instance;
+   }
+
+   GbSphere3D* createGbObject3D() { return new GbSphere3D(); }
+
+   std::string getGbObject3DTypeID() { return "GbSphere3D"; };
+   std::string toString()            { return "GbSphere3DCreator"; }
+
+private:
+   GbSphere3DCreator( const GbSphere3DCreator& );                  //no copy allowed 
+   const GbSphere3DCreator& operator=( const GbSphere3DCreator& ); //no copy allowed
+   GbSphere3DCreator() : GbObject3DCreator() {}
+
+#ifdef CAB_QT 
+public:
+
+   GbSphere3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      GbSphere3D* sphere = this->createGbObject3D();
+      sphere->setRadius(3.0);
+      sphere->setCenterX1Coordinate(6.0);
+
+      QGbSphere3DInstrument instrument(parent, flags);
+      instrument.setGbSphere3D(sphere);
+      if (instrument.exec()) { return sphere; }
+      delete sphere;
+      return NULL;
+   }
+   QDialog* getSpecificInstrument(QWidget* parent=0, Qt::WFlags flags=0) { return new QGbSphere3DInstrument(parent, flags); }
+
+   void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      GbSphere3D* sphere = dynamic_cast<GbSphere3D*>(gbObj);
+      if(!sphere) throw UbException(UB_EXARGS,"selected object to edit is no GbSphere3D");
+
+      QGbSphere3DInstrument instrument(parent, flags);
+      instrument.setGbSphere3D(sphere);
+      instrument.exec();
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbSphere3D(dynamic_cast<GbSphere3D*>(object)); }
+#endif
+  
+
+#ifdef CAB_PARAVIEW
+   vtkPVSource* createPVSource(vtkPVWindow *Window);
+#endif
+};
+
+#ifdef CAB_PARAVIEW                  
+vtkPVSource* GbSphere3DCreator::createPVSource(vtkPVWindow *Window)
+{
+   GbSphere3D *mysphere = this->createGbObject3D();
+   mysphere->setCenterX1Coordinate(2.0);
+   mysphere->setCenterX2Coordinate(1.0);
+   mysphere->setCenterX3Coordinate(3.0);
+   mysphere->setRadius(0.3);
+
+   vtkPVSource* pvs = Window->CreatePVSource("SphereSource");
+   pvs->CreateProperties();
+   if (pvs)
+   {
+      pvs->IsPermanentOn();
+      pvs->Accept(1, 1);
+      //pvs->SetTraceReferenceObject(this->GetWindow());
+      pvs->SetTraceReferenceObject(Window);
+   }
+   //vtkPVDisplayGUI *settingsGUI= pvs->GetPVOutput();
+
+   vtkSMSourceProxy* proxy = pvs->GetProxy();
+   vtkSMProperty *prop = proxy->GetProperty("Center");
+
+   vtkSMDoubleVectorProperty *doubleprop = vtkSMDoubleVectorProperty::SafeDownCast(proxy->GetProperty("Center"));
+   doubleprop->SetElement(0, mysphere->getX1Centroid());
+   doubleprop->SetElement(1, mysphere->getX2Centroid());
+   doubleprop->SetElement(2, mysphere->getX3Centroid());
+   pvs->SetLabel("Kugel");
+
+   doubleprop = vtkSMDoubleVectorProperty::SafeDownCast(proxy->GetProperty("Radius"));
+   doubleprop->SetElement(0, mysphere->getRadius());
+
+   pvs->GetPVWidget("Center")->ResetInternal();
+   pvs->GetPVWidget("Radius")->ResetInternal();
+
+   pvs->SetVisibility(TRUE);
+   pvs->AcceptCallback();
+   pvs->Update();
+   return pvs;
+}
+#endif
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbSphere3DCreator::getInstance()), CAB_GbSphere3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriFaceMesh3DCreator.cpp b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriFaceMesh3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8129dfeaf8f58d17d22220dc23c9b432995b7667
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriFaceMesh3DCreator.cpp
@@ -0,0 +1,355 @@
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/utilities/UbTiming.h>
+
+using namespace std;
+
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   if(meshName.empty())
+   {
+      size_t pos=filename.rfind("/");
+      if(pos!=string::npos) meshName = filename.substr(pos+1);
+      else                  meshName = filename;
+   }
+
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   string ext=stlfile.getFileExtension();
+
+   //in "kleinbuchstaben" umwandeln
+   transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int))tolower); //(int(*)(int)) ist irgendso ein fieser cast, weil tolower ne alte c-methode ist
+
+   //UBLOG(logINFO, "GbTriFaceMesh3DCreator::readMeshFromFile - read " <<filename );
+
+   if     ( !ext.compare("ply" ) ) return GbTriFaceMesh3DCreator::readMeshFromPLYFile(filename, meshName,splitAlg , removeRedundantNodes);
+   else if( !ext.compare("stl" ) ) return GbTriFaceMesh3DCreator::readMeshFromSTLFile(filename, meshName,splitAlg , removeRedundantNodes);
+   else if( !ext.compare("inp" ) ) return GbTriFaceMesh3DCreator::readMeshFromAVSFile(filename, meshName,splitAlg , removeRedundantNodes);
+   else if( !ext.compare("mesh") ) return GbTriFaceMesh3DCreator::readMeshFromMeshFile(filename, meshName,splitAlg , removeRedundantNodes);
+   //else if( !ext.compare("raw") ) return GbTriFaceMesh3DCreator::readMeshFromRAWFile(filename,splitAlg , meshName);
+   else throw UbException(UB_EXARGS,"fileformat "+ext);
+
+   return NULL;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromMeshFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII meshfile(filename);
+   if(!meshfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromMeshFile(&meshfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromMeshFile(UbFileInput* in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+
+   while( !in->eof() )
+   {
+      std::string line = in->readStringLine();
+      if( line.find("Vertices") !=std::string::npos )
+         break;
+   }
+   int numVertices = in->readInteger();
+
+   UBLOG(logDEBUG1,"Number of vertices "<<numVertices);
+
+   nodes->resize(numVertices);
+   
+   float x, y, z;
+   for (int i=0; i<numVertices; i++)
+   {
+      x = in->readFloat();
+      y = in->readFloat();
+      z = in->readFloat();
+      in->readLine();
+      (*nodes)[i] = GbTriFaceMesh3D::Vertex(x,y,z);
+   }
+   UBLOG(logDEBUG1," - read vertices (#"<<numVertices<<") done");
+
+   while( !in->eof() )
+   {
+      std::string line = in->readStringLine();
+      if( line.find("Triangles") !=std::string::npos )
+         break;
+   }
+   int numFaces = in->readInteger();
+   triangles->reserve(numFaces);
+   UBLOG(logDEBUG1,"Number of faces    "<<numFaces);
+
+   int j,k,l;
+   for(int i=0; i<numFaces; i++)
+   {
+      j = in->readInteger()-1;
+      k = in->readInteger()-1;
+      l = in->readInteger()-1;
+      in->readLine();
+
+      (*triangles).push_back(GbTriFaceMesh3D::TriFace(j,k,l));
+   }
+   UBLOG(logDEBUG1," - read faces (#"<<(int)triangles->size()<<", #nonTriangles="<<(int)triangles->size()-numFaces<<") done");
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes );
+
+   return mesh;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromPLYFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII plyfile(filename);
+   if(!plyfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromPLYFile(&plyfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromPLYFile(UbFileInput* in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   //cout<<"GbTriangularMesh3DFile.readMeshFromPLYFile !!! Dieses Format hat leider redundante Knoten ..."<<endl;
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   
+   float x, y, z;
+   string dummy;
+
+   int numVertices = in->readIntegerAfterString("element vertex");
+   int numFaces    = in->readIntegerAfterString("element face");
+   in->setPosAfterLineWithString("end_header");
+   
+   UBLOG(logDEBUG1,"Number of vertices "<<numVertices);
+   UBLOG(logDEBUG1,"Number of faces    "<<numFaces);
+   
+   nodes->resize(numVertices);
+   triangles->reserve(numFaces);
+
+   int onePercent = (int)UbMath::max(1,UbMath::integerRounding(numVertices*0.01));
+   for (int i=0; i<numVertices; i++)
+   {
+      if( i%onePercent==0 )
+         cout<<" - read vertices (#"<<numVertices<<") "<<UbMath::integerRounding(i/(double)numVertices*100.0)<<"% "<<"\r"<<flush;
+      x = in->readFloat();
+      y = in->readFloat();
+      z = in->readFloat();
+      in->readLine();
+      (*nodes)[i] = GbTriFaceMesh3D::Vertex(x,y,z);
+   }
+   UBLOG(logDEBUG1," - read vertices (#"<<numVertices<<") done");
+
+   int p,j,k,l,n;
+   onePercent = (int)UbMath::max(1,UbMath::integerRounding(numFaces*0.01));
+   for(int i=0; i<numFaces; i++)
+   {
+      if( i%onePercent==0 ) cout<<" - read faces (#"<<numFaces<<") "<<UbMath::integerRounding(i/(double)numFaces*100.0)<<"% "<<"\r"<<flush;
+      
+      p = in->readInteger();
+      if(p==3)  //Dreieck, alles andere wird stumpf ingnoriert
+      {
+         j = in->readInteger();
+         k = in->readInteger();
+         l = in->readInteger();
+
+         if(   !UbMath::inClosedInterval(j,0,numVertices-1) 
+            || !UbMath::inClosedInterval(k,0,numVertices-1) 
+            || !UbMath::inClosedInterval(l,0,numVertices-1) ) 
+         {         
+            throw UbException(UB_EXARGS,"dreiecksindex ist groesser als max Knotenindex oder kleiner 0");
+         }
+         triangles->push_back(GbTriFaceMesh3D::TriFace(j,k,l));
+      }
+      else if(p==4)  //Viereck --> wird zu zwei Dreiecken!
+      {
+         j = in->readInteger();
+         k = in->readInteger();
+         l = in->readInteger();
+         n = in->readInteger();
+         numFaces++;
+         i++;
+
+         if(   !UbMath::inClosedInterval(j,0,numVertices-1) 
+            || !UbMath::inClosedInterval(k,0,numVertices-1) 
+            || !UbMath::inClosedInterval(l,0,numVertices-1) 
+            || !UbMath::inClosedInterval(n,0,numVertices-1) 
+            ) 
+         {         
+            throw UbException(UB_EXARGS,"vierecksindex ist groesser als max Knotenindex oder kleiner 0");
+         }
+         triangles->push_back(GbTriFaceMesh3D::TriFace(j,k,l));
+         triangles->push_back(GbTriFaceMesh3D::TriFace(l,n,j));
+      }
+
+      in->readLine();
+
+   }
+   UBLOG(logDEBUG1," - read faces (#"<<(int)triangles->size()<<", #nonTriangles="<<(int)triangles->size()-numFaces<<") done");
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes);
+   
+   return mesh;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromSTLFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromSTLFile(&stlfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromSTLFile(UbFileInput *in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator::readMeshFromSTLFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   double x, y, z;
+   int nr=0;
+
+   in->readLine();
+   while(dummy!="endsolid")
+   {
+      in->readLine();
+      in->readLine();
+      dummy = in->readString();
+      if(dummy!="vertex") throw UbException(UB_EXARGS,"no vertex format");
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in->readLine();
+      in->readString();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in->readLine();
+      in->readString();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      triangles->push_back(GbTriFaceMesh3D::TriFace(nr,nr+1,nr+2));
+      in->readLine();
+      in->readLine();
+      in->readLine();
+      dummy = in->readString();
+      nr+=3;
+      //std::cout<<"read mesh "<< nr <<" \n";
+   }
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes);
+   
+   return mesh;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromAVSFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromAVSFile(&stlfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromAVSFile(UbFileInput *in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg , bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator.readMeshFromAVSFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   in->readLine();
+   int numberNodes = in->readInteger();
+   int numberTris  = in->readInteger();
+   in->readLine();
+
+   double x,y,z;
+   for(int u=0;u<numberNodes;u++)
+   {
+      in->readInteger();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      in->readLine();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+   }
+   int id1,id2,id3;
+   for(int u=0;u<numberTris;u++)
+   {
+      in->readInteger();
+      in->readInteger();
+      in->readString();
+      id1 = in->readInteger();
+      id2 = in->readInteger();
+      id3 = in->readInteger();
+      triangles->push_back(GbTriFaceMesh3D::TriFace(id1-1,id2-1,id3-1));
+   }
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes);
+   
+   return mesh;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(&stlfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(UbFileInput *in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator.readMeshFromVTKASCIIFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   
+   in->readString();
+   int numberNodes = in->readInteger();
+   in->readLine();
+
+   double x,y,z;
+   for(int u=0;u<numberNodes;u++)
+   {
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      //cout<<u<<" - x,y,z:"<<x<<","<<y<<","<<z<<endl;
+      //x=in->readDouble();
+      //y=in->readDouble();
+      //z=in->readDouble();
+      //nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      //x=in->readDouble();
+      //y=in->readDouble();
+      //z=in->readDouble();
+      //nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      //in->readLine();
+   }
+   in->readLine();
+   in->readString();
+   int numberTris  = in->readInteger();
+   in->readLine();
+   UBLOG(logDEBUG1,"numberTris:"<<numberTris);
+
+   int id1,id2,id3;
+   for(int u=0;u<numberTris;u++)
+   {
+      in->readInteger();
+      id1 = in->readInteger();
+      id2 = in->readInteger();
+      id3 = in->readInteger();
+      triangles->push_back(GbTriFaceMesh3D::TriFace(id1,id2,id3));
+      //cout<<u<<" - id1,id2,id3:"<<id1<<","<<id2<<","<<id3<<endl;
+   }
+   UBLOG(logDEBUG1,"Tris gelesen");
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes);
+   UBLOG(logDEBUG1,"mesh erzeugt (with remove redundant nodes = "<< boolalpha <<removeRedundantNodes<<")");
+
+
+   return mesh;
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..0fb144d8548b22c1e76999c22db0bc1a448a4ef6
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h
@@ -0,0 +1,84 @@
+#ifndef GBTRIFACEMESH3DCREATOR_H
+#define GBTRIFACEMESH3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+#ifdef CAB_QT 
+#include <qfiledialog.h>    
+#endif
+
+#ifdef CAB_VTK
+#include <numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h>
+#endif
+
+class GbTriFaceMesh3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbTriFaceMesh3DCreator* getInstance()
+   {
+      static GbTriFaceMesh3DCreator instance;
+      return &instance;
+   }
+   static GbTriFaceMesh3D* readMeshFromFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromMeshFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+   static GbTriFaceMesh3D* readMeshFromMeshFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromPLYFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+   static GbTriFaceMesh3D* readMeshFromPLYFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromSTLFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true); 
+   static GbTriFaceMesh3D* readMeshFromSTLFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromAVSFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true); 
+   static GbTriFaceMesh3D* readMeshFromAVSFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromVTKASCIIFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true); 
+   static GbTriFaceMesh3D* readMeshFromVTKASCIIFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   GbTriFaceMesh3D* createGbObject3D() { return new GbTriFaceMesh3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "GbTriFaceMesh3D"; };
+   std::string toString()           { return "GbTriFaceMesh3DCreator"; }
+
+#ifdef CAB_QT 
+
+
+   GbTriFaceMesh3D* createGbObject3DwithQt()
+   {
+	   //QString s = QFileDialog::getOpenFileName(NULL,NULL,NULL,"open file dialog","Choose a STL file" );
+	   QString s = QFileDialog::getOpenFileName(NULL, "Choose a STL file", "/home", "*.stl");
+      //QFileDialog* fd = new QFileDialog( NULL );
+      //fd->setIconText(QString("Hallo"));
+      //fd->show();
+      //TODO: Open File Dialog einbauen.		
+      UbFileInputASCII in( s.toAscii().data() );
+      stringstream stream;
+      stream <<"TriangularMesh3D ";//<<_objCount++;
+      GbTriFaceMesh3D *mesh = NULL;//GbTriFaceMesh3DCreator::readMeshFromSTLFile(&in, stream.str() );
+      return mesh;
+   }
+   //QDialog* getSpecificInstrument()  {  return 0;}
+   void editGbObject3DwithQt(GbObject3D* gbObj)
+   { 
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbTriangularMesh3D((GbTriangularMesh3D*)object); }
+#endif
+
+
+private:
+   GbTriFaceMesh3DCreator( const GbTriFaceMesh3DCreator& );                  //no copy allowed 
+   const GbTriFaceMesh3DCreator& operator=( const GbTriFaceMesh3DCreator& ); //no copy allowed
+   GbTriFaceMesh3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbTriFaceMesh3DCreator::getInstance()), CAB_GbTriFaceMesh3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangle3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangle3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c075d6a022824fbd59bc15f844b48bc80221f10
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangle3DCreator.h
@@ -0,0 +1,31 @@
+#ifndef GBTRIANGLE3DCREATOR_H
+#define GBTRIANGLE3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+class GbTriangle3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbTriangle3DCreator* getInstance()
+   {
+      static GbTriangle3DCreator instance;
+      return &instance;
+   }
+
+   GbTriangle3D* createGbObject3D() { return new GbTriangle3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "GbTriangle3D";        }
+   std::string toString()           { return "GbTriangle3DCreator"; }
+
+private:
+   GbTriangle3DCreator( const GbTriangle3DCreator& ); //no copy allowed 
+   const GbTriangle3DCreator& operator=( const GbTriangle3DCreator& ); //no copy allowed
+   GbTriangle3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbTriangle3DCreator::getInstance()), CAB_GbTriangle3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangularMesh3DCreator.cpp b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangularMesh3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bfb42296037a0b86bc374b083250e2889fa9e5ee
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangularMesh3DCreator.cpp
@@ -0,0 +1,258 @@
+#include <numerics/geometry3d/creator/GbTriangularMesh3DCreator.h>
+#include <algorithm>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+                                               
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromFile(string filename, string meshName)
+{
+   if(meshName.empty())
+   {
+      size_t pos=filename.rfind("/");
+      if(pos!=string::npos) meshName = filename.substr(pos+1);
+      else                  meshName = filename; 
+   }
+   
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   string ext=stlfile.getFileExtension();
+
+   //in "kleinbuchstaben" umwandeln
+   transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int))tolower);
+
+   if     ( !ext.compare("ply") ) return GbTriangularMesh3DCreator::readMeshFromPLYFile(filename, meshName);
+   else if( !ext.compare("stl") ) return GbTriangularMesh3DCreator::readMeshFromSTLFile(filename, meshName);
+   else if( !ext.compare("gts") ) return GbTriangularMesh3DCreator::readMeshFromGTSFile(filename, meshName);
+   else if( !ext.compare("raw") ) return GbTriangularMesh3DCreator::readMeshFromRAWFile(filename, meshName);
+   else throw UbException(UB_EXARGS,"unrecognized fileformat "+ext);
+
+   return NULL;
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromSTLFile(string filename, string meshName) 
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriangularMesh3DCreator::readMeshFromSTLFile(&stlfile,meshName);
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromSTLFile(UbFileInput* in, string meshName) 
+{
+   UBLOG(logINFO,"GbTriangularMesh3DFile.readMeshFromSTLFile !!! Dieses Format hat leider redundante Knoten ...");
+   vector<GbPoint3D*>     *nodes     = new vector<GbPoint3D*>;
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   nodes->resize(0, NULL);
+   triangles->resize(0, NULL);
+   double x, y, z;
+   //int nr=0;
+   string dummy;
+   GbPoint3D     *node1    = NULL;                      
+   GbPoint3D     *node2    = NULL;
+   GbPoint3D     *node3    = NULL;
+   GbTriangle3D *triangle = NULL;
+   in->readLine();
+   while(dummy!="endsolid")
+   {		
+      in->readLine();	
+      in->readLine();	
+      dummy = in->readString(); if(dummy!="vertex") throw UbException(UB_EXARGS,"no vertex format");
+      x=in->readDouble(); 
+      y=in->readDouble();           
+      z=in->readDouble(); 
+      node1 = new GbPoint3D(x,y,z); nodes->push_back(node1);
+      in->readLine();	
+      in->readString();	
+      x=in->readDouble();
+      y=in->readDouble(); 
+      z=in->readDouble();	
+      node2 = new GbPoint3D(x,y,z); nodes->push_back(node2);
+      in->readLine();	
+      in->readString();	
+      x=in->readDouble();
+      y=in->readDouble(); 
+      z=in->readDouble();	
+      node3 = new GbPoint3D(x,y,z); nodes->push_back(node3); 
+      triangle = new GbTriangle3D(node1, node2, node3); triangles->push_back(triangle);
+      in->readLine();
+      in->readLine();
+      in->readLine();
+      dummy = in->readString();		
+   }
+   return new GbTriangularMesh3D(meshName, nodes, triangles);
+}                                     
+/*======================================================================*/
+/**
+* Returns a triangular mesh created from the specified TICAD source ASCII stream (system.dat format).
+* @param in the input stream
+* @param meshName the name of the created mesh
+* @return a triangular mesh created from the specified TICAD source ASCII stream
+* @exception IOException if any error occurs in creating the triangular mesh
+*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromGTSFile(string inputfile, string meshName) 
+{
+   UbFileInputASCII gtlfile(inputfile);
+   if(!gtlfile) throw UbException(UB_EXARGS,"cannot open file "+inputfile);
+   return GbTriangularMesh3DCreator::readMeshFromGTSFile(&gtlfile,meshName);
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromGTSFile(UbFileInput *in, string meshName) 
+{
+   UBLOG(logINFO,"GbTriangularMesh3DFile.readMeshFromGTSFile !!! ");
+   vector<GbPoint3D*>     *nodes     = new vector<GbPoint3D*>;
+   vector<GbLine3D*>      *edges     = new vector<GbLine3D*>;
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   nodes->resize(0, NULL);
+   edges->resize(0, NULL);
+   triangles->resize(0, NULL);
+   double x, y, z;
+   int point1, point2, point3;
+   //int nr = 0;
+   //in->readLine();
+   int nodesize     = in->readInteger();
+   int edgesize     = in->readInteger();
+   int trianglesize = in->readInteger();
+   UBLOG(logINFO,"node-/edge-/trianglesize: "<<nodesize<<" / "<<edgesize<<" / "<<trianglesize);
+
+   for(int i=0; i<nodesize;i++)
+   {		
+      in->readLine();	
+      x=in->readDouble(); 
+      y=in->readDouble();  
+      z=in->readDouble(); 
+      nodes->push_back(new GbPoint3D(x,y,z));
+   }
+   for(int i=0; i<edgesize;i++)
+   {		
+      in->readLine();	
+      point1=in->readInteger()-1; 
+      point2=in->readInteger()-1; 
+      edges->push_back(new GbLine3D((*nodes)[point1],(*nodes)[point2]));
+   }
+   for(int i=0; i<trianglesize;i++)
+   {		
+      in->readLine();	
+      point1=in->readInteger();                
+      point2=in->readInteger(); 
+      point3=in->readInteger(); 
+      //triangles->push_back(new GbTriangle3D((*nodes)[point1-1],(*nodes)[point2-1],(*nodes)[point3-1]));
+      triangles->push_back(new GbTriangle3D((GbPoint3D*)(*edges)[point1-1]->getPoint1(),(GbPoint3D*)(*edges)[point2-1]->getPoint1(),(GbPoint3D*)(*edges)[point3-1]->getPoint1()));
+   }
+   return(new GbTriangularMesh3D(meshName, nodes, edges, triangles));
+}                                  
+/*======================================================================*/
+/**
+* Returns a triangular mesh created from the specified TICAD source ASCII stream (system.dat format).
+* @param in the input stream
+* @param meshName the name of the created mesh
+* @return a triangular mesh created from the specified TICAD source ASCII stream
+* @exception IOException if any error occurs in creating the triangular mesh
+*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromPLYFile(string inputfile, string meshName) 
+{
+   UbFileInputASCII plyfile(inputfile);
+   if(!plyfile) throw UbException(UB_EXARGS,"cannot open file "+inputfile);
+   return GbTriangularMesh3DCreator::readMeshFromPLYFile(&plyfile,meshName);
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromPLYFile(UbFileInput *in, string meshName) 
+{
+   //cout<<"GbTriangularMesh3DFile.readMeshFromPLYFile !!! Dieses Format hat leider redundante Knoten ..."<<endl;
+   vector<GbPoint3D*>     *nodes     = new vector<GbPoint3D*>;
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   nodes->resize(0, NULL);
+   triangles->resize(0, NULL);
+   double x, y, z;
+   int nr=0;
+   string dummy;
+   int numVertices, numFaces;
+   GbPoint3D     *node     = NULL;
+   GbPoint3D     *node1    = NULL;
+   GbPoint3D     *node2    = NULL;
+   GbPoint3D     *node3    = NULL;
+   GbTriangle3D *triangle = NULL;
+   in->readLine();
+   in->readLine();
+   in->readString(); in->readString(); numVertices = in->readInteger();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readString(); in->readString(); numFaces = in->readInteger(); in->readLine();
+   in->readLine();
+   in->readLine();
+   UBLOG(logINFO,"Number of vertices "<<numVertices);
+   UBLOG(logINFO,"Number of faces    "<<numFaces);
+   for (int i=0; i<numVertices; i++)
+   {
+      x = in->readDouble();
+      y = in->readDouble();
+      z = in->readDouble();
+      //       cout<<x<<y<<z;
+      //       in->readString(); in->readString(); in->readString();
+      in->readLine();
+      node = new GbPoint3D(x,y,z); nodes->push_back(node); 
+   }
+   nr=0;
+
+   for (int i=0; i<numFaces; i++)
+   {
+      in->readString();
+      int j,k,l;
+      j = in->readInteger(); k = in->readInteger(); l = in->readInteger();
+      node1 = (*nodes)[j];
+      node2 = (*nodes)[k];
+      node3 = (*nodes)[l];
+      in->readLine();
+      nr++;
+      triangle = new GbTriangle3D(node1, node2, node3); triangles->push_back(triangle); 
+   }
+
+   return(new GbTriangularMesh3D(meshName, nodes, triangles));
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromRAWFile(string inputfile, string meshName) 
+{
+   UbFileInputASCII stlfile(inputfile);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+inputfile);
+   return GbTriangularMesh3DCreator::readMeshFromRAWFile(&stlfile,meshName);
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromRAWFile(UbFileInput *in, string meshName) 
+{
+   UBLOG(logINFO,"GbTriangularMesh3DFile.readMeshFromGTSFile !!! ");
+   vector<GbPoint3D*>     *nodes     = new vector<GbPoint3D*>;
+   vector<GbLine3D*>      *edges     = new vector<GbLine3D*>;
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   nodes->resize(0, NULL);
+   edges->resize(0, NULL);
+   triangles->resize(0, NULL);
+   double x, y, z;
+   int point1, point2, point3;
+   //int nr = 0;
+   //in->readLine();
+   int nodesize     = in->readInteger();
+   int trianglesize = in->readInteger();
+   int edgesize = 0;
+   UBLOG(logINFO,"node-/edge-/trianglesize "<<nodesize<<" / "<<edgesize<<" / "<<trianglesize);
+
+   for(int i=0; i<nodesize;i++)
+   {		
+      in->readLine();	
+      x=in->readDouble(); 
+      y=in->readDouble();  
+      z=in->readDouble(); 
+      nodes->push_back(new GbPoint3D(x,y,z));
+   }
+   for(int i=0; i<trianglesize;i++)
+   {		
+      in->readLine();	
+      point1=in->readInteger();                
+      point2=in->readInteger(); 
+      point3=in->readInteger(); 
+      triangles->push_back(new GbTriangle3D((*nodes)[point1],(*nodes)[point2],(*nodes)[point3]));
+   }
+   return(new GbTriangularMesh3D(meshName, nodes, edges, triangles));
+}                                  
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangularMesh3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangularMesh3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..d090115e321256764dae67df8afcad2e07df2a7e
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbTriangularMesh3DCreator.h
@@ -0,0 +1,83 @@
+#ifndef GBTRIANGULARMESH3DCREATOR_H
+#define GBTRIANGULARMESH3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbTriangularMesh3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+#ifdef CAB_QT 
+#include <qfiledialog.h>    
+#endif
+
+#ifdef CAB_VTK
+#include <numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h>
+#endif
+
+class GbTriangularMesh3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbTriangularMesh3DCreator* getInstance()
+   {
+      static GbTriangularMesh3DCreator instance;
+      return &instance;
+   }
+   
+   static GbTriangularMesh3D* readMeshFromFile(std::string filename, std::string meshName="");
+
+   static GbTriangularMesh3D* readMeshFromSTLFile(std::string filename, std::string meshName);
+   static GbTriangularMesh3D* readMeshFromGTSFile(std::string filename, std::string meshName);     
+   static GbTriangularMesh3D* readMeshFromPLYFile(std::string filename, std::string meshName);
+   //static GbTriangularMesh3D* readMeshFromAVSFile(std::string filename, std::string meshName);
+   static GbTriangularMesh3D* readMeshFromRAWFile(std::string inputFile, std::string meshName);
+
+   static GbTriangularMesh3D* readMeshFromSTLFile(UbFileInput* infile, std::string meshName);
+   static GbTriangularMesh3D* readMeshFromGTSFile(UbFileInput* infile, std::string meshName);     
+   static GbTriangularMesh3D* readMeshFromPLYFile(UbFileInput* infile, std::string meshName);
+   //static GbTriangularMesh3D* readMeshFromAVSFile(UbFileInput* infile, std::string meshName);
+   static GbTriangularMesh3D* readMeshFromRAWFile(UbFileInput* infile, std::string meshName);
+	
+   
+	GbTriangularMesh3D* createGbObject3D() { return new GbTriangularMesh3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "GbTriangularMesh3D"; };
+   std::string toString()           { return "GbTriangularMesh3DCreator"; }
+
+#ifdef CAB_QT 
+
+   GbTriangularMesh3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0)
+   {
+	   //QString s = QFileDialog::getOpenFileName(NULL,NULL,NULL,"open file dialog","Choose a STL file" );
+	   QString s = QFileDialog::getOpenFileName(NULL, "Choose a STL file", "/home", "*.stl");
+      //QFileDialog* fd = new QFileDialog( NULL );
+      //fd->setIconText(QString("Hallo"));
+      //fd->show();
+      //TODO: Open File Dialog einbauen.		
+      UbFileInputASCII in( s.toAscii().data() );
+      stringstream stream;
+      stream <<"TriangularMesh3D ";//<<_objCount++;
+      GbTriangularMesh3D *mesh = GbTriangularMesh3DCreator::readMeshFromSTLFile(&in, stream.str() );
+      mesh->deleteRedundantNodes();
+      return mesh;
+   }
+   //QDialog* getSpecificInstrument()  {  return 0;}
+   void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbTriangularMesh3D((GbTriangularMesh3D*)object); }
+#endif
+
+
+private:
+   GbTriangularMesh3DCreator( const GbTriangularMesh3DCreator& );                  //no copy allowed 
+   const GbTriangularMesh3DCreator& operator=( const GbTriangularMesh3DCreator& ); //no copy allowed
+   GbTriangularMesh3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbTriangularMesh3DCreator::getInstance()), CAB_GbTriangularMesh3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbVoxelMatrix3DCreator.cpp b/source/ThirdParty/Library/numerics/geometry3d/creator/GbVoxelMatrix3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..52b09e9aeca68ec4f46e49edff4301782a690456
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbVoxelMatrix3DCreator.cpp
@@ -0,0 +1,84 @@
+#include <numerics/geometry3d/creator/GbVoxelMatrix3DCreator.h>
+#include <numerics/geometry3d/GbVoxelMatrix3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+
+/***************************************************************************/
+GbVoxelMatrix3D* GbVoxelMatrix3DCreator::createFromRawFloatFile(  string filename, int nodesX1, int nodesX2, int nodesX3, float threshold)
+{
+   UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromRawFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+   ifstream in(filename.c_str(), ios::binary);
+   if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+   
+   in.seekg( 0, ios::end );     //Ende springen
+   fstream::off_type length = in.tellg(); //Position abfragen
+   in.seekg( 0, ios::beg );    //An den Anfang springen 
+   if( (nodesX1*nodesX2*nodesX3)*sizeof(float) != (long)length )
+   {
+      throw UbException(UB_EXARGS,"number of nodes doesn't match filesize");
+   }
+
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+   GbVoxelMatrix3D* voxelGeo = new GbVoxelMatrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID, threshold);
+   
+   UBLOG(logINFO,"  - init values");
+   float val;
+   for(int x3=0; x3<nodesX3; x3++)
+      for(int x2=0; x2<nodesX2; x2++)
+         for(int x1=0; x1<nodesX1; x1++)
+         {
+            in.read((char*)&val,sizeof(float));
+            //if( !UbMath::equal(val, 0.0f) ) 
+            if( UbMath::greater(val, threshold) ) 
+            {
+               (*voxelGeo)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+            }
+         }
+   
+   UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromRawFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+
+   return voxelGeo;
+}
+/***************************************************************************/
+GbVoxelMatrix3D* GbVoxelMatrix3DCreator::createFromVtiASCIIFloatFile(  string filename, int nodesX1, int nodesX2, int nodesX3, float threshold)
+{
+   UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromVtiASCIIFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+   UbFileInputASCII in(filename);
+   //ifstream in(filename.c_str(), ios::binary);
+   if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   //in.readLine(); !!!manchmal hat das vti file noch die xml version dabei ...
+
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+   GbVoxelMatrix3D* voxelGeo = new GbVoxelMatrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID, threshold);
+
+   UBLOG(logINFO,"  - init values");
+   int val;
+   int u=0;
+   for(int x3=0; x3<nodesX3; x3++)
+      for(int x2=0; x2<nodesX2; x2++)
+         for(int x1=0; x1<nodesX1; x1++)
+         {
+            val = in.readInteger();
+            
+            //u++; if(u>125000) UBLOG(logINFO,"val:"<<u<<" "<<val);
+
+            //if( !UbMath::equal(val, 0.0f) ) 
+            if( UbMath::greater(val, threshold) ) 
+            {
+               (*voxelGeo)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+            }
+         }
+
+         UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromVtiASCIIFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+
+         return voxelGeo;
+}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/creator/GbVoxelMatrix3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/creator/GbVoxelMatrix3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..33e77c6bc8c8a434629f947f28c36ded6e8d2d86
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/creator/GbVoxelMatrix3DCreator.h
@@ -0,0 +1,81 @@
+#ifndef GBVOXELMATRIX3DCREATOR_H
+#define GBVOXELMATRIX3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbVoxelMatrix3D.h>     
+#include <iostream>
+#include <fstream>
+
+class GbVoxelMatrix3DCreator : public GbObject3DCreator              
+{               
+public:
+   enum DataType {t8bit, t16bit};
+public:
+   static GbVoxelMatrix3DCreator* getInstance()
+   {
+      static GbVoxelMatrix3DCreator instance;
+      return &instance;
+   }
+
+   GbVoxelMatrix3D* createGbObject3D() { return new GbVoxelMatrix3D(); }          
+   GbVoxelMatrix3D* createFromRawFloatFile(  std::string filename, int nodesX1, int nodesX2, int nodesX3, float threshold=0.0);
+   GbVoxelMatrix3D* createFromVtiASCIIFloatFile(  std::string filename, int nodesX1, int nodesX2, int nodesX3, float threshold=0.0);
+
+   std::string getGbObject3DTypeID() { return "GbVoxelMatrix3D"; };
+   std::string toString()            { return "GbVoxelMatrix3DCreator"; }
+
+private:
+   GbVoxelMatrix3DCreator() : GbObject3DCreator() {}
+
+   GbVoxelMatrix3DCreator( const GbVoxelMatrix3DCreator& );                  //no copy allowed 
+   const GbVoxelMatrix3DCreator& operator=( const GbVoxelMatrix3DCreator& ); //no copy allowed
+
+public:
+   template< typename T >
+   GbVoxelMatrix3D* createFromRawFile(std::string filename, int nodesX1, int nodesX2, int nodesX3, float threshold)
+   {
+      UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromRawFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+
+      std::ifstream in(filename.c_str(), std::ios::binary);
+      if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+
+      in.seekg( 0, std::ios::end );     //Ende springen
+      std::fstream::off_type length = in.tellg(); //Position abfragen
+      in.seekg( 0, std::ios::beg );    //An den Anfang springen 
+      long m_size = (nodesX1*nodesX2*nodesX3)*sizeof(T);
+      if( m_size != (long)length )
+      {
+         throw UbException(UB_EXARGS,"number of nodes doesn't match filesize: " + UbSystem::toString(length));
+      }
+
+      UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+      GbVoxelMatrix3D* voxelGeo = new GbVoxelMatrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID, threshold);
+
+      UBLOG(logINFO,"  - init values");
+      T val;
+      for(int x3=0; x3<nodesX3; x3++)
+         for(int x2=0; x2<nodesX2; x2++)
+            for(int x1=0; x1<nodesX1; x1++)
+            {
+               in.read((char*)&val,sizeof(T));
+               //if( !UbMath::equal(val, 0.0f) ) 
+               //if( UbMath::greater(val, (T)threshold) ) 
+               if(val > (T)threshold)
+               {
+                  (*voxelGeo)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+               }
+            }
+
+      UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromRawFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+
+      return voxelGeo;
+   }
+};
+
+
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbVoxelMatrix3DCreator::getInstance()), CAB_GbVoxelMatrix3DCreator);
+#endif
+
+#endif  //GBVOXELMATRIX3DCREATOR_H 
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/insideOutsideTests/CMakeLists.txt b/source/ThirdParty/Library/numerics/geometry3d/examples/insideOutsideTests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..153431958236b26fc67f1103d742ae8169364653
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/insideOutsideTests/CMakeLists.txt
@@ -0,0 +1,61 @@
+cmake_minimum_required(VERSION 2.4)
+
+INCLUDE("../../../../CMakeCABMacros.txt")
+INCLUDE("../../../../CMakeSetCompilerFlags.txt")
+
+CHECK_FOR_VARIABLE(CAB_MACHINE "machine name, e.g. ALTIX, ARWEN")
+SET(CMAKE_CONFIG_FILE "${SOURCE_ROOT}/cmake_config_files/${CAB_MACHINE}.config.cmake")
+
+IF(CAB_MACHINE AND EXISTS ${CMAKE_CONFIG_FILE} )
+   
+   PROJECT(geo3dCellCutTests)
+
+   SET(EXECUTABLE_NAME geo3dCellCutTests)
+
+   #erst hier das config file einfügen, ansonsten werden manche settings durch (Project) überschrieben)  
+   INCLUDE(${CMAKE_CONFIG_FILE})  
+  
+   #################################################################
+   ###   PACKAGES						###
+   #################################################################
+   INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+   INCLUDE(${SOURCE_ROOT}/basics/objects/CMakePackage.txt)
+   INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/CMakePackage.txt)
+   INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/creator/CMakePackage.txt)
+   INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/fem/CMakePackage.txt)
+   
+   #################################################################
+   ###   OWN DEFINES 						###
+   #################################################################
+   FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                            ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) 
+
+
+   SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+   SOURCE_GROUP(example FILES ${SPECIFIC_FILES})
+
+   SET_COMPILER_SPECIFIC_FLAGS(${CAB_COMPILER} BINARY)
+   
+   #################################################################
+   ###   ADDITIONAL_MAKE_CLEAN_FILES                             ###
+   #################################################################
+   SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${GENERATED_FILES}")
+
+   #################################################################
+   ###   EXCECUTABLE						###
+   #################################################################
+   ADD_EXECUTABLE(${EXECUTABLE_NAME} ${ALL_SOURCES} )
+
+   #################################################################
+   ###   ADDITIONAL LINK PROPERTIES    			        ###
+   #################################################################
+   IF(CAB_ADDITIONAL_LINK_FLAGS)
+     SET_TARGET_PROPERTIES(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS ${CAB_ADDITIONAL_LINK_FLAGS})
+   ENDIF(CAB_ADDITIONAL_LINK_FLAGS)
+ELSE()
+    IF(CAB_MACHINE)
+      MESSAGE("CAB_MACHINE error - following file is missing: \n ${CMAKE_CONFIG_FILE}")
+    ELSE()
+      MESSAGE("check CAB_MACHINE!!!")
+    ENDIF()  
+ENDIF()
\ No newline at end of file
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/insideOutsideTests/main.cpp b/source/ThirdParty/Library/numerics/geometry3d/examples/insideOutsideTests/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..911bc6965a1ee38a28b45d5e0e9f6874a2aa564d
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/insideOutsideTests/main.cpp
@@ -0,0 +1,46 @@
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/GbSphere3D.h>
+#include <numerics/geometry3d/GbCylinder3D.h>
+
+int main(int argc, char** argv)
+{
+     GbSphere3D test(10,10,10,8);
+     
+     bool cutSp1    /*false*/= test.isCellCuttingGbObject3D(9,9,9,11,11,11); //cell komplett IN sphere
+     bool cutSp2    /*true */= test.isCellCuttingGbObject3D(0,0,0,20,20,20); //cell umhuellt    sphere
+     bool cutSp3    /*true */= test.isCellCuttingGbObject3D(0,0,0,10,10,10); //cell cutted      sphere
+     bool cutSp4    /*false*/= test.isCellCuttingGbObject3D(100,100,100,101,101,101); //cell nix      sphere
+
+     
+     bool cutInsSp1 /*true */= test.isCellInsideOrCuttingGbObject3D(9,9,9,11,11,11);     //cell komplett IN sphere
+     bool cutInsSp2 /*true */= test.isCellInsideOrCuttingGbObject3D(0,0,0,20,20,20);     //cell umhuellt    sphere
+     bool cutInsSp3 /*true */= test.isCellInsideOrCuttingGbObject3D(0,0,0,10,10,10);     //cell cutted      sphere
+     bool cutInsSp4 /*false*/= test.isCellInsideOrCuttingGbObject3D(100,100,100,101,101,101); //cell nix      sphere
+                                                                    
+     GbCuboid3D test1(0,0,0,10,10,10);
+
+     bool cutCu1    /*false*/= test1.isCellCuttingGbObject3D(4,4,4,6,6,6);       //cell komplett IN cube
+     bool cutCu2    /*true */= test1.isCellCuttingGbObject3D(-1,-1,-1,11,11,11); //cell umhuellt    cube
+     bool cutCu3    /*true */= test1.isCellCuttingGbObject3D(5,5,5,15,15,15);   //cell cutted      cube
+     bool cutCu4    /*false*/= test1.isCellCuttingGbObject3D(12,12,12,15,15,15);   //cell nix      cube
+
+     bool cutInsCu1 /*true */= test1.isCellInsideOrCuttingGbObject3D(4,4,4,6,6,6);       //cell komplett IN cube
+     bool cutInsCu2 /*true */= test1.isCellInsideOrCuttingGbObject3D(-1,-1,-1,11,11,11); //cell umhuellt    cube
+     bool cutInsCu3 /*true */= test1.isCellInsideOrCuttingGbObject3D(5,5,5,15,15,15);   //cell cutted      cube
+     bool cutInsCu4 /*false*/= test1.isCellInsideOrCuttingGbObject3D(12,12,12,15,15,15);  //cell nix      cube
+
+     GbCylinder3D test2( 0,0,0, 20, 0, 0, 10);
+
+     bool cutCy1     /*false*/ = test2.isCellCuttingGbObject3D(1,-1,-1,4,1,1);       //cell komplett IN cyl
+     bool cutCy2     /*true */ = test2.isCellCuttingGbObject3D(10,0,0,15,12,11);     //cell umhuellt    cyl
+     bool cutCy3a    /*true */ = test2.isCellCuttingGbObject3D(5,5,5,15,15,15);      //cell cutted      cyl im kreisbreich
+     bool cutCy3b    /*true */ = test2.isCellCuttingGbObject3D(-5,-1,-1,5,1,1);      //cell cutted      cyl am stirn
+     bool cutCy4     /*false*/= test2.isCellCuttingGbObject3D(-10,-10,-10,-5,-5,-5);   //cell nix      cyl
+
+
+     bool cutInsCy1  /*true */= test2.isCellInsideOrCuttingGbObject3D(4,4,4,6,6,6);       //cell komplett IN cube
+     bool cutInsCy2  /*true */= test2.isCellInsideOrCuttingGbObject3D(10,0,0,15,12,11);   //cell umhuellt    cyl
+     bool cutInsCy3a /*true */= test2.isCellInsideOrCuttingGbObject3D(5,5,5,15,15,15);      //cell cutted      cyl im kreisbreich
+     bool cutInsCy3b /*true */= test2.isCellInsideOrCuttingGbObject3D(-5,-1,-1,5,1,1);   //cell cutted      cube
+     bool cutInsCy4  /*false*/= test2.isCellInsideOrCuttingGbObject3D(-10,-10,-10,-5,-5,-5);   //cell nix      cube
+}
\ No newline at end of file
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/CMakeLists.txt b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..37e3f930aa4a3c9ca9ce5d96206c2269e67636ef
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/CMakeLists.txt
@@ -0,0 +1,140 @@
+SET(SOURCE_ROOT $ENV{CAB_DIR} CACHE PATH "(e.g. d:/temp/source)" )
+STRING(REGEX REPLACE "\\\\" "/" SOURCE_ROOT ${SOURCE_ROOT}) # "\" --> "/"
+
+IF(EXISTS ${SOURCE_ROOT})
+ IF(EXISTS ${SOURCE_ROOT}/basics)
+  
+  INCLUDE(${SOURCE_ROOT}/CMakeCABMacros.txt) 
+ 
+  PROJECT (STL2INP)
+  SET(EXECUTABLE_NAME stl2inp)
+
+  #################################################################
+  ###   PACKAGES						###
+  #################################################################
+ 
+  INCLUDE(${SOURCE_ROOT}/basics/objects/CMakeLists.txt)
+  INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakeLists.txt)
+  INCLUDE(${SOURCE_ROOT}/basics/relation/CMakeLists.txt)
+
+ 
+  INCLUDE(${SOURCE_ROOT}/numerics/geometry2d/CMakeLists.txt)
+  INCLUDE(${SOURCE_ROOT}/numerics/geometry2d/creator/CMakeLists.txt)
+ 
+  INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/CMakeLists.txt)
+  INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/creator/CMakeLists.txt)
+ 
+  INCLUDE(${SOURCE_ROOT}/octree/CMakeLists.txt)
+  INCLUDE(${SOURCE_ROOT}/octree/facette/CMakeLists.txt)
+ 
+  INCLUDE(${SOURCE_ROOT}/quadtree/CMakeLists.txt)
+  INCLUDE(${SOURCE_ROOT}/quadtree/nodeadaptation/CMakeLists.txt)
+
+ 
+  #################################################################
+  ###   OWN DEFINES                                             ###
+  #################################################################
+ # ADD_DEFINITIONS( -DCAB_QT )
+ # ADD_DEFINITIONS( -DCAB_QTONLY )
+  ADD_DEFINITIONS( -DMEMPOOL_A2PIIOCTNODEVD)
+  SET(SPECIFIC_FILES main.cpp stl2inp.h stl2inp.cpp QDefineUniformMesh.h QDefineUniformMesh.cpp)
+  SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+  SOURCE_GROUP(z_specific FILES ${SPECIFIC_FILES})
+
+  IF(WIN32)
+    ADD_CXX_FLAGS("/wd4996")
+  ELSE(WIN32)
+    ADD_CXX_FLAGS("-O3 -mcpu=athlon-4 -fomit-frame-pointer -finline-functions -funroll-all-loops")
+  ENDIF(WIN32)
+
+  
+
+  #################################################################
+  ### QT SPECIFIC (only has effects if a QT source is included)	###
+  #################################################################
+  #QT specific 
+   SET(NEED_QT "YES")
+  INCLUDE(${SOURCE_ROOT}/CMakeQtMacros.txt)
+
+  IF(QT_FOUND)
+    INCLUDE_DIRECTORIES( ${QT_INCLUDE_DIR} 
+			 ${QT_INCLUDE_PATH} 
+			 ${QT_QTCORE_INCLUDE_DIR}
+			 ${QT_QTGUI_INCLUDE_DIR}  
+                       )
+    LINK_LIBRARIES ( ${QT_QTCORE_LIBRARY} 
+                     ${QT_QTGUI_LIBRARY} 
+                    )
+    ADD_DEFINITIONS( ${QT_DEFINITIONS})
+   ELSE(QT_FOUND)
+    IF(${NEED_QT} MATCHES "YES") 
+      MESSAGE("Ups\nAt least one package needs Qt!\nPlease check Qt settings\n(e.g. librarys within Advanced Values)")
+    ENDIF(${NEED_QT} MATCHES "YES") 
+   
+    
+  ENDIF(QT_FOUND)
+
+ IF(QT_FOUND)
+     SET(SUBDIRPATH numerics/geometry3d/examples/stl2inp) 
+     SET(CURRENT_DIR ${SOURCE_ROOT}/${SUBDIRPATH})
+ 
+     ################################################################
+    ###         Qt4      UI FILES                                ###
+    ################################################################
+    FILE(GLOB UI_FILES ${CURRENT_DIR}/*.ui)           #collect ui files
+    QT4_WRAP_UI(${CURRENT_DIR} OUTFILES ${UI_FILES})  #wrap ui files
+    REMOVE(TEMP_FILES ${OUTFILES} )
+    SET(TEMP_FILES ${TEMP_FILES} ${OUTFILES} )
+    
+    #make subfolders for VS with new files
+    SOURCE_GROUP(${SUBDIRPATH} FILES ${OUTFILES})
+    
+    IF(WIN32)
+      SET(ALL_SOURCES ${ALL_SOURCES} ${UI_FILES})
+      SOURCE_GROUP(${SUBDIRPATH} FILES ${UI_FILES})
+    ENDIF(WIN32)
+ 
+   ################################################################
+    ###       Qt4        HEADERS TO BE MOCED                     ###
+    ################################################################
+    MAKE_DIRECTORY(${CURRENT_DIR}${QTGEN_MOC})
+    SET(MOC_FILES ) #empty MOC_FILES
+    #SET(MOC_CLASSES  ${CURRENT_DIR}/stl2inp.h QDefineUniformMesh.ui )
+
+    QT4_WRAP_CPP(${CURRENT_DIR}${QTGEN_MOC} MOC_FILES ${MOC_CLASSES})
+    REMOVE(TEMP_FILES ${MOC_FILES})
+    SET(TEMP_FILES ${TEMP_FILES} ${MOC_FILES})
+    SOURCE_GROUP(${SUBDIRPATH}${QTGEN_MOC} FILES ${MOC_FILES})
+   
+    SET(ALL_SOURCES ${ALL_SOURCES} ${TEMP_FILES})
+   
+  ENDIF(QT_FOUND)
+
+
+  #################################################################
+  ###   ADDITIONAL_MAKE_CLEAN_FILES                             ###
+  #################################################################
+  SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${GENERATED_FILES}")
+  
+  #################################################################
+  ###   EXCECUTABLE						###
+  #################################################################
+    ADD_EXECUTABLE( ${EXECUTABLE_NAME} 
+                  ${ALL_SOURCES}
+                )
+
+
+  #################################################################
+  ###   ADDITIONAL LINK PROPERTIES    			        ###
+  #################################################################
+  IF(CAB_ADDITIONAL_LINK_FLAGS)
+    SET_TARGET_PROPERTIES(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS ${CAB_ADDITIONAL_LINK_FLAGS})
+  ENDIF(CAB_ADDITIONAL_LINK_FLAGS)
+
+ ELSE(EXISTS ${SOURCE_ROOT}/basics)
+   MESSAGE("Set Path to \"source\" directory at\nSOURCE_ROOT\nis not correct")
+ ENDIF(EXISTS ${SOURCE_ROOT}/basics)
+ELSE(EXISTS ${SOURCE_ROOT})
+ SET(SOURCE_ROOT "CAB_DIR NOT FOUND" CACHE PATH "(e.g. d:/temp/source)" FORCE)
+ MESSAGE("Please Set Path to \"source\" directory at\nSOURCE_ROOT\n(e.g. D:/temp/source)")
+ENDIF(EXISTS ${SOURCE_ROOT})
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.cpp b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..278d021653712124e5f0bfb40eb5aaffd4291754
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.cpp
@@ -0,0 +1,17 @@
+#include "./QDefineUniformMesh.h"
+#include <QtGui/QFileDialog>
+#include <QString>
+#include <QFile>
+#include <QMessageBox>
+#include <cstdio>
+
+
+QDefineUniformMesh::QDefineUniformMesh(QWidget *parent, Qt::WFlags flags)
+{
+	ui.setupUi(this);
+}
+
+QDefineUniformMesh::~QDefineUniformMesh()
+{
+
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.h b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.h
new file mode 100644
index 0000000000000000000000000000000000000000..f470a8edce55e67e93d17cd5de52e0bebef9a281
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.h
@@ -0,0 +1,35 @@
+#ifndef QDEFINEUNIFORMMESH_H
+#define QDEFINEUNIFORMMESH_H
+
+#include <QtGui/QDialog>
+#include "./QDefineUniformMeshUI.h"
+
+class QDefineUniformMesh : public QDialog
+{
+	Q_OBJECT
+
+public:
+	QDefineUniformMesh(QWidget *parent = 0, Qt::WFlags flags = 0);
+	~QDefineUniformMesh();
+
+	void	setStartLevel(int startLevel)	{ ui.spinBox_startLevel->setValue(startLevel); }
+	void	setStopLevel(int stopLevel)		{ ui.spinBox_stopLevel->setValue(stopLevel); }
+	void	setDelta(double delta)		{ ui.doubleSpinBox_delta->setValue(delta); }
+	void	setNX1(int nx1)				{ ui.spinBox_nx1->setValue(nx1); }
+	void	setNX2(int nx2)				{ ui.spinBox_nx2->setValue(nx2); }
+	void	setNX3(int nx3)				{ ui.spinBox_nx3->setValue(nx3); }
+
+	int		getStartLevel()	{ return ui.spinBox_startLevel->value(); }
+	int		getStopLevel()	{ return ui.spinBox_stopLevel->value(); }
+	double	getDelta()		{ return ui.doubleSpinBox_delta->value(); }
+	int		getNX1()		{ return ui.spinBox_nx1->value(); }
+	int		getNX2()		{ return ui.spinBox_nx2->value(); }
+	int		getNX3()		{ return ui.spinBox_nx3->value(); }
+
+private:
+	Ui::QDefineUniformMesh ui;
+
+//private slots:
+};
+
+#endif // QDEFINEUNIFORMMESH_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.ui b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.ui
new file mode 100644
index 0000000000000000000000000000000000000000..c03b2513f5b64cfb9a4e1a5ea3ce9cbab96e11b2
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.ui
@@ -0,0 +1,258 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QDefineUniformMesh</class>
+ <widget class="QDialog" name="QDefineUniformMesh" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>180</width>
+    <height>220</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Define Mesh Parameters</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>9</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item row="0" column="0" >
+    <layout class="QGridLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item row="1" column="0" >
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label" >
+         <property name="toolTip" >
+          <string>Stop-Level der Verfeinerung</string>
+         </property>
+         <property name="text" >
+          <string>Stop-Level</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSpinBox" name="spinBox_stopLevel" />
+       </item>
+      </layout>
+     </item>
+     <item row="0" column="0" >
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label_6" >
+         <property name="toolTip" >
+          <string>Start-Level der Verfeinerung</string>
+         </property>
+         <property name="text" >
+          <string>Start-Level</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSpinBox" name="spinBox_startLevel" />
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item row="1" column="0" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="label_2" >
+       <property name="toolTip" >
+        <string>Größe der Zellen</string>
+       </property>
+       <property name="text" >
+        <string>Delta</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QDoubleSpinBox" name="doubleSpinBox_delta" />
+     </item>
+    </layout>
+   </item>
+   <item row="3" column="0" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>131</width>
+         <height>31</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="okButton" >
+       <property name="text" >
+        <string>OK</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cancelButton" >
+       <property name="text" >
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="0" >
+    <layout class="QVBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label_3" >
+         <property name="toolTip" >
+          <string>Anzahl Zellen in X-Richtung</string>
+         </property>
+         <property name="text" >
+          <string>nx1</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSpinBox" name="spinBox_nx1" />
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label_4" >
+         <property name="toolTip" >
+          <string>Anzahl Zellen in Y-Richtung</string>
+         </property>
+         <property name="text" >
+          <string>nx2</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSpinBox" name="spinBox_nx2" />
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label_5" >
+         <property name="toolTip" >
+          <string>Anzahl Zellen in Z-Richtung</string>
+         </property>
+         <property name="text" >
+          <string>nx3</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSpinBox" name="spinBox_nx3" />
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>okButton</sender>
+   <signal>clicked()</signal>
+   <receiver>QDefineUniformMesh</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>286</x>
+     <y>257</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>96</x>
+     <y>254</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>cancelButton</sender>
+   <signal>clicked()</signal>
+   <receiver>QDefineUniformMesh</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>369</x>
+     <y>257</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>179</x>
+     <y>282</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/main.cpp b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..17bf6a44174af3acbdd3d4d7a259235767b197ed
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/main.cpp
@@ -0,0 +1,15 @@
+#include <iostream>
+#include <cstdlib>
+
+#include <QtGui/QApplication>
+#include "./stl2inp.h"
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    STL2INP w;
+
+	w.show();
+    a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
+    return a.exec();
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.cpp b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d5e95f17a269cd716170f9a0a66d0b64273269b
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.cpp
@@ -0,0 +1,261 @@
+#include "stl2inp.h"
+#include <QtGui/QFileDialog>
+#include <QString>
+#include <QFile>
+#include <QMessageBox>
+#include <cstdio>
+
+#include "./QDefineUniformMesh.h"
+
+#include "./../../../../../source/basics/utilities/UbFileInputASCII.h"
+#include "./../../../../../source/basics/utilities/UbFileOutputASCII.h"
+#include "./../../../../../source/basics/utilities/UbFileOutputBinary.h"
+#include "./../../../../../source/numerics/geometry3d/GbTriangularMesh3D.h"
+#include "./../../../../../source/numerics/geometry3d/creator/GbTriangularMesh3DCreator.h"
+#include "./../../../../../source/numerics/geometry3D/CoordinateTransformation3D.h"
+#include "./../../../../../source/basics/utilities/UbTiming.h"
+#include "./../../../../../source/octree/facette/OctFacettenGrid2.h"
+
+STL2INP::STL2INP(QWidget *parent, Qt::WFlags flags)
+: QMainWindow(parent, flags)
+{
+	ui.setupUi(this);
+	startLevel	= 0;
+	stopLevel	= 3;
+	delta		= 10.00;
+	nx1			= 30;
+	nx2			= 15;
+	nx3			= 5;
+	
+}
+
+STL2INP::~STL2INP()
+{
+
+}
+
+void STL2INP::on_pBtn_Input_pressed()
+{
+	QString s = QFileDialog::getOpenFileName(
+		this,
+		"Choose a file",
+		"E:/",
+		"STL-Files (*.stl)");
+	if(s != ""){
+		ui.lineEdit_In->setText(s);
+		ui.statusBar->showMessage("Input-File: Filename defined", 3000);
+	}
+	else
+		ui.statusBar->showMessage("Input-File: No file found", 3000);
+
+}
+
+void STL2INP::on_lineEdit_In_returnPressed(){
+	QString s = ui.lineEdit_In->text();
+	if(s != ""){
+		if(!s.endsWith(".stl",Qt::CaseSensitivity(false)))
+		{
+			s.append(".stl");
+			ui.lineEdit_In->setText(s);
+		}
+		if(QFile::exists(s))
+			ui.statusBar->showMessage("Inputput-File: File found", 3000);
+		else
+			ui.statusBar->showMessage("Input-File: File does not exist", 3000);
+	}
+	else
+		ui.statusBar->showMessage("Input-File: no Filename", 3000);
+}
+
+void STL2INP::on_pBtn_Output_pressed(){
+	QString s = QFileDialog::getSaveFileName(
+		this,
+		"Choose a filename to save under",
+		"E:/",
+		"AVS-File (*.inp)");
+	if(s != ""){
+		ui.lineEdit_Out->setText(s);
+		ui.statusBar->showMessage("Output-File: Filename defined", 3000);
+	}
+	else
+		ui.statusBar->showMessage("Output-File: No file defined", 3000);
+}
+
+void STL2INP::on_lineEdit_Out_returnPressed(){
+	QString s = ui.lineEdit_Out->text();
+	if(s != ""){
+		if(!s.endsWith(".inp",Qt::CaseSensitivity(false)))
+		{
+			s.append(".inp");
+			ui.lineEdit_Out->setText(s);
+		}
+		if (QFile::exists(s))
+			if(QMessageBox::question(this,
+				tr("Overwrite File? -- Application Name"),
+				tr("A file called %1 already exists."
+				"Do you want to overwrite it?")
+				.arg(s),
+				tr("&Yes"), tr("&No"),
+				QString(), 0, 1))
+				ui.lineEdit_Out->setText("");
+			else
+				ui.statusBar->showMessage("Output-File: overwrite existing File", 3000);
+		else
+			ui.statusBar->showMessage("Output-File: Filename defined", 3000);
+	}
+	else
+		ui.statusBar->showMessage("Output-File: No file defined", 3000);
+}
+
+void STL2INP::on_pBtn_Output_2_pressed(){
+	QString s = QFileDialog::getSaveFileName(
+		this,
+		"Choose a filename to save under",
+		"E:/",
+		"Data-File (*.dat)");
+	if(s != ""){
+		ui.pBtn_EditMesh->setEnabled(true);
+		ui.lineEdit_Out_2->setText(s);
+		ui.statusBar->showMessage("Output-File: Filename defined", 3000);
+		on_pBtn_EditMesh_pressed();
+	}
+	else
+		ui.statusBar->showMessage("Output-File: No file defined", 3000);
+}
+
+void STL2INP::on_lineEdit_Out_2_returnPressed(){
+	QString s = ui.lineEdit_Out_2->text();
+	if(s != ""){
+		ui.pBtn_EditMesh->setEnabled(true);
+		if(!s.endsWith(".dat",Qt::CaseSensitivity(false)))
+		{
+			s.append(".dat");
+			ui.lineEdit_Out_2->setText(s);
+		}
+		if (QFile::exists(s))
+			if(QMessageBox::question(this,
+				tr("Overwrite File? -- Application Name"),
+				tr("A file called %1 already exists."
+				"Do you want to overwrite it?")
+				.arg(s),
+				tr("&Yes"), tr("&No"),
+				QString(), 0, 1)){
+					ui.lineEdit_Out_2->setText("");
+					ui.pBtn_EditMesh->setEnabled(false);
+			}
+			else{
+				ui.statusBar->showMessage("Output-File: overwrite existing File", 3000);
+				ui.pBtn_EditMesh->setEnabled(true);
+			}
+		else{
+			ui.statusBar->showMessage("Output-File: Filename defined", 3000);
+			on_pBtn_EditMesh_pressed();
+		}
+	}
+	else
+		ui.statusBar->showMessage("Output-File: No file defined", 3000);
+}
+
+void STL2INP::on_pBtn_Convert_pressed(){
+	if(ui.lineEdit_In->text() == "")
+		QMessageBox::warning(this,"ERROR", "No Input-File defined!",
+		QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
+	else if(ui.lineEdit_Out->text() == "" && ui.lineEdit_Out_2->text() == "")
+		QMessageBox::warning(this,"ERROR", "No Output-File defined!",
+		QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);  
+	else
+	{
+		UbFileInputASCII *fileInput = new UbFileInputASCII(std::string(ui.lineEdit_In->text().toAscii()));
+		GbTriangularMesh3D *mesh = GbTriangularMesh3DCreator::readMeshFromSTLFile(fileInput, "Cube");
+		ui.statusBar->showMessage("Input-File was read", 3000);
+		delete fileInput;
+		cout<<mesh->toString()<<endl;
+		if(ui.checkBox_writeAVS->isChecked()){
+			if(ui.checkBox_Binary->isChecked()){
+				UbFileOutputBinary *fileOutput_AVS = new UbFileOutputBinary(std::string(ui.lineEdit_Out->text().toAscii()));
+				mesh->writeAVSMesh(fileOutput_AVS);
+				delete fileOutput_AVS;
+			}
+			else{
+				UbFileOutputASCII *fileOutput_AVS = new UbFileOutputASCII(std::string(ui.lineEdit_Out->text().toAscii()));
+				mesh->writeAVSMesh(fileOutput_AVS);
+				delete fileOutput_AVS;
+			}
+			ui.statusBar->showMessage("wrote AVS-Output-File");
+		}
+		if(ui.checkBox_writeUM->isChecked()){
+			cout<<"MinX:"<<mesh->getX1Minimum()<<endl;
+			cout<<"MaxX:"<<mesh->getX1Maximum()<<endl;
+			cout<<"MinY:"<<mesh->getX2Minimum()<<endl;
+			cout<<"MaxY:"<<mesh->getX2Maximum()<<endl;
+			cout<<"MinZ:"<<mesh->getX3Minimum()<<endl;
+			cout<<"MaxZ:"<<mesh->getX3Maximum()<<endl;
+			ui.statusBar->showMessage("start Writing Uniform-Mesh-File");
+			double minX = 0.0;
+			double minY = 0.0;    
+			double minZ = 0.0;
+
+			CoordinateTransformation3D *trafo = new CoordinateTransformation3D(minX, minY, minZ, delta, delta, delta);
+
+			UbTiming time;
+			time.initTiming();
+			time.startTiming();
+
+			ui.statusBar->showMessage("start Building FacetteGrid", 3000);
+			OctFacettenGrid2 *facettegrid = new OctFacettenGrid2("FacettenGrid", nx1, nx2, nx3, startLevel, stopLevel, mesh, trafo);
+			ui.statusBar->showMessage("end Building FacetteGrid", 3000);
+
+			UbFileOutputASCII out("E:/DATA/test.inp");
+			facettegrid->writeCellsToAVS(&out);
+
+			time.endTiming();
+			cout<<"Dauer:"<<time.getDuration()<<endl;
+			cout<<"Number of cells:"<<facettegrid->getNumberOfCells()<<endl;
+			cout<<"after generation ..."<<endl<<endl;                                         
+			double mydouble=0.0;
+
+			time.initTiming(); 
+			time.startTiming();
+			ui.statusBar->showMessage("start writing", 3000);
+			UbFileOutputASCII *fileOutput_UM = new UbFileOutputASCII(std::string(ui.lineEdit_Out_2->text().toAscii()));
+			facettegrid->writeToUniformGridFile2(fileOutput_UM);
+			delete fileOutput_UM;
+			time.endTiming();
+			cout<<"Dauer:"<<time.getDuration()<<endl;
+			int number = (int)facettegrid->getCells()->size();
+			delete trafo;
+			delete mesh;
+			delete facettegrid;
+			cout<<"Ready!!!"<<endl;
+			ui.statusBar->showMessage("wrote Unstructured-Mesh Output-File", 3000);
+		}
+	}
+}
+
+void STL2INP::on_checkBox_stateChanged(int)
+{
+
+}
+
+void STL2INP::on_pBtn_EditMesh_pressed()
+{
+	QDefineUniformMesh *meshdef = new QDefineUniformMesh(this); 
+	meshdef->setStartLevel(startLevel);
+	meshdef->setStopLevel(stopLevel);
+	meshdef->setDelta(delta);
+	meshdef->setNX1(nx1);
+	meshdef->setNX2(nx2);
+	meshdef->setNX3(nx3);
+	meshdef->exec();
+
+	startLevel = meshdef->getStartLevel();
+	stopLevel = meshdef->getStopLevel();
+	//cout<<"Start-Level: "<<startLevel<<"  Stop-Level: "<<stopLevel<<endl;
+	delta = meshdef->getDelta();
+	//cout<<"Delta: "<<delta<<endl;
+	nx1 = meshdef->getNX1();
+	nx2 = meshdef->getNX2();
+	nx3 = meshdef->getNX3();
+	//cout<<"nx1: "<<nx1<<"  nx2: "<<nx2<<"  nx3: "<<nx3<<endl;
+	delete meshdef;
+}
\ No newline at end of file
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.h b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.h
new file mode 100644
index 0000000000000000000000000000000000000000..a48fd463a7bc7ebb9ad0a16b83c78368365d5630
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.h
@@ -0,0 +1,36 @@
+#ifndef STL2INP_H
+#define STL2INP_H
+
+#include <QtGui/QMainWindow>
+#include <QtGui/QProgressBar>
+#include <QTimer>
+#include "stl2inpUI.h"
+
+class STL2INP : public QMainWindow
+{
+	Q_OBJECT
+
+public:
+	STL2INP(QWidget *parent = 0, Qt::WFlags flags = 0);
+	~STL2INP();
+	
+	int startLevel, stopLevel;
+	double delta;
+	int nx1, nx2, nx3;
+
+private:
+	Ui::STL2INPClass ui;
+
+	private slots:
+		void on_checkBox_stateChanged(int);
+		void on_pBtn_Input_pressed();
+		void on_pBtn_Output_pressed();
+		void on_pBtn_Output_2_pressed();
+		void on_pBtn_Convert_pressed();
+		void on_lineEdit_In_returnPressed();
+		void on_lineEdit_Out_returnPressed();
+		void on_lineEdit_Out_2_returnPressed();
+		void on_pBtn_EditMesh_pressed();
+};
+
+#endif // STL2INP_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.ui b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.ui
new file mode 100644
index 0000000000000000000000000000000000000000..28d3ab49ca511a249430e804088b461320d72d0a
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/examples/stl2inp/stl2inp.ui
@@ -0,0 +1,452 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>STL2INPClass</class>
+ <widget class="QMainWindow" name="STL2INPClass" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>350</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>STL2INP</string>
+  </property>
+  <property name="statusTip" >
+   <string>...</string>
+  </property>
+  <widget class="QWidget" name="centralWidget" >
+   <layout class="QGridLayout" >
+    <property name="margin" >
+     <number>9</number>
+    </property>
+    <property name="spacing" >
+     <number>6</number>
+    </property>
+    <item row="4" column="0" colspan="2" >
+     <widget class="QGroupBox" name="groupBox_2" >
+      <property name="title" >
+       <string>Output-Files</string>
+      </property>
+      <layout class="QGridLayout" >
+       <property name="margin" >
+        <number>9</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item row="0" column="0" >
+        <widget class="QCheckBox" name="checkBox_writeAVS" >
+         <property name="text" >
+          <string>write AVS-File</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1" colspan="3" >
+        <widget class="QCheckBox" name="checkBox_Binary" >
+         <property name="text" >
+          <string>write *.inp to Binary</string>
+         </property>
+        </widget>
+       </item>
+       <item row="4" column="0" >
+        <widget class="QCheckBox" name="checkBox_writeUM" >
+         <property name="text" >
+          <string>write Uniform-Mesh-File</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0" colspan="3" >
+        <widget class="QLineEdit" name="lineEdit_Out" >
+         <property name="enabled" >
+          <bool>false</bool>
+         </property>
+         <property name="minimumSize" >
+          <size>
+           <width>300</width>
+           <height>17</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item row="5" column="3" >
+        <widget class="QPushButton" name="pBtn_Output_2" >
+         <property name="enabled" >
+          <bool>false</bool>
+         </property>
+         <property name="maximumSize" >
+          <size>
+           <width>25</width>
+           <height>23</height>
+          </size>
+         </property>
+         <property name="text" >
+          <string>...</string>
+         </property>
+        </widget>
+       </item>
+       <item row="5" column="0" colspan="3" >
+        <widget class="QLineEdit" name="lineEdit_Out_2" >
+         <property name="enabled" >
+          <bool>false</bool>
+         </property>
+         <property name="minimumSize" >
+          <size>
+           <width>300</width>
+           <height>17</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="3" >
+        <widget class="QPushButton" name="pBtn_Output" >
+         <property name="enabled" >
+          <bool>false</bool>
+         </property>
+         <property name="maximumSize" >
+          <size>
+           <width>25</width>
+           <height>23</height>
+          </size>
+         </property>
+         <property name="text" >
+          <string>...</string>
+         </property>
+        </widget>
+       </item>
+       <item rowspan="2" row="2" column="0" colspan="4" >
+        <widget class="Line" name="line" >
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item rowspan="2" row="3" column="2" colspan="2" >
+        <widget class="QPushButton" name="pBtn_EditMesh" >
+         <property name="enabled" >
+          <bool>false</bool>
+         </property>
+         <property name="minimumSize" >
+          <size>
+           <width>51</width>
+           <height>20</height>
+          </size>
+         </property>
+         <property name="maximumSize" >
+          <size>
+           <width>51</width>
+           <height>20</height>
+          </size>
+         </property>
+         <property name="text" >
+          <string>Edit Mesh</string>
+         </property>
+        </widget>
+       </item>
+       <item row="4" column="1" >
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="0" column="0" >
+     <widget class="QLabel" name="label_3" >
+      <property name="font" >
+       <font>
+        <family>Tahoma</family>
+        <pointsize>14</pointsize>
+        <weight>75</weight>
+        <italic>false</italic>
+        <bold>true</bold>
+        <underline>false</underline>
+        <strikeout>false</strikeout>
+       </font>
+      </property>
+      <property name="text" >
+       <string>STL2INP</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="0" >
+     <spacer>
+      <property name="orientation" >
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeHint" >
+       <size>
+        <width>20</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item row="6" column="0" >
+     <layout class="QHBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <widget class="QPushButton" name="pushButton_4" >
+        <property name="text" >
+         <string>EXIT</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer>
+        <property name="orientation" >
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" >
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="pBtn_Convert" >
+        <property name="text" >
+         <string>Convert</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item row="5" column="0" >
+     <spacer>
+      <property name="orientation" >
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeHint" >
+       <size>
+        <width>20</width>
+        <height>21</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item row="2" column="0" >
+     <widget class="QGroupBox" name="groupBox" >
+      <property name="title" >
+       <string>Input-File</string>
+      </property>
+      <layout class="QGridLayout" >
+       <property name="margin" >
+        <number>9</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item row="0" column="1" >
+        <widget class="QPushButton" name="pBtn_Input" >
+         <property name="maximumSize" >
+          <size>
+           <width>25</width>
+           <height>23</height>
+          </size>
+         </property>
+         <property name="text" >
+          <string>...</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="0" >
+        <widget class="QLineEdit" name="lineEdit_In" >
+         <property name="minimumSize" >
+          <size>
+           <width>300</width>
+           <height>17</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="3" column="0" >
+     <spacer>
+      <property name="orientation" >
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeHint" >
+       <size>
+        <width>20</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QStatusBar" name="statusBar" >
+   <property name="geometry" >
+    <rect>
+     <x>0</x>
+     <y>331</y>
+     <width>400</width>
+     <height>19</height>
+    </rect>
+   </property>
+  </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <tabstops>
+  <tabstop>lineEdit_In</tabstop>
+  <tabstop>pBtn_Input</tabstop>
+  <tabstop>lineEdit_Out</tabstop>
+  <tabstop>pBtn_Output</tabstop>
+  <tabstop>checkBox_Binary</tabstop>
+  <tabstop>pBtn_Convert</tabstop>
+  <tabstop>pushButton_4</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>pushButton_4</sender>
+   <signal>clicked()</signal>
+   <receiver>STL2INPClass</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>82</x>
+     <y>320</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>222</x>
+     <y>349</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>checkBox_writeAVS</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>lineEdit_Out</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>43</x>
+     <y>189</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>99</x>
+     <y>210</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>checkBox_writeAVS</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>pBtn_Output</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>130</x>
+     <y>189</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>380</x>
+     <y>209</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>checkBox_writeUM</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>lineEdit_Out_2</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>74</x>
+     <y>237</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>88</x>
+     <y>258</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>checkBox_writeUM</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>pBtn_Output_2</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>152</x>
+     <y>237</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>380</x>
+     <y>257</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>lineEdit_In</sender>
+   <signal>selectionChanged()</signal>
+   <receiver>pBtn_Input</receiver>
+   <slot>animateClick()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>236</x>
+     <y>105</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>345</x>
+     <y>98</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>lineEdit_Out</sender>
+   <signal>selectionChanged()</signal>
+   <receiver>pBtn_Output</receiver>
+   <slot>animateClick()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>302</x>
+     <y>203</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>362</x>
+     <y>202</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>lineEdit_Out_2</sender>
+   <signal>selectionChanged()</signal>
+   <receiver>pBtn_Output_2</receiver>
+   <slot>animateClick()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>256</x>
+     <y>249</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>365</x>
+     <y>253</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/CMakePackage.txt b/source/ThirdParty/Library/numerics/geometry3d/fem/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fb2d6a4735aec73c8966db5d20f5b8ac29612b9e
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/CMakePackage.txt
@@ -0,0 +1,37 @@
+SET(SUBDIRPATH numerics/geometry3d/fem) 
+SET(OPTION_LABEL BUILD_GEO3D_FEM)
+
+SET(CURRENT_DIR ${SOURCE_ROOT}/${SUBDIRPATH})
+
+OPTION(${OPTION_LABEL} "${CURRENT_DIR}" ON)
+IF(${OPTION_LABEL})
+  SET(TEMP_FILES "") 
+  FILE(GLOB HEADER_FILES ${CURRENT_DIR}/*.h  )
+  FILE(GLOB CPP_FILES    ${CURRENT_DIR}/*.cpp)
+  
+
+  SET(TEMPO_FILES ${HEADER_FILES} ${CPP_FILES})
+  IF(NOT ADHOC)
+    FILE(GLOB ADHOC_FILES ${CURRENT_DIR}/*Adhoc* )
+    REMOVE(TEMPO_FILES ${ADHOC_FILES} )
+  ENDIF(NOT ADHOC)
+
+  IF(NOT EIGENVALUE)
+    FILE(GLOB EIGENVALUE_FILES ${CURRENT_DIR}/*Eigen* )
+    REMOVE(TEMPO_FILES ${EIGENVALUE_FILES} )
+  ENDIF(NOT EIGENVALUE)
+
+IF(CAB_PACKAGE_DEFINTIONS)
+    SET_SOURCE_FILES_PROPERTIES(${CPP_FILES} PROPERTIES COMPILE_FLAGS ${CAB_PACKAGE_DEFINTIONS})
+ENDIF(CAB_PACKAGE_DEFINTIONS)
+
+  SET(ALL_SOURCES ${ALL_SOURCES} ${TEMPO_FILES})
+  
+  IF(${WITH_SUBFOLDERS_FOR_SG} MATCHES YES)  
+    STRING(REGEX REPLACE "/" "\\\\" SG_PATH ${SUBDIRPATH})
+    SOURCE_GROUP(${SG_PATH} FILES ${TEMPO_FILES})
+  ELSE(${WITH_SUBFOLDERS_FOR_SG} MATCHES YES)
+    SOURCE_GROUP(${SUBDIRPATH} FILES ${TEMPO_FILES})
+  ENDIF(${WITH_SUBFOLDERS_FOR_SG} MATCHES YES)
+
+ENDIF(${OPTION_LABEL})
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FeAdhocTriFaceMesh3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/fem/FeAdhocTriFaceMesh3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..86b7cc239d0a33da9db6a6263d8959863bcfa0da
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FeAdhocTriFaceMesh3D.cpp
@@ -0,0 +1,124 @@
+#include "./FeAdhocTriFaceMesh3D.h"
+
+#include "./../GbPoint3D.h"
+#include "./../GbTriangle3D.h"
+#include "./../GbTriangularMesh3D.h"
+
+#include "./../../../basics/utilities/UbFileOutputASCII.h"
+#include "./../../../basics/utilities/UbLogger.h"
+
+/*====================================================*/
+FeAdhocTriFaceMesh3D::FeAdhocTriFaceMesh3D():FeTriFaceMesh3D()
+{
+}
+/*====================================================*/
+FeAdhocTriFaceMesh3D::FeAdhocTriFaceMesh3D(std::string name, Mesh* mesh):FeTriFaceMesh3D()
+{
+   this->mesh = mesh;
+   this->setName(name);
+
+   std::cout << "FeAdhocTriFaceMesh3D:Konstruktor !!!"<<std::endl;
+   std::cout << "num vertices: " << mesh->VL->nitem << ", num triangles: " << mesh->TL->nitem
+             << ", num quads: " << mesh->QL->nitem << std::endl;
+
+ //  this->writeAdhoCMeshForStefan("/scratch/geller/StudienMitAdhoC3D/mesh.inp");
+   this->adhocVertices = new vector< ::Vertex*>;
+
+   List *vertexlist  = mesh->VL;
+   List *elementlist = mesh->TL;
+
+   ListItem*  LI;
+   ListItem*  LI2;
+   Tri*       triangle;
+ //  double z1, z2, z3;
+   int    id1, id2, id3;
+   ::Vertex *v1, *v2, *v3;
+
+   //if (mesh->VL->status==open)  close_Vertex_List(mesh->VL);
+
+   FOR_ALL(vertexlist->first, LI, 0)
+   {
+      ::Vertex* V = get_Vertex(LI);
+      this->nodes->push_back(GbTriFaceMesh3D::Vertex((float)V->x, (float)V->y, (float)V->z));
+      this->adhocVertices->push_back(V);
+   }
+   int countTris=0;
+    int fred=0;
+   FOR_ALL(elementlist->first, LI, 0)
+   {
+      triangle = get_Tri(LI);
+    if(triangle==NULL) UBLOG(logINFO, "hugo - dreieck ist NULL");
+      v1 = triangle->V[0];
+      v2 = triangle->V[1];
+      v3 = triangle->V[2];
+      int count=0;
+      id1=-1; id2=-1; id3=-1;
+      FOR_ALL(vertexlist->first, LI2, 0)
+      {
+         ::Vertex* V = get_Vertex(LI2);
+         if(v1==V) id1=count;
+         if(v2==V) id2=count;
+         if(v3==V) id3=count;
+         if((id1!=-1) && (id2!=-1) && (id3!=-1))
+         {
+            break;
+         }
+         count++;
+      }
+    //  this->triangles->push_back(GbTriFaceMesh3D::TriFace(v1->id, v2->id, v3->id));
+    // das geht bei Winkelplatte und Bathe
+      this->triangles->push_back(GbTriFaceMesh3D::TriFace(id2, id1, id3));
+    //  this->triangles->push_back(GbTriFaceMesh3D::TriFace(id1, id2, id3));
+      countTris++;
+   }
+
+   std::cout<<"#################################"<<std::endl;
+   std::cout<<"countTris:"<<countTris<<std::endl;
+   std::cout<<"vecSize:"<<this->triangles->size()<<std::endl;
+   this->attributes->resize(nodes->size());
+
+   countTris=0;
+   for(int u=0;u<(int)this->triangles->size(); u++)
+   {
+       double area = (*this->triangles)[u].getArea(*this->nodes);
+       if(UbMath::zero(area))  countTris++;
+   }
+   std::cout<<"#################################"<<std::endl;
+   std::cout<<"Area 0 für:"<<countTris<<" Dreiecke"<<std::endl;
+
+   this->calculateValues();
+
+   this->createVertexTriFaceMap();
+}
+/*===============================================================================*/
+void FeAdhocTriFaceMesh3D::writeAdhoCMeshForStefan(string filename)
+{
+   std::cout << "FeAdhocTriFaceMesh3D::writeAdhoCMeshForStefan ...\n";
+   List *elementlist = mesh->TL;
+
+   ListItem* LI;
+   Tri*      triangle;
+
+   vector<GbPoint3D*>*     tmnodes     = new vector<GbPoint3D*>;
+   vector<GbTriangle3D*>*  tmtriangles = new vector<GbTriangle3D*>;
+
+   FOR_ALL(elementlist->first, LI, 0)
+   {
+      triangle = get_Tri(LI);
+
+      GbPoint3D *node1 = new GbPoint3D(triangle->V[0]->x, triangle->V[0]->y, triangle->V[0]->z);
+      GbPoint3D *node2 = new GbPoint3D(triangle->V[1]->x, triangle->V[1]->y, triangle->V[1]->z);
+      GbPoint3D *node3 = new GbPoint3D(triangle->V[2]->x, triangle->V[2]->y, triangle->V[2]->z);
+
+      tmnodes->push_back(node1);
+      tmnodes->push_back(node2);
+      tmnodes->push_back(node3);
+      tmtriangles->push_back(new GbTriangle3D(node1, node2, node3));
+
+   }
+
+   GbTriangularMesh3D tmmesh("Name", tmnodes, tmtriangles);
+   UbFileOutputASCII out(filename);
+   tmmesh.writeAVSMesh(&out);
+}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FeAdhocTriFaceMesh3D.h b/source/ThirdParty/Library/numerics/geometry3d/fem/FeAdhocTriFaceMesh3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0f3e339aa742b7669e18ad84c50a078771da7ab
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FeAdhocTriFaceMesh3D.h
@@ -0,0 +1,62 @@
+#ifndef FEADHOCTRIFACEMESH3D_H
+#define FEADHOCTRIFACEMESH3D_H
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+using namespace std;
+
+//extern "C"
+//{
+   //#include "mshpi.h"
+    #include "fsi_interface.h"
+    #include "fsi_user_interface.h"
+//}
+
+#include "./FeTriFaceMesh3D.h"
+
+#ifdef CAB_RCF
+#include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+
+/*=========================================================================*/
+/* FeAdhocTriFaceMesh3D                                                    */
+/*                                                                         */
+/**
+ * This Class provides the triangular meshes.
+ * Note, that up to now no methods for checking consistency are included.
+ * in this context this class describes facettes from an 3D-object !!!
+*/
+class FeAdhocTriFaceMesh3D : public FeTriFaceMesh3D
+{
+public:
+   FeAdhocTriFaceMesh3D();
+   FeAdhocTriFaceMesh3D(std::string name, Mesh *mesh);
+
+   Mesh*  getMesh() { return mesh; }
+
+   void writeAdhoCMeshForStefan(string filename);
+   std::vector< ::Vertex*>* getAdhocVertices() { return this->adhocVertices; }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      serializeParent<FeTriFaceMesh3D>(ar, *this);
+   }
+#endif //CAB_RCF
+
+private:
+   Mesh* mesh;
+   std::vector< ::Vertex*>* adhocVertices;
+};
+
+#ifdef RCF_USE_SF_SERIALIZATION
+UB_AUTO_RUN_NAMED(   SF::registerType<FeAdhocTriFaceMesh3D  >("FeAdhocTriFaceMesh3D  ")    , SF_FeAdhocTriFaceMesh3D     );
+UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< FeTriFaceMesh3D, FeAdhocTriFaceMesh3D>() ), SF_FeAdhocTriFaceMesh3D_BD1 );
+UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbTriFaceMesh3D, FeAdhocTriFaceMesh3D>() ), SF_FeAdhocTriFaceMesh3D_BD2 );
+UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, FeAdhocTriFaceMesh3D>() ), SF_FeAdhocTriFaceMesh3D_BD3 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //FEADHOCTRIFACEMESH3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FeHalfDisc3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/fem/FeHalfDisc3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b392588173b909338d025e7dc752f4decf95c66
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FeHalfDisc3D.cpp
@@ -0,0 +1,622 @@
+#include <numerics/geometry3d/fem/FeHalfDisc3D.h>    
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/fem/FePoint3D.h>
+#include <basics/utilities/UbInfinity.h>
+
+using namespace std;
+
+/*=======================================================*/
+ObObjectCreator* FeHalfDisc3D::getCreator()
+{
+   return NULL;//FeHalfDisc3DCreator::getInstance(); 
+}
+// Konstruktor
+/*==========================================================*/
+FeHalfDisc3D::FeHalfDisc3D()
+{
+   GbPoint3D* p1 = new GbPoint3D();
+   GbPoint3D* p2 = new GbPoint3D();
+   mLine = new GbLine3D(p1,p2);
+   this->mLine->addObserver(this);
+   mRad = 0.0;
+   cylinderType = FeHalfDisc3D::NOTPARALLELTOAXIS;
+}                                                   
+/*=======================================================*/
+FeHalfDisc3D::FeHalfDisc3D(FeHalfDisc3D* cylinder)
+{
+   mRad         = cylinder->getRadius();
+   cylinderType = cylinder->cylinderType;
+   mLine        = cylinder->getLine()->clone();
+
+   this->mLine->addObserver(this);
+}                                                   
+/*==========================================================*/
+FeHalfDisc3D::FeHalfDisc3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b, const double& rad)
+{
+   mLine = new GbLine3D;
+   mLine->setPoints( new GbPoint3D(min(x1a,x1b), min(x2a,x2b), min(x3a,x3b))
+	                 ,new GbPoint3D(max(x1a,x1b), max(x2a,x2b), max(x3a,x3b)));
+   this->mLine->addObserver(this);
+   mRad = fabs(rad);
+
+   this->initCylinderType();
+   if((this->cylinderType & NOTPARALLELTOAXIS)==NOTPARALLELTOAXIS) 
+      throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}                                                            
+/*==========================================================*/
+FeHalfDisc3D::FeHalfDisc3D(GbPoint3D* p1, GbPoint3D* p2, const double& rad)
+{
+   mRad = rad;
+
+   mLine = new GbLine3D(p1,p2);
+   this->mLine->addObserver(this);
+   this->initCylinderType();
+   if((this->cylinderType & NOTPARALLELTOAXIS)==NOTPARALLELTOAXIS) 
+      throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+FeHalfDisc3D::FeHalfDisc3D(GbLine3D* line, const double& rad)
+{
+   mRad = rad;
+
+   this->mLine = line;
+   this->mLine->addObserver(this);
+   this->initCylinderType();
+   if((this->cylinderType & NOTPARALLELTOAXIS)==NOTPARALLELTOAXIS) 
+      throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/		
+// Destruktor
+FeHalfDisc3D::~FeHalfDisc3D()
+{
+   if(mLine) this->mLine->removeObserver(this);
+   mLine = NULL;
+}
+/*=======================================================*/
+void FeHalfDisc3D::initCylinderType()
+{
+   double x1a = mLine->getPoint1()->x1;    double x1b = mLine->getPoint2()->x1;
+   double x2a = mLine->getPoint1()->x2;    double x2b = mLine->getPoint2()->x2;
+   double x3a = mLine->getPoint1()->x3;    double x3b = mLine->getPoint2()->x3;
+   
+   if     (x1a!=x1b && x2a==x2b && x3a==x3b)  this->cylinderType = X1PARALLEL; 
+   else if(x2a!=x2b && x1a==x1b && x3a==x3b)  this->cylinderType = X2PARALLEL; 
+   else if(x3a!=x3b && x1a==x1b && x2a==x2b)  this->cylinderType = X3PARALLEL; 
+   else                                       this->cylinderType = NOTPARALLELTOAXIS;
+}
+/*=======================================================*/
+void FeHalfDisc3D::finalize() 
+{ 
+   if(this->mLine) 
+   {
+      mLine->finalize();
+      delete mLine; 
+      mLine=NULL;
+   } 
+}
+/*=======================================================*/
+double FeHalfDisc3D::getHeight()
+{
+   if(mLine) return mLine->getLength(); return 0.0; 
+}
+/*=======================================================*/
+GbPoint3D* FeHalfDisc3D::getPoint1()
+{
+   if(this->mLine) return this->mLine->getPoint1();
+   return NULL;
+}
+/*=======================================================*/
+GbPoint3D* FeHalfDisc3D::getPoint2()
+{
+   if(this->mLine) return this->mLine->getPoint2();
+   return NULL;
+}
+/*=======================================================*/
+void FeHalfDisc3D::setRadius(const double& radius) 
+{ 
+   this->mRad = std::fabs(radius); 
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void FeHalfDisc3D::setLine(GbLine3D* line) 
+{
+   if(this->mLine) this->mLine->removeObserver(this);
+   this->mLine = line;  
+   this->mLine->addObserver(this);
+   this->initCylinderType();
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void FeHalfDisc3D::setPoint1(const double& x1, const double& x2, const double& x3)
+{ 
+   if(!mLine->getPoint1()) throw UbException(UB_EXARGS,"line has no point1");
+   mLine->getPoint1()->setCoordinates(x1,x2,x3);
+   this->initCylinderType();
+
+   //this->notifyObserversObjectChanged(); //wird automatisch aufgerufen, da der point (this) benachrichtigt...
+}
+/*=======================================================*/
+void FeHalfDisc3D::setPoint2(const double& x1, const double& x2, const double& x3)
+{ 
+   if(!mLine->getPoint2()) throw UbException(UB_EXARGS,"line has no point2");
+   mLine->getPoint2()->setCoordinates(x1,x2,x3);
+   this->initCylinderType();
+
+   //this->notifyObserversObjectChanged(); //wird automatisch aufgerufen, da der point (this) benachrichtigt...
+}
+/*==========================================================*/		
+double FeHalfDisc3D::getX1Centroid()  
+{
+   return mLine->getX1Centroid();
+}
+/*==========================================================*/
+double FeHalfDisc3D::getX1Minimum()   
+{
+   if     (this->isParallelToX1Axis()) return mLine->getX1Minimum(); 
+   else if(this->isParallelToX2Axis()) return mLine->getX1Centroid()-mRad; 
+   else if(this->isParallelToX3Axis()) return mLine->getX1Centroid()-mRad; 
+   else throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+double FeHalfDisc3D::getX1Maximum()   
+{
+   if     (this->isParallelToX1Axis()) return mLine->getX1Maximum(); 
+   else if(this->isParallelToX2Axis()) return mLine->getX1Centroid()+mRad; 
+   else if(this->isParallelToX3Axis()) return mLine->getX1Centroid()+mRad; 
+   else throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+double FeHalfDisc3D::getX2Centroid()
+{
+   return mLine->getX2Centroid();
+}
+/*==========================================================*/
+double FeHalfDisc3D::getX2Minimum()   
+{
+   if     (this->isParallelToX1Axis()) return mLine->getX2Centroid()-mRad;
+   else if(this->isParallelToX2Axis()) return mLine->getX2Minimum();
+   else if(this->isParallelToX3Axis()) return mLine->getX2Centroid()-mRad; 
+   else throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}	
+/*==========================================================*/
+double FeHalfDisc3D::getX2Maximum()   
+{
+   if     (this->isParallelToX1Axis())  return mLine->getX2Centroid()+mRad;
+   else if(this->isParallelToX2Axis())  return mLine->getX2Maximum();
+   else if(this->isParallelToX3Axis())  return mLine->getX2Centroid()+mRad; 
+   else throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+double FeHalfDisc3D::getX3Centroid()
+{
+   return mLine->getX3Centroid();
+}
+/*==========================================================*/
+double FeHalfDisc3D::getX3Minimum()   
+{	
+   if     (this->isParallelToX1Axis()) return mLine->getX3Centroid()-mRad;
+   else if(this->isParallelToX2Axis()) return mLine->getX3Centroid()-mRad; 
+   else if(this->isParallelToX3Axis()) return mLine->getX3Minimum(); 
+   else throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}	
+/*==========================================================*/
+double FeHalfDisc3D::getX3Maximum()   
+{
+   if     (this->isParallelToX1Axis()) return mLine->getX3Centroid()+mRad;
+   else if(this->isParallelToX2Axis()) return mLine->getX3Centroid()+mRad; 
+   else if(this->isParallelToX3Axis()) return mLine->getX3Maximum(); 
+   else throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+bool FeHalfDisc3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   throw UbException(UB_EXARGS,"sollte mal einer machen ... ");
+}
+/*==========================================================*/
+bool FeHalfDisc3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   throw UbException(UB_EXARGS,"sollte mal einer machen ... ");
+}
+/*=======================================================*/
+bool FeHalfDisc3D::isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   throw UbException(UB_EXARGS,"sollte mal einer machen ... ");
+}
+
+/*==========================================================*/
+string FeHalfDisc3D::toString() 
+{
+	stringstream ss;
+	ss<<"FeHalfDisc3D[";
+	ss<<"line="<<this->mLine->toString();
+   ss<<", r="<<this->mRad;
+   ss<<"]";
+   return(ss.str());
+}
+/*==========================================================*/
+bool FeHalfDisc3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   throw UbException(UB_EXARGS,"sollte mal einer machen ... ");   
+}
+/*==========================================================*/
+bool FeHalfDisc3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   throw UbException(UB_EXARGS,"sollte mal einer machen ... ");
+}
+/*==========================================================*/
+GbLine3D* FeHalfDisc3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"sollte mal einer machen ... ");
+}
+/*==========================================================*/
+vector<GbTriangle3D*> FeHalfDisc3D::getSurfaceTriangleSet()
+{
+   double x1ma,x1mb,x2m,x3m;
+   if( this->isParallelToX1Axis() ) 
+   {
+      x1ma = this->getX1Minimum();
+      x1mb = this->getX1Maximum();
+      x2m  = this->getX2Centroid();
+      x3m  = this->getX3Centroid();
+   }
+   else if( this->isParallelToX2Axis() ) 
+   {
+      x1ma = this->getX2Minimum();
+      x1mb = this->getX2Maximum();
+      x2m  = this->getX1Centroid();
+      x3m  = this->getX3Centroid();
+   }
+   else if( this->isParallelToX3Axis() ) 
+   {
+      x1ma = this->getX3Minimum();
+      x1mb = this->getX3Maximum();
+      x2m  = this->getX2Centroid();
+      x3m  = this->getX1Centroid();
+   }
+   else throw UbException(UB_EXARGS,"cylinder is not axis prallel");
+   
+   vector<GbTriangle3D*> triangles;    
+
+   int segmentsCircle  = 14;
+   double deltaPhi = UbMath::PI/(double)segmentsCircle;
+
+   double phiX1a,phiX1b;
+   double x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+   
+   double dXCylinder =  fabs((x1mb-x1ma)); ///(double)0.5;
+   int segmentsCylinder = (int)(fabs(x1mb-x1ma)/dXCylinder);
+   for(int segCyl = 0; segCyl<segmentsCylinder; segCyl++)
+   {
+      x1a = x1d = x1ma+segCyl*dXCylinder;
+      x1b = x1c = x1a+dXCylinder;
+      
+      for(phiX1a=UbMath::PI-deltaPhi; phiX1a>-deltaPhi; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+         
+         x2a =  x2m+mRad*std::sin(phiX1a);
+         x3a =  x3m+mRad*std::cos(phiX1a);
+         x2b =  x2m+mRad*std::sin(phiX1b);
+         x3b =  x3m+mRad*std::cos(phiX1b);
+         
+         if( this->isParallelToX1Axis() ) 
+         { 
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1b,x2a,x3a),new FePoint3D(x1b,x2b,x3b),new FePoint3D(x1a,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1a,x2b,x3b),new FePoint3D(x1a,x2a,x3a),new FePoint3D(x1b,x2b,x3b))); 
+         }
+         else if( this->isParallelToX2Axis() ) 
+         { 
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x2b,x1b,x3b),new FePoint3D(x2a,x1b,x3a),new FePoint3D(x2a,x1a,x3a)));
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x2a,x1a,x3a),new FePoint3D(x2b,x1a,x3b),new FePoint3D(x2b,x1b,x3b))); 
+         }
+         else if( this->isParallelToX3Axis() ) 
+         { 
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x3b,x2b,x1b),new FePoint3D(x3a,x2a,x1b),new FePoint3D(x3a,x2a,x1a)));
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x3a,x2a,x1a),new FePoint3D(x3b,x2b,x1a),new FePoint3D(x3b,x2b,x1b))); 
+         }
+
+      }
+   }
+
+   x2a = x2m;
+   x3a = x3m;
+   x2d = x2m;
+   x3d = x3m+mRad;
+   x3b = x3m;
+   x3c = x3m-mRad;
+   
+   triangles.push_back(new GbTriangle3D(new FePoint3D(x1ma,x2a,x3a),new FePoint3D(x1mb,x2a,x3a),new FePoint3D(x1ma,x2a,x3d)));
+   triangles.push_back(new GbTriangle3D(new FePoint3D(x1ma,x2a,x3d),new FePoint3D(x1mb,x2a,x3a),new FePoint3D(x1mb,x2a,x3d)));
+   triangles.push_back(new GbTriangle3D(new FePoint3D(x1mb,x2a,x3b),new FePoint3D(x1ma,x2a,x3b),new FePoint3D(x1ma,x2a,x3c)));
+   triangles.push_back(new GbTriangle3D(new FePoint3D(x1mb,x2a,x3b),new FePoint3D(x1ma,x2a,x3c),new FePoint3D(x1mb,x2a,x3c)));
+  
+   for(phiX1a=UbMath::PI-deltaPhi; phiX1a>-deltaPhi; phiX1a-=deltaPhi)
+   {
+      phiX1b = phiX1a+deltaPhi;
+
+      x2a =  x2m;
+      x3a =  x3m;
+      x2b =  x2m;
+      x3b =  x3m;
+      x2c =  x2m+mRad*std::sin(phiX1b);
+      x3c =  x3m+mRad*std::cos(phiX1b);
+      x2d =  x2m+mRad*std::sin(phiX1a);
+      x3d =  x3m+mRad*std::cos(phiX1a);
+
+      if( this->isParallelToX1Axis() ) 
+      { 
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x1ma,x2d,x3d),new FePoint3D(x1ma,x2c,x3c),new FePoint3D(x1ma,x2a,x3a)));
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x1mb,x2d,x3d),new FePoint3D(x1mb,x2a,x3a),new FePoint3D(x1mb,x2c,x3c)));
+      }
+      else if( this->isParallelToX2Axis() ) 
+      { 
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x2a,x1ma,x3a),new FePoint3D(x2b,x1ma,x3b),new FePoint3D(x2c,x1ma,x3c)));
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x2c,x1ma,x3c),new FePoint3D(x2d,x1ma,x3d),new FePoint3D(x2a,x1ma,x3a)));
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x2c,x1mb,x3c),new FePoint3D(x2b,x1mb,x3b),new FePoint3D(x2a,x1mb,x3a)));
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x2a,x1mb,x3a),new FePoint3D(x2d,x1mb,x3d),new FePoint3D(x2c,x1mb,x3c)));
+      }
+      else if( this->isParallelToX3Axis() ) 
+      { 
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x3a,x2a,x1ma),new FePoint3D(x3b,x2b,x1ma),new FePoint3D(x3c,x2c,x1ma)));
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x3c,x2c,x1ma),new FePoint3D(x3d,x2d,x1ma),new FePoint3D(x3a,x2a,x1ma)));
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x3c,x2c,x1mb),new FePoint3D(x3b,x2b,x1mb),new FePoint3D(x3a,x2a,x1mb)));
+         triangles.push_back(new GbTriangle3D(new FePoint3D(x3a,x2a,x1mb),new FePoint3D(x3d,x2d,x1mb),new FePoint3D(x3c,x2c,x1mb)));
+      }
+   }
+
+   return triangles;
+}
+/*==========================================================*/
+void FeHalfDisc3D::objectChanged(UbObservable* changedObject)
+{
+   GbLine3D* line = dynamic_cast<GbLine3D*>(changedObject);
+   if(!line || this->mLine!=line) return;
+
+   this->notifyObserversObjectChanged();
+}
+/*==========================================================*/
+void FeHalfDisc3D::objectWillBeDeleted(UbObservable* objectForDeletion)
+{
+   if(this->mLine)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->mLine);
+      if(objectForDeletion == observedObj) { this->mLine = NULL; }
+   }
+}
+/*=======================================================*/
+void FeHalfDisc3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{  
+   if( this->isParallelToX1Axis() )
+   {
+      if(!UbMath::equal(sx2,sx3)) throw UbException(UB_EXARGS,"|| to x1 -> different scaling sx2 and sx3 not possible");
+      this->mRad*=sx2;
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      if(!UbMath::equal(sx1,sx3)) throw UbException(UB_EXARGS,"|| to x2 -> different scaling sx1 and sx3 not possible");
+      this->mRad*=sx1;
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      if(!UbMath::equal(sx1,sx2)) throw UbException(UB_EXARGS,"|| to x3 -> different scaling sx1 and sx2 not possible");
+      this->mRad*=sx1;
+   }
+   else throw UbException(UB_EXARGS,"unknown direction");
+
+   this->mLine->scale(sx1,sx2,sx3);
+   //notify observer wird automatisch aufgerufen
+}
+/*==========================================================*/
+void FeHalfDisc3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   mLine->write(out);
+   out->writeDouble(mRad);
+   out->writeInteger(cylinderType);
+}
+/*==========================================================*/
+void FeHalfDisc3D::read(UbFileInput* in) 
+{  
+   in->readString();                                    
+   mLine = new GbLine3D;
+   mLine->read(in);
+   mRad         = in->readDouble();
+   cylinderType = in->readInteger();
+}
+/*==========================================================*/
+double FeHalfDisc3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   /*
+   Distance D of the intersection between a Ray((ox1,ox2,ox3),(dx1,dx2,dx3)) and a Plane P: ax+by+cz+d=0 
+   dc = a*dx1 + b*dx2 + c*dx3
+   dw = a*ox1 + b*ox2 + c*ox3 + d
+   D =   - dw / dc
+   */
+   double px1, px2, px3;
+   double d = Ub::inf; // Distance to Min or Max Plane of the Cylinder  
+                       // final distance should be less that d 
+   
+   if( this->isParallelToX1Axis() )
+   {
+      double minX1 = this->getX1Minimum();
+      double maxX1 = this->getX1Maximum();
+
+      if     (UbMath::equal(x1 ,minX1) && UbMath::negative(rx1))    return -1.0; 
+      else if(UbMath::equal(x1 ,maxX1) && UbMath::positive(rx1))    return -1.0; 
+
+      //falls die Linie nicht parallel zu den Seitenflächen ist
+      if( x1< minX1  ||  x1 > maxX1 ) //nur für punkte links und rechts des cylinders
+      {
+         px1 = (x1 < minX1 ? minX1 : maxX1);
+         //falls die Linie nicht parallel zu den Seitenflächen ist
+         if( !UbMath::zero(rx1) )
+         {
+            // Plane a= 0, b= 1, c=0 d= -1*px2
+            d   = -1.0*(x1 - px1) / rx1;
+            px2 = x2 + d*rx2;
+            px3 = x3 + d*rx3;
+
+            if(UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad))
+            {
+               if     (x1 < minX1 && rx1>0.0 ) d = Ub::inf;  //punkt liegt "links" vom cylinder und strahl hat evtl weiteren SP auf oberfläche 
+               else if(x1 > maxX1 && rx1<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else 
+      {
+         if     (UbMath::negative(rx1)) d = -1.0 * (x1 - minX1) / rx1;
+         else if(UbMath::positive(rx1)) d = -1.0 * (x1 - maxX1) / rx1;
+      }
+   }
+   else if( this->isParallelToX2Axis() )
+   { 
+      double minX2 = this->getX2Minimum();
+      double maxX2 = this->getX2Maximum();
+
+      if     (UbMath::equal(x2 ,minX2) && UbMath::negative(rx2))    return -1; 
+      else if(UbMath::equal(x2 ,maxX2) && UbMath::positive(rx2))    return -1; 
+
+      if( minX2 > x2  ||  x2 > maxX2 )
+      {
+         px2 = (x2 < minX2 ? minX2 : maxX2);
+         //falls die Linie nicht parallel zu den Seitenflächen ist
+         if( !UbMath::zero(rx2) )
+         {
+            // Plane a= 0, b= 1, c=0 d= -1*px2
+            d   = -1*(x2 - px2) / rx2;
+            px1 = x1 + d*rx1;
+            px3 = x3 + d*rx3;
+            
+            if (UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad))
+            {
+               if     (x2 < minX2 && rx2>0.0 ) d = Ub::inf;  //punkt liegt "links oberhalb" vom cylinder und strahl mit pos x1 hat evtl weiteren SP auf oberfläche 
+               else if(x2 > maxX2 && rx2<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else
+      {
+         if     (UbMath::negative(rx2)) d = -1.0 * (x2 - minX2) / rx2;
+         else if(UbMath::positive(rx2)) d = -1.0 * (x2 - maxX2) / rx2;
+      }
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      double minX3 = this->getX3Minimum();
+      double maxX3 = this->getX3Maximum();
+
+      if     (UbMath::equal(x3, minX3) && UbMath::negative(rx3)) return -1.0; 
+      else if(UbMath::equal(x3, maxX3) && UbMath::positive(rx3)) return -1.0; 
+
+      if(minX3 > x3  ||  x3 > maxX3 )
+      {
+         px3 = (x3 < minX3 ? minX3 : maxX3);
+         //falls die Linie nicht parallel zu den Seitenflächen ist
+         if (!UbMath::zero(rx3))
+         {
+            // Plane a= 0, b= 0, c=1 d= -1*px3
+            d   = -1.0*(x3 - px3) / rx3;
+            px2 = x2 + d*rx2;
+            px1 = x1 + d*rx1;
+            if( UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad) )
+            {
+               if     (x3 < minX3 && rx3>0.0 ) d = Ub::inf;  
+               else if(x3 > maxX3 && rx3<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else 
+      {
+         if     (UbMath::negative(rx3)) d = -1.0 * (x3 - minX3) / rx3;
+         else if(UbMath::positive(rx3)) d = -1.0 * (x3 - maxX3) / rx3;
+      }
+   }
+   else throw UbException(UB_EXARGS,"funzt nur bei achsen parallelem cylinder");
+   //////////////////////////////////////////////////////////////////////////
+   //Q berechnen für Infinity Cylinder
+   GbPoint3D* p1 = mLine->getPoint1();
+   GbPoint3D* p2 = mLine->getPoint2();
+   
+   double axisX1 = p2->x1 - p1->x1;  /* Axis of the cylinder   */
+   double axisX2 = p2->x2 - p1->x2;  /* mit p1 als base of cylinder */
+   double axisX3 = p2->x3 - p1->x3;       
+
+   //double dirlen = mLine->getLength(); 
+   //double abs, t, s;
+
+   double RCx1 = x1 - p1->x1;
+   double RCx2 = x2 - p1->x2; 
+   double RCx3 = x3 - p1->x3; 
+   
+   //n = ray x axis
+   double nx1 = rx2*axisX3 - rx3*axisX2;
+   double nx2 = rx3*axisX1 - rx1*axisX3;
+   double nx3 = rx1*axisX2 - rx2*axisX1;
+   double nLength = nx1*nx1 + nx2*nx2 + nx3*nx3;
+
+   double abs;
+   if( UbMath::zero( nLength ) )
+   {  /* ray parallel to cyl  */
+      //abs = RC dot axis
+      double abs = RCx1*axisX1 + RCx2*axisX2 + RCx3*axisX3;
+      double dx1 = RCx1 - abs*axisX1; 
+      double dx2 = RCx2 - abs*axisX2;
+      double dx3 = RCx3 - abs*axisX3;
+      //abs   = sqrt(dx1*dx1 + dx2*dx2 + dx3*dx3);
+      if( UbMath::greater( dx1*dx1 + dx2*dx2 + dx3*dx3 , mRad*mRad) ) 
+         return -1.0;
+   }
+
+   //normalize "n"
+   nLength = std::sqrt(nLength);
+   double invnLength = 1.0/nLength;
+   nx1*=invnLength;
+   nx2*=invnLength;
+   nx3*=invnLength;
+
+   //shortest distance  = fabs( RC dot n )
+   abs = fabs( RCx1*nx1 + RCx2*nx2 + RCx3*nx3 );     
+   
+   if( UbMath::lessEqual(abs, mRad) )
+   {                    /* if ray hits cylinder */
+      //Ox1 = RC x axis
+      double Ox1 = RCx2*axisX3 - RCx3*axisX2;
+      double Ox2 = RCx3*axisX1 - RCx1*axisX3;
+      double Ox3 = RCx1*axisX2 - RCx2*axisX1;
+      //t = - O dot n / nLength;
+      double t = - (Ox1*nx1 + Ox2*nx2 + Ox3*nx3) / nLength;
+      
+      //O = n x axis;
+      Ox1 = nx2*axisX3 - nx3*axisX2;
+      Ox2 = nx3*axisX1 - nx1*axisX3;
+      Ox3 = nx1*axisX2 - nx2*axisX1;
+
+      //normalize O
+      invnLength = 1.0/sqrt(Ox1*Ox1 + Ox2*Ox2 + Ox3*Ox3);
+      Ox1*=invnLength;
+      Ox2*=invnLength;
+      Ox3*=invnLength;
+
+      double s = fabs( sqrt(mRad*mRad - abs*abs) / (rx1*Ox1 + rx2*Ox2 + rx3*Ox3) );
+      
+      if( UbMath::greater(t-s,d) ) return -1.0;
+      
+      return  t - s;
+   }
+   
+   return -1.0;
+}
+/*==========================================================*/
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FeHalfDisc3D.h b/source/ThirdParty/Library/numerics/geometry3d/fem/FeHalfDisc3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f7ad43f816a073b8b39eaf0f2a4f8923b3647da
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FeHalfDisc3D.h
@@ -0,0 +1,104 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef FEHALFDISC3D_H
+#define FEHALFDISC3D_H
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <basics/utilities/UbObserver.h>
+
+class GbPoint3D;
+class GbLine3D;
+class GbTriangle3D;
+
+class GbObject3DCreator;
+
+class FeHalfDisc3D : public GbObject3D , public UbObserver 
+{
+public:
+   FeHalfDisc3D();
+	FeHalfDisc3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b, const double& radius);
+	FeHalfDisc3D(GbPoint3D* p1, GbPoint3D* p2, const double& radius);
+	FeHalfDisc3D(GbLine3D* line, const double& rad);
+	FeHalfDisc3D(FeHalfDisc3D* cylinder);
+	~FeHalfDisc3D();    
+
+	FeHalfDisc3D* clone() { return new FeHalfDisc3D(this); }
+	void finalize();
+
+	double     getRadius() { return this->mRad; };
+	GbLine3D*  getLine() {return mLine;}
+	GbPoint3D* getPoint1();
+	GbPoint3D* getPoint2();
+
+	void setRadius(const double& radius);
+	void setLine(GbLine3D* line);
+	void setPoint1(const double& x1, const double& x2, const double& x3);
+	void setPoint2(const double& x1, const double& x2, const double& x3);
+
+	bool isParallelToX1Axis() { return((this->cylinderType & X1PARALLEL        )    ==  X1PARALLEL        );}
+	bool isParallelToX2Axis() { return((this->cylinderType & X2PARALLEL        )    ==  X2PARALLEL        );}
+	bool isParallelToX3Axis() { return((this->cylinderType & X3PARALLEL        )    ==  X3PARALLEL        );}
+	bool isNotParallelToAxis(){ return((this->cylinderType & NOTPARALLELTOAXIS )    ==  NOTPARALLELTOAXIS );}
+
+	double getHeight(); 
+
+	void scale(const double& sx1, const double& sx2, const double& sx3);
+
+	double getX1Centroid();
+	double getX1Minimum() ;
+	double getX1Maximum() ;
+	double getX2Centroid();
+	double getX2Minimum() ;
+	double getX2Maximum() ;
+	double getX3Centroid();
+	double getX3Minimum() ;
+	double getX3Maximum() ;
+
+	bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); 
+	bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary); 
+   bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+	GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+   
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+	std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   
+	std::string toString();
+	ObObjectCreator* getCreator();
+	void write(UbFileOutput* out);
+	void read(UbFileInput* in);
+
+	//virtuelle Methoden von UbObserver
+	void objectChanged(UbObservable* changedObject);
+	void objectWillBeDeleted(UbObservable* objectForDeletion);
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+protected:
+	void initCylinderType();
+
+   GbLine3D* mLine;
+	double    mRad;
+
+	int cylinderType;
+
+	//void berechneQuerschnittsWerte();
+   static const int NOTPARALLELTOAXIS  = (1<<0); //1
+   static const int X1PARALLEL         = (1<<1); //2
+   static const int X2PARALLEL         = (1<<2); //4
+   static const int X3PARALLEL         = (1<<3); //8
+};
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FePlateTriangularMesh3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/fem/FePlateTriangularMesh3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..82f053daa4c38de22c79466530e184858e91083f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FePlateTriangularMesh3D.cpp
@@ -0,0 +1,223 @@
+#include <numerics/geometry3d/fem/FePlateTriangularMesh3D.h>
+
+using namespace std;
+                         
+FePlateTriangularMesh3D::FePlateTriangularMesh3D() : GbTriangularMesh3D()
+{
+}
+
+FePlateTriangularMesh3D::FePlateTriangularMesh3D(string name, vector<GbPoint3D*> *nodes, vector<GbTriangle3D*> *triangles) : GbTriangularMesh3D(name, nodes, triangles)
+{
+}
+
+/*=============================================================================================*/
+
+FePlateTriangularMesh3D::FePlateTriangularMesh3D(string name, vector<GbTriangle3D*> *triangles) : GbTriangularMesh3D(name, triangles)
+{
+}
+
+/*=============================================================================================*/
+FePlateTriangularMesh3D::FePlateTriangularMesh3D(string name, vector<GbPoint3D*> *nodes, vector<GbLine3D*> *edges, vector<GbTriangle3D*> *triangles) : GbTriangularMesh3D(name, nodes, edges, triangles)
+{
+}
+/*=============================================================================================*/
+FePlateTriangularMesh3D::~FePlateTriangularMesh3D()
+{
+
+}
+/*======================================================================*/
+
+/*======================================================================*/
+bool FePlateTriangularMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+{
+	//cout<<"GbTriangularMesh3D::isPointInGbObject3D"<<endl;
+	//Sebastian
+	//double xmin=this->getX1Minimum();	double xmax=this->getX1Maximum();
+ //  double ymin=this->getX2Minimum();	double ymax=this->getX2Maximum();
+ //  double zmin=this->getX3Minimum();	double zmax=this->getX3Maximum();
+ //  double dX = (xmax-xmin)/100.;
+ //  double dY = (ymax-ymin)/100.;
+ //  double dZ = (zmax-zmin)/100.;
+ //  GbCuboid3D boundingCube(xmin-dX, ymin-dY, zmin-dZ, xmax+dX, ymax+dY, zmax+dZ);
+	//
+	//if(this->isPointInObject3DHalfSpace(x1,x2,x3))
+	//{
+	//	return true;
+	//}
+	//if(!boundingCube.isPointInGbObject3D(x1, x2, x3))
+	//{
+	//	return false;
+	//}
+
+	//return false;
+	//Marco
+	int inside = 0;
+   int nx1 = this->getNodesX1Dir()-1;
+   int nx2 = this->getNodesX2Dir()-1;
+   int maxTriangels = 2*nx1*nx2;
+
+   //Überprüft, ob der Punkt innerhalb des Netzes liegt
+	double xmin=this->getX1Minimum();	double xmax=this->getX1Maximum();
+	double ymin=this->getX2Minimum();	double ymax=this->getX2Maximum();
+	double zmin=this->getX3Minimum();	double zmax=this->getX3Maximum();
+	if(	x1<=xmax && x1>=xmin
+		&& x2<=ymax && x2>=ymin
+		&& x3<=zmax && x3>=zmin)
+	{
+      //Achtung Sonderfall
+      //Es wird nur gegen die obere Lage Dreiecke getestet, da die untere Lage um den Abstand 'height' verschoben ist!
+      //Die Seiten müssen somit auch nicht berücksichtigt werden
+      for(int i=0; i<int(maxTriangels);i++)     
+		{
+			if(	(triangles->at(i))->enclosesPoint2D(x1, x2)
+				&&	x3<triangles->at(i)->getX3Centroid()
+				&& x3>triangles->at(i)->getX3Centroid() - this->height  )
+			{
+					inside++;
+			}
+		}
+	}
+
+	if(inside!=0)
+	{
+		return true;
+	}
+	else return false;
+}
+/*======================================================================*/
+FePlateTriangularMesh3D* FePlateTriangularMesh3D::createMeshByElements(int ElementsX1, int ElementsX2, double nulllevel, double deltaX1, double deltaX2, double height)
+{
+   FePlateTriangularMesh3D* triMesh = FePlateTriangularMesh3D::createMeshByNodes(ElementsX1+1, ElementsX2+1, nulllevel, deltaX1, deltaX2, height);
+   return triMesh;
+}
+/*======================================================================*/
+FePlateTriangularMesh3D* FePlateTriangularMesh3D::createMeshByNodes(int nodesX1, int nodesX2, double nulllevel, double deltaX1, double deltaX2, double height)
+{
+   cout<<"erstelle GbTriangularMesh3D -> ";
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   vector<GbPoint3D*> *points = new vector<GbPoint3D*>;
+   double h1=nulllevel+0.5*height;
+   double h2=nulllevel-0.5*height;
+   GbPoint3D* point1;
+   GbPoint3D* point2;
+   GbPoint3D* point3;
+   GbPoint3D* point4;
+   //Erstelle Knoten
+   //oben
+   for(int i=0; i<nodesX1; i++)
+   {
+      for(int j=0; j<nodesX2; j++)
+      {
+         GbPoint3D* point = new GbPoint3D(i*deltaX1,j*deltaX2,h1);
+         points->push_back(point);
+      }
+   }
+   //unten
+   for(int i=0; i<nodesX1; i++)
+   {
+      for(int j=0; j<nodesX2; j++)
+      {
+         GbPoint3D* point = new GbPoint3D(i*deltaX1,j*deltaX2,h2);
+         points->push_back(point);
+      }
+   }
+   int size=int(points->size());
+   //Erstelle Dreiecke
+   //oben
+   for(int i=0; i<(size/2)-nodesX2; i+=nodesX2)
+   {
+      for(int j=0; j<nodesX2-1; j++)
+      {
+         point1 = points->at(i+j);
+         point2 = points->at(i+j+1);
+         point3 = points->at(i+j+nodesX2);
+         point4 = points->at(i+j+nodesX2+1);
+         GbTriangle3D* tri1 = new GbTriangle3D(point1,point3,point4);
+         GbTriangle3D* tri2 = new GbTriangle3D(point1,point4,point2);
+         triangles->push_back(tri1);
+         triangles->push_back(tri2);
+      }
+   }
+   //unten
+   for(int i=(size/2); i<size-nodesX2; i+=nodesX2)
+   {
+      for(int j=0; j<nodesX2-1; j++)
+      {
+         point1 = points->at(i+j);
+         point2 = points->at(i+j+1);
+         point3 = points->at(i+j+nodesX2);
+         point4 = points->at(i+j+nodesX2+1);
+         GbTriangle3D* tri1 = new GbTriangle3D(point4,point3,point1);
+         GbTriangle3D* tri2 = new GbTriangle3D(point2,point4,point1);
+         triangles->push_back(tri1);
+         triangles->push_back(tri2);
+      }
+   }
+   //Rand
+   //Nord
+   for(int i=0;i<nodesX1-1;i++)
+   {	
+      int a = i*nodesX2+nodesX2-1;
+      int b = (i+1)*nodesX2+nodesX2-1;
+      point1 = points->at(a);
+      point2 = points->at(b);
+      point3 = points->at(a+size/2);
+      point4 = points->at(b+size/2);
+      GbTriangle3D* tri1 = new GbTriangle3D(point1,point2,point3);
+      GbTriangle3D* tri2 = new GbTriangle3D(point2,point4,point3);
+      triangles->push_back(tri1);
+      triangles->push_back(tri2);
+   }
+   //Süd
+   for(int i=0;i<nodesX1-1;i++)
+   {	
+      int a = i*nodesX2;
+      int b = (i+1)*nodesX2;
+      point1 = points->at(a);
+      point2 = points->at(b);
+      point3 = points->at(a+size/2);
+      point4 = points->at(b+size/2);
+      GbTriangle3D* tri1 = new GbTriangle3D(point3,point2,point1);
+      GbTriangle3D* tri2 = new GbTriangle3D(point3,point4,point2);
+      triangles->push_back(tri1);
+      triangles->push_back(tri2);
+   }
+   //Ost
+   for(int j=0;j<nodesX2-1;j++)
+   {	
+      int a = j;
+      int b = j+1;
+      point1 = points->at(a);
+      point2 = points->at(b);
+      point3 = points->at(a+size/2);
+      point4 = points->at(b+size/2);
+      GbTriangle3D* tri1 = new GbTriangle3D(point1,point2,point3);
+      GbTriangle3D* tri2 = new GbTriangle3D(point4,point3,point2);
+      triangles->push_back(tri1);
+      triangles->push_back(tri2);
+   }
+   //West
+   for(int j=0;j<nodesX2-1;j++)
+   {	
+      int a = j+(nodesX1-1)*nodesX2;
+      int b = j+(nodesX1-1)*nodesX2+1;
+      point1 = points->at(a);
+      point2 = points->at(b);
+      point3 = points->at(a+size/2);
+      point4 = points->at(b+size/2);
+      GbTriangle3D* tri1 = new GbTriangle3D(point3,point2,point1);
+      GbTriangle3D* tri2 = new GbTriangle3D(point2,point3,point4);
+      triangles->push_back(tri1);
+      triangles->push_back(tri2);
+   }
+   string name = "TriMesh";
+   FePlateTriangularMesh3D* triMesh = new FePlateTriangularMesh3D(name,points,triangles);
+   triMesh->setNullLevel((float)nulllevel);
+   triMesh->setHeight(height);
+   triMesh->setNodesX1Dir(nodesX1);
+   triMesh->setNodesX2Dir(nodesX2);
+   cout<<"done"<<endl;
+   return triMesh;
+}
+
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FePlateTriangularMesh3D.h b/source/ThirdParty/Library/numerics/geometry3d/fem/FePlateTriangularMesh3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..a938503a2fff98c4d2b034b61f5f46e853adad89
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FePlateTriangularMesh3D.h
@@ -0,0 +1,50 @@
+#ifndef FEPLATETRIANGULARMESH_H
+#define FEPLATETRIANGULARMESH_H
+
+#include <sstream>
+#include <iostream>
+
+#include <numerics/geometry3d/GbTriangularMesh3D.h>
+
+
+/*=========================================================================*/
+/* GbTriangularMesh3D                                                      */
+/*                                                                         */
+/**
+ * This Class provides the triangular meshes.
+ * Note, that up to now no methods for checking consistency are included.
+ * in this context this class describes facettes from an 3D-object !!!
+*/
+class FePlateTriangularMesh3D : public GbTriangularMesh3D 
+{                             
+public:
+   FePlateTriangularMesh3D();
+   FePlateTriangularMesh3D(std::string name, std::vector<GbPoint3D*> *nodes, std::vector<GbTriangle3D*> *triangles);
+   FePlateTriangularMesh3D(std::string name, std::vector<GbTriangle3D*> *triangles);
+   FePlateTriangularMesh3D(std::string name, std::vector<GbPoint3D*> *nodes, std::vector<GbLine3D*> *edges, std::vector<GbTriangle3D*> *triangles);
+	virtual ~FePlateTriangularMesh3D();   
+
+   static FePlateTriangularMesh3D* createMeshByNodes(int nodesX1, int nodesX2, double nulllevel, double deltaX1, double deltaX2, double height);
+   static FePlateTriangularMesh3D* createMeshByElements(int ElementsX1, int ElementsX2, double nulllevel, double deltaX1, double deltaX2, double height);
+
+
+	float	 getNullLevel()						{	return this->nulllevel;	}
+	void	 setNullLevel(float nulllevel)	{	this->nulllevel = nulllevel;	}
+   double getHeight()							{	return this->height;	}
+   void	 setHeight(double height)			{	this->height = height;	}
+   int    getNodesX1Dir()						{	return this->nodesX1Dir;	}
+   void	 setNodesX1Dir(int nodesX1Dir)   {	this->nodesX1Dir = nodesX1Dir;	}
+   int    getNodesX2Dir()						{	return this->nodesX2Dir;	}
+   void	 setNodesX2Dir(int nodesX2Dir)   {	this->nodesX2Dir = nodesX2Dir;	}
+
+	bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   
+   /*======================================================================*/
+private:
+	float			nulllevel;
+	double		height;
+   int         nodesX1Dir;
+   int         nodesX2Dir;
+};
+/*=========================================================================*/
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FePoint3D.h b/source/ThirdParty/Library/numerics/geometry3d/fem/FePoint3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..c26ac282c0c6f054c2ec214f47e64b40044a3eb0
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FePoint3D.h
@@ -0,0 +1,148 @@
+#ifndef FEPOINT3D_H
+#define FEPOINT3D_H
+
+#include <sstream>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+
+/*=========================================================================*/
+/* GbPoint3D                                                               */
+/*                                                                         */
+/**
+ * This Class provides basic 3D point objects.
+ * <BR><BR><HR>
+ * @author <A HREF="mailto:geller@bauinf.tu-cottbus.de">S. Geller</A>
+ * @version 1.0 - 10.02.07
+ * 
+	*/
+class FePoint3D : public GbPoint3D 
+{
+private:
+
+	double Fx;
+	double Fy;
+	double Fz;
+    //double oldFx;
+    //double oldFy;
+    double sumFx;
+    double sumFy;
+    double sumFz;
+	double velocityX;
+	double velocityY;
+	double velocityZ;
+    //double accelerationX;
+    //double accelerationY;
+   UbTupleDouble6 stresses; 
+
+   double area;
+public:
+	FePoint3D():GbPoint3D()
+   {
+      this->init();
+	}
+	FePoint3D(double x, double y, double z):GbPoint3D(x,y,z)
+	{
+      this->init();
+	}
+   FePoint3D(GbPoint3D *point):GbPoint3D(point)
+   {
+      this->init();
+   }
+
+	FePoint3D(FePoint3D *point):GbPoint3D(point)
+	{
+      this->Fx = point->Fx;
+      this->Fy = point->Fy;
+      this->Fz = point->Fz;
+      throw UbException(__FILE__,__LINE__,"spaeter fertig machen...");
+   }
+
+	virtual ~FePoint3D()
+	{
+	}
+
+   void init()
+   {
+      this->Fx = 0.0;
+      this->Fy = 0.0;
+      this->Fz = 0.0;
+      //this->oldFx = 0.0;
+      //this->oldFy = 0.0;
+      this->sumFx = 0.0;
+      this->sumFy = 0.0;
+      this->sumFz = 0.0;
+      val<1>(stresses) = 0.0;
+      val<2>(stresses) = 0.0;
+      val<3>(stresses) = 0.0;
+      val<4>(stresses) = 0.0;
+      val<5>(stresses) = 0.0;
+      val<6>(stresses) = 0.0;
+      this->area = 0.0;
+      this->velocityX = 0.0;
+      this->velocityY = 0.0;
+      this->velocityZ = 0.0;
+   }
+	/*======================================================================*/
+   FePoint3D* clone()   
+   { 
+      return(new FePoint3D(this)); 
+   }
+
+	double getVelocityX()   { return(this->velocityX); }
+	double getVelocityY()   { return(this->velocityY); }
+	double getVelocityZ()   { return(this->velocityZ); }
+	void setVelocityX(double x)   { this->velocityX = x; }
+	void setVelocityY(double y)   { this->velocityY = y; }
+	void setVelocityZ(double z)   { this->velocityZ = z; }
+
+   double getFX()   { return(this->Fx); }
+	double getFY()   { return(this->Fy); }
+	double getFZ()   { return(this->Fz); }
+	void setFX(double FX)   { this->Fx = FX; }
+	void setFY(double FY)   { this->Fy = FY; }
+	void setFZ(double FZ)   { this->Fz = FZ; }
+	void addFX(double FX)   { this->Fx += FX; }
+	void addFY(double FY)   { this->Fy += FY; }
+	void addFZ(double FZ)   { this->Fz += FZ; }
+
+   double getSumFX()   { return(this->sumFx); }
+   double getSumFY()   { return(this->sumFy); }
+   double getSumFZ()   { return(this->sumFz); }
+   void setSumFX(double FX)   { this->sumFx = FX; }
+   void setSumFY(double FY)   { this->sumFy = FY; }
+   void setSumFZ(double FZ)   { this->sumFz = FZ; }
+   void addSumFX(double FX)   { this->sumFx += FX; }
+   void addSumFY(double FY)   { this->sumFy += FY; }
+   void addSumFZ(double FZ)   { this->sumFz += FZ; }
+
+   UbTupleDouble6& getStresses() { return this->stresses; }
+//   void setS11(double S11) { this->S11 = S11; }
+//   void setS12(double S12) { this->S12 = S12; }
+//   void setS22(double S22) { this->S22 = S22; }
+   double getArea() { return this->area; }
+   void setArea(double area) { this->area = area; }
+   void addArea(double area) { this->area += area; }
+
+   /**
+    * Returns a string representation of this 3D fe-point.
+    * @return a string representation of this 3D fe-point
+    */
+   std::string toString()
+   {
+      std::stringstream ss; 
+      ss<<"FePoint3D[";
+		ss<<"x1="<<this->x1;
+		ss<<", x2="<<this->x2;		
+		ss<<", x3="<<this->x3;		
+		ss<<", Fx="<<this->Fx;
+		ss<<", Fy="<<this->Fy;
+		ss<<", Fz="<<this->Fz<<"]";
+		return((ss.str()).c_str());
+   }
+   /*======================================================================*/
+};
+/*=========================================================================*/
+#endif
+
+
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FeRing3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/fem/FeRing3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8b30959432d1003324ba4070aaba3679b926f346
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FeRing3D.cpp
@@ -0,0 +1,468 @@
+#include <numerics/geometry3d/fem/FeRing3D.h>    
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/fem/FePoint3D.h>                    
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+using namespace std;
+
+/*=======================================================*/
+ObObjectCreator* FeRing3D::getCreator()
+{
+   return NULL; //FeRing3DCreator::getInstance(); 
+}
+// Konstruktor
+/*==========================================================*/
+FeRing3D::FeRing3D()
+{
+   GbPoint3D* p1 = new GbPoint3D();
+   GbPoint3D* p2 = new GbPoint3D();
+   mLine = new GbLine3D(p1,p2);
+   this->mLine->addObserver(this);
+   inRadius = 0.0;
+   outRadius = 0.0;
+   ringType = FeRing3D::NOTPARALLELTOAXIS;
+}                                                   
+/*=======================================================*/
+FeRing3D::FeRing3D(FeRing3D* ring)
+{
+   inRadius     = ring->getInRadius();
+   outRadius    = ring->getOutRadius();
+   ringType     = ring->ringType;
+   mLine        = ring->getLine()->clone();
+
+   this->mLine->addObserver(this);
+}                                                   
+/*==========================================================*/
+FeRing3D::FeRing3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b, const double& inradius, const double& outradius)
+{
+   mLine = new GbLine3D;
+   mLine->setPoints( new GbPoint3D(min(x1a,x1b), min(x2a,x2b), min(x3a,x3b))
+	                 ,new GbPoint3D(max(x1a,x1b), max(x2a,x2b), max(x3a,x3b)));
+   this->mLine->addObserver(this);
+   this->inRadius = inradius;
+   this->outRadius = outradius;
+
+   this->initRingType();
+   if((this->ringType & NOTPARALLELTOAXIS)==NOTPARALLELTOAXIS) 
+      throw UbException("FeRing3D::FeRing3D - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}                                                            
+/*==========================================================*/
+FeRing3D::FeRing3D(GbPoint3D* p1, GbPoint3D* p2, const double& inradius, const double& outradius)
+{
+   this->inRadius = inradius;
+   this->outRadius = outradius;
+
+   mLine = new GbLine3D(p1,p2);
+   this->mLine->addObserver(this);
+   this->initRingType();
+   if((this->ringType & NOTPARALLELTOAXIS)==NOTPARALLELTOAXIS) 
+      throw UbException("FeRing3D::FeRing3D - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+FeRing3D::FeRing3D(GbLine3D* line, const double& inradius, const double& outradius)
+{
+   this->inRadius = inradius;
+   this->outRadius = outradius;
+
+   this->mLine = line;
+   this->mLine->addObserver(this);
+   this->initRingType();
+   if((this->ringType & NOTPARALLELTOAXIS)==NOTPARALLELTOAXIS) 
+      throw UbException("FeRing3D::FeRing3D - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/		
+// Destruktor
+FeRing3D::~FeRing3D()
+{
+   if(mLine) this->mLine->removeObserver(this);
+   mLine = NULL;
+}
+/*=======================================================*/
+void FeRing3D::initRingType()
+{
+   double x1a = mLine->getPoint1()->x1;    double x1b = mLine->getPoint2()->x1;
+   double x2a = mLine->getPoint1()->x2;    double x2b = mLine->getPoint2()->x2;
+   double x3a = mLine->getPoint1()->x3;    double x3b = mLine->getPoint2()->x3;
+   
+   if     (x1a!=x1b && x2a==x2b && x3a==x3b)  this->ringType = X1PARALLEL; 
+   else if(x2a!=x2b && x1a==x1b && x3a==x3b)  this->ringType = X2PARALLEL; 
+   else if(x3a!=x3b && x1a==x1b && x2a==x2b)  this->ringType = X3PARALLEL; 
+   else                                       this->ringType = NOTPARALLELTOAXIS;
+}
+/*=======================================================*/
+void FeRing3D::finalize() 
+{ 
+   if(this->mLine) 
+   {
+      mLine->finalize();
+      delete mLine; 
+      mLine=NULL;
+   } 
+}
+/*=======================================================*/
+double FeRing3D::getHeight()
+{
+   if(mLine) return mLine->getLength(); return 0.0; 
+}
+/*=======================================================*/
+GbPoint3D* FeRing3D::getPoint1()
+{
+   if(this->mLine) return this->mLine->getPoint1();
+   return NULL;
+}
+/*=======================================================*/
+GbPoint3D* FeRing3D::getPoint2()
+{
+   if(this->mLine) return this->mLine->getPoint2();
+   return NULL;
+}
+/*=======================================================*/
+void FeRing3D::setInRadius(const double& radius) 
+{ 
+   this->inRadius = std::fabs(radius); 
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void FeRing3D::setOutRadius(const double& radius) 
+{ 
+   this->outRadius = std::fabs(radius); 
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void FeRing3D::setLine(GbLine3D* line) 
+{
+   if(this->mLine) this->mLine->removeObserver(this);
+   this->mLine = line;  
+   this->mLine->addObserver(this);
+   this->initRingType();
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void FeRing3D::setPoint1(const double& x1, const double& x2, const double& x3)
+{ 
+   if(!mLine->getPoint1()) throw UbException("FeRing3D::setPoint1() - line has no point1");
+   mLine->getPoint1()->setCoordinates(x1,x2,x3);
+   this->initRingType();
+
+   //this->notifyObserversObjectChanged(); //wird automatisch aufgerufen, da der point (this) benachrichtigt...
+}
+/*=======================================================*/
+void FeRing3D::setPoint2(const double& x1, const double& x2, const double& x3)
+{ 
+   if(!mLine->getPoint2()) throw UbException("FeRing3D::setPoint1() - line has no point2");
+   mLine->getPoint2()->setCoordinates(x1,x2,x3);
+   this->initRingType();
+
+   //this->notifyObserversObjectChanged(); //wird automatisch aufgerufen, da der point (this) benachrichtigt...
+}
+/*==========================================================*/		
+double FeRing3D::getX1Centroid()  
+{
+   return mLine->getX1Centroid();
+}
+/*==========================================================*/
+double FeRing3D::getX1Minimum()   
+{
+   if     (this->isParallelToX1Axis()) return mLine->getX1Minimum(); 
+   else if(this->isParallelToX2Axis()) return mLine->getX1Centroid()-outRadius; 
+   else if(this->isParallelToX3Axis()) return mLine->getX1Centroid()-outRadius; 
+   else throw UbException(__FILE__, __LINE__, "FeRing3D::getX3Minimum - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+double FeRing3D::getX1Maximum()   
+{
+   if     (this->isParallelToX1Axis()) return mLine->getX1Maximum(); 
+   else if(this->isParallelToX2Axis()) return mLine->getX1Centroid()+outRadius; 
+   else if(this->isParallelToX3Axis()) return mLine->getX1Centroid()+outRadius; 
+   else throw UbException(__FILE__, __LINE__, "FeRing3D::getX3Maximum - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+double FeRing3D::getX2Centroid()
+{
+   return mLine->getX2Centroid();
+}
+/*==========================================================*/
+double FeRing3D::getX2Minimum()   
+{
+   if     (this->isParallelToX1Axis()) return mLine->getX2Centroid()-outRadius;
+   else if(this->isParallelToX2Axis()) return mLine->getX2Minimum();
+   else if(this->isParallelToX3Axis()) return mLine->getX2Centroid()-outRadius; 
+   else throw UbException(__FILE__, __LINE__, "FeRing3D::getX3Minimum - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}	
+/*==========================================================*/
+double FeRing3D::getX2Maximum()   
+{
+   if     (this->isParallelToX1Axis())  return mLine->getX2Centroid()+outRadius;
+   else if(this->isParallelToX2Axis())  return mLine->getX2Maximum();
+   else if(this->isParallelToX3Axis())  return mLine->getX2Centroid()+outRadius; 
+   else throw UbException(__FILE__, __LINE__, "FeRing3D::getX3Maximum - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+double FeRing3D::getX3Centroid()
+{
+   return mLine->getX3Centroid();
+}
+/*==========================================================*/
+double FeRing3D::getX3Minimum()   
+{	
+   if     (this->isParallelToX1Axis()) return mLine->getX3Centroid()-outRadius;
+   else if(this->isParallelToX2Axis()) return mLine->getX3Centroid()-outRadius; 
+   else if(this->isParallelToX3Axis()) return mLine->getX3Minimum(); 
+   else throw UbException(__FILE__, __LINE__, "FeRing3D::getX3Minimum - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}	
+/*==========================================================*/
+double FeRing3D::getX3Maximum()   
+{
+   if     (this->isParallelToX1Axis()) return mLine->getX3Centroid()+outRadius;
+   else if(this->isParallelToX2Axis()) return mLine->getX3Centroid()+outRadius; 
+   else if(this->isParallelToX3Axis()) return mLine->getX3Maximum(); 
+   else throw UbException(__FILE__, __LINE__, "FeRing3D::getX3Maximum - derzeit nur zu Achsen orthogonale Cylinder erlaubt... isPointInObject3D funzt sonst ned");
+}
+/*==========================================================*/
+bool FeRing3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   throw UbException(__FILE__,__LINE__,"FeRing3D function not implemented");
+
+}
+/*==========================================================*/
+bool FeRing3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   throw UbException(__FILE__,__LINE__,"FeRing3D function not implemented");
+}
+/*=======================================================*/
+bool FeRing3D::isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   throw UbException(__FILE__,__LINE__,"FeRing3D function not implemented");
+}
+
+/*==========================================================*/
+string FeRing3D::toString() 
+{
+	stringstream ss;
+	ss<<"FeRing3D[";
+	ss<<"line="<<this->mLine->toString();
+   ss<<", inRadius="<<this->inRadius;
+   ss<<", outRadius="<<this->outRadius;
+   ss<<"]";
+   return(ss.str());
+}
+/*==========================================================*/
+bool FeRing3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   throw UbException(__FILE__,__LINE__,"FeRing3D function not implemented");
+}
+/*==========================================================*/
+bool FeRing3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   throw UbException(__FILE__,__LINE__,"FeRing3D function not implemented");
+}
+/*==========================================================*/
+GbLine3D* FeRing3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(__FILE__,__LINE__,"FeRing3D function not implemented");
+}
+/*==========================================================*/
+vector<GbTriangle3D*> FeRing3D::getSurfaceTriangleSet()
+{
+   double x1ma,x1mb,x2m,x3m;
+   if( this->isParallelToX1Axis() ) 
+   {
+      x1ma = this->getX1Minimum();
+      x1mb = this->getX1Maximum();
+      x2m  = this->getX2Centroid();
+      x3m  = this->getX3Centroid();
+   }
+   else if( this->isParallelToX2Axis() ) 
+   {
+      x1ma = this->getX2Minimum();
+      x1mb = this->getX2Maximum();
+      x2m  = this->getX1Centroid();
+      x3m  = this->getX3Centroid();
+   }
+   else if( this->isParallelToX3Axis() ) 
+   {
+      x1ma = this->getX3Minimum();
+      x1mb = this->getX3Maximum();
+      x2m  = this->getX2Centroid();
+      x3m  = this->getX1Centroid();
+   }
+   else throw UbException(__FILE__, __LINE__, "FeRing3D::getSurfaceTriangleSet() - ring not axis prallel");
+   
+   vector<GbTriangle3D*> triangles;    
+
+   int segmentsCircle  = 14;
+   double deltaPhi = UbMath::PI/(double)segmentsCircle;
+
+   double phiX1a,phiX1b;
+   double x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+   double x2aa,x3aa,x2bb,x3bb;
+   
+   double dXCylinder =  fabs((x1mb-x1ma)); // /(double)segmentsCircle;
+   int segmentsCylinder = (int)(fabs(x1mb-x1ma)/dXCylinder);
+   for(int segCyl = 0; segCyl<segmentsCylinder; segCyl++)
+   {
+      x1a = x1d = x1ma+segCyl*dXCylinder;
+      x1b = x1c = x1a+dXCylinder;
+      
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+         
+         x2a =  x2m+this->outRadius*std::sin(phiX1a);
+         x3a =  x3m+this->outRadius*std::cos(phiX1a);
+         x2b =  x2m+this->outRadius*std::sin(phiX1b);
+         x3b =  x3m+this->outRadius*std::cos(phiX1b);
+
+         x2aa =  x2m+this->inRadius*std::sin(phiX1a);
+         x3aa =  x3m+this->inRadius*std::cos(phiX1a);
+         x2bb =  x2m+this->inRadius*std::sin(phiX1b);
+         x3bb =  x3m+this->inRadius*std::cos(phiX1b);
+         
+         if( this->isParallelToX1Axis() ) 
+         { 
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1b,x2a,x3a),new FePoint3D(x1b,x2b,x3b),new FePoint3D(x1a,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1a,x2b,x3b),new FePoint3D(x1a,x2a,x3a),new FePoint3D(x1b,x2b,x3b))); 
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1b,x2bb,x3bb),new FePoint3D(x1b,x2aa,x3aa),new FePoint3D(x1a,x2aa,x3aa)));
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1a,x2aa,x3aa),new FePoint3D(x1a,x2bb,x3bb),new FePoint3D(x1b,x2bb,x3bb))); 
+         }
+         else if( this->isParallelToX2Axis() ) 
+         { 
+            throw UbException(__FILE__,__LINE__," sollte man mal machen");
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x2b,x1b,x3b),new FePoint3D(x2a,x1b,x3a),new FePoint3D(x2a,x1a,x3a)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x2a,x1a,x3a),new FePoint3D(x2b,x1a,x3b),new FePoint3D(x2b,x1b,x3b))); 
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x2bb,x1b,x3bb),new FePoint3D(x2aa,x1b,x3aa),new FePoint3D(x2aa,x1a,x3aa)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x2aa,x1a,x3aa),new FePoint3D(x2bb,x1a,x3bb),new FePoint3D(x2bb,x1b,x3bb))); 
+         }
+         else if( this->isParallelToX3Axis() ) 
+         { 
+            throw UbException(__FILE__,__LINE__," sollte man mal machen");
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x3b,x2b,x1b),new FePoint3D(x3a,x2a,x1b),new FePoint3D(x3a,x2a,x1a)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x3a,x2a,x1a),new FePoint3D(x3b,x2b,x1a),new FePoint3D(x3b,x2b,x1b))); 
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x3bb,x2bb,x1b),new FePoint3D(x3aa,x2aa,x1b),new FePoint3D(x3aa,x2aa,x1a)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x3aa,x2aa,x1a),new FePoint3D(x3bb,x2bb,x1a),new FePoint3D(x3bb,x2bb,x1b))); 
+         }
+
+      }
+   }
+   
+   //int segmentsSide = (int)(this->outRadius/dXCylinder);
+
+   double radius0, radius1;
+   //for(int segCyl = 10; segCyl<segmentsSide; segCyl++)
+   //{
+      radius0 = inRadius;//segCyl*dXCylinder;
+      radius1 = outRadius;//radius0+dXCylinder;
+      //if(segCyl==segmentsSide-1) radius1=outRadius;
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  x2m+radius0*std::sin(phiX1a);
+         x3a =  x3m+radius0*std::cos(phiX1a);
+         x2b =  x2m+radius0*std::sin(phiX1b);
+         x3b =  x3m+radius0*std::cos(phiX1b);
+         x2c =  x2m+radius1*std::sin(phiX1b);
+         x3c =  x3m+radius1*std::cos(phiX1b);
+         x2d =  x2m+radius1*std::sin(phiX1a);
+         x3d =  x3m+radius1*std::cos(phiX1a);
+
+         if( this->isParallelToX1Axis() ) 
+         { 
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1ma,x2b,x3b),new FePoint3D(x1ma,x2a,x3a),new FePoint3D(x1ma,x2c,x3c)));
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1ma,x2d,x3d),new FePoint3D(x1ma,x2c,x3c),new FePoint3D(x1ma,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1mb,x2b,x3b),new FePoint3D(x1mb,x2c,x3c),new FePoint3D(x1mb,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new FePoint3D(x1mb,x2d,x3d),new FePoint3D(x1mb,x2a,x3a),new FePoint3D(x1mb,x2c,x3c)));
+         }                                                                   
+         else if( this->isParallelToX2Axis() ) 
+         { 
+            throw UbException(__FILE__,__LINE__," sollte man mal machen");
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x2a,x1ma,x3a),new FePoint3D(x2b,x1ma,x3b),new FePoint3D(x2c,x1ma,x3c)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x2c,x1ma,x3c),new FePoint3D(x2d,x1ma,x3d),new FePoint3D(x2a,x1ma,x3a)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x2c,x1mb,x3c),new FePoint3D(x2b,x1mb,x3b),new FePoint3D(x2a,x1mb,x3a)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x2a,x1mb,x3a),new FePoint3D(x2d,x1mb,x3d),new FePoint3D(x2c,x1mb,x3c)));
+         }
+         else if( this->isParallelToX3Axis() ) 
+         { 
+            throw UbException(__FILE__,__LINE__," sollte man mal machen");
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x3a,x2a,x1ma),new FePoint3D(x3b,x2b,x1ma),new FePoint3D(x3c,x2c,x1ma)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x3c,x2c,x1ma),new FePoint3D(x3d,x2d,x1ma),new FePoint3D(x3a,x2a,x1ma)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x3c,x2c,x1mb),new FePoint3D(x3b,x2b,x1mb),new FePoint3D(x3a,x2a,x1mb)));
+            //triangles.push_back(new GbTriangle3D(new FePoint3D(x3a,x2a,x1mb),new FePoint3D(x3d,x2d,x1mb),new FePoint3D(x3c,x2c,x1mb)));
+         }
+      }
+  // }
+
+   return triangles;
+}
+/*==========================================================*/
+void FeRing3D::objectChanged(UbObservable* changedObject)
+{
+   GbLine3D* line = dynamic_cast<GbLine3D*>(changedObject);
+   if(!line || this->mLine!=line) return;
+
+   this->notifyObserversObjectChanged();
+}
+/*==========================================================*/
+void FeRing3D::objectWillBeDeleted(UbObservable* objectForDeletion)
+{
+   if(this->mLine)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->mLine);
+      if(objectForDeletion == observedObj) { this->mLine = NULL; }
+   }
+}
+/*=======================================================*/
+void FeRing3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{  
+   if( this->isParallelToX1Axis() )
+   {
+      if(!UbMath::equal(sx2,sx3)) throw UbException("FeRing3D::scale - || to x1 -> different scaling sx2 and sx3 not possible");
+      this->inRadius*=sx2;
+      this->outRadius*=sx2;
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      if(!UbMath::equal(sx1,sx3)) throw UbException("FeRing3D::scale - || to x2 -> different scaling sx1 and sx3 not possible");
+      this->inRadius*=sx1;
+      this->outRadius*=sx1;
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      if(!UbMath::equal(sx1,sx2)) throw UbException("FeRing3D::scale - || to x3 -> different scaling sx1 and sx2 not possible");
+      this->inRadius*=sx1;
+      this->outRadius*=sx1;
+   }
+   else throw UbException("FeRing3D::scale - unknown direction");
+
+   this->mLine->scale(sx1,sx2,sx3);
+   //notify observer wird automatisch aufgerufen
+}
+/*==========================================================*/
+void FeRing3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   mLine->write(out);
+   out->writeDouble(inRadius);
+   out->writeDouble(outRadius);
+   out->writeInteger(ringType);
+}
+/*==========================================================*/
+void FeRing3D::read(UbFileInput* in) 
+{  
+   in->readString();                                    
+   mLine = new GbLine3D;
+   mLine->read(in);
+   inRadius  = in->readDouble();
+   outRadius = in->readDouble();
+   ringType  = in->readInteger();
+}
+/*==========================================================*/
+double FeRing3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   throw UbException(__FILE__,__LINE__,"FeRing3D function not implemented");
+}
+/*==========================================================*/
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FeRing3D.h b/source/ThirdParty/Library/numerics/geometry3d/fem/FeRing3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2d45f5339ff7028d03be9b97ad6cd45fc026a32
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FeRing3D.h
@@ -0,0 +1,107 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef FERING3D_H
+#define FERING3D_H
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <basics/utilities/UbObserver.h>
+
+class GbPoint3D;
+class GbLine3D;
+class GbTriangle3D;
+
+class GbObject3DCreator;
+
+class FeRing3D : public GbObject3D , public UbObserver 
+{
+public:
+   FeRing3D();
+	FeRing3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b, const double& inradius, const double& outradius);
+	FeRing3D(GbPoint3D* p1, GbPoint3D* p2, const double& inradius, const double& outradius);
+	FeRing3D(GbLine3D* line, const double& inradius, const double& outradius);
+	FeRing3D(FeRing3D* ring);
+	~FeRing3D();    
+
+	FeRing3D* clone() { return new FeRing3D(this); }
+	void finalize();
+
+	double     getInRadius() { return this->inRadius; };
+   double     getOutRadius() { return this->outRadius; };
+	GbLine3D*  getLine() {return mLine;}
+	GbPoint3D* getPoint1();
+	GbPoint3D* getPoint2();
+
+	void setInRadius(const double& radius);
+   void setOutRadius(const double& radius);
+	void setLine(GbLine3D* line);
+	void setPoint1(const double& x1, const double& x2, const double& x3);
+	void setPoint2(const double& x1, const double& x2, const double& x3);
+
+	bool isParallelToX1Axis() { return((this->ringType & X1PARALLEL        )    ==  X1PARALLEL        );}
+	bool isParallelToX2Axis() { return((this->ringType & X2PARALLEL        )    ==  X2PARALLEL        );}
+	bool isParallelToX3Axis() { return((this->ringType & X3PARALLEL        )    ==  X3PARALLEL        );}
+	bool isNotParallelToAxis(){ return((this->ringType & NOTPARALLELTOAXIS )    ==  NOTPARALLELTOAXIS );}
+
+	double getHeight(); 
+
+	void scale(const double& sx1, const double& sx2, const double& sx3);
+
+	double getX1Centroid();
+	double getX1Minimum() ;
+	double getX1Maximum() ;
+	double getX2Centroid();
+	double getX2Minimum() ;
+	double getX2Maximum() ;
+	double getX3Centroid();
+	double getX3Minimum() ;
+	double getX3Maximum() ;
+
+	bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); 
+	bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary); 
+   bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+	GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+   
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+	std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   
+	std::string toString();
+	ObObjectCreator* getCreator();
+	void write(UbFileOutput* out);
+	void read(UbFileInput* in);
+
+	//virtuelle Methoden von UbObserver
+	void objectChanged(UbObservable* changedObject);
+	void objectWillBeDeleted(UbObservable* objectForDeletion);
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+protected:
+	void initRingType();
+
+   GbLine3D* mLine;
+	double    inRadius;
+   double    outRadius;
+
+	int ringType;
+
+	//void berechneQuerschnittsWerte();
+   static const int NOTPARALLELTOAXIS  = (1<<0); //1
+   static const int X1PARALLEL         = (1<<1); //2
+   static const int X2PARALLEL         = (1<<2); //4
+   static const int X3PARALLEL         = (1<<3); //8
+};
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FeTriFaceMesh3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/fem/FeTriFaceMesh3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5b0a7835f0459609c15b7fa6bba7713dc800c16
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FeTriFaceMesh3D.cpp
@@ -0,0 +1,256 @@
+#include <numerics/geometry3d/fem/FeTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+
+using namespace std;
+
+FeTriFaceMesh3D::FeTriFaceMesh3D():GbTriFaceMesh3D()
+{
+   this->attributes = new vector<VertexAttributes>;
+//   this->createVertexTriFaceMap();
+}
+/*====================================================*/
+FeTriFaceMesh3D::FeTriFaceMesh3D(std::string name, std::vector<Vertex>* nodes, std::vector<TriFace>* triangles):GbTriFaceMesh3D(name,nodes,triangles)
+{
+   this->attributes = new vector<VertexAttributes>;
+   this->attributes->resize(nodes->size());
+//   this->createVertexTriFaceMap();
+}
+/*======================================================================*/
+ObObjectCreator* FeTriFaceMesh3D::getCreator()
+{
+   return FeTriFaceMesh3DCreator::getInstance();
+}
+/*====================================================*/
+void FeTriFaceMesh3D::resizeAttributes()
+{
+   this->attributes->resize(nodes->size());
+}
+/*====================================================*/
+//void FeTriFaceMesh3D::createVertexTriFaceMap()
+//{
+//   vertexTriFaceMap.clear();
+//   vector<TriFace>& tris = *this->triangles;
+//   vector<Vertex>&  pts  = *this->nodes;
+//
+//   for(size_t t=0; t<tris.size(); t++)
+//   {
+//      TriFace& tri = tris[t];
+//      Vertex& vert1 = pts[tri.v1];
+//      Vertex& vert2 = pts[tri.v2];
+//      Vertex& vert3 = pts[tri.v3];
+//      vertexTriFaceMap.setVertexTriFaceRelation(&vert1,&tri);
+//      vertexTriFaceMap.setVertexTriFaceRelation(&vert2,&tri);
+//      vertexTriFaceMap.setVertexTriFaceRelation(&vert3,&tri);
+//   }
+//}
+/*====================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3D::createMeshByTriangles(std::string name, std::vector<GbTriangle3D*> *triangles)
+{
+   vector<GbTriFaceMesh3D::Vertex>    *nodes = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *tris  = new vector<GbTriFaceMesh3D::TriFace>;
+   int nr=0;
+   for(int u=0;u<(int)triangles->size();u++)
+   {
+      if(UbMath::zero((*triangles)[u]->getArea())) continue;
+
+      GbPoint3D* p1 = (*triangles)[u]->getPoint1();
+      GbPoint3D* p2 = (*triangles)[u]->getPoint2();
+      GbPoint3D* p3 = (*triangles)[u]->getPoint3();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)p1->getX1Coordinate(),(float)p1->getX2Coordinate(),(float)p1->getX3Coordinate()));
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)p2->getX1Coordinate(),(float)p2->getX2Coordinate(),(float)p2->getX3Coordinate()));
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)p3->getX1Coordinate(),(float)p3->getX2Coordinate(),(float)p3->getX3Coordinate()));
+      tris->push_back(GbTriFaceMesh3D::TriFace(nr,nr+1,nr+2));
+      nr+=3;
+   }
+   FeTriFaceMesh3D* triMesh = new FeTriFaceMesh3D(name, nodes, tris);
+   triMesh->deleteRedundantNodes();
+   triMesh->resizeAttributes();
+   return triMesh;
+}
+
+/*======================================================================*/
+UbTuple<string,string> FeTriFaceMesh3D::writeMesh(string filename, WbWriter* writer, bool writeNormals, std::vector< std::string >* datanames, std::vector< std::vector < double > >* nodedata)
+{
+   if(datanames || nodedata)
+   {
+      UBLOG(logWARNING,"FeTriFaceMesh3D::writeMesh - no support for extra datanames || nodedata");
+   }
+
+   UBLOG2(logDEBUG1,std::cout,"FeTriFaceMesh3D::writeMesh - start");
+
+   UbTuple<string,string> filenames;
+
+   if( dynamic_cast<WbWriterVtkXmlBinary*>(writer) || dynamic_cast<WbWriterVtkXmlASCII*>(writer))
+   {
+      vector< UbTupleFloat3 > triNodes( nodes->size() );
+      vector< UbTupleInt3   > tris( triangles->size() );
+
+      for(size_t i=0; i<nodes->size(); i++)
+         triNodes[i] = makeUbTuple( (*nodes)[i].x, (*nodes)[i].y, (*nodes)[i].z );
+
+      for(size_t i=0; i<triangles->size(); i++)
+         tris[i] = makeUbTuple( (*triangles)[i].v1, (*triangles)[i].v2, (*triangles)[i].v3 ) ;
+
+      vector<string> localDataNames;
+      localDataNames.push_back("Fx"      );		
+      localDataNames.push_back("Fy"      );		
+      localDataNames.push_back("Fz"      );		
+      localDataNames.push_back("sumFx"   );		
+      localDataNames.push_back("sumFy"   );		
+      localDataNames.push_back("sumFz"   );		
+      localDataNames.push_back("vx"      );		
+      localDataNames.push_back("vy"      );		
+      localDataNames.push_back("vz"      );		
+      localDataNames.push_back("S1"      );		
+      localDataNames.push_back("S2"      );		
+      localDataNames.push_back("S3"      );		
+      localDataNames.push_back("S4"      );		
+      localDataNames.push_back("S5"      );		
+      localDataNames.push_back("S6"      );		
+      localDataNames.push_back("Pressure");		
+
+      std::vector< std::vector < double > > localNodedata( localDataNames.size(), std::vector<double>( nodes->size() ) );
+      for(size_t n=0; n<nodes->size(); n++)
+      {
+         FeTriFaceMesh3D::VertexAttributes& attribut = (*this->attributes)[n];
+
+         localNodedata[ 0][n] = attribut.getFX();
+         localNodedata[ 1][n] = attribut.getFY();
+         localNodedata[ 2][n] = attribut.getFZ();
+         localNodedata[ 3][n] = attribut.getSumFX();
+         localNodedata[ 4][n] = attribut.getSumFY();
+         localNodedata[ 5][n] = attribut.getSumFZ();
+         localNodedata[ 6][n] = attribut.getVelocityX();
+         localNodedata[ 7][n] = attribut.getVelocityY();
+         localNodedata[ 8][n] = attribut.getVelocityZ();
+         localNodedata[ 9][n] = val<1>(attribut.getStresses());
+         localNodedata[10][n] = val<2>(attribut.getStresses());
+         localNodedata[11][n] = val<3>(attribut.getStresses());
+         localNodedata[12][n] = val<4>(attribut.getStresses());
+         localNodedata[13][n] = val<5>(attribut.getStresses());
+         localNodedata[14][n] = val<6>(attribut.getStresses());
+         localNodedata[15][n] = attribut.getPressure();
+      }
+      val<1>(filenames) = writer->writeTrianglesWithNodeData(filename,triNodes,tris,localDataNames,localNodedata);
+   }
+   else
+   {
+      string avsfilename = filename+writer->getFileExtension();
+      val<1>(filenames)=avsfilename;
+
+      ofstream out(avsfilename.c_str(),ios::out);
+      if(!out)
+      { 
+         out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+         string path = UbSystem::getPathFromString(filename);
+         if(path.size()>0){UbSystem::makeDirectory(path);out.open(filename.c_str(),ios::out);}
+         if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden");
+      }
+
+      //cout<<"AvsASCII - writeLines to "<<avsfilename<<" ...";
+
+      int nofNodes = (int)nodes->size(); 
+      int nofTrian = (int)triangles->size(); 
+      int dataSize = 16;
+
+      out<<"# UCD-File created by WbWriterAvsASCII\n";
+      out<<nofNodes<<" "<<nofTrian<<" "<<dataSize<<" 0 0 "<<endl;
+
+      for(int i=0; i<nofNodes; i++)
+         out<<i+1<<" "<< (*nodes)[i].x<<" "<< (*nodes)[i].y<<" "<< (*nodes)[i].z<<" \n";
+
+      for(int i=0; i<nofTrian; i++)
+         out<<i+1<<" 2 tri "<<(*triangles)[i].v1+1<<" "<<(*triangles)[i].v2+1<<" "<<(*triangles)[i].v3+1<<" "<<endl;
+
+      out<<dataSize;	
+      for(int i=0;i<dataSize;i++) out<<" "<<1;
+      out<<endl;
+
+      out<<"Fx, no_unit"<<endl;		
+      out<<"Fy, no_unit"<<endl;		
+      out<<"Fz, no_unit"<<endl;		
+      out<<"sumFx, no_unit"<<endl;		
+      out<<"sumFy, no_unit"<<endl;		
+      out<<"sumFz, no_unit"<<endl;		
+      out<<"vx, no_unit"<<endl;		
+      out<<"vy, no_unit"<<endl;		
+      out<<"vz, no_unit"<<endl;		
+      out<<"S1, no_unit"<<endl;		
+      out<<"S2, no_unit"<<endl;		
+      out<<"S3, no_unit"<<endl;		
+      out<<"S4, no_unit"<<endl;		
+      out<<"S5, no_unit"<<endl;		
+      out<<"S6, no_unit"<<endl;		
+      out<<"Pressure, no_unit"<<endl;		
+
+      for(int n=0; n<nofNodes; n++)
+      {
+         FeTriFaceMesh3D::VertexAttributes& attribut = (*this->attributes)[n];
+
+         double Fx = attribut.getFX();
+         double Fy = attribut.getFY();
+         double Fz = attribut.getFZ();
+         double sumFx = attribut.getSumFX();
+         double sumFy = attribut.getSumFY();
+         double sumFz = attribut.getSumFZ();
+         double vx = attribut.getVelocityX();
+         double vy = attribut.getVelocityY();
+         double vz = attribut.getVelocityZ();
+         double p = attribut.getPressure();
+         UbTupleDouble6& stresses = attribut.getStresses();
+         out<<n+1<<" "<<Fx<<" "<<Fy<<" "<<Fz;
+         out<<" "<<sumFx<<" "<<sumFy<<" "<<sumFz;
+         out<<" "<<vx<<" "<<vy<<" "<<vz;
+         out<<" "<<val<1>(stresses)<<" "<<val<2>(stresses)<<" "<<val<3>(stresses);
+         out<<" "<<val<4>(stresses)<<" "<<val<5>(stresses)<<" "<<val<6>(stresses);
+         out<<" "<<p<<endl;
+      }
+      out.close();
+   }
+
+   if(writeNormals)
+   {
+      vector<UbTupleFloat3 > lineNodes(triangles->size()*2);
+      vector<UbTupleInt2 >   lines(triangles->size());
+      for(size_t i=0; i<triangles->size(); i++)
+      {
+         TriFace& triangle = (*triangles)[i];
+         lineNodes[i*2  ] = makeUbTuple( triangle.getX1Centroid(*nodes)
+                                        ,triangle.getX2Centroid(*nodes)
+                                        ,triangle.getX3Centroid(*nodes));
+         lineNodes[i*2+1] = makeUbTuple( (float)(triangle.getX1Centroid(*nodes)+triangle.nx)
+                                        ,(float)(triangle.getX2Centroid(*nodes)+triangle.ny)
+                                        ,(float)(triangle.getX3Centroid(*nodes)+triangle.nz));
+
+         lines[i] = makeUbTuple((int)i*2,(int)i*2+1);
+      }
+      val<2>(filenames) = writer->writeLines(filename+"_normals",lineNodes,lines);
+   }
+
+
+   if(writeNormals)
+   {
+      vector<UbTupleFloat3 > lineNodes(nodes->size()*2);
+      vector<UbTupleInt2 >   lines(nodes->size());
+      for(size_t i=0; i<nodes->size(); i++)
+      {
+   	    FeTriFaceMesh3D::VertexAttributes& attribut = (*this->attributes)[i];
+         lineNodes[i*2  ] = makeUbTuple((*nodes)[i].x, (*nodes)[i].y, (*nodes)[i].z );
+         lineNodes[i*2+1] = makeUbTuple((*nodes)[i].x+(float)attribut.getNormalX()
+                                       ,(*nodes)[i].y+(float)attribut.getNormalY()
+                                       ,(*nodes)[i].z+(float)attribut.getNormalZ());
+
+         lines[i] = makeUbTuple((int)i*2,(int)i*2+1);
+      }
+      writer->writeLines(filename+"_PointNormals",lineNodes,lines);
+   }
+
+   UBLOG2(logDEBUG1,std::cout,"FeTriFaceMesh3D::writeMesh - end");
+
+   return filenames;
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/FeTriFaceMesh3D.h b/source/ThirdParty/Library/numerics/geometry3d/fem/FeTriFaceMesh3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..ae05f674aaae03d1407b1ebe980f1a3455eebd00
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/FeTriFaceMesh3D.h
@@ -0,0 +1,204 @@
+#ifndef FETRIFACEMESH3D_H
+#define FETRIFACEMESH3D_H
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+#include <map>
+
+#include "./../GbTriFaceMesh3D.h"
+
+#ifdef CAB_RCF
+#include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+/*=========================================================================*/
+/* FeTriFaceMesh3D                                                                  */
+/*                                                                         */
+/**
+ * This Class provides the triangular meshes.
+ * Note, that up to now no methods for checking consistency are included.
+ * in this context this class describes facettes from an 3D-object !!!
+*/
+class FeTriFaceMesh3D : public GbTriFaceMesh3D
+{                             
+public:
+   class VertexAttributes
+   {
+   private:
+      double Fx;
+      double Fy;
+      double Fz;
+      double sumFx;
+      double sumFy;
+      double sumFz;
+      double velocityX;
+      double velocityY;
+      double velocityZ;
+      double normalX;
+      double normalY;
+      double normalZ;
+      UbTupleDouble6 stresses; 
+      double area;
+      double p; //pressure
+   public:
+      VertexAttributes()
+      {
+         this->init();
+      }
+      ~VertexAttributes() {}
+
+#ifdef CAB_RCF
+      template<class Archive>
+      void SF_SERIALIZE(Archive & ar)
+      {
+         ar & Fx; ar & Fy; ar & Fz;
+         ar & velocityX; ar & velocityY; ar & velocityZ;
+      }
+#endif //CAB_RCF
+
+      void init()
+      {
+         this->Fx         = 0.0;
+         this->Fy         = 0.0;
+         this->Fz         = 0.0;
+         this->sumFx      = 0.0;
+         this->sumFy      = 0.0;
+         this->sumFz      = 0.0;
+         val<1>(stresses) = 0.0;
+         val<2>(stresses) = 0.0;
+         val<3>(stresses) = 0.0;
+         val<4>(stresses) = 0.0;
+         val<5>(stresses) = 0.0;
+         val<6>(stresses) = 0.0;
+         this->area       = 0.0;
+         this->p = 0.0;
+         this->velocityX  = 0.0;
+         this->velocityY  = 0.0;
+         this->velocityZ  = 0.0;
+         this->normalX  = 0.0;
+         this->normalY  = 0.0;
+         this->normalZ  = 0.0;
+      }
+      double getVelocityX()         { return this->velocityX; }
+      double getVelocityY()         { return this->velocityY; }
+      double getVelocityZ()         { return this->velocityZ; }
+      void   setVelocityX(double x) { this->velocityX = x;    }
+      void   setVelocityY(double y) { this->velocityY = y;    }
+      void   setVelocityZ(double z) { this->velocityZ = z;    }
+
+      double getNormalX()         { return this->normalX; }
+      double getNormalY()         { return this->normalY; }
+      double getNormalZ()         { return this->normalZ; }
+      void   setNormalX(double x) { this->normalX = x;    }
+      void   setNormalY(double y) { this->normalY = y;    }
+      void   setNormalZ(double z) { this->normalZ = z;    }
+
+      double getFX()          { return this->Fx; }
+      double getFY()          { return this->Fy; }
+      double getFZ()          { return this->Fz; }
+      void   setFX(double FX) { this->Fx = FX;   }
+      void   setFY(double FY) { this->Fy = FY;   }
+      void   setFZ(double FZ) { this->Fz = FZ;   }
+      void   addFX(double FX) { this->Fx += FX;  }
+      void   addFY(double FY) { this->Fy += FY;  }
+      void   addFZ(double FZ) { this->Fz += FZ;  }
+
+      double getSumFX()          { return this->sumFx; }
+      double getSumFY()          { return this->sumFy; }
+      double getSumFZ()          { return this->sumFz; }
+      void   setSumFX(double FX) { this->sumFx = FX;   }
+      void   setSumFY(double FY) { this->sumFy = FY;   }
+      void   setSumFZ(double FZ) { this->sumFz = FZ;   }
+      void   addSumFX(double FX) { this->sumFx += FX;  }
+      void   addSumFY(double FY) { this->sumFy += FY;  }
+      void   addSumFZ(double FZ) { this->sumFz += FZ;  }
+
+      UbTupleDouble6& getStresses() { return this->stresses; }
+      
+      double getArea()            { return this->area;  }
+      void   setArea(double area) { this->area  = area; }
+      void   addArea(double area) { this->area += area; }
+
+      double getPressure()         { return this->p;  }
+      void   setPressure(double p) { this->p = p; }
+
+   };
+/*=========================================================================*/
+/*=========================================================================*/
+/*=========================================================================*/
+   //class VertexTriFaceMap : public std::multimap<Vertex*, TriFace*>
+   //{
+   //public:
+   //   VertexTriFaceMap()  {}
+   //   /*=========================================================================*/
+   //   void setVertexTriFaceRelation(Vertex* v, TriFace* tri)
+   //   {
+   //      this->insert(std::pair<Vertex*,TriFace*>(v,tri));
+   //   }
+   //   /*=========================================================================*/
+   //   int getNumberOfTriFaces(Vertex* v)
+   //   {  
+   //      return((int)this->count(v));
+   //   }
+   //   /*=========================================================================*/
+   //   std::vector<TriFace*> getTriFacesForVertex(Vertex* v)
+   //   {
+   //      std::vector<TriFace*> trivector;
+   //      unsigned number = (unsigned)this->count(v);
+   //      std::multimap<Vertex*,TriFace*>::iterator mapIterator = this->find(v);
+   //      for(unsigned u =0; u<number; u++) 
+   //      {
+   //         trivector.push_back(mapIterator->second);
+   //         mapIterator ++;
+   //      }
+   //      return trivector;
+   //   }
+   //   //void deleteNeighbors(QtInteractor* interactor);
+   //   ///*=========================================================================*/
+   //};
+/*=========================================================================*/
+/*=========================================================================*/
+/*=========================================================================*/
+public:
+   //#ifndef SWIG
+   //VertexTriFaceMap vertexTriFaceMap;
+   //#endif
+
+   FeTriFaceMesh3D();
+   FeTriFaceMesh3D(std::string name, std::vector<Vertex>* nodes, std::vector<TriFace>* triangles);
+
+   std::vector<VertexAttributes>* getAttributes() { return this->attributes; }
+   void resizeAttributes();
+   //void createVertexTriFaceMap();
+
+   UbTuple<std::string,std::string> writeMesh(std::string filename, WbWriter* writer, bool writeNormals=false, std::vector< std::string >* datanames=NULL, std::vector< std::vector < double > >* nodedata=NULL);
+
+   static FeTriFaceMesh3D* createMeshByTriangles(std::string name, std::vector<GbTriangle3D*>* triangles);
+
+   virtual ObObjectCreator* getCreator();
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbTriFaceMesh3D>(ar, *this);
+      ar & attributes;
+      //if( ArchiveTools::isReading(ar) ) this->createVertexTriFaceMap();
+   }
+#endif //CAB_RCF
+
+
+protected:
+   std::vector<VertexAttributes>* attributes;
+   
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<FeTriFaceMesh3D  >("FeTriFaceMesh3D  ")     , SF_FeTriFaceMesh3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbTriFaceMesh3D, FeTriFaceMesh3D >() ), SF_FeTriFaceMesh3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, FeTriFaceMesh3D >() ), SF_FeTriFaceMesh3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+#endif //FETRIFACEMESH3D_H
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/creator/CMakePackage.txt b/source/ThirdParty/Library/numerics/geometry3d/fem/creator/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de1dc5a88225180b8e40c6cf46f4a6fbb102778f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/creator/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
\ No newline at end of file
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.cpp b/source/ThirdParty/Library/numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4e47547ad966b0de03f5590c45995cca7e983eaf
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.cpp
@@ -0,0 +1,417 @@
+#include <numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/utilities/UbTiming.h>
+
+using namespace std;
+
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromFile(string filename, string meshName, bool removeRedundantNodes)
+{
+   if(meshName.empty())
+   {
+      size_t pos=filename.rfind("/");
+      if(pos!=string::npos) meshName = filename.substr(pos+1);
+      else                  meshName = filename;
+   }
+
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   string ext=stlfile.getFileExtension();
+
+   //in "kleinbuchstaben" umwandeln
+   transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int))tolower); //(int(*)(int)) ist irgendso ein fieser cast, weil tolower ne alte c-methode ist
+
+   if     ( !ext.compare("ply") ) return FeTriFaceMesh3DCreator::readMeshFromPLYFile(filename, meshName, removeRedundantNodes);
+   else if( !ext.compare("stl") ) return FeTriFaceMesh3DCreator::readMeshFromSTLFile(filename, meshName, removeRedundantNodes);
+   else if( !ext.compare("inp") ) return FeTriFaceMesh3DCreator::readMeshFromAVSFile(filename, meshName, removeRedundantNodes);
+   //else if( !ext.compare("gts") ) return FeTriFaceMesh3DCreator::readMeshFromGTSFile(filename, meshName);
+   //else if( !ext.compare("raw") ) return FeTriFaceMesh3DCreator::readMeshFromRAWFile(filename, meshName);
+   else throw UbException(UB_EXARGS,"fileformat "+ext);
+
+   return NULL;
+}
+/*======================================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromPLYFile(string filename, string meshName, bool removeRedundantNodes)
+{
+   UbFileInputASCII plyfile(filename);
+   if(!plyfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return FeTriFaceMesh3DCreator::readMeshFromPLYFile(&plyfile,meshName);
+}
+/*======================================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromPLYFile(UbFileInput* in, string meshName, bool removeRedundantNodes)
+{
+   //cout<<"GbTriangularMesh3DFile.readMeshFromPLYFile !!! Dieses Format hat leider redundante Knoten ..."<<endl;
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+
+   float x, y, z;
+   string dummy;
+
+   int numVertices = in->readIntegerAfterString("element vertex");
+   int numFaces    = in->readIntegerAfterString("element face");
+   in->setPosAfterLineWithString("end_header");
+
+   UBLOG(logDEBUG1,"Number of vertices "<<numVertices);
+   UBLOG(logDEBUG1,"Number of faces    "<<numFaces);
+
+   nodes->resize(numVertices);
+   triangles->reserve(numFaces);
+
+   int onePercent = (int)UbMath::max(1,UbMath::integerRounding(numVertices*0.01));
+   for (int i=0; i<numVertices; i++)
+   {
+      if( i%onePercent==0 )
+         cout<<" - read vertices (#"<<numVertices<<") "<<UbMath::integerRounding(i/(double)numVertices*100.0)<<"% "<<"\r"<<flush;
+      x = in->readFloat();
+      y = in->readFloat();
+      z = in->readFloat();
+      in->readLine();
+      (*nodes)[i] = GbTriFaceMesh3D::Vertex(x,y,z);
+   }
+   UBLOG(logDEBUG1," - read vertices (#"<<numVertices<<") done");
+
+   int p,j,k,l,n;
+   onePercent = (int)UbMath::max(1,UbMath::integerRounding(numFaces*0.01));
+   for(int i=0; i<numFaces; i++)
+   {
+      if( i%onePercent==0 ) cout<<" - read faces (#"<<numFaces<<") "<<UbMath::integerRounding(i/(double)numFaces*100.0)<<"% "<<"\r"<<flush;
+
+      p = in->readInteger();
+      if(p==3)  //Dreieck, alles andere wird stumpf ingnoriert
+      {
+         j = in->readInteger();
+         k = in->readInteger();
+         l = in->readInteger();
+
+         if(   !UbMath::inClosedInterval(j,0,numVertices-1) 
+            || !UbMath::inClosedInterval(k,0,numVertices-1) 
+            || !UbMath::inClosedInterval(l,0,numVertices-1) ) 
+         {         
+            throw UbException(UB_EXARGS,"dreiecksindex ist groesser als max Knotenindex oder kleiner 0");
+         }
+         triangles->push_back(GbTriFaceMesh3D::TriFace(j,k,l));
+      }
+      else if(p==4)  //Viereck --> wird zu zwei Dreiecken!
+      {
+         j = in->readInteger();
+         k = in->readInteger();
+         l = in->readInteger();
+         n = in->readInteger();
+         numFaces++;
+         i++;
+
+         if(   !UbMath::inClosedInterval(j,0,numVertices-1) 
+            || !UbMath::inClosedInterval(k,0,numVertices-1) 
+            || !UbMath::inClosedInterval(l,0,numVertices-1) 
+            || !UbMath::inClosedInterval(n,0,numVertices-1) 
+            ) 
+         {         
+            throw UbException(UB_EXARGS,"vierecksindex ist groesser als max Knotenindex oder kleiner 0");
+         }
+         triangles->push_back(GbTriFaceMesh3D::TriFace(j,k,l));
+         triangles->push_back(GbTriFaceMesh3D::TriFace(l,n,j));
+      }
+
+      in->readLine();
+
+   }
+   UBLOG(logDEBUG1," - read faces (#"<<(int)triangles->size()<<", #nonTriangles="<<(int)triangles->size()-numFaces<<") done");
+
+   FeTriFaceMesh3D* mesh = new FeTriFaceMesh3D(meshName, nodes, triangles);
+   
+   if(removeRedundantNodes) mesh->deleteRedundantNodes();
+
+   mesh->resizeAttributes();
+   //mesh->createVertexTriFaceMap();
+   mesh->calculateValues();
+
+
+   return mesh;
+}
+/*======================================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromSTLFile(string filename, string meshName, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return FeTriFaceMesh3DCreator::readMeshFromSTLFile(&stlfile,meshName,removeRedundantNodes);
+}
+/*======================================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromSTLFile(UbFileInput *in, string meshName, bool removeRedundantNodes)
+{
+   UBLOG(logINFO,"FeTriFaceMesh3DCreator::readMeshFromSTLFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<FeTriFaceMesh3D::Vertex>    *nodes     = new vector<FeTriFaceMesh3D::Vertex>;
+   vector<FeTriFaceMesh3D::TriFace>   *triangles = new vector<FeTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   double x, y, z;
+   int nr=0;
+
+   in->readLine();
+   while(dummy!="endsolid")
+   {
+      in->readLine();
+      in->readLine();
+      dummy = in->readString();
+      if(dummy!="vertex") throw UbException(UB_EXARGS,"no vertex format");
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(FeTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in->readLine();
+      in->readString();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(FeTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in->readLine();
+      in->readString();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(FeTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      triangles->push_back(FeTriFaceMesh3D::TriFace(nr,nr+1,nr+2));
+      in->readLine();
+      in->readLine();
+      in->readLine();
+      dummy = in->readString();
+      nr+=3;
+   }
+
+
+   FeTriFaceMesh3D* mesh = new FeTriFaceMesh3D(meshName, nodes, triangles);
+   
+   if(removeRedundantNodes) mesh->deleteRedundantNodes();
+
+   mesh->resizeAttributes();
+//   mesh->createVertexTriFaceMap();
+   mesh->calculateValues();
+
+   
+   return mesh;
+}
+// /*======================================================================*/
+// FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromMeshFile(string filename, string meshName, bool removeRedundantNodes)
+// {
+//    public static void read(String file, ArrayList<Node3d> nodeList, ArrayList<TrianglePatch> patches) throws FileReaderException {
+// 
+//       UBLOG(logINFO,"FeTriFaceMesh3DCreator::readMeshFromSTLFile !!! Dieses Format hat leider redundante Knoten ...");
+// 
+//    vector<FeTriFaceMesh3D::Vertex>    *nodes     = new vector<FeTriFaceMesh3D::Vertex>;
+//    vector<FeTriFaceMesh3D::TriFace>   *triangles = new vector<FeTriFaceMesh3D::TriFace>;
+//    string dummy;
+// 
+//    double x, y, z;
+//    int nr=0;
+// 
+//    in->readLine();
+//    while(dummy!="endsolid")
+//    {
+//       in->readLine();
+//       in->readLine();
+//       dummy = in->readString();
+//       if(dummy!="vertex") throw UbException(UB_EXARGS,"no vertex format");
+//       x=in->readDouble();
+//       y=in->readDouble();
+//       z=in->readDouble();
+//       nodes->push_back(FeTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+//       in->readLine();
+//       in->readString();
+//       x=in->readDouble();
+//       y=in->readDouble();
+//       z=in->readDouble();
+//       nodes->push_back(FeTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+//       in->readLine();
+//       in->readString();
+//       x=in->readDouble();
+//       y=in->readDouble();
+//       z=in->readDouble();
+//       nodes->push_back(FeTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+//       triangles->push_back(FeTriFaceMesh3D::TriFace(nr,nr+1,nr+2));
+//       in->readLine();
+//       in->readLine();
+//       in->readLine();
+//       dummy = in->readString();
+//       nr+=3;
+//    }
+// 
+// 
+//    FeTriFaceMesh3D* mesh = new FeTriFaceMesh3D(meshName, nodes, triangles);
+// 
+//    if(removeRedundantNodes) mesh->deleteRedundantNodes();
+// 
+//    return mesh;
+// 
+// 
+//    try {
+// 
+//       FileInput input = new FileInput(file);
+// 
+//       int line = 0;
+//       while(true)
+//       { 
+//          if(line>1000) break;            
+//          if(input.readLine().contains("Vertices")) 
+//             break;              
+//          line++;
+//       }
+// 
+//       int num_of_points = input.readInt();
+// 
+//       for (int i = 0; i < num_of_points; i++) {               
+//          float x = (float) input.readDouble();
+//          float y = (float) input.readDouble();
+//          float z = (float) input.readDouble();
+//          int nr = input.readInt();
+//          nodeList.add(new Node3d(x, y, z));
+//       }
+// 
+//       input.skipLine();
+//       input.skipLine();
+//       int num_of_triangles = input.readInt();
+// 
+//       for (int i = 0; i < num_of_triangles; i++) {
+// 
+//          int a = input.readInt();
+//          int b = input.readInt();
+//          int c = input.readInt();
+//          int nr = input.readInt();
+// 
+//          Node3d P1 = nodeList.get(a - 1);
+//          Node3d P2 = nodeList.get(b - 1);
+//          Node3d P3 = nodeList.get(c - 1);
+// 
+//          patches.add(new TrianglePatch(P1, P2, P3));
+//       }
+// 
+//       // END reading mesh file
+//    }
+// 
+//    -- 
+// 
+//       Dipl.-Ing. Sebastian Bindick
+// 
+//       Institute for Computational Modeling in Civil Engineering (iRMB) Technische Universität Braunschweig Pockelsstr. 3 (9th Floor) D-38106, Braunschweig, Germany
+// 
+//       phone +49 531/391-7598
+//       fax   +49 531/391-7599
+//       email    bindick@irmb.tu-bs.de
+//       web  www.irmb.tu-bs.de
+// 
+// 
+/*======================================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromAVSFile(string filename, string meshName, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return FeTriFaceMesh3DCreator::readMeshFromAVSFile(&stlfile,meshName,removeRedundantNodes);
+}
+/*======================================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromAVSFile(UbFileInput *in, string meshName, bool removeRedundantNodes)
+{
+   UBLOG(logINFO,"FeTriFaceMesh3DCreator.readMeshFromAVSFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<FeTriFaceMesh3D::Vertex>    *nodes     = new vector<FeTriFaceMesh3D::Vertex>;
+   vector<FeTriFaceMesh3D::TriFace>   *triangles = new vector<FeTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   in->readLine();
+   int numberNodes = in->readInteger();
+   int numberTris  = in->readInteger();
+   in->readLine();
+
+   double x,y,z;
+   for(int u=0;u<numberNodes;u++)
+   {
+      in->readInteger();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      in->readLine();
+      nodes->push_back(FeTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+   }
+   int id1,id2,id3;
+   for(int u=0;u<numberTris;u++)
+   {
+      in->readInteger();
+      in->readInteger();
+      in->readString();
+      id1 = in->readInteger();
+      id2 = in->readInteger();
+      id3 = in->readInteger();
+      triangles->push_back(FeTriFaceMesh3D::TriFace(id1-1,id2-1,id3-1));
+   }
+
+   FeTriFaceMesh3D* mesh = new FeTriFaceMesh3D(meshName, nodes, triangles);
+   
+   if(removeRedundantNodes) mesh->deleteRedundantNodes();
+
+   mesh->resizeAttributes();
+//   mesh->createVertexTriFaceMap();
+   mesh->calculateValues();
+
+
+   return mesh;
+}
+/*======================================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return FeTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(&stlfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+FeTriFaceMesh3D* FeTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(UbFileInput *in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator.readMeshFromVTKASCIIFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+
+   in->readString();
+   int numberNodes = in->readInteger();
+   in->readLine();
+
+   double x,y,z;
+   for(int u=0;u<numberNodes;u++)
+   {
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+   }
+   in->readLine();
+   in->readString();
+   int numberTris  = in->readInteger();
+   in->readLine();
+   UBLOG(logDEBUG1,"numberTris:"<<numberTris);
+
+   int id1,id2,id3;
+   for(int u=0;u<numberTris;u++)
+   {
+      in->readInteger();
+      id1 = in->readInteger();
+      id2 = in->readInteger();
+      id3 = in->readInteger();
+      triangles->push_back(GbTriFaceMesh3D::TriFace(id1,id2,id3));
+      //cout<<u<<" - id1,id2,id3:"<<id1<<","<<id2<<","<<id3<<endl;
+   }
+   UBLOG(logDEBUG1,"Tris gelesen");
+
+   FeTriFaceMesh3D* mesh = new FeTriFaceMesh3D(meshName, nodes, triangles);
+
+   if(removeRedundantNodes) mesh->deleteRedundantNodes();
+   
+   mesh->resizeAttributes();
+//   mesh->createVertexTriFaceMap();
+   mesh->calculateValues();
+
+   UBLOG(logDEBUG1,"mesh erzeugt (with remove redundant nodes = "<< boolalpha <<removeRedundantNodes<<")");
+
+   return mesh;
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.h b/source/ThirdParty/Library/numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..43f25b99e1c08e188242e260bead0898896bb1e8
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.h
@@ -0,0 +1,82 @@
+#ifndef FETRIFACEMESH3DCREATOR_H
+#define FETRIFACEMESH3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/fem/FeTriFaceMesh3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+#ifdef CAB_QT 
+#include <qfiledialog.h>    
+#endif
+
+#ifdef CAB_VTK
+//#include <numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h>
+#endif
+
+class FeTriFaceMesh3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static FeTriFaceMesh3DCreator* getInstance()
+   {
+      static FeTriFaceMesh3DCreator instance;
+      return &instance;
+   }
+   static FeTriFaceMesh3D* readMeshFromFile(std::string filename, std::string meshName, bool removeRedundantNodes=true);
+
+   static FeTriFaceMesh3D* readMeshFromPLYFile(std::string filename, std::string meshName, bool removeRedundantNodes=true);
+   static FeTriFaceMesh3D* readMeshFromPLYFile(UbFileInput* in, std::string meshName, bool removeRedundantNodes=true);
+
+   static FeTriFaceMesh3D* readMeshFromSTLFile(std::string filename, std::string meshName, bool removeRedundantNodes=true); 
+   static FeTriFaceMesh3D* readMeshFromSTLFile(UbFileInput* in, std::string meshName, bool removeRedundantNodes=true);
+
+   static FeTriFaceMesh3D* readMeshFromAVSFile(std::string filename, std::string meshName, bool removeRedundantNodes=true); 
+   static FeTriFaceMesh3D* readMeshFromAVSFile(UbFileInput* in, std::string meshName, bool removeRedundantNodes=true);
+
+   static FeTriFaceMesh3D* readMeshFromVTKASCIIFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true); 
+   static FeTriFaceMesh3D* readMeshFromVTKASCIIFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+
+   FeTriFaceMesh3D* createGbObject3D() { return new FeTriFaceMesh3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "FeTriFaceMesh3D"; };
+   std::string toString()           { return "FeTriFaceMesh3DCreator"; }
+
+#ifdef CAB_QT 
+
+
+   FeTriFaceMesh3D* createGbObject3DwithQt()
+   {
+	   //QString s = QFileDialog::getOpenFileName(NULL,NULL,NULL,"open file dialog","Choose a STL file" );
+	   QString s = QFileDialog::getOpenFileName(NULL, "Choose a STL file", "/home", "*.stl");
+      //QFileDialog* fd = new QFileDialog( NULL );
+      //fd->setIconText(QString("Hallo"));
+      //fd->show();
+      //TODO: Open File Dialog einbauen.		
+      UbFileInputASCII in( s.toAscii().data() );
+      stringstream stream;
+      stream <<"TriangularMesh3D ";//<<_objCount++;
+      FeTriFaceMesh3D *mesh = NULL;//FeTriFaceMesh3DCreator::readMeshFromSTLFile(&in, stream.str() );
+      return mesh;
+   }
+   //QDialog* getSpecificInstrument()  {  return 0;}
+   void editGbObject3DwithQt(GbObject3D* gbObj)
+   { 
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbTriangularMesh3D((GbTriangularMesh3D*)object); }
+#endif
+
+
+private:
+   FeTriFaceMesh3DCreator( const FeTriFaceMesh3DCreator& );                  //no copy allowed 
+   const FeTriFaceMesh3DCreator& operator=( const FeTriFaceMesh3DCreator& ); //no copy allowed
+   FeTriFaceMesh3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(FeTriFaceMesh3DCreator::getInstance()), CAB_FeTriFaceMesh3DCreator);
+#endif
+
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/CMakePackage.txt b/source/ThirdParty/Library/numerics/geometry3d/presentation/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..56dbc3800e73aec047b6d09d2e5957bfbf2ef3e3
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/CMakePackage.txt
@@ -0,0 +1,93 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_QT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
+
+#SET(SUBDIRPATH numerics/geometry3d/presentation) 
+#SET(OPTION_LABEL BUILD_GEOMETRY3DPRESENTATION)
+#
+#SET(CURRENT_DIR ${SOURCE_ROOT}/${SUBDIRPATH})
+#
+#IF(${WITH_SUBFOLDERS_FOR_SG} MATCHES YES)  
+#    STRING(REGEX REPLACE "/" "\\\\" SUBDIRPATH ${SUBDIRPATH})
+#ENDIF(${WITH_SUBFOLDERS_FOR_SG} MATCHES YES)
+#
+#OPTION(${OPTION_LABEL} "${CURRENT_DIR}" ON)
+#IF(${OPTION_LABEL})
+#
+#  SET(TEMP_FILES "")
+#  ################################################################
+#  ###             GET HEADER AND SOURCE FILES                  ###
+#  ################################################################
+#  FILE(GLOB HEADER_FILES ${CURRENT_DIR}/*.h  )
+#  FILE(GLOB CPP_FILES    ${CURRENT_DIR}/*.cpp)
+#  
+#  IF(NOT NEED_VTK)
+#    FILE(GLOB VTK_FILES ${CURRENT_DIR}/*vtk*  )
+#    REMOVE(HEADER_FILES ${VTK_FILES} )
+#    REMOVE(CPP_FILES    ${VTK_FILES} )
+#  ENDIF(NOT NEED_VTK)
+#
+#  SET(TEMP_FILES ${HEADER_FILES} ${CPP_FILES})
+#
+#  SOURCE_GROUP(${SUBDIRPATH} FILES ${TEMP_FILES})
+# 
+#  ################################################################
+#  ###             VTK STUFF                                    ###
+#  ################################################################
+#  
+##GANZ SICHER NICHT!!!!! -> bitte NEED_VTK im globalen CMakeLists.txt definieren
+##SET(NEED_VTK "TRUE")
+#
+#  ################################################################
+#  ###             Qt STUFF                                     ###
+#  ################################################################
+#  SET(NEED_QT "YES")
+#  INCLUDE(${SOURCE_ROOT}/CMakeQtMacros.txt)
+#  IF(QT_FOUND)
+#    ################################################################
+#    ###         Qt4      UI FILES                                ###
+#    ################################################################
+#    FILE(GLOB UI_FILES ${CURRENT_DIR}/*.ui)           #collect ui files
+#    QT4_WRAP_UI(${CURRENT_DIR} OUTFILES ${UI_FILES})  #wrap ui files
+#    REMOVE(TEMP_FILES ${OUTFILES} )
+#    SET(TEMP_FILES ${TEMP_FILES} ${OUTFILES} )
+#    
+#    #make subfolders for VS with new files
+#    SOURCE_GROUP(${SUBDIRPATH} FILES ${OUTFILES})
+#    
+#    IF(WIN32)
+#      SET(ALL_SOURCES ${ALL_SOURCES} ${UI_FILES})
+#      SOURCE_GROUP(${SUBDIRPATH} FILES ${UI_FILES})
+#    ENDIF(WIN32)
+#
+#    ################################################################
+#    ###       Qt4        HEADERS TO BE MOCED                     ###
+#    ################################################################
+#    MAKE_DIRECTORY(${CURRENT_DIR}${QTGEN_MOC})
+#    SET(HEADER_FILES_FOR_MOCCHECK ${HEADER_FILES})
+#    REMOVE(HEADER_FILES_FOR_MOCCHECK ${OUTFILES} ) #bereits durch QT4_WRAP_UI bearbeitete Header-files entferne
+#    QT4_GET_TOBEMOCED_HEADERS(MOC_CLASSES ${HEADER_FILES_FOR_MOCCHECK})
+#    IF(MOC_CLASSES)    
+#       SET(MOC_FILES ) #empty MOC_FILES
+#       QT4_WRAP_CPP(${CURRENT_DIR}${QTGEN_MOC} MOC_FILES ${MOC_CLASSES})
+#       REMOVE(TEMP_FILES ${MOC_FILES})
+#       SET(TEMP_FILES ${TEMP_FILES} ${MOC_FILES})
+#       SOURCE_GROUP(${SUBDIRPATH}${QTGEN_MOC} FILES ${MOC_FILES})
+#    ENDIF(MOC_CLASSES)
+#
+#    #MAKE_DIRECTORY(${CURRENT_DIR}${QTGEN_MOC})
+#    #SET(MOC_FILES ) #empty MOC_FILES
+#    #SET(MOC_CLASSES
+#    #        ${CURRENT_DIR}/QGbObject2DViewer.h
+#    #        ${CURRENT_DIR}/QGbObject2DMainWindow.h
+#    #    )
+#
+#    #QT4_WRAP_CPP(${CURRENT_DIR}${QTGEN_MOC} MOC_FILES ${MOC_CLASSES})
+#    #REMOVE(TEMP_FILES ${MOC_FILES})
+#    #SET(TEMP_FILES ${TEMP_FILES} ${MOC_FILES})
+#    #SOURCE_GROUP(${SUBDIRPATH}${QTGEN_MOC} FILES ${MOC_FILES})
+#
+#   ENDIF(QT_FOUND)
+#
+#  SET(ALL_SOURCES ${ALL_SOURCES} ${TEMP_FILES})
+#
+#ENDIF(${OPTION_LABEL})
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..81ea5bb168f179cdfc8837899e7cc6782907b137
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.cpp
@@ -0,0 +1,67 @@
+#include "./QGbCuboid3DInstrument.h"
+
+/**** Qt ****/
+#include <qlineedit.h>
+#include <qstring.h>
+#include <qcheckbox.h>
+
+/**** CAB ****/
+#include "./../GbCuboid3D.h"
+#include "./../GbPoint3D.h"
+
+
+QGbCuboid3DInstrument::QGbCuboid3DInstrument( QWidget* parent, Qt::WFlags flags ):QDialog(parent, flags)
+{
+	ui.setupUi(this);
+
+	this->gbCuboid = NULL;
+
+}
+
+QGbCuboid3DInstrument::~QGbCuboid3DInstrument()
+{
+}
+
+void QGbCuboid3DInstrument::setGbCuboid3D(GbCuboid3D* cuboid)
+{
+	this->gbCuboid = cuboid;
+	ui.lineEditPoint1X->setText( QString("%1").arg(gbCuboid->getPoint1()->getX1Coordinate() ) );
+	ui.lineEditPoint1Y->setText( QString("%1").arg(gbCuboid->getPoint1()->getX2Coordinate() ) );
+	ui.lineEditPoint1Z->setText( QString("%1").arg(gbCuboid->getPoint1()->getX3Coordinate() ) );
+	ui.lineEditPoint2X->setText( QString("%1").arg(gbCuboid->getPoint2()->getX1Coordinate() ) );
+	ui.lineEditPoint2Y->setText( QString("%1").arg(gbCuboid->getPoint2()->getX2Coordinate() ) );
+	ui.lineEditPoint2Z->setText( QString("%1").arg(gbCuboid->getPoint2()->getX3Coordinate() ) );
+	//this->checkBoxActive->setChecked( cuboid->isActive() );
+	ui.checkBoxActive->setChecked( true );
+}
+
+GbCuboid3D* QGbCuboid3DInstrument::getGbCuboid3D()
+{
+	return this->gbCuboid;
+}
+
+//void QGbCuboid3DInstrument::SetGbObject3D(GbObject3D* gbObj)
+//{
+//		this->SetGbSphere(dynamic_cast<GbSphere3D*>(gbObj));
+//}
+
+void QGbCuboid3DInstrument::on_pBtnOK_clicked()
+{
+	this->gbCuboid->getPoint1()->setX1(ui.lineEditPoint1X->text().toDouble() );
+	this->gbCuboid->getPoint1()->setX2(ui.lineEditPoint1Y->text().toDouble() );
+	this->gbCuboid->getPoint1()->setX3(ui.lineEditPoint1Z->text().toDouble() );
+	this->gbCuboid->getPoint2()->setX1(ui.lineEditPoint2X->text().toDouble() );
+	this->gbCuboid->getPoint2()->setX2(ui.lineEditPoint2Y->text().toDouble() );
+	this->gbCuboid->getPoint2()->setX3(ui.lineEditPoint2Z->text().toDouble() );
+	//this->gbCuboid->setActive( this->checkBoxActive->isChecked() );
+
+	this->gbCuboid->notifyObserversObjectChanged();
+	this->accept();
+}
+
+
+void QGbCuboid3DInstrument::on_pBtnCancel_clicked()
+{
+	this->reject();
+}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.h
new file mode 100644
index 0000000000000000000000000000000000000000..45555d457bc28da60c0107ae2491d1d95ffb0b69
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.h
@@ -0,0 +1,31 @@
+#ifndef QGBCUBOID3DINSTRUMENT_H
+#define QGBCUBOID3DINSTRUMENT_H
+
+
+#include "./QGbCuboid3DInstrumentUI.h"
+
+class GbCuboid3D;
+class GbObject3D;
+
+class QGbCuboid3DInstrument : public QDialog
+{
+	Q_OBJECT
+
+public:
+	QGbCuboid3DInstrument( QWidget* parent = 0, Qt::WFlags fl = 0 );
+	~QGbCuboid3DInstrument();
+	void setGbCuboid3D(GbCuboid3D* cuboid);        
+	GbCuboid3D* getGbCuboid3D();
+
+protected:
+	GbCuboid3D* gbCuboid;
+
+private:
+	Ui::QGbCuboid3DInstrument ui;
+
+private slots:
+	void on_pBtnOK_clicked();
+	void on_pBtnCancel_clicked();
+};
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.ui b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.ui
new file mode 100644
index 0000000000000000000000000000000000000000..e584634af9e5b0ac129a66f4ce105d5cba6e86ee
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCuboid3DInstrument.ui
@@ -0,0 +1,347 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QGbCuboid3DInstrument</class>
+ <widget class="QDialog" name="QGbCuboid3DInstrument" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>252</width>
+    <height>239</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>GbCuboid3DInstrument</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>10</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item row="0" column="0" >
+    <widget class="QLabel" name="textLabel2" >
+     <property name="font" >
+      <font>
+       <family>Arial</family>
+       <pointsize>20</pointsize>
+       <weight>50</weight>
+       <italic>false</italic>
+       <bold>false</bold>
+       <underline>false</underline>
+       <strikeout>false</strikeout>
+      </font>
+     </property>
+     <property name="text" >
+      <string>Cuboid</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="4" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="textLabelPoint1" >
+         <property name="font" >
+          <font>
+           <family>Arial</family>
+           <pointsize>10</pointsize>
+           <weight>50</weight>
+           <italic>false</italic>
+           <bold>false</bold>
+           <underline>false</underline>
+           <strikeout>false</strikeout>
+          </font>
+         </property>
+         <property name="text" >
+          <string>Point 1:</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel1" >
+           <property name="text" >
+            <string>X:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditPoint1X" >
+           <property name="text" >
+            <string>0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel1_2" >
+           <property name="text" >
+            <string>Y:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditPoint1Y" >
+           <property name="text" >
+            <string>0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel1_3" >
+           <property name="text" >
+            <string>Z:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditPoint1Z" >
+           <property name="text" >
+            <string>0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="textLabelPoint2" >
+         <property name="font" >
+          <font>
+           <family>Arial</family>
+           <pointsize>10</pointsize>
+           <weight>50</weight>
+           <italic>false</italic>
+           <bold>false</bold>
+           <underline>false</underline>
+           <strikeout>false</strikeout>
+          </font>
+         </property>
+         <property name="text" >
+          <string>Point 2:</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel1_4" >
+           <property name="text" >
+            <string>X:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditPoint2X" >
+           <property name="text" >
+            <string>0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel1_2_2" >
+           <property name="text" >
+            <string>Y:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditPoint2Y" >
+           <property name="text" >
+            <string>0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel1_3_2" >
+           <property name="text" >
+            <string>Z:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditPoint2Z" >
+           <property name="text" >
+            <string>0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item row="0" column="2" colspan="2" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>90</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="4" column="0" >
+    <widget class="QPushButton" name="pBtnOK" >
+     <property name="text" >
+      <string>OK</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="3" >
+    <widget class="QPushButton" name="pBtnCancel" >
+     <property name="text" >
+      <string>Cancel</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="2" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>13</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="2" column="3" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="2" column="0" colspan="3" >
+    <widget class="QCheckBox" name="checkBoxActive" >
+     <property name="text" >
+      <string>Active</string>
+     </property>
+     <property name="checked" >
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="1" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a1cff7b94a1653db8ade52e20b43943a7a84d5b
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.cpp
@@ -0,0 +1,102 @@
+#include "./QGbCylinder3DInstrument.h"
+
+/**** Qt ****/
+#include <QtCore/QString>
+#include <QtGui/QLineEdit>
+#include <QtGui/QCheckBox>
+#include <QtGui/QTabWidget>
+
+/**** CAB ****/
+#include "./../GbCylinder3D.h"
+#include "./../GbPoint3D.h"
+
+QGbCylinder3DInstrument::QGbCylinder3DInstrument( QWidget* parent, Qt::WFlags flags )
+{
+	ui.setupUi(this);
+   
+   /*JZ TODO daher Buttons noch ausgeschaltet (29.11.05)*/
+   ui.rBtnXAxis->setEnabled(false);
+   ui.rBtnYAxis->setEnabled(false);
+   ui.rBtnZAxis->setEnabled(false);
+	
+   this->gbCylinder = NULL;
+}
+
+QGbCylinder3DInstrument::~QGbCylinder3DInstrument(void)
+{
+}
+
+void QGbCylinder3DInstrument::setGbCylinder3D(GbCylinder3D* cylinder)
+{
+   this->gbCylinder = cylinder;
+   ui.lineEdit1_X_1->setText( QString("%1").arg(gbCylinder->getPoint1()->x1 ) );
+   ui.lineEdit1_Y_1->setText( QString("%1").arg(gbCylinder->getPoint1()->x2 ) );
+   ui.lineEdit1_Z_1->setText( QString("%1").arg(gbCylinder->getPoint1()->x3 ) );
+   ui.lineEdit1_X_2->setText( QString("%1").arg(gbCylinder->getPoint2()->x1 ) );
+   ui.lineEdit1_Y_2->setText( QString("%1").arg(gbCylinder->getPoint2()->x2 ) );
+   ui.lineEdit1_Z_2->setText( QString("%1").arg(gbCylinder->getPoint2()->x3 ) );
+   ui.dSpBoxRadius1->setValue(gbCylinder->getRadius());
+   ui.checkBoxActive1->setChecked( true );
+   ui.lineEdit2_X->setText( QString("%1").arg(gbCylinder->getPoint1()->x1 ) );
+   ui.lineEdit2_Y->setText( QString("%1").arg(gbCylinder->getPoint1()->x2 ) );
+   ui.lineEdit2_Z->setText( QString("%1").arg(gbCylinder->getPoint1()->x3 ) );
+   ui.dSpBoxRadius2->setValue(gbCylinder->getRadius());
+   ui.checkBoxActive2->setChecked( true );
+   ui.lineEditLength->setText( QString("%1").arg(gbCylinder->getHeight()) );
+   //if (!this->gbCylinder->isParallelToX1Axis()) 
+   //{
+   //   if (!this->gbCylinder->isParallelToX2Axis()) 
+   //   {
+   //      ui.rBtnZAxis->setChecked(true);
+   //   }
+   //   else ui.rBtnYAxis->setChecked(true);
+   //}
+   //else ui.rBtnXAxis->setChecked(true);
+}
+
+GbCylinder3D* QGbCylinder3DInstrument::getGbCylinder3D(void)
+{
+	return this->gbCylinder;
+}
+
+//void QGbSphere3DInstrument::SetGbObject3D(GbObject3D* gbObj)
+//{
+//		this->SetGbSphere(dynamic_cast<GbSphere3D*>(gbObj));
+//}
+
+void QGbCylinder3DInstrument::on_pBtnOK_clicked()
+{
+   if(ui.tabWidget->currentIndex()==0)
+   {
+      this->gbCylinder->setPoint1(  ui.lineEdit1_X_1->text().toDouble(),
+                                    ui.lineEdit1_Y_1->text().toDouble(),
+                                    ui.lineEdit1_Z_1->text().toDouble());
+     
+      this->gbCylinder->setPoint2(  ui.lineEdit1_X_2->text().toDouble(),
+                                    ui.lineEdit1_Y_2->text().toDouble(),
+                                    ui.lineEdit1_Z_2->text().toDouble());
+      this->gbCylinder->setRadius(ui.dSpBoxRadius1->value());
+
+      this->gbCylinder->notifyObserversObjectChanged();
+   }
+   if(ui.tabWidget->currentIndex()==1)
+   {
+      this->gbCylinder->setPoint1(  ui.lineEdit2_X->text().toDouble(),
+                                    ui.lineEdit2_Y->text().toDouble(),
+                                    ui.lineEdit2_Z->text().toDouble());
+      this->gbCylinder->setPoint2(  ui.lineEdit2_X->text().toDouble(),
+                                    ui.lineEdit2_Y->text().toDouble()+ui.lineEditLength->text().toDouble(),
+                                    ui.lineEdit2_Z->text().toDouble());
+      this->gbCylinder->setRadius(ui.dSpBoxRadius2->value());
+
+      this->gbCylinder->notifyObserversObjectChanged();
+   }
+
+   this->accept();
+}
+
+
+void QGbCylinder3DInstrument::on_pBtnCancel_clicked()
+{
+	this->reject();
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.h
new file mode 100644
index 0000000000000000000000000000000000000000..a22278cc427a3fcbf7104f9924a3d5c30fc38f5a
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.h
@@ -0,0 +1,35 @@
+#ifndef QGBCYLINDER3DINSTRUMENT_H
+#define QGBCYLINDER3DINSTRUMENT_H
+
+#include <QtGui/QDialog>
+#include <QtGui/QWidget>
+
+#include "./QGbCylinder3DInstrumentUI.h"
+#include "./QGbObject3DInstrument.h"
+
+class GbCylinder3D;
+class GbObject3D;
+
+class QGbCylinder3DInstrument : public QDialog
+{
+
+   Q_OBJECT
+
+public:
+   QGbCylinder3DInstrument( QWidget* parent = 0, Qt::WFlags flags = 0 );
+   ~QGbCylinder3DInstrument();
+   void setGbCylinder3D(GbCylinder3D* cylinder);
+   GbCylinder3D* getGbCylinder3D();
+
+protected:
+   GbCylinder3D* gbCylinder;
+
+private:
+   Ui::QGbCylinder3DInstrument ui;
+
+private slots:
+   void on_pBtnOK_clicked();
+   void on_pBtnCancel_clicked();
+};
+
+#endif
\ No newline at end of file
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.ui b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.ui
new file mode 100644
index 0000000000000000000000000000000000000000..18f74c5767165ca2f6621611bda9f26c7d630a27
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbCylinder3DInstrument.ui
@@ -0,0 +1,682 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QGbCylinder3DInstrument</class>
+ <widget class="QDialog" name="QGbCylinder3DInstrument" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>457</width>
+    <height>347</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>GbCylinder3DInstrument</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>8</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item row="1" column="0" >
+    <widget class="QTabWidget" name="tabWidget" >
+     <widget class="QWidget" name="tabPoints" >
+      <attribute name="title" >
+       <string>Define by Points</string>
+      </attribute>
+      <layout class="QGridLayout" >
+       <property name="margin" >
+        <number>8</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item row="0" column="0" >
+        <widget class="QGroupBox" name="groupBox" >
+         <property name="title" >
+          <string>Base Centerpoint</string>
+         </property>
+         <layout class="QGridLayout" >
+          <property name="margin" >
+           <number>8</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item row="2" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_3_2" >
+              <property name="text" >
+               <string>Z:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit1_Z_1" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="1" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_2_3" >
+              <property name="text" >
+               <string>Y:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit1_Y_1" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_5" >
+              <property name="text" >
+               <string>X:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit1_X_1" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="0" column="1" >
+        <widget class="QGroupBox" name="groupBox_2" >
+         <property name="title" >
+          <string>Top Centerpoint</string>
+         </property>
+         <layout class="QGridLayout" >
+          <property name="margin" >
+           <number>8</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item row="2" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_3_3_2_2" >
+              <property name="text" >
+               <string>Z:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit1_Z_2" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="1" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_2_2_2_2" >
+              <property name="text" >
+               <string>Y:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit1_Y_2" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_4_2_2" >
+              <property name="text" >
+               <string>X:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit1_X_2" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="1" column="0" colspan="2" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QCheckBox" name="checkBoxActive1" >
+           <property name="text" >
+            <string>Active</string>
+           </property>
+           <property name="checked" >
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" >
+            <size>
+             <width>51</width>
+             <height>60</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBox_3_2" >
+           <property name="minimumSize" >
+            <size>
+             <width>16</width>
+             <height>60</height>
+            </size>
+           </property>
+           <property name="title" >
+            <string>Radius</string>
+           </property>
+           <layout class="QGridLayout" >
+            <property name="margin" >
+             <number>8</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item row="0" column="1" >
+             <widget class="QDoubleSpinBox" name="dSpBoxRadius1" >
+              <property name="decimals" >
+               <number>1</number>
+              </property>
+              <property name="maximum" >
+               <double>100</double>
+              </property>
+              <property name="value" >
+               <double>3</double>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tabLength" >
+      <attribute name="title" >
+       <string>Define by Length</string>
+      </attribute>
+      <layout class="QGridLayout" >
+       <property name="margin" >
+        <number>8</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item row="0" column="1" >
+        <widget class="QGroupBox" name="groupBox_5" >
+         <property name="title" >
+          <string>Parameters</string>
+         </property>
+         <layout class="QGridLayout" >
+          <property name="margin" >
+           <number>8</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item row="2" column="0" colspan="2" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QRadioButton" name="rBtnXAxis" >
+              <property name="text" >
+               <string>X - Axis</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="rBtnYAxis" >
+              <property name="text" >
+               <string>Y - Axis</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="rBtnZAxis" >
+              <property name="text" >
+               <string>Z - Axis</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_5_2_2" >
+              <property name="text" >
+               <string>Length:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEditLength" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="1" column="0" >
+           <widget class="QLabel" name="label" >
+            <property name="text" >
+             <string>Parallel to</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+         <widget class="QWidget" name="widget_2" >
+          <property name="geometry" >
+           <rect>
+            <x>11</x>
+            <y>71</y>
+            <width>194</width>
+            <height>18</height>
+           </rect>
+          </property>
+         </widget>
+        </widget>
+       </item>
+       <item row="0" column="0" >
+        <widget class="QGroupBox" name="groupBox_4" >
+         <property name="title" >
+          <string>Base Centerpoint</string>
+         </property>
+         <layout class="QGridLayout" >
+          <property name="margin" >
+           <number>8</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item row="2" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_3_2_2" >
+              <property name="text" >
+               <string>Z:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit2_Z" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="1" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_2_3_2" >
+              <property name="text" >
+               <string>Y:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit2_Y" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="0" >
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_5_2" >
+              <property name="text" >
+               <string>X:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="lineEdit2_X" >
+              <property name="text" >
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="1" column="0" colspan="2" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QCheckBox" name="checkBoxActive2" >
+           <property name="text" >
+            <string>Active</string>
+           </property>
+           <property name="checked" >
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" >
+            <size>
+             <width>51</width>
+             <height>60</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="groupBox_3_2_2" >
+           <property name="minimumSize" >
+            <size>
+             <width>16</width>
+             <height>60</height>
+            </size>
+           </property>
+           <property name="title" >
+            <string>Radius</string>
+           </property>
+           <layout class="QGridLayout" >
+            <property name="margin" >
+             <number>8</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item row="0" column="1" >
+             <widget class="QDoubleSpinBox" name="dSpBoxRadius2" >
+              <property name="decimals" >
+               <number>1</number>
+              </property>
+              <property name="maximum" >
+               <double>100</double>
+              </property>
+              <property name="value" >
+               <double>3</double>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+      <widget class="QWidget" name="widget" >
+       <property name="geometry" >
+        <rect>
+         <x>9</x>
+         <y>9</y>
+         <width>415</width>
+         <height>101</height>
+        </rect>
+       </property>
+      </widget>
+     </widget>
+    </widget>
+   </item>
+   <item row="0" column="0" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="textLabel2" >
+       <property name="font" >
+        <font>
+         <family>Arial</family>
+         <pointsize>20</pointsize>
+         <weight>50</weight>
+         <italic>false</italic>
+         <bold>false</bold>
+         <underline>false</underline>
+         <strikeout>false</strikeout>
+        </font>
+       </property>
+       <property name="text" >
+        <string>Cylinder</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType" >
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item row="3" column="0" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="pBtnOK" >
+       <property name="text" >
+        <string>OK</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pBtnCancel" >
+       <property name="text" >
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="0" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <tabstops>
+  <tabstop>tabWidget</tabstop>
+  <tabstop>lineEdit1_X_1</tabstop>
+  <tabstop>lineEdit1_X_2</tabstop>
+  <tabstop>lineEdit1_Y_1</tabstop>
+  <tabstop>lineEdit1_Y_2</tabstop>
+  <tabstop>lineEdit1_Z_1</tabstop>
+  <tabstop>lineEdit1_Z_2</tabstop>
+  <tabstop>checkBoxActive1</tabstop>
+  <tabstop>dSpBoxRadius1</tabstop>
+  <tabstop>lineEdit2_X</tabstop>
+  <tabstop>lineEdit2_Y</tabstop>
+  <tabstop>lineEdit2_Z</tabstop>
+  <tabstop>lineEditLength</tabstop>
+  <tabstop>rBtnXAxis</tabstop>
+  <tabstop>rBtnYAxis</tabstop>
+  <tabstop>rBtnZAxis</tabstop>
+  <tabstop>checkBoxActive2</tabstop>
+  <tabstop>dSpBoxRadius2</tabstop>
+  <tabstop>pBtnOK</tabstop>
+  <tabstop>pBtnCancel</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d873fd905cf9a7c9b34210601168c0b4089dd1c
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.cpp
@@ -0,0 +1,66 @@
+#include "./QGbObject3DInstrument.h"
+
+/**** Qt ****/
+#include <qlineedit.h>
+
+/**** vtk ****/
+#include "./../GbObject3D.h"
+#include "./../../../basics/utilities/UbMath.h"
+
+//#define PI   3.14159265358979323846
+
+QGbObject3DInstrument::QGbObject3DInstrument( QWidget* parent, Qt::WFlags flags )
+{
+	ui.setupUi(this);
+
+	this->gbObject3D = NULL;
+}
+
+QGbObject3DInstrument::~QGbObject3DInstrument()
+{
+}
+
+void QGbObject3DInstrument::setGbObject3D(GbObject3D* obj)
+{                               
+	this->gbObject3D = obj;
+}
+
+GbObject3D* QGbObject3DInstrument::getGbObject3D()
+{
+	return this->gbObject3D;
+}
+
+void QGbObject3DInstrument::on_pBtnOK_clicked()
+{
+	double rx = ui.lineEditRotationX->text().toDouble();
+	double ry = ui.lineEditRotationY->text().toDouble();
+	double rz = ui.lineEditRotationZ->text().toDouble();
+
+	rx *= UbMath::PI /180;     
+	ry *= UbMath::PI /180;
+	rz *= UbMath::PI /180;
+
+	if ( rx != 0.0 || ry != 0.0 || rz != 0.0 ) this->gbObject3D->rotate(rx, ry, rz);
+
+	double sx = ui.lineEditScalingX->text().toDouble();
+	double sy = ui.lineEditScalingY->text().toDouble();
+	double sz = ui.lineEditScalingZ->text().toDouble();
+
+	if ( sx != 0.0 || sy != 0.0 || sz != 0.0 ) this->gbObject3D->scale(sx, sy, sz);
+
+	double x = ui.lineEditTranlationX->text().toDouble();
+	double y = ui.lineEditTranlationY->text().toDouble();
+	double z = ui.lineEditTranlationZ->text().toDouble();
+
+	if ( x != 0.0 || y != 0.0 || z != 0.0 ) this->gbObject3D->translate(x, y, z);
+
+	this->gbObject3D->notifyObserversObjectChanged();
+
+	this->accept();
+}
+
+
+void QGbObject3DInstrument::on_pBtnCancel_clicked()
+{
+	this->reject();
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.h
new file mode 100644
index 0000000000000000000000000000000000000000..6165be7237f8eb83653a6c1089fc661859231ce0
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.h
@@ -0,0 +1,30 @@
+#ifndef QGBOBJECT3DINSTRUMENT_H
+#define QGBOBJECT3DINSTRUMENT_H
+
+#include <QDialog>
+#include "./QGbObject3DInstrumentUI.h"
+
+
+class GbObject3D;
+
+class QGbObject3DInstrument : public QDialog
+{
+	Q_OBJECT
+
+public:
+	QGbObject3DInstrument( QWidget* parent = 0, Qt::WFlags flags = 0 );
+	~QGbObject3DInstrument();
+	void setGbObject3D(GbObject3D* gbObject);           
+	GbObject3D* getGbObject3D();
+
+protected:
+	GbObject3D *gbObject3D;
+
+private:
+	Ui::QGbObject3DInstrument ui;
+
+private slots:
+	void on_pBtnOK_clicked();
+	void on_pBtnCancel_clicked();
+};
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.ui b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.ui
new file mode 100644
index 0000000000000000000000000000000000000000..2fb6f96a9432533a5d7af0e71f3fcc6cbc5caf8a
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbObject3DInstrument.ui
@@ -0,0 +1,512 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QGbObject3DInstrument</class>
+ <widget class="QDialog" name="QGbObject3DInstrument" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>391</width>
+    <height>167</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>GeneralModifyInstrument</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>10</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item row="2" column="1" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="pBtnOK" >
+       <property name="text" >
+        <string>OK</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pBtnCancel" >
+       <property name="text" >
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="2" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="2" column="0" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="1" column="1" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>16</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="0" column="0" colspan="3" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <layout class="QGridLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item row="0" column="0" >
+        <widget class="QLabel" name="textLabel1" >
+         <property name="font" >
+          <font>
+           <family>Tahoma</family>
+           <pointsize>10</pointsize>
+           <weight>50</weight>
+           <italic>false</italic>
+           <bold>false</bold>
+           <underline>false</underline>
+           <strikeout>false</strikeout>
+          </font>
+         </property>
+         <property name="text" >
+          <string>Translation:</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2_2_2" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>Z:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditTranlationZ" >
+           <property name="text" >
+            <string>0.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="1" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>X:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditTranlationX" >
+           <property name="text" >
+            <string>0.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="2" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2_2" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>Y:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditTranlationY" >
+           <property name="text" >
+            <string>0.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QGridLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item row="0" column="0" >
+        <widget class="QLabel" name="textLabel1_2" >
+         <property name="font" >
+          <font>
+           <family>Tahoma</family>
+           <pointsize>10</pointsize>
+           <weight>50</weight>
+           <italic>false</italic>
+           <bold>false</bold>
+           <underline>false</underline>
+           <strikeout>false</strikeout>
+          </font>
+         </property>
+         <property name="text" >
+          <string>Rotation:</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2_2_2_2" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>Z:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditRotationZ" >
+           <property name="text" >
+            <string>0.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="1" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2_3" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>X:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditRotationX" >
+           <property name="text" >
+            <string>0.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="2" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2_2_3" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>Y:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditRotationY" >
+           <property name="text" >
+            <string>0.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QGridLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item row="0" column="0" >
+        <widget class="QLabel" name="textLabel1_2_2" >
+         <property name="font" >
+          <font>
+           <family>Tahoma</family>
+           <pointsize>10</pointsize>
+           <weight>50</weight>
+           <italic>false</italic>
+           <bold>false</bold>
+           <underline>false</underline>
+           <strikeout>false</strikeout>
+          </font>
+         </property>
+         <property name="text" >
+          <string>Scaling:</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2_2_2_2_2" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>Z:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditScalingZ" >
+           <property name="text" >
+            <string>1.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="1" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2_3_2" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>X:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditScalingX" >
+           <property name="text" >
+            <string>1.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="2" column="0" >
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="textLabel2_2_3_2" >
+           <property name="font" >
+            <font>
+             <family>Tahoma</family>
+             <pointsize>10</pointsize>
+             <weight>50</weight>
+             <italic>false</italic>
+             <bold>false</bold>
+             <underline>false</underline>
+             <strikeout>false</strikeout>
+            </font>
+           </property>
+           <property name="text" >
+            <string>Y:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditScalingY" >
+           <property name="text" >
+            <string>1.0</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fdc1c6078a2ad3c59ae695e069d1440a6c9cf7b3
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.cpp
@@ -0,0 +1,60 @@
+#include "./QGbSphere3DInstrument.h"
+
+/**** Qt ****/
+#include <qlineedit.h>
+#include <qstring.h>
+#include <qcheckbox.h>
+
+/**** CAB ****/
+#include "./../GbSphere3D.h"
+
+QGbSphere3DInstrument::QGbSphere3DInstrument( QWidget* parent, Qt::WFlags flags ):QDialog(parent,flags)
+{
+
+	ui.setupUi(this);
+   
+	this->gbSphere = NULL;
+}
+
+QGbSphere3DInstrument::~QGbSphere3DInstrument(void)
+{
+}
+
+void QGbSphere3DInstrument::setGbSphere3D(GbSphere3D* sphere)
+{
+	this->gbSphere = sphere;
+	ui.lineEditX->setText( QString("%1").arg(gbSphere->getX1Centroid() ) );
+	ui.lineEditY->setText( QString("%1").arg(gbSphere->getX2Centroid() ) );
+	ui.lineEditZ->setText( QString("%1").arg(gbSphere->getX3Centroid() ) );
+   ui.lineEditName->setText( QString(gbSphere->getName().c_str()) );
+	ui.lineEditRadius->setText( QString("%1").arg(gbSphere->getRadius() ) );
+	ui.checkBoxActive->setChecked( true );
+}
+
+GbSphere3D* QGbSphere3DInstrument::getGbSphere3D(void)
+{
+	return this->gbSphere;
+}
+
+//void QGbSphere3DInstrument::SetGbObject3D(GbObject3D* gbObj)
+//{
+//		this->SetGbSphere(dynamic_cast<GbSphere3D*>(gbObj));
+//}
+
+void QGbSphere3DInstrument::on_pBtnOK_clicked()
+{
+	this->gbSphere->setCenterX1Coordinate(ui.lineEditX->text().toDouble());
+	this->gbSphere->setCenterX2Coordinate(ui.lineEditY->text().toDouble());
+	this->gbSphere->setCenterX3Coordinate(ui.lineEditZ->text().toDouble());
+	this->gbSphere->setRadius(ui.lineEditRadius->text().toDouble());
+   this->gbSphere->setName(ui.lineEditName->text().toStdString());
+	//this->gbSphere->setActive( this->checkBoxActive->isChecked() );
+	this->gbSphere->notifyObserversObjectChanged();
+	this->accept();
+}
+
+
+void QGbSphere3DInstrument::on_pBtnCancel_clicked()
+{
+	this->reject();
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.h
new file mode 100644
index 0000000000000000000000000000000000000000..95bb56b3ad635234df26c856c1404826c5239e1a
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.h
@@ -0,0 +1,36 @@
+#ifndef QGBSPHERE3DINSTRUMENT_H
+#define QGBSPHERE3DINSTRUMENT_H
+
+#include <QtGui/QDialog>
+#include <QtGui/QWidget>
+
+#include "./QGbSphere3DInstrumentUI.h"
+#include "./QGbObject3DInstrument.h"
+
+class GbSphere3D;
+class GbObject3D;
+
+
+class QGbSphere3DInstrument : public QDialog
+{
+	Q_OBJECT
+
+public:
+	QGbSphere3DInstrument( QWidget* parent = 0, Qt::WFlags flags = 0 );
+	~QGbSphere3DInstrument();
+	void setGbSphere3D(GbSphere3D* sphere);     
+	GbSphere3D* getGbSphere3D();
+	//void SetGbObject3D(GbObject3D*);
+
+protected:
+	GbSphere3D* gbSphere;
+
+private:
+	Ui::QGbSphere3DInstrument ui;
+
+private slots:
+	void on_pBtnOK_clicked();
+	void on_pBtnCancel_clicked();
+};
+
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.ui b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.ui
new file mode 100644
index 0000000000000000000000000000000000000000..dced5d31c34f6a58ac6c1c9b235f975cbc542a2f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QGbSphere3DInstrument.ui
@@ -0,0 +1,303 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QGbSphere3DInstrument</class>
+ <widget class="QDialog" name="QGbSphere3DInstrument" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>426</width>
+    <height>180</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>GbSphere3DInstrument</string>
+  </property>
+  <widget class="QWidget" name="layoutWidget" >
+   <property name="geometry" >
+    <rect>
+     <x>10</x>
+     <y>50</y>
+     <width>406</width>
+     <height>82</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" >
+    <property name="margin" >
+     <number>0</number>
+    </property>
+    <property name="spacing" >
+     <number>6</number>
+    </property>
+    <item>
+     <layout class="QVBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <layout class="QHBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="textLabel1" >
+          <property name="text" >
+           <string>X:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEditX" >
+          <property name="text" >
+           <string>0</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="textLabel1_2" >
+          <property name="text" >
+           <string>Y:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEditY" >
+          <property name="text" >
+           <string>0</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="textLabel1_3" >
+          <property name="text" >
+           <string>Z:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEditZ" >
+          <property name="text" >
+           <string>0</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QVBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <layout class="QVBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="textLabel1_3_2" >
+            <property name="text" >
+             <string>Radius:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="lineEditRadius" >
+            <property name="text" >
+             <string>5</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="checkBoxActive" >
+        <property name="text" >
+         <string>Active</string>
+        </property>
+        <property name="checked" >
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer>
+        <property name="orientation" >
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType" >
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" >
+         <size>
+          <width>20</width>
+          <height>16</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="layoutWidget" >
+   <property name="geometry" >
+    <rect>
+     <x>10</x>
+     <y>144</y>
+     <width>401</width>
+     <height>28</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" >
+    <property name="margin" >
+     <number>0</number>
+    </property>
+    <property name="spacing" >
+     <number>6</number>
+    </property>
+    <item>
+     <widget class="QPushButton" name="pBtnOK" >
+      <property name="text" >
+       <string>OK</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <spacer>
+      <property name="orientation" >
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeType" >
+       <enum>QSizePolicy::Expanding</enum>
+      </property>
+      <property name="sizeHint" >
+       <size>
+        <width>132</width>
+        <height>16</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pBtnCancel" >
+      <property name="text" >
+       <string>Cancel</string>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="" >
+   <property name="geometry" >
+    <rect>
+     <x>12</x>
+     <y>12</y>
+     <width>401</width>
+     <height>35</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" >
+    <property name="margin" >
+     <number>0</number>
+    </property>
+    <property name="spacing" >
+     <number>6</number>
+    </property>
+    <item>
+     <widget class="QLabel" name="textLabel2" >
+      <property name="font" >
+       <font>
+        <family>Arial</family>
+        <pointsize>20</pointsize>
+        <weight>50</weight>
+        <italic>false</italic>
+        <bold>false</bold>
+        <underline>false</underline>
+        <strikeout>false</strikeout>
+       </font>
+      </property>
+      <property name="text" >
+       <string>Sphere</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <spacer>
+      <property name="orientation" >
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <property name="sizeType" >
+       <enum>QSizePolicy::Expanding</enum>
+      </property>
+      <property name="sizeHint" >
+       <size>
+        <width>101</width>
+        <height>33</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item>
+     <widget class="QLabel" name="textLabel1_3_3" >
+      <property name="text" >
+       <string>Name:</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QLineEdit" name="lineEditName" />
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QVTKGbObject3DViewer.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/QVTKGbObject3DViewer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ddd2d2e2277de467fef2204ce000aaa07cf7c04
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QVTKGbObject3DViewer.cpp
@@ -0,0 +1,35 @@
+#include "./QVTKGbObject3DViewer.h"
+
+/**** Qt ****/
+#include <qtabwidget.h>
+#include <qlabel.h>
+/**** vtk ****/
+
+#include <QVTKWidget.h>
+//#include "QvtkWindow.h"
+
+/**** CAB ****/
+#include "./../../../basics/utilities/UbMath.h"
+#include "./../GbObject3DManager.h"
+
+
+#include "./../../../userinterface/instrument/QManagerPresentatorInstrument.h"
+//#include "./QGbObject3DManagerInstrument.h"
+
+
+
+QVTKGbObject3DViewer::QVTKGbObject3DViewer():QVTKViewer3DApplication()
+{
+	//GbObjectManagerInstrument
+   this->gbObject3DManager = new GbObject3DManager();
+   QManagerPresentatorInstrument* gbObjManInst = new QManagerPresentatorInstrument(gbObject3DManager);
+	//gbObjManInst->setQViewer(this->getViewer());
+	
+	//Instrumente hinzufügen
+	this->addInstrument(gbObjManInst, "Geometries");
+}
+
+QVTKGbObject3DViewer::~QVTKGbObject3DViewer()
+{
+}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/QVTKGbObject3DViewer.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/QVTKGbObject3DViewer.h
new file mode 100644
index 0000000000000000000000000000000000000000..dc2e7ba4add517e22870cbcd097650338f267e0f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/QVTKGbObject3DViewer.h
@@ -0,0 +1,22 @@
+#ifndef QVTKGBOBJECT3DVIEWER_H
+#define QVTGBOBJECT3DKVIEWER_H
+
+#include "./../../../userinterface/viewer3d/QVTKViewer3DApplication.h"
+
+class QVTKWindow;
+class QVTKViewer3D;
+class GbObject3DManager;
+class OctNodeGridManager;
+
+class QVTKGbObject3DViewer : public QVTKViewer3DApplication
+{
+public:
+	QVTKGbObject3DViewer();
+	~QVTKGbObject3DViewer();
+   
+protected:
+
+	GbObject3DManager* gbObject3DManager;
+
+};
+#endif
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCuboid3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCuboid3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2b8f66a91310bab57f97509ead907aef21c3be25
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCuboid3D.cpp
@@ -0,0 +1,144 @@
+#include "./vtkGbCuboid3D.h"
+
+#include "./../GbCuboid3D.h"
+#include "./../../../userinterface/presentation/vtkEventCallbacks.h"
+
+#include "vtkCubeSource.h"
+#include "vtkPolyDataMapper.h"
+//#include "math.h"
+
+vtkGbCuboid3D::vtkGbCuboid3D(GbCuboid3D* gbObject)
+{
+	this->gbCuboid = gbObject;
+	this->gbCuboid->addObserver(this);
+
+   this->setName("vtkGbCuboid3D");
+
+	this->source = vtkCubeSource::New();
+   this->mapper = vtkPolyDataMapper::New();
+
+	this->setValues();
+
+	this->mapper->SetInput( this->source->GetOutput() );
+	this->actor->SetMapper( this->mapper );
+}
+
+vtkGbCuboid3D::~vtkGbCuboid3D(void)
+{
+   this->gbCuboid->removeObserver(this);
+	if (this->source) this->source->Delete();
+}
+
+//void vtkGbCuboid3D::ModifiedEventFired()
+//{
+//	//double a_orien[3];
+//	double a_pos[3];
+//	this->actor->GetPosition(a_pos);
+//	//this->actor->GetOrientation(a_orien);
+//	this->actor->SetPosition(0.0,0.0,0.0);
+//	this->actor->SetOrientation(0.0,0.0,0.0);
+//	this->actor->SetScale(1.0,1.0,1.0);
+//
+//	//cout<<"Orien:"<<a_orien[0]<<","<<a_orien[1]<<","<<a_orien[3]<<endl;
+//	//cout<<"Position:"<<a_pos[0]<<","<<a_pos[1]<<","<<a_pos[3]<<endl;
+//
+//	this->gbCuboid->translate(a_pos[0], a_pos[1], a_pos[2]);
+//	this->gbCuboid->notifyObserversObjectChanged();
+//}
+
+void vtkGbCuboid3D::applyActorModifications()
+{
+	if (isModified) 
+	{
+		double pos[3];
+		double scale[3];
+		//double orien[3];
+		this->actor->GetPosition(pos);
+		this->actor->GetScale(scale);
+		//this->actor->GetOrientation(orien);
+
+		this->actor->SetPosition(0.0,0.0,0.0);
+		this->actor->SetOrientation(0.0,0.0,0.0);
+		this->actor->SetScale(1.0,1.0,1.0);
+
+		//cout<<"Orien:"<<a_orien[0]<<","<<a_orien[1]<<","<<a_orien[3]<<endl;
+		//cout<<"Position:"<<a_pos[0]<<","<<a_pos[1]<<","<<a_pos[3]<<endl;
+
+
+		////////////////////////////////////////////////////////////////////////////
+		////Rotieren
+		////[Cy x1 + Sy x3, x2, -Sy x1 + Cy x3, 1]
+		//double center[3];
+		//center[0] = this->gbCuboid->getX1Centroid();
+		//center[1] = this->gbCuboid->getX2Centroid();
+		//center[2] = this->gbCuboid->getX3Centroid();
+
+		////Punkt1
+		//double p1x = this->gbCuboid->getPoint1()->getX1Coordinate();
+		//double p1y = this->gbCuboid->getPoint1()->getX2Coordinate();
+		//double p1z = this->gbCuboid->getPoint1()->getX3Coordinate();
+
+		//p1x = cos(orien[1]) * p1x + sin(orien[1]) * p1z;
+		////p1y = p1y;
+		//p1z = -sin(orien[1]) * p1x + cos(orien[1]) * p1z;
+
+		//this->gbCuboid->getPoint1()->setX1(p1x);
+		//this->gbCuboid->getPoint1()->setX2(p1y);
+		//this->gbCuboid->getPoint1()->setX3(p1z);
+
+		//
+		////Punkt2
+		//double p2x = this->gbCuboid->getPoint2()->getX1Coordinate();
+		//double p2y = this->gbCuboid->getPoint2()->getX2Coordinate();
+		//double p2z = this->gbCuboid->getPoint2()->getX3Coordinate();
+
+		//p2x = cos(orien[1]) * p2x + sin(orien[1]) * p2z;
+		////p1y = p1y;
+		//p2z = -sin(orien[1]) * p2x + cos(orien[1]) * p2z;
+
+		//this->gbCuboid->getPoint2()->setX1(p2x);
+		//this->gbCuboid->getPoint2()->setX2(p2y);
+		//this->gbCuboid->getPoint2()->setX3(p2z);
+		//
+		////////////////////////////////////////////////////////////////////////////
+
+		if (scale[0] != 1.0) this->gbCuboid->scale(scale[0], scale[1], scale[2]);
+		else this->gbCuboid->translate(pos[0], pos[1], pos[2]);
+		this->gbCuboid->notifyObserversObjectChanged();
+
+		//Methode der Basisklasse aufrufen.
+		vtkPoElement3D::applyActorModifications();
+	}
+}
+
+void vtkGbCuboid3D::setValues(void)
+{
+	double bounds[6];
+	bounds[0] = this->gbCuboid->getX1Minimum();
+	bounds[1] = this->gbCuboid->getX1Maximum();
+	bounds[2] = this->gbCuboid->getX2Minimum();
+	bounds[3] = this->gbCuboid->getX2Maximum();
+	bounds[4] = this->gbCuboid->getX3Minimum();
+	bounds[5] = this->gbCuboid->getX3Maximum();
+	this->source->SetBounds(bounds);
+
+//	this->actor->SetVisibility( this->gbCuboid->isActive() );
+}
+
+bool vtkGbCuboid3D::isPointInObject(double const point[3])
+{
+	return this->gbCuboid->isPointInGbObject3D(point[0], point[1], point[2]);
+}
+
+void vtkGbCuboid3D::objectChanged(UbObservable*)
+{
+	this->setValues();
+	this->source->Update();
+}
+
+void vtkGbCuboid3D::objectWillBeDeleted(UbObservable*)
+{
+	//TODO: Hier muss auf jeden Fall noch was geschehen....
+	this->gbCuboid->removeObserver(this);
+	delete this;
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCuboid3D.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCuboid3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..e70fb61c53412a1c81a0f97a422def19ca8e3095
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCuboid3D.h
@@ -0,0 +1,29 @@
+#ifndef VTKGBCUBOID3D_H
+#define VTKGBCUBOID3D_H
+
+#include "./../../../userinterface/presentation/vtkPoElement3D.h"
+
+/**** vtk ****/
+class vtkCubeSource;
+class vtkPolyDataMapper;
+
+class GbCuboid3D;
+
+class vtkGbCuboid3D : public vtkPoElement3D
+{
+public:
+	vtkGbCuboid3D(GbCuboid3D*);
+	~vtkGbCuboid3D(void);
+	void objectChanged(UbObservable*);
+	void objectWillBeDeleted(UbObservable*);
+	//void ModifiedEventFired(void);
+	void applyActorModifications();
+	bool isPointInObject(double const point[3]);
+protected:
+	void setValues();
+
+	GbCuboid3D* gbCuboid;
+	vtkCubeSource* source;
+   vtkPolyDataMapper* mapper;
+};
+#endif   
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCylinder3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCylinder3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5f3c4111740f69e6af0d99ea8c0fa4e66d18ac51
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCylinder3D.cpp
@@ -0,0 +1,103 @@
+#include "./vtkGbCylinder3D.h"
+
+#include "./../GbCylinder3D.h"
+#include "./../GbPoint3D.h"
+#include "./../../../userinterface/presentation/vtkEventCallbacks.h"
+
+#include "vtkCylinderSource.h"
+#include "vtkPolyDataMapper.h"
+
+
+vtkGbCylinder3D::vtkGbCylinder3D(GbCylinder3D* gbObject)
+{
+	this->gbCylinder = gbObject;
+	this->gbCylinder->addObserver(this);
+
+   this->setName("vtkGbCylinder3D");
+
+	this->source = vtkCylinderSource::New();
+   this->mapper = vtkPolyDataMapper::New();
+	
+	this->setValues();
+
+	this->mapper->SetInput( this->source->GetOutput() );
+	this->actor->SetMapper( this->mapper );
+
+   //this->applyActorModifications();
+}
+
+vtkGbCylinder3D::~vtkGbCylinder3D(void)
+{
+   this->gbCylinder->removeObserver(this);
+	if (this->source) this->source->Delete();
+}
+
+
+void vtkGbCylinder3D::setValues(void)
+{
+   //this->source->SetCenter(   this->gbCylinder->getX1Centroid(),
+   //                           this->gbCylinder->getX2Centroid(),
+   //                           this->gbCylinder->getX3Centroid());
+   //this->source->SetHeight(this->gbCylinder->getLength());
+   //this->source->SetRadius( this->gbCylinder->getRadius());
+
+   /* JZ Attention not ready still some work TODO*/
+   this->source->SetHeight(this->gbCylinder->getHeight());
+   this->source->SetCenter(this->gbCylinder->getX1Centroid(),
+                           this->gbCylinder->getX2Centroid(),
+                           this->gbCylinder->getX3Centroid());
+   this->source->SetRadius( this->gbCylinder->getRadius() );
+   this->source->SetResolution(10);
+}
+
+void vtkGbCylinder3D::applyActorModifications()
+{
+   //this->actor->SetScale(1.0, this->gbCylinder->getLength(), 1.0);
+   this->source->SetHeight(this->gbCylinder->getHeight());
+   this->actor->SetPosition(  this->gbCylinder->getPoint1()->x1,
+                              this->gbCylinder->getPoint1()->x2,
+                              this->gbCylinder->getPoint1()->x3);
+   this->source->SetRadius( this->gbCylinder->getRadius() );
+
+
+
+   //if (this->isModified)
+	//{
+	//	double pos[3];
+	//	double scale[3];
+	//	this->actor->GetPosition(pos);
+	//	this->actor->GetScale(scale);
+
+	//	this->actor->SetPosition(0.0,0.0,0.0);
+	//	this->actor->SetOrientation(0.0,0.0,0.0);
+	//	this->actor->SetScale(1.0,1.0,1.0);
+
+
+	//	if (scale[0] != 1.0) this->gbCylinder->scale(scale[0], scale[1], scale[2]);
+	//	else this->gbCylinder->translate(pos[0], pos[1], pos[2]);
+	//	this->gbCylinder->notifyObserversObjectChanged();
+
+	//	vtkPoElement3D::applyActorModifications();
+	//}
+}
+
+bool vtkGbCylinder3D::isPointInObject(double const point[3])
+{
+	return this->gbCylinder->isPointInGbObject3D(point[0], point[1], point[2]);
+}
+
+//Wird aufgerufen, wenn sich das zugehörige GBObject3D ändert.
+void vtkGbCylinder3D::objectChanged(UbObservable*)
+{
+   this->setValues();
+//	this->applyActorModifications();
+	this->source->Modified();
+}
+
+void vtkGbCylinder3D::objectWillBeDeleted(UbObservable*)
+{
+	//TODO: Hier muss auf jeden Fall noch was geschehen....
+	this->gbCylinder->removeObserver(this);
+	delete this;
+}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCylinder3D.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCylinder3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6a37f1979e7c170ec49f7d63cda5dd514f1557f
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbCylinder3D.h
@@ -0,0 +1,30 @@
+#ifndef VTKGBCYLINDER3D_H
+#define VTKGBCYLINDER3D_H
+
+#include "./../../../userinterface/presentation/vtkPoElement3D.h"
+
+class GbCylinder3D;
+
+class vtkCylinderSource;
+class vtkPolyDataMapper;
+
+
+class vtkGbCylinder3D : public vtkPoElement3D
+{
+public:
+	vtkGbCylinder3D(GbCylinder3D* cylinder);
+	~vtkGbCylinder3D();
+	void objectChanged(UbObservable*);
+	void objectWillBeDeleted(UbObservable*);
+	//void ModifiedEventFired(void);
+	void applyActorModifications();             
+	bool isPointInObject(double const point[3]);
+protected:
+	void setValues();
+
+	GbCylinder3D* gbCylinder;
+   vtkCylinderSource* source;
+   vtkPolyDataMapper* mapper;
+};
+#endif   
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbSphere3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbSphere3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3ab7b25da151d5408fc154a149a05444b36bc849
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbSphere3D.cpp
@@ -0,0 +1,112 @@
+#include "./vtkGbSphere3D.h"
+
+#include "./../GbSphere3D.h"
+#include "./../../../userinterface/presentation/vtkEventCallbacks.h"
+
+#include "vtkSphereSource.h"
+#include "vtkPolyDataMapper.h"
+
+
+vtkGbSphere3D::vtkGbSphere3D(GbSphere3D* gbObject):vtkPoElement3D()
+{
+	this->gbSphere = gbObject;
+	this->gbSphere->addObserver(this);
+   
+   this->setName("vtkGbSphere3D");
+
+
+	this->source = vtkSphereSource::New();
+   this->mapper = vtkPolyDataMapper::New();
+	
+	this->setValues();
+
+	this->mapper->SetInput( this->source->GetOutput() );
+	this->actor->SetMapper( this->mapper );
+//	this->actor->GetProperty()->SetRepresentationToWireframe();
+}
+
+vtkGbSphere3D::~vtkGbSphere3D(void)
+{
+   this->gbSphere->removeObserver(this);
+	if (this->source) this->source->Delete();
+}
+
+//void vtkGbSphere3D::ModifiedEventFired()
+//{
+//	////double a_orien[3];
+//	//double a_pos[3];
+//	////double a_scale[3];
+//	//this->actor->GetPosition(a_pos);
+//	////this->actor->GetOrientation(a_orien);
+//	////this->actor->GetScale(a_scale);
+//
+//	//this->actor->SetPosition(0.0,0.0,0.0);
+//	//this->actor->SetOrientation(0.0,0.0,0.0);
+//	//this->actor->SetScale(1.0,1.0,1.0);
+//	//
+//	////cout<<"Orien:"<<a_orien[0]<<","<<a_orien[1]<<","<<a_orien[3]<<endl;
+//	////cout<<"Position:"<<a_pos[0]<<","<<a_pos[1]<<","<<a_pos[3]<<endl;
+//	////cout<<"Scale:"<<a_scale[0]<<","<<a_scale[1]<<","<<a_scale[3]<<endl;
+//
+//	//this->gbSphere->translate(a_pos[0], a_pos[1], a_pos[2]);
+//	//this->gbSphere->notifyObserversObjectChanged();
+//	PoElement3D::ModifiedEventFired();
+//}
+
+void vtkGbSphere3D::setValues(void)
+{
+	this->source->SetCenter(	this->gbSphere->getX1Centroid(),
+								this->gbSphere->getX2Centroid(),
+								this->gbSphere->getX3Centroid()	);
+	
+	this->source->SetRadius( this->gbSphere->getRadius() );
+//	this->actor->SetVisibility( this->gbSphere->isActive() );
+}
+
+void vtkGbSphere3D::applyActorModifications()
+{
+	if (this->isModified)
+	{
+		//double a_orien[3];
+		double pos[3];
+		double scale[3];
+		this->actor->GetPosition(pos);
+		//this->actor->GetOrientation(a_orien);
+		this->actor->GetScale(scale);
+
+		this->actor->SetPosition(0.0,0.0,0.0);
+		this->actor->SetOrientation(0.0,0.0,0.0);
+		this->actor->SetScale(1.0,1.0,1.0);
+
+		//cout<<"Orien:"<<a_orien[0]<<","<<a_orien[1]<<","<<a_orien[3]<<endl;
+		//cout<<"Position:"<<a_pos[0]<<","<<a_pos[1]<<","<<a_pos[3]<<endl;
+		//cout<<"Scale:"<<a_scale[0]<<","<<a_scale[1]<<","<<a_scale[3]<<endl;
+
+		if (scale[0] != 1.0) this->gbSphere->scale(scale[0], scale[1], scale[2]);
+		else this->gbSphere->translate(pos[0], pos[1], pos[2]);
+		this->gbSphere->notifyObserversObjectChanged();
+
+		vtkPoElement3D::applyActorModifications();
+	}
+}
+
+bool vtkGbSphere3D::isPointInObject(double const point[3])
+{
+	return this->gbSphere->isPointInGbObject3D(point[0], point[1], point[2]);
+}
+
+//Wird aufgerufen, wenn sich das zugehörige GBObject3D ändert.
+void vtkGbSphere3D::objectChanged(UbObservable*)
+{
+	this->setValues();
+	this->source->Modified();
+	this->actor->Modified();
+}
+
+void vtkGbSphere3D::objectWillBeDeleted(UbObservable*)
+{
+	//TODO: Hier muss auf jeden Fall noch was geschehen....
+	this->gbSphere->removeObserver(this);
+	delete this;
+}
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbSphere3D.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbSphere3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec086a6470c0330dbeed2e0566c583f9ff3a50bf
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbSphere3D.h
@@ -0,0 +1,33 @@
+#ifndef VTKGBSPHERE3D_H
+#define VTKGBSPHERE3D_H
+
+#include "./../../../userinterface/presentation/vtkPoElement3D.h"
+//#include "./../../../../vtkEventListeners.h"
+
+class GbSphere3D;
+
+class vtkSphereSource;
+class vtkPolyDataMapper;
+
+class vtkGbSphere3D : public vtkPoElement3D
+{
+public:
+	vtkGbSphere3D(GbSphere3D*);
+	~vtkGbSphere3D(void);
+	void objectChanged(UbObservable*);
+	void objectWillBeDeleted(UbObservable*);
+	//void ModifiedEventFired(void);
+	void applyActorModifications(); 
+	bool isPointInObject(double const point[3]);
+
+   virtual string toString() { return "vtkGbSphere3D";  }
+
+protected:
+	void setValues();
+
+	GbSphere3D* gbSphere;
+   vtkPolyDataMapper* mapper;
+	vtkSphereSource* source;
+};
+#endif   
+
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbTriangularMesh3D.cpp b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbTriangularMesh3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..92f08be6390098e56a82d6382aa29c56250190e3
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbTriangularMesh3D.cpp
@@ -0,0 +1,167 @@
+#include "./vtkGbTriangularMesh3D.h"
+
+/**** CAB ****/
+#include "./../GbTriangularMesh3D.h"
+#include "./../GbTriangle3D.h"
+#include "./../../../basics/utilities/UbMath.h"
+
+/**** vtk ****/
+#include "vtkUnstructuredGrid.h"
+#include "vtkDataSetMapper.h"
+#include "vtkPoints.h"
+#include "vtkTriangle.h"
+#include "vtkIdList.h"
+
+/*** temp ****/
+#include "./../GbPoint3D.h"
+#include "vtkMatrix4x4.h"
+
+//#define PI   3.14159265358979323846
+
+vtkGbTriangularMesh3D::vtkGbTriangularMesh3D(GbTriangularMesh3D* mesh)
+{
+	this->gbTriangularMesh = mesh;
+	this->gbTriangularMesh->addObserver(this);
+
+   this->setName("vtkGbTriangularMesh3D");
+
+	this->unstGrid = vtkUnstructuredGrid::New();
+	this->buildGrid();
+
+	
+	this->dataSetMapper = vtkDataSetMapper::New();
+	this->dataSetMapper->SetInput(unstGrid);
+
+	this->actor->SetMapper( this->dataSetMapper );
+}
+
+vtkGbTriangularMesh3D::~vtkGbTriangularMesh3D(void)
+{
+   this->gbTriangularMesh->removeObserver(this);
+	this->unstGrid->Delete();
+	this->dataSetMapper->Delete();
+}
+
+//void vtkGbTriangularMesh3D::ModifiedEventFired()
+//{
+//	double pos[3];
+//	this->actor->GetPosition(pos);
+//
+//	this->actor->SetPosition(0.0,0.0,0.0);
+//	this->actor->SetOrientation(0.0,0.0,0.0);
+//	this->actor->SetScale(1.0,1.0,1.0);
+//
+//	double x1 = pos[0];
+//	double x2 = pos[1];
+//	double x3 = pos[3];
+//
+//	vector<GbPoint3D*>* pointList = this->gbTriangularMesh->getNodes();
+//	for (int pos=0; pos<pointList->size(); pos++) 
+//	{
+//		(*pointList)[pos]->translate(x1,x2,x3);
+//		//((*pointList)[pos])->translate(pos[0], pos[1], pos[3]);
+//	}
+//	this->gbTriangularMesh->notifyObserversObjectChanged();
+//}
+
+void vtkGbTriangularMesh3D::applyActorModifications()
+{
+	if (isModified) 
+	{
+		double pos[3];
+		double orien[3];
+		double scale[3];
+		this->actor->GetPosition(pos);
+		this->actor->GetOrientation(orien);
+		this->actor->GetScale(scale);
+
+      orien[0] = orien[0] / 180 * UbMath::PI;
+		orien[1] = orien[1] / 180 * UbMath::PI;
+		orien[2] = orien[2] / 180 * UbMath::PI;
+
+		//cout<<"Orien:"<<orien[0]<<","<<orien[1]<<","<<orien[3]<<endl;
+		//cout<<"Position:"<<pos[0]<<","<<pos[1]<<","<<pos[3]<<endl;
+		//cout<<"Scale:"<<scale[0]<<","<<scale[1]<<","<<scale[3]<<endl;
+		
+		this->actor->SetPosition(0.0,0.0,0.0);
+		this->actor->SetOrientation(0.0,0.0,0.0);
+		this->actor->SetScale(1.0,1.0,1.0);
+		
+		vector<GbPoint3D*>* pointList = this->gbTriangularMesh->getNodes();
+		for (int index=0; index<(int)pointList->size(); index++) 
+		{
+			(*pointList)[index]->rotate(orien[0], orien[1], orien[2]);
+			(*pointList)[index]->scale(scale[0], scale[1], scale[2]);
+			(*pointList)[index]->translate(pos[0], pos[1], pos[2]);
+		}
+		this->gbTriangularMesh->notifyObserversObjectChanged();
+		//Methode der Basisklasse aufrufen.
+		vtkPoElement3D::applyActorModifications();
+	}
+}
+
+void vtkGbTriangularMesh3D::buildGrid(void)
+{
+	this->unstGrid->Reset();
+
+	vector<GbTriangle3D*>* triangles = this->gbTriangularMesh->getTriangles();
+	double xyz[3];
+	//this.setContext(new PoContext3D());
+
+	vtkPoints* points  = vtkPoints::New();
+	vtkTriangle* triangle = vtkTriangle::New();
+	for(int u=0; u<(int)triangles->size(); u++)
+	{
+		xyz[0] = (*triangles)[u]->getPoint(0)->getX1Coordinate();
+		xyz[1] = (*triangles)[u]->getPoint(0)->getX2Coordinate();
+		xyz[2] = (*triangles)[u]->getPoint(0)->getX3Coordinate();
+		triangle->GetPointIds()->InsertId(0, points->InsertNextPoint(xyz));
+		//points.InsertPoint(u, xyz);       // 3D geometry
+
+		xyz[0] = (*triangles)[u]->getPoint(1)->getX1Coordinate();
+		xyz[1] = (*triangles)[u]->getPoint(1)->getX2Coordinate();
+		xyz[2] = (*triangles)[u]->getPoint(1)->getX3Coordinate();
+		triangle->GetPointIds()->InsertId(1, points->InsertNextPoint(xyz));
+		//points.InsertPoint(u, xyz);       // 3D geometry
+
+		xyz[0] = (*triangles)[u]->getPoint(2)->getX1Coordinate();
+		xyz[1] = (*triangles)[u]->getPoint(2)->getX2Coordinate();
+		xyz[2] = (*triangles)[u]->getPoint(2)->getX3Coordinate();
+		triangle->GetPointIds()->InsertId(2, points->InsertNextPoint(xyz));
+		//points.InsertPoint(u, xyz);       // 3D geometry
+
+		this->insertNextCell( triangle->GetCellType(), triangle->GetPointIds() ); // grid topology
+
+	}
+	this->setPoints(points);
+	//this->source->SetCenter(	this->gbSphere->getX1Centroid(),
+	//	this->gbSphere->getX2Centroid(),
+	//	this->gbSphere->getX3Centroid()	);
+
+	//this->source->SetRadius( this->gbSphere->getRadius() );
+	//this->actor->SetVisibility( this->gbSphere->isActive() );
+	//this->unstGrid->Modified();
+}
+
+int vtkGbTriangularMesh3D::insertNextCell(int type, vtkIdList* idList)
+{
+	return this->unstGrid->InsertNextCell(type, idList);
+}
+
+void vtkGbTriangularMesh3D::setPoints(vtkPoints* points)
+{
+	this->unstGrid->SetPoints(points);
+}
+
+void vtkGbTriangularMesh3D::objectChanged(UbObservable*)
+{
+	this->buildGrid();
+	this->unstGrid->Update();
+}
+
+void vtkGbTriangularMesh3D::objectWillBeDeleted(UbObservable*)
+{
+	//TODO: Hier muss auf jeden Fall noch was geschehen....
+	this->gbTriangularMesh->removeObserver(this);
+	delete this;
+}
diff --git a/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d59515f29789949e4cfd3094802d073a61690dc
--- /dev/null
+++ b/source/ThirdParty/Library/numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h
@@ -0,0 +1,31 @@
+#ifndef VTKGBTRIANGULARMESH3D_H
+#define VTKGBTRIANGULARMESH3D_H
+
+#include "./../../../userinterface/presentation/vtkPoElement3D.h"
+
+class GbTriangularMesh3D;
+class vtkUnstructuredGrid;
+class vtkDataSetMapper;
+class vtkIdList;
+class vtkPoints;
+
+class vtkGbTriangularMesh3D : public vtkPoElement3D
+{
+public:
+	vtkGbTriangularMesh3D(GbTriangularMesh3D* mesh);
+	~vtkGbTriangularMesh3D();
+	void objectChanged(UbObservable* );
+	void objectWillBeDeleted(UbObservable* );
+	int insertNextCell(int, vtkIdList*);
+	void setPoints(vtkPoints*);
+	//void ModifiedEventFired(void);
+	void applyActorModifications();
+protected:
+	void buildGrid();
+
+	GbTriangularMesh3D* gbTriangularMesh;
+	vtkUnstructuredGrid* unstGrid;
+	vtkDataSetMapper* dataSetMapper;
+};
+#endif   
+
diff --git a/source/ThirdParty/MarchingCubes/CMakePackage.txt b/source/ThirdParty/MarchingCubes/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bea0c0b7df77f75944c36260ff48bb9353fc8394
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/CMakePackage.txt
@@ -0,0 +1,6 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES outOption outSourceGroupName)
+
+IF(${outOption})
+   LIST(APPEND CAB_ADDTIONAL_COMPILER_FLAGS -DMC_CUBES  )
+ENDIF()
diff --git a/source/ThirdParty/MarchingCubes/MarchingCubes.h b/source/ThirdParty/MarchingCubes/MarchingCubes.h
new file mode 100644
index 0000000000000000000000000000000000000000..2854983888eaeb71f4011099d3cd58e6b5f66051
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/MarchingCubes.h
@@ -0,0 +1,1640 @@
+#ifndef MARCHINGCUBES_H
+#define MARCHINGCUBES_H
+/**
+* @file    MarchingCubes.h
+* @author  Thomas Lewiner <thomas.lewiner@polytechnique.org>
+* @author  Math Dept, PUC-Rio
+* @version 0.2
+* @date    12/08/2002
+*
+* @brief   MarchingCubes Algorithm
+*/
+//________________________________________________
+
+#include <3rdParty/MarchingCubes/McTypes.h>
+#include <3rdParty/MarchingCubes/MatrixWrapper.h>
+#include <3rdParty/MarchingCubes/Matrix3DWrapper.h>
+#include <3rdParty/MarchingCubes/Matrix4DWrapper.h>
+#include <3rdParty/MarchingCubes/McLookUpTable.h>
+#include <3rdParty/MarchingCubes/McPly.h>
+
+#include <cmath>
+#include <ctime>
+#include <cfloat>
+#include <iostream>
+
+namespace McCubes{
+//_____________________________________________________________________________
+/** Marching Cubes algorithm wrapper */
+/** \class MarchingCubes
+  * \brief Marching Cubes algorithm.
+  */
+template<typename DataWrapper = MatrixWrapper<real> >
+class MarchingCubes
+//-----------------------------------------------------------------------------
+{
+public:
+   //nested classes
+   //-----------------------------------------------------------------------------
+   // Vertex structure
+   /** \struct Vertex "MarchingCubes.h" MarchingCubes
+   * Position and normal of a vertex
+   * \brief vertex structure
+   * \param x X coordinate
+   * \param y Y coordinate
+   * \param z Z coordinate
+   * \param nx X component of the normal
+   * \param ny Y component of the normal
+   * \param nz Z component of the normal
+   */
+   typedef struct Vertex
+   {
+      real  x,  y,  z ;  /**< Vertex coordinates */
+      real nx, ny, nz ;  /**< Vertex normal */
+   } Vertex ;
+
+   //-----------------------------------------------------------------------------
+   // Triangle structure
+   /** \struct Triangle "MarchingCubes.h" MarchingCubes
+   * Indices of the oriented triange vertices
+   * \brief triangle structure
+   * \param v1 First vertex index
+   * \param v2 Second vertex index
+   * \param v3 Third vertex index
+   */
+   typedef struct Triangle
+   {
+      int v1,v2,v3 ;  /**< Triangle vertices */
+   } Triangle ;
+   //_____________________________________________________________________________
+
+public :
+   // Constructors
+  /**
+   * Main and default constructor
+   * \brief constructor
+   * \param size_x width  of the grid
+   * \param size_y depth  of the grid
+   * \param size_z height of the grid
+   */
+  MarchingCubes ( const int size_x = -1, const int size_y = -1, const int size_z = -1 ) ;
+  MarchingCubes ( const DataWrapper& dataWrapper );
+  /** Destructor */
+  ~MarchingCubes() ;
+
+//-----------------------------------------------------------------------------
+// Accessors
+public :
+  /** accesses the number of vertices of the generated mesh */
+  inline const int nverts() const { return _nverts ; }
+  /** accesses the number of triangles of the generated mesh */
+  inline const int ntrigs() const { return _ntrigs ; }
+  /** accesses a specific vertex of the generated mesh */
+  inline Vertex   * vert( const int i ) const { if( i < 0  || i >= _nverts ) return ( Vertex *)NULL ; return _vertices  + i ; }
+  /** accesses a specific triangle of the generated mesh */
+  inline Triangle * trig( const int i ) const { if( i < 0  || i >= _ntrigs ) return (Triangle*)NULL ; return _triangles + i ; }
+
+  /** accesses the vertex buffer of the generated mesh */
+  inline Vertex   *vertices () { return _vertices  ; }
+  /** accesses the triangle buffer of the generated mesh */
+  inline Triangle *triangles() { return _triangles ; }
+
+  /**  accesses the width  of the grid */
+  inline const int size_x() const { return dataWrapper.getNX1(); /*_size_x ;*/ }
+  /**  accesses the depth  of the grid */
+  inline const int size_y() const { return dataWrapper.getNX2(); /*_size_y ;*/ }
+  /**  accesses the height of the grid */
+  inline const int size_z() const { return dataWrapper.getNX3(); /*_size_z ;*/ }
+
+  /**
+   * changes the size of the grid
+   * \param size_x width  of the grid
+   * \param size_y depth  of the grid
+   * \param size_z height of the grid
+   */
+  inline void set_resolution( const int size_x, const int size_y, const int size_z )
+  {
+     dataWrapper.resize(size_x, size_y, size_z);
+     //throw UbException("MarchingCubes::set_resolution disabled by CAB");
+     //_size_x = size_x ;  _size_y = size_y ;  _size_z = size_z ;
+  }
+  /**
+   * selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes
+   * \param originalMC true for the original Marching Cubes
+   */
+  inline void set_method    ( const bool originalMC = false ) { _originalMC = originalMC ; }
+  /**
+   * selects to use data from another class
+   * \param data is the pointer to the external data, allocated as a size_x*size_y*size_z vector running in x first
+   */
+  inline void set_ext_data  ( real *data )
+  {
+     throw UbException(UB_EXARGS, "disabled by CAB");
+     //if( !_ext_data ) delete [] _data ;  _ext_data = data != NULL ;  if( _ext_data ) _data = data ;
+  }
+  /**
+   * selects to allocate data
+   */
+  inline void set_int_data  ()
+  {
+     throw UbException(UB_EXARGS,"disabled by CAB");
+     //_ext_data = false ;  _data = NULL ;
+  }
+
+  // Data access
+  /**
+   * accesses a specific cube of the grid
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  //MODIFIED BY CAB
+  inline const real get_data  ( const int& i, const int& j, const int& k ) const
+  {
+     return dataWrapper.getData(i,j,k);
+     //return _data[ i + j*_size_x + k*_size_x*_size_y] ;
+  }
+  /**
+   * sets a specific cube of the grid
+   * \param val new value for the cube
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  //MODIFIED BY CAB
+  inline void  set_data  ( const real& val, const int& i, const int& j, const int& k )
+  {
+     dataWrapper.setData(val,i,j,k);
+     //_data[ i + j*_size_x + k*_size_x*_size_y] = val ;
+  }
+
+  // Data initialization
+  /** inits temporary structures (must set sizes before call) : the grid and the vertex index per cube */
+  void init_temps () ;
+  /** inits all structures (must set sizes before call) : the temporary structures and the mesh buffers */
+  void init_all   () ;
+  /** clears temporary structures : the grid and the main */
+  void clean_temps() ;
+  /** clears all structures : the temporary structures and the mesh buffers */
+  void clean_all  () ;
+
+
+//-----------------------------------------------------------------------------
+// Exportation
+public :
+  /**
+   * PLY exportation of the generated mesh
+   * \param fn  name of the PLY file to create
+   * \param bin if true, the PLY will be written in binary mode
+   */
+  void writePLY( const char *fn, bool bin = false ) ;
+
+  /**
+   * VRML / Open Inventor exportation of the generated mesh
+   * \param fn  name of the IV file to create
+   */
+  void writeIV ( const char *fn ) ;
+
+  /**
+   * ISO exportation of the input grid
+   * \param fn  name of the ISO file to create
+   */
+  void writeISO( const char *fn ) ;
+
+
+  void writeUCD( std::string filename );
+  void writeUCDwithNormals( std::string filename );
+
+//-----------------------------------------------------------------------------
+// Algorithm
+public :
+  /**
+   * Main algorithm : must be called after init_all
+   * \param iso isovalue
+   */
+  void run( real iso = (real)0.0 ) ;
+
+protected :
+  /** tesselates one cube */
+  void process_cube ()             ;
+  /** tests if the components of the tesselation of the cube should be connected by the interior of an ambiguous face */
+  bool test_face    ( schar face ) ;
+  /** tests if the components of the tesselation of the cube should be connected through the interior of the cube */
+  bool test_interior( schar s )    ;
+
+
+//-----------------------------------------------------------------------------
+// Operations
+protected :
+  /**
+   * computes almost all the vertices of the mesh by interpolation along the cubes edges
+   * \param iso isovalue
+   */
+  void compute_intersection_points( real iso ) ;
+
+  /**
+   * routine to add a triangle to the mesh
+   * \param trig the code for the triangle as a sequence of edges index
+   * \param n    the number of triangles to produce
+   * \param v12  the index of the interior vertex to use, if necessary
+   */
+  void add_triangle ( const char* trig, char n, int v12 = -1 ) ;
+
+  /** tests and eventually doubles the vertex buffer capacity for a new vertex insertion */
+  void test_vertex_addition() ;
+  /** adds a vertex on the current horizontal edge */
+  int add_x_vertex() ;
+  /** adds a vertex on the current longitudinal edge */
+  int add_y_vertex() ;
+  /** adds a vertex on the current vertical edge */
+  int add_z_vertex() ;
+  /** adds a vertex inside the current cube */
+  int add_c_vertex() ;
+
+  /**
+   * interpolates the horizontal gradient of the implicit function at the lower vertex of the specified cube
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  real get_x_grad( const int i, const int j, const int k ) const ;
+  /**
+   * interpolates the longitudinal gradient of the implicit function at the lower vertex of the specified cube
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  real get_y_grad( const int i, const int j, const int k ) const ;
+  /**
+   * interpolates the vertical gradient of the implicit function at the lower vertex of the specified cube
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  real get_z_grad( const int i, const int j, const int k ) const ;
+
+  /**
+   * accesses the pre-computed vertex index on the lower horizontal edge of a specific cube
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  inline int   get_x_vert( const int i, const int j, const int k ) const { return _x_verts[ i + j*dataWrapper.getNX1() + k*dataWrapper.getNX1()*dataWrapper.getNX2()] ; }
+  /**
+   * accesses the pre-computed vertex index on the lower longitudinal edge of a specific cube
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  inline int   get_y_vert( const int i, const int j, const int k ) const { return _y_verts[ i + j*dataWrapper.getNX1() + k*dataWrapper.getNX1()*dataWrapper.getNX2()] ; }
+  /**
+   * accesses the pre-computed vertex index on the lower vertical edge of a specific cube
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  inline int   get_z_vert( const int i, const int j, const int k ) const { return _z_verts[ i + j*dataWrapper.getNX1() + k*dataWrapper.getNX1()*dataWrapper.getNX2()] ; }
+
+  /**
+   * sets the pre-computed vertex index on the lower horizontal edge of a specific cube
+   * \param val the index of the new vertex
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  inline void  set_x_vert( const int val, const int i, const int j, const int k ) { _x_verts[ i + j*dataWrapper.getNX1() + k*dataWrapper.getNX1()*dataWrapper.getNX2()] = val ; }
+  /**
+   * sets the pre-computed vertex index on the lower longitudinal edge of a specific cube
+   * \param val the index of the new vertex
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  inline void  set_y_vert( const int val, const int i, const int j, const int k ) { _y_verts[ i + j*dataWrapper.getNX1() + k*dataWrapper.getNX1()*dataWrapper.getNX2()] = val ; }
+  /**
+   * sets the pre-computed vertex index on the lower vertical edge of a specific cube
+   * \param val the index of the new vertex
+   * \param i abscisse of the cube
+   * \param j ordinate of the cube
+   * \param k height of the cube
+   */
+  inline void  set_z_vert( const int val, const int i, const int j, const int k ) { _z_verts[ i + j*dataWrapper.getNX1() + k*dataWrapper.getNX1()*dataWrapper.getNX2()] = val ; }
+
+  /** prints cube for debug */
+  void print_cube(std::ostream& os) ;
+
+//-----------------------------------------------------------------------------
+// Elements
+protected :
+  bool      _originalMC ;   /**< selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes */
+//  bool      _ext_data   ;   /**< selects wether to allocate data or use data from another class */
+
+//folgendes ist nun alles folgenden dataWrapper:
+//   int       _size_x     ;  /**< width  of the grid */
+//   int       _size_y     ;  /**< depth  of the grid */
+//   int       _size_z     ;  /**< height of the grid */
+//real     *_data       ;  /**< implicit function values sampled on the grid */
+  DataWrapper   dataWrapper;
+
+  int      *_x_verts    ;  /**< pre-computed vertex indices on the lower horizontal   edge of each cube */
+  int      *_y_verts    ;  /**< pre-computed vertex indices on the lower longitudinal edge of each cube */
+  int      *_z_verts    ;  /**< pre-computed vertex indices on the lower vertical     edge of each cube */
+
+  int       _nverts     ;  /**< number of allocated vertices  in the vertex   buffer */
+  int       _ntrigs     ;  /**< number of allocated triangles in the triangle buffer */
+  int       _Nverts     ;  /**< size of the vertex   buffer */
+  int       _Ntrigs     ;  /**< size of the triangle buffer */
+  Vertex   *_vertices   ;  /**< vertex   buffer */
+  Triangle *_triangles  ;  /**< triangle buffer */
+
+  int       _i          ;  /**< abscisse of the active cube */
+  int       _j          ;  /**< height of the active cube */
+  int       _k          ;  /**< ordinate of the active cube */
+
+  real      _cube[8]    ;  /**< values of the implicit function on the active cube */
+  uchar     _lut_entry  ;  /**< cube sign representation in [0..255] */
+  uchar     _case       ;  /**< case of the active cube in [0..15] */
+  uchar     _config     ;  /**< configuration of the active cube */
+  uchar     _subconfig  ;  /**< subconfiguration of the active cube */
+
+private:
+   MarchingCubes ( const MarchingCubes & );                //no copy allowed 
+   const MarchingCubes& operator=( const MarchingCubes& ); //no copy allowed
+};
+//_____________________________________________________________________________
+
+
+// step size of the arrays of vertices and triangles
+static const int ALLOC_SIZE = 65536;
+
+//_____________________________________________________________________________
+// print cube for debug
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::print_cube(std::ostream& os)
+{ 
+   os<<_cube[0]<<","<<_cube[1]<<","<<_cube[2]<<","<<_cube[3]<<","
+     <<_cube[4]<<","<<_cube[5]<<","<<_cube[6]<<","<<_cube[7]; 
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// Constructors
+
+template<typename DataWrapper >
+MarchingCubes< DataWrapper >::MarchingCubes( const int size_x /*= -1*/, const int size_y /*= -1*/, const int size_z /*= -1*/ ) :
+_originalMC(false),
+//_ext_data  (false),
+// _size_x    (size_x),
+// _size_y    (size_y),
+// _size_z    (size_z),
+//_data      ((real *)NULL),
+_x_verts   (( int *)NULL),
+_y_verts   (( int *)NULL),
+_z_verts   (( int *)NULL),
+_nverts    (0),
+_ntrigs    (0),
+_Nverts    (0),
+_Ntrigs    (0),
+_vertices  (( Vertex *)NULL),
+_triangles ((Triangle*)NULL)
+{
+   this->dataWrapper = DataWrapper(size_x,size_y,size_z);
+}
+
+template<typename DataWrapper >
+MarchingCubes< DataWrapper >::MarchingCubes ( const DataWrapper& dataWrapper ) :
+_originalMC(false),
+//_ext_data  (false),
+// _size_x    (size_x),
+// _size_y    (size_y),
+// _size_z    (size_z),
+//_data      ((real *)NULL),
+_x_verts   (( int *)NULL),
+_y_verts   (( int *)NULL),
+_z_verts   (( int *)NULL),
+_nverts    (0),
+_ntrigs    (0),
+_Nverts    (0),
+_Ntrigs    (0),
+_vertices  (( Vertex *)NULL),
+_triangles ((Triangle*)NULL)
+{
+   this->dataWrapper = dataWrapper;
+}
+
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// Destructor
+template<typename DataWrapper >
+MarchingCubes<DataWrapper >::~MarchingCubes()
+//-----------------------------------------------------------------------------
+{
+   clean_all() ;
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// main algorithm
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::run( real iso )
+//-----------------------------------------------------------------------------
+{
+   //printf("Marching Cubes begin: cpu %ld\n", clock() ) ;
+
+   compute_intersection_points( iso ) ;
+
+   for( _k = dataWrapper.getMinX3(); _k < dataWrapper.getMaxX3(); _k++ )
+      for( _j = dataWrapper.getMinX2(); _j < dataWrapper.getMaxX2(); _j++ )
+         for( _i = dataWrapper.getMinX1(); _i < dataWrapper.getMaxX1(); _i++ )
+         {
+            _lut_entry = 0 ;
+            for( int p = 0 ; p < 8 ; ++p )
+            {
+               _cube[p] = get_data( _i+((p^(p>>1))&1), _j+((p>>1)&1), _k+((p>>2)&1) ) - iso ;
+               if( std::fabs( _cube[p] ) < FLT_EPSILON ) _cube[p] = FLT_EPSILON ;
+               if( _cube[p] > 0 ) _lut_entry += 1 << p ;
+            }
+            /*
+            if( ( _cube[0] = get_data( _i , _j , _k ) ) > 0 ) _lut_entry +=   1 ;
+            if( ( _cube[1] = get_data(_i+1, _j , _k ) ) > 0 ) _lut_entry +=   2 ;
+            if( ( _cube[2] = get_data(_i+1,_j+1, _k ) ) > 0 ) _lut_entry +=   4 ;
+            if( ( _cube[3] = get_data( _i ,_j+1, _k ) ) > 0 ) _lut_entry +=   8 ;
+            if( ( _cube[4] = get_data( _i , _j ,_k+1) ) > 0 ) _lut_entry +=  16 ;
+            if( ( _cube[5] = get_data(_i+1, _j ,_k+1) ) > 0 ) _lut_entry +=  32 ;
+            if( ( _cube[6] = get_data(_i+1,_j+1,_k+1) ) > 0 ) _lut_entry +=  64 ;
+            if( ( _cube[7] = get_data( _i ,_j+1,_k+1) ) > 0 ) _lut_entry += 128 ;
+            */
+            process_cube( ) ;
+         }
+
+    //     printf("Marching Cubes end: cpu %ld\n", clock() ) ;
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// init temporary structures (must set sizes before call)
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::init_temps()
+//-----------------------------------------------------------------------------
+{
+//    if( !_ext_data )
+//       _data    = new real [_size_x * _size_y * _size_z] ;
+   _x_verts = new int  [dataWrapper.getNX1() * dataWrapper.getNX2() * dataWrapper.getNX3()] ;
+   _y_verts = new int  [dataWrapper.getNX1() * dataWrapper.getNX2() * dataWrapper.getNX3()] ;
+   _z_verts = new int  [dataWrapper.getNX1() * dataWrapper.getNX2() * dataWrapper.getNX3()] ;
+
+   memset( _x_verts, -1, dataWrapper.getNX1() * dataWrapper.getNX2() * dataWrapper.getNX3() * sizeof( int ) ) ;
+   memset( _y_verts, -1, dataWrapper.getNX1() * dataWrapper.getNX2() * dataWrapper.getNX3() * sizeof( int ) ) ;
+   memset( _z_verts, -1, dataWrapper.getNX1() * dataWrapper.getNX2() * dataWrapper.getNX3() * sizeof( int ) ) ;
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// init all structures (must set sizes before call)
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::init_all ()
+//-----------------------------------------------------------------------------
+{
+   init_temps() ;
+
+   _nverts = _ntrigs = 0 ;
+   _Nverts = _Ntrigs = ALLOC_SIZE ;
+   _vertices  = new Vertex  [_Nverts] ;
+   _triangles = new Triangle[_Ntrigs] ;
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// clean temporary structures
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::clean_temps()
+//-----------------------------------------------------------------------------
+{
+//    if( !_ext_data )
+//       delete [] _data;
+   delete [] _x_verts;
+   delete [] _y_verts;
+   delete [] _z_verts;
+
+//    if( !_ext_data )
+//       _data     = (real*)NULL ;
+   _x_verts  = (int*)NULL ;
+   _y_verts  = (int*)NULL ;
+   _z_verts  = (int*)NULL ;
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// clean all structures
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::clean_all()
+//-----------------------------------------------------------------------------
+{
+   clean_temps() ;
+   delete [] _vertices  ;
+   delete [] _triangles ;
+   _vertices  = (Vertex   *)NULL ;
+   _triangles = (Triangle *)NULL ;
+   _nverts = _ntrigs = 0 ;
+   _Nverts = _Ntrigs = 0 ;
+
+   //_size_x = _size_y = _size_z = -1 ;
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+// Compute the intersection points
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::compute_intersection_points( real iso )
+//-----------------------------------------------------------------------------
+{
+   for( _k = 0 ; _k < dataWrapper.getNX3() ; _k++ )
+      for( _j = 0 ; _j < dataWrapper.getNX2() ; _j++ )
+         for( _i = 0 ; _i < dataWrapper.getNX1() ; _i++ )
+         {
+            _cube[0] = get_data( _i, _j, _k ) - iso ;
+            if( _i < dataWrapper.getNX1() - 1 ) _cube[1] = get_data(_i+1, _j , _k ) - iso ;
+            else                                _cube[1] = _cube[0] ;
+
+            if( _j < dataWrapper.getNX2() - 1 ) _cube[3] = get_data( _i ,_j+1, _k ) - iso ;
+            else                                _cube[3] = _cube[0] ;
+
+            if( _k < dataWrapper.getNX3() - 1 ) _cube[4] = get_data( _i , _j ,_k+1) - iso ;
+            else                                _cube[4] = _cube[0] ;
+
+            if( std::fabs( _cube[0] ) < FLT_EPSILON ) _cube[0] = FLT_EPSILON ;
+            if( std::fabs( _cube[1] ) < FLT_EPSILON ) _cube[1] = FLT_EPSILON ;
+            if( std::fabs( _cube[3] ) < FLT_EPSILON ) _cube[3] = FLT_EPSILON ;
+            if( std::fabs( _cube[4] ) < FLT_EPSILON ) _cube[4] = FLT_EPSILON ;
+
+            if( _cube[0] < 0 )
+            {
+               if( _cube[1] > 0 ) set_x_vert( add_x_vertex( ), _i,_j,_k ) ;
+               if( _cube[3] > 0 ) set_y_vert( add_y_vertex( ), _i,_j,_k ) ;
+               if( _cube[4] > 0 ) set_z_vert( add_z_vertex( ), _i,_j,_k ) ;
+            }
+            else
+            {
+               if( _cube[1] < 0 ) set_x_vert( add_x_vertex( ), _i,_j,_k ) ;
+               if( _cube[3] < 0 ) set_y_vert( add_y_vertex( ), _i,_j,_k ) ;
+               if( _cube[4] < 0 ) set_z_vert( add_z_vertex( ), _i,_j,_k ) ;
+            }
+         }
+}
+//_____________________________________________________________________________
+
+
+
+
+
+//_____________________________________________________________________________
+// Test a face
+// if face>0 return true if the face contains a part of the surface
+template<typename DataWrapper >
+bool MarchingCubes<DataWrapper >::test_face( schar face )
+//-----------------------------------------------------------------------------
+{
+   real A,B,C,D ;
+
+   switch( face )
+   {
+   case -1 : case 1 :  A = _cube[0] ;  B = _cube[4] ;  C = _cube[5] ;  D = _cube[1] ;  break ;
+   case -2 : case 2 :  A = _cube[1] ;  B = _cube[5] ;  C = _cube[6] ;  D = _cube[2] ;  break ;
+   case -3 : case 3 :  A = _cube[2] ;  B = _cube[6] ;  C = _cube[7] ;  D = _cube[3] ;  break ;
+   case -4 : case 4 :  A = _cube[3] ;  B = _cube[7] ;  C = _cube[4] ;  D = _cube[0] ;  break ;
+   case -5 : case 5 :  A = _cube[0] ;  B = _cube[3] ;  C = _cube[2] ;  D = _cube[1] ;  break ;
+   case -6 : case 6 :  A = _cube[4] ;  B = _cube[7] ;  C = _cube[6] ;  D = _cube[5] ;  break ;
+   default : 
+      std::cerr<<" MarchingCubes<DataWrapper >::test_face ["<<__LINE__<<"]:: Invalid face code "<< face <<std::endl;
+      print_cube(std::cerr);  
+      A = B = C = D = 0 ;
+   };
+
+   if( std::fabs( A*C - B*D ) < FLT_EPSILON )
+      return face >= 0 ;
+   return face * A * ( A*C - B*D ) >= 0  ;  // face and A invert signs
+}
+//_____________________________________________________________________________
+
+
+
+
+
+//_____________________________________________________________________________
+// Test the interior of a cube
+// if s == 7, return true  if the interior is empty
+// if s ==-7, return false if the interior is empty
+template<typename DataWrapper >
+bool MarchingCubes<DataWrapper >::test_interior( schar s )
+//-----------------------------------------------------------------------------
+{
+   real t, At=0, Bt=0, Ct=0, Dt=0, a, b ;
+   char  test =  0 ;
+   char  edge = -1 ; // reference edge of the triangulation
+
+   switch( _case )
+   {
+   case  4 :
+   case 10 :
+      a = ( _cube[4] - _cube[0] ) * ( _cube[6] - _cube[2] ) - ( _cube[7] - _cube[3] ) * ( _cube[5] - _cube[1] ) ;
+      b =  _cube[2] * ( _cube[4] - _cube[0] ) + _cube[0] * ( _cube[6] - _cube[2] )
+         - _cube[1] * ( _cube[7] - _cube[3] ) - _cube[3] * ( _cube[5] - _cube[1] ) ;
+      t = - b / (2*a) ;
+      if( t<0 || t>1 ) return s>0 ;
+
+      At = _cube[0] + ( _cube[4] - _cube[0] ) * t ;
+      Bt = _cube[3] + ( _cube[7] - _cube[3] ) * t ;
+      Ct = _cube[2] + ( _cube[6] - _cube[2] ) * t ;
+      Dt = _cube[1] + ( _cube[5] - _cube[1] ) * t ;
+      break ;
+
+   case  6 :
+   case  7 :
+   case 12 :
+   case 13 :
+      switch( _case )
+      {
+      case  6 : edge = test6 [_config][2] ; break ;
+      case  7 : edge = test7 [_config][4] ; break ;
+      case 12 : edge = test12[_config][3] ; break ;
+      case 13 : edge = tiling13_5_1[_config][_subconfig][0] ; break ;
+      }
+      switch( edge )
+      {
+      case  0 :
+         t  = _cube[0] / ( _cube[0] - _cube[1] ) ;
+         At = 0 ;
+         Bt = _cube[3] + ( _cube[2] - _cube[3] ) * t ;
+         Ct = _cube[7] + ( _cube[6] - _cube[7] ) * t ;
+         Dt = _cube[4] + ( _cube[5] - _cube[4] ) * t ;
+         break ;
+      case  1 :
+         t  = _cube[1] / ( _cube[1] - _cube[2] ) ;
+         At = 0 ;
+         Bt = _cube[0] + ( _cube[3] - _cube[0] ) * t ;
+         Ct = _cube[4] + ( _cube[7] - _cube[4] ) * t ;
+         Dt = _cube[5] + ( _cube[6] - _cube[5] ) * t ;
+         break ;
+      case  2 :
+         t  = _cube[2] / ( _cube[2] - _cube[3] ) ;
+         At = 0 ;
+         Bt = _cube[1] + ( _cube[0] - _cube[1] ) * t ;
+         Ct = _cube[5] + ( _cube[4] - _cube[5] ) * t ;
+         Dt = _cube[6] + ( _cube[7] - _cube[6] ) * t ;
+         break ;
+      case  3 :
+         t  = _cube[3] / ( _cube[3] - _cube[0] ) ;
+         At = 0 ;
+         Bt = _cube[2] + ( _cube[1] - _cube[2] ) * t ;
+         Ct = _cube[6] + ( _cube[5] - _cube[6] ) * t ;
+         Dt = _cube[7] + ( _cube[4] - _cube[7] ) * t ;
+         break ;
+      case  4 :
+         t  = _cube[4] / ( _cube[4] - _cube[5] ) ;
+         At = 0 ;
+         Bt = _cube[7] + ( _cube[6] - _cube[7] ) * t ;
+         Ct = _cube[3] + ( _cube[2] - _cube[3] ) * t ;
+         Dt = _cube[0] + ( _cube[1] - _cube[0] ) * t ;
+         break ;
+      case  5 :
+         t  = _cube[5] / ( _cube[5] - _cube[6] ) ;
+         At = 0 ;
+         Bt = _cube[4] + ( _cube[7] - _cube[4] ) * t ;
+         Ct = _cube[0] + ( _cube[3] - _cube[0] ) * t ;
+         Dt = _cube[1] + ( _cube[2] - _cube[1] ) * t ;
+         break ;
+      case  6 :
+         t  = _cube[6] / ( _cube[6] - _cube[7] ) ;
+         At = 0 ;
+         Bt = _cube[5] + ( _cube[4] - _cube[5] ) * t ;
+         Ct = _cube[1] + ( _cube[0] - _cube[1] ) * t ;
+         Dt = _cube[2] + ( _cube[3] - _cube[2] ) * t ;
+         break ;
+      case  7 :
+         t  = _cube[7] / ( _cube[7] - _cube[4] ) ;
+         At = 0 ;
+         Bt = _cube[6] + ( _cube[5] - _cube[6] ) * t ;
+         Ct = _cube[2] + ( _cube[1] - _cube[2] ) * t ;
+         Dt = _cube[3] + ( _cube[0] - _cube[3] ) * t ;
+         break ;
+      case  8 :
+         t  = _cube[0] / ( _cube[0] - _cube[4] ) ;
+         At = 0 ;
+         Bt = _cube[3] + ( _cube[7] - _cube[3] ) * t ;
+         Ct = _cube[2] + ( _cube[6] - _cube[2] ) * t ;
+         Dt = _cube[1] + ( _cube[5] - _cube[1] ) * t ;
+         break ;
+      case  9 :
+         t  = _cube[1] / ( _cube[1] - _cube[5] ) ;
+         At = 0 ;
+         Bt = _cube[0] + ( _cube[4] - _cube[0] ) * t ;
+         Ct = _cube[3] + ( _cube[7] - _cube[3] ) * t ;
+         Dt = _cube[2] + ( _cube[6] - _cube[2] ) * t ;
+         break ;
+      case 10 :
+         t  = _cube[2] / ( _cube[2] - _cube[6] ) ;
+         At = 0 ;
+         Bt = _cube[1] + ( _cube[5] - _cube[1] ) * t ;
+         Ct = _cube[0] + ( _cube[4] - _cube[0] ) * t ;
+         Dt = _cube[3] + ( _cube[7] - _cube[3] ) * t ;
+         break ;
+      case 11 :
+         t  = _cube[3] / ( _cube[3] - _cube[7] ) ;
+         At = 0 ;
+         Bt = _cube[2] + ( _cube[6] - _cube[2] ) * t ;
+         Ct = _cube[1] + ( _cube[5] - _cube[1] ) * t ;
+         Dt = _cube[0] + ( _cube[4] - _cube[0] ) * t ;
+         break ;
+      default : 
+         std::cerr<<" MarchingCubes<DataWrapper >::test_interior ["<<__LINE__<<"]: Invalid edge "<< edge <<std::endl;
+         print_cube(std::cerr);  
+         break;
+      }
+      break ;
+
+   default : 
+      std::cerr<<" MarchingCubes<DataWrapper >::test_interior ["<<__LINE__<<"]: Invalid ambiguous case "<< _case <<std::endl;
+      print_cube(std::cerr);  
+      break;
+   }
+
+   if( At >= 0 ) test ++ ;
+   if( Bt >= 0 ) test += 2 ;
+   if( Ct >= 0 ) test += 4 ;
+   if( Dt >= 0 ) test += 8 ;
+   switch( test )
+   {
+   case  0 : return s>0 ;
+   case  1 : return s>0 ;
+   case  2 : return s>0 ;
+   case  3 : return s>0 ;
+   case  4 : return s>0 ;
+   case  5 : if( At * Ct - Bt * Dt <  FLT_EPSILON ) return s>0 ; break ;
+   case  6 : return s>0 ;
+   case  7 : return s<0 ;
+   case  8 : return s>0 ;
+   case  9 : return s>0 ;
+   case 10 : if( At * Ct - Bt * Dt >= FLT_EPSILON ) return s>0 ; break ;
+   case 11 : return s<0 ;
+   case 12 : return s>0 ;
+   case 13 : return s<0 ;
+   case 14 : return s<0 ;
+   case 15 : return s<0 ;
+   }
+
+   return s<0 ;
+}
+//_____________________________________________________________________________
+
+
+
+
+//_____________________________________________________________________________
+// Process a unit cube
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::process_cube( )
+//-----------------------------------------------------------------------------
+{
+   if( _originalMC )
+   {
+      char nt = 0 ;
+      while( casesClassic[_lut_entry][3*nt] != -1 ) nt++ ;
+      add_triangle( casesClassic[_lut_entry], nt ) ;
+      return ;
+   }
+
+   int   v12 = -1 ;
+   _case   = cases[_lut_entry][0] ;
+   _config = cases[_lut_entry][1] ;
+   _subconfig = 0 ;
+
+   switch( _case )
+   {
+   case  0 :
+      break ;
+
+   case  1 :
+      add_triangle( tiling1[_config], 1 ) ;
+      break ;
+
+   case  2 :
+      add_triangle( tiling2[_config], 2 ) ;
+      break ;
+
+   case  3 :
+      if( test_face( test3[_config]) )
+         add_triangle( tiling3_2[_config], 4 ) ; // 3.2
+      else
+         add_triangle( tiling3_1[_config], 2 ) ; // 3.1
+      break ;
+
+   case  4 :
+      if( test_interior( test4[_config]) )
+         add_triangle( tiling4_1[_config], 2 ) ; // 4.1.1
+      else
+         add_triangle( tiling4_2[_config], 6 ) ; // 4.1.2
+      break ;
+
+   case  5 :
+      add_triangle( tiling5[_config], 3 ) ;
+      break ;
+
+   case  6 :
+      if( test_face( test6[_config][0]) )
+         add_triangle( tiling6_2[_config], 5 ) ; // 6.2
+      else
+      {
+         if( test_interior( test6[_config][1]) )
+            add_triangle( tiling6_1_1[_config], 3 ) ; // 6.1.1
+         else
+            add_triangle( tiling6_1_2[_config], 7 ) ; // 6.1.2
+      }
+      break ;
+
+   case  7 :
+      if( test_face( test7[_config][0] ) ) _subconfig +=  1 ;
+      if( test_face( test7[_config][1] ) ) _subconfig +=  2 ;
+      if( test_face( test7[_config][2] ) ) _subconfig +=  4 ;
+      switch( _subconfig )
+      {
+      case 0 :
+         add_triangle( tiling7_1[_config], 3 ) ; break ;
+      case 1 :
+         add_triangle( tiling7_2[_config][0], 5 ) ; break ;
+      case 2 :
+         add_triangle( tiling7_2[_config][1], 5 ) ; break ;
+      case 3 :
+         v12 = add_c_vertex() ;
+         add_triangle( tiling7_3[_config][0], 9, v12 ) ; break ;
+      case 4 :
+         add_triangle( tiling7_2[_config][2], 5 ) ; break ;
+      case 5 :
+         v12 = add_c_vertex() ;
+         add_triangle( tiling7_3[_config][1], 9, v12 ) ; break ;
+      case 6 :
+         v12 = add_c_vertex() ;
+         add_triangle( tiling7_3[_config][2], 9, v12 ) ; break ;
+      case 7 :
+         if( test_interior( test7[_config][3]) )
+            add_triangle( tiling7_4_2[_config], 9 ) ;
+         else
+            add_triangle( tiling7_4_1[_config], 5 ) ;
+         break ;
+      };
+      break ;
+
+   case  8 :
+      add_triangle( tiling8[_config], 2 ) ;
+      break ;
+
+   case  9 :
+      add_triangle( tiling9[_config], 4 ) ;
+      break ;
+
+   case 10 :
+      if( test_face( test10[_config][0]) )
+      {
+         if( test_face( test10[_config][1]) )
+            add_triangle( tiling10_1_1_[_config], 4 ) ; // 10.1.1
+         else
+         {
+            v12 = add_c_vertex() ;
+            add_triangle( tiling10_2[_config], 8, v12 ) ; // 10.2
+         }
+      }
+      else
+      {
+         if( test_face( test10[_config][1]) )
+         {
+            v12 = add_c_vertex() ;
+            add_triangle( tiling10_2_[_config], 8, v12 ) ; // 10.2
+         }
+         else
+         {
+            if( test_interior( test10[_config][2]) )
+               add_triangle( tiling10_1_1[_config], 4 ) ; // 10.1.1
+            else
+               add_triangle( tiling10_1_2[_config], 8 ) ; // 10.1.2
+         }
+      }
+      break ;
+
+   case 11 :
+      add_triangle( tiling11[_config], 4 ) ;
+      break ;
+
+   case 12 :
+      if( test_face( test12[_config][0]) )
+      {
+         if( test_face( test12[_config][1]) )
+            add_triangle( tiling12_1_1_[_config], 4 ) ; // 12.1.1
+         else
+         {
+            v12 = add_c_vertex() ;
+            add_triangle( tiling12_2[_config], 8, v12 ) ; // 12.2
+         }
+      }
+      else
+      {
+         if( test_face( test12[_config][1]) )
+         {
+            v12 = add_c_vertex() ;
+            add_triangle( tiling12_2_[_config], 8, v12 ) ; // 12.2
+         }
+         else
+         {
+            if( test_interior( test12[_config][2]) )
+               add_triangle( tiling12_1_1[_config], 4 ) ; // 12.1.1
+            else
+               add_triangle( tiling12_1_2[_config], 8 ) ; // 12.1.2
+         }
+      }
+      break ;
+
+   case 13 :
+      if( test_face( test13[_config][0] ) ) _subconfig +=  1 ;
+      if( test_face( test13[_config][1] ) ) _subconfig +=  2 ;
+      if( test_face( test13[_config][2] ) ) _subconfig +=  4 ;
+      if( test_face( test13[_config][3] ) ) _subconfig +=  8 ;
+      if( test_face( test13[_config][4] ) ) _subconfig += 16 ;
+      if( test_face( test13[_config][5] ) ) _subconfig += 32 ;
+      switch( subconfig13[_subconfig] )
+      {
+      case 0 :/* 13.1 */
+         add_triangle( tiling13_1[_config], 4 ) ; break ;
+
+      case 1 :/* 13.2 */
+         add_triangle( tiling13_2[_config][0], 6 ) ; break ;
+      case 2 :/* 13.2 */
+         add_triangle( tiling13_2[_config][1], 6 ) ; break ;
+      case 3 :/* 13.2 */
+         add_triangle( tiling13_2[_config][2], 6 ) ; break ;
+      case 4 :/* 13.2 */
+         add_triangle( tiling13_2[_config][3], 6 ) ; break ;
+      case 5 :/* 13.2 */
+         add_triangle( tiling13_2[_config][4], 6 ) ; break ;
+      case 6 :/* 13.2 */
+         add_triangle( tiling13_2[_config][5], 6 ) ; break ;
+
+      case 7 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][0], 10, v12 ) ; break ;
+      case 8 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][1], 10, v12 ) ; break ;
+      case 9 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][2], 10, v12 ) ; break ;
+      case 10 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][3], 10, v12 ) ; break ;
+      case 11 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][4], 10, v12 ) ; break ;
+      case 12 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][5], 10, v12 ) ; break ;
+      case 13 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][6], 10, v12 ) ; break ;
+      case 14 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][7], 10, v12 ) ; break ;
+      case 15 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][8], 10, v12 ) ; break ;
+      case 16 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][9], 10, v12 ) ; break ;
+      case 17 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][10], 10, v12 ) ; break ;
+      case 18 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3[_config][11], 10, v12 ) ; break ;
+
+      case 19 :/* 13.4 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_4[_config][0], 12, v12 ) ; break ;
+      case 20 :/* 13.4 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_4[_config][1], 12, v12 ) ; break ;
+      case 21 :/* 13.4 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_4[_config][2], 12, v12 ) ; break ;
+      case 22 :/* 13.4 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_4[_config][3], 12, v12 ) ; break ;
+
+      case 23 :/* 13.5 */
+         _subconfig = 0 ;
+         if( test_interior( test13[_config][6] ) )
+            add_triangle( tiling13_5_1[_config][0], 6 ) ;
+         else
+            add_triangle( tiling13_5_2[_config][0], 10 ) ;
+         break ;
+      case 24 :/* 13.5 */
+         _subconfig = 1 ;
+         if( test_interior( test13[_config][6] ) )
+            add_triangle( tiling13_5_1[_config][1], 6 ) ;
+         else
+            add_triangle( tiling13_5_2[_config][1], 10 ) ;
+         break ;
+      case 25 :/* 13.5 */
+         _subconfig = 2 ;
+         if( test_interior( test13[_config][6] ) )
+            add_triangle( tiling13_5_1[_config][2], 6 ) ;
+         else
+            add_triangle( tiling13_5_2[_config][2], 10 ) ;
+         break ;
+      case 26 :/* 13.5 */
+         _subconfig = 3 ;
+         if( test_interior( test13[_config][6] ) )
+            add_triangle( tiling13_5_1[_config][3], 6 ) ;
+         else
+            add_triangle( tiling13_5_2[_config][3], 10 ) ;
+         break ;
+
+      case 27 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][0], 10, v12 ) ; break ;
+      case 28 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][1], 10, v12 ) ; break ;
+      case 29 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][2], 10, v12 ) ; break ;
+      case 30 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][3], 10, v12 ) ; break ;
+      case 31 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][4], 10, v12 ) ; break ;
+      case 32 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][5], 10, v12 ) ; break ;
+      case 33 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][6], 10, v12 ) ; break ;
+      case 34 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][7], 10, v12 ) ; break ;
+      case 35 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][8], 10, v12 ) ; break ;
+      case 36 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][9], 10, v12 ) ; break ;
+      case 37 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][10], 10, v12 ) ; break ;
+      case 38 :/* 13.3 */
+         v12 = add_c_vertex() ;
+         add_triangle( tiling13_3_[_config][11], 10, v12 ) ; break ;
+
+      case 39 :/* 13.2 */
+         add_triangle( tiling13_2_[_config][0], 6 ) ; break ;
+      case 40 :/* 13.2 */
+         add_triangle( tiling13_2_[_config][1], 6 ) ; break ;
+      case 41 :/* 13.2 */
+         add_triangle( tiling13_2_[_config][2], 6 ) ; break ;
+      case 42 :/* 13.2 */
+         add_triangle( tiling13_2_[_config][3], 6 ) ; break ;
+      case 43 :/* 13.2 */
+         add_triangle( tiling13_2_[_config][4], 6 ) ; break ;
+      case 44 :/* 13.2 */
+         add_triangle( tiling13_2_[_config][5], 6 ) ; break ;
+
+      case 45 :/* 13.1 */
+         add_triangle( tiling13_1_[_config], 4 ) ; break ;
+
+      default :
+         std::cerr<<" MarchingCubes<DataWrapper >::process_cube ["<<__LINE__<<"]: Impossible case 13?"<<std::endl;
+         print_cube(std::cerr);  
+      }
+      break ;
+
+   case 14 :
+      add_triangle( tiling14[_config], 4 ) ;
+      break ;
+   };
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// Adding triangles
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::add_triangle( const char* trig, char n, int v12 )
+//-----------------------------------------------------------------------------
+{
+   int    tv[3] ;
+
+   for( int t = 0 ; t < 3*n ; t++ )
+   {
+      switch( trig[t] )
+      {
+      case  0 : tv[ t % 3 ] = get_x_vert( _i , _j , _k ) ; break ;
+      case  1 : tv[ t % 3 ] = get_y_vert(_i+1, _j , _k ) ; break ;
+      case  2 : tv[ t % 3 ] = get_x_vert( _i ,_j+1, _k ) ; break ;
+      case  3 : tv[ t % 3 ] = get_y_vert( _i , _j , _k ) ; break ;
+      case  4 : tv[ t % 3 ] = get_x_vert( _i , _j ,_k+1) ; break ;
+      case  5 : tv[ t % 3 ] = get_y_vert(_i+1, _j ,_k+1) ; break ;
+      case  6 : tv[ t % 3 ] = get_x_vert( _i ,_j+1,_k+1) ; break ;
+      case  7 : tv[ t % 3 ] = get_y_vert( _i , _j ,_k+1) ; break ;
+      case  8 : tv[ t % 3 ] = get_z_vert( _i , _j , _k ) ; break ;
+      case  9 : tv[ t % 3 ] = get_z_vert(_i+1, _j , _k ) ; break ;
+      case 10 : tv[ t % 3 ] = get_z_vert(_i+1,_j+1, _k ) ; break ;
+      case 11 : tv[ t % 3 ] = get_z_vert( _i ,_j+1, _k ) ; break ;
+      case 12 : tv[ t % 3 ] = v12 ; break ;
+      default : break ;
+      }
+
+      if( tv[t%3] == -1 )
+      {
+         std::cerr<<"Marching Cubes::add_triangle  ["<<__LINE__<<"]: invalid triangle "<<_ntrigs+1<<std::endl;
+         print_cube(std::cerr) ;
+      }
+
+      if( t%3 == 2 )
+      {
+         if( _ntrigs >= _Ntrigs )
+         {
+            Triangle *temp = _triangles ;
+            _triangles = new Triangle[ 2*_Ntrigs ] ;
+            memcpy( _triangles, temp, _Ntrigs*sizeof(Triangle) ) ;
+            delete[] temp ;
+            //std::cout<<_Ntrigs <<" allocated triangles"<<std::endl;
+            _Ntrigs *= 2 ;
+         }
+
+         Triangle *T = _triangles + _ntrigs++ ;
+         T->v1    = tv[0] ;
+         T->v2    = tv[1] ;
+         T->v3    = tv[2] ;
+      }
+   }
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+// Calculating gradient
+
+template<typename DataWrapper >
+real MarchingCubes<DataWrapper >::get_x_grad( const int i, const int j, const int k ) const
+//-----------------------------------------------------------------------------
+{
+   if( i > 0 )
+   {
+      if ( i < dataWrapper.getNX1() - 1 )
+         return ( get_data( i+1, j, k ) - get_data( i-1, j, k ) ) / 2 ;
+      else
+         return get_data( i, j, k ) - get_data( i-1, j, k ) ;
+   }
+   else
+      return get_data( i+1, j, k ) - get_data( i, j, k ) ;
+}
+//-----------------------------------------------------------------------------
+
+template<typename DataWrapper >
+real MarchingCubes<DataWrapper >::get_y_grad( const int i, const int j, const int k ) const
+//-----------------------------------------------------------------------------
+{
+   if( j > 0 )
+   {
+      if ( j < dataWrapper.getNX2() - 1 )
+         return ( get_data( i, j+1, k ) - get_data( i, j-1, k ) ) / 2 ;
+      else
+         return get_data( i, j, k ) - get_data( i, j-1, k ) ;
+   }
+   else
+      return get_data( i, j+1, k ) - get_data( i, j, k ) ;
+}
+//-----------------------------------------------------------------------------
+
+template<typename DataWrapper >
+real MarchingCubes<DataWrapper >::get_z_grad( const int i, const int j, const int k ) const
+//-----------------------------------------------------------------------------
+{
+   if( k > 0 )
+   {
+      if ( k < dataWrapper.getNX3() - 1 )
+         return ( get_data( i, j, k+1 ) - get_data( i, j, k-1 ) ) / 2 ;
+      else
+         return get_data( i, j, k ) - get_data( i, j, k-1 ) ;
+   }
+   else
+      return get_data( i, j, k+1 ) - get_data( i, j, k ) ;
+}
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+// Adding vertices
+
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::test_vertex_addition()
+{
+   if( _nverts >= _Nverts )
+   {
+      Vertex *temp = _vertices ;
+      _vertices = new Vertex[ _Nverts*2 ] ;
+      memcpy( _vertices, temp, _Nverts*sizeof(Vertex) ) ;
+      delete[] temp ;
+      //std::cout<<_Nverts<<" allocated vertices"<<std::endl;
+      _Nverts *= 2 ;
+   }
+}
+
+
+template<typename DataWrapper >
+int MarchingCubes<DataWrapper >::add_x_vertex( )
+//-----------------------------------------------------------------------------
+{
+   test_vertex_addition() ;
+   Vertex *vert = _vertices + _nverts++ ;
+
+   real u = ( _cube[0] ) / ( _cube[0] - _cube[1] ) ;
+
+   vert->x      = (real)_i+u;
+   vert->y      = (real) _j ;
+   vert->z      = (real) _k ;
+
+   vert->nx = (1-u)*get_x_grad(_i,_j,_k) + u*get_x_grad(_i+1,_j,_k) ;
+   vert->ny = (1-u)*get_y_grad(_i,_j,_k) + u*get_y_grad(_i+1,_j,_k) ;
+   vert->nz = (1-u)*get_z_grad(_i,_j,_k) + u*get_z_grad(_i+1,_j,_k) ;
+
+   u = (real) sqrt( vert->nx * vert->nx + vert->ny * vert->ny +vert->nz * vert->nz ) ;
+   if( u > 0 )
+   {
+      vert->nx /= u ;
+      vert->ny /= u ;
+      vert->nz /= u ;
+   }
+
+
+   return _nverts-1 ;
+}
+//-----------------------------------------------------------------------------
+
+template<typename DataWrapper >
+int MarchingCubes<DataWrapper >::add_y_vertex( )
+//-----------------------------------------------------------------------------
+{
+   test_vertex_addition() ;
+   Vertex *vert = _vertices + _nverts++ ;
+
+   real u = ( _cube[0] ) / ( _cube[0] - _cube[3] ) ;
+
+   vert->x      = (real) _i ;
+   vert->y      = (real)_j+u;
+   vert->z      = (real) _k ;
+
+   vert->nx = (1-u)*get_x_grad(_i,_j,_k) + u*get_x_grad(_i,_j+1,_k) ;
+   vert->ny = (1-u)*get_y_grad(_i,_j,_k) + u*get_y_grad(_i,_j+1,_k) ;
+   vert->nz = (1-u)*get_z_grad(_i,_j,_k) + u*get_z_grad(_i,_j+1,_k) ;
+
+   u = (real) sqrt( vert->nx * vert->nx + vert->ny * vert->ny +vert->nz * vert->nz ) ;
+   if( u > 0 )
+   {
+      vert->nx /= u ;
+      vert->ny /= u ;
+      vert->nz /= u ;
+   }
+
+   return _nverts-1 ;
+}
+//-----------------------------------------------------------------------------
+
+template<typename DataWrapper >
+int MarchingCubes<DataWrapper >::add_z_vertex( )
+//-----------------------------------------------------------------------------
+{
+   test_vertex_addition() ;
+   Vertex *vert = _vertices + _nverts++ ;
+
+   real u = ( _cube[0] ) / ( _cube[0] - _cube[4] ) ;
+
+   vert->x      = (real) _i ;
+   vert->y      = (real) _j ;
+   vert->z      = (real)_k+u;
+
+   vert->nx = (1-u)*get_x_grad(_i,_j,_k) + u*get_x_grad(_i,_j,_k+1) ;
+   vert->ny = (1-u)*get_y_grad(_i,_j,_k) + u*get_y_grad(_i,_j,_k+1) ;
+   vert->nz = (1-u)*get_z_grad(_i,_j,_k) + u*get_z_grad(_i,_j,_k+1) ;
+
+   u = (real) sqrt( vert->nx * vert->nx + vert->ny * vert->ny +vert->nz * vert->nz ) ;
+   if( u > 0 )
+   {
+      vert->nx /= u ;
+      vert->ny /= u ;
+      vert->nz /= u ;
+   }
+
+   return _nverts-1 ;
+}
+
+
+template<typename DataWrapper >
+int MarchingCubes<DataWrapper >::add_c_vertex( )
+//-----------------------------------------------------------------------------
+{
+   test_vertex_addition() ;
+   Vertex *vert = _vertices + _nverts++ ;
+
+   real u = 0 ;
+   int   vid ;
+
+   vert->x = vert->y = vert->z =  vert->nx = vert->ny = vert->nz = 0 ;
+
+   // Computes the average of the intersection points of the cube
+   vid = get_x_vert( _i , _j , _k ) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_y_vert(_i+1, _j , _k ) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_x_vert( _i ,_j+1, _k ) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_y_vert( _i , _j , _k ) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_x_vert( _i , _j ,_k+1) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_y_vert(_i+1, _j ,_k+1) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_x_vert( _i ,_j+1,_k+1) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_y_vert( _i , _j ,_k+1) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_z_vert( _i , _j , _k ) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_z_vert(_i+1, _j , _k ) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_z_vert(_i+1,_j+1, _k ) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+   vid = get_z_vert( _i ,_j+1, _k ) ;
+   if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ;  vert->y += v.y ;  vert->z += v.z ;  vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; }
+
+   vert->x  /= u ;
+   vert->y  /= u ;
+   vert->z  /= u ;
+
+   u = (real) sqrt( vert->nx * vert->nx + vert->ny * vert->ny +vert->nz * vert->nz ) ;
+   if( u > 0 )
+   {
+      vert->nx /= u ;
+      vert->ny /= u ;
+      vert->nz /= u ;
+   }
+
+   return _nverts-1 ;
+}
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+//_____________________________________________________________________________
+
+
+
+
+//_____________________________________________________________________________
+// Grid exportation
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::writeISO(const char *fn )
+//-----------------------------------------------------------------------------
+{
+   unsigned char buf[sizeof(float)] ;
+
+   FILE *fp = fopen( fn, "wb" ) ;
+
+   // header
+   * (int*) buf = dataWrapper.getNX1() ;
+   fwrite(buf, sizeof(float), 1, fp);
+   * (int*) buf = dataWrapper.getNX2() ;
+   fwrite(buf, sizeof(float), 1, fp);
+   * (int*) buf = dataWrapper.getNX3();
+   fwrite(buf, sizeof(float), 1, fp);
+
+   * (float*) buf = -1.0f ;
+   fwrite(buf, sizeof(float), 1, fp);
+   * (float*) buf =  1.0f ;
+   fwrite(buf, sizeof(float), 1, fp);
+   * (float*) buf = -1.0f ;
+   fwrite(buf, sizeof(float), 1, fp);
+   * (float*) buf =  1.0f ;
+   fwrite(buf, sizeof(float), 1, fp);
+   * (float*) buf = -1.0f ;
+   fwrite(buf, sizeof(float), 1, fp);
+   * (float*) buf =  1.0f ;
+   fwrite(buf, sizeof(float), 1, fp);
+
+   for( int i = 0 ; i < dataWrapper.getNX1() ; i++ )
+   {
+      for( int j = 0 ; j < dataWrapper.getNX2() ; j++ )
+      {
+         for( int k = 0 ; k < dataWrapper.getNX3() ; k++ )
+         {
+            * (float*) buf = (float)get_data( i,j,k ) ;
+            fwrite(buf, sizeof(float), 1, fp);
+         }
+      }
+   }
+
+   fclose(fp) ;
+}
+//_____________________________________________________________________________
+
+
+
+
+
+//_____________________________________________________________________________
+// PLY exportation
+
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::writePLY(const char *fn, bool bin )
+//-----------------------------------------------------------------------------
+{
+
+   typedef struct PlyFace {
+      unsigned char nverts;    /* number of Vertex indices in list */
+      int *verts;              /* Vertex index list */
+   } PlyFace;
+
+
+   PlyProperty vert_props[]  = { /* list of property information for a PlyVertex */
+      {"x", Float32, Float32, offsetof( Vertex,x ), 0, 0, 0, 0},
+      {"y", Float32, Float32, offsetof( Vertex,y ), 0, 0, 0, 0},
+      {"z", Float32, Float32, offsetof( Vertex,z ), 0, 0, 0, 0},
+      {"nx", Float32, Float32, offsetof( Vertex,nx ), 0, 0, 0, 0},
+      {"ny", Float32, Float32, offsetof( Vertex,ny ), 0, 0, 0, 0},
+      {"nz", Float32, Float32, offsetof( Vertex,nz ), 0, 0, 0, 0}
+   };
+
+   PlyProperty face_props[]  = { /* list of property information for a PlyFace */
+      {"vertex_indices", Int32, Int32, offsetof( PlyFace,verts ),
+      1, Uint8, Uint8, offsetof( PlyFace,nverts )},
+   };
+
+
+   PlyFile    *ply;
+   FILE       *fp = fopen( fn, "w" );
+
+   int          i ;
+   PlyFace     face ;
+   int         verts[3] ;
+   char       *elem_names[]  = { "vertex", "face" };
+   std::cout<<"McCubes.MarchingCubes<DataWrapper >.writePLY ("<<fn<<")...";
+   ply = write_ply ( fp, 2, elem_names, bin? PLY_BINARY_LE : PLY_ASCII );
+
+   /* describe what properties go into the PlyVertex elements */
+   describe_element_ply ( ply, "vertex", _nverts );
+   describe_property_ply ( ply, &vert_props[0] );
+   describe_property_ply ( ply, &vert_props[1] );
+   describe_property_ply ( ply, &vert_props[2] );
+   describe_property_ply ( ply, &vert_props[3] );
+   describe_property_ply ( ply, &vert_props[4] );
+   describe_property_ply ( ply, &vert_props[5] );
+
+   /* describe PlyFace properties (just list of PlyVertex indices) */
+   describe_element_ply ( ply, "face", _ntrigs );
+   describe_property_ply ( ply, &face_props[0] );
+
+   header_complete_ply ( ply );
+
+   /* set up and write the PlyVertex elements */
+   put_element_setup_ply ( ply, "vertex" );
+   for ( i = 0; i < _nverts; i++ )
+      put_element_ply ( ply, ( void * ) &(_vertices[i]) );
+   std::cout<<_nverts<<" vertices written\n";
+
+   /* set up and write the PlyFace elements */
+   put_element_setup_ply ( ply, "face" );
+   face.nverts = 3 ;
+   face.verts  = verts ;
+   for ( i = 0; i < _ntrigs; i++ )
+   {
+      face.verts[0] = _triangles[i].v1 ;
+      face.verts[1] = _triangles[i].v2 ;
+      face.verts[2] = _triangles[i].v3 ;
+      put_element_ply ( ply, ( void * ) &face );
+   }
+   std::cout<<_ntrigs<<" triangles written\n";
+   
+   close_ply ( ply );
+   free_ply ( ply );
+   fclose( fp ) ;
+}
+//_____________________________________________________________________________
+
+//_____________________________________________________________________________
+// Open Inventor / VRML 1.0 ascii exportation
+template<typename DataWrapper >
+void MarchingCubes<DataWrapper >::writeIV(const char *fn )
+//-----------------------------------------------------------------------------
+{
+   FILE *fp = fopen( fn, "w" ) ;
+   int   i ;
+
+   std::cout<<"Marching Cubes::exportIV("<<fn<<")...";
+
+   fprintf( fp, "#Inventor V2.1 ascii \n\nSeparator { \n    ShapeHints {\n        vertexOrdering  COUNTERCLOCKWISE\n        shapeType       UNKNOWN_SHAPE_TYPE\n        creaseAngle     0.0\n    }\n Coordinate3 { \n point [  \n" ) ;
+   for ( i = 0; i < _nverts; i++ )
+      fprintf( fp, " %f %f %f,\n", _vertices[i].x, _vertices[i].y, _vertices[i].z ) ;
+   std::cout<<_nverts<<" vertices written\n";
+
+   fprintf( fp, "\n ] \n} \nNormal { \nvector [ \n" ) ;
+   for ( i = 0; i < _nverts; i++ )
+      fprintf( fp, " %f %f %f,\n", _vertices[i].nx, _vertices[i].ny, _vertices[i].nz ) ;
+
+   fprintf( fp, "\n ] \n} \nIndexedFaceSet { \ncoordIndex [ \n" ) ;
+   for ( i = 0; i < _ntrigs; i++ )
+      fprintf( fp, "%d, %d, %d, -1,\n", _triangles[i].v1, _triangles[i].v2, _triangles[i].v3 ) ;
+
+   fprintf( fp, " ] \n } \n } \n" ) ;
+   fclose( fp ) ;
+   std::cout<<_ntrigs<<" triangles written\n";
+}
+
+/*=======================================================================*/
+template<typename DataWrapper >
+void MarchingCubes< DataWrapper >::writeUCD( std::string filename )
+{
+   std::cout<<"MarchingCubes::writeUCD("<<filename<<")...";
+
+   //Dreiecke in UCD Datei schreiben
+   std::ofstream out(filename.c_str());
+   if(!out) throw UbException(UB_EXARGS,"couldn't open "+filename);
+
+   out<<"# UCD-File containing triangulated geometry data"<<std::endl;
+   out<<this->nverts()<<" "<<this->ntrigs()<<" 0 0 0"<<std::endl;
+
+   int count = 1;
+   for(int k=0;k<this->nverts();k++) 
+      out<<count++<<" "<<_vertices[k].x<<" "<<_vertices[k].y<<" "<<_vertices[k].z<<std::endl;
+
+   count = 1;
+   for(int k=0;k<this->ntrigs();k++)
+      out<<count++<<" "<<"1"<<" tri "<<_triangles[k].v1+1<<" " <<_triangles[k].v2+1<<" "<<_triangles[k].v3+1<<std::endl;
+
+   out.flush();
+   out.close();
+   std::cout<<"done\n";
+
+}
+
+template<typename DataWrapper >
+void MarchingCubes< DataWrapper >::writeUCDwithNormals( std::string filename)
+{
+   std::cout<<"MarchingCubes::writeUCDwithNormals("<<filename<<")...";
+
+   //Dreiecke in UCD Datei schreiben
+   std::ofstream out(filename.c_str());
+   if(!out) throw UbException(UB_EXARGS,"couldn't open "+filename);
+
+   out<<"# UCD-File containing triangulated geometry data an vertex normals"<<std::endl;
+   out<<2*this->nverts()<<" "<<this->ntrigs()+this->nverts()<<" 0 0 0"<<std::endl;
+
+   int count = 1;
+   for(int k=0;k<this->nverts();k++) out<<count++<<" "<<_vertices[k].x+_vertices[k].nx<<" "<<_vertices[k].y+_vertices[k].ny<<" "<<_vertices[k].z+_vertices[k].nz<<std::endl;
+   for(int k=0;k<this->nverts();k++) out<<count++<<" "<<_vertices[k].x+_vertices[k].nx<<" "<<_vertices[k].y+_vertices[k].ny<<" "<<_vertices[k].z+_vertices[k].nz<<std::endl;
+
+   count = 1;
+   for(int k=0;k<this->ntrigs();k++)
+      out<<count++<<" "<<"1"<<" tri "<<_triangles[k].v1+1<<" " <<_triangles[k].v2+1<<" "<<_triangles[k].v3+1<<std::endl;
+
+   for(int k=0;k<this->nverts();k++)
+      out<<count++<<" "<< "1"<<" line "<<k+1<<" " <<this->nverts()+k+1<<" "<<std::endl;
+
+   out.flush();
+   out.close();
+   std::cout<<"done\n";
+}
+
+} //namespace McCubes
+
+#endif // _MARCHINGCUBES_H_
diff --git a/source/ThirdParty/MarchingCubes/Matrix3DWrapper.h b/source/ThirdParty/MarchingCubes/Matrix3DWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..84482fc1f9aef3ede9b5bc1b414c25348aa4b1e6
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/Matrix3DWrapper.h
@@ -0,0 +1,126 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MATRIX3DWRAPPER_H
+#define MATRIX3DWRAPPER_H
+
+//extension by CAB
+#include <vector>
+#include <string>
+#include <fstream>
+
+#include <basics/utilities/UbException.h>
+#include <3rdParty/MarchingCubes/McTypes.h>
+
+//neu: matrix muss lediglich double operator()(int x1, int x2, int x3) überladen, dann kann man sie verwenden!!
+
+//////////////////////////////////////////////////////////////////////////
+//Matrix3DWrapper-Wrapper
+//   CbUniformMatrix3D<double> data(10,8,5);
+//   for(int x3=0; x3<data.getNX3(); x3++)
+//    for(int x2=0; x2<data.getNX2(); x2++)
+//      for(int x1=0; x1<data.getNX1(); x1++)
+//        data(x1,x2,x3) = x1;
+//
+//   Matrix3DWrapper< CbUniformMatrix3D<double> > wrapper(&data);
+//   MarchingCubes< Matrix3DWrapper< CbUniformMatrix3D<double> > > mc( wrapper );
+//
+//   mc.init_all();
+//   mc.run(3.5);
+//   mc.writeUCD("c:/temp/triangles.inp");
+//   mc.clean_all();
+
+namespace McCubes{
+
+template< typename Matrix3D >
+class Matrix3DWrapper
+{
+public:
+   Matrix3DWrapper()
+      :  matrix(NULL)
+       , minX1(-1), minX2(-1), minX3(-1)
+       , maxX1(-1), maxX2(-1), maxX3(-1)
+       , nx1(-1)  , nx2(-1)  , nx3(-1)
+   {
+      //wird benötigt, damit MarchingCubes generell eine membervariabel erstellen kann
+   }
+   /*==========================================================*/
+   Matrix3DWrapper( Matrix3D* matrix)
+      : matrix(matrix)
+   {
+      nx1 = (int)matrix->getNX1();
+      nx2 = (int)matrix->getNX2();
+      nx3 = (int)matrix->getNX3();
+
+      minX1 = minX2 = minX3 = 0;
+      maxX1 = nx1-1;
+      maxX2 = nx2-1;
+      maxX3 = nx3-1;
+   }
+   /*==========================================================*/
+   Matrix3DWrapper( Matrix3D* matrix, const int& n1, const int& nx2, const int& nx3)
+      : matrix(matrix)
+      , nx1(nx1), nx2(nx2), nx3(nx3)
+   {
+      minX1 = minX2 = minX3 = 0;
+      maxX1 = nx1-1;
+      maxX2 = nx2-1;
+      maxX3 = nx3-1;
+   }
+   /*==========================================================*/
+   Matrix3DWrapper( Matrix3D* matrix, const int& minX1, const int& minX2, const int& minX3
+                                    , const int& maxX1, const int& maxX2, const int& maxX3 )
+      :  matrix(matrix)
+       , minX1(minX1), minX2(minX2), minX3(minX3)
+       , maxX1(maxX1), maxX2(maxX2), maxX3(maxX3)
+   {
+      nx1 = matrix->getNX1();
+      nx2 = matrix->getNX2();
+      nx3 = matrix->getNX3();
+
+      if(minX1<0 || minX2<0 || minX3<0 || maxX1>=nx1 || maxX2>=nx2 || maxX3>=nx3)
+         throw UbException(UB_EXARGS,"range error");
+   }
+   /*==========================================================*/
+   //wenn man z.B. matrixX1 von[0..10] geht und man nur den bereich 1..9 fuer MC
+   //verwenden möchte -> minX1=1 und maxX2=2
+   Matrix3DWrapper( Matrix3D* matrix, const int& minX1, const int& minX2, const int& minX3
+                                    , const int& maxX1, const int& maxX2, const int& maxX3
+                                    , const int& n1   , const int& nx2  , const int& nx3   )
+      :   matrix(matrix)
+        , minX1(minX1), minX2(minX2), minX3(minX3)
+        , maxX1(maxX1), maxX2(maxX2), maxX3(maxX3)
+        , nx1(n1)     , nx2(nx2)    , nx3(nx3)
+   {
+      if(minX1<0 || minX2<0 || minX3<0 || maxX1>=nx1 || maxX2>=nx2 || maxX3>=nx3)
+         throw UbException(UB_EXARGS,"range error");
+   }
+   /*==========================================================*/
+   inline real getData(const int& x1, const int& x2, const int& x3 ) const
+   {
+      return static_cast<real>( (*matrix)(x1, x2, x3) );
+   }
+   /*==========================================================*/
+   inline int getMinX1() const { return minX1; }  
+   inline int getMinX2() const { return minX2; }  
+   inline int getMinX3() const { return minX3; }  
+
+   inline int getMaxX1() const { return maxX1; }  
+   inline int getMaxX2() const { return maxX2; }  
+   inline int getMaxX3() const { return maxX3; }  
+
+   inline int getNX1()   const { return nx1;   }  
+   inline int getNX2()   const { return nx2;   }  
+   inline int getNX3()   const { return nx3;   }  
+
+protected:
+   Matrix3D* matrix;
+   int minX1, minX2, minX3, maxX1, maxX2, maxX3, nx1, nx2, nx3;
+};
+
+} //namespace McCubes
+
+#endif //MATRIX3DWRAPPER_H
diff --git a/source/ThirdParty/MarchingCubes/Matrix4DWrapper.h b/source/ThirdParty/MarchingCubes/Matrix4DWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4dc16976d81184468d7f1dd42cac9b05010f5cc
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/Matrix4DWrapper.h
@@ -0,0 +1,131 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MATRIX4DWRAPPER_H
+#define MATRIX4DWRAPPER_H
+
+//extension by CAB
+#include <vector>
+#include <string>
+#include <fstream>
+
+#include <basics/utilities/UbException.h>
+#include <3rdParty/MarchingCubes/McTypes.h>
+
+//neu: matrix muss lediglich double operator()(int x1, int x2, int x3, int x4) überladen, dann kann man sie verwenden!!
+
+//////////////////////////////////////////////////////////////////////////
+//Matrix4DWrapper-Wrapper
+//example:
+//   int indexForDataValue = 1;
+//   CbUniformMatrix4D<double> data(10,8,5,2);
+//   for(int x3=0; x3<data.getNX3(); x3++)
+//    for(int x2=0; x2<data.getNX2(); x2++)
+//      for(int x1=0; x1<data.getNX1(); x1++)
+//        data(x1,x2,x3,indexForDataValue) = x1;
+//
+//   Matrix4DWrapper< CbUniformMatrix4D<double> > wrapper(&data,indexForDataValue);
+//   MarchingCubes< Matrix4DWrapper< CbUniformMatrix4D<double> > > mc( wrapper );
+//
+//   mc.init_all();
+//   mc.run(3.5);
+//   mc.writeUCD("c:/temp/triangles.inp");
+//   mc.clean_all();
+
+namespace McCubes{
+
+template< typename Matrix4D >
+class Matrix4DWrapper
+{
+public:
+   Matrix4DWrapper() 
+      :  valIndex(-1), matrix(NULL)
+       , minX1(-1), minX2(-1), minX3(-1)
+       , maxX1(-1), maxX2(-1), maxX3(-1)
+       , nx1(-1)  , nx2(-1)  , nx3(-1)
+   {
+      //wird benötigt, damit MarchingCubes generell eine membervariabel erstellen kann
+   }
+   /*==========================================================*/
+   Matrix4DWrapper( Matrix4D* matrix, const int& valIndex,const int& n1, const int& nx2, const int& nx3)
+      :  valIndex(valIndex), matrix(matrix)
+       , nx1(nx1), nx2(nx2), nx3(nx3)
+   {
+      minX1 = minX2 = minX3 = 0;
+      maxX1 = nx1-1;
+      maxX2 = nx2-1;
+      maxX3 = nx3-1;
+   }
+   /*==========================================================*/
+   Matrix4DWrapper( Matrix4D* matrix, const int& valIndex)
+      : valIndex(valIndex), matrix(matrix)
+   {
+      nx1 = matrix->getNX1();
+      nx2 = matrix->getNX2();
+      nx3 = matrix->getNX3();
+
+      minX1 = minX2 = minX3 = 0;
+      maxX1 = nx1-1;
+      maxX2 = nx2-1;
+      maxX3 = nx3-1;
+   }
+   /*==========================================================*/
+   //wenn man z.B. matrixX1 von[0..10] geht und man nur den bereich 1..9 fuer MC
+   //verwenden möchte -> minX1=1 und maxX2=2
+   Matrix4DWrapper( Matrix4D* matrix, const int& valIndex, const int& minX1, const int& minX2, const int& minX3,
+                                                           const int& maxX1, const int& maxX2, const int& maxX3)
+       :  valIndex(valIndex), matrix(matrix)
+        , minX1(minX1), minX2(minX2), minX3(minX3)
+        , maxX1(maxX1), maxX2(maxX2), maxX3(maxX3)
+   {
+      nx1 = matrix->getNX1();
+      nx2 = matrix->getNX2();
+      nx3 = matrix->getNX3();
+
+      if(minX1<0 || minX2<0 || minX3<0 || maxX1>=nx1 || maxX2>=nx2 || maxX3>=nx3)
+         throw UbException(UB_EXARGS,"range error");
+   }
+   /*==========================================================*/
+   //wenn man z.B. matrixX1 von[0..10] geht und man nur den bereich 1..9 fuer MC
+   //verwenden möchte -> minX1=1 und maxX2=2
+   Matrix4DWrapper( Matrix4D* matrix, const int& valIndex, const int& minX1, const int& minX2, const int& minX3
+                                                         , const int& maxX1, const int& maxX2, const int& maxX3
+                                                         , const int& n1   , const int& nx2  , const int& nx3   )
+      :  valIndex(valIndex), matrix(matrix)
+       , minX1(minX1), minX2(minX2), minX3(minX3)
+       , maxX1(maxX1), maxX2(maxX2), maxX3(maxX3)
+       , nx1(nx1)    , nx2(nx2)    , nx3(nx3)
+   {
+      if(minX1<0 || minX2<0 || minX3<0 || maxX1>=nx1 || maxX2>=nx2 || maxX3>=nx3)
+         throw UbException(UB_EXARGS,"range error");
+   }
+   /*==========================================================*/
+   inline real getData(const int& x1, const int& x2, const int& x3 ) const
+   {
+      return static_cast<real>( (*matrix)(x1, x2, x3, valIndex) );
+   }
+   /*==========================================================*/
+   inline int getMinX1() const { return minX1; }  
+   inline int getMinX2() const { return minX2; }  
+   inline int getMinX3() const { return minX3; }  
+
+   inline int getMaxX1() const { return maxX1; }  
+   inline int getMaxX2() const { return maxX2; }  
+   inline int getMaxX3() const { return maxX3; }  
+
+   inline int getNX1()   const { return nx1;   }  
+   inline int getNX2()   const { return nx2;   }  
+   inline int getNX3()   const { return nx3;   }  
+
+protected:
+   int valIndex;
+   Matrix4D* matrix;
+   int minX1, minX2, minX3, maxX1, maxX2, maxX3, nx1, nx2, nx3;
+};
+
+} //namespace McCubes
+
+#endif //MATRIX4DWRAPPER_H
diff --git a/source/ThirdParty/MarchingCubes/MatrixWrapper.h b/source/ThirdParty/MarchingCubes/MatrixWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab0c29de4b1f8da3d4b39889e95350f6552058c5
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/MatrixWrapper.h
@@ -0,0 +1,131 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MATRIXWRAPPER_H
+#define MATRIXWRAPPER_H
+
+//extension by CAB
+#include <vector>
+#include <string>
+#include <fstream>
+
+#include <basics/utilities/UbException.h>
+
+#include <3rdParty/MarchingCubes/McTypes.h>
+
+//////////////////////////////////////////////////////////////////////////
+//Standard-Wrapper
+//   MarchingCubes<DataWrapper> mc( 10,8,5 );
+//   for(int z=0; z<mc.size_z(); z++)
+//    for(int y=0; y<mc.size_y(); y++)
+//      for(int x=0; x<mc.size_x(); x++)
+//        mc.set_data(x,x,y,z);
+//
+//   mc.init_all();
+//   mc.run(3.5);
+//   mc.writeUCD("c:/temp/triangles.inp");
+//   mc.clean_all();
+
+namespace McCubes{
+
+template< typename T=real >
+class MatrixWrapper
+{
+public:
+   typedef T                                                   value_type;
+   typedef typename std::vector< value_type >::reference       reference;
+   typedef typename std::vector< value_type >::const_reference const_reference;
+   typedef typename std::vector< value_type >::pointer         pointer;
+   typedef typename std::vector< value_type >::const_pointer   const_pointer;
+
+public:
+   MatrixWrapper() : nx1(-1), nx2(-1), nx3(-1)
+   {
+   }
+   /*==========================================================*/
+   MatrixWrapper(const int& nx1, const int& nx2, const int& nx3, const T& initVal=T())
+   {
+      this->resize(nx1,nx2,nx3,initVal);
+   }
+   /*=======================================================================*/
+   reference operator() (const int& x1, const int& x2, const int& x3)
+   {
+      #ifdef _DEBUG
+         return this->data.at(x1 + x2*nx1 + x3*nx1*nx2);
+      #else
+         return this->data[x1 + x2*nx1 + x3*nx1*nx2];
+      #endif
+   }
+   /*=======================================================================*/
+   const_reference operator() (const int& x1, const int& x2, const int& x3)	const
+   {
+      #ifdef _DEBUG
+         return this->data.at(x1 + x2*nx1 + x3*nx1*nx2);
+      #else
+         return this->data[x1 + x2*nx1 + x3*nx1*nx2];
+      #endif
+   }
+   /*==========================================================*/
+   inline void setData( const T& val, const int& x1, const int& x2, const int& x3 )
+   {
+      #ifdef _DEBUG
+         this->data.at(x1 + x2*nx1 + x3*nx1*nx2) = val;
+      #else
+         this->data[x1 + x2*nx1 + x3*nx1*nx2] = val;
+      #endif
+   }
+   /*==========================================================*/
+   inline value_type getData(const int& x1, const int& x2, const int& x3 ) const
+   {
+      #ifdef _DEBUG
+         return this->data.at(x1 + x2*nx1 + x3*nx1*nx2);
+      #else
+         return this->data[x1 + x2*nx1 + x3*nx1*nx2];
+      #endif
+   }
+   /*==========================================================*/
+   inline void resize(const int& nx1, const int& nx2, const int& nx3)
+   {
+      if(nx1>0 && nx2>0 && nx3>0)
+      {
+         this->nx1 = nx1;
+         this->nx2 = nx2;
+         this->nx3 = nx3;
+         this->data.resize(nx1*nx2*nx3);
+      }
+   }
+   /*==========================================================*/
+   inline void resize(const int& nx1, const int& nx2, const int& nx3, const T& initVal)
+   {
+      if(nx1>0 && nx2>0 && nx3>0)
+      {
+         this->nx1 = nx1;
+         this->nx2 = nx2;
+         this->nx3 = nx3;
+         this->data.resize(nx1*nx2*nx3,initVal);
+      }
+   }
+   /*==========================================================*/
+   inline int getMinX1() const { return 0;     }  
+   inline int getMinX2() const { return 0;     }  
+   inline int getMinX3() const { return 0;     }  
+
+   inline int getMaxX1() const { return nx1-1; }  
+   inline int getMaxX2() const { return nx2-1; }  
+   inline int getMaxX3() const { return nx3-1; }  
+
+   inline int getNX1()   const { return nx1;   }  
+   inline int getNX2()   const { return nx2;   }  
+   inline int getNX3()   const { return nx3;   }  
+
+protected:
+   std::vector<T> data;
+   int nx1, nx2, nx3;
+};
+
+} //namespace McCubes
+
+#endif //MATRIXWRAPPER_H
diff --git a/source/ThirdParty/MarchingCubes/McLookUpTable.h b/source/ThirdParty/MarchingCubes/McLookUpTable.h
new file mode 100644
index 0000000000000000000000000000000000000000..9fed1e50175da325347559c5f137a2f5c66e1985
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/McLookUpTable.h
@@ -0,0 +1,2320 @@
+/**
+ * @file    LookUpTable.h
+ * @author  Thomas Lewiner <thomas.lewiner@polytechnique.org>
+ * @author  Math Dept, PUC-Rio
+ * @version 0.2
+ * @date    12/08/2002
+ *
+ * @brief   LookUpTable for the MarchingCubes 33 Algorithm
+ */
+//________________________________________________
+
+
+
+#ifndef MCLOOKUPTABLE_H
+#define MCLOOKUPTABLE_H
+
+namespace McCubes{ 
+
+//_____________________________________________________________________________
+/**
+ * \brief case mapping
+ * For each of the possible vertex states listed in this table there is a
+ * specific triangulation of the edge intersection points.  The table lists
+ * all of them in the form of 0-5 edge triples with the list terminated by
+ * the invalid value -1.  For example: case[3] list the 2 triangles
+ * formed when cube[0] and cube[1] are inside of the surface, but the rest of
+ * the cube is not.
+ *
+ * Cube description:
+ *         7 ________ 6           _____6__             ________
+ *         /|       /|         7/|       /|          /|       /|
+ *       /  |     /  |        /  |     /5 |        /  6     /  |
+ *   4 /_______ /    |      /__4____ /    10     /_______3/    |
+ *    |     |  |5    |     |    11  |     |     |     |  |   2 |
+ *    |    3|__|_____|2    |     |__|__2__|     | 4   |__|_____|
+ *    |    /   |    /      8   3/   9    /      |    /   |    /
+ *    |  /     |  /        |  /     |  /1       |  /     5  /
+ *    |/_______|/          |/___0___|/          |/_1_____|/
+ *   0          1        0          1
+ */
+//-----------------------------------------------------------------------------
+static const char cases[256][2] = {
+/*   0:                          */  {  0, -1 },
+/*   1: 0,                       */  {  1,  0 },
+/*   2:    1,                    */  {  1,  1 },
+/*   3: 0, 1,                    */  {  2,  0 },
+/*   4:       2,                 */  {  1,  2 },
+/*   5: 0,    2,                 */  {  3,  0 },
+/*   6:    1, 2,                 */  {  2,  3 },
+/*   7: 0, 1, 2,                 */  {  5,  0 },
+/*   8:          3,              */  {  1,  3 },
+/*   9: 0,       3,              */  {  2,  1 },
+/*  10:    1,    3,              */  {  3,  3 },
+/*  11: 0, 1,    3,              */  {  5,  1 },
+/*  12:       2, 3,              */  {  2,  5 },
+/*  13: 0,    2, 3,              */  {  5,  4 },
+/*  14:    1, 2, 3,              */  {  5,  9 },
+/*  15: 0, 1, 2, 3,              */  {  8,  0 },
+/*  16:             4,           */  {  1,  4 },
+/*  17: 0,          4,           */  {  2,  2 },
+/*  18:    1,       4,           */  {  3,  4 },
+/*  19: 0, 1,       4,           */  {  5,  2 },
+/*  20:       2,    4,           */  {  4,  2 },
+/*  21: 0,    2,    4,           */  {  6,  2 },
+/*  22:    1, 2,    4,           */  {  6,  9 },
+/*  23: 0, 1, 2,    4,           */  { 11,  0 },
+/*  24:          3, 4,           */  {  3,  8 },
+/*  25: 0,       3, 4,           */  {  5,  5 },
+/*  26:    1,    3, 4,           */  {  7,  3 },
+/*  27: 0, 1,    3, 4,           */  {  9,  1 },
+/*  28:       2, 3, 4,           */  {  6, 16 },
+/*  29: 0,    2, 3, 4,           */  { 14,  3 },
+/*  30:    1, 2, 3, 4,           */  { 12, 12 },
+/*  31: 0, 1, 2, 3, 4,           */  {  5, 24 },
+/*  32:                5,        */  {  1,  5 },
+/*  33: 0,             5,        */  {  3,  1 },
+/*  34:    1,          5,        */  {  2,  4 },
+/*  35: 0, 1,          5,        */  {  5,  3 },
+/*  36:       2,       5,        */  {  3,  6 },
+/*  37: 0,    2,       5,        */  {  7,  0 },
+/*  38:    1, 2,       5,        */  {  5, 10 },
+/*  39: 0, 1, 2,       5,        */  {  9,  0 },
+/*  40:          3,    5,        */  {  4,  3 },
+/*  41: 0,       3,    5,        */  {  6,  4 },
+/*  42:    1,    3,    5,        */  {  6, 11 },
+/*  43: 0, 1,    3,    5,        */  { 14,  1 },
+/*  44:       2, 3,    5,        */  {  6, 17 },
+/*  45: 0,    2, 3,    5,        */  { 12,  4 },
+/*  46:    1, 2, 3,    5,        */  { 11,  6 },
+/*  47: 0, 1, 2, 3,    5,        */  {  5, 25 },
+/*  48:             4, 5,        */  {  2,  8 },
+/*  49: 0,          4, 5,        */  {  5,  7 },
+/*  50:    1,       4, 5,        */  {  5, 12 },
+/*  51: 0, 1,       4, 5,        */  {  8,  1 },
+/*  52:       2,    4, 5,        */  {  6, 18 },
+/*  53: 0,    2,    4, 5,        */  { 12,  5 },
+/*  54:    1, 2,    4, 5,        */  { 14,  7 },
+/*  55: 0, 1, 2,    4, 5,        */  {  5, 28 },
+/*  56:          3, 4, 5,        */  {  6, 21 },
+/*  57: 0,       3, 4, 5,        */  { 11,  4 },
+/*  58:    1,    3, 4, 5,        */  { 12, 15 },
+/*  59: 0, 1,    3, 4, 5,        */  {  5, 30 },
+/*  60:       2, 3, 4, 5,        */  { 10,  5 },
+/*  61: 0,    2, 3, 4, 5,        */  {  6, 32 },
+/*  62:    1, 2, 3, 4, 5,        */  {  6, 39 },
+/*  63: 0, 1, 2, 3, 4, 5,        */  {  2, 12 },
+/*  64:                   6,     */  {  1,  6 },
+/*  65: 0,                6,     */  {  4,  0 },
+/*  66:    1,             6,     */  {  3,  5 },
+/*  67: 0, 1,             6,     */  {  6,  0 },
+/*  68:       2,          6,     */  {  2,  6 },
+/*  69: 0,    2,          6,     */  {  6,  3 },
+/*  70:    1, 2,          6,     */  {  5, 11 },
+/*  71: 0, 1, 2,          6,     */  { 14,  0 },
+/*  72:          3,       6,     */  {  3,  9 },
+/*  73: 0,       3,       6,     */  {  6,  5 },
+/*  74:    1,    3,       6,     */  {  7,  4 },
+/*  75: 0, 1,    3,       6,     */  { 12,  1 },
+/*  76:       2, 3,       6,     */  {  5, 14 },
+/*  77: 0,    2, 3,       6,     */  { 11,  3 },
+/*  78:    1, 2, 3,       6,     */  {  9,  4 },
+/*  79: 0, 1, 2, 3,       6,     */  {  5, 26 },
+/*  80:             4,    6,     */  {  3, 10 },
+/*  81: 0,          4,    6,     */  {  6,  6 },
+/*  82:    1,       4,    6,     */  {  7,  5 },
+/*  83: 0, 1,       4,    6,     */  { 12,  2 },
+/*  84:       2,    4,    6,     */  {  6, 19 },
+/*  85: 0,    2,    4,    6,     */  { 10,  1 },
+/*  86:    1, 2,    4,    6,     */  { 12, 13 },
+/*  87: 0, 1, 2,    4,    6,     */  {  6, 24 },
+/*  88:          3, 4,    6,     */  {  7,  7 },
+/*  89: 0,       3, 4,    6,     */  { 12,  9 },
+/*  90:    1,    3, 4,    6,     */  { 13,  1 },
+/*  91: 0, 1,    3, 4,    6,     */  {  7,  9 },
+/*  92:       2, 3, 4,    6,     */  { 12, 20 },
+/*  93: 0,    2, 3, 4,    6,     */  {  6, 33 },
+/*  94:    1, 2, 3, 4,    6,     */  {  7, 13 },
+/*  95: 0, 1, 2, 3, 4,    6,     */  {  3, 12 },
+/*  96:                5, 6,     */  {  2, 10 },
+/*  97: 0,             5, 6,     */  {  6,  7 },
+/*  98:    1,          5, 6,     */  {  5, 13 },
+/*  99: 0, 1,          5, 6,     */  { 11,  2 },
+/* 100:       2,       5, 6,     */  {  5, 16 },
+/* 101: 0,    2,       5, 6,     */  { 12,  7 },
+/* 102:    1, 2,       5, 6,     */  {  8,  3 },
+/* 103: 0, 1, 2,       5, 6,     */  {  5, 29 },
+/* 104:          3,    5, 6,     */  {  6, 22 },
+/* 105: 0,       3,    5, 6,     */  { 10,  2 },
+/* 106:    1,    3,    5, 6,     */  { 12, 17 },
+/* 107: 0, 1,    3,    5, 6,     */  {  6, 27 },
+/* 108:       2, 3,    5, 6,     */  { 14,  9 },
+/* 109: 0,    2, 3,    5, 6,     */  {  6, 34 },
+/* 110:    1, 2, 3,    5, 6,     */  {  5, 39 },
+/* 111: 0, 1, 2, 3,    5, 6,     */  {  2, 14 },
+/* 112:             4, 5, 6,     */  {  5, 20 },
+/* 113: 0,          4, 5, 6,     */  { 14,  5 },
+/* 114:    1,       4, 5, 6,     */  {  9,  5 },
+/* 115: 0, 1,       4, 5, 6,     */  {  5, 32 },
+/* 116:       2,    4, 5, 6,     */  { 11, 10 },
+/* 117: 0,    2,    4, 5, 6,     */  {  6, 35 },
+/* 118:    1, 2,    4, 5, 6,     */  {  5, 41 },
+/* 119: 0, 1, 2,    4, 5, 6,     */  {  2, 16 },
+/* 120:          3, 4, 5, 6,     */  { 12, 23 },
+/* 121: 0,       3, 4, 5, 6,     */  {  6, 37 },
+/* 122:    1,    3, 4, 5, 6,     */  {  7, 14 },
+/* 123: 0, 1,    3, 4, 5, 6,     */  {  3, 16 },
+/* 124:       2, 3, 4, 5, 6,     */  {  6, 46 },
+/* 125: 0,    2, 3, 4, 5, 6,     */  {  4,  6 },
+/* 126:    1, 2, 3, 4, 5, 6,     */  {  3, 21 },
+/* 127: 0, 1, 2, 3, 4, 5, 6,     */  {  1,  8 },
+/* 128:                      7,  */  {  1,  7 },
+/* 129: 0,                   7,  */  {  3,  2 },
+/* 130:    1,                7,  */  {  4,  1 },
+/* 131: 0, 1,                7,  */  {  6,  1 },
+/* 132:       2,             7,  */  {  3,  7 },
+/* 133: 0,    2,             7,  */  {  7,  1 },
+/* 134:    1, 2,             7,  */  {  6, 10 },
+/* 135: 0, 1, 2,             7,  */  { 12,  0 },
+/* 136:          3,          7,  */  {  2,  7 },
+/* 137: 0,       3,          7,  */  {  5,  6 },
+/* 138:    1,    3,          7,  */  {  6, 12 },
+/* 139: 0, 1,    3,          7,  */  { 11,  1 },
+/* 140:       2, 3,          7,  */  {  5, 15 },
+/* 141: 0,    2, 3,          7,  */  {  9,  2 },
+/* 142:    1, 2, 3,          7,  */  { 14,  6 },
+/* 143: 0, 1, 2, 3,          7,  */  {  5, 27 },
+/* 144:             4,       7,  */  {  2,  9 },
+/* 145: 0,          4,       7,  */  {  5,  8 },
+/* 146:    1,       4,       7,  */  {  6, 13 },
+/* 147: 0, 1,       4,       7,  */  { 14,  2 },
+/* 148:       2,    4,       7,  */  {  6, 20 },
+/* 149: 0,    2,    4,       7,  */  { 12,  6 },
+/* 150:    1, 2,    4,       7,  */  { 10,  3 },
+/* 151: 0, 1, 2,    4,       7,  */  {  6, 25 },
+/* 152:          3, 4,       7,  */  {  5, 18 },
+/* 153: 0,       3, 4,       7,  */  {  8,  2 },
+/* 154:    1,    3, 4,       7,  */  { 12, 16 },
+/* 155: 0, 1,    3, 4,       7,  */  {  5, 31 },
+/* 156:       2, 3, 4,       7,  */  { 11,  9 },
+/* 157: 0,    2, 3, 4,       7,  */  {  5, 34 },
+/* 158:    1, 2, 3, 4,       7,  */  {  6, 40 },
+/* 159: 0, 1, 2, 3, 4,       7,  */  {  2, 13 },
+/* 160:                5,    7,  */  {  3, 11 },
+/* 161: 0,             5,    7,  */  {  7,  2 },
+/* 162:    1,          5,    7,  */  {  6, 14 },
+/* 163: 0, 1,          5,    7,  */  { 12,  3 },
+/* 164:       2,       5,    7,  */  {  7,  6 },
+/* 165: 0,    2,       5,    7,  */  { 13,  0 },
+/* 166:    1, 2,       5,    7,  */  { 12, 14 },
+/* 167: 0, 1, 2,       5,    7,  */  {  7,  8 },
+/* 168:          3,    5,    7,  */  {  6, 23 },
+/* 169: 0,       3,    5,    7,  */  { 12, 10 },
+/* 170:    1,    3,    5,    7,  */  { 10,  4 },
+/* 171: 0, 1,    3,    5,    7,  */  {  6, 28 },
+/* 172:       2, 3,    5,    7,  */  { 12, 21 },
+/* 173: 0,    2, 3,    5,    7,  */  {  7, 10 },
+/* 174:    1, 2, 3,    5,    7,  */  {  6, 41 },
+/* 175: 0, 1, 2, 3,    5,    7,  */  {  3, 13 },
+/* 176:             4, 5,    7,  */  {  5, 21 },
+/* 177: 0,          4, 5,    7,  */  {  9,  3 },
+/* 178:    1,       4, 5,    7,  */  { 11,  8 },
+/* 179: 0, 1,       4, 5,    7,  */  {  5, 33 },
+/* 180:       2,    4, 5,    7,  */  { 12, 22 },
+/* 181: 0,    2,    4, 5,    7,  */  {  7, 11 },
+/* 182:    1, 2,    4, 5,    7,  */  {  6, 42 },
+/* 183: 0, 1, 2,    4, 5,    7,  */  {  3, 14 },
+/* 184:          3, 4, 5,    7,  */  { 14, 11 },
+/* 185: 0,       3, 4, 5,    7,  */  {  5, 36 },
+/* 186:    1,    3, 4, 5,    7,  */  {  6, 44 },
+/* 187: 0, 1,    3, 4, 5,    7,  */  {  2, 17 },
+/* 188:       2, 3, 4, 5,    7,  */  {  6, 47 },
+/* 189: 0,    2, 3, 4, 5,    7,  */  {  3, 18 },
+/* 190:    1, 2, 3, 4, 5,    7,  */  {  4,  7 },
+/* 191: 0, 1, 2, 3, 4, 5,    7,  */  {  1,  9 },
+/* 192:                   6, 7,  */  {  2, 11 },
+/* 193: 0,                6, 7,  */  {  6,  8 },
+/* 194:    1,             6, 7,  */  {  6, 15 },
+/* 195: 0, 1,             6, 7,  */  { 10,  0 },
+/* 196:       2,          6, 7,  */  {  5, 17 },
+/* 197: 0,    2,          6, 7,  */  { 12,  8 },
+/* 198:    1, 2,          6, 7,  */  { 11,  7 },
+/* 199: 0, 1, 2,          6, 7,  */  {  6, 26 },
+/* 200:          3,       6, 7,  */  {  5, 19 },
+/* 201: 0,       3,       6, 7,  */  { 14,  4 },
+/* 202:    1,    3,       6, 7,  */  { 12, 18 },
+/* 203: 0, 1,    3,       6, 7,  */  {  6, 29 },
+/* 204:       2, 3,       6, 7,  */  {  8,  4 },
+/* 205: 0,    2, 3,       6, 7,  */  {  5, 35 },
+/* 206:    1, 2, 3,       6, 7,  */  {  5, 40 },
+/* 207: 0, 1, 2, 3,       6, 7,  */  {  2, 15 },
+/* 208:             4,    6, 7,  */  {  5, 22 },
+/* 209: 0,          4,    6, 7,  */  { 11,  5 },
+/* 210:    1,       4,    6, 7,  */  { 12, 19 },
+/* 211: 0, 1,       4,    6, 7,  */  {  6, 30 },
+/* 212:       2,    4,    6, 7,  */  { 14, 10 },
+/* 213: 0,    2,    4,    6, 7,  */  {  6, 36 },
+/* 214:    1, 2,    4,    6, 7,  */  {  6, 43 },
+/* 215: 0, 1, 2,    4,    6, 7,  */  {  4,  4 },
+/* 216:          3, 4,    6, 7,  */  {  9,  7 },
+/* 217: 0,       3, 4,    6, 7,  */  {  5, 37 },
+/* 218:    1,    3, 4,    6, 7,  */  {  7, 15 },
+/* 219: 0, 1,    3, 4,    6, 7,  */  {  3, 17 },
+/* 220:       2, 3, 4,    6, 7,  */  {  5, 44 },
+/* 221: 0,    2, 3, 4,    6, 7,  */  {  2, 19 },
+/* 222:    1, 2, 3, 4,    6, 7,  */  {  3, 22 },
+/* 223: 0, 1, 2, 3, 4,    6, 7,  */  {  1, 10 },
+/* 224:                5, 6, 7,  */  {  5, 23 },
+/* 225: 0,             5, 6, 7,  */  { 12, 11 },
+/* 226:    1,          5, 6, 7,  */  { 14,  8 },
+/* 227: 0, 1,          5, 6, 7,  */  {  6, 31 },
+/* 228:       2,       5, 6, 7,  */  {  9,  6 },
+/* 229: 0,    2,       5, 6, 7,  */  {  7, 12 },
+/* 230:    1, 2,       5, 6, 7,  */  {  5, 42 },
+/* 231: 0, 1, 2,       5, 6, 7,  */  {  3, 15 },
+/* 232:          3,    5, 6, 7,  */  { 11, 11 },
+/* 233: 0,       3,    5, 6, 7,  */  {  6, 38 },
+/* 234:    1,    3,    5, 6, 7,  */  {  6, 45 },
+/* 235: 0, 1,    3,    5, 6, 7,  */  {  4,  5 },
+/* 236:       2, 3,    5, 6, 7,  */  {  5, 45 },
+/* 237: 0,    2, 3,    5, 6, 7,  */  {  3, 19 },
+/* 238:    1, 2, 3,    5, 6, 7,  */  {  2, 21 },
+/* 239: 0, 1, 2, 3,    5, 6, 7,  */  {  1, 11 },
+/* 240:             4, 5, 6, 7,  */  {  8,  5 },
+/* 241: 0,          4, 5, 6, 7,  */  {  5, 38 },
+/* 242:    1,       4, 5, 6, 7,  */  {  5, 43 },
+/* 243: 0, 1,       4, 5, 6, 7,  */  {  2, 18 },
+/* 244:       2,    4, 5, 6, 7,  */  {  5, 46 },
+/* 245: 0,    2,    4, 5, 6, 7,  */  {  3, 20 },
+/* 246:    1, 2,    4, 5, 6, 7,  */  {  2, 22 },
+/* 247: 0, 1, 2,    4, 5, 6, 7,  */  {  1, 12 },
+/* 248:          3, 4, 5, 6, 7,  */  {  5, 47 },
+/* 249: 0,       3, 4, 5, 6, 7,  */  {  2, 20 },
+/* 250:    1,    3, 4, 5, 6, 7,  */  {  3, 23 },
+/* 251: 0, 1,    3, 4, 5, 6, 7,  */  {  1, 13 },
+/* 252:       2, 3, 4, 5, 6, 7,  */  {  2, 23 },
+/* 253: 0,    2, 3, 4, 5, 6, 7,  */  {  1, 14 },
+/* 254:    1, 2, 3, 4, 5, 6, 7,  */  {  1, 15 },
+/* 255: 0, 1, 2, 3, 4, 5, 6, 7,  */  {  0, -1 }
+};
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling1[16][3] = {
+/*   1: 0,                       */  {  0,  8,  3 },
+/*   2:    1,                    */  {  0,  1,  9 },
+/*   4:       2,                 */  {  1,  2, 10 },
+/*   8:          3,              */  {  3, 11,  2 },
+/*  16:             4,           */  {  4,  7,  8 },
+/*  32:                5,        */  {  9,  5,  4 },
+/*  64:                   6,     */  { 10,  6,  5 },
+/* 128:                      7,  */  {  7,  6, 11 },
+/* 127: 0, 1, 2, 3, 4, 5, 6,     */  {  7, 11,  6 },
+/* 191: 0, 1, 2, 3, 4, 5,    7,  */  { 10,  5,  6 },
+/* 223: 0, 1, 2, 3, 4,    6, 7,  */  {  9,  4,  5 },
+/* 239: 0, 1, 2, 3,    5, 6, 7,  */  {  4,  8,  7 },
+/* 247: 0, 1, 2,    4, 5, 6, 7,  */  {  3,  2, 11 },
+/* 251: 0, 1,    3, 4, 5, 6, 7,  */  {  1, 10,  2 },
+/* 253: 0,    2, 3, 4, 5, 6, 7,  */  {  0,  9,  1 },
+/* 254:    1, 2, 3, 4, 5, 6, 7,  */  {  0,  3,  8 }
+};
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling2[24][6] = {
+/*   3: 0, 1,                    */  {  1,  8,  3,  9,  8,  1 },
+/*   9: 0,       3,              */  {  0, 11,  2,  8, 11,  0 },
+/*  17: 0,          4,           */  {  4,  3,  0,  7,  3,  4 },
+/*   6:    1, 2,                 */  {  9,  2, 10,  0,  2,  9 },
+/*  34:    1,          5,        */  {  0,  5,  4,  1,  5,  0 },
+/*  12:       2, 3,              */  {  3, 10,  1, 11, 10,  3 },
+/*  68:       2,          6,     */  {  1,  6,  5,  2,  6,  1 },
+/* 136:          3,          7,  */  {  7,  2,  3,  6,  2,  7 },
+/*  48:             4, 5,        */  {  9,  7,  8,  5,  7,  9 },
+/* 144:             4,       7,  */  {  6,  8,  4, 11,  8,  6 },
+/*  96:                5, 6,     */  { 10,  4,  9,  6,  4, 10 },
+/* 192:                   6, 7,  */  { 11,  5, 10,  7,  5, 11 },
+/*  63: 0, 1, 2, 3, 4, 5,        */  { 11, 10,  5,  7, 11,  5 },
+/* 159: 0, 1, 2, 3, 4,       7,  */  { 10,  9,  4,  6, 10,  4 },
+/* 111: 0, 1, 2, 3,    5, 6,     */  {  6,  4,  8, 11,  6,  8 },
+/* 207: 0, 1, 2, 3,       6, 7,  */  {  9,  8,  7,  5,  9,  7 },
+/* 119: 0, 1, 2,    4, 5, 6,     */  {  7,  3,  2,  6,  7,  2 },
+/* 187: 0, 1,    3, 4, 5,    7,  */  {  1,  5,  6,  2,  1,  6 },
+/* 243: 0, 1,       4, 5, 6, 7,  */  {  3,  1, 10, 11,  3, 10 },
+/* 221: 0,    2, 3, 4,    6, 7,  */  {  0,  4,  5,  1,  0,  5 },
+/* 249: 0,       3, 4, 5, 6, 7,  */  {  9, 10,  2,  0,  9,  2 },
+/* 238:    1, 2, 3,    5, 6, 7,  */  {  4,  0,  3,  7,  4,  3 },
+/* 246:    1, 2,    4, 5, 6, 7,  */  {  0,  2, 11,  8,  0, 11 },
+/* 252:       2, 3, 4, 5, 6, 7,  */  {  1,  3,  8,  9,  1,  8 }
+};
+//_____________________________________________________________________________
+
+//_____________________________________________________________________________
+/**
+ * \brief test table for case 3
+ * One face to test
+ * When the test on the specified face is positive : 4 first triangles
+ * When the test on the specified face is negative : 2 last triangles
+ *
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char test3[24] = {
+/*   5: 0,    2,                 */    5,
+/*  33: 0,             5,        */    1,
+/* 129: 0,                   7,  */    4,
+/*  10:    1,    3,              */    5,
+/*  18:    1,       4,           */    1,
+/*  66:    1,             6,     */    2,
+/*  36:       2,       5,        */    2,
+/* 132:       2,             7,  */    3,
+/*  24:          3, 4,           */    4,
+/*  72:          3,       6,     */    3,
+/*  80:             4,    6,     */    6,
+/* 160:                5,    7,  */    6,
+/*  95: 0, 1, 2, 3, 4,    6,     */   -6,
+/* 175: 0, 1, 2, 3,    5,    7,  */   -6,
+/* 183: 0, 1, 2,    4, 5,    7,  */   -3,
+/* 231: 0, 1, 2,       5, 6, 7,  */   -4,
+/* 123: 0, 1,    3, 4, 5, 6,     */   -3,
+/* 219: 0, 1,    3, 4,    6, 7,  */   -2,
+/* 189: 0,    2, 3, 4, 5,    7,  */   -2,
+/* 237: 0,    2, 3,    5, 6, 7,  */   -1,
+/* 245: 0,    2,    4, 5, 6, 7,  */   -5,
+/* 126:    1, 2, 3, 4, 5, 6,     */   -4,
+/* 222:    1, 2, 3, 4,    6, 7,  */   -1,
+/* 250:    1,    3, 4, 5, 6, 7,  */   -5
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 3.1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling3_1[24][6] = {
+/*   5: 0,    2,                 */  {  0,  8,  3,  1,  2, 10 },
+/*  33: 0,             5,        */  {  9,  5,  4,  0,  8,  3 },
+/* 129: 0,                   7,  */  {  3,  0,  8, 11,  7,  6 },
+/*  10:    1,    3,              */  {  1,  9,  0,  2,  3, 11 },
+/*  18:    1,       4,           */  {  0,  1,  9,  8,  4,  7 },
+/*  66:    1,             6,     */  {  9,  0,  1,  5, 10,  6 },
+/*  36:       2,       5,        */  {  1,  2, 10,  9,  5,  4 },
+/* 132:       2,             7,  */  { 10,  1,  2,  6, 11,  7 },
+/*  24:          3, 4,           */  {  8,  4,  7,  3, 11,  2 },
+/*  72:          3,       6,     */  {  2,  3, 11, 10,  6,  5 },
+/*  80:             4,    6,     */  {  5, 10,  6,  4,  7,  8 },
+/* 160:                5,    7,  */  {  4,  9,  5,  7,  6, 11 },
+/*  95: 0, 1, 2, 3, 4,    6,     */  {  5,  9,  4, 11,  6,  7 },
+/* 175: 0, 1, 2, 3,    5,    7,  */  {  6, 10,  5,  8,  7,  4 },
+/* 183: 0, 1, 2,    4, 5,    7,  */  { 11,  3,  2,  5,  6, 10 },
+/* 231: 0, 1, 2,       5, 6, 7,  */  {  7,  4,  8,  2, 11,  3 },
+/* 123: 0, 1,    3, 4, 5, 6,     */  {  2,  1, 10,  7, 11,  6 },
+/* 219: 0, 1,    3, 4,    6, 7,  */  { 10,  2,  1,  4,  5,  9 },
+/* 189: 0,    2, 3, 4, 5,    7,  */  {  1,  0,  9,  6, 10,  5 },
+/* 237: 0,    2, 3,    5, 6, 7,  */  {  9,  1,  0,  7,  4,  8 },
+/* 245: 0,    2,    4, 5, 6, 7,  */  {  0,  9,  1, 11,  3,  2 },
+/* 126:    1, 2, 3, 4, 5, 6,     */  {  8,  0,  3,  6,  7, 11 },
+/* 222:    1, 2, 3, 4,    6, 7,  */  {  4,  5,  9,  3,  8,  0 },
+/* 250:    1,    3, 4, 5, 6, 7,  */  {  3,  8,  0, 10,  2,  1 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 3.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling3_2[24][12] = {
+/*   5: 0,    2,                 */  { 10,  3,  2, 10,  8,  3, 10,  1,  0,  8, 10,  0 },
+/*  33: 0,             5,        */  {  3,  4,  8,  3,  5,  4,  3,  0,  9,  5,  3,  9 },
+/* 129: 0,                   7,  */  {  6,  8,  7,  6,  0,  8,  6, 11,  3,  0,  6,  3 },
+/*  10:    1,    3,              */  { 11,  0,  3, 11,  9,  0, 11,  2,  1,  9, 11,  1 },
+/*  18:    1,       4,           */  {  7,  9,  4,  7,  1,  9,  7,  8,  0,  1,  7,  0 },
+/*  66:    1,             6,     */  {  6,  1, 10,  6,  0,  1,  9,  0,  6,  9,  6,  5 },
+/*  36:       2,       5,        */  {  4, 10,  5,  4,  2, 10,  4,  9,  1,  2,  4,  1 },
+/* 132:       2,             7,  */  {  7,  2, 11,  7,  1,  2,  7,  6, 10,  1,  7, 10 },
+/*  24:          3, 4,           */  {  2,  7, 11,  2,  4,  7,  2,  3,  8,  4,  2,  8 },
+/*  72:          3,       6,     */  {  5, 11,  6,  5,  3, 11,  5, 10,  2,  3,  5,  2 },
+/*  80:             4,    6,     */  {  8,  6,  7,  8, 10,  6,  8,  4,  5, 10,  8,  5 },
+/* 160:                5,    7,  */  { 11,  5,  6, 11,  9,  5, 11,  7,  4,  9, 11,  4 },
+/*  95: 0, 1, 2, 3, 4,    6,     */  {  6,  5, 11,  5,  9, 11,  4,  7, 11,  4, 11,  9 },
+/* 175: 0, 1, 2, 3,    5,    7,  */  {  7,  6,  8,  6, 10,  8,  5,  4,  8,  5,  8, 10 },
+/* 183: 0, 1, 2,    4, 5,    7,  */  {  6, 11,  5, 11,  3,  5,  2, 10,  5,  2,  5,  3 },
+/* 231: 0, 1, 2,       5, 6, 7,  */  { 11,  7,  2,  7,  4,  2,  8,  3,  2,  8,  2,  4 },
+/* 123: 0, 1,    3, 4, 5, 6,     */  { 11,  2,  7,  2,  1,  7, 10,  6,  7, 10,  7,  1 },
+/* 219: 0, 1,    3, 4,    6, 7,  */  {  5, 10,  4, 10,  2,  4,  1,  9,  4,  1,  4,  2 },
+/* 189: 0,    2, 3, 4, 5,    7,  */  { 10,  1,  6,  1,  0,  6,  6,  0,  9,  5,  6,  9 },
+/* 237: 0,    2, 3,    5, 6, 7,  */  {  4,  9,  7,  9,  1,  7,  0,  8,  7,  0,  7,  1 },
+/* 245: 0,    2,    4, 5, 6, 7,  */  {  3,  0, 11,  0,  9, 11,  1,  2, 11,  1, 11,  9 },
+/* 126:    1, 2, 3, 4, 5, 6,     */  {  7,  8,  6,  8,  0,  6,  3, 11,  6,  3,  6,  0 },
+/* 222:    1, 2, 3, 4,    6, 7,  */  {  8,  4,  3,  4,  5,  3,  9,  0,  3,  9,  3,  5 },
+/* 250:    1,    3, 4, 5, 6, 7,  */  {  2,  3, 10,  3,  8, 10,  0,  1, 10,  0, 10,  8 }
+};
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+/**
+ * \brief test table for case 4
+ * Interior to test
+ * When the test on the interior is negative : 2 first triangles
+ * When the test on the interior is positive : 6 last triangles
+ *
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char test4[8] = {
+/*  65: 0,                6,     */   7,
+/* 130:    1,                7,  */   7,
+/*  20:       2,    4,           */   7,
+/*  40:          3,    5,        */   7,
+/* 215: 0, 1, 2,    4,    6, 7,  */  -7,
+/* 235: 0, 1,    3,    5, 6, 7,  */  -7,
+/* 125: 0,    2, 3, 4, 5, 6,     */  -7,
+/* 190:    1, 2, 3, 4, 5,    7,  */  -7
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 4.1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling4_1[8][6] = {
+/*  65: 0,                6,     */  {  0,  8,  3,  5, 10,  6 },
+/* 130:    1,                7,  */  {  0,  1,  9, 11,  7,  6 },
+/*  20:       2,    4,           */  {  1,  2, 10,  8,  4,  7 },
+/*  40:          3,    5,        */  {  9,  5,  4,  2,  3, 11 },
+/* 215: 0, 1, 2,    4,    6, 7,  */  {  4,  5,  9, 11,  3,  2 },
+/* 235: 0, 1,    3,    5, 6, 7,  */  { 10,  2,  1,  7,  4,  8 },
+/* 125: 0,    2, 3, 4, 5, 6,     */  {  9,  1,  0,  6,  7, 11 },
+/* 190:    1, 2, 3, 4, 5,    7,  */  {  3,  8,  0,  6, 10,  5 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 4.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling4_2[8][18] = {
+/*  65: 0,                6,     */  {  8,  5,  0,  5,  8,  6,  3,  6,  8,  6,  3, 10,  0, 10,  3, 10,  0,  5 },
+/* 130:    1,                7,  */  {  9,  6,  1,  6,  9,  7,  0,  7,  9,  7,  0, 11,  1, 11,  0, 11,  1,  6 },
+/*  20:       2,    4,           */  { 10,  7,  2,  7, 10,  4,  1,  4, 10,  4,  1,  8,  2,  8,  1,  8,  2,  7 },
+/*  40:          3,    5,        */  { 11,  4,  3,  4, 11,  5,  2,  5, 11,  5,  2,  9,  3,  9,  2,  9,  3,  4 },
+/* 215: 0, 1, 2,    4,    6, 7,  */  {  3,  4, 11,  5, 11,  4, 11,  5,  2,  9,  2,  5,  2,  9,  3,  4,  3,  9 },
+/* 235: 0, 1,    3,    5, 6, 7,  */  {  2,  7, 10,  4, 10,  7, 10,  4,  1,  8,  1,  4,  1,  8,  2,  7,  2,  8 },
+/* 125: 0,    2, 3, 4, 5, 6,     */  {  1,  6,  9,  7,  9,  6,  9,  7,  0, 11,  0,  7,  0, 11,  1,  6,  1, 11 },
+/* 190:    1, 2, 3, 4, 5,    7,  */  {  0,  5,  8,  6,  8,  5,  8,  6,  3, 10,  3,  6,  3, 10,  0,  5,  0, 10 }
+};
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 5
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling5[48][9] = {
+/*   7: 0, 1, 2,                 */  {  2,  8,  3,  2, 10,  8, 10,  9,  8 },
+/*  11: 0, 1,    3,              */  {  1, 11,  2,  1,  9, 11,  9,  8, 11 },
+/*  19: 0, 1,       4,           */  {  4,  1,  9,  4,  7,  1,  7,  3,  1 },
+/*  35: 0, 1,          5,        */  {  8,  5,  4,  8,  3,  5,  3,  1,  5 },
+/*  13: 0,    2, 3,              */  {  0, 10,  1,  0,  8, 10,  8, 11, 10 },
+/*  25: 0,       3, 4,           */  { 11,  4,  7, 11,  2,  4,  2,  0,  4 },
+/* 137: 0,       3,          7,  */  {  7,  0,  8,  7,  6,  0,  6,  2,  0 },
+/*  49: 0,          4, 5,        */  {  9,  3,  0,  9,  5,  3,  5,  7,  3 },
+/* 145: 0,          4,       7,  */  {  3,  6, 11,  3,  0,  6,  0,  4,  6 },
+/*  14:    1, 2, 3,              */  {  3,  9,  0,  3, 11,  9, 11, 10,  9 },
+/*  38:    1, 2,       5,        */  {  5,  2, 10,  5,  4,  2,  4,  0,  2 },
+/*  70:    1, 2,          6,     */  {  9,  6,  5,  9,  0,  6,  0,  2,  6 },
+/*  50:    1,       4, 5,        */  {  0,  7,  8,  0,  1,  7,  1,  5,  7 },
+/*  98:    1,          5, 6,     */  { 10,  0,  1, 10,  6,  0,  6,  4,  0 },
+/*  76:       2, 3,       6,     */  {  6,  3, 11,  6,  5,  3,  5,  1,  3 },
+/* 140:       2, 3,          7,  */  { 10,  7,  6, 10,  1,  7,  1,  3,  7 },
+/* 100:       2,       5, 6,     */  {  1,  4,  9,  1,  2,  4,  2,  6,  4 },
+/* 196:       2,          6, 7,  */  { 11,  1,  2, 11,  7,  1,  7,  5,  1 },
+/* 152:          3, 4,       7,  */  {  8,  2,  3,  8,  4,  2,  4,  6,  2 },
+/* 200:          3,       6, 7,  */  {  2,  5, 10,  2,  3,  5,  3,  7,  5 },
+/* 112:             4, 5, 6,     */  {  7, 10,  6,  7,  8, 10,  8,  9, 10 },
+/* 176:             4, 5,    7,  */  {  6,  9,  5,  6, 11,  9, 11,  8,  9 },
+/* 208:             4,    6, 7,  */  {  5,  8,  4,  5, 10,  8, 10, 11,  8 },
+/* 224:                5, 6, 7,  */  {  4, 11,  7,  4,  9, 11,  9, 10, 11 },
+/*  31: 0, 1, 2, 3, 4,           */  {  4,  7, 11,  4, 11,  9,  9, 11, 10 },
+/*  47: 0, 1, 2, 3,    5,        */  {  5,  4,  8,  5,  8, 10, 10,  8, 11 },
+/*  79: 0, 1, 2, 3,       6,     */  {  6,  5,  9,  6,  9, 11, 11,  9,  8 },
+/* 143: 0, 1, 2, 3,          7,  */  {  7,  6, 10,  7, 10,  8,  8, 10,  9 },
+/*  55: 0, 1, 2,    4, 5,        */  {  2, 10,  5,  2,  5,  3,  3,  5,  7 },
+/* 103: 0, 1, 2,       5, 6,     */  {  8,  3,  2,  8,  2,  4,  4,  2,  6 },
+/*  59: 0, 1,    3, 4, 5,        */  { 11,  2,  1, 11,  1,  7,  7,  1,  5 },
+/* 155: 0, 1,    3, 4,       7,  */  {  1,  9,  4,  1,  4,  2,  2,  4,  6 },
+/* 115: 0, 1,       4, 5, 6,     */  { 10,  6,  7, 10,  7,  1,  1,  7,  3 },
+/* 179: 0, 1,       4, 5,    7,  */  {  6, 11,  3,  6,  3,  5,  5,  3,  1 },
+/* 157: 0,    2, 3, 4,       7,  */  { 10,  1,  0, 10,  0,  6,  6,  0,  4 },
+/* 205: 0,    2, 3,       6, 7,  */  {  0,  8,  7,  0,  7,  1,  1,  7,  5 },
+/* 185: 0,       3, 4, 5,    7,  */  {  9,  5,  6,  9,  6,  0,  0,  6,  2 },
+/* 217: 0,       3, 4,    6, 7,  */  {  5, 10,  2,  5,  2,  4,  4,  2,  0 },
+/* 241: 0,          4, 5, 6, 7,  */  {  3,  0,  9,  3,  9, 11, 11,  9, 10 },
+/* 110:    1, 2, 3,    5, 6,     */  {  3, 11,  6,  3,  6,  0,  0,  6,  4 },
+/* 206:    1, 2, 3,       6, 7,  */  {  9,  0,  3,  9,  3,  5,  5,  3,  7 },
+/* 118:    1, 2,    4, 5, 6,     */  {  7,  8,  0,  7,  0,  6,  6,  0,  2 },
+/* 230:    1, 2,       5, 6, 7,  */  { 11,  7,  4, 11,  4,  2,  2,  4,  0 },
+/* 242:    1,       4, 5, 6, 7,  */  {  0,  1, 10,  0, 10,  8,  8, 10, 11 },
+/* 220:       2, 3, 4,    6, 7,  */  {  8,  4,  5,  8,  5,  3,  3,  5,  1 },
+/* 236:       2, 3,    5, 6, 7,  */  {  4,  9,  1,  4,  1,  7,  7,  1,  3 },
+/* 244:       2,    4, 5, 6, 7,  */  {  1,  2, 11,  1, 11,  9,  9, 11,  8 },
+/* 248:          3, 4, 5, 6, 7,  */  {  2,  3,  8,  2,  8, 10, 10,  8,  9 }
+};
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+/**
+ * \brief test table for case 6
+ * 1 face to test + eventually the interior
+ * When the test on the specified face is positive : 5 first triangles
+ * When the test on the specified face is negative :
+ * - if the test on the interior is negative : 3 middle triangles
+ * - if the test on the interior is positive : 8 last triangles
+ * The support edge for the interior test is marked as the 3rd column.
+ *
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char test6[48][3] = {
+/*  67: 0, 1,             6,     */  {  2,  7,  10  },
+/* 131: 0, 1,                7,  */  {  4,  7,  11  },
+/*  21: 0,    2,    4,           */  {  5,  7,   1  },
+/*  69: 0,    2,          6,     */  {  5,  7,   3  },
+/*  41: 0,       3,    5,        */  {  1,  7,   9  },
+/*  73: 0,       3,       6,     */  {  3,  7,  10  },
+/*  81: 0,          4,    6,     */  {  6,  7,   5  },
+/*  97: 0,             5, 6,     */  {  1,  7,   8  },
+/* 193: 0,                6, 7,  */  {  4,  7,   8  },
+/*  22:    1, 2,    4,           */  {  1,  7,   8  },
+/* 134:    1, 2,             7,  */  {  3,  7,  11  },
+/*  42:    1,    3,    5,        */  {  5,  7,   2  },
+/* 138:    1,    3,          7,  */  {  5,  7,   0  },
+/* 146:    1,       4,       7,  */  {  1,  7,   9  },
+/* 162:    1,          5,    7,  */  {  6,  7,   6  },
+/* 194:    1,             6, 7,  */  {  2,  7,   9  },
+/*  28:       2, 3, 4,           */  {  4,  7,   8  },
+/*  44:       2, 3,    5,        */  {  2,  7,   9  },
+/*  52:       2,    4, 5,        */  {  2,  7,  10  },
+/*  84:       2,    4,    6,     */  {  6,  7,   7  },
+/* 148:       2,    4,       7,  */  {  3,  7,  10  },
+/*  56:          3, 4, 5,        */  {  4,  7,  11  },
+/* 104:          3,    5, 6,     */  {  3,  7,  11  },
+/* 168:          3,    5,    7,  */  {  6,  7,   4  },
+/*  87: 0, 1, 2,    4,    6,     */  { -6, -7,   4  },
+/* 151: 0, 1, 2,    4,       7,  */  { -3, -7,  11  },
+/* 199: 0, 1, 2,          6, 7,  */  { -4, -7,  11  },
+/* 107: 0, 1,    3,    5, 6,     */  { -3, -7,  10  },
+/* 171: 0, 1,    3,    5,    7,  */  { -6, -7,   7  },
+/* 203: 0, 1,    3,       6, 7,  */  { -2, -7,  10  },
+/* 211: 0, 1,       4,    6, 7,  */  { -2, -7,   9  },
+/* 227: 0, 1,          5, 6, 7,  */  { -4, -7,   8  },
+/*  61: 0,    2, 3, 4, 5,        */  { -2, -7,   9  },
+/*  93: 0,    2, 3, 4,    6,     */  { -6, -7,   6  },
+/* 109: 0,    2, 3,    5, 6,     */  { -1, -7,   9  },
+/* 117: 0,    2,    4, 5, 6,     */  { -5, -7,   0  },
+/* 213: 0,    2,    4,    6, 7,  */  { -5, -7,   2  },
+/* 121: 0,       3, 4, 5, 6,     */  { -3, -7,  11  },
+/* 233: 0,       3,    5, 6, 7,  */  { -1, -7,   8  },
+/*  62:    1, 2, 3, 4, 5,        */  { -4, -7,   8  },
+/* 158:    1, 2, 3, 4,       7,  */  { -1, -7,   8  },
+/* 174:    1, 2, 3,    5,    7,  */  { -6, -7,   5  },
+/* 182:    1, 2,    4, 5,    7,  */  { -3, -7,  10  },
+/* 214:    1, 2,    4,    6, 7,  */  { -1, -7,   9  },
+/* 186:    1,    3, 4, 5,    7,  */  { -5, -7,   3  },
+/* 234:    1,    3,    5, 6, 7,  */  { -5, -7,   1  },
+/* 124:       2, 3, 4, 5, 6,     */  { -4, -7,  11  },
+/* 188:       2, 3, 4, 5,    7,  */  { -2, -7,  10  }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 6.1.1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling6_1_1[48][9] = {
+/*  67: 0, 1,             6,     */  {  6,  5, 10,  3,  1,  8,  9,  8,  1 },
+/* 131: 0, 1,                7,  */  { 11,  7,  6,  9,  3,  1,  3,  9,  8 },
+/*  21: 0,    2,    4,           */  {  1,  2, 10,  7,  0,  4,  0,  7,  3 },
+/*  69: 0,    2,          6,     */  {  3,  0,  8,  5,  2,  6,  2,  5,  1 },
+/*  41: 0,       3,    5,        */  {  5,  4,  9,  2,  0, 11,  8, 11,  0 },
+/*  73: 0,       3,       6,     */  { 10,  6,  5,  8,  2,  0,  2,  8, 11 },
+/*  81: 0,          4,    6,     */  { 10,  6,  5,  0,  4,  3,  7,  3,  4 },
+/*  97: 0,             5, 6,     */  {  3,  0,  8,  6,  4, 10,  9, 10,  4 },
+/* 193: 0,                6, 7,  */  {  8,  3,  0, 10,  7,  5,  7, 10, 11 },
+/*  22:    1, 2,    4,           */  {  8,  4,  7, 10,  0,  2,  0, 10,  9 },
+/* 134:    1, 2,             7,  */  {  7,  6, 11,  0,  2,  9, 10,  9,  2 },
+/*  42:    1,    3,    5,        */  {  2,  3, 11,  4,  1,  5,  1,  4,  0 },
+/* 138:    1,    3,          7,  */  {  0,  1,  9,  6,  3,  7,  3,  6,  2 },
+/* 146:    1,       4,       7,  */  {  9,  0,  1, 11,  4,  6,  4, 11,  8 },
+/* 162:    1,          5,    7,  */  { 11,  7,  6,  1,  5,  0,  4,  0,  5 },
+/* 194:    1,             6, 7,  */  {  0,  1,  9,  7,  5, 11, 10, 11,  5 },
+/*  28:       2, 3, 4,           */  {  4,  7,  8,  1,  3, 10, 11, 10,  3 },
+/*  44:       2, 3,    5,        */  {  9,  5,  4, 11,  1,  3,  1, 11, 10 },
+/*  52:       2,    4, 5,        */  { 10,  1,  2,  8,  5,  7,  5,  8,  9 },
+/*  84:       2,    4,    6,     */  {  8,  4,  7,  2,  6,  1,  5,  1,  6 },
+/* 148:       2,    4,       7,  */  {  1,  2, 10,  4,  6,  8, 11,  8,  6 },
+/*  56:          3, 4, 5,        */  {  2,  3, 11,  5,  7,  9,  8,  9,  7 },
+/* 104:          3,    5, 6,     */  { 11,  2,  3,  9,  6,  4,  6,  9, 10 },
+/* 168:          3,    5,    7,  */  {  9,  5,  4,  3,  7,  2,  6,  2,  7 },
+/*  87: 0, 1, 2,    4,    6,     */  {  4,  5,  9,  2,  7,  3,  7,  2,  6 },
+/* 151: 0, 1, 2,    4,       7,  */  {  3,  2, 11,  4,  6,  9, 10,  9,  6 },
+/* 199: 0, 1, 2,          6, 7,  */  { 11,  3,  2,  9,  7,  5,  7,  9,  8 },
+/* 107: 0, 1,    3,    5, 6,     */  { 10,  2,  1,  8,  6,  4,  6,  8, 11 },
+/* 171: 0, 1,    3,    5,    7,  */  {  7,  4,  8,  1,  6,  2,  6,  1,  5 },
+/* 203: 0, 1,    3,       6, 7,  */  {  2,  1, 10,  7,  5,  8,  9,  8,  5 },
+/* 211: 0, 1,       4,    6, 7,  */  {  4,  5,  9,  3,  1, 11, 10, 11,  1 },
+/* 227: 0, 1,          5, 6, 7,  */  {  8,  7,  4, 10,  3,  1,  3, 10, 11 },
+/*  61: 0,    2, 3, 4, 5,        */  {  9,  1,  0, 11,  5,  7,  5, 11, 10 },
+/*  93: 0,    2, 3, 4,    6,     */  {  6,  7, 11,  0,  5,  1,  5,  0,  4 },
+/* 109: 0,    2, 3,    5, 6,     */  {  1,  0,  9,  6,  4, 11,  8, 11,  4 },
+/* 117: 0,    2,    4, 5, 6,     */  {  9,  1,  0,  7,  3,  6,  2,  6,  3 },
+/* 213: 0,    2,    4,    6, 7,  */  { 11,  3,  2,  5,  1,  4,  0,  4,  1 },
+/* 121: 0,       3, 4, 5, 6,     */  { 11,  6,  7,  9,  2,  0,  2,  9, 10 },
+/* 233: 0,       3,    5, 6, 7,  */  {  7,  4,  8,  2,  0, 10,  9, 10,  0 },
+/*  62:    1, 2, 3, 4, 5,        */  {  0,  3,  8,  5,  7, 10, 11, 10,  7 },
+/* 158:    1, 2, 3, 4,       7,  */  {  8,  0,  3, 10,  4,  6,  4, 10,  9 },
+/* 174:    1, 2, 3,    5,    7,  */  {  5,  6, 10,  3,  4,  0,  4,  3,  7 },
+/* 182:    1, 2,    4, 5,    7,  */  {  5,  6, 10,  0,  2,  8, 11,  8,  2 },
+/* 214:    1, 2,    4,    6, 7,  */  {  9,  4,  5, 11,  0,  2,  0, 11,  8 },
+/* 186:    1,    3, 4, 5,    7,  */  {  8,  0,  3,  6,  2,  5,  1,  5,  2 },
+/* 234:    1,    3,    5, 6, 7,  */  { 10,  2,  1,  4,  0,  7,  3,  7,  0 },
+/* 124:       2, 3, 4, 5, 6,     */  {  6,  7, 11,  1,  3,  9,  8,  9,  3 },
+/* 188:       2, 3, 4, 5,    7,  */  { 10,  5,  6,  8,  1,  3,  1,  8,  9 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 6.1.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling6_1_2[48][21] = {
+/*  67: 0, 1,             6,     */  {  1, 10,  3,  6,  3, 10,  3,  6,  8,  5,  8,  6,  8,  5,  9,  1,  9,  5, 10,  1,  5 },
+/* 131: 0, 1,                7,  */  {  1, 11,  3, 11,  1,  6,  9,  6,  1,  6,  9,  7,  8,  7,  9,  7,  8,  3,  7,  3, 11 },
+/*  21: 0,    2,    4,           */  {  4,  1,  0,  1,  4, 10,  7, 10,  4, 10,  7,  2,  3,  2,  7,  2,  3,  0,  2,  0,  1 },
+/*  69: 0,    2,          6,     */  {  6,  3,  2,  3,  6,  8,  5,  8,  6,  8,  5,  0,  1,  0,  5,  0,  1,  2,  0,  2,  3 },
+/*  41: 0,       3,    5,        */  {  0,  9,  2,  5,  2,  9,  2,  5, 11,  4, 11,  5, 11,  4,  8,  0,  8,  4,  9,  0,  4 },
+/*  73: 0,       3,       6,     */  {  0, 10,  2, 10,  0,  5,  8,  5,  0,  5,  8,  6, 11,  6,  8,  6, 11,  2,  6,  2, 10 },
+/*  81: 0,          4,    6,     */  {  4,  5,  0, 10,  0,  5,  0, 10,  3,  6,  3, 10,  3,  6,  7,  4,  7,  6,  5,  4,  6 },
+/*  97: 0,             5, 6,     */  {  4,  8,  6,  3,  6,  8,  6,  3, 10,  0, 10,  3, 10,  0,  9,  4,  9,  0,  8,  4,  0 },
+/* 193: 0,                6, 7,  */  {  5,  8,  7,  8,  5,  0, 10,  0,  5,  0, 10,  3, 11,  3, 10,  3, 11,  7,  3,  7,  8 },
+/*  22:    1, 2,    4,           */  {  2,  8,  0,  8,  2,  7, 10,  7,  2,  7, 10,  4,  9,  4, 10,  4,  9,  0,  4,  0,  8 },
+/* 134:    1, 2,             7,  */  {  2, 11,  0,  7,  0, 11,  0,  7,  9,  6,  9,  7,  9,  6, 10,  2, 10,  6, 11,  2,  6 },
+/*  42:    1,    3,    5,        */  {  5,  2,  1,  2,  5, 11,  4, 11,  5, 11,  4,  3,  0,  3,  4,  3,  0,  1,  3,  1,  2 },
+/* 138:    1,    3,          7,  */  {  7,  0,  3,  0,  7,  9,  6,  9,  7,  9,  6,  1,  2,  1,  6,  1,  2,  3,  1,  3,  0 },
+/* 146:    1,       4,       7,  */  {  6,  9,  4,  9,  6,  1, 11,  1,  6,  1, 11,  0,  8,  0, 11,  0,  8,  4,  0,  4,  9 },
+/* 162:    1,          5,    7,  */  {  5,  6,  1, 11,  1,  6,  1, 11,  0,  7,  0, 11,  0,  7,  4,  5,  4,  7,  6,  5,  7 },
+/* 194:    1,             6, 7,  */  {  5,  9,  7,  0,  7,  9,  7,  0, 11,  1, 11,  0, 11,  1, 10,  5, 10,  1,  9,  5,  1 },
+/*  28:       2, 3, 4,           */  {  3,  8,  1,  4,  1,  8,  1,  4, 10,  7, 10,  4, 10,  7, 11,  3, 11,  7,  8,  3,  7 },
+/*  44:       2, 3,    5,        */  {  3,  9,  1,  9,  3,  4, 11,  4,  3,  4, 11,  5, 10,  5, 11,  5, 10,  1,  5,  1,  9 },
+/*  52:       2,    4, 5,        */  {  7, 10,  5, 10,  7,  2,  8,  2,  7,  2,  8,  1,  9,  1,  8,  1,  9,  5,  1,  5, 10 },
+/*  84:       2,    4,    6,     */  {  6,  7,  2,  8,  2,  7,  2,  8,  1,  4,  1,  8,  1,  4,  5,  6,  5,  4,  7,  6,  4 },
+/* 148:       2,    4,       7,  */  {  6, 10,  4,  1,  4, 10,  4,  1,  8,  2,  8,  1,  8,  2, 11,  6, 11,  2, 10,  6,  2 },
+/*  56:          3, 4, 5,        */  {  7, 11,  5,  2,  5, 11,  5,  2,  9,  3,  9,  2,  9,  3,  8,  7,  8,  3, 11,  7,  3 },
+/* 104:          3,    5, 6,     */  {  4, 11,  6, 11,  4,  3,  9,  3,  4,  3,  9,  2, 10,  2,  9,  2, 10,  6,  2,  6, 11 },
+/* 168:          3,    5,    7,  */  {  7,  4,  3,  9,  3,  4,  3,  9,  2,  5,  2,  9,  2,  5,  6,  7,  6,  5,  4,  7,  5 },
+/*  87: 0, 1, 2,    4,    6,     */  {  3,  4,  7,  4,  3,  9,  2,  9,  3,  9,  2,  5,  6,  5,  2,  5,  6,  7,  5,  7,  4 },
+/* 151: 0, 1, 2,    4,       7,  */  {  6, 11,  4,  3,  4, 11,  4,  3,  9,  2,  9,  3,  9,  2, 10,  6, 10,  2, 11,  6,  2 },
+/* 199: 0, 1, 2,          6, 7,  */  {  5, 11,  7, 11,  5,  2,  9,  2,  5,  2,  9,  3,  8,  3,  9,  3,  8,  7,  3,  7, 11 },
+/* 107: 0, 1,    3,    5, 6,     */  {  4, 10,  6, 10,  4,  1,  8,  1,  4,  1,  8,  2, 11,  2,  8,  2, 11,  6,  2,  6, 10 },
+/* 171: 0, 1,    3,    5,    7,  */  {  2,  7,  6,  7,  2,  8,  1,  8,  2,  8,  1,  4,  5,  4,  1,  4,  5,  6,  4,  6,  7 },
+/* 203: 0, 1,    3,       6, 7,  */  {  5, 10,  7,  2,  7, 10,  7,  2,  8,  1,  8,  2,  8,  1,  9,  5,  9,  1, 10,  5,  1 },
+/* 211: 0, 1,       4,    6, 7,  */  {  1,  9,  3,  4,  3,  9,  3,  4, 11,  5, 11,  4, 11,  5, 10,  1, 10,  5,  9,  1,  5 },
+/* 227: 0, 1,          5, 6, 7,  */  {  1,  8,  3,  8,  1,  4, 10,  4,  1,  4, 10,  7, 11,  7, 10,  7, 11,  3,  7,  3,  8 },
+/*  61: 0,    2, 3, 4, 5,        */  {  7,  9,  5,  9,  7,  0, 11,  0,  7,  0, 11,  1, 10,  1, 11,  1, 10,  5,  1,  5,  9 },
+/*  93: 0,    2, 3, 4,    6,     */  {  1,  6,  5,  6,  1, 11,  0, 11,  1, 11,  0,  7,  4,  7,  0,  7,  4,  5,  7,  5,  6 },
+/* 109: 0,    2, 3,    5, 6,     */  {  4,  9,  6,  1,  6,  9,  6,  1, 11,  0, 11,  1, 11,  0,  8,  4,  8,  0,  9,  4,  0 },
+/* 117: 0,    2,    4, 5, 6,     */  {  3,  0,  7,  9,  7,  0,  7,  9,  6,  1,  6,  9,  6,  1,  2,  3,  2,  1,  0,  3,  1 },
+/* 213: 0,    2,    4,    6, 7,  */  {  1,  2,  5, 11,  5,  2,  5, 11,  4,  3,  4, 11,  4,  3,  0,  1,  0,  3,  2,  1,  3 },
+/* 121: 0,       3, 4, 5, 6,     */  {  0, 11,  2, 11,  0,  7,  9,  7,  0,  7,  9,  6, 10,  6,  9,  6, 10,  2,  6,  2, 11 },
+/* 233: 0,       3,    5, 6, 7,  */  {  0,  8,  2,  7,  2,  8,  2,  7, 10,  4, 10,  7, 10,  4,  9,  0,  9,  4,  8,  0,  4 },
+/*  62:    1, 2, 3, 4, 5,        */  {  7,  8,  5,  0,  5,  8,  5,  0, 10,  3, 10,  0, 10,  3, 11,  7, 11,  3,  8,  7,  3 },
+/* 158:    1, 2, 3, 4,       7,  */  {  6,  8,  4,  8,  6,  3, 10,  3,  6,  3, 10,  0,  9,  0, 10,  0,  9,  4,  0,  4,  8 },
+/* 174:    1, 2, 3,    5,    7,  */  {  0,  5,  4,  5,  0, 10,  3, 10,  0, 10,  3,  6,  7,  6,  3,  6,  7,  4,  6,  4,  5 },
+/* 182:    1, 2,    4, 5,    7,  */  {  2, 10,  0,  5,  0, 10,  0,  5,  8,  6,  8,  5,  8,  6, 11,  2, 11,  6, 10,  2,  6 },
+/* 214:    1, 2,    4,    6, 7,  */  {  2,  9,  0,  9,  2,  5, 11,  5,  2,  5, 11,  4,  8,  4, 11,  4,  8,  0,  4,  0,  9 },
+/* 186:    1,    3, 4, 5,    7,  */  {  2,  3,  6,  8,  6,  3,  6,  8,  5,  0,  5,  8,  5,  0,  1,  2,  1,  0,  3,  2,  0 },
+/* 234:    1,    3,    5, 6, 7,  */  {  0,  1,  4, 10,  4,  1,  4, 10,  7,  2,  7, 10,  7,  2,  3,  0,  3,  2,  1,  0,  2 },
+/* 124:       2, 3, 4, 5, 6,     */  {  3, 11,  1,  6,  1, 11,  1,  6,  9,  7,  9,  6,  9,  7,  8,  3,  8,  7, 11,  3,  7 },
+/* 188:       2, 3, 4, 5,    7,  */  {  3, 10,  1, 10,  3,  6,  8,  6,  3,  6,  8,  5,  9,  5,  8,  5,  9,  1,  5,  1, 10 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 6.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling6_2[48][15] = {
+/*  67: 0, 1,             6,     */  {  1, 10,  3,  6,  3, 10,  3,  6,  8,  5,  8,  6,  8,  5,  9 },
+/* 131: 0, 1,                7,  */  {  1, 11,  3, 11,  1,  6,  9,  6,  1,  6,  9,  7,  8,  7,  9 },
+/*  21: 0,    2,    4,           */  {  4,  1,  0,  1,  4, 10,  7, 10,  4, 10,  7,  2,  3,  2,  7 },
+/*  69: 0,    2,          6,     */  {  6,  3,  2,  3,  6,  8,  5,  8,  6,  8,  5,  0,  1,  0,  5 },
+/*  41: 0,       3,    5,        */  {  0,  9,  2,  5,  2,  9,  2,  5, 11,  4, 11,  5, 11,  4,  8 },
+/*  73: 0,       3,       6,     */  {  0, 10,  2, 10,  0,  5,  8,  5,  0,  5,  8,  6, 11,  6,  8 },
+/*  81: 0,          4,    6,     */  {  4,  5,  0, 10,  0,  5,  0, 10,  3,  6,  3, 10,  3,  6,  7 },
+/*  97: 0,             5, 6,     */  {  4,  8,  6,  3,  6,  8,  6,  3, 10,  0, 10,  3, 10,  0,  9 },
+/* 193: 0,                6, 7,  */  {  5,  8,  7,  8,  5,  0, 10,  0,  5,  0, 10,  3, 11,  3, 10 },
+/*  22:    1, 2,    4,           */  {  2,  8,  0,  8,  2,  7, 10,  7,  2,  7, 10,  4,  9,  4, 10 },
+/* 134:    1, 2,             7,  */  {  2, 11,  0,  7,  0, 11,  0,  7,  9,  6,  9,  7,  9,  6, 10 },
+/*  42:    1,    3,    5,        */  {  5,  2,  1,  2,  5, 11,  4, 11,  5, 11,  4,  3,  0,  3,  4 },
+/* 138:    1,    3,          7,  */  {  7,  0,  3,  0,  7,  9,  6,  9,  7,  9,  6,  1,  2,  1,  6 },
+/* 146:    1,       4,       7,  */  {  6,  9,  4,  9,  6,  1, 11,  1,  6,  1, 11,  0,  8,  0, 11 },
+/* 162:    1,          5,    7,  */  {  5,  6,  1, 11,  1,  6,  1, 11,  0,  7,  0, 11,  0,  7,  4 },
+/* 194:    1,             6, 7,  */  {  5,  9,  7,  0,  7,  9,  7,  0, 11,  1, 11,  0, 11,  1, 10 },
+/*  28:       2, 3, 4,           */  {  3,  8,  1,  4,  1,  8,  1,  4, 10,  7, 10,  4, 10,  7, 11 },
+/*  44:       2, 3,    5,        */  {  3,  9,  1,  9,  3,  4, 11,  4,  3,  4, 11,  5, 10,  5, 11 },
+/*  52:       2,    4, 5,        */  {  7, 10,  5, 10,  7,  2,  8,  2,  7,  2,  8,  1,  9,  1,  8 },
+/*  84:       2,    4,    6,     */  {  6,  7,  2,  8,  2,  7,  2,  8,  1,  4,  1,  8,  1,  4,  5 },
+/* 148:       2,    4,       7,  */  {  6, 10,  4,  1,  4, 10,  4,  1,  8,  2,  8,  1,  8,  2, 11 },
+/*  56:          3, 4, 5,        */  {  7, 11,  5,  2,  5, 11,  5,  2,  9,  3,  9,  2,  9,  3,  8 },
+/* 104:          3,    5, 6,     */  {  4, 11,  6, 11,  4,  3,  9,  3,  4,  3,  9,  2, 10,  2,  9 },
+/* 168:          3,    5,    7,  */  {  7,  4,  3,  9,  3,  4,  3,  9,  2,  5,  2,  9,  2,  5,  6 },
+/*  87: 0, 1, 2,    4,    6,     */  {  3,  4,  7,  4,  3,  9,  2,  9,  3,  9,  2,  5,  6,  5,  2 },
+/* 151: 0, 1, 2,    4,       7,  */  {  6, 11,  4,  3,  4, 11,  4,  3,  9,  2,  9,  3,  9,  2, 10 },
+/* 199: 0, 1, 2,          6, 7,  */  {  5, 11,  7, 11,  5,  2,  9,  2,  5,  2,  9,  3,  8,  3,  9 },
+/* 107: 0, 1,    3,    5, 6,     */  {  4, 10,  6, 10,  4,  1,  8,  1,  4,  1,  8,  2, 11,  2,  8 },
+/* 171: 0, 1,    3,    5,    7,  */  {  2,  7,  6,  7,  2,  8,  1,  8,  2,  8,  1,  4,  5,  4,  1 },
+/* 203: 0, 1,    3,       6, 7,  */  {  5, 10,  7,  2,  7, 10,  7,  2,  8,  1,  8,  2,  8,  1,  9 },
+/* 211: 0, 1,       4,    6, 7,  */  {  1,  9,  3,  4,  3,  9,  3,  4, 11,  5, 11,  4, 11,  5, 10 },
+/* 227: 0, 1,          5, 6, 7,  */  {  1,  8,  3,  8,  1,  4, 10,  4,  1,  4, 10,  7, 11,  7, 10 },
+/*  61: 0,    2, 3, 4, 5,        */  {  7,  9,  5,  9,  7,  0, 11,  0,  7,  0, 11,  1, 10,  1, 11 },
+/*  93: 0,    2, 3, 4,    6,     */  {  1,  6,  5,  6,  1, 11,  0, 11,  1, 11,  0,  7,  4,  7,  0 },
+/* 109: 0,    2, 3,    5, 6,     */  {  4,  9,  6,  1,  6,  9,  6,  1, 11,  0, 11,  1, 11,  0,  8 },
+/* 117: 0,    2,    4, 5, 6,     */  {  3,  0,  7,  9,  7,  0,  7,  9,  6,  1,  6,  9,  6,  1,  2 },
+/* 213: 0,    2,    4,    6, 7,  */  {  1,  2,  5, 11,  5,  2,  5, 11,  4,  3,  4, 11,  4,  3,  0 },
+/* 121: 0,       3, 4, 5, 6,     */  {  0, 11,  2, 11,  0,  7,  9,  7,  0,  7,  9,  6, 10,  6,  9 },
+/* 233: 0,       3,    5, 6, 7,  */  {  0,  8,  2,  7,  2,  8,  2,  7, 10,  4, 10,  7, 10,  4,  9 },
+/*  62:    1, 2, 3, 4, 5,        */  {  7,  8,  5,  0,  5,  8,  5,  0, 10,  3, 10,  0, 10,  3, 11 },
+/* 158:    1, 2, 3, 4,       7,  */  {  6,  8,  4,  8,  6,  3, 10,  3,  6,  3, 10,  0,  9,  0, 10 },
+/* 174:    1, 2, 3,    5,    7,  */  {  0,  5,  4,  5,  0, 10,  3, 10,  0, 10,  3,  6,  7,  6,  3 },
+/* 182:    1, 2,    4, 5,    7,  */  {  2, 10,  0,  5,  0, 10,  0,  5,  8,  6,  8,  5,  8,  6, 11 },
+/* 214:    1, 2,    4,    6, 7,  */  {  2,  9,  0,  9,  2,  5, 11,  5,  2,  5, 11,  4,  8,  4, 11 },
+/* 186:    1,    3, 4, 5,    7,  */  {  2,  3,  6,  8,  6,  3,  6,  8,  5,  0,  5,  8,  5,  0,  1 },
+/* 234:    1,    3,    5, 6, 7,  */  {  0,  1,  4, 10,  4,  1,  4, 10,  7,  2,  7, 10,  7,  2,  3 },
+/* 124:       2, 3, 4, 5, 6,     */  {  3, 11,  1,  6,  1, 11,  1,  6,  9,  7,  9,  6,  9,  7,  8 },
+/* 188:       2, 3, 4, 5,    7,  */  {  3, 10,  1, 10,  3,  6,  8,  6,  3,  6,  8,  5,  9,  5,  8 }
+};
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+/**
+ * \brief test table for case 7
+ * 3 faces to test + eventually the interior
+ * When the tests on the 3 specified faces are positive :
+ * - if the test on the interior is positive : 5 first triangles
+ * - if the test on the interior is negative : 9 next triangles
+ * When the tests on the first  and the second specified faces are positive : 9 next triangles
+ * When the tests on the first  and the third  specified faces are positive : 9 next triangles
+ * When the tests on the second and the third  specified faces are positive : 9 next triangles
+ * When the test on the first  specified face is positive : 5 next triangles
+ * When the test on the second specified face is positive : 5 next triangles
+ * When the test on the third  specified face is positive : 5 next triangles
+ * When the tests on the 3 specified faces are negative : 3 last triangles
+ * The support edge for the interior test is marked as the 5th column.
+ *
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char test7[16][5] = {
+/*  37: 0,    2,       5,        */  {  1,  2,  5,  7,   1 },
+/* 133: 0,    2,             7,  */  {  3,  4,  5,  7,   3 },
+/* 161: 0,             5,    7,  */  {  4,  1,  6,  7,   4 },
+/*  26:    1,    3, 4,           */  {  4,  1,  5,  7,   0 },
+/*  74:    1,    3,       6,     */  {  2,  3,  5,  7,   2 },
+/*  82:    1,       4,    6,     */  {  1,  2,  6,  7,   5 },
+/* 164:       2,       5,    7,  */  {  2,  3,  6,  7,   6 },
+/*  88:          3, 4,    6,     */  {  3,  4,  6,  7,   7 },
+/* 167: 0, 1, 2,       5,    7,  */  { -3, -4, -6, -7,   7 },
+/*  91: 0, 1,    3, 4,    6,     */  { -2, -3, -6, -7,   6 },
+/* 173: 0,    2, 3,    5,    7,  */  { -1, -2, -6, -7,   5 },
+/* 181: 0,    2,    4, 5,    7,  */  { -2, -3, -5, -7,   2 },
+/* 229: 0,    2,       5, 6, 7,  */  { -4, -1, -5, -7,   0 },
+/*  94:    1, 2, 3, 4,    6,     */  { -4, -1, -6, -7,   4 },
+/* 122:    1,    3, 4, 5, 6,     */  { -3, -4, -5, -7,   3 },
+/* 218:    1,    3, 4,    6, 7,  */  { -1, -2, -5, -7,   1 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 7.1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling7_1[16][9] = {
+/*  37: 0,    2,       5,        */  {  9,  5,  4, 10,  1,  2,  8,  3,  0 },
+/* 133: 0,    2,             7,  */  { 11,  7,  6,  8,  3,  0, 10,  1,  2 },
+/* 161: 0,             5,    7,  */  {  3,  0,  8,  5,  4,  9,  7,  6, 11 },
+/*  26:    1,    3, 4,           */  {  8,  4,  7,  9,  0,  1, 11,  2,  3 },
+/*  74:    1,    3,       6,     */  { 10,  6,  5, 11,  2,  3,  9,  0,  1 },
+/*  82:    1,       4,    6,     */  {  0,  1,  9,  6,  5, 10,  4,  7,  8 },
+/* 164:       2,       5,    7,  */  {  1,  2, 10,  7,  6, 11,  5,  4,  9 },
+/*  88:          3, 4,    6,     */  {  2,  3, 11,  4,  7,  8,  6,  5, 10 },
+/* 167: 0, 1, 2,       5,    7,  */  { 11,  3,  2,  8,  7,  4, 10,  5,  6 },
+/*  91: 0, 1,    3, 4,    6,     */  { 10,  2,  1, 11,  6,  7,  9,  4,  5 },
+/* 173: 0,    2, 3,    5,    7,  */  {  9,  1,  0, 10,  5,  6,  8,  7,  4 },
+/* 181: 0,    2,    4, 5,    7,  */  {  5,  6, 10,  3,  2, 11,  1,  0,  9 },
+/* 229: 0,    2,       5, 6, 7,  */  {  7,  4,  8,  1,  0,  9,  3,  2, 11 },
+/*  94:    1, 2, 3, 4,    6,     */  {  8,  0,  3,  9,  4,  5, 11,  6,  7 },
+/* 122:    1,    3, 4, 5, 6,     */  {  6,  7, 11,  0,  3,  8,  2,  1, 10 },
+/* 218:    1,    3, 4,    6, 7,  */  {  4,  5,  9,  2,  1, 10,  0,  3,  8 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 7.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling7_2[16][3][15] = {
+/*  37: 0,    2,       5,        */  {
+ /* 1,0 */ {  1,  2, 10,  3,  4,  8,  4,  3,  5,  0,  5,  3,  5,  0,  9 },
+ /* 0,1 */ {  3,  0,  8,  9,  1,  4,  2,  4,  1,  4,  2,  5, 10,  5,  2 },
+ /* 1,1 */ {  9,  5,  4,  0, 10,  1, 10,  0,  8, 10,  8,  2,  3,  2,  8 }
+},
+/* 133: 0,    2,             7,  */  {
+ /* 1,0 */ {  3,  0,  8,  1,  6, 10,  6,  1,  7,  2,  7,  1,  7,  2, 11 },
+ /* 0,1 */ {  1,  2, 10, 11,  3,  6,  0,  6,  3,  6,  0,  7,  8,  7,  0 },
+ /* 1,1 */ { 11,  7,  6,  2,  8,  3,  8,  2, 10,  8, 10,  0,  1,  0, 10 }
+},
+/* 161: 0,             5,    7,  */  {
+ /* 1,0 */ {  9,  5,  4, 11,  3,  6,  0,  6,  3,  6,  0,  7,  8,  7,  0 },
+ /* 0,1 */ { 11,  7,  6,  3,  4,  8,  4,  3,  5,  0,  5,  3,  5,  0,  9 },
+ /* 1,1 */ {  3,  0,  8,  4,  9,  7, 11,  7,  9,  5, 11,  9, 11,  5,  6 }
+},
+/*  26:    1,    3, 4,           */  {
+ /* 1,0 */ {  0,  1,  9,  2,  7, 11,  7,  2,  4,  3,  4,  2,  4,  3,  8 },
+ /* 0,1 */ {  2,  3, 11,  8,  0,  7,  1,  7,  0,  7,  1,  4,  9,  4,  1 },
+ /* 1,1 */ {  8,  4,  7,  3,  9,  0,  9,  3, 11,  9, 11,  1,  2,  1, 11 }
+},
+/*  74:    1,    3,       6,     */  {
+ /* 1,0 */ {  2,  3, 11,  0,  5,  9,  5,  0,  6,  1,  6,  0,  6,  1, 10 },
+ /* 0,1 */ {  0,  1,  9, 10,  2,  5,  3,  5,  2,  5,  3,  6, 11,  6,  3 },
+ /* 1,1 */ {  6,  5, 10,  1, 11,  2, 11,  1,  9, 11,  9,  3,  0,  3,  9 }
+},
+/*  82:    1,       4,    6,     */  {
+ /* 1,0 */ {  6,  5, 10,  8,  0,  7,  1,  7,  0,  7,  1,  4,  9,  4,  1 },
+ /* 0,1 */ {  8,  4,  7,  0,  5,  9,  5,  0,  6,  1,  6,  0,  6,  1, 10 },
+ /* 1,1 */ {  0,  1,  9,  5, 10,  4,  8,  4, 10,  6,  8, 10,  8,  6,  7 }
+},
+/* 164:       2,       5,    7,  */  {
+ /* 1,0 */ { 11,  7,  6,  9,  1,  4,  2,  4,  1,  4,  2,  5, 10,  5,  2 },
+ /* 0,1 */ {  9,  5,  4,  1,  6, 10,  6,  1,  7,  2,  7,  1,  7,  2, 11 },
+ /* 1,1 */ {  1,  2, 10,  6, 11,  5,  9,  5, 11,  7,  9, 11,  9,  7,  4 }
+},
+/*  88:          3, 4,    6,     */  {
+ /* 1,0 */ {  8,  4,  7, 10,  2,  5,  3,  5,  2,  5,  3,  6, 11,  6,  3 },
+ /* 0,1 */ {  6,  5, 10,  2,  7, 11,  7,  2,  4,  3,  4,  2,  4,  3,  8 },
+ /* 1,1 */ {  2,  3, 11,  7,  8,  6, 10,  6,  8,  4, 10,  8, 10,  4,  5 }
+},
+/* 167: 0, 1, 2,       5,    7,  */  {
+ /* 1,0 */ {  7,  4,  8,  5,  2, 10,  2,  5,  3,  6,  3,  5,  3,  6, 11 },
+ /* 0,1 */ { 10,  5,  6, 11,  7,  2,  4,  2,  7,  2,  4,  3,  8,  3,  4 },
+ /* 1,1 */ { 11,  3,  2,  6,  8,  7,  8,  6, 10,  8, 10,  4,  5,  4, 10 }
+},
+/*  91: 0, 1,    3, 4,    6,     */  {
+ /* 1,0 */ {  6,  7, 11,  4,  1,  9,  1,  4,  2,  5,  2,  4,  2,  5, 10 },
+ /* 0,1 */ {  4,  5,  9, 10,  6,  1,  7,  1,  6,  1,  7,  2, 11,  2,  7 },
+ /* 1,1 */ { 10,  2,  1,  5, 11,  6, 11,  5,  9, 11,  9,  7,  4,  7,  9 }
+},
+/* 173: 0,    2, 3,    5,    7,  */  {
+ /* 1,0 */ { 10,  5,  6,  7,  0,  8,  0,  7,  1,  4,  1,  7,  1,  4,  9 },
+ /* 0,1 */ {  7,  4,  8,  9,  5,  0,  6,  0,  5,  0,  6,  1, 10,  1,  6 },
+ /* 1,1 */ {  9,  1,  0,  4, 10,  5, 10,  4,  8, 10,  8,  6,  7,  6,  8 }
+},
+/* 181: 0,    2,    4, 5,    7,  */  {
+ /* 1,0 */ { 11,  3,  2,  9,  5,  0,  6,  0,  5,  0,  6,  1, 10,  1,  6 },
+ /* 0,1 */ {  9,  1,  0,  5,  2, 10,  2,  5,  3,  6,  3,  5,  3,  6, 11 },
+ /* 1,1 */ { 10,  5,  6,  2, 11,  1,  9,  1, 11,  3,  9, 11,  9,  3,  0 }
+},
+/* 229: 0,    2,       5, 6, 7,  */  {
+ /* 1,0 */ {  9,  1,  0, 11,  7,  2,  4,  2,  7,  2,  4,  3,  8,  3,  4 },
+ /* 0,1 */ { 11,  3,  2,  7,  0,  8,  0,  7,  1,  4,  1,  7,  1,  4,  9 },
+ /* 1,1 */ {  7,  4,  8,  0,  9,  3, 11,  3,  9,  1, 11,  9, 11,  1,  2 }
+},
+/*  94:    1, 2, 3, 4,    6,     */  {
+ /* 1,0 */ {  4,  5,  9,  6,  3, 11,  3,  6,  0,  7,  0,  6,  0,  7,  8 },
+ /* 0,1 */ {  6,  7, 11,  8,  4,  3,  5,  3,  4,  3,  5,  0,  9,  0,  5 },
+ /* 1,1 */ {  8,  0,  3,  7,  9,  4,  9,  7, 11,  9, 11,  5,  6,  5, 11 }
+},
+/* 122:    1,    3, 4, 5, 6,     */  {
+ /* 1,0 */ {  8,  0,  3, 10,  6,  1,  7,  1,  6,  1,  7,  2, 11,  2,  7 },
+ /* 0,1 */ { 10,  2,  1,  6,  3, 11,  3,  6,  0,  7,  0,  6,  0,  7,  8 },
+ /* 1,1 */ {  6,  7, 11,  3,  8,  2, 10,  2,  8,  0, 10,  8, 10,  0,  1 }
+},
+/* 218:    1,    3, 4,    6, 7,  */  {
+ /* 1,0 */ { 10,  2,  1,  8,  4,  3,  5,  3,  4,  3,  5,  0,  9,  0,  5 },
+ /* 0,1 */ {  8,  0,  3,  4,  1,  9,  1,  4,  2,  5,  2,  4,  2,  5, 10 },
+ /* 1,1 */ {  4,  5,  9,  1, 10,  0,  8,  0, 10,  2,  8, 10,  8,  2,  3 } }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 7.3
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling7_3[16][3][27] = {
+/*  37: 0,    2,       5,        */  {
+ /* 1,0 */ { 12,  2, 10, 12, 10,  5, 12,  5,  4, 12,  4,  8, 12,  8,  3, 12,  3,  0, 12,  0,  9, 12,  9,  1, 12,  1,  2 },
+ /* 0,1 */ { 12,  5,  4, 12,  4,  8, 12,  8,  3, 12,  3,  2, 12,  2, 10, 12, 10,  1, 12,  1,  0, 12,  0,  9, 12,  9,  5 },
+ /* 1,1 */ {  5,  4, 12, 10,  5, 12,  2, 10, 12,  3,  2, 12,  8,  3, 12,  0,  8, 12,  1,  0, 12,  9,  1, 12,  4,  9, 12 }
+},
+/* 133: 0,    2,             7,  */  {
+ /* 1,0 */ { 12,  0,  8, 12,  8,  7, 12,  7,  6, 12,  6, 10, 12, 10,  1, 12,  1,  2, 12,  2, 11, 12, 11,  3, 12,  3,  0 },
+ /* 0,1 */ { 12,  7,  6, 12,  6, 10, 12, 10,  1, 12,  1,  0, 12,  0,  8, 12,  8,  3, 12,  3,  2, 12,  2, 11, 12, 11,  7 },
+ /* 1,1 */ {  7,  6, 12,  8,  7, 12,  0,  8, 12,  1,  0, 12, 10,  1, 12,  2, 10, 12,  3,  2, 12, 11,  3, 12,  6, 11, 12 }
+},
+/* 161: 0,             5,    7,  */  {
+ /* 1,0 */ {  9,  5, 12,  0,  9, 12,  3,  0, 12, 11,  3, 12,  6, 11, 12,  7,  6, 12,  8,  7, 12,  4,  8, 12,  5,  4, 12 },
+ /* 0,1 */ {  3,  0, 12, 11,  3, 12,  6, 11, 12,  5,  6, 12,  9,  5, 12,  4,  9, 12,  7,  4, 12,  8,  7, 12,  0,  8, 12 },
+ /* 1,1 */ { 12,  3,  0, 12,  0,  9, 12,  9,  5, 12,  5,  6, 12,  6, 11, 12, 11,  7, 12,  7,  4, 12,  4,  8, 12,  8,  3 }
+},
+/*  26:    1,    3, 4,           */  {
+ /* 1,0 */ { 12,  1,  9, 12,  9,  4, 12,  4,  7, 12,  7, 11, 12, 11,  2, 12,  2,  3, 12,  3,  8, 12,  8,  0, 12,  0,  1 },
+ /* 0,1 */ { 12,  4,  7, 12,  7, 11, 12, 11,  2, 12,  2,  1, 12,  1,  9, 12,  9,  0, 12,  0,  3, 12,  3,  8, 12,  8,  4 },
+ /* 1,1 */ {  4,  7, 12,  9,  4, 12,  1,  9, 12,  2,  1, 12, 11,  2, 12,  3, 11, 12,  0,  3, 12,  8,  0, 12,  7,  8, 12 }
+},
+/*  74:    1,    3,       6,     */  {
+ /* 1,0 */ { 12,  3, 11, 12, 11,  6, 12,  6,  5, 12,  5,  9, 12,  9,  0, 12,  0,  1, 12,  1, 10, 12, 10,  2, 12,  2,  3 },
+ /* 0,1 */ { 12,  6,  5, 12,  5,  9, 12,  9,  0, 12,  0,  3, 12,  3, 11, 12, 11,  2, 12,  2,  1, 12,  1, 10, 12, 10,  6 },
+ /* 1,1 */ {  6,  5, 12, 11,  6, 12,  3, 11, 12,  0,  3, 12,  9,  0, 12,  1,  9, 12,  2,  1, 12, 10,  2, 12,  5, 10, 12 }
+},
+/*  82:    1,       4,    6,     */  {
+ /* 1,0 */ { 10,  6, 12,  1, 10, 12,  0,  1, 12,  8,  0, 12,  7,  8, 12,  4,  7, 12,  9,  4, 12,  5,  9, 12,  6,  5, 12 },
+ /* 0,1 */ {  0,  1, 12,  8,  0, 12,  7,  8, 12,  6,  7, 12, 10,  6, 12,  5, 10, 12,  4,  5, 12,  9,  4, 12,  1,  9, 12 },
+ /* 1,1 */ { 12,  0,  1, 12,  1, 10, 12, 10,  6, 12,  6,  7, 12,  7,  8, 12,  8,  4, 12,  4,  5, 12,  5,  9, 12,  9,  0 }
+},
+/* 164:       2,       5,    7,  */  {
+ /* 1,0 */ { 11,  7, 12,  2, 11, 12,  1,  2, 12,  9,  1, 12,  4,  9, 12,  5,  4, 12, 10,  5, 12,  6, 10, 12,  7,  6, 12 },
+ /* 0,1 */ {  1,  2, 12,  9,  1, 12,  4,  9, 12,  7,  4, 12, 11,  7, 12,  6, 11, 12,  5,  6, 12, 10,  5, 12,  2, 10, 12 },
+ /* 1,1 */ { 12,  1,  2, 12,  2, 11, 12, 11,  7, 12,  7,  4, 12,  4,  9, 12,  9,  5, 12,  5,  6, 12,  6, 10, 12, 10,  1 }
+},
+/*  88:          3, 4,    6,     */  {
+ /* 1,0 */ {  8,  4, 12,  3,  8, 12,  2,  3, 12, 10,  2, 12,  5, 10, 12,  6,  5, 12, 11,  6, 12,  7, 11, 12,  4,  7, 12 },
+ /* 0,1 */ {  2,  3, 12, 10,  2, 12,  5, 10, 12,  4,  5, 12,  8,  4, 12,  7,  8, 12,  6,  7, 12, 11,  6, 12,  3, 11, 12 },
+ /* 1,1 */ { 12,  2,  3, 12,  3,  8, 12,  8,  4, 12,  4,  5, 12,  5, 10, 12, 10,  6, 12,  6,  7, 12,  7, 11, 12, 11,  2 }
+},
+/* 167: 0, 1, 2,       5,    7,  */  {
+ /* 1,0 */ { 12,  4,  8, 12,  8,  3, 12,  3,  2, 12,  2, 10, 12, 10,  5, 12,  5,  6, 12,  6, 11, 12, 11,  7, 12,  7,  4 },
+ /* 0,1 */ { 12,  3,  2, 12,  2, 10, 12, 10,  5, 12,  5,  4, 12,  4,  8, 12,  8,  7, 12,  7,  6, 12,  6, 11, 12, 11,  3 },
+ /* 1,1 */ {  3,  2, 12,  8,  3, 12,  4,  8, 12,  5,  4, 12, 10,  5, 12,  6, 10, 12,  7,  6, 12, 11,  7, 12,  2, 11, 12 }
+},
+/*  91: 0, 1,    3, 4,    6,     */  {
+ /* 1,0 */ { 12,  7, 11, 12, 11,  2, 12,  2,  1, 12,  1,  9, 12,  9,  4, 12,  4,  5, 12,  5, 10, 12, 10,  6, 12,  6,  7 },
+ /* 0,1 */ { 12,  2,  1, 12,  1,  9, 12,  9,  4, 12,  4,  7, 12,  7, 11, 12, 11,  6, 12,  6,  5, 12,  5, 10, 12, 10,  2 },
+ /* 1,1 */ {  2,  1, 12, 11,  2, 12,  7, 11, 12,  4,  7, 12,  9,  4, 12,  5,  9, 12,  6,  5, 12, 10,  6, 12,  1, 10, 12 }
+},
+/* 173: 0,    2, 3,    5,    7,  */  {
+ /* 1,0 */ { 12,  6, 10, 12, 10,  1, 12,  1,  0, 12,  0,  8, 12,  8,  7, 12,  7,  4, 12,  4,  9, 12,  9,  5, 12,  5,  6 },
+ /* 0,1 */ { 12,  1,  0, 12,  0,  8, 12,  8,  7, 12,  7,  6, 12,  6, 10, 12, 10,  5, 12,  5,  4, 12,  4,  9, 12,  9,  1 },
+ /* 1,1 */ {  1,  0, 12, 10,  1, 12,  6, 10, 12,  7,  6, 12,  8,  7, 12,  4,  8, 12,  5,  4, 12,  9,  5, 12,  0,  9, 12 }
+},
+/* 181: 0,    2,    4, 5,    7,  */  {
+ /* 1,0 */ { 11,  3, 12,  6, 11, 12,  5,  6, 12,  9,  5, 12,  0,  9, 12,  1,  0, 12, 10,  1, 12,  2, 10, 12,  3,  2, 12 },
+ /* 0,1 */ {  5,  6, 12,  9,  5, 12,  0,  9, 12,  3,  0, 12, 11,  3, 12,  2, 11, 12,  1,  2, 12, 10,  1, 12,  6, 10, 12 },
+ /* 1,1 */ { 12,  5,  6, 12,  6, 11, 12, 11,  3, 12,  3,  0, 12,  0,  9, 12,  9,  1, 12,  1,  2, 12,  2, 10, 12, 10,  5 }
+},
+/* 229: 0,    2,       5, 6, 7,  */  {
+ /* 1,0 */ {  9,  1, 12,  4,  9, 12,  7,  4, 12, 11,  7, 12,  2, 11, 12,  3,  2, 12,  8,  3, 12,  0,  8, 12,  1,  0, 12 },
+ /* 0,1 */ {  7,  4, 12, 11,  7, 12,  2, 11, 12,  1,  2, 12,  9,  1, 12,  0,  9, 12,  3,  0, 12,  8,  3, 12,  4,  8, 12 },
+ /* 1,1 */ { 12,  7,  4, 12,  4,  9, 12,  9,  1, 12,  1,  2, 12,  2, 11, 12, 11,  3, 12,  3,  0, 12,  0,  8, 12,  8,  7 }
+},
+/*  94:    1, 2, 3, 4,    6,     */  {
+ /* 1,0 */ { 12,  5,  9, 12,  9,  0, 12,  0,  3, 12,  3, 11, 12, 11,  6, 12,  6,  7, 12,  7,  8, 12,  8,  4, 12,  4,  5 },
+ /* 0,1 */ { 12,  0,  3, 12,  3, 11, 12, 11,  6, 12,  6,  5, 12,  5,  9, 12,  9,  4, 12,  4,  7, 12,  7,  8, 12,  8,  0 },
+ /* 1,1 */ {  0,  3, 12,  9,  0, 12,  5,  9, 12,  6,  5, 12, 11,  6, 12,  7, 11, 12,  4,  7, 12,  8,  4, 12,  3,  8, 12 }
+},
+/* 122:    1,    3, 4, 5, 6,     */  {
+ /* 1,0 */ {  8,  0, 12,  7,  8, 12,  6,  7, 12, 10,  6, 12,  1, 10, 12,  2,  1, 12, 11,  2, 12,  3, 11, 12,  0,  3, 12 },
+ /* 0,1 */ {  6,  7, 12, 10,  6, 12,  1, 10, 12,  0,  1, 12,  8,  0, 12,  3,  8, 12,  2,  3, 12, 11,  2, 12,  7, 11, 12 },
+ /* 1,1 */ { 12,  6,  7, 12,  7,  8, 12,  8,  0, 12,  0,  1, 12,  1, 10, 12, 10,  2, 12,  2,  3, 12,  3, 11, 12, 11,  6 }
+},
+/* 218:    1,    3, 4,    6, 7,  */  {
+ /* 1,0 */ { 10,  2, 12,  5, 10, 12,  4,  5, 12,  8,  4, 12,  3,  8, 12,  0,  3, 12,  9,  0, 12,  1,  9, 12,  2,  1, 12 },
+ /* 0,1 */ {  4,  5, 12,  8,  4, 12,  3,  8, 12,  2,  3, 12, 10,  2, 12,  1, 10, 12,  0,  1, 12,  9,  0, 12,  5,  9, 12 },
+ /* 1,1 */ { 12,  4,  5, 12,  5, 10, 12, 10,  2, 12,  2,  3, 12,  3,  8, 12,  8,  0, 12,  0,  1, 12,  1,  9, 12,  9,  4 } }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 7.4.1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling7_4_1[16][15] = {
+/*  37: 0,    2,       5,        */  {  3,  4,  8,  4,  3, 10,  2, 10,  3,  4, 10,  5,  9,  1,  0 },
+/* 133: 0,    2,             7,  */  {  1,  6, 10,  6,  1,  8,  0,  8,  1,  6,  8,  7, 11,  3,  2 },
+/* 161: 0,             5,    7,  */  { 11,  3,  6,  9,  6,  3,  6,  9,  5,  0,  9,  3,  7,  4,  8 },
+/*  26:    1,    3, 4,           */  {  2,  7, 11,  7,  2,  9,  1,  9,  2,  7,  9,  4,  8,  0,  3 },
+/*  74:    1,    3,       6,     */  {  0,  5,  9,  5,  0, 11,  3, 11,  0,  5, 11,  6, 10,  2,  1 },
+/*  82:    1,       4,    6,     */  {  8,  0,  7, 10,  7,  0,  7, 10,  6,  1, 10,  0,  4,  5,  9 },
+/* 164:       2,       5,    7,  */  {  9,  1,  4, 11,  4,  1,  4, 11,  7,  2, 11,  1,  5,  6, 10 },
+/*  88:          3, 4,    6,     */  { 10,  2,  5,  8,  5,  2,  5,  8,  4,  3,  8,  2,  6,  7, 11 },
+/* 167: 0, 1, 2,       5,    7,  */  {  5,  2, 10,  2,  5,  8,  4,  8,  5,  2,  8,  3, 11,  7,  6 },
+/*  91: 0, 1,    3, 4,    6,     */  {  4,  1,  9,  1,  4, 11,  7, 11,  4,  1, 11,  2, 10,  6,  5 },
+/* 173: 0,    2, 3,    5,    7,  */  {  7,  0,  8,  0,  7, 10,  6, 10,  7,  0, 10,  1,  9,  5,  4 },
+/* 181: 0,    2,    4, 5,    7,  */  {  9,  5,  0, 11,  0,  5,  0, 11,  3,  6, 11,  5,  1,  2, 10 },
+/* 229: 0,    2,       5, 6, 7,  */  { 11,  7,  2,  9,  2,  7,  2,  9,  1,  4,  9,  7,  3,  0,  8 },
+/*  94:    1, 2, 3, 4,    6,     */  {  6,  3, 11,  3,  6,  9,  5,  9,  6,  3,  9,  0,  8,  4,  7 },
+/* 122:    1,    3, 4, 5, 6,     */  { 10,  6,  1,  8,  1,  6,  1,  8,  0,  7,  8,  6,  2,  3, 11 },
+/* 218:    1,    3, 4,    6, 7,  */  {  8,  4,  3, 10,  3,  4,  3, 10,  2,  5, 10,  4,  0,  1,  9 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 7.4.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling7_4_2[16][27] = {
+/*  37: 0,    2,       5,        */  {   9,  4,  8,  4,  9,  5, 10,  5,  9,  1, 10,  9, 10,  1,  2,  0,  2,  1,  2,  0,  3,  8,  3,  0,  9,  8,  0 },
+/* 133: 0,    2,             7,  */  {  11,  6, 10,  6, 11,  7,  8,  7, 11,  3,  8, 11,  8,  3,  0,  2,  0,  3,  0,  2,  1, 10,  1,  2, 11, 10,  2 },
+/* 161: 0,             5,    7,  */  {  11,  3,  8,  0,  8,  3,  8,  0,  9,  8,  9,  4,  5,  4,  9,  4,  5,  7,  6,  7,  5,  7,  6, 11,  7, 11,  8 },
+/*  26:    1,    3, 4,           */  {   8,  7, 11,  7,  8,  4,  9,  4,  8,  0,  9,  8,  9,  0,  1,  3,  1,  0,  1,  3,  2, 11,  2,  3,  8, 11,  3 },
+/*  74:    1,    3,       6,     */  {  10,  5,  9,  5, 10,  6, 11,  6, 10,  2, 11, 10, 11,  2,  3,  1,  3,  2,  3,  1,  0,  9,  0,  1, 10,  9,  1 },
+/*  82:    1,       4,    6,     */  {   8,  0,  9,  1,  9,  0,  9,  1, 10,  9, 10,  5,  6,  5, 10,  5,  6,  4,  7,  4,  6,  4,  7,  8,  4,  8,  9 },
+/* 164:       2,       5,    7,  */  {   9,  1, 10,  2, 10,  1, 10,  2, 11, 10, 11,  6,  7,  6, 11,  6,  7,  5,  4,  5,  7,  5,  4,  9,  5,  9, 10 },
+/*  88:          3, 4,    6,     */  {  10,  2, 11,  3, 11,  2, 11,  3,  8, 11,  8,  7,  4,  7,  8,  7,  4,  6,  5,  6,  4,  6,  5, 10,  6, 10, 11 },
+/* 167: 0, 1, 2,       5,    7,  */  {  11,  2, 10,  2, 11,  3,  8,  3, 11,  7,  8, 11,  8,  7,  4,  6,  4,  7,  4,  6,  5, 10,  5,  6, 11, 10,  6 },
+/*  91: 0, 1,    3, 4,    6,     */  {  10,  1,  9,  1, 10,  2, 11,  2, 10,  6, 11, 10, 11,  6,  7,  5,  7,  6,  7,  5,  4,  9,  4,  5, 10,  9,  5 },
+/* 173: 0,    2, 3,    5,    7,  */  {   9,  0,  8,  0,  9,  1, 10,  1,  9,  5, 10,  9, 10,  5,  6,  4,  6,  5,  6,  4,  7,  8,  7,  4,  9,  8,  4 },
+/* 181: 0,    2,    4, 5,    7,  */  {   9,  5, 10,  6, 10,  5, 10,  6, 11, 10, 11,  2,  3,  2, 11,  2,  3,  1,  0,  1,  3,  1,  0,  9,  1,  9, 10 },
+/* 229: 0,    2,       5, 6, 7,  */  {  11,  7,  8,  4,  8,  7,  8,  4,  9,  8,  9,  0,  1,  0,  9,  0,  1,  3,  2,  3,  1,  3,  2, 11,  3, 11,  8 },
+/*  94:    1, 2, 3, 4,    6,     */  {   8,  3, 11,  3,  8,  0,  9,  0,  8,  4,  9,  8,  9,  4,  5,  7,  5,  4,  5,  7,  6, 11,  6,  7,  8, 11,  7 },
+/* 122:    1,    3, 4, 5, 6,     */  {  10,  6, 11,  7, 11,  6, 11,  7,  8, 11,  8,  3,  0,  3,  8,  3,  0,  2,  1,  2,  0,  2,  1, 10,  2, 10, 11 },
+/* 218:    1,    3, 4,    6, 7,  */  {   8,  4,  9,  5,  9,  4,  9,  5, 10,  9, 10,  1,  2,  1, 10,  1,  2,  0,  3,  0,  2,  0,  3,  8,  0,  8,  9 }
+};
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 8
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling8[6][6] = {
+/*  15: 0, 1, 2, 3,              */  { 9,  8, 10, 10,  8, 11 },
+/*  51: 0, 1,       4, 5,        */  { 1,  5,  3,  3,  5,  7 },
+/* 153: 0,       3, 4,       7,  */  { 0,  4,  2,  4,  6,  2 },
+/* 102:    1, 2,       5, 6,     */  { 0,  2,  4,  4,  2,  6 },
+/* 204:       2, 3,       6, 7,  */  { 1,  3,  5,  3,  7,  5 },
+/* 240:             4, 5, 6, 7,  */  { 9, 10,  8, 10, 11,  8 }
+};
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 9
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling9[8][12] = {
+/*  39: 0, 1, 2,       5,        */  {  2, 10,  5,  3,  2,  5,  3,  5,  4,  3,  4,  8 },
+/*  27: 0, 1,    3, 4,           */  {  4,  7, 11,  9,  4, 11,  9, 11,  2,  9,  2,  1 },
+/* 141: 0,    2, 3,          7,  */  { 10,  7,  6,  1,  7, 10,  1,  8,  7,  1,  0,  8 },
+/* 177: 0,          4, 5,    7,  */  {  3,  6, 11,  0,  6,  3,  0,  5,  6,  0,  9,  5 },
+/*  78:    1, 2, 3,       6,     */  {  3, 11,  6,  0,  3,  6,  0,  6,  5,  0,  5,  9 },
+/* 114:    1,       4, 5, 6,     */  { 10,  6,  7,  1, 10,  7,  1,  7,  8,  1,  8,  0 },
+/* 228:       2,       5, 6, 7,  */  {  4, 11,  7,  9, 11,  4,  9,  2, 11,  9,  1,  2 },
+/* 216:          3, 4,    6, 7,  */  {  2,  5, 10,  3,  5,  2,  3,  4,  5,  3,  8,  4 }
+};
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+/**
+ * \brief test table for case 10
+ * 2 faces to test + eventually the interior
+ * When the tests on both specified faces are positive : 4 middle triangles (1)
+ * When the test on the first  specified face is positive : 8 first triangles
+ * When the test on the second specified face is positive : 8 next triangles
+ * When the tests on both specified faces are negative :
+ * - if the test on the interior is negative : 4 middle triangles
+ * - if the test on the interior is positive : 8 last triangles
+ *
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char test10[6][3] = {
+/* 195: 0, 1,             6, 7,  */  {  2,  4,  7 },
+/*  85: 0,    2,    4,    6,     */  {  5,  6,  7 },
+/* 105: 0,       3,    5, 6,     */  {  1,  3,  7 },
+/* 150:    1, 2,    4,       7,  */  {  1,  3,  7 },
+/* 170:    1,    3,    5,    7,  */  {  5,  6,  7 },
+/*  60:       2, 3, 4, 5,        */  {  2,  4,  7 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 10.1.1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling10_1_1[6][12] = {
+/* 195: 0, 1,             6, 7,  */  {  5, 10,  7, 11,  7, 10,  8,  1,  9,  1,  8,  3 },
+/*  85: 0,    2,    4,    6,     */  {  1,  2,  5,  6,  5,  2,  4,  3,  0,  3,  4,  7 },
+/* 105: 0,       3,    5, 6,     */  { 11,  0,  8,  0, 11,  2,  4,  9,  6, 10,  6,  9 },
+/* 150:    1, 2,    4,       7,  */  {  9,  0, 10,  2, 10,  0,  6,  8,  4,  8,  6, 11 },
+/* 170:    1,    3,    5,    7,  */  {  7,  2,  3,  2,  7,  6,  0,  1,  4,  5,  4,  1 },
+/*  60:       2, 3, 4, 5,        */  {  7,  9,  5,  9,  7,  8, 10,  1, 11,  3, 11,  1 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 10.1.1 inverted
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling10_1_1_[6][12] = {
+/* 195: 0, 1,             6, 7,  */  {  5,  9,  7,  8,  7,  9, 11,  1, 10,  1, 11,  3 },
+/*  85: 0,    2,    4,    6,     */  {  3,  2,  7,  6,  7,  2,  4,  1,  0,  1,  4,  5 },
+/* 105: 0,       3,    5, 6,     */  { 10,  0,  9,  0, 10,  2,  4,  8,  6, 11,  6,  8 },
+/* 150:    1, 2,    4,       7,  */  {  8,  0, 11,  2, 11,  0,  6,  9,  4,  9,  6, 10 },
+/* 170:    1,    3,    5,    7,  */  {  5,  2,  1,  2,  5,  6,  0,  3,  4,  7,  4,  3 },
+/*  60:       2, 3, 4, 5,        */  {  7, 10,  5, 10,  7, 11,  9,  1,  8,  3,  8,  1 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 10.1.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling10_1_2[6][24] = {
+/* 195: 0, 1,             6, 7,  */  {  3, 11,  7,  3,  7,  8,  9,  8,  7,  5,  9,  7,  9,  5, 10,  9, 10,  1,  3,  1, 10, 11,  3, 10 },
+/*  85: 0,    2,    4,    6,     */  {  7,  6,  5,  7,  5,  4,  0,  4,  5,  1,  0,  5,  0,  1,  2,  0,  2,  3,  7,  3,  2,  6,  7,  2 },
+/* 105: 0,       3,    5, 6,     */  { 11,  2, 10,  6, 11, 10, 11,  6,  4, 11,  4,  8,  0,  8,  4,  9,  0,  4,  0,  9, 10,  0, 10,  2 },
+/* 150:    1, 2,    4,       7,  */  { 11,  2, 10, 11, 10,  6,  4,  6, 10,  9,  4, 10,  4,  9,  0,  4,  0,  8, 11,  8,  0,  2, 11,  0 },
+/* 170:    1,    3,    5,    7,  */  {  7,  6,  5,  4,  7,  5,  7,  4,  0,  7,  0,  3,  2,  3,  0,  1,  2,  0,  2,  1,  5,  2,  5,  6 },
+/*  60:       2, 3, 4, 5,        */  {  7,  8,  3, 11,  7,  3,  7, 11, 10,  7, 10,  5,  9,  5, 10,  1,  9, 10,  9,  1,  3,  9,  3,  8 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 10.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling10_2[6][24] = {
+/* 195: 0, 1,             6, 7,  */  { 12,  5,  9, 12,  9,  8, 12,  8,  3, 12,  3,  1, 12,  1, 10, 12, 10, 11, 12, 11,  7, 12,  7,  5 },
+/*  85: 0,    2,    4,    6,     */  { 12,  1,  0, 12,  0,  4, 12,  4,  7, 12,  7,  3, 12,  3,  2, 12,  2,  6, 12,  6,  5, 12,  5,  1 },
+/* 105: 0,       3,    5, 6,     */  {  4,  8, 12,  6,  4, 12, 10,  6, 12,  9, 10, 12,  0,  9, 12,  2,  0, 12, 11,  2, 12,  8, 11, 12 },
+/* 150:    1, 2,    4,       7,  */  { 12,  9,  4, 12,  4,  6, 12,  6, 11, 12, 11,  8, 12,  8,  0, 12,  0,  2, 12,  2, 10, 12, 10,  9 },
+/* 170:    1,    3,    5,    7,  */  {  0,  3, 12,  4,  0, 12,  5,  4, 12,  1,  5, 12,  2,  1, 12,  6,  2, 12,  7,  6, 12,  3,  7, 12 },
+/*  60:       2, 3, 4, 5,        */  { 10,  5, 12, 11, 10, 12,  3, 11, 12,  1,  3, 12,  9,  1, 12,  8,  9, 12,  7,  8, 12,  5,  7, 12 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 10.2 inverted
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling10_2_[6][24] = {
+/* 195: 0, 1,             6, 7,  */  {  8,  7, 12,  9,  8, 12,  1,  9, 12,  3,  1, 12, 11,  3, 12, 10, 11, 12,  5, 10, 12,  7,  5, 12 },
+/*  85: 0,    2,    4,    6,     */  {  4,  5, 12,  0,  4, 12,  3,  0, 12,  7,  3, 12,  6,  7, 12,  2,  6, 12,  1,  2, 12,  5,  1, 12 },
+/* 105: 0,       3,    5, 6,     */  { 12, 11,  6, 12,  6,  4, 12,  4,  9, 12,  9, 10, 12, 10,  2, 12,  2,  0, 12,  0,  8, 12,  8, 11 },
+/* 150:    1, 2,    4,       7,  */  {  6, 10, 12,  4,  6, 12,  8,  4, 12, 11,  8, 12,  2, 11, 12,  0,  2, 12,  9,  0, 12, 10,  9, 12 },
+/* 170:    1,    3,    5,    7,  */  { 12,  7,  4, 12,  4,  0, 12,  0,  1, 12,  1,  5, 12,  5,  6, 12,  6,  2, 12,  2,  3, 12,  3,  7 },
+/*  60:       2, 3, 4, 5,        */  { 12,  7, 11, 12, 11, 10, 12, 10,  1, 12,  1,  3, 12,  3,  8, 12,  8,  9, 12,  9,  5, 12,  5,  7 }
+};
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 11
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling11[12][12] = {
+/*  23: 0, 1, 2,    4,           */  { 2, 10,  9,  2,  9,  7,  2,  7,  3,  7,  9,  4 },
+/* 139: 0, 1,    3,          7,  */  { 1,  6,  2,  1,  8,  6,  1,  9,  8,  8,  7,  6 },
+/*  99: 0, 1,          5, 6,     */  { 8,  3,  1,  8,  1,  6,  8,  6,  4,  6,  1, 10 },
+/*  77: 0,    2, 3,       6,     */  { 0,  8, 11,  0, 11,  5,  0,  5,  1,  5, 11,  6 },
+/*  57: 0,       3, 4, 5,        */  { 9,  5,  7,  9,  7,  2,  9,  2,  0,  2,  7, 11 },
+/* 209: 0,          4,    6, 7,  */  { 5,  0,  4,  5, 11,  0,  5, 10, 11, 11,  3,  0 },
+/*  46:    1, 2, 3,    5,        */  { 5,  4,  0,  5,  0, 11,  5, 11, 10, 11,  0,  3 },
+/* 198:    1, 2,          6, 7,  */  { 9,  7,  5,  9,  2,  7,  9,  0,  2,  2, 11,  7 },
+/* 178:    1,       4, 5,    7,  */  { 0, 11,  8,  0,  5, 11,  0,  1,  5,  5,  6, 11 },
+/* 156:       2, 3, 4,       7,  */  { 8,  1,  3,  8,  6,  1,  8,  4,  6,  6, 10,  1 },
+/* 116:       2,    4, 5, 6,     */  { 1,  2,  6,  1,  6,  8,  1,  8,  9,  8,  6,  7 },
+/* 232:          3,    5, 6, 7,  */  { 2,  9, 10,  2,  7,  9,  2,  3,  7,  7,  4,  9 }
+};
+//_____________________________________________________________________________
+
+
+//_____________________________________________________________________________
+/**
+ * \brief test table for case 12
+ * 2 faces to test + eventually the interior
+ * When the tests on both specified faces are positive : 4 middle triangles (1)
+ * When the test on the first  specified face is positive : 8 first triangles
+ * When the test on the second specified face is positive : 8 next triangles
+ * When the tests on both specified faces are negative :
+ * - if the test on the interior is negative : 4 middle triangles
+ * - if the test on the interior is positive : 8 last triangles
+ * The support edge for the interior test is marked as the 4th column.
+ *
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char test12[24][4] = {
+/* 135: 0, 1, 2,             7,  */  {  4,  3,  7,  11 },
+/*  75: 0, 1,    3,       6,     */  {  3,  2,  7,  10 },
+/*  83: 0, 1,       4,    6,     */  {  2,  6,  7,   5 },
+/* 163: 0, 1,          5,    7,  */  {  6,  4,  7,   7 },
+/*  45: 0,    2, 3,    5,        */  {  2,  1,  7,   9 },
+/*  53: 0,    2,    4, 5,        */  {  5,  2,  7,   1 },
+/* 149: 0,    2,    4,       7,  */  {  5,  3,  7,   2 },
+/* 101: 0,    2,       5, 6,     */  {  5,  1,  7,   0 },
+/* 197: 0,    2,          6, 7,  */  {  5,  4,  7,   3 },
+/*  89: 0,       3, 4,    6,     */  {  6,  3,  7,   6 },
+/* 169: 0,       3,    5,    7,  */  {  1,  6,  7,   4 },
+/* 225: 0,             5, 6, 7,  */  {  1,  4,  7,   8 },
+/*  30:    1, 2, 3, 4,           */  {  4,  1,  7,   8 },
+/*  86:    1, 2,    4,    6,     */  {  6,  1,  7,   4 },
+/* 166:    1, 2,       5,    7,  */  {  3,  6,  7,   6 },
+/*  58:    1,    3, 4, 5,        */  {  4,  5,  7,   3 },
+/* 154:    1,    3, 4,       7,  */  {  1,  5,  7,   0 },
+/* 106:    1,    3,    5, 6,     */  {  3,  5,  7,   2 },
+/* 202:    1,    3,       6, 7,  */  {  2,  5,  7,   1 },
+/* 210:    1,       4,    6, 7,  */  {  1,  2,  7,   9 },
+/*  92:       2, 3, 4,    6,     */  {  4,  6,  7,   7 },
+/* 172:       2, 3,    5,    7,  */  {  6,  2,  7,   5 },
+/* 180:       2,    4, 5,    7,  */  {  2,  3,  7,  10 },
+/* 120:          3, 4, 5, 6,     */  {  3,  4,  7,  11 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 12.1.1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling12_1_1[24][12] = {
+/* 135: 0, 1, 2,             7,  */  {  7,  6, 11, 10,  3,  2,  3, 10,  8,  9,  8, 10 },
+/*  75: 0, 1,    3,       6,     */  {  6,  5, 10,  9,  2,  1,  2,  9, 11,  8, 11,  9 },
+/*  83: 0, 1,       4,    6,     */  { 10,  6,  5,  7,  9,  4,  9,  7,  1,  3,  1,  7 },
+/* 163: 0, 1,          5,    7,  */  {  7,  6, 11,  4,  8,  5,  3,  5,  8,  5,  3,  1 },
+/*  45: 0,    2, 3,    5,        */  {  5,  4,  9,  8,  1,  0,  1,  8, 10, 11, 10,  8 },
+/*  53: 0,    2,    4, 5,        */  {  1,  2, 10,  0,  9,  3,  5,  3,  9,  3,  5,  7 },
+/* 149: 0,    2,    4,       7,  */  { 10,  1,  2,  0, 11,  3, 11,  0,  6,  4,  6,  0 },
+/* 101: 0,    2,       5, 6,     */  {  8,  3,  0,  2,  9,  1,  9,  2,  4,  6,  4,  2 },
+/* 197: 0,    2,          6, 7,  */  {  3,  0,  8,  2, 11,  1,  7,  1, 11,  1,  7,  5 },
+/*  89: 0,       3, 4,    6,     */  {  6,  5, 10,  7, 11,  4,  2,  4, 11,  4,  2,  0 },
+/* 169: 0,       3,    5,    7,  */  {  9,  5,  4,  6,  8,  7,  8,  6,  0,  2,  0,  6 },
+/* 225: 0,             5, 6, 7,  */  {  8,  3,  0,  7,  4, 11,  9, 11,  4, 11,  9, 10 },
+/*  30:    1, 2, 3, 4,           */  {  4,  7,  8, 11,  0,  3,  0, 11,  9, 10,  9, 11 },
+/*  86:    1, 2,    4,    6,     */  {  4,  7,  8,  5,  9,  6,  0,  6,  9,  6,  0,  2 },
+/* 166:    1, 2,       5,    7,  */  { 11,  7,  6,  4, 10,  5, 10,  4,  2,  0,  2,  4 },
+/*  58:    1,    3, 4, 5,        */  { 11,  2,  3,  1,  8,  0,  8,  1,  7,  5,  7,  1 },
+/* 154:    1,    3, 4,       7,  */  {  0,  1,  9,  3,  8,  2,  4,  2,  8,  2,  4,  6 },
+/* 106:    1,    3,    5, 6,     */  {  2,  3, 11,  1, 10,  0,  6,  0, 10,  0,  6,  4 },
+/* 202:    1,    3,       6, 7,  */  {  9,  0,  1,  3, 10,  2, 10,  3,  5,  7,  5,  3 },
+/* 210:    1,       4,    6, 7,  */  {  9,  0,  1,  4,  5,  8, 10,  8,  5,  8, 10, 11 },
+/*  92:       2, 3, 4,    6,     */  {  8,  4,  7,  5, 11,  6, 11,  5,  3,  1,  3,  5 },
+/* 172:       2, 3,    5,    7,  */  {  5,  4,  9,  6, 10,  7,  1,  7, 10,  7,  1,  3 },
+/* 180:       2,    4, 5,    7,  */  { 10,  1,  2,  5,  6,  9, 11,  9,  6,  9, 11,  8 },
+/* 120:          3, 4, 5, 6,     */  { 11,  2,  3,  6,  7, 10,  8, 10,  7, 10,  8,  9 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 12.1.1 inverted
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling12_1_1_[24][12] = {
+/* 135: 0, 1, 2,             7,  */  {  3,  2, 11, 10,  7,  6,  7, 10,  8,  9,  8, 10 },
+/*  75: 0, 1,    3,       6,     */  {  2,  1, 10,  9,  6,  5,  6,  9, 11,  8, 11,  9 },
+/*  83: 0, 1,       4,    6,     */  {  9,  4,  5,  7, 10,  6, 10,  7,  1,  3,  1,  7 },
+/* 163: 0, 1,          5,    7,  */  {  7,  4,  8,  6, 11,  5,  3,  5, 11,  5,  3,  1 },
+/*  45: 0,    2, 3,    5,        */  {  1,  0,  9,  8,  5,  4,  5,  8, 10, 11, 10,  8 },
+/*  53: 0,    2,    4, 5,        */  {  1,  0,  9,  2, 10,  3,  5,  3, 10,  3,  5,  7 },
+/* 149: 0,    2,    4,       7,  */  { 11,  3,  2,  0, 10,  1, 10,  0,  6,  4,  6,  0 },
+/* 101: 0,    2,       5, 6,     */  {  9,  1,  0,  2,  8,  3,  8,  2,  4,  6,  4,  2 },
+/* 197: 0,    2,          6, 7,  */  {  3,  2, 11,  0,  8,  1,  7,  1,  8,  1,  7,  5 },
+/*  89: 0,       3, 4,    6,     */  {  6,  7, 11,  5, 10,  4,  2,  4, 10,  4,  2,  0 },
+/* 169: 0,       3,    5,    7,  */  {  8,  7,  4,  6,  9,  5,  9,  6,  0,  2,  0,  6 },
+/* 225: 0,             5, 6, 7,  */  {  8,  7,  4,  3,  0, 11,  9, 11,  0, 11,  9, 10 },
+/*  30:    1, 2, 3, 4,           */  {  0,  3,  8, 11,  4,  7,  4, 11,  9, 10,  9, 11 },
+/*  86:    1, 2,    4,    6,     */  {  4,  5,  9,  7,  8,  6,  0,  6,  8,  6,  0,  2 },
+/* 166:    1, 2,       5,    7,  */  { 10,  5,  6,  4, 11,  7, 11,  4,  2,  0,  2,  4 },
+/*  58:    1,    3, 4, 5,        */  {  8,  0,  3,  1, 11,  2, 11,  1,  7,  5,  7,  1 },
+/* 154:    1,    3, 4,       7,  */  {  0,  3,  8,  1,  9,  2,  4,  2,  9,  2,  4,  6 },
+/* 106:    1,    3,    5, 6,     */  {  2,  1, 10,  3, 11,  0,  6,  0, 11,  0,  6,  4 },
+/* 202:    1,    3,       6, 7,  */  { 10,  2,  1,  3,  9,  0,  9,  3,  5,  7,  5,  3 },
+/* 210:    1,       4,    6, 7,  */  {  9,  4,  5,  0,  1,  8, 10,  8,  1,  8, 10, 11 },
+/*  92:       2, 3, 4,    6,     */  { 11,  6,  7,  5,  8,  4,  8,  5,  3,  1,  3,  5 },
+/* 172:       2, 3,    5,    7,  */  {  5,  6, 10,  4,  9,  7,  1,  7,  9,  7,  1,  3 },
+/* 180:       2,    4, 5,    7,  */  { 10,  5,  6,  1,  2,  9, 11,  9,  2,  9, 11,  8 },
+/* 120:          3, 4, 5, 6,     */  { 11,  6,  7,  2,  3, 10,  8, 10,  3, 10,  8,  9 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 12.1.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling12_1_2[24][24] = {
+/* 135: 0, 1, 2,             7,  */  {  7,  3, 11,  3,  7,  8,  9,  8,  7,  6,  9,  7,  9,  6, 10,  2, 10,  6, 11,  2,  6,  2, 11,  3 },
+/*  75: 0, 1,    3,       6,     */  {  6,  2, 10,  2,  6, 11,  8, 11,  6,  5,  8,  6,  8,  5,  9,  1,  9,  5, 10,  1,  5,  1, 10,  2 },
+/*  83: 0, 1,       4,    6,     */  { 10,  9,  5,  9, 10,  1,  3,  1, 10,  6,  3, 10,  3,  6,  7,  4,  7,  6,  5,  4,  6,  4,  5,  9 },
+/* 163: 0, 1,          5,    7,  */  {  7,  8, 11,  3, 11,  8, 11,  3,  1, 11,  1,  6,  5,  6,  1,  6,  5,  4,  6,  4,  7,  8,  7,  4 },
+/*  45: 0,    2, 3,    5,        */  {  5,  1,  9,  1,  5, 10, 11, 10,  5,  4, 11,  5, 11,  4,  8,  0,  8,  4,  9,  0,  4,  0,  9,  1 },
+/*  53: 0,    2,    4, 5,        */  {  1,  9, 10,  5, 10,  9, 10,  5,  7, 10,  7,  2,  3,  2,  7,  2,  3,  0,  2,  0,  1,  9,  1,  0 },
+/* 149: 0,    2,    4,       7,  */  { 10, 11,  2, 11, 10,  6,  4,  6, 10,  1,  4, 10,  4,  1,  0,  3,  0,  1,  2,  3,  1,  3,  2, 11 },
+/* 101: 0,    2,       5, 6,     */  {  8,  9,  0,  9,  8,  4,  6,  4,  8,  3,  6,  8,  6,  3,  2,  1,  2,  3,  0,  1,  3,  1,  0,  9 },
+/* 197: 0,    2,          6, 7,  */  {  3, 11,  8,  7,  8, 11,  8,  7,  5,  8,  5,  0,  1,  0,  5,  0,  1,  2,  0,  2,  3, 11,  3,  2 },
+/*  89: 0,       3, 4,    6,     */  {  6, 11, 10,  2, 10, 11, 10,  2,  0, 10,  0,  5,  4,  5,  0,  5,  4,  7,  5,  7,  6, 11,  6,  7 },
+/* 169: 0,       3,    5,    7,  */  {  9,  8,  4,  8,  9,  0,  2,  0,  9,  5,  2,  9,  2,  5,  6,  7,  6,  5,  4,  7,  5,  7,  4,  8 },
+/* 225: 0,             5, 6, 7,  */  {  8,  4,  0,  9,  0,  4,  0,  9, 10,  0, 10,  3, 11,  3, 10,  3, 11,  7,  3,  7,  8,  4,  8,  7 },
+/*  30:    1, 2, 3, 4,           */  {  4,  0,  8,  0,  4,  9, 10,  9,  4,  7, 10,  4, 10,  7, 11,  3, 11,  7,  8,  3,  7,  3,  8,  0 },
+/*  86:    1, 2,    4,    6,     */  {  4,  9,  8,  0,  8,  9,  8,  0,  2,  8,  2,  7,  6,  7,  2,  7,  6,  5,  7,  5,  4,  9,  4,  5 },
+/* 166:    1, 2,       5,    7,  */  { 11, 10,  6, 10, 11,  2,  0,  2, 11,  7,  0, 11,  0,  7,  4,  5,  4,  7,  6,  5,  7,  5,  6, 10 },
+/*  58:    1,    3, 4, 5,        */  { 11,  8,  3,  8, 11,  7,  5,  7, 11,  2,  5, 11,  5,  2,  1,  0,  1,  2,  3,  0,  2,  0,  3,  8 },
+/* 154:    1,    3, 4,       7,  */  {  0,  8,  9,  4,  9,  8,  9,  4,  6,  9,  6,  1,  2,  1,  6,  1,  2,  3,  1,  3,  0,  8,  0,  3 },
+/* 106:    1,    3,    5, 6,     */  {  2, 10, 11,  6, 11, 10, 11,  6,  4, 11,  4,  3,  0,  3,  4,  3,  0,  1,  3,  1,  2, 10,  2,  1 },
+/* 202:    1,    3,       6, 7,  */  {  9, 10,  1, 10,  9,  5,  7,  5,  9,  0,  7,  9,  7,  0,  3,  2,  3,  0,  1,  2,  0,  2,  1, 10 },
+/* 210:    1,       4,    6, 7,  */  {  9,  5,  1, 10,  1,  5,  1, 10, 11,  1, 11,  0,  8,  0, 11,  0,  8,  4,  0,  4,  9,  5,  9,  4 },
+/*  92:       2, 3, 4,    6,     */  {  8, 11,  7, 11,  8,  3,  1,  3,  8,  4,  1,  8,  1,  4,  5,  6,  5,  4,  7,  6,  4,  6,  7, 11 },
+/* 172:       2, 3,    5,    7,  */  {  5, 10,  9,  1,  9, 10,  9,  1,  3,  9,  3,  4,  7,  4,  3,  4,  7,  6,  4,  6,  5, 10,  5,  6 },
+/* 180:       2,    4, 5,    7,  */  { 10,  6,  2, 11,  2,  6,  2, 11,  8,  2,  8,  1,  9,  1,  8,  1,  9,  5,  1,  5, 10,  6, 10,  5 },
+/* 120:          3, 4, 5, 6,     */  { 11,  7,  3,  8,  3,  7,  3,  8,  9,  3,  9,  2, 10,  2,  9,  2, 10,  6,  2,  6, 11,  7, 11,  6 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 12.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling12_2[24][24] = {
+/* 135: 0, 1, 2,             7,  */  {   9,  8, 12, 10,  9, 12,  2, 10, 12,  3,  2, 12, 11,  3, 12,  6, 11, 12,  7,  6, 12,  8,  7, 12 },
+/*  75: 0, 1,    3,       6,     */  {   8, 11, 12,  9,  8, 12,  1,  9, 12,  2,  1, 12, 10,  2, 12,  5, 10, 12,  6,  5, 12, 11,  6, 12 },
+/*  83: 0, 1,       4,    6,     */  {   3,  1, 12,  7,  3, 12,  4,  7, 12,  9,  4, 12,  5,  9, 12,  6,  5, 12, 10,  6, 12,  1, 10, 12 },
+/* 163: 0, 1,          5,    7,  */  {  12,  3,  1, 12,  1,  5, 12,  5,  6, 12,  6, 11, 12, 11,  7, 12,  7,  4, 12,  4,  8, 12,  8,  3 },
+/*  45: 0,    2, 3,    5,        */  {  11, 10, 12,  8, 11, 12,  0,  8, 12,  1,  0, 12,  9,  1, 12,  4,  9, 12,  5,  4, 12, 10,  5, 12 },
+/*  53: 0,    2,    4, 5,        */  {  12,  5,  7, 12,  7,  3, 12,  3,  2, 12,  2, 10, 12, 10,  1, 12,  1,  0, 12,  0,  9, 12,  9,  5 },
+/* 149: 0,    2,    4,       7,  */  {   4,  6, 12,  0,  4, 12,  1,  0, 12, 10,  1, 12,  2, 10, 12,  3,  2, 12, 11,  3, 12,  6, 11, 12 },
+/* 101: 0,    2,       5, 6,     */  {   6,  4, 12,  2,  6, 12,  3,  2, 12,  8,  3, 12,  0,  8, 12,  1,  0, 12,  9,  1, 12,  4,  9, 12 },
+/* 197: 0,    2,          6, 7,  */  {  12,  7,  5, 12,  5,  1, 12,  1,  0, 12,  0,  8, 12,  8,  3, 12,  3,  2, 12,  2, 11, 12, 11,  7 },
+/*  89: 0,       3, 4,    6,     */  {  12,  2,  0, 12,  0,  4, 12,  4,  5, 12,  5, 10, 12, 10,  6, 12,  6,  7, 12,  7, 11, 12, 11,  2 },
+/* 169: 0,       3,    5,    7,  */  {   2,  0, 12,  6,  2, 12,  7,  6, 12,  8,  7, 12,  4,  8, 12,  5,  4, 12,  9,  5, 12,  0,  9, 12 },
+/* 225: 0,             5, 6, 7,  */  {  12,  9, 10, 12, 10, 11, 12, 11,  7, 12,  7,  4, 12,  4,  8, 12,  8,  3, 12,  3,  0, 12,  0,  9 },
+/*  30:    1, 2, 3, 4,           */  {  10,  9, 12, 11, 10, 12,  7, 11, 12,  4,  7, 12,  8,  4, 12,  3,  8, 12,  0,  3, 12,  9,  0, 12 },
+/*  86:    1, 2,    4,    6,     */  {  12,  0,  2, 12,  2,  6, 12,  6,  7, 12,  7,  8, 12,  8,  4, 12,  4,  5, 12,  5,  9, 12,  9,  0 },
+/* 166:    1, 2,       5,    7,  */  {   0,  2, 12,  4,  0, 12,  5,  4, 12, 10,  5, 12,  6, 10, 12,  7,  6, 12, 11,  7, 12,  2, 11, 12 },
+/*  58:    1,    3, 4, 5,        */  {   5,  7, 12,  1,  5, 12,  0,  1, 12,  8,  0, 12,  3,  8, 12,  2,  3, 12, 11,  2, 12,  7, 11, 12 },
+/* 154:    1,    3, 4,       7,  */  {  12,  4,  6, 12,  6,  2, 12,  2,  3, 12,  3,  8, 12,  8,  0, 12,  0,  1, 12,  1,  9, 12,  9,  4 },
+/* 106:    1,    3,    5, 6,     */  {  12,  6,  4, 12,  4,  0, 12,  0,  1, 12,  1, 10, 12, 10,  2, 12,  2,  3, 12,  3, 11, 12, 11,  6 },
+/* 202:    1,    3,       6, 7,  */  {   7,  5, 12,  3,  7, 12,  2,  3, 12, 10,  2, 12,  1, 10, 12,  0,  1, 12,  9,  0, 12,  5,  9, 12 },
+/* 210:    1,       4,    6, 7,  */  {  12, 10, 11, 12, 11,  8, 12,  8,  0, 12,  0,  1, 12,  1,  9, 12,  9,  4, 12,  4,  5, 12,  5, 10 },
+/*  92:       2, 3, 4,    6,     */  {   1,  3, 12,  5,  1, 12,  6,  5, 12, 11,  6, 12,  7, 11, 12,  4,  7, 12,  8,  4, 12,  3,  8, 12 },
+/* 172:       2, 3,    5,    7,  */  {  12,  1,  3, 12,  3,  7, 12,  7,  4, 12,  4,  9, 12,  9,  5, 12,  5,  6, 12,  6, 10, 12, 10,  1 },
+/* 180:       2,    4, 5,    7,  */  {  12, 11,  8, 12,  8,  9, 12,  9,  1, 12,  1,  2, 12,  2, 10, 12, 10,  5, 12,  5,  6, 12,  6, 11 },
+/* 120:          3, 4, 5, 6,     */  {  12,  8,  9, 12,  9, 10, 12, 10,  2, 12,  2,  3, 12,  3, 11, 12, 11,  6, 12,  6,  7, 12,  7,  8 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 12.2 inverted
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling12_2_[24][24] = {
+/* 135: 0, 1, 2,             7,  */  { 12,  2, 11, 12, 11,  7, 12,  7,  6, 12,  6, 10, 12, 10,  9, 12,  9,  8, 12,  8,  3, 12,  3,  2 },
+/*  75: 0, 1,    3,       6,     */  { 12,  1, 10, 12, 10,  6, 12,  6,  5, 12,  5,  9, 12,  9,  8, 12,  8, 11, 12, 11,  2, 12,  2,  1 },
+/*  83: 0, 1,       4,    6,     */  { 12,  4,  5, 12,  5, 10, 12, 10,  6, 12,  6,  7, 12,  7,  3, 12,  3,  1, 12,  1,  9, 12,  9,  4 },
+/* 163: 0, 1,          5,    7,  */  {  7,  6, 12,  8,  7, 12,  4,  8, 12,  5,  4, 12,  1,  5, 12,  3,  1, 12, 11,  3, 12,  6, 11, 12 },
+/*  45: 0,    2, 3,    5,        */  { 12,  0,  9, 12,  9,  5, 12,  5,  4, 12,  4,  8, 12,  8, 11, 12, 11, 10, 12, 10,  1, 12,  1,  0 },
+/*  53: 0,    2,    4, 5,        */  {  1,  2, 12,  9,  1, 12,  0,  9, 12,  3,  0, 12,  7,  3, 12,  5,  7, 12, 10,  5, 12,  2, 10, 12 },
+/* 149: 0,    2,    4,       7,  */  { 12,  1,  2, 12,  2, 11, 12, 11,  3, 12,  3,  0, 12,  0,  4, 12,  4,  6, 12,  6, 10, 12, 10,  1 },
+/* 101: 0,    2,       5, 6,     */  { 12,  3,  0, 12,  0,  9, 12,  9,  1, 12,  1,  2, 12,  2,  6, 12,  6,  4, 12,  4,  8, 12,  8,  3 },
+/* 197: 0,    2,          6, 7,  */  {  3,  0, 12, 11,  3, 12,  2, 11, 12,  1,  2, 12,  5,  1, 12,  7,  5, 12,  8,  7, 12,  0,  8, 12 },
+/*  89: 0,       3, 4,    6,     */  {  6,  5, 12, 11,  6, 12,  7, 11, 12,  4,  7, 12,  0,  4, 12,  2,  0, 12, 10,  2, 12,  5, 10, 12 },
+/* 169: 0,       3,    5,    7,  */  { 12,  7,  4, 12,  4,  9, 12,  9,  5, 12,  5,  6, 12,  6,  2, 12,  2,  0, 12,  0,  8, 12,  8,  7 },
+/* 225: 0,             5, 6, 7,  */  {  8,  7, 12,  0,  8, 12,  3,  0, 12, 11,  3, 12, 10, 11, 12,  9, 10, 12,  4,  9, 12,  7,  4, 12 },
+/*  30:    1, 2, 3, 4,           */  { 12,  7,  8, 12,  8,  0, 12,  0,  3, 12,  3, 11, 12, 11, 10, 12, 10,  9, 12,  9,  4, 12,  4,  7 },
+/*  86:    1, 2,    4,    6,     */  {  4,  7, 12,  9,  4, 12,  5,  9, 12,  6,  5, 12,  2,  6, 12,  0,  2, 12,  8,  0, 12,  7,  8, 12 },
+/* 166:    1, 2,       5,    7,  */  { 12,  5,  6, 12,  6, 11, 12, 11,  7, 12,  7,  4, 12,  4,  0, 12,  0,  2, 12,  2, 10, 12, 10,  5 },
+/*  58:    1,    3, 4, 5,        */  { 12,  0,  3, 12,  3, 11, 12, 11,  2, 12,  2,  1, 12,  1,  5, 12,  5,  7, 12,  7,  8, 12,  8,  0 },
+/* 154:    1,    3, 4,       7,  */  {  0,  3, 12,  9,  0, 12,  1,  9, 12,  2,  1, 12,  6,  2, 12,  4,  6, 12,  8,  4, 12,  3,  8, 12 },
+/* 106:    1,    3,    5, 6,     */  {  2,  1, 12, 11,  2, 12,  3, 11, 12,  0,  3, 12,  4,  0, 12,  6,  4, 12, 10,  6, 12,  1, 10, 12 },
+/* 202:    1,    3,       6, 7,  */  { 12,  2,  1, 12,  1,  9, 12,  9,  0, 12,  0,  3, 12,  3,  7, 12,  7,  5, 12,  5, 10, 12, 10,  2 },
+/* 210:    1,       4,    6, 7,  */  {  9,  0, 12,  5,  9, 12,  4,  5, 12,  8,  4, 12, 11,  8, 12, 10, 11, 12,  1, 10, 12,  0,  1, 12 },
+/*  92:       2, 3, 4,    6,     */  { 12,  6,  7, 12,  7,  8, 12,  8,  4, 12,  4,  5, 12,  5,  1, 12,  1,  3, 12,  3, 11, 12, 11,  6 },
+/* 172:       2, 3,    5,    7,  */  {  5,  4, 12, 10,  5, 12,  6, 10, 12,  7,  6, 12,  3,  7, 12,  1,  3, 12,  9,  1, 12,  4,  9, 12 },
+/* 180:       2,    4, 5,    7,  */  { 10,  1, 12,  6, 10, 12,  5,  6, 12,  9,  5, 12,  8,  9, 12, 11,  8, 12,  2, 11, 12,  1,  2, 12 },
+/* 120:          3, 4, 5, 6,     */  { 11,  2, 12,  7, 11, 12,  6,  7, 12, 10,  6, 12,  9, 10, 12,  8,  9, 12,  3,  8, 12,  2,  3, 12 }
+};
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+/**
+ * \brief test table for case 13
+ * All faces are to be tested
+ *
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13: face test */
+static const char test13[2][7] = {
+/* 165: 0,    2,       5,    7,  */  { 1,2,3,4,5,6,7 },
+/*  90:    1,    3, 4,    6,     */  { 2,3,4,1,5,6,7 },
+};
+
+
+
+//_____________________________________________________________________________
+/**
+ * \brief subconfiguration table for case 13
+ * Hard-coded tests for the subconfiguration determination
+ *
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13: sub configs */
+static const char subconfig13[64] = {
+/*  0: 0,0,0,0,0,0 */   0,
+/*  1: 1,0,0,0,0,0 */   1,
+/*  2: 0,1,0,0,0,0 */   2,
+/*  3: 1,1,0,0,0,0 */   7,
+/*  4: 0,0,1,0,0,0 */   3,
+/*  5: 1,0,1,0,0,0 */  -1,
+/*  6: 0,1,1,0,0,0 */  11,
+/*  7: 1,1,1,0,0,0 */  -1,
+/*  8: 0,0,0,1,0,0 */   4,
+/*  9: 1,0,0,1,0,0 */   8,
+/* 10: 0,1,0,1,0,0 */  -1,
+/* 11: 1,1,0,1,0,0 */  -1,
+/* 12: 0,0,1,1,0,0 */  14,
+/* 13: 1,0,1,1,0,0 */  -1,
+/* 14: 0,1,1,1,0,0 */  -1,
+/* 15: 1,1,1,1,0,0 */  -1,
+/* 16: 0,0,0,0,1,0 */   5,
+/* 17: 1,0,0,0,1,0 */   9,
+/* 18: 0,1,0,0,1,0 */  12,
+/* 19: 1,1,0,0,1,0 */  23,
+/* 20: 0,0,1,0,1,0 */  15,
+/* 21: 1,0,1,0,1,0 */  -1,
+/* 22: 0,1,1,0,1,0 */  21,
+/* 23: 1,1,1,0,1,0 */  38,
+/* 24: 0,0,0,1,1,0 */  17,
+/* 25: 1,0,0,1,1,0 */  20,
+/* 26: 0,1,0,1,1,0 */  -1,
+/* 27: 1,1,0,1,1,0 */  36,
+/* 28: 0,0,1,1,1,0 */  26,
+/* 29: 1,0,1,1,1,0 */  33,
+/* 30: 0,1,1,1,1,0 */  30,
+/* 31: 1,1,1,1,1,0 */  44,
+/* 32: 0,0,0,0,0,1 */   6,
+/* 33: 1,0,0,0,0,1 */  10,
+/* 34: 0,1,0,0,0,1 */  13,
+/* 35: 1,1,0,0,0,1 */  19,
+/* 36: 0,0,1,0,0,1 */  16,
+/* 37: 1,0,1,0,0,1 */  -1,
+/* 38: 0,1,1,0,0,1 */  25,
+/* 39: 1,1,1,0,0,1 */  37,
+/* 40: 0,0,0,1,0,1 */  18,
+/* 41: 1,0,0,1,0,1 */  24,
+/* 42: 0,1,0,1,0,1 */  -1,
+/* 43: 1,1,0,1,0,1 */  35,
+/* 44: 0,0,1,1,0,1 */  22,
+/* 45: 1,0,1,1,0,1 */  32,
+/* 46: 0,1,1,1,0,1 */  29,
+/* 47: 1,1,1,1,0,1 */  43,
+/* 48: 0,0,0,0,1,1 */  -1,
+/* 49: 1,0,0,0,1,1 */  -1,
+/* 50: 0,1,0,0,1,1 */  -1,
+/* 51: 1,1,0,0,1,1 */  34,
+/* 52: 0,0,1,0,1,1 */  -1,
+/* 53: 1,0,1,0,1,1 */  -1,
+/* 54: 0,1,1,0,1,1 */  28,
+/* 55: 1,1,1,0,1,1 */  42,
+/* 56: 0,0,0,1,1,1 */  -1,
+/* 57: 1,0,0,1,1,1 */  31,
+/* 58: 0,1,0,1,1,1 */  -1,
+/* 59: 1,1,0,1,1,1 */  41,
+/* 60: 0,0,1,1,1,1 */  27,
+/* 61: 1,0,1,1,1,1 */  40,
+/* 62: 0,1,1,1,1,1 */  39,
+/* 63: 1,1,1,1,1,1 */  45,
+};
+
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.1
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.1 */
+static const char tiling13_1[2][12] = {
+/* 165: 0,    2,       5,    7,  */  { 11,  7,  6,  1,  2, 10,  8,  3,  0,  9,  5, 4 },
+/*  90:    1,    3, 4,    6,     */  {  8,  4,  7,  2,  3, 11,  9,  0,  1, 10,  6, 5 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.1 inverted
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.1 */
+static const char tiling13_1_[2][12] = {
+/* 165: 0,    2,       5,    7,  */  { 7,  4,  8, 11,  3,  2,  1,  0,  9,  5,  6, 10 },
+/*  90:    1,    3, 4,    6,     */  { 6,  7, 11, 10,  2,  1,  0,  3,  8,  4,  5,  9 }
+};
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.2 */
+static const char tiling13_2[2][6][18] = {
+/* 165: 0,    2,       5,    7,  */  {
+ /* 1 */ { 1,  2, 10, 11,  7,  6,  3,  4,  8,  4,  3,  5,  0,  5,  3,  5,  0,  9 },
+ /* 2 */ { 8,  3,  0, 11,  7,  6,  9,  1,  4,  2,  4,  1,  4,  2,  5, 10,  5,  2 },
+ /* 3 */ { 9,  5,  4,  8,  3,  0,  1,  6, 10,  6,  1,  7,  2,  7,  1,  7,  2, 11 },
+ /* 4 */ { 9,  5,  4,  1,  2, 10, 11,  3,  6,  0,  6,  3,  6,  0,  7,  8,  7,  0 },
+ /* 5 */ { 9,  5,  4, 11,  7,  6,  0, 10,  1, 10,  0,  8, 10,  8,  2,  3,  2,  8 },
+ /* 6 */ { 1,  2, 10,  3,  0,  8,  4,  9,  7, 11,  7,  9,  5, 11,  9, 11,  5,  6 }
+},
+/*  90:    1,    3, 4,    6,     */  {
+ /* 1 */ { 2,  3, 11,  8,  4,  7,  0,  5,  9,  5,  0,  6,  1,  6,  0,  6,  1, 10 },
+ /* 2 */ { 9,  0,  1,  8,  4,  7, 10,  2,  5,  3,  5,  2,  5,  3,  6, 11,  6,  3 },
+ /* 3 */ { 6,  5, 10,  9,  0,  1,  2,  7, 11,  7,  2,  4,  3,  4,  2,  4,  3,  8 },
+ /* 4 */ { 6,  5, 10,  2,  3, 11,  8,  0,  7,  1,  7,  0,  7,  1,  4,  9,  4,  1 },
+ /* 5 */ { 6,  5, 10,  8,  4,  7,  1, 11,  2, 11,  1,  9, 11,  9,  3,  0,  3,  9 },
+ /* 6 */ { 2,  3, 11,  0,  1,  9,  5, 10,  4,  8,  4, 10,  6,  8, 10,  8,  6,  7 }
+} };
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.2 inverted
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.2 */
+static const char tiling13_2_[2][6][18] = {
+/* 165: 0,    2,       5,    7,  */  {
+ /* 1 */ { 10,  5,  6, 11,  3,  2,  7,  0,  8,  0,  7,  1,  4,  1,  7,  1,  4,  9 },
+ /* 2 */ { 11,  3,  2,  7,  4,  8,  9,  5,  0,  6,  0,  5,  0,  6,  1, 10,  1,  6 },
+ /* 3 */ {  1,  0,  9,  7,  4,  8,  5,  2, 10,  2,  5,  3,  6,  3,  5,  3,  6, 11 },
+ /* 4 */ { 10,  5,  6,  1,  0,  9, 11,  7,  2,  4,  2,  7,  2,  4,  3,  8,  3,  4 },
+ /* 5 */ { 10,  5,  6,  7,  4,  8,  2, 11,  1,  9,  1, 11,  3,  9, 11,  9,  3,  0 },
+ /* 6 */ { 11,  3,  2,  9,  1,  0,  4, 10,  5, 10,  4,  8, 10,  8,  6,  7,  6,  8 }
+},
+/*  90:    1,    3, 4,    6,     */  {
+ /* 1 */ {  6,  7, 11,  8,  0,  3,  4,  1,  9,  1,  4,  2,  5,  2,  4,  2,  5, 10 },
+ /* 2 */ {  8,  0,  3,  4,  5,  9, 10,  6,  1,  7,  1,  6,  1,  7,  2, 11,  2,  7 },
+ /* 3 */ {  2,  1, 10,  4,  5,  9,  6,  3, 11,  3,  6,  0,  7,  0,  6,  0,  7,  8 },
+ /* 4 */ {  6,  7, 11,  2,  1, 10,  8,  4,  3,  5,  3,  4,  3,  5,  0,  9,  0,  5 },
+ /* 5 */ {  6,  7, 11,  4,  5,  9,  3,  8,  2, 10,  2,  8,  0, 10,  8, 10,  0,  1 },
+ /* 6 */ {  8,  0,  3, 10,  2,  1,  5, 11,  6, 11,  5,  9, 11,  9,  7,  4,  7,  9 }
+} };
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.3
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.3 */
+static const char tiling13_3[2][12][30] = {
+/* 165: 0,    2,       5,    7,  */  {
+ /* 1,2 */ { 11,  7,  6, 12,  2, 10, 12, 10,  5, 12,  5,  4, 12,  4,  8, 12,  8,  3, 12,  3,  0, 12,  0,  9, 12,  9,  1, 12,  1,  2 },
+ /* 1,4 */ {  1,  2, 10,  9,  5, 12,  0,  9, 12,  3,  0, 12, 11,  3, 12,  6, 11, 12,  7,  6, 12,  8,  7, 12,  4,  8, 12,  5,  4, 12 },
+ /* 1,5 */ { 11,  7,  6, 12,  5,  4, 12,  4,  8, 12,  8,  3, 12,  3,  2, 12,  2, 10, 12, 10,  1, 12,  1,  0, 12,  0,  9, 12,  9,  5 },
+ /* 1,6 */ {  1,  2, 10, 12,  3,  0, 12,  0,  9, 12,  9,  5, 12,  5,  6, 12,  6, 11, 12, 11,  7, 12,  7,  4, 12,  4,  8, 12,  8,  3 },
+ /* 2,3 */ {  8,  3,  0, 11,  7, 12,  2, 11, 12,  1,  2, 12,  9,  1, 12,  4,  9, 12,  5,  4, 12, 10,  5, 12,  6, 10, 12,  7,  6, 12 },
+ /* 2,5 */ { 11,  7,  6,  5,  4, 12, 10,  5, 12,  2, 10, 12,  3,  2, 12,  8,  3, 12,  0,  8, 12,  1,  0, 12,  9,  1, 12,  4,  9, 12 },
+ /* 2,6 */ {  8,  3,  0,  1,  2, 12,  9,  1, 12,  4,  9, 12,  7,  4, 12, 11,  7, 12,  6, 11, 12,  5,  6, 12, 10,  5, 12,  2, 10, 12 },
+ /* 3,4 */ {  9,  5,  4, 12,  0,  8, 12,  8,  7, 12,  7,  6, 12,  6, 10, 12, 10,  1, 12,  1,  2, 12,  2, 11, 12, 11,  3, 12,  3,  0 },
+ /* 3,5 */ {  9,  5,  4, 12,  7,  6, 12,  6, 10, 12, 10,  1, 12,  1,  0, 12,  0,  8, 12,  8,  3, 12,  3,  2, 12,  2, 11, 12, 11,  7 },
+ /* 3,6 */ {  8,  3,  0, 12,  1,  2, 12,  2, 11, 12, 11,  7, 12,  7,  4, 12,  4,  9, 12,  9,  5, 12,  5,  6, 12,  6, 10, 12, 10,  1 },
+ /* 4,5 */ {  9,  5,  4,  7,  6, 12,  8,  7, 12,  0,  8, 12,  1,  0, 12, 10,  1, 12,  2, 10, 12,  3,  2, 12, 11,  3, 12,  6, 11, 12 },
+ /* 4,6 */ {  1,  2, 10,  3,  0, 12, 11,  3, 12,  6, 11, 12,  5,  6, 12,  9,  5, 12,  4,  9, 12,  7,  4, 12,  8,  7, 12,  0,  8, 12 }
+},
+/*  90:    1,    3, 4,    6,     */  {
+ /* 1,2 */ {  8,  4,  7, 12,  3, 11, 12, 11,  6, 12,  6,  5, 12,  5,  9, 12,  9,  0, 12,  0,  1, 12,  1, 10, 12, 10,  2, 12,  2,  3 },
+ /* 1,4 */ {  2,  3, 11, 10,  6, 12,  1, 10, 12,  0,  1, 12,  8,  0, 12,  7,  8, 12,  4,  7, 12,  9,  4, 12,  5,  9, 12,  6,  5, 12 },
+ /* 1,5 */ {  8,  4,  7, 12,  6,  5, 12,  5,  9, 12,  9,  0, 12,  0,  3, 12,  3, 11, 12, 11,  2, 12,  2,  1, 12,  1, 10, 12, 10,  6 },
+ /* 1,6 */ {  2,  3, 11, 12,  0,  1, 12,  1, 10, 12, 10,  6, 12,  6,  7, 12,  7,  8, 12,  8,  4, 12,  4,  5, 12,  5,  9, 12,  9,  0 },
+ /* 2,3 */ {  0,  1,  9,  8,  4, 12,  3,  8, 12,  2,  3, 12, 10,  2, 12,  5, 10, 12,  6,  5, 12, 11,  6, 12,  7, 11, 12,  4,  7, 12 },
+ /* 2,5 */ {  8,  4,  7,  6,  5, 12, 11,  6, 12,  3, 11, 12,  0,  3, 12,  9,  0, 12,  1,  9, 12,  2,  1, 12, 10,  2, 12,  5, 10, 12 },
+ /* 2,6 */ {  9,  0,  1,  2,  3, 12, 10,  2, 12,  5, 10, 12,  4,  5, 12,  8,  4, 12,  7,  8, 12,  6,  7, 12, 11,  6, 12,  3, 11, 12 },
+ /* 3,4 */ {  6,  5, 10, 12,  1,  9, 12,  9,  4, 12,  4,  7, 12,  7, 11, 12, 11,  2, 12,  2,  3, 12,  3,  8, 12,  8,  0, 12,  0,  1 },
+ /* 3,5 */ {  6,  5, 10, 12,  4,  7, 12,  7, 11, 12, 11,  2, 12,  2,  1, 12,  1,  9, 12,  9,  0, 12,  0,  3, 12,  3,  8, 12,  8,  4 },
+ /* 3,6 */ {  9,  0,  1, 12,  2,  3, 12,  3,  8, 12,  8,  4, 12,  4,  5, 12,  5, 10, 12, 10,  6, 12,  6,  7, 12,  7, 11, 12, 11,  2 },
+ /* 4,5 */ {  6,  5, 10,  4,  7, 12,  9,  4, 12,  1,  9, 12,  2,  1, 12, 11,  2, 12,  3, 11, 12,  0,  3, 12,  8,  0, 12,  7,  8, 12 },
+ /* 4,6 */ {  2,  3, 11,  0,  1, 12,  8,  0, 12,  7,  8, 12,  6,  7, 12, 10,  6, 12,  5, 10, 12,  4,  5, 12,  9,  4, 12,  1,  9, 12 }
+} };
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.3, inverted
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.3 */
+static const char tiling13_3_[2][12][30] = {
+/* 165: 0,    2,       5,    7,  */  {
+ /* 1,2 */ {  3,  2, 11,  8,  7, 12,  0,  8, 12,  1,  0, 12, 10,  1, 12,  6, 10, 12,  5,  6, 12,  9,  5, 12,  4,  9, 12,  7,  4, 12 },
+ /* 1,4 */ {  5,  6, 10, 12,  2, 11, 12, 11,  7, 12,  7,  4, 12,  4,  9, 12,  9,  1, 12,  1,  0, 12,  0,  8, 12,  8,  3, 12,  3,  2 },
+ /* 1,5 */ { 10,  5,  6, 12,  7,  4, 12,  4,  9, 12,  9,  1, 12,  1,  2, 12,  2, 11, 12, 11,  3, 12,  3,  0, 12,  0,  8, 12,  8,  7 },
+ /* 1,6 */ { 11,  3,  2, 12,  1,  0, 12,  0,  8, 12,  8,  7, 12,  7,  6, 12,  6, 10, 12, 10,  5, 12,  5,  4, 12,  4,  9, 12,  9,  1 },
+ /* 2,3 */ {  7,  4,  8, 11,  3, 12,  6, 11, 12,  5,  6, 12,  9,  5, 12,  0,  9, 12,  1,  0, 12, 10,  1, 12,  2, 10, 12,  3,  2, 12 },
+ /* 2,5 */ {  7,  4,  8,  5,  6, 12,  9,  5, 12,  0,  9, 12,  3,  0, 12, 11,  3, 12,  2, 11, 12,  1,  2, 12, 10,  1, 12,  6, 10, 12 },
+ /* 2,6 */ { 11,  3,  2,  1,  0, 12, 10,  1, 12,  6, 10, 12,  7,  6, 12,  8,  7, 12,  4,  8, 12,  5,  4, 12,  9,  5, 12,  0,  9, 12 },
+ /* 3,4 */ {  1,  0,  9, 12,  4,  8, 12,  8,  3, 12,  3,  2, 12,  2, 10, 12, 10,  5, 12,  5,  6, 12,  6, 11, 12, 11,  7, 12,  7,  4 },
+ /* 3,5 */ {  7,  4,  8, 12,  5,  6, 12,  6, 11, 12, 11,  3, 12,  3,  0, 12,  0,  9, 12,  9,  1, 12,  1,  2, 12,  2, 10, 12, 10,  5 },
+ /* 3,6 */ {  1,  0,  9, 12,  3,  2, 12,  2, 10, 12, 10,  5, 12,  5,  4, 12,  4,  8, 12,  8,  7, 12,  7,  6, 12,  6, 11, 12, 11,  3 },
+ /* 4,5 */ { 10,  5,  6,  7,  4, 12, 11,  7, 12,  2, 11, 12,  1,  2, 12,  9,  1, 12,  0,  9, 12,  3,  0, 12,  8,  3, 12,  4,  8, 12 },
+ /* 4,6 */ {  9,  1,  0,  3,  2, 12,  8,  3, 12,  4,  8, 12,  5,  4, 12, 10,  5, 12,  6, 10, 12,  7,  6, 12, 11,  7, 12,  2, 11, 12 }
+},
+/*  90:    1,    3, 4,    6,     */  {
+ /* 1,2 */ {  0,  3,  8,  9,  4, 12,  1,  9, 12,  2,  1, 12, 11,  2, 12,  7, 11, 12,  6,  7, 12, 10,  6, 12,  5, 10, 12,  4,  5, 12 },
+ /* 1,4 */ { 11,  6,  7, 12,  3,  8, 12,  8,  4, 12,  4,  5, 12,  5, 10, 12, 10,  2, 12,  2,  1, 12,  1,  9, 12,  9,  0, 12,  0,  3 },
+ /* 1,5 */ {  6,  7, 11, 12,  4,  5, 12,  5, 10, 12, 10,  2, 12,  2,  3, 12,  3,  8, 12,  8,  0, 12,  0,  1, 12,  1,  9, 12,  9,  4 },
+ /* 1,6 */ {  8,  0,  3, 12,  2,  1, 12,  1,  9, 12,  9,  4, 12,  4,  7, 12,  7, 11, 12, 11,  6, 12,  6,  5, 12,  5, 10, 12, 10,  2 },
+ /* 2,3 */ {  4,  5,  9,  8,  0, 12,  7,  8, 12,  6,  7, 12, 10,  6, 12,  1, 10, 12,  2,  1, 12, 11,  2, 12,  3, 11, 12,  0,  3, 12 },
+ /* 2,5 */ {  4,  5,  9,  6,  7, 12, 10,  6, 12,  1, 10, 12,  0,  1, 12,  8,  0, 12,  3,  8, 12,  2,  3, 12, 11,  2, 12,  7, 11, 12 },
+ /* 2,6 */ {  8,  0,  3,  2,  1, 12, 11,  2, 12,  7, 11, 12,  4,  7, 12,  9,  4, 12,  5,  9, 12,  6,  5, 12, 10,  6, 12,  1, 10, 12 },
+ /* 3,4 */ {  2,  1, 10, 12,  5,  9, 12,  9,  0, 12,  0,  3, 12,  3, 11, 12, 11,  6, 12,  6,  7, 12,  7,  8, 12,  8,  4, 12,  4,  5 },
+ /* 3,5 */ {  4,  5,  9, 12,  6,  7, 12,  7,  8, 12,  8,  0, 12,  0,  1, 12,  1, 10, 12, 10,  2, 12,  2,  3, 12,  3, 11, 12, 11,  6 },
+ /* 3,6 */ {  2,  1, 10, 12,  0,  3, 12,  3, 11, 12, 11,  6, 12,  6,  5, 12,  5,  9, 12,  9,  4, 12,  4,  7, 12,  7,  8, 12,  8,  0 },
+ /* 4,5 */ {  6,  7, 11,  4,  5, 12,  8,  4, 12,  3,  8, 12,  2,  3, 12, 10,  2, 12,  1, 10, 12,  0,  1, 12,  9,  0, 12,  5,  9, 12 },
+ /* 4,6 */ { 10,  2,  1,  0,  3, 12,  9,  0, 12,  5,  9, 12,  6,  5, 12, 11,  6, 12,  7, 11, 12,  4,  7, 12,  8,  4, 12,  3,  8, 12 }
+} };
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.4
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.4 */
+static const char tiling13_4[2][4][36] = {
+/* 165: 0,    2,       5,    7,  */  {
+/* 1,2,6 */  { 12,  2, 10, 12, 10,  5, 12,  5,  6, 12,  6, 11, 12, 11,  7, 12,  7,  4, 12,  4,  8, 12,  8,  3, 12,  3,  0, 12,  0,  9, 12,  9,  1, 12,  1,  2 },
+/* 1,4,5 */  { 11,  3, 12,  6, 11, 12,  7,  6, 12,  8,  7, 12,  4,  8, 12,  5,  4, 12,  9,  5, 12,  0,  9, 12,  1,  0, 12, 10,  1, 12,  2, 10, 12,  3,  2, 12 },
+/* 2,3,5 */  {  9,  1, 12,  4,  9, 12,  5,  4, 12, 10,  5, 12,  6, 10, 12,  7,  6, 12, 11,  7, 12,  2, 11, 12,  3,  2, 12,  8,  3, 12,  0,  8, 12,  1,  0, 12 },
+/* 3,4,6 */  { 12,  0,  8, 12,  8,  7, 12,  7,  4, 12,  4,  9, 12,  9,  5, 12,  5,  6, 12,  6, 10, 12, 10,  1, 12,  1,  2, 12,  2, 11, 12, 11,  3, 12,  3,  0 }
+},
+/*  90:    1,    3, 4,    6,     */  {
+/* 1,2,6 */  { 12,  3, 11, 12, 11,  6, 12,  6,  7, 12,  7,  8, 12,  8,  4, 12,  4,  5, 12,  5,  9, 12,  9,  0, 12,  0,  1, 12,  1, 10, 12, 10,  2, 12,  2,  3 },
+/* 1,4,5 */  {  8,  0, 12,  7,  8, 12,  4,  7, 12,  9,  4, 12,  5,  9, 12,  6,  5, 12, 10,  6, 12,  1, 10, 12,  2,  1, 12, 11,  2, 12,  3, 11, 12,  0,  3, 12 },
+/* 2,3,5 */  { 10,  2, 12,  5, 10, 12,  6,  5, 12, 11,  6, 12,  7, 11, 12,  4,  7, 12,  8,  4, 12,  3,  8, 12,  0,  3, 12,  9,  0, 12,  1,  9, 12,  2,  1, 12 },
+/* 3,4,6 */  { 12,  1,  9, 12,  9,  4, 12,  4,  5, 12,  5, 10, 12, 10,  6, 12,  6,  7, 12,  7, 11, 12, 11,  2, 12,  2,  3, 12,  3,  8, 12,  8,  0, 12,  0,  1 }
+} };
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.5.1
+ * The support edge for the interior test is marked as the 1st column.
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.5.1 */
+static const char tiling13_5_1[2][4][18] = {
+/* 165: 0,    2,       5,    7,  */  {
+/* 1,2,5 */  {  7,  6, 11,  1,  0,  9, 10,  3,  2,  3, 10,  5,  3,  5,  8,  4,  8, 5 },
+/* 1,4,6 */  {  1,  2, 10,  7,  4,  8,  3,  0, 11,  6, 11,  0,  9,  6,  0,  6,  9, 5 },
+/* 2,3,6 */  {  3,  0,  8,  5,  6, 10,  1,  2,  9,  4,  9,  2, 11,  4,  2,  4, 11, 7 },
+/* 3,4,5 */  {  5,  4,  9,  3,  2, 11,  8,  1,  0,  1,  8,  7,  1,  7, 10,  6, 10, 7 }
+},
+/*  90:    1,    3, 4,    6,     */  {
+/* 1,2,5 */  {  4,  7,  8,  2,  1, 10, 11,  0,  3,  0, 11,  6,  0,  6,  9,  5,  9, 6 },
+/* 1,4,6 */  {  2,  3, 11,  4,  5,  9,  0,  1,  8,  7,  8,  1, 10,  7,  1,  7, 10, 6 },
+/* 2,3,6 */  {  0,  1,  9,  6,  7, 11,  2,  3, 10,  5, 10,  3,  8,  5,  3,  5,  8, 4 },
+/* 3,4,5 */  {  6,  5, 10,  0,  3,  8,  9,  2,  1,  2,  9,  4,  2,  4, 11,  7, 11, 4 }
+} };
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 13.5.2
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+/* 13.5.2 */
+static const char tiling13_5_2[2][4][30] = {
+/* 165: 0,    2,       5,    7,  */  {
+/* 1,2,5 */  { 1,  0,  9,  7,  4,  8,  7,  8,  3,  7,  3, 11,  2, 11,  3, 11,  2, 10, 11, 10,  6,  5,  6, 10,  6,  5,  7,  4,  7, 5 },
+/* 1,4,6 */  { 7,  4,  8, 11,  3,  2,  6, 11,  2, 10,  6,  2,  6, 10,  5,  9,  5, 10,  1,  9, 10,  9,  1,  0,  2,  0,  1,  0,  2, 3 },
+/* 2,3,6 */  { 5,  6, 10,  9,  1,  0,  4,  9,  0,  8,  4,  0,  4,  8,  7, 11,  7,  8,  3, 11,  8, 11,  3,  2,  0,  2,  3,  2,  0, 1 },
+/* 3,4,5 */  { 3,  2, 11,  5,  6, 10,  5, 10,  1,  5,  1,  9,  0,  9,  1,  9,  0,  8,  9,  8,  4,  4,  8,  7,  4,  7,  5,  6,  5, 7 }
+},
+/*  90:    1,    3, 4,    6,     */  {
+/* 1,2,5 */  { 2,  1, 10,  4,  5,  9,  4,  9,  0,  4,  0,  8,  3,  8,  0,  8,  3, 11,  8, 11,  7,  6,  7, 11,  7,  6,  4,  5,  4, 6 },
+/* 1,4,6 */  { 4,  5,  9,  8,  0,  3,  7,  8,  3, 11,  7,  3,  7, 11,  6, 10,  6, 11,  2, 10, 11, 10,  2,  1,  3,  1,  2,  1,  3, 0 },
+/* 2,3,6 */  { 6,  7, 11, 10,  2,  1,  5, 10,  1,  9,  5,  1,  5,  9,  4,  8,  4,  9,  0,  8,  9,  8,  0,  3,  1,  3,  0,  3,  1, 2 },
+/* 3,4,5 */  { 0,  3,  8,  6,  7, 11,  6, 11,  2,  6,  2, 10,  1, 10,  2, 10,  1,  9, 10,  9,  5,  5,  9,  4,  5,  4,  6,  7,  6, 4 }
+} };
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+/**
+ * \brief tiling table for case 14
+ * For each of the case above, the specific triangulation of the edge
+ * intersection points is given.
+ * When a case is ambiguous, there is an auxiliary table that contains
+ * the face number to test and the tiling table contains the specific
+ * triangulations depending on the results
+ * A minus sign means to invert the result of the test.
+ */
+//-----------------------------------------------------------------------------
+static const char tiling14[12][12] = {
+/*  71: 0, 1, 2,          6,     */  {  5,  9,  8,  5,  8,  2,  5,  2,  6,  3,  2,  8 },
+/*  43: 0, 1,    3,    5,        */  {  2,  1,  5,  2,  5,  8,  2,  8, 11,  4,  8,  5 },
+/* 147: 0, 1,       4,       7,  */  {  9,  4,  6,  9,  6,  3,  9,  3,  1, 11,  3,  6 },
+/*  29: 0,    2, 3, 4,           */  {  1, 11, 10,  1,  4, 11,  1,  0,  4,  7, 11,  4 },
+/* 201: 0,       3,       6, 7,  */  {  8,  2,  0,  8,  5,  2,  8,  7,  5, 10,  2,  5 },
+/* 113: 0,          4, 5, 6,     */  {  0,  7,  3,  0, 10,  7,  0,  9, 10,  6,  7, 10 },
+/* 142:    1, 2, 3,          7,  */  {  0,  3,  7,  0,  7, 10,  0, 10,  9,  6, 10,  7 },
+/*  54:    1, 2,    4, 5,        */  {  8,  0,  2,  8,  2,  5,  8,  5,  7, 10,  5,  2 },
+/* 226:    1,          5, 6, 7,  */  {  1, 10, 11,  1, 11,  4,  1,  4,  0,  7,  4, 11 },
+/* 108:       2, 3,    5, 6,     */  {  9,  6,  4,  9,  3,  6,  9,  1,  3, 11,  6,  3 },
+/* 212:       2,    4,    6, 7,  */  {  2,  5,  1,  2,  8,  5,  2, 11,  8,  4,  5,  8 },
+/* 184:          3, 4, 5,    7,  */  {  5,  8,  9,  5,  2,  8,  5,  6,  2,  3,  8,  2 }
+};
+//_____________________________________________________________________________
+
+
+
+//_____________________________________________________________________________
+/**
+ * \brief original Marching Cubes implementation
+ * For each of the possible vertex states listed in this table there is a
+ * specific triangulation of the edge intersection points.  The table lists
+ * all of them in the form of 0-5 edge triples with the list terminated by
+ * the invalid value -1.  For example: casesClassic[3] list the 2 triangles
+ * formed when cube[0] and cube[1] are inside of the surface, but the rest of
+ * the cube is not.
+ */
+//-----------------------------------------------------------------------------
+static const char casesClassic[256][16] = {
+/*   0:                          */  { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*   1: 0,                       */  {  0,  8,  3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*   2:    1,                    */  {  0,  1,  9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*   3: 0, 1,                    */  {  1,  8,  3,  9,  8,  1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*   4:       2,                 */  {  1,  2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*   5: 0,    2,                 */  {  0,  8,  3,  1,  2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*   6:    1, 2,                 */  {  9,  2, 10,  0,  2,  9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*   7: 0, 1, 2,                 */  {  2,  8,  3,  2, 10,  8, 10,  9,  8, -1, -1, -1, -1, -1, -1, -1 },
+/*   8:          3,              */  {  3, 11,  2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*   9: 0,       3,              */  {  0, 11,  2,  8, 11,  0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  10:    1,    3,              */  {  1,  9,  0,  2,  3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  11: 0, 1,    3,              */  {  1, 11,  2,  1,  9, 11,  9,  8, 11, -1, -1, -1, -1, -1, -1, -1 },
+/*  12:       2, 3,              */  {  3, 10,  1, 11, 10,  3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  13: 0,    2, 3,              */  {  0, 10,  1,  0,  8, 10,  8, 11, 10, -1, -1, -1, -1, -1, -1, -1 },
+/*  14:    1, 2, 3,              */  {  3,  9,  0,  3, 11,  9, 11, 10,  9, -1, -1, -1, -1, -1, -1, -1 },
+/*  15: 0, 1, 2, 3,              */  {  9,  8, 10, 10,  8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  16:             4,           */  {  4,  7,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  17: 0,          4,           */  {  4,  3,  0,  7,  3,  4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  18:    1,       4,           */  {  0,  1,  9,  8,  4,  7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  19: 0, 1,       4,           */  {  4,  1,  9,  4,  7,  1,  7,  3,  1, -1, -1, -1, -1, -1, -1, -1 },
+/*  20:       2,    4,           */  {  1,  2, 10,  8,  4,  7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  21: 0,    2,    4,           */  {  3,  4,  7,  3,  0,  4,  1,  2, 10, -1, -1, -1, -1, -1, -1, -1 },
+/*  22:    1, 2,    4,           */  {  9,  2, 10,  9,  0,  2,  8,  4,  7, -1, -1, -1, -1, -1, -1, -1 },
+/*  23: 0, 1, 2,    4,           */  {  2, 10,  9,  2,  9,  7,  2,  7,  3,  7,  9,  4, -1, -1, -1, -1 },
+/*  24:          3, 4,           */  {  8,  4,  7,  3, 11,  2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  25: 0,       3, 4,           */  { 11,  4,  7, 11,  2,  4,  2,  0,  4, -1, -1, -1, -1, -1, -1, -1 },
+/*  26:    1,    3, 4,           */  {  9,  0,  1,  8,  4,  7,  2,  3, 11, -1, -1, -1, -1, -1, -1, -1 },
+/*  27: 0, 1,    3, 4,           */  {  4,  7, 11,  9,  4, 11,  9, 11,  2,  9,  2,  1, -1, -1, -1, -1 },
+/*  28:       2, 3, 4,           */  {  3, 10,  1,  3, 11, 10,  7,  8,  4, -1, -1, -1, -1, -1, -1, -1 },
+/*  29: 0,    2, 3, 4,           */  {  1, 11, 10,  1,  4, 11,  1,  0,  4,  7, 11,  4, -1, -1, -1, -1 },
+/*  30:    1, 2, 3, 4,           */  {  4,  7,  8,  9,  0, 11,  9, 11, 10, 11,  0,  3, -1, -1, -1, -1 },
+/*  31: 0, 1, 2, 3, 4,           */  {  4,  7, 11,  4, 11,  9,  9, 11, 10, -1, -1, -1, -1, -1, -1, -1 },
+/*  32:                5,        */  {  9,  5,  4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  33: 0,             5,        */  {  9,  5,  4,  0,  8,  3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  34:    1,          5,        */  {  0,  5,  4,  1,  5,  0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  35: 0, 1,          5,        */  {  8,  5,  4,  8,  3,  5,  3,  1,  5, -1, -1, -1, -1, -1, -1, -1 },
+/*  36:       2,       5,        */  {  1,  2, 10,  9,  5,  4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  37: 0,    2,       5,        */  {  3,  0,  8,  1,  2, 10,  4,  9,  5, -1, -1, -1, -1, -1, -1, -1 },
+/*  38:    1, 2,       5,        */  {  5,  2, 10,  5,  4,  2,  4,  0,  2, -1, -1, -1, -1, -1, -1, -1 },
+/*  39: 0, 1, 2,       5,        */  {  2, 10,  5,  3,  2,  5,  3,  5,  4,  3,  4,  8, -1, -1, -1, -1 },
+/*  40:          3,    5,        */  {  9,  5,  4,  2,  3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  41: 0,       3,    5,        */  {  0, 11,  2,  0,  8, 11,  4,  9,  5, -1, -1, -1, -1, -1, -1, -1 },
+/*  42:    1,    3,    5,        */  {  0,  5,  4,  0,  1,  5,  2,  3, 11, -1, -1, -1, -1, -1, -1, -1 },
+/*  43: 0, 1,    3,    5,        */  {  2,  1,  5,  2,  5,  8,  2,  8, 11,  4,  8,  5, -1, -1, -1, -1 },
+/*  44:       2, 3,    5,        */  { 10,  3, 11, 10,  1,  3,  9,  5,  4, -1, -1, -1, -1, -1, -1, -1 },
+/*  45: 0,    2, 3,    5,        */  {  4,  9,  5,  0,  8,  1,  8, 10,  1,  8, 11, 10, -1, -1, -1, -1 },
+/*  46:    1, 2, 3,    5,        */  {  5,  4,  0,  5,  0, 11,  5, 11, 10, 11,  0,  3, -1, -1, -1, -1 },
+/*  47: 0, 1, 2, 3,    5,        */  {  5,  4,  8,  5,  8, 10, 10,  8, 11, -1, -1, -1, -1, -1, -1, -1 },
+/*  48:             4, 5,        */  {  9,  7,  8,  5,  7,  9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  49: 0,          4, 5,        */  {  9,  3,  0,  9,  5,  3,  5,  7,  3, -1, -1, -1, -1, -1, -1, -1 },
+/*  50:    1,       4, 5,        */  {  0,  7,  8,  0,  1,  7,  1,  5,  7, -1, -1, -1, -1, -1, -1, -1 },
+/*  51: 0, 1,       4, 5,        */  {  1,  5,  3,  3,  5,  7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  52:       2,    4, 5,        */  {  9,  7,  8,  9,  5,  7, 10,  1,  2, -1, -1, -1, -1, -1, -1, -1 },
+/*  53: 0,    2,    4, 5,        */  { 10,  1,  2,  9,  5,  0,  5,  3,  0,  5,  7,  3, -1, -1, -1, -1 },
+/*  54:    1, 2,    4, 5,        */  {  8,  0,  2,  8,  2,  5,  8,  5,  7, 10,  5,  2, -1, -1, -1, -1 },
+/*  55: 0, 1, 2,    4, 5,        */  {  2, 10,  5,  2,  5,  3,  3,  5,  7, -1, -1, -1, -1, -1, -1, -1 },
+/*  56:          3, 4, 5,        */  {  7,  9,  5,  7,  8,  9,  3, 11,  2, -1, -1, -1, -1, -1, -1, -1 },
+/*  57: 0,       3, 4, 5,        */  {  9,  5,  7,  9,  7,  2,  9,  2,  0,  2,  7, 11, -1, -1, -1, -1 },
+/*  58:    1,    3, 4, 5,        */  {  2,  3, 11,  0,  1,  8,  1,  7,  8,  1,  5,  7, -1, -1, -1, -1 },
+/*  59: 0, 1,    3, 4, 5,        */  { 11,  2,  1, 11,  1,  7,  7,  1,  5, -1, -1, -1, -1, -1, -1, -1 },
+/*  60:       2, 3, 4, 5,        */  {  9,  5,  8,  8,  5,  7, 10,  1,  3, 10,  3, 11, -1, -1, -1, -1 },
+/*  61: 0,    2, 3, 4, 5,        */  {  5,  7,  0,  5,  0,  9,  7, 11,  0,  1,  0, 10, 11, 10,  0, -1 },
+/*  62:    1, 2, 3, 4, 5,        */  { 11, 10,  0, 11,  0,  3, 10,  5,  0,  8,  0,  7,  5,  7,  0, -1 },
+/*  63: 0, 1, 2, 3, 4, 5,        */  { 11, 10,  5,  7, 11,  5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  64:                   6,     */  { 10,  6,  5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  65: 0,                6,     */  {  0,  8,  3,  5, 10,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  66:    1,             6,     */  {  9,  0,  1,  5, 10,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  67: 0, 1,             6,     */  {  1,  8,  3,  1,  9,  8,  5, 10,  6, -1, -1, -1, -1, -1, -1, -1 },
+/*  68:       2,          6,     */  {  1,  6,  5,  2,  6,  1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  69: 0,    2,          6,     */  {  1,  6,  5,  1,  2,  6,  3,  0,  8, -1, -1, -1, -1, -1, -1, -1 },
+/*  70:    1, 2,          6,     */  {  9,  6,  5,  9,  0,  6,  0,  2,  6, -1, -1, -1, -1, -1, -1, -1 },
+/*  71: 0, 1, 2,          6,     */  {  5,  9,  8,  5,  8,  2,  5,  2,  6,  3,  2,  8, -1, -1, -1, -1 },
+/*  72:          3,       6,     */  {  2,  3, 11, 10,  6,  5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  73: 0,       3,       6,     */  { 11,  0,  8, 11,  2,  0, 10,  6,  5, -1, -1, -1, -1, -1, -1, -1 },
+/*  74:    1,    3,       6,     */  {  0,  1,  9,  2,  3, 11,  5, 10,  6, -1, -1, -1, -1, -1, -1, -1 },
+/*  75: 0, 1,    3,       6,     */  {  5, 10,  6,  1,  9,  2,  9, 11,  2,  9,  8, 11, -1, -1, -1, -1 },
+/*  76:       2, 3,       6,     */  {  6,  3, 11,  6,  5,  3,  5,  1,  3, -1, -1, -1, -1, -1, -1, -1 },
+/*  77: 0,    2, 3,       6,     */  {  0,  8, 11,  0, 11,  5,  0,  5,  1,  5, 11,  6, -1, -1, -1, -1 },
+/*  78:    1, 2, 3,       6,     */  {  3, 11,  6,  0,  3,  6,  0,  6,  5,  0,  5,  9, -1, -1, -1, -1 },
+/*  79: 0, 1, 2, 3,       6,     */  {  6,  5,  9,  6,  9, 11, 11,  9,  8, -1, -1, -1, -1, -1, -1, -1 },
+/*  80:             4,    6,     */  {  5, 10,  6,  4,  7,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  81: 0,          4,    6,     */  {  4,  3,  0,  4,  7,  3,  6,  5, 10, -1, -1, -1, -1, -1, -1, -1 },
+/*  82:    1,       4,    6,     */  {  1,  9,  0,  5, 10,  6,  8,  4,  7, -1, -1, -1, -1, -1, -1, -1 },
+/*  83: 0, 1,       4,    6,     */  { 10,  6,  5,  1,  9,  7,  1,  7,  3,  7,  9,  4, -1, -1, -1, -1 },
+/*  84:       2,    4,    6,     */  {  6,  1,  2,  6,  5,  1,  4,  7,  8, -1, -1, -1, -1, -1, -1, -1 },
+/*  85: 0,    2,    4,    6,     */  {  1,  2,  5,  5,  2,  6,  3,  0,  4,  3,  4,  7, -1, -1, -1, -1 },
+/*  86:    1, 2,    4,    6,     */  {  8,  4,  7,  9,  0,  5,  0,  6,  5,  0,  2,  6, -1, -1, -1, -1 },
+/*  87: 0, 1, 2,    4,    6,     */  {  7,  3,  9,  7,  9,  4,  3,  2,  9,  5,  9,  6,  2,  6,  9, -1 },
+/*  88:          3, 4,    6,     */  {  3, 11,  2,  7,  8,  4, 10,  6,  5, -1, -1, -1, -1, -1, -1, -1 },
+/*  89: 0,       3, 4,    6,     */  {  5, 10,  6,  4,  7,  2,  4,  2,  0,  2,  7, 11, -1, -1, -1, -1 },
+/*  90:    1,    3, 4,    6,     */  {  0,  1,  9,  4,  7,  8,  2,  3, 11,  5, 10,  6, -1, -1, -1, -1 },
+/*  91: 0, 1,    3, 4,    6,     */  {  9,  2,  1,  9, 11,  2,  9,  4, 11,  7, 11,  4,  5, 10,  6, -1 },
+/*  92:       2, 3, 4,    6,     */  {  8,  4,  7,  3, 11,  5,  3,  5,  1,  5, 11,  6, -1, -1, -1, -1 },
+/*  93: 0,    2, 3, 4,    6,     */  {  5,  1, 11,  5, 11,  6,  1,  0, 11,  7, 11,  4,  0,  4, 11, -1 },
+/*  94:    1, 2, 3, 4,    6,     */  {  0,  5,  9,  0,  6,  5,  0,  3,  6, 11,  6,  3,  8,  4,  7, -1 },
+/*  95: 0, 1, 2, 3, 4,    6,     */  {  6,  5,  9,  6,  9, 11,  4,  7,  9,  7, 11,  9, -1, -1, -1, -1 },
+/*  96:                5, 6,     */  { 10,  4,  9,  6,  4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/*  97: 0,             5, 6,     */  {  4, 10,  6,  4,  9, 10,  0,  8,  3, -1, -1, -1, -1, -1, -1, -1 },
+/*  98:    1,          5, 6,     */  { 10,  0,  1, 10,  6,  0,  6,  4,  0, -1, -1, -1, -1, -1, -1, -1 },
+/*  99: 0, 1,          5, 6,     */  {  8,  3,  1,  8,  1,  6,  8,  6,  4,  6,  1, 10, -1, -1, -1, -1 },
+/* 100:       2,       5, 6,     */  {  1,  4,  9,  1,  2,  4,  2,  6,  4, -1, -1, -1, -1, -1, -1, -1 },
+/* 101: 0,    2,       5, 6,     */  {  3,  0,  8,  1,  2,  9,  2,  4,  9,  2,  6,  4, -1, -1, -1, -1 },
+/* 102:    1, 2,       5, 6,     */  {  0,  2,  4,  4,  2,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 103: 0, 1, 2,       5, 6,     */  {  8,  3,  2,  8,  2,  4,  4,  2,  6, -1, -1, -1, -1, -1, -1, -1 },
+/* 104:          3,    5, 6,     */  { 10,  4,  9, 10,  6,  4, 11,  2,  3, -1, -1, -1, -1, -1, -1, -1 },
+/* 105: 0,       3,    5, 6,     */  {  0,  8,  2,  2,  8, 11,  4,  9, 10,  4, 10,  6, -1, -1, -1, -1 },
+/* 106:    1,    3,    5, 6,     */  {  3, 11,  2,  0,  1,  6,  0,  6,  4,  6,  1, 10, -1, -1, -1, -1 },
+/* 107: 0, 1,    3,    5, 6,     */  {  6,  4,  1,  6,  1, 10,  4,  8,  1,  2,  1, 11,  8, 11,  1, -1 },
+/* 108:       2, 3,    5, 6,     */  {  9,  6,  4,  9,  3,  6,  9,  1,  3, 11,  6,  3, -1, -1, -1, -1 },
+/* 109: 0,    2, 3,    5, 6,     */  {  8, 11,  1,  8,  1,  0, 11,  6,  1,  9,  1,  4,  6,  4,  1, -1 },
+/* 110:    1, 2, 3,    5, 6,     */  {  3, 11,  6,  3,  6,  0,  0,  6,  4, -1, -1, -1, -1, -1, -1, -1 },
+/* 111: 0, 1, 2, 3,    5, 6,     */  {  6,  4,  8, 11,  6,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 112:             4, 5, 6,     */  {  7, 10,  6,  7,  8, 10,  8,  9, 10, -1, -1, -1, -1, -1, -1, -1 },
+/* 113: 0,          4, 5, 6,     */  {  0,  7,  3,  0, 10,  7,  0,  9, 10,  6,  7, 10, -1, -1, -1, -1 },
+/* 114:    1,       4, 5, 6,     */  { 10,  6,  7,  1, 10,  7,  1,  7,  8,  1,  8,  0, -1, -1, -1, -1 },
+/* 115: 0, 1,       4, 5, 6,     */  { 10,  6,  7, 10,  7,  1,  1,  7,  3, -1, -1, -1, -1, -1, -1, -1 },
+/* 116:       2,    4, 5, 6,     */  {  1,  2,  6,  1,  6,  8,  1,  8,  9,  8,  6,  7, -1, -1, -1, -1 },
+/* 117: 0,    2,    4, 5, 6,     */  {  2,  6,  9,  2,  9,  1,  6,  7,  9,  0,  9,  3,  7,  3,  9, -1 },
+/* 118:    1, 2,    4, 5, 6,     */  {  7,  8,  0,  7,  0,  6,  6,  0,  2, -1, -1, -1, -1, -1, -1, -1 },
+/* 119: 0, 1, 2,    4, 5, 6,     */  {  7,  3,  2,  6,  7,  2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 120:          3, 4, 5, 6,     */  {  2,  3, 11, 10,  6,  8, 10,  8,  9,  8,  6,  7, -1, -1, -1, -1 },
+/* 121: 0,       3, 4, 5, 6,     */  {  2,  0,  7,  2,  7, 11,  0,  9,  7,  6,  7, 10,  9, 10,  7, -1 },
+/* 122:    1,    3, 4, 5, 6,     */  {  1,  8,  0,  1,  7,  8,  1, 10,  7,  6,  7, 10,  2,  3, 11, -1 },
+/* 123: 0, 1,    3, 4, 5, 6,     */  { 11,  2,  1, 11,  1,  7, 10,  6,  1,  6,  7,  1, -1, -1, -1, -1 },
+/* 124:       2, 3, 4, 5, 6,     */  {  8,  9,  6,  8,  6,  7,  9,  1,  6, 11,  6,  3,  1,  3,  6, -1 },
+/* 125: 0,    2, 3, 4, 5, 6,     */  {  0,  9,  1, 11,  6,  7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 126:    1, 2, 3, 4, 5, 6,     */  {  7,  8,  0,  7,  0,  6,  3, 11,  0, 11,  6,  0, -1, -1, -1, -1 },
+/* 127: 0, 1, 2, 3, 4, 5, 6,     */  {  7, 11,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 128:                      7,  */  {  7,  6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 129: 0,                   7,  */  {  3,  0,  8, 11,  7,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 130:    1,                7,  */  {  0,  1,  9, 11,  7,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 131: 0, 1,                7,  */  {  8,  1,  9,  8,  3,  1, 11,  7,  6, -1, -1, -1, -1, -1, -1, -1 },
+/* 132:       2,             7,  */  { 10,  1,  2,  6, 11,  7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 133: 0,    2,             7,  */  {  1,  2, 10,  3,  0,  8,  6, 11,  7, -1, -1, -1, -1, -1, -1, -1 },
+/* 134:    1, 2,             7,  */  {  2,  9,  0,  2, 10,  9,  6, 11,  7, -1, -1, -1, -1, -1, -1, -1 },
+/* 135: 0, 1, 2,             7,  */  {  6, 11,  7,  2, 10,  3, 10,  8,  3, 10,  9,  8, -1, -1, -1, -1 },
+/* 136:          3,          7,  */  {  7,  2,  3,  6,  2,  7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 137: 0,       3,          7,  */  {  7,  0,  8,  7,  6,  0,  6,  2,  0, -1, -1, -1, -1, -1, -1, -1 },
+/* 138:    1,    3,          7,  */  {  2,  7,  6,  2,  3,  7,  0,  1,  9, -1, -1, -1, -1, -1, -1, -1 },
+/* 139: 0, 1,    3,          7,  */  {  1,  6,  2,  1,  8,  6,  1,  9,  8,  8,  7,  6, -1, -1, -1, -1 },
+/* 140:       2, 3,          7,  */  { 10,  7,  6, 10,  1,  7,  1,  3,  7, -1, -1, -1, -1, -1, -1, -1 },
+/* 141: 0,    2, 3,          7,  */  { 10,  7,  6,  1,  7, 10,  1,  8,  7,  1,  0,  8, -1, -1, -1, -1 },
+/* 142:    1, 2, 3,          7,  */  {  0,  3,  7,  0,  7, 10,  0, 10,  9,  6, 10,  7, -1, -1, -1, -1 },
+/* 143: 0, 1, 2, 3,          7,  */  {  7,  6, 10,  7, 10,  8,  8, 10,  9, -1, -1, -1, -1, -1, -1, -1 },
+/* 144:             4,       7,  */  {  6,  8,  4, 11,  8,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 145: 0,          4,       7,  */  {  3,  6, 11,  3,  0,  6,  0,  4,  6, -1, -1, -1, -1, -1, -1, -1 },
+/* 146:    1,       4,       7,  */  {  8,  6, 11,  8,  4,  6,  9,  0,  1, -1, -1, -1, -1, -1, -1, -1 },
+/* 147: 0, 1,       4,       7,  */  {  9,  4,  6,  9,  6,  3,  9,  3,  1, 11,  3,  6, -1, -1, -1, -1 },
+/* 148:       2,    4,       7,  */  {  6,  8,  4,  6, 11,  8,  2, 10,  1, -1, -1, -1, -1, -1, -1, -1 },
+/* 149: 0,    2,    4,       7,  */  {  1,  2, 10,  3,  0, 11,  0,  6, 11,  0,  4,  6, -1, -1, -1, -1 },
+/* 150:    1, 2,    4,       7,  */  {  4, 11,  8,  4,  6, 11,  0,  2,  9,  2, 10,  9, -1, -1, -1, -1 },
+/* 151: 0, 1, 2,    4,       7,  */  { 10,  9,  3, 10,  3,  2,  9,  4,  3, 11,  3,  6,  4,  6,  3, -1 },
+/* 152:          3, 4,       7,  */  {  8,  2,  3,  8,  4,  2,  4,  6,  2, -1, -1, -1, -1, -1, -1, -1 },
+/* 153: 0,       3, 4,       7,  */  {  0,  4,  2,  4,  6,  2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 154:    1,    3, 4,       7,  */  {  1,  9,  0,  2,  3,  4,  2,  4,  6,  4,  3,  8, -1, -1, -1, -1 },
+/* 155: 0, 1,    3, 4,       7,  */  {  1,  9,  4,  1,  4,  2,  2,  4,  6, -1, -1, -1, -1, -1, -1, -1 },
+/* 156:       2, 3, 4,       7,  */  {  8,  1,  3,  8,  6,  1,  8,  4,  6,  6, 10,  1, -1, -1, -1, -1 },
+/* 157: 0,    2, 3, 4,       7,  */  { 10,  1,  0, 10,  0,  6,  6,  0,  4, -1, -1, -1, -1, -1, -1, -1 },
+/* 158:    1, 2, 3, 4,       7,  */  {  4,  6,  3,  4,  3,  8,  6, 10,  3,  0,  3,  9, 10,  9,  3, -1 },
+/* 159: 0, 1, 2, 3, 4,       7,  */  { 10,  9,  4,  6, 10,  4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 160:                5,    7,  */  {  4,  9,  5,  7,  6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 161: 0,             5,    7,  */  {  0,  8,  3,  4,  9,  5, 11,  7,  6, -1, -1, -1, -1, -1, -1, -1 },
+/* 162:    1,          5,    7,  */  {  5,  0,  1,  5,  4,  0,  7,  6, 11, -1, -1, -1, -1, -1, -1, -1 },
+/* 163: 0, 1,          5,    7,  */  { 11,  7,  6,  8,  3,  4,  3,  5,  4,  3,  1,  5, -1, -1, -1, -1 },
+/* 164:       2,       5,    7,  */  {  9,  5,  4, 10,  1,  2,  7,  6, 11, -1, -1, -1, -1, -1, -1, -1 },
+/* 165: 0,    2,       5,    7,  */  {  6, 11,  7,  1,  2, 10,  0,  8,  3,  4,  9,  5, -1, -1, -1, -1 },
+/* 166:    1, 2,       5,    7,  */  {  7,  6, 11,  5,  4, 10,  4,  2, 10,  4,  0,  2, -1, -1, -1, -1 },
+/* 167: 0, 1, 2,       5,    7,  */  {  3,  4,  8,  3,  5,  4,  3,  2,  5, 10,  5,  2, 11,  7,  6, -1 },
+/* 168:          3,    5,    7,  */  {  7,  2,  3,  7,  6,  2,  5,  4,  9, -1, -1, -1, -1, -1, -1, -1 },
+/* 169: 0,       3,    5,    7,  */  {  9,  5,  4,  0,  8,  6,  0,  6,  2,  6,  8,  7, -1, -1, -1, -1 },
+/* 170:    1,    3,    5,    7,  */  {  3,  6,  2,  3,  7,  6,  1,  5,  0,  5,  4,  0, -1, -1, -1, -1 },
+/* 171: 0, 1,    3,    5,    7,  */  {  6,  2,  8,  6,  8,  7,  2,  1,  8,  4,  8,  5,  1,  5,  8, -1 },
+/* 172:       2, 3,    5,    7,  */  {  9,  5,  4, 10,  1,  6,  1,  7,  6,  1,  3,  7, -1, -1, -1, -1 },
+/* 173: 0,    2, 3,    5,    7,  */  {  1,  6, 10,  1,  7,  6,  1,  0,  7,  8,  7,  0,  9,  5,  4, -1 },
+/* 174:    1, 2, 3,    5,    7,  */  {  4,  0, 10,  4, 10,  5,  0,  3, 10,  6, 10,  7,  3,  7, 10, -1 },
+/* 175: 0, 1, 2, 3,    5,    7,  */  {  7,  6, 10,  7, 10,  8,  5,  4, 10,  4,  8, 10, -1, -1, -1, -1 },
+/* 176:             4, 5,    7,  */  {  6,  9,  5,  6, 11,  9, 11,  8,  9, -1, -1, -1, -1, -1, -1, -1 },
+/* 177: 0,          4, 5,    7,  */  {  3,  6, 11,  0,  6,  3,  0,  5,  6,  0,  9,  5, -1, -1, -1, -1 },
+/* 178:    1,       4, 5,    7,  */  {  0, 11,  8,  0,  5, 11,  0,  1,  5,  5,  6, 11, -1, -1, -1, -1 },
+/* 179: 0, 1,       4, 5,    7,  */  {  6, 11,  3,  6,  3,  5,  5,  3,  1, -1, -1, -1, -1, -1, -1, -1 },
+/* 180:       2,    4, 5,    7,  */  {  1,  2, 10,  9,  5, 11,  9, 11,  8, 11,  5,  6, -1, -1, -1, -1 },
+/* 181: 0,    2,    4, 5,    7,  */  {  0, 11,  3,  0,  6, 11,  0,  9,  6,  5,  6,  9,  1,  2, 10, -1 },
+/* 182:    1, 2,    4, 5,    7,  */  { 11,  8,  5, 11,  5,  6,  8,  0,  5, 10,  5,  2,  0,  2,  5, -1 },
+/* 183: 0, 1, 2,    4, 5,    7,  */  {  6, 11,  3,  6,  3,  5,  2, 10,  3, 10,  5,  3, -1, -1, -1, -1 },
+/* 184:          3, 4, 5,    7,  */  {  5,  8,  9,  5,  2,  8,  5,  6,  2,  3,  8,  2, -1, -1, -1, -1 },
+/* 185: 0,       3, 4, 5,    7,  */  {  9,  5,  6,  9,  6,  0,  0,  6,  2, -1, -1, -1, -1, -1, -1, -1 },
+/* 186:    1,    3, 4, 5,    7,  */  {  1,  5,  8,  1,  8,  0,  5,  6,  8,  3,  8,  2,  6,  2,  8, -1 },
+/* 187: 0, 1,    3, 4, 5,    7,  */  {  1,  5,  6,  2,  1,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 188:       2, 3, 4, 5,    7,  */  {  1,  3,  6,  1,  6, 10,  3,  8,  6,  5,  6,  9,  8,  9,  6, -1 },
+/* 189: 0,    2, 3, 4, 5,    7,  */  { 10,  1,  0, 10,  0,  6,  9,  5,  0,  5,  6,  0, -1, -1, -1, -1 },
+/* 190:    1, 2, 3, 4, 5,    7,  */  {  0,  3,  8,  5,  6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 191: 0, 1, 2, 3, 4, 5,    7,  */  { 10,  5,  6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 192:                   6, 7,  */  { 11,  5, 10,  7,  5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 193: 0,                6, 7,  */  { 11,  5, 10, 11,  7,  5,  8,  3,  0, -1, -1, -1, -1, -1, -1, -1 },
+/* 194:    1,             6, 7,  */  {  5, 11,  7,  5, 10, 11,  1,  9,  0, -1, -1, -1, -1, -1, -1, -1 },
+/* 195: 0, 1,             6, 7,  */  { 10,  7,  5, 10, 11,  7,  9,  8,  1,  8,  3,  1, -1, -1, -1, -1 },
+/* 196:       2,          6, 7,  */  { 11,  1,  2, 11,  7,  1,  7,  5,  1, -1, -1, -1, -1, -1, -1, -1 },
+/* 197: 0,    2,          6, 7,  */  {  0,  8,  3,  1,  2,  7,  1,  7,  5,  7,  2, 11, -1, -1, -1, -1 },
+/* 198:    1, 2,          6, 7,  */  {  9,  7,  5,  9,  2,  7,  9,  0,  2,  2, 11,  7, -1, -1, -1, -1 },
+/* 199: 0, 1, 2,          6, 7,  */  {  7,  5,  2,  7,  2, 11,  5,  9,  2,  3,  2,  8,  9,  8,  2, -1 },
+/* 200:          3,       6, 7,  */  {  2,  5, 10,  2,  3,  5,  3,  7,  5, -1, -1, -1, -1, -1, -1, -1 },
+/* 201: 0,       3,       6, 7,  */  {  8,  2,  0,  8,  5,  2,  8,  7,  5, 10,  2,  5, -1, -1, -1, -1 },
+/* 202:    1,    3,       6, 7,  */  {  9,  0,  1,  5, 10,  3,  5,  3,  7,  3, 10,  2, -1, -1, -1, -1 },
+/* 203: 0, 1,    3,       6, 7,  */  {  9,  8,  2,  9,  2,  1,  8,  7,  2, 10,  2,  5,  7,  5,  2, -1 },
+/* 204:       2, 3,       6, 7,  */  {  1,  3,  5,  3,  7,  5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 205: 0,    2, 3,       6, 7,  */  {  0,  8,  7,  0,  7,  1,  1,  7,  5, -1, -1, -1, -1, -1, -1, -1 },
+/* 206:    1, 2, 3,       6, 7,  */  {  9,  0,  3,  9,  3,  5,  5,  3,  7, -1, -1, -1, -1, -1, -1, -1 },
+/* 207: 0, 1, 2, 3,       6, 7,  */  {  9,  8,  7,  5,  9,  7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 208:             4,    6, 7,  */  {  5,  8,  4,  5, 10,  8, 10, 11,  8, -1, -1, -1, -1, -1, -1, -1 },
+/* 209: 0,          4,    6, 7,  */  {  5,  0,  4,  5, 11,  0,  5, 10, 11, 11,  3,  0, -1, -1, -1, -1 },
+/* 210:    1,       4,    6, 7,  */  {  0,  1,  9,  8,  4, 10,  8, 10, 11, 10,  4,  5, -1, -1, -1, -1 },
+/* 211: 0, 1,       4,    6, 7,  */  { 10, 11,  4, 10,  4,  5, 11,  3,  4,  9,  4,  1,  3,  1,  4, -1 },
+/* 212:       2,    4,    6, 7,  */  {  2,  5,  1,  2,  8,  5,  2, 11,  8,  4,  5,  8, -1, -1, -1, -1 },
+/* 213: 0,    2,    4,    6, 7,  */  {  0,  4, 11,  0, 11,  3,  4,  5, 11,  2, 11,  1,  5,  1, 11, -1 },
+/* 214:    1, 2,    4,    6, 7,  */  {  0,  2,  5,  0,  5,  9,  2, 11,  5,  4,  5,  8, 11,  8,  5, -1 },
+/* 215: 0, 1, 2,    4,    6, 7,  */  {  9,  4,  5,  2, 11,  3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 216:          3, 4,    6, 7,  */  {  2,  5, 10,  3,  5,  2,  3,  4,  5,  3,  8,  4, -1, -1, -1, -1 },
+/* 217: 0,       3, 4,    6, 7,  */  {  5, 10,  2,  5,  2,  4,  4,  2,  0, -1, -1, -1, -1, -1, -1, -1 },
+/* 218:    1,    3, 4,    6, 7,  */  {  3, 10,  2,  3,  5, 10,  3,  8,  5,  4,  5,  8,  0,  1,  9, -1 },
+/* 219: 0, 1,    3, 4,    6, 7,  */  {  5, 10,  2,  5,  2,  4,  1,  9,  2,  9,  4,  2, -1, -1, -1, -1 },
+/* 220:       2, 3, 4,    6, 7,  */  {  8,  4,  5,  8,  5,  3,  3,  5,  1, -1, -1, -1, -1, -1, -1, -1 },
+/* 221: 0,    2, 3, 4,    6, 7,  */  {  0,  4,  5,  1,  0,  5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 222:    1, 2, 3, 4,    6, 7,  */  {  8,  4,  5,  8,  5,  3,  9,  0,  5,  0,  3,  5, -1, -1, -1, -1 },
+/* 223: 0, 1, 2, 3, 4,    6, 7,  */  {  9,  4,  5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 224:                5, 6, 7,  */  {  4, 11,  7,  4,  9, 11,  9, 10, 11, -1, -1, -1, -1, -1, -1, -1 },
+/* 225: 0,             5, 6, 7,  */  {  0,  8,  3,  4,  9,  7,  9, 11,  7,  9, 10, 11, -1, -1, -1, -1 },
+/* 226:    1,          5, 6, 7,  */  {  1, 10, 11,  1, 11,  4,  1,  4,  0,  7,  4, 11, -1, -1, -1, -1 },
+/* 227: 0, 1,          5, 6, 7,  */  {  3,  1,  4,  3,  4,  8,  1, 10,  4,  7,  4, 11, 10, 11,  4, -1 },
+/* 228:       2,       5, 6, 7,  */  {  4, 11,  7,  9, 11,  4,  9,  2, 11,  9,  1,  2, -1, -1, -1, -1 },
+/* 229: 0,    2,       5, 6, 7,  */  {  9,  7,  4,  9, 11,  7,  9,  1, 11,  2, 11,  1,  0,  8,  3, -1 },
+/* 230:    1, 2,       5, 6, 7,  */  { 11,  7,  4, 11,  4,  2,  2,  4,  0, -1, -1, -1, -1, -1, -1, -1 },
+/* 231: 0, 1, 2,       5, 6, 7,  */  { 11,  7,  4, 11,  4,  2,  8,  3,  4,  3,  2,  4, -1, -1, -1, -1 },
+/* 232:          3,    5, 6, 7,  */  {  2,  9, 10,  2,  7,  9,  2,  3,  7,  7,  4,  9, -1, -1, -1, -1 },
+/* 233: 0,       3,    5, 6, 7,  */  {  9, 10,  7,  9,  7,  4, 10,  2,  7,  8,  7,  0,  2,  0,  7, -1 },
+/* 234:    1,    3,    5, 6, 7,  */  {  3,  7, 10,  3, 10,  2,  7,  4, 10,  1, 10,  0,  4,  0, 10, -1 },
+/* 235: 0, 1,    3,    5, 6, 7,  */  {  1, 10,  2,  8,  7,  4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 236:       2, 3,    5, 6, 7,  */  {  4,  9,  1,  4,  1,  7,  7,  1,  3, -1, -1, -1, -1, -1, -1, -1 },
+/* 237: 0,    2, 3,    5, 6, 7,  */  {  4,  9,  1,  4,  1,  7,  0,  8,  1,  8,  7,  1, -1, -1, -1, -1 },
+/* 238:    1, 2, 3,    5, 6, 7,  */  {  4,  0,  3,  7,  4,  3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 239: 0, 1, 2, 3,    5, 6, 7,  */  {  4,  8,  7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 240:             4, 5, 6, 7,  */  {  9, 10,  8, 10, 11,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 241: 0,          4, 5, 6, 7,  */  {  3,  0,  9,  3,  9, 11, 11,  9, 10, -1, -1, -1, -1, -1, -1, -1 },
+/* 242:    1,       4, 5, 6, 7,  */  {  0,  1, 10,  0, 10,  8,  8, 10, 11, -1, -1, -1, -1, -1, -1, -1 },
+/* 243: 0, 1,       4, 5, 6, 7,  */  {  3,  1, 10, 11,  3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 244:       2,    4, 5, 6, 7,  */  {  1,  2, 11,  1, 11,  9,  9, 11,  8, -1, -1, -1, -1, -1, -1, -1 },
+/* 245: 0,    2,    4, 5, 6, 7,  */  {  3,  0,  9,  3,  9, 11,  1,  2,  9,  2, 11,  9, -1, -1, -1, -1 },
+/* 246:    1, 2,    4, 5, 6, 7,  */  {  0,  2, 11,  8,  0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 247: 0, 1, 2,    4, 5, 6, 7,  */  {  3,  2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 248:          3, 4, 5, 6, 7,  */  {  2,  3,  8,  2,  8, 10, 10,  8,  9, -1, -1, -1, -1, -1, -1, -1 },
+/* 249: 0,       3, 4, 5, 6, 7,  */  {  9, 10,  2,  0,  9,  2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 250:    1,    3, 4, 5, 6, 7,  */  {  2,  3,  8,  2,  8, 10,  0,  1,  8,  1, 10,  8, -1, -1, -1, -1 },
+/* 251: 0, 1,    3, 4, 5, 6, 7,  */  {  1, 10,  2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 252:       2, 3, 4, 5, 6, 7,  */  {  1,  3,  8,  9,  1,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 253: 0,    2, 3, 4, 5, 6, 7,  */  {  0,  9,  1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 254:    1, 2, 3, 4, 5, 6, 7,  */  {  0,  3,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+/* 255: 0, 1, 2, 3, 4, 5, 6, 7,  */  { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
+};
+//_____________________________________________________________________________
+
+} //namespace McCubes
+
+#endif // _LOOKUPTABLE_H_
diff --git a/source/ThirdParty/MarchingCubes/McPly.cpp b/source/ThirdParty/MarchingCubes/McPly.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..35b9b718eb60b259ca221135dbc4109582e1a057
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/McPly.cpp
@@ -0,0 +1,3320 @@
+/*
+
+The interface routines for reading and writing PLY polygon files.
+
+Greg Turk
+
+---------------------------------------------------------------
+
+A PLY file contains a single polygonal _object_.
+
+An object is composed of lists of _elements_.  Typical elements are
+vertices, faces, edges and materials.
+
+Each type of element for a given object has one or more _properties_
+associated with the element type.  For instance, a vertex element may
+have as properties the floating-point values x,y,z and the three unsigned
+chars representing red, green and blue.
+
+-----------------------------------------------------------------------
+
+Copyright (c) 1998 Georgia Institute of Technology.  All rights reserved.
+
+Permission to use, copy, modify and distribute this software and its
+documentation for any purpose is hereby granted without fee, provided
+that the above copyright notice and this permission notice appear in
+all copies of this software and that you do not sell the software.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+*/
+
+#include "./McPly.h"
+#include <iostream>
+#include <cstdio>
+
+namespace McCubes{
+
+const char *type_names[]      = {  /* names of scalar types */
+"invalid",
+"int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64"
+};
+
+const char *old_type_names[]  = {  /* old names of types for backward compatability */
+"invalid",
+"char", "short", "int", "uchar", "ushort", "uint", "float", "double"
+};
+
+int   ply_type_size[]   = {
+0, 1, 2, 4, 1, 2, 4, 4, 8
+};
+
+#define NO_OTHER_PROPS  -1
+
+#define DONT_STORE_PROP  0
+#define STORE_PROP       1
+
+#define OTHER_PROP       0
+#define NAMED_PROP       1
+
+/* returns 1 if strings are equal, 0 if not */
+int           equal_strings( const char * , const char * );
+
+/* find an element in a plyfile's list */
+PlyElement   *find_element( PlyFile * , const char * );
+
+/* find a property in an element's list */
+PlyProperty  *find_property( PlyElement * , const char * , int * );
+
+/* write to a file the word describing a PLY file data type */
+void          write_scalar_type( FILE * , int );
+
+/* read a line from a file and break it up into separate words */
+char*        *get_words( FILE * , int * , char ** );
+
+/* write an item to a file */
+void          write_binary_item( FILE * , int, unsigned int, double, int );
+void          write_ascii_item( FILE * , int, unsigned int, double, int );
+
+/* add information to a PLY file descriptor */
+void          add_element( PlyFile * , char ** , int );
+void          add_property( PlyFile * , char ** , int );
+void          add_comment( PlyFile * , const char * );
+void          add_obj_info( PlyFile * , const char * );
+
+/* copy a property */
+void          copy_property( PlyProperty * , PlyProperty * );
+
+/* store a value into where a pointer and a type specify */
+void          store_item( char * , int, int, unsigned int, double );
+
+/* return the value of a stored item */
+void          get_stored_item( void * , int, int * , unsigned int * , double * );
+
+/* return the value stored in an item, given ptr to it and its type */
+double        get_item_value( const char * , int );
+
+/* get binary or ascii item and store it according to ptr and type */
+void          get_ascii_item( const char * , int, int * , unsigned int * , double * );
+void          get_binary_item( FILE * , int, int * , unsigned int * , double * );
+
+/* get a bunch of elements from a file */
+void          ascii_get_element( PlyFile * , char * );
+void          binary_get_element( PlyFile * , char * );
+
+/* memory allocation */
+static char  *my_alloc( int, int, const char * );
+
+
+/*************/
+/*  Writing  */
+/*************/
+
+
+/******************************************************************************
+Given a file pointer, get ready to write PLY data to the file.
+
+Entry:
+fp         - the given file pointer
+nelems     - number of elements in object
+elem_names - list of element names
+file_type  - file type, either ascii or binary
+
+Exit:
+returns a pointer to a PlyFile, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *ply_write( FILE *fp, int nelems, char **elem_names, int file_type )
+{
+  int         i;
+  PlyFile    *plyfile;
+  PlyElement *elem;
+
+  /* check for NULL file pointer */
+  if ( fp == NULL )
+    return ( NULL );
+
+  /* create a record for this object */
+
+  plyfile = ( PlyFile *  ) myalloc ( sizeof ( PlyFile ) );
+  plyfile->file_type = file_type;
+  plyfile->num_comments = 0;
+  plyfile->num_obj_info = 0;
+  plyfile->num_elem_types = nelems;
+  plyfile->version = 1.0;
+  plyfile->fp = fp;
+  plyfile->other_elems = NULL;
+
+  /* tuck aside the names of the elements */
+
+  plyfile->elems = ( PlyElement *  *  ) myalloc ( sizeof ( PlyElement *  ) * nelems );
+  for ( i = 0; i < nelems; i++ )
+  {
+    elem = ( PlyElement *  ) myalloc ( sizeof ( PlyElement ) );
+    plyfile->elems[i] = elem;
+    elem->name = strdup ( elem_names[i] );
+    elem->num = 0;
+    elem->nprops = 0;
+  }
+
+  /* return pointer to the file descriptor */
+  return ( plyfile );
+}
+
+
+/******************************************************************************
+Open a polygon file for writing.
+
+Entry:
+filename   - name of file to read from
+nelems     - number of elements in object
+elem_names - list of element names
+file_type  - file type, either ascii or binary
+
+Exit:
+returns a file identifier, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *open_for_writing_ply( const char *filename, int nelems, char **elem_names, int file_type )
+{
+  PlyFile  *plyfile;
+  char     *name;
+  FILE     *fp;
+
+  /* tack on the extension .ply, if necessary */
+
+  name = ( char * ) myalloc ( sizeof ( char ) * ( (int)strlen ( filename ) + 5 ) );
+  strcpy ( name, filename );
+  if ( strlen ( name ) < 4 || strcmp ( name + strlen ( name ) - 4, ".ply" ) != 0 )
+    strcat ( name, ".ply" );
+
+  /* open the file for writing */
+
+  fp = fopen ( name, "w" );
+  if ( fp == NULL )
+  {
+    return ( NULL );
+  }
+
+  /* create the actual PlyFile structure */
+
+  plyfile = ply_write ( fp, nelems, elem_names, file_type );
+  if ( plyfile == NULL )
+    return ( NULL );
+
+  /* return pointer to the file descriptor */
+  return ( plyfile );
+}
+
+
+/******************************************************************************
+Describe an element, including its properties and how many will be written
+to the file.
+
+Entry:
+plyfile   - file identifier
+elem_name - name of element that information is being specified about
+nelems    - number of elements of this type to be written
+nprops    - number of properties contained in the element
+prop_list - list of properties
+******************************************************************************/
+
+void element_layout_ply( PlyFile *plyfile, const char *elem_name, int nelems, int nprops, PlyProperty *prop_list )
+{
+  int           i;
+  PlyElement   *elem;
+  PlyProperty  *prop;
+
+  /* look for appropriate element */
+  elem = find_element ( plyfile, elem_name );
+  if ( elem == NULL )
+  {
+    fprintf( stderr,"element_layout_ply: can't find element '%s'\n",elem_name );
+    exit ( -1 );
+  }
+
+  elem->num = nelems;
+
+  /* copy the list of properties */
+
+  elem->nprops = nprops;
+  elem->props = ( PlyProperty *  *  ) myalloc ( sizeof ( PlyProperty *  ) * nprops );
+  elem->store_prop = ( char * ) myalloc ( sizeof ( char ) * nprops );
+
+  for ( i = 0; i < nprops; i++ )
+  {
+    prop = ( PlyProperty *  ) myalloc ( sizeof ( PlyProperty ) );
+    elem->props[i] = prop;
+    elem->store_prop[i] = NAMED_PROP;
+    copy_property ( prop, &prop_list[i] );
+  }
+}
+
+
+/******************************************************************************
+Describe a property of an element.
+
+Entry:
+plyfile   - file identifier
+elem_name - name of element that information is being specified about
+prop      - the new property
+******************************************************************************/
+
+void ply_describe_property( PlyFile *plyfile, const char *elem_name, PlyProperty *prop )
+{
+  PlyElement   *elem;
+  PlyProperty  *elem_prop;
+
+  /* look for appropriate element */
+  elem = find_element ( plyfile, elem_name );
+  if ( elem == NULL )
+  {
+    fprintf( stderr, "ply_describe_property: can't find element '%s'\n",
+    elem_name );
+    return;
+  }
+
+  /* create room for new property */
+
+  if ( elem->nprops == 0 )
+  {
+    elem->props = ( PlyProperty *  *  ) myalloc ( sizeof ( PlyProperty *  ) );
+    elem->store_prop = ( char * ) myalloc ( sizeof ( char ) );
+    elem->nprops = 1;
+  }
+  else
+  {
+    elem->nprops++;
+    elem->props = ( PlyProperty *  *  )
+    realloc ( elem->props, sizeof ( PlyProperty *  ) * elem->nprops );
+    elem->store_prop = ( char * )
+    realloc ( elem->store_prop, sizeof ( char ) * elem->nprops );
+  }
+
+  /* copy the new property */
+
+  elem_prop = ( PlyProperty *  ) myalloc ( sizeof ( PlyProperty ) );
+  elem->props[elem->nprops - 1] = elem_prop;
+  elem->store_prop[elem->nprops - 1] = NAMED_PROP;
+  copy_property ( elem_prop, prop );
+}
+
+
+/******************************************************************************
+State how many of a given element will be written.
+
+Entry:
+plyfile   - file identifier
+elem_name - name of element that information is being specified about
+nelems    - number of elements of this type to be written
+******************************************************************************/
+
+void element_count_ply( PlyFile *plyfile, const char *elem_name, int nelems )
+{
+  PlyElement *elem;
+
+  /* look for appropriate element */
+  elem = find_element ( plyfile, elem_name );
+  if ( elem == NULL )
+  {
+    fprintf( stderr,"element_count_ply: can't find element '%s'\n",elem_name );
+    exit ( -1 );
+  }
+
+  elem->num = nelems;
+}
+
+
+/******************************************************************************
+Signal that we've described everything a PLY file's header and that the
+header should be written to the file.
+
+Entry:
+plyfile - file identifier
+******************************************************************************/
+
+void header_complete_ply( PlyFile *plyfile )
+{
+  int           i,j;
+  FILE         *fp  = plyfile->fp;
+  PlyElement   *elem;
+  PlyProperty  *prop;
+
+  fprintf ( fp, "ply\n" );
+
+  switch ( plyfile->file_type )
+  {
+    case PLY_ASCII:
+      fprintf ( fp, "format ascii 1.0\n" );
+      break;
+    case PLY_BINARY_BE:
+      fprintf ( fp, "format binary_big_endian 1.0\n" );
+      break;
+    case PLY_BINARY_LE:
+      fprintf ( fp, "format binary_little_endian 1.0\n" );
+      break;
+    default:
+      fprintf ( stderr, "ply_header_complete: bad file type = %d\n",
+      plyfile->file_type );
+      exit ( -1 );
+  }
+
+  /* write out the comments */
+
+  for ( i = 0; i < plyfile->num_comments; i++ )
+    fprintf ( fp, "comment %s\n", plyfile->comments[i] );
+
+  /* write out object information */
+
+  for ( i = 0; i < plyfile->num_obj_info; i++ )
+    fprintf ( fp, "obj_info %s\n", plyfile->obj_info[i] );
+
+  /* write out information about each element */
+
+  for ( i = 0; i < plyfile->num_elem_types; i++ )
+  {
+    elem = plyfile->elems[i];
+    fprintf ( fp, "element %s %d\n", elem->name, elem->num );
+
+    /* write out each property */
+    for ( j = 0; j < elem->nprops; j++ )
+    {
+      prop = elem->props[j];
+      if ( prop->is_list == PLY_LIST )
+      {
+        fprintf ( fp, "property list " );
+        write_scalar_type ( fp, prop->count_external );
+        fprintf ( fp, " " );
+        write_scalar_type ( fp, prop->external_type );
+        fprintf ( fp, " %s\n", prop->name );
+      }
+      else if ( prop->is_list == PLY_STRING )
+      {
+        fprintf ( fp, "property string" );
+        fprintf ( fp, " %s\n", prop->name );
+      }
+      else
+      {
+        fprintf ( fp, "property " );
+        write_scalar_type ( fp, prop->external_type );
+        fprintf ( fp, " %s\n", prop->name );
+      }
+    }
+  }
+
+  fprintf ( fp, "end_header\n" );
+}
+
+
+/******************************************************************************
+Specify which elements are going to be written.  This should be called
+before a call to the routine ply_put_element().
+
+Entry:
+plyfile   - file identifier
+elem_name - name of element we're talking about
+******************************************************************************/
+
+void put_element_setup_ply( PlyFile *plyfile, const char *elem_name )
+{
+  PlyElement *elem;
+
+  elem = find_element ( plyfile, elem_name );
+  if ( elem == NULL )
+  {
+    fprintf( stderr, "put_element_setup_ply: can't find element '%s'\n", elem_name );
+    exit ( -1 );
+  }
+
+  plyfile->which_elem = elem;
+}
+
+
+/******************************************************************************
+Write an element to the file.  This routine assumes that we're
+writing the type of element specified in the last call to the routine
+put_element_setup_ply().
+
+Entry:
+plyfile  - file identifier
+elem_ptr - pointer to the element
+******************************************************************************/
+
+void put_element_ply( PlyFile *plyfile, void *elem_ptr )
+{
+  int           j,k;
+  FILE         *fp  = plyfile->fp;
+  PlyElement   *elem;
+  PlyProperty  *prop;
+  char         *item;
+  char         *elem_data;
+  char*        *item_ptr;
+  int           list_count;
+  int           item_size;
+  int           int_val;
+  unsigned int uint_val;
+  double  double_val;
+  char*  *other_ptr;
+
+  elem = plyfile->which_elem;
+  elem_data = ( char * ) elem_ptr;
+  other_ptr = ( char * *  ) ( ( ( char * ) elem_ptr ) + elem->other_offset );
+
+  /* write out either to an ascii or binary file */
+
+  if ( plyfile->file_type == PLY_ASCII )
+  {
+    /* write an ascii file */
+
+    /* write out each property of the element */
+    for ( j = 0; j < elem->nprops; j++ )
+    {
+      prop = elem->props[j];
+
+      if ( elem->store_prop[j] == OTHER_PROP )
+        elem_data = *other_ptr;
+      else
+        elem_data = ( char * ) elem_ptr;
+
+      if ( prop->is_list == PLY_LIST )
+      {
+        /* list */
+        item = elem_data + prop->count_offset;
+        get_stored_item ( ( void * ) item, prop->count_internal,
+        &int_val, &uint_val, &double_val );
+        write_ascii_item ( fp, int_val, uint_val, double_val,
+        prop->count_external );
+        list_count = uint_val;
+        item_ptr = ( char * *  ) ( elem_data + prop->offset );
+        item = item_ptr[0];
+        item_size = ply_type_size[prop->internal_type];
+        for ( k = 0; k < list_count; k++ )
+        {
+          get_stored_item ( ( void * ) item, prop->internal_type,
+          &int_val, &uint_val, &double_val );
+          write_ascii_item ( fp, int_val, uint_val, double_val,
+          prop->external_type );
+          item += item_size;
+        }
+      }
+      else if ( prop->is_list == PLY_STRING )
+      {
+        /* string */
+        char*  *str;
+        item = elem_data + prop->offset;
+        str = ( char * *  ) item;
+        fprintf ( fp, "\"%s\"", *str );
+      }
+      else
+      {
+        /* scalar */
+        item = elem_data + prop->offset;
+        get_stored_item ( ( void * ) item, prop->internal_type,
+        &int_val, &uint_val, &double_val );
+        write_ascii_item ( fp, int_val, uint_val, double_val,
+        prop->external_type );
+      }
+    }
+
+    fprintf ( fp, "\n" );
+  }
+  else
+  {
+    /* write a binary file */
+
+    /* write out each property of the element */
+    for ( j = 0; j < elem->nprops; j++ )
+    {
+      prop = elem->props[j];
+      if ( elem->store_prop[j] == OTHER_PROP )
+        elem_data = *other_ptr;
+      else
+        elem_data = ( char * ) elem_ptr;
+      if ( prop->is_list == PLY_LIST )
+      {
+        /* list */
+        item = elem_data + prop->count_offset;
+        item_size = ply_type_size[prop->count_internal];
+        get_stored_item ( ( void * ) item, prop->count_internal,
+        &int_val, &uint_val, &double_val );
+        write_binary_item ( fp, int_val, uint_val, double_val,
+        prop->count_external );
+        list_count = uint_val;
+        item_ptr = ( char * *  ) ( elem_data + prop->offset );
+        item = item_ptr[0];
+        item_size = ply_type_size[prop->internal_type];
+        for ( k = 0; k < list_count; k++ )
+        {
+          get_stored_item ( ( void * ) item, prop->internal_type,
+          &int_val, &uint_val, &double_val );
+          write_binary_item ( fp, int_val, uint_val, double_val,
+          prop->external_type );
+          item += item_size;
+        }
+      }
+      else if ( prop->is_list == PLY_STRING )
+      {
+        /* string */
+        int     len;
+        char*  *str;
+        item = elem_data + prop->offset;
+        str = ( char * *  ) item;
+
+        /* write the length */
+        len = (int)strlen( *str ) + 1;
+        fwrite ( &len, sizeof( int ), 1, fp );
+
+        /* write the string, including the null character */
+        fwrite ( *str, len, 1, fp );
+      }
+      else
+      {
+        /* scalar */
+        item = elem_data + prop->offset;
+        item_size = ply_type_size[prop->internal_type];
+        get_stored_item ( ( void * ) item, prop->internal_type,
+        &int_val, &uint_val, &double_val );
+        write_binary_item ( fp, int_val, uint_val, double_val,
+        prop->external_type );
+      }
+    }
+  }
+}
+
+
+
+
+
+
+/*************/
+/*  Reading  */
+/*************/
+
+
+
+/******************************************************************************
+Given a file pointer, get ready to read PLY data from the file.
+
+Entry:
+fp - the given file pointer
+
+Exit:
+nelems     - number of elements in object
+elem_names - list of element names
+returns a pointer to a PlyFile, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *ply_read( FILE *fp, int *nelems, char ***elem_names )
+{
+  int         i,j;
+  PlyFile    *plyfile;
+  int         nwords;
+  char*      *words;
+  int         found_format  = 0;
+  char*      *elist;
+  PlyElement *elem;
+  char       *orig_line;
+
+  /* check for NULL file pointer */
+  if ( fp == NULL )
+    return ( NULL );
+
+  /* create record for this object */
+
+  plyfile = ( PlyFile *  ) myalloc ( sizeof ( PlyFile ) );
+  plyfile->num_elem_types = 0;
+  plyfile->comments = NULL;
+  plyfile->num_comments = 0;
+  plyfile->obj_info = NULL;
+  plyfile->num_obj_info = 0;
+  plyfile->fp = fp;
+  plyfile->other_elems = NULL;
+  plyfile->rule_list = NULL;
+
+  /* read and parse the file's header */
+
+  words = get_words ( plyfile->fp, &nwords, &orig_line );
+  if ( !words || !equal_strings ( words[0], "ply" ) )
+    return ( NULL );
+
+  while ( words )
+  {
+    /* parse words */
+
+    if ( equal_strings ( words[0], "format" ) )
+    {
+      if ( nwords != 3 )
+        return ( NULL );
+      if ( equal_strings ( words[1], "ascii" ) )
+        plyfile->file_type = PLY_ASCII;
+      else if ( equal_strings ( words[1], "binary_big_endian" ) )
+        plyfile->file_type = PLY_BINARY_BE;
+      else if ( equal_strings ( words[1], "binary_little_endian" ) )
+        plyfile->file_type = PLY_BINARY_LE;
+      else
+        return ( NULL );
+      plyfile->version = ( float ) atof ( words[2] );
+      found_format = 1;
+    }
+    else if ( equal_strings ( words[0], "element" ) )
+      add_element ( plyfile, words, nwords );
+    else if ( equal_strings ( words[0], "property" ) )
+      add_property ( plyfile, words, nwords );
+    else if ( equal_strings ( words[0], "comment" ) )
+      add_comment ( plyfile, orig_line );
+    else if ( equal_strings ( words[0], "obj_info" ) )
+      add_obj_info ( plyfile, orig_line );
+    else if ( equal_strings ( words[0], "end_header" ) )
+      break;
+
+    /* free up words space */
+    free ( words );
+
+    words = get_words ( plyfile->fp, &nwords, &orig_line );
+  }
+
+  /* create tags for each property of each element, to be used */
+  /* later to say whether or not to store each property for the user */
+
+  for ( i = 0; i < plyfile->num_elem_types; i++ )
+  {
+    elem = plyfile->elems[i];
+    elem->store_prop = ( char * ) myalloc ( sizeof ( char ) * elem->nprops );
+    for ( j = 0; j < elem->nprops; j++ )
+      elem->store_prop[j] = DONT_STORE_PROP;
+    elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
+  }
+
+  /* set return values about the elements */
+
+  elist = ( char * *  ) myalloc ( sizeof ( char * ) * plyfile->num_elem_types );
+  for ( i = 0; i < plyfile->num_elem_types; i++ )
+    elist[i] = strdup ( plyfile->elems[i]->name );
+
+  *elem_names = elist;
+  *nelems = plyfile->num_elem_types;
+
+  /* return a pointer to the file's information */
+
+  return ( plyfile );
+}
+
+
+/******************************************************************************
+Open a polygon file for reading.
+
+Entry:
+filename - name of file to read from
+
+Exit:
+nelems     - number of elements in object
+elem_names - list of element names
+file_type  - file type, either ascii or binary
+version    - version number of PLY file
+returns a file identifier, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *ply_open_for_reading( const char *filename, int *nelems, char ***elem_names, int *file_type, float *version )
+{
+  FILE     *fp;
+  PlyFile  *plyfile;
+  char     *name;
+
+  /* tack on the extension .ply, if necessary */
+
+  name = ( char * ) myalloc ( sizeof ( char ) * ( (int)strlen ( filename ) + 5 ) );
+  strcpy ( name, filename );
+  if ( strlen ( name ) < 4 || strcmp ( name + strlen ( name ) - 4, ".ply" ) != 0 )
+    strcat ( name, ".ply" );
+
+  /* open the file for reading */
+
+  fp = fopen ( name, "r" );
+  if ( fp == NULL )
+    return ( NULL );
+
+  /* create the PlyFile data structure */
+
+  plyfile = ply_read ( fp, nelems, elem_names );
+
+  /* determine the file type and version */
+
+  *file_type = plyfile->file_type;
+  *version = plyfile->version;
+
+  /* return a pointer to the file's information */
+
+  return ( plyfile );
+}
+
+
+/******************************************************************************
+Get information about a particular element.
+
+Entry:
+plyfile   - file identifier
+elem_name - name of element to get information about
+
+Exit:
+nelems   - number of elements of this type in the file
+nprops   - number of properties
+returns a list of properties, or NULL if the file doesn't contain that elem
+******************************************************************************/
+
+PlyProperty **get_element_description_ply( PlyFile *plyfile, const char *elem_name, int *nelems, int *nprops )
+{
+  int             i;
+  PlyElement     *elem;
+  PlyProperty    *prop;
+  PlyProperty*   *prop_list;
+
+  /* find information about the element */
+  elem = find_element ( plyfile, elem_name );
+  if ( elem == NULL )
+    return ( NULL );
+
+  *nelems = elem->num;
+  *nprops = elem->nprops;
+
+  /* make a copy of the element's property list */
+  prop_list = ( PlyProperty *  *  ) myalloc ( sizeof ( PlyProperty *  ) * elem->nprops );
+  for ( i = 0; i < elem->nprops; i++ )
+  {
+    prop = ( PlyProperty *  ) myalloc ( sizeof ( PlyProperty ) );
+    copy_property ( prop, elem->props[i] );
+    prop_list[i] = prop;
+  }
+
+  /* return this duplicate property list */
+  return ( prop_list );
+}
+
+
+/******************************************************************************
+Specify which properties of an element are to be returned.  This should be
+called before a call to the routine get_element_ply().
+
+Entry:
+plyfile   - file identifier
+elem_name - which element we're talking about
+nprops    - number of properties
+prop_list - list of properties
+******************************************************************************/
+
+void get_element_setup_ply( PlyFile *plyfile, const char *elem_name, int nprops, PlyProperty *prop_list )
+{
+  int           i;
+  PlyElement   *elem;
+  PlyProperty  *prop;
+  int           index;
+
+  /* find information about the element */
+  elem = find_element ( plyfile, elem_name );
+  plyfile->which_elem = elem;
+
+  /* deposit the property information into the element's description */
+  for ( i = 0; i < nprops; i++ )
+  {
+    /* look for actual property */
+    prop = find_property ( elem, prop_list[i].name, &index );
+    if ( prop == NULL )
+    {
+      fprintf ( stderr, "Warning:  Can't find property '%s' in element '%s'\n",
+      prop_list[i].name, elem_name );
+      continue;
+    }
+
+    /* store its description */
+    prop->internal_type = prop_list[i].internal_type;
+    prop->offset = prop_list[i].offset;
+    prop->count_internal = prop_list[i].count_internal;
+    prop->count_offset = prop_list[i].count_offset;
+
+    /* specify that the user wants this property */
+    elem->store_prop[index] = STORE_PROP;
+  }
+}
+
+
+/******************************************************************************
+Specify a property of an element that is to be returned.  This should be
+called (usually multiple times) before a call to the routine ply_get_element().
+This routine should be used in preference to the less flexible old routine
+called ply_get_element_setup().
+
+Entry:
+plyfile   - file identifier
+elem_name - which element we're talking about
+prop      - property to add to those that will be returned
+******************************************************************************/
+
+void ply_get_property( PlyFile *plyfile, const char *elem_name, PlyProperty *prop )
+{
+  PlyElement   *elem;
+  PlyProperty  *prop_ptr;
+  int           index;
+
+  /* find information about the element */
+  elem = find_element ( plyfile, elem_name );
+  plyfile->which_elem = elem;
+
+  /* deposit the property information into the element's description */
+
+  prop_ptr = find_property ( elem, prop->name, &index );
+  if ( prop_ptr == NULL )
+  {
+    fprintf ( stderr, "Warning:  Can't find property '%s' in element '%s'\n",
+    prop->name, elem_name );
+    return;
+  }
+  prop_ptr->internal_type = prop->internal_type;
+  prop_ptr->offset = prop->offset;
+  prop_ptr->count_internal = prop->count_internal;
+  prop_ptr->count_offset = prop->count_offset;
+
+  /* specify that the user wants this property */
+  elem->store_prop[index] = STORE_PROP;
+}
+
+
+/******************************************************************************
+Read one element from the file.  This routine assumes that we're reading
+the type of element specified in the last call to the routine
+ply_get_element_setup().
+
+Entry:
+plyfile  - file identifier
+elem_ptr - pointer to location where the element information should be put
+******************************************************************************/
+
+void ply_get_element( PlyFile *plyfile, void *elem_ptr )
+{
+  if ( plyfile->file_type == PLY_ASCII )
+    ascii_get_element ( plyfile, ( char * ) elem_ptr );
+  else
+    binary_get_element ( plyfile, ( char * ) elem_ptr );
+}
+
+
+/******************************************************************************
+Extract the comments from the header information of a PLY file.
+
+Entry:
+plyfile - file identifier
+
+Exit:
+num_comments - number of comments returned
+returns a pointer to a list of comments
+******************************************************************************/
+
+char **get_comments_ply( PlyFile *plyfile, int *num_comments )
+{
+  *num_comments = plyfile->num_comments;
+  return ( plyfile->comments );
+}
+
+
+/******************************************************************************
+Extract the object information (arbitrary text) from the header information
+of a PLY file.
+
+Entry:
+plyfile - file identifier
+
+Exit:
+num_obj_info - number of lines of text information returned
+returns a pointer to a list of object info lines
+******************************************************************************/
+
+char **get_obj_info_ply( PlyFile *plyfile, int *num_obj_info )
+{
+  *num_obj_info = plyfile->num_obj_info;
+  return ( plyfile->obj_info );
+}
+
+
+/******************************************************************************
+ake ready for "other" properties of an element-- those properties that
+the user has not explicitly asked for, but that are to be stashed away
+in a special structure to be carried along with the element's other
+information.
+
+Entry:
+plyfile - file identifier
+elem    - element for which we want to save away other properties
+******************************************************************************/
+
+void setup_other_props( PlyFile *plyfile, PlyElement *elem )
+{
+  int           i;
+  PlyProperty  *prop;
+  int           size  = 0;
+  int           type_size;
+
+  /* Examine each property in decreasing order of size. */
+  /* We do this so that all data types will be aligned by */
+  /* word, half-word, or whatever within the structure. */
+
+  for ( type_size = 8; type_size > 0; type_size /= 2 )
+  {
+    /* add up the space taken by each property, and save this information */
+    /* away in the property descriptor */
+
+    for ( i = 0; i < elem->nprops; i++ )
+    {
+      /* don't bother with properties we've been asked to store explicitly */
+      if ( elem->store_prop[i] )
+        continue;
+
+      prop = elem->props[i];
+
+      /* internal types will be same as external */
+      prop->internal_type = prop->external_type;
+      prop->count_internal = prop->count_external;
+
+      /* list case */
+      if ( prop->is_list == PLY_LIST )
+      {
+        /* pointer to list */
+        if ( type_size == sizeof ( void * ) )
+        {
+          prop->offset = size;
+          size += sizeof ( void * );    /* always use size of a pointer here */
+        }
+
+        /* count of number of list elements */
+        if ( type_size == ply_type_size[prop->count_external] )
+        {
+          prop->count_offset = size;
+          size += ply_type_size[prop->count_external];
+        }
+      }
+      /* string */
+      else if ( prop->is_list == PLY_STRING )
+      {
+        /* pointer to string */
+        if ( type_size == sizeof ( char * ) )
+        {
+          prop->offset = size;
+          size += sizeof ( char * );
+        }
+      }
+      /* scalar */
+      else if ( type_size == ply_type_size[prop->external_type] )
+      {
+        prop->offset = size;
+        size += ply_type_size[prop->external_type];
+      }
+    }
+  }
+
+  /* save the size for the other_props structure */
+  elem->other_size = size;
+}
+
+
+/******************************************************************************
+Specify that we want the "other" properties of an element to be tucked
+away within the user's structure.
+
+Entry:
+plyfile - file identifier
+elem    - the element that we want to store other_props in
+offset  - offset to where other_props will be stored inside user's structure
+
+Exit:
+returns pointer to structure containing description of other_props
+******************************************************************************/
+
+static PlyOtherProp *get_other_properties( PlyFile *plyfile, PlyElement *elem, int offset )
+{
+  int           i;
+  PlyOtherProp *other;
+  PlyProperty  *prop;
+  int           nprops;
+
+  /* remember that this is the "current" element */
+  plyfile->which_elem = elem;
+
+  /* save the offset to where to store the other_props */
+  elem->other_offset = offset;
+
+  /* place the appropriate pointers, etc. in the element's property list */
+  setup_other_props ( plyfile, elem );
+
+  /* create structure for describing other_props */
+  other = ( PlyOtherProp *  ) myalloc ( sizeof ( PlyOtherProp ) );
+  other->name = strdup ( elem->name );
+#if 0
+if (elem->other_offset == NO_OTHER_PROPS) {
+other->size = 0;
+other->props = NULL;
+other->nprops = 0;
+return (other);
+}
+#endif
+  other->size = elem->other_size;
+  other->props = ( PlyProperty *  *  ) myalloc ( sizeof( PlyProperty ) * elem->nprops );
+
+  /* save descriptions of each "other" property */
+  nprops = 0;
+  for ( i = 0; i < elem->nprops; i++ )
+  {
+    if ( elem->store_prop[i] )
+      continue;
+    prop = ( PlyProperty *  ) myalloc ( sizeof ( PlyProperty ) );
+    copy_property ( prop, elem->props[i] );
+    other->props[nprops] = prop;
+    nprops++;
+  }
+  other->nprops = nprops;
+
+  /* set other_offset pointer appropriately if there are NO other properties */
+  if ( other->nprops == 0 )
+  {
+    elem->other_offset = NO_OTHER_PROPS;
+  }
+
+  /* return structure */
+  return ( other );
+}
+
+
+/******************************************************************************
+Specify that we want the "other" properties of an element to be tucked
+away within the user's structure.  The user needn't be concerned for how
+these properties are stored.
+
+Entry:
+plyfile   - file identifier
+elem_name - name of element that we want to store other_props in
+offset    - offset to where other_props will be stored inside user's structure
+
+Exit:
+returns pointer to structure containing description of other_props
+******************************************************************************/
+
+PlyOtherProp *ply_get_other_properties( PlyFile *plyfile, const char *elem_name, int offset )
+{
+  PlyElement   *elem;
+  PlyOtherProp *other;
+
+  /* find information about the element */
+  elem = find_element ( plyfile, elem_name );
+  if ( elem == NULL )
+  {
+    fprintf ( stderr, "ply_get_other_properties: Can't find element '%s'\n",
+    elem_name );
+    return ( NULL );
+  }
+
+  other = get_other_properties ( plyfile, elem, offset );
+  return ( other );
+}
+
+
+
+
+/*************************/
+/*  Other Element Stuff  */
+/*************************/
+
+
+
+
+
+/******************************************************************************
+Grab all the data for the current element that a user does not want to
+explicitly read in.  Stores this in the PLY object's data structure.
+
+Entry:
+plyfile - pointer to file
+
+Exit:
+returns pointer to ALL the "other" element data for this PLY file
+******************************************************************************/
+
+PlyOtherElems *get_other_element_ply( PlyFile *plyfile )
+{
+  int             i;
+  PlyElement     *elem;
+  char           *elem_name;
+  int             elem_count;
+  PlyOtherElems  *other_elems;
+  OtherElem      *other;
+
+  elem = plyfile->which_elem;
+  elem_name = elem->name;
+  elem_count = elem->num;
+
+  /* create room for the new "other" element, initializing the */
+  /* other data structure if necessary */
+
+  if ( plyfile->other_elems == NULL )
+  {
+    plyfile->other_elems = ( PlyOtherElems *  ) myalloc ( sizeof ( PlyOtherElems ) );
+    other_elems = plyfile->other_elems;
+    other_elems->other_list = ( OtherElem *  ) myalloc ( sizeof ( OtherElem ) );
+    other = &( other_elems->other_list[0] );
+    other_elems->num_elems = 1;
+  }
+  else
+  {
+    other_elems = plyfile->other_elems;
+    other_elems->other_list = ( OtherElem *  ) realloc ( other_elems->other_list,
+    sizeof ( OtherElem ) * other_elems->num_elems + 1 );
+    other = &( other_elems->other_list[other_elems->num_elems] );
+    other_elems->num_elems++;
+  }
+
+  /* count of element instances in file */
+  other->elem_count = elem_count;
+
+  /* save name of element */
+  other->elem_name = strdup ( elem_name );
+
+  /* create a list to hold all the current elements */
+  other->other_data = ( OtherData *  *  )
+  malloc ( sizeof ( OtherData *  ) * other->elem_count );
+
+  /* set up for getting elements */
+  other->other_props = ply_get_other_properties ( plyfile, elem_name,
+  offsetof( OtherData,other_props ) );
+
+  /* grab all these elements */
+  for ( i = 0; i < other->elem_count; i++ )
+  {
+    /* grab and element from the file */
+    other->other_data[i] = ( OtherData *  ) malloc ( sizeof ( OtherData ) );
+    ply_get_element ( plyfile, ( void * ) other->other_data[i] );
+  }
+
+  /* return pointer to the other elements data */
+  return ( other_elems );
+}
+
+
+/******************************************************************************
+Write out the "other" elements specified for this PLY file.
+
+Entry:
+plyfile - pointer to PLY file to write out other elements for
+******************************************************************************/
+
+void put_other_elements_ply( PlyFile *plyfile )
+{
+  int         i,j;
+  OtherElem  *other;
+
+  /* make sure we have other elements to write */
+  if ( plyfile->other_elems == NULL )
+    return;
+
+  /* write out the data for each "other" element */
+
+  for ( i = 0; i < plyfile->other_elems->num_elems; i++ )
+  {
+    other = &( plyfile->other_elems->other_list[i] );
+    put_element_setup_ply ( plyfile, other->elem_name );
+
+    /* write out each instance of the current element */
+    for ( j = 0; j < other->elem_count; j++ )
+      put_element_ply ( plyfile, ( void * ) other->other_data[j] );
+  }
+}
+
+
+/******************************************************************************
+Free up storage used by an "other" elements data structure.
+
+Entry:
+other_elems - data structure to free up
+******************************************************************************/
+
+void free_other_elements_ply( PlyOtherElems *other_elems )
+{
+}
+
+
+
+/*******************/
+/*  Miscellaneous  */
+/*******************/
+
+
+
+/******************************************************************************
+Close a PLY file.
+
+Entry:
+plyfile - identifier of file to close
+******************************************************************************/
+
+void ply_close( PlyFile *plyfile )
+{
+  fclose ( plyfile->fp );
+
+  /* free up memory associated with the PLY file */
+  free ( plyfile );
+}
+
+
+/******************************************************************************
+Get version number and file type of a PlyFile.
+
+Entry:
+ply - pointer to PLY file
+
+Exit:
+version - version of the file
+file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
+******************************************************************************/
+
+void get_info_ply( PlyFile *ply, float *version, int *file_type )
+{
+  if ( ply == NULL )
+    return;
+
+  *version = ply->version;
+  *file_type = ply->file_type;
+}
+
+
+/******************************************************************************
+Compare two strings.  Returns 1 if they are the same, 0 if not.
+******************************************************************************/
+
+int equal_strings( const char *s1, const char *s2 )
+{
+  while ( *s1 && *s2 )
+    if ( *s1++ != *s2++ )
+      return ( 0 );
+
+  if ( *s1 != *s2 )
+    return ( 0 );
+  else
+    return ( 1 );
+}
+
+
+/******************************************************************************
+Re-create the command line that was used to invoke this program.
+
+Entry:
+argc - number of words in argv
+argv - array of words in command line
+******************************************************************************/
+
+char *recreate_command_line( int argc, char *argv[] )
+{
+  int   i;
+  char *line;
+  int   len = 0;
+
+  /* count total number of characters needed, including separating spaces */
+  for ( i = 0; i < argc; i++ )
+    len += (int)strlen( argv[i] ) + 1;
+
+  /* create empty line */
+  line = ( char * ) malloc ( sizeof( char ) * len );
+  line[0] = '\0';
+
+  /* repeatedly append argv */
+  for ( i = 0; i < argc; i++ )
+  {
+    strcat ( line, argv[i] );
+    if ( i != argc - 1 )
+      strcat ( line, " " );
+  }
+
+  return ( line );
+}
+
+
+/******************************************************************************
+Find an element from the element list of a given PLY object.
+
+Entry:
+plyfile - file id for PLY file
+element - name of element we're looking for
+
+Exit:
+returns the element, or NULL if not found
+******************************************************************************/
+
+PlyElement *find_element( PlyFile *plyfile, const char *element )
+{
+  int i;
+
+  for ( i = 0; i < plyfile->num_elem_types; i++ )
+    if ( equal_strings ( element, plyfile->elems[i]->name ) )
+      return ( plyfile->elems[i] );
+
+  return ( NULL );
+}
+
+
+/******************************************************************************
+Find a property in the list of properties of a given element.
+
+Entry:
+elem      - pointer to element in which we want to find the property
+prop_name - name of property to find
+
+Exit:
+index - index to position in list
+returns a pointer to the property, or NULL if not found
+******************************************************************************/
+
+PlyProperty *find_property( PlyElement *elem, const char *prop_name, int *index )
+{
+  int i;
+
+  for ( i = 0; i < elem->nprops; i++ )
+    if ( equal_strings ( prop_name, elem->props[i]->name ) )
+    {
+      *index = i;
+      return ( elem->props[i] );
+    }
+
+  *index = -1;
+  return ( NULL );
+}
+
+
+/******************************************************************************
+Read an element from an ascii file.
+
+Entry:
+plyfile  - file identifier
+elem_ptr - pointer to element
+******************************************************************************/
+
+void ascii_get_element( PlyFile *plyfile, char *elem_ptr )
+{
+  int           j,k;
+  PlyElement   *elem=NULL;
+  PlyProperty  *prop=NULL;
+  char*        *words=NULL;
+  int           nwords;
+  int           which_word;
+  char         *elem_data=NULL,*item=NULL;
+  char         *item_ptr=NULL;
+  int           item_size;
+  int           int_val;
+  unsigned int uint_val;
+  double  double_val;
+  int     list_count;
+  int     store_it;
+  char*  *store_array=NULL;
+  char   *orig_line=NULL;
+  char   *other_data=NULL;
+  int     other_flag;
+
+  /* the kind of element we're reading currently */
+  elem = plyfile->which_elem;
+
+  /* do we need to setup for other_props? */
+
+  if ( elem->other_offset != NO_OTHER_PROPS )
+  {
+    char*  *ptr;
+    other_flag = 1;
+    /* make room for other_props */
+    other_data = ( char * ) myalloc ( elem->other_size );
+    /* store pointer in user's structure to the other_props */
+    ptr = ( char * *  ) ( elem_ptr + elem->other_offset );
+    *ptr = other_data;
+  }
+  else
+    other_flag = 0;
+
+  /* read in the element */
+
+  words = get_words ( plyfile->fp, &nwords, &orig_line );
+  if ( words == NULL )
+  {
+    fprintf ( stderr, "ply_get_element: unexpected end of file\n" );
+    exit ( -1 );
+  }
+
+  which_word = 0;
+
+  for ( j = 0; j < elem->nprops; j++ )
+  {
+    prop = elem->props[j];
+    store_it = ( elem->store_prop[j] | other_flag );
+
+    /* store either in the user's structure or in other_props */
+    if ( elem->store_prop[j] )
+      elem_data = elem_ptr;
+    else
+      elem_data = other_data;
+
+    if ( prop->is_list == PLY_LIST )
+    {
+      /* a list */
+
+      /* get and store the number of items in the list */
+      get_ascii_item ( words[which_word++], prop->count_external,
+      &int_val, &uint_val, &double_val );
+      if ( store_it )
+      {
+        item = elem_data + prop->count_offset;
+        store_item( item, prop->count_internal, int_val, uint_val, double_val );
+      }
+
+      /* allocate space for an array of items and store a ptr to the array */
+      list_count = int_val;
+      item_size = ply_type_size[prop->internal_type];
+      store_array = ( char * *  ) ( elem_data + prop->offset );
+
+      if ( list_count == 0 )
+      {
+        if ( store_it )
+          *store_array = NULL;
+      }
+      else
+      {
+        if ( store_it )
+        {
+          item_ptr = ( char * ) myalloc ( sizeof ( char ) * item_size * list_count );
+          item = item_ptr;
+          *store_array = item_ptr;
+        }
+
+        /* read items and store them into the array */
+        for ( k = 0; k < list_count; k++ )
+        {
+          get_ascii_item ( words[which_word++], prop->external_type,
+          &int_val, &uint_val, &double_val );
+          if ( store_it )
+          {
+            store_item ( item, prop->internal_type,
+            int_val, uint_val, double_val );
+            item += item_size;
+          }
+        }
+      }
+    }
+    else if ( prop->is_list == PLY_STRING )
+    {
+      /* a string */
+      if ( store_it )
+      {
+        char   *str;
+        char*  *str_ptr;
+        str = strdup ( words[which_word++] );
+        item = elem_data + prop->offset;
+        str_ptr = ( char * *  ) item;
+        *str_ptr = str;
+      }
+      else
+      {
+        which_word++;
+      }
+    }
+    else
+    {
+      /* a scalar */
+      get_ascii_item ( words[which_word++], prop->external_type,
+      &int_val, &uint_val, &double_val );
+      if ( store_it )
+      {
+        item = elem_data + prop->offset;
+        store_item ( item, prop->internal_type, int_val, uint_val, double_val );
+      }
+    }
+  }
+
+  free ( words );
+}
+
+
+/******************************************************************************
+Read an element from a binary file.
+
+Entry:
+plyfile  - file identifier
+elem_ptr - pointer to an element
+******************************************************************************/
+
+void binary_get_element( PlyFile *plyfile, char *elem_ptr )
+{
+  int           j,k;
+  PlyElement   *elem= NULL;
+  PlyProperty  *prop= NULL;
+  FILE         *fp  = plyfile->fp;
+  char         *elem_data;
+  char         *item = NULL;
+  char         *item_ptr= NULL;
+  int           item_size;
+  int           int_val;
+  unsigned int uint_val;
+  double  double_val;
+  int     list_count;
+  int     store_it;
+  char*  *store_array= NULL;
+  char   *other_data= NULL;
+  int     other_flag;
+
+  /* the kind of element we're reading currently */
+  elem = plyfile->which_elem;
+
+  /* do we need to setup for other_props? */
+
+  if ( elem->other_offset != NO_OTHER_PROPS )
+  {
+    char*  *ptr;
+    other_flag = 1;
+    /* make room for other_props */
+    other_data = ( char * ) myalloc ( elem->other_size );
+    /* store pointer in user's structure to the other_props */
+    ptr = ( char * *  ) ( elem_ptr + elem->other_offset );
+    *ptr = other_data;
+  }
+  else
+    other_flag = 0;
+
+  /* read in a number of elements */
+
+  for ( j = 0; j < elem->nprops; j++ )
+  {
+    prop = elem->props[j];
+    store_it = ( elem->store_prop[j] | other_flag );
+
+    /* store either in the user's structure or in other_props */
+    if ( elem->store_prop[j] )
+      elem_data = elem_ptr;
+    else
+      elem_data = other_data;
+
+    if ( prop->is_list == PLY_LIST )
+    {
+      /* list */
+
+      /* get and store the number of items in the list */
+      get_binary_item ( fp, prop->count_external,
+      &int_val, &uint_val, &double_val );
+      if ( store_it )
+      {
+        item = elem_data + prop->count_offset;
+        store_item( item, prop->count_internal, int_val, uint_val, double_val );
+      }
+
+      /* allocate space for an array of items and store a ptr to the array */
+      list_count = int_val;
+      item_size = ply_type_size[prop->internal_type];
+      store_array = ( char * *  ) ( elem_data + prop->offset );
+      if ( list_count == 0 )
+      {
+        if ( store_it )
+          *store_array = NULL;
+      }
+      else
+      {
+        if ( store_it )
+        {
+          item_ptr = ( char * ) myalloc ( sizeof ( char ) * item_size * list_count );
+          item = item_ptr;
+          *store_array = item_ptr;
+        }
+
+        /* read items and store them into the array */
+        for ( k = 0; k < list_count; k++ )
+        {
+          get_binary_item ( fp, prop->external_type,
+          &int_val, &uint_val, &double_val );
+          if ( store_it )
+          {
+            store_item ( item, prop->internal_type,
+            int_val, uint_val, double_val );
+            item += item_size;
+          }
+        }
+      }
+    }
+    else if ( prop->is_list == PLY_STRING )
+    {
+      /* string */
+      int   len;
+      char *str;
+      fread ( &len, sizeof( int ), 1, fp );
+      str = ( char * ) myalloc ( len );
+      fread ( str, len, 1, fp );
+      if ( store_it )
+      {
+        char*  *str_ptr;
+        item = elem_data + prop->offset;
+        str_ptr = ( char * *  ) item;
+        *str_ptr = str;
+      }
+    }
+    else
+    {
+      /* scalar */
+      get_binary_item ( fp, prop->external_type,
+      &int_val, &uint_val, &double_val );
+      if ( store_it )
+      {
+        item = elem_data + prop->offset;
+        store_item ( item, prop->internal_type, int_val, uint_val, double_val );
+      }
+    }
+  }
+}
+
+
+/******************************************************************************
+Write to a file the word that represents a PLY data type.
+
+Entry:
+fp   - file pointer
+code - code for type
+******************************************************************************/
+
+void write_scalar_type( FILE *fp, int code )
+{
+  /* make sure this is a valid code */
+
+  if ( code <= StartType || code >= EndType )
+  {
+    fprintf ( stderr, "write_scalar_type: bad data code = %d\n", code );
+    exit ( -1 );
+  }
+
+  /* write the code to a file */
+
+  fprintf ( fp, "%s", type_names[code] );
+}
+
+
+/******************************************************************************
+Get a text line from a file and break it up into words.
+
+IMPORTANT: The calling routine should call "free" on the returned pointer once
+finished with it.
+
+Entry:
+fp - file to read from
+
+Exit:
+nwords    - number of words returned
+orig_line - the original line of characters
+returns a list of words from the line, or NULL if end-of-file
+******************************************************************************/
+
+char **get_words( FILE *fp, int *nwords, char **orig_line )
+{
+#define BIG_STRING 4096
+  static char str[BIG_STRING];
+  static char str_copy[BIG_STRING];
+  char*      *words;
+  int         max_words = 10;
+  int         num_words = 0;
+  char       *ptr,*ptr2;
+  char       *result;
+
+  words = ( char * *  ) myalloc ( sizeof ( char * ) * max_words );
+
+  /* read in a line */
+  result = fgets ( str, BIG_STRING, fp );
+  if ( result == NULL )
+  {
+    *nwords = 0;
+    *orig_line = NULL;
+    return ( NULL );
+  }
+
+  /* convert line-feed and tabs into spaces */
+  /* (this guarentees that there will be a space before the */
+  /*  null character at the end of the string) */
+
+  str[BIG_STRING - 2] = ' ';
+  str[BIG_STRING - 1] = '\0';
+
+  for ( ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++ )
+  {
+    *ptr2 = *ptr;
+    if ( *ptr == '\t' )
+    {
+      *ptr = ' ';
+      *ptr2 = ' ';
+    }
+    else if ( *ptr == '\n' )
+    {
+      *ptr = ' ';
+      *ptr2 = ' ';
+      break;
+    }
+    else if ( *ptr == '\r' )
+    {
+      *ptr = ' ';
+      *ptr2 = '\0';
+    }
+  }
+
+  /* find the words in the line */
+
+  ptr = str;
+  while ( *ptr != '\0' )
+  {
+    /* jump over leading spaces */
+    while ( *ptr == ' ' )
+      ptr++;
+
+    /* break if we reach the end */
+    if ( *ptr == '\0' )
+      break;
+
+    /* allocate more room for words if necessary */
+    if ( num_words >= max_words )
+    {
+      max_words += 10;
+      words = ( char * *  ) realloc ( words, sizeof ( char * ) * max_words );
+    }
+
+    if ( *ptr == '\"' )
+    {
+      /* a quote indidicates that we have a string */
+
+      /* skip over leading quote */
+      ptr++;
+
+      /* save pointer to beginning of word */
+      words[num_words++] = ptr;
+
+      /* find trailing quote or end of line */
+      while ( *ptr != '\"' && *ptr != '\0' )
+        ptr++;
+
+      /* replace quote with a null character to mark the end of the word */
+      /* if we are not already at the end of the line */
+      if ( *ptr != '\0' )
+        *ptr++ = '\0';
+    }
+    else
+    {
+      /* non-string */
+
+      /* save pointer to beginning of word */
+      words[num_words++] = ptr;
+
+      /* jump over non-spaces */
+      while ( *ptr != ' ' )
+        ptr++;
+
+      /* place a null character here to mark the end of the word */
+      *ptr++ = '\0';
+    }
+  }
+
+  /* return the list of words */
+  *nwords = num_words;
+  *orig_line = str_copy;
+  return ( words );
+}
+
+
+/******************************************************************************
+Return the value of an item, given a pointer to it and its type.
+
+Entry:
+item - pointer to item
+type - data type that "item" points to
+
+Exit:
+returns a double-precision float that contains the value of the item
+******************************************************************************/
+
+double get_item_value( const char *item, int type )
+{
+  unsigned char *puchar;
+  char       *pchar;
+  short int  *pshort;
+  unsigned short int *pushort;
+  int  *pint;
+  unsigned int *puint;
+  float  *pfloat;
+  double *pdouble;
+  int     int_value;
+  unsigned int uint_value;
+  double  double_value;
+
+  switch ( type )
+  {
+    case Int8:
+      pchar = ( char * ) item;
+      int_value = *pchar;
+      return ( ( double ) int_value );
+    case Uint8:
+      puchar = ( unsigned char * ) item;
+      int_value = *puchar;
+      return ( ( double ) int_value );
+    case Int16:
+      pshort = ( short int * ) item;
+      int_value = *pshort;
+      return ( ( double ) int_value );
+    case Uint16:
+      pushort = ( unsigned short int * ) item;
+      int_value = *pushort;
+      return ( ( double ) int_value );
+    case Int32:
+      pint = ( int * ) item;
+      int_value = *pint;
+      return ( ( double ) int_value );
+    case Uint32:
+      puint = ( unsigned int * ) item;
+      uint_value = *puint;
+      return ( ( double ) uint_value );
+    case Float32:
+      pfloat = ( float * ) item;
+      double_value = *pfloat;
+      return ( double_value );
+    case Float64:
+      pdouble = ( double * ) item;
+      double_value = *pdouble;
+      return ( double_value );
+    default:
+      fprintf ( stderr, "get_item_value: bad type = %d\n", type );
+      exit ( -1 );
+  }
+
+  return ( 0.0 );  /* never actually gets here */
+}
+
+
+/******************************************************************************
+Write out an item to a file as raw binary bytes.
+
+Entry:
+fp         - file to write to
+int_val    - integer version of item
+uint_val   - unsigned integer version of item
+double_val - double-precision float version of item
+type       - data type to write out
+******************************************************************************/
+
+void write_binary_item( FILE *fp, int int_val, unsigned int uint_val, double double_val, int type )
+{
+  unsigned char uchar_val;
+  char  char_val;
+  unsigned short ushort_val;
+  short short_val;
+  float float_val;
+
+  switch ( type )
+  {
+    case Int8:
+      char_val = int_val;
+      fwrite ( &char_val, 1, 1, fp );
+      break;
+    case Int16:
+      short_val = int_val;
+      fwrite ( &short_val, 2, 1, fp );
+      break;
+    case Int32:
+      fwrite ( &int_val, 4, 1, fp );
+      break;
+    case Uint8:
+      uchar_val = uint_val;
+      fwrite ( &uchar_val, 1, 1, fp );
+      break;
+    case Uint16:
+      ushort_val = uint_val;
+      fwrite ( &ushort_val, 2, 1, fp );
+      break;
+    case Uint32:
+      fwrite ( &uint_val, 4, 1, fp );
+      break;
+    case Float32:
+      float_val = ( float ) double_val;
+      fwrite ( &float_val, 4, 1, fp );
+      break;
+    case Float64:
+      fwrite ( &double_val, 8, 1, fp );
+      break;
+    default:
+      fprintf ( stderr, "write_binary_item: bad type = %d\n", type );
+      exit ( -1 );
+  }
+}
+
+
+/******************************************************************************
+Write out an item to a file as ascii characters.
+
+Entry:
+fp         - file to write to
+int_val    - integer version of item
+uint_val   - unsigned integer version of item
+double_val - double-precision float version of item
+type       - data type to write out
+******************************************************************************/
+
+void write_ascii_item( FILE *fp, int int_val, unsigned int uint_val, double double_val, int type )
+{
+  switch ( type )
+  {
+    case Int8:
+    case Int16:
+    case Int32:
+      fprintf ( fp, "%d ", int_val );
+      break;
+    case Uint8:
+    case Uint16:
+    case Uint32:
+      fprintf ( fp, "%u ", uint_val );
+      break;
+    case Float32:
+    case Float64:
+      fprintf ( fp, "%12f ", double_val );
+      break;
+    default:
+      fprintf ( stderr, "write_ascii_item: bad type = %d\n", type );
+      exit ( -1 );
+  }
+}
+
+
+/******************************************************************************
+Get the value of an item that is in memory, and place the result
+into an integer, an unsigned integer and a double.
+
+Entry:
+ptr  - pointer to the item
+type - data type supposedly in the item
+
+Exit:
+int_val    - integer value
+uint_val   - unsigned integer value
+double_val - double-precision floating point value
+******************************************************************************/
+
+void get_stored_item( void *ptr, int type, int *int_val, unsigned int *uint_val, double *double_val )
+{
+  switch ( type )
+  {
+    case Int8:
+      *int_val = *( ( char * ) ptr );
+      *uint_val = *int_val;
+      *double_val = *int_val;
+      break;
+    case Uint8:
+      *uint_val = *( ( unsigned char * ) ptr );
+      *int_val = *uint_val;
+      *double_val = *uint_val;
+      break;
+    case Int16:
+      *int_val = *( ( short int * ) ptr );
+      *uint_val = *int_val;
+      *double_val = *int_val;
+      break;
+    case Uint16:
+      *uint_val = *( ( unsigned short int * ) ptr );
+      *int_val = *uint_val;
+      *double_val = *uint_val;
+      break;
+    case Int32:
+      *int_val = *( ( int * ) ptr );
+      *uint_val = *int_val;
+      *double_val = *int_val;
+      break;
+    case Uint32:
+      *uint_val = *( ( unsigned int * ) ptr );
+      *int_val = *uint_val;
+      *double_val = *uint_val;
+      break;
+    case Float32:
+      *double_val = *( ( float * ) ptr );
+      *int_val = ( int ) *double_val;
+      *uint_val = ( unsigned int ) *double_val;
+      break;
+    case Float64:
+      *double_val = *( ( double * ) ptr );
+      *int_val = ( int ) *double_val;
+      *uint_val = ( unsigned int ) *double_val;
+      break;
+    default:
+      fprintf ( stderr, "get_stored_item: bad type = %d\n", type );
+      exit ( -1 );
+  }
+}
+
+
+/******************************************************************************
+Get the value of an item from a binary file, and place the result
+into an integer, an unsigned integer and a double.
+
+Entry:
+fp   - file to get item from
+type - data type supposedly in the word
+
+Exit:
+int_val    - integer value
+uint_val   - unsigned integer value
+double_val - double-precision floating point value
+******************************************************************************/
+
+void get_binary_item( FILE *fp, int type, int *int_val, unsigned int *uint_val, double *double_val )
+{
+  char  c[8];
+  void *ptr;
+
+  ptr = ( void * ) c;
+
+  switch ( type )
+  {
+    case Int8:
+      fread ( ptr, 1, 1, fp );
+      *int_val = *( ( char * ) ptr );
+      *uint_val = *int_val;
+      *double_val = *int_val;
+      break;
+    case Uint8:
+      fread ( ptr, 1, 1, fp );
+      *uint_val = *( ( unsigned char * ) ptr );
+      *int_val = *uint_val;
+      *double_val = *uint_val;
+      break;
+    case Int16:
+      fread ( ptr, 2, 1, fp );
+      *int_val = *( ( short int * ) ptr );
+      *uint_val = *int_val;
+      *double_val = *int_val;
+      break;
+    case Uint16:
+      fread ( ptr, 2, 1, fp );
+      *uint_val = *( ( unsigned short int * ) ptr );
+      *int_val = *uint_val;
+      *double_val = *uint_val;
+      break;
+    case Int32:
+      fread ( ptr, 4, 1, fp );
+      *int_val = *( ( int * ) ptr );
+      *uint_val = *int_val;
+      *double_val = *int_val;
+      break;
+    case Uint32:
+      fread ( ptr, 4, 1, fp );
+      *uint_val = *( ( unsigned int * ) ptr );
+      *int_val = *uint_val;
+      *double_val = *uint_val;
+      break;
+    case Float32:
+      fread ( ptr, 4, 1, fp );
+      *double_val = *( ( float * ) ptr );
+      *int_val = ( int ) *double_val;
+      *uint_val = ( unsigned int ) *double_val;
+      break;
+    case Float64:
+      fread ( ptr, 8, 1, fp );
+      *double_val = *( ( double * ) ptr );
+      *int_val = ( int ) *double_val;
+      *uint_val = ( unsigned int ) *double_val;
+      break;
+    default:
+      fprintf ( stderr, "get_binary_item: bad type = %d\n", type );
+      exit ( -1 );
+  }
+}
+
+
+/******************************************************************************
+Extract the value of an item from an ascii word, and place the result
+into an integer, an unsigned integer and a double.
+
+Entry:
+word - word to extract value from
+type - data type supposedly in the word
+
+Exit:
+int_val    - integer value
+uint_val   - unsigned integer value
+double_val - double-precision floating point value
+******************************************************************************/
+
+void get_ascii_item( const char *word, int type, int *int_val, unsigned int *uint_val, double *double_val )
+{
+  switch ( type )
+  {
+    case Int8:
+    case Uint8:
+    case Int16:
+    case Uint16:
+    case Int32:
+      *int_val = atoi ( word );
+      *uint_val = *int_val;
+      *double_val = *int_val;
+      break;
+
+    case Uint32:
+      *uint_val = strtoul ( word, ( char * *  ) NULL, 10 );
+      *int_val = *uint_val;
+      *double_val = *uint_val;
+      break;
+
+    case Float32:
+    case Float64:
+      *double_val = atof ( word );
+      *int_val = ( int ) *double_val;
+      *uint_val = ( unsigned int ) *double_val;
+      break;
+
+    default:
+      fprintf ( stderr, "get_ascii_item: bad type = %d\n", type );
+      exit ( -1 );
+  }
+}
+
+
+/******************************************************************************
+Store a value into a place being pointed to, guided by a data type.
+
+Entry:
+item       - place to store value
+type       - data type
+int_val    - integer version of value
+uint_val   - unsigned integer version of value
+double_val - double version of value
+
+Exit:
+item - pointer to stored value
+******************************************************************************/
+
+void store_item( char *item, int type, int int_val, unsigned int uint_val, double double_val )
+{
+  unsigned char *puchar;
+  short int  *pshort;
+  unsigned short int *pushort;
+  int  *pint;
+  unsigned int *puint;
+  float  *pfloat;
+  double *pdouble;
+
+  switch ( type )
+  {
+    case Int8:
+      *item = int_val;
+      break;
+    case Uint8:
+      puchar = ( unsigned char * ) item;
+      *puchar = uint_val;
+      break;
+    case Int16:
+      pshort = ( short * ) item;
+      *pshort = int_val;
+      break;
+    case Uint16:
+      pushort = ( unsigned short * ) item;
+      *pushort = uint_val;
+      break;
+    case Int32:
+      pint = ( int * ) item;
+      *pint = int_val;
+      break;
+    case Uint32:
+      puint = ( unsigned int * ) item;
+      *puint = uint_val;
+      break;
+    case Float32:
+      pfloat = ( float * ) item;
+      *pfloat = ( float ) double_val;
+      break;
+    case Float64:
+      pdouble = ( double * ) item;
+      *pdouble = double_val;
+      break;
+    default:
+      fprintf ( stderr, "store_item: bad type = %d\n", type );
+      exit ( -1 );
+  }
+}
+
+
+/******************************************************************************
+Add an element to a PLY file descriptor.
+
+Entry:
+plyfile - PLY file descriptor
+words   - list of words describing the element
+nwords  - number of words in the list
+******************************************************************************/
+
+void add_element( PlyFile *plyfile, char **words, int nwords )
+{
+  PlyElement *elem;
+
+  /* create the new element */
+  elem = ( PlyElement *  ) myalloc ( sizeof ( PlyElement ) );
+  elem->name = strdup ( words[1] );
+  elem->num = atoi ( words[2] );
+  elem->nprops = 0;
+
+  /* make room for new element in the object's list of elements */
+  if ( plyfile->num_elem_types == 0 )
+    plyfile->elems = ( PlyElement *  *  ) myalloc ( sizeof ( PlyElement *  ) );
+  else
+    plyfile->elems = ( PlyElement *  *  ) realloc ( plyfile->elems,
+    sizeof ( PlyElement *  ) * ( plyfile->num_elem_types + 1 ) );
+
+  /* add the new element to the object's list */
+  plyfile->elems[plyfile->num_elem_types] = elem;
+  plyfile->num_elem_types++;
+}
+
+
+/******************************************************************************
+Return the type of a property, given the name of the property.
+
+Entry:
+name - name of property type
+
+Exit:
+returns integer code for property, or 0 if not found
+******************************************************************************/
+
+int get_prop_type( const char *type_name )
+{
+  int i;
+
+  /* try to match the type name */
+  for ( i = StartType + 1; i < EndType; i++ )
+    if ( equal_strings ( type_name, type_names[i] ) )
+      return ( i );
+
+  /* see if we can match an old type name */
+  for ( i = StartType + 1; i < EndType; i++ )
+    if ( equal_strings ( type_name, old_type_names[i] ) )
+      return ( i );
+
+  /* if we get here, we didn't find the type */
+  return ( 0 );
+}
+
+
+/******************************************************************************
+Add a property to a PLY file descriptor.
+
+Entry:
+plyfile - PLY file descriptor
+words   - list of words describing the property
+nwords  - number of words in the list
+******************************************************************************/
+
+void add_property( PlyFile *plyfile, char **words, int nwords )
+{
+  PlyProperty  *prop;
+  PlyElement   *elem;
+
+  /* create the new property */
+
+  prop = ( PlyProperty *  ) myalloc ( sizeof ( PlyProperty ) );
+
+  if ( equal_strings ( words[1], "list" ) )
+  {
+    /* list */
+    prop->count_external = get_prop_type ( words[2] );
+    prop->external_type = get_prop_type ( words[3] );
+    prop->name = strdup ( words[4] );
+    prop->is_list = PLY_LIST;
+  }
+  else if ( equal_strings ( words[1], "string" ) )
+  {
+    /* string */
+    prop->count_external = Int8;
+    prop->external_type = Int8;
+    prop->name = strdup ( words[2] );
+    prop->is_list = PLY_STRING;
+  }
+  else
+  {
+    /* scalar */
+    prop->external_type = get_prop_type ( words[1] );
+    prop->name = strdup ( words[2] );
+    prop->is_list = PLY_SCALAR;
+  }
+
+  /* add this property to the list of properties of the current element */
+
+  elem = plyfile->elems[plyfile->num_elem_types - 1];
+
+  if ( elem->nprops == 0 )
+    elem->props = ( PlyProperty *  *  ) myalloc ( sizeof ( PlyProperty *  ) );
+  else
+    elem->props = ( PlyProperty *  *  ) realloc ( elem->props,
+    sizeof ( PlyProperty *  ) * ( elem->nprops + 1 ) );
+
+  elem->props[elem->nprops] = prop;
+  elem->nprops++;
+}
+
+
+/******************************************************************************
+Add a comment to a PLY file descriptor.
+
+Entry:
+plyfile - PLY file descriptor
+line    - line containing comment
+******************************************************************************/
+
+void add_comment( PlyFile *plyfile, const char *line )
+{
+  int i;
+
+  /* skip over "comment" and leading spaces and tabs */
+  i = 7;
+  while ( line[i] == ' ' || line[i] == '\t' )
+    i++;
+
+  append_comment_ply ( plyfile, &line[i] );
+}
+
+
+/******************************************************************************
+Add a some object information to a PLY file descriptor.
+
+Entry:
+plyfile - PLY file descriptor
+line    - line containing text info
+******************************************************************************/
+
+void add_obj_info( PlyFile *plyfile, const char *line )
+{
+  int i;
+
+  /* skip over "obj_info" and leading spaces and tabs */
+  i = 8;
+  while ( line[i] == ' ' || line[i] == '\t' )
+    i++;
+
+  append_obj_info_ply ( plyfile, &line[i] );
+}
+
+
+/******************************************************************************
+Copy a property.
+******************************************************************************/
+
+void copy_property( PlyProperty *dest, PlyProperty *src )
+{
+  dest->name = strdup ( src->name );
+  dest->external_type = src->external_type;
+  dest->internal_type = src->internal_type;
+  dest->offset = src->offset;
+
+  dest->is_list = src->is_list;
+  dest->count_external = src->count_external;
+  dest->count_internal = src->count_internal;
+  dest->count_offset = src->count_offset;
+}
+
+
+/******************************************************************************
+Allocate some memory.
+
+Entry:
+size  - amount of memory requested (in bytes)
+lnum  - line number from which memory was requested
+fname - file name from which memory was requested
+******************************************************************************/
+
+static char *my_alloc( int size, int lnum, const char *fname )
+{
+  char *ptr;
+
+  ptr = ( char * ) malloc ( size );
+
+  if ( ptr == 0 )
+  {
+    fprintf( stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname );
+  }
+
+  return ( ptr );
+}
+
+
+/**** NEW STUFF ****/
+/**** NEW STUFF ****/
+/**** NEW STUFF ****/
+/**** NEW STUFF ****/
+
+
+
+/******************************************************************************
+Given a file pointer, get ready to read PLY data from the file.
+
+Entry:
+fp - the given file pointer
+
+Exit:
+nelems     - number of elements in object
+elem_names - list of element names
+returns a pointer to a PlyFile, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *read_ply( FILE *fp )
+{
+  PlyFile  *ply;
+  int       num_elems;
+  char*    *elem_names;
+
+  ply = ply_read ( fp, &num_elems, &elem_names );
+
+  return ( ply );
+}
+
+
+/******************************************************************************
+Given a file pointer, get ready to write PLY data to the file.
+
+Entry:
+fp         - the given file pointer
+nelems     - number of elements in object
+elem_names - list of element names
+file_type  - file type, either ascii or binary
+
+Exit:
+returns a pointer to a PlyFile, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *write_ply( FILE *fp, int nelems, char **elem_names, int file_type )
+{
+  PlyFile  *ply;
+
+  ply = ply_write ( fp, nelems, elem_names, file_type );
+
+  return ( ply );
+}
+
+
+/******************************************************************************
+Return a list of the names of the elements in a particular PLY file.
+
+Entry:
+ply - PLY file whose element name list we want
+
+Exit:
+num_elems  - the number of element names in the list
+returns the list of names
+******************************************************************************/
+
+char **get_element_list_ply( PlyFile *ply, int *num_elems )
+{
+  int     i;
+  char*  *elist;
+
+  /* create the list of element names */
+
+  elist = ( char * *  ) myalloc ( sizeof ( char * ) * ply->num_elem_types );
+  for ( i = 0; i < ply->num_elem_types; i++ )
+    elist[i] = strdup ( ply->elems[i]->name );
+
+  /* return the number of elements and the list of element names */
+  *num_elems = ply->num_elem_types;
+  return ( elist );
+}
+
+
+/******************************************************************************
+Append a comment to a PLY file.
+
+Entry:
+ply     - file to append comment to
+comment - the comment to append
+******************************************************************************/
+
+void append_comment_ply( PlyFile *ply, const char *comment )
+{
+  /* (re)allocate space for new comment */
+  if ( ply->num_comments == 0 )
+    ply->comments = ( char * *  ) myalloc ( sizeof ( char * ) );
+  else
+    ply->comments = ( char * *  ) realloc ( ply->comments,
+    sizeof ( char * ) * ( ply->num_comments + 1 ) );
+
+  /* add comment to list */
+  ply->comments[ply->num_comments] = strdup ( comment );
+  ply->num_comments++;
+}
+
+
+/******************************************************************************
+Copy the comments from one PLY file to another.
+
+Entry:
+out_ply - destination file to copy comments to
+in_ply  - the source of the comments
+******************************************************************************/
+
+void copy_comments_ply( PlyFile *out_ply, PlyFile *in_ply )
+{
+  int i;
+
+  for ( i = 0; i < in_ply->num_comments; i++ )
+    append_comment_ply ( out_ply, in_ply->comments[i] );
+}
+
+
+/******************************************************************************
+Append object information (arbitrary text) to a PLY file.
+
+Entry:
+ply      - file to append object info to
+obj_info - the object info to append
+******************************************************************************/
+
+void append_obj_info_ply( PlyFile *ply, const char *obj_info )
+{
+  /* (re)allocate space for new info */
+  if ( ply->num_obj_info == 0 )
+    ply->obj_info = ( char * *  ) myalloc ( sizeof ( char * ) );
+  else
+    ply->obj_info = ( char * *  ) realloc ( ply->obj_info,
+    sizeof ( char * ) * ( ply->num_obj_info + 1 ) );
+
+  /* add info to list */
+  ply->obj_info[ply->num_obj_info] = strdup ( obj_info );
+  ply->num_obj_info++;
+}
+
+
+/******************************************************************************
+Copy the object information from one PLY file to another.
+
+Entry:
+out_ply - destination file to copy object information to
+in_ply  - the source of the object information
+******************************************************************************/
+
+void copy_obj_info_ply( PlyFile *out_ply, PlyFile *in_ply )
+{
+  int i;
+
+  for ( i = 0; i < in_ply->num_obj_info; i++ )
+    append_obj_info_ply ( out_ply, in_ply->obj_info[i] );
+}
+
+
+/******************************************************************************
+Close a PLY file.
+
+Entry:
+plyfile - identifier of file to close
+******************************************************************************/
+
+void close_ply( PlyFile *plyfile )
+{
+  fclose ( plyfile->fp );
+}
+
+
+/******************************************************************************
+Free the memory used by a PLY file.
+
+Entry:
+plyfile - identifier of file
+******************************************************************************/
+
+void free_ply( PlyFile *plyfile )
+{
+  /* free up memory associated with the PLY file */
+  free ( plyfile );
+}
+
+
+/******************************************************************************
+Specify the index of the next element to be read in from a PLY file.
+
+Entry:
+ply - file to read from
+index - index of the element to be read
+
+Exit:
+elem_count - the number of elements in the file
+returns pointer to the name of this next element
+******************************************************************************/
+
+char *setup_element_read_ply( PlyFile *ply, int index, int *elem_count )
+{
+  PlyElement *elem;
+
+  if ( index < 0 || index > ply->num_elem_types )
+  {
+    fprintf ( stderr, "Warning:  No element with index %d\n", index );
+    return ( 0 );
+  }
+
+  elem = ply->elems[index];
+
+  /* set this to be the current element */
+  ply->which_elem = elem;
+
+  /* return the number of such elements in the file and the element's name */
+  *elem_count = elem->num;
+  return ( elem->name );
+}
+
+
+/******************************************************************************
+Read one element from the file.  This routine assumes that we're reading
+the type of element specified in the last call to the routine
+setup_element_read_ply().
+
+Entry:
+plyfile  - file identifier
+elem_ptr - pointer to location where the element information should be put
+******************************************************************************/
+
+void get_element_ply( PlyFile *plyfile, void *elem_ptr )
+{
+  if ( plyfile->file_type == PLY_ASCII )
+    ascii_get_element ( plyfile, ( char * ) elem_ptr );
+  else
+    binary_get_element ( plyfile, ( char * ) elem_ptr );
+}
+
+
+/******************************************************************************
+Specify one of several properties of the current element that is to be
+read from a file.  This should be called (usually multiple times) before a
+call to the routine get_element_ply().
+
+Entry:
+plyfile - file identifier
+prop    - property to add to those that will be returned
+
+Exit:
+0 if the property has not been found
+1 if the property has been found
+******************************************************************************/
+
+int setup_property_ply( PlyFile *plyfile, PlyProperty *prop )
+{
+  PlyElement   *elem;
+  PlyProperty  *prop_ptr;
+  int           index;
+
+  elem = plyfile->which_elem;
+
+  /* deposit the property information into the element's description */
+
+  prop_ptr = find_property ( elem, prop->name, &index );
+  if ( prop_ptr == NULL )
+  {
+    fprintf ( stderr, "Warning:  Can't find property '%s' in element '%s'\n",
+    prop->name, elem->name );
+    return 0;
+  }
+  prop_ptr->internal_type = prop->internal_type;
+  prop_ptr->offset = prop->offset;
+  prop_ptr->count_internal = prop->count_internal;
+  prop_ptr->count_offset = prop->count_offset;
+
+  /* specify that the user wants this property */
+  elem->store_prop[index] = STORE_PROP;
+  return 1 ;
+}
+
+
+/******************************************************************************
+Specify that we want the "other" properties of the current element to be tucked
+away within the user's structure.
+
+Entry:
+plyfile - file identifier
+offset  - offset to where other_props will be stored inside user's structure
+
+Exit:
+returns pointer to structure containing description of other_props
+******************************************************************************/
+
+PlyOtherProp *get_other_properties_ply( PlyFile *plyfile, int offset )
+{
+  PlyOtherProp *other;
+
+  other = get_other_properties ( plyfile, plyfile->which_elem, offset );
+  return ( other );
+}
+
+
+/******************************************************************************
+Describe which element is to be written next and state how many of them will
+be written.
+
+Entry:
+plyfile   - file identifier
+elem_name - name of element that information is being described
+nelems    - number of elements of this type to be written
+******************************************************************************/
+
+void describe_element_ply( PlyFile *plyfile, char *elem_name, int nelems )
+{
+  PlyElement *elem;
+
+  /* look for appropriate element */
+  elem = find_element ( plyfile, elem_name );
+  if ( elem == NULL )
+  {
+    fprintf( stderr,"describe_element_ply: can't find element '%s'\n",elem_name );
+    exit ( -1 );
+  }
+
+  elem->num = nelems;
+
+  /* now this element is the current element */
+  plyfile->which_elem = elem;
+}
+
+
+/******************************************************************************
+Describe a property of an element.
+
+Entry:
+plyfile   - file identifier
+prop      - the new property
+******************************************************************************/
+
+void describe_property_ply( PlyFile *plyfile, PlyProperty *prop )
+{
+  PlyElement   *elem;
+  PlyProperty  *elem_prop;
+
+  elem = plyfile->which_elem;
+
+  /* create room for new property */
+
+  if ( elem->nprops == 0 )
+  {
+    elem->props = ( PlyProperty *  *  ) myalloc ( sizeof ( PlyProperty *  ) );
+    elem->store_prop = ( char * ) myalloc ( sizeof ( char ) );
+    elem->nprops = 1;
+  }
+  else
+  {
+    elem->nprops++;
+    elem->props = ( PlyProperty *  *  )
+    realloc ( elem->props, sizeof ( PlyProperty *  ) * elem->nprops );
+    elem->store_prop = ( char * )
+    realloc ( elem->store_prop, sizeof ( char ) * elem->nprops );
+  }
+
+  /* copy the new property */
+
+  elem_prop = ( PlyProperty *  ) myalloc ( sizeof ( PlyProperty ) );
+  elem->props[elem->nprops - 1] = elem_prop;
+  elem->store_prop[elem->nprops - 1] = NAMED_PROP;
+  copy_property ( elem_prop, prop );
+}
+
+
+/******************************************************************************
+Describe what the "other" properties are that are to be stored, and where
+they are in an element.
+******************************************************************************/
+
+void describe_other_properties_ply( PlyFile *plyfile, PlyOtherProp *other, int offset )
+{
+  int           i;
+  PlyElement   *elem;
+  PlyProperty  *prop;
+
+  /* look for appropriate element */
+  elem = find_element ( plyfile, other->name );
+  if ( elem == NULL )
+  {
+    fprintf( stderr, "describe_other_properties_ply: can't find element '%s'\n",
+    other->name );
+    return;
+  }
+
+  /* create room for other properties */
+
+  if ( elem->nprops == 0 )
+  {
+    elem->props = ( PlyProperty *  *  )
+    myalloc ( sizeof ( PlyProperty *  ) * other->nprops );
+    elem->store_prop = ( char * ) myalloc ( sizeof ( char ) * other->nprops );
+    elem->nprops = 0;
+  }
+  else
+  {
+    int newsize;
+    newsize = elem->nprops + other->nprops;
+    elem->props = ( PlyProperty *  *  )
+    realloc ( elem->props, sizeof ( PlyProperty *  ) * newsize );
+    elem->store_prop = ( char * )
+    realloc ( elem->store_prop, sizeof ( char ) * newsize );
+  }
+
+  /* copy the other properties */
+
+  for ( i = 0; i < other->nprops; i++ )
+  {
+    prop = ( PlyProperty *  ) myalloc ( sizeof ( PlyProperty ) );
+    copy_property ( prop, other->props[i] );
+    elem->props[elem->nprops] = prop;
+    elem->store_prop[elem->nprops] = OTHER_PROP;
+    elem->nprops++;
+  }
+
+  /* save other info about other properties */
+  elem->other_size = other->size;
+  elem->other_offset = offset;
+}
+
+
+/******************************************************************************
+Pass along a pointer to "other" elements that we want to save in a given
+PLY file.  These other elements were presumably read from another PLY file.
+
+Entry:
+plyfile     - file pointer in which to store this other element info
+other_elems - info about other elements that we want to store
+******************************************************************************/
+
+void describe_other_elements_ply( PlyFile *plyfile, PlyOtherElems *other_elems )
+{
+  int         i;
+  OtherElem  *other;
+
+  /* ignore this call if there is no other element */
+  if ( other_elems == NULL )
+    return;
+
+  /* save pointer to this information */
+  plyfile->other_elems = other_elems;
+
+  /* describe the other properties of this element */
+
+  for ( i = 0; i < other_elems->num_elems; i++ )
+  {
+    other = &( other_elems->other_list[i] );
+    element_count_ply ( plyfile, other->elem_name, other->elem_count );
+    describe_other_properties_ply ( plyfile, other->other_props,
+    offsetof( OtherData,other_props ) );
+  }
+}
+
+
+
+/**** Property Propagation Rules ****/
+
+
+typedef struct RuleName {
+int code;
+const char *name;
+} RuleName;
+
+const RuleName  rule_name_list[]  = {
+{AVERAGE_RULE, "avg"},
+{RANDOM_RULE, "rnd"},
+{MINIMUM_RULE, "max"},
+{MAXIMUM_RULE, "min"},
+{MAJORITY_RULE, "major"},
+{SAME_RULE, "same"},
+{-1, "end_marker"},
+};
+
+
+
+/******************************************************************************
+Initialize the property propagation rules for an element.  Default is to
+use averaging (AVERAGE_RULE) for creating all new properties.
+
+Entry:
+ply       - PLY object that this is for
+elem_name - name of the element that we're making the rules for
+
+Exit:
+returns pointer to the default rules
+******************************************************************************/
+
+PlyPropRules *init_rule_ply( PlyFile *ply, char *elem_name )
+{
+  int           i,j;
+  PlyElement   *elem;
+  PlyPropRules *rules;
+  PlyRuleList  *list;
+  int           found_prop;
+
+  elem = find_element ( ply, elem_name );
+  if ( elem == NULL )
+  {
+    fprintf ( stderr, "init_rule_ply: Can't find element '%s'\n", elem_name );
+    exit ( -1 );
+  }
+
+  rules = ( PlyPropRules *  ) myalloc ( sizeof ( PlyPropRules ) );
+  rules->elem = elem;
+  rules->rule_list = ( int * ) myalloc ( sizeof( int ) * elem->nprops );
+  rules->max_props = 0;
+  rules->nprops = 0;
+
+  /* default is to use averaging rule */
+  for ( i = 0; i < elem->nprops; i++ )
+    rules->rule_list[i] = AVERAGE_RULE;
+
+  /* see if there are other rules we should use */
+
+  if ( ply->rule_list == NULL )
+    return ( rules );
+
+  /* try to match the element, property and rule name */
+
+  for ( list = ply->rule_list; list != NULL; list = list->next )
+  {
+    if ( !equal_strings ( list->element, elem->name ) )
+      continue;
+
+    found_prop = 0;
+
+    for ( i = 0; i < elem->nprops; i++ )
+      if ( equal_strings ( list->property, elem->props[i]->name ) )
+      {
+        found_prop = 1;
+
+        /* look for matching rule name */
+        for ( j = 0; rule_name_list[j].code != -1; j++ )
+          if ( equal_strings ( list->name, rule_name_list[j].name ) )
+          {
+            rules->rule_list[i] = rule_name_list[j].code;
+            break;
+          }
+      }
+
+    if ( !found_prop )
+    {
+      fprintf ( stderr, "Can't find property '%s' for rule '%s'\n",
+      list->property, list->name );
+      continue;
+    }
+  }
+
+  return ( rules );
+}
+
+
+/******************************************************************************
+odify a property propagation rule.
+
+Entry:
+rules - rules for the element
+prop_name - name of the property whose rule we're modifying
+rule_type - type of rule (MAXIMUM_RULE, MINIMUM_RULE, MAJORITY_RULE, etc.)
+******************************************************************************/
+
+void modify_rule_ply( PlyPropRules *rules, char *prop_name, int rule_type )
+{
+  int         i;
+  PlyElement *elem  = rules->elem;
+
+  /* find the property and modify its rule type */
+
+  for ( i = 0; i < elem->nprops; i++ )
+    if ( equal_strings ( elem->props[i]->name, prop_name ) )
+    {
+      rules->rule_list[i] = rule_type;
+      return;
+    }
+
+  /* we didn't find the property if we get here */
+  fprintf ( stderr, "modify_rule_ply: Can't find property '%s'\n", prop_name );
+  exit ( -1 );
+}
+
+
+/******************************************************************************
+Begin to create a set of properties from a set of propagation rules.
+
+Entry:
+ply   - PLY object whose rules we're preparing to use
+rules - rules for the element
+******************************************************************************/
+
+void start_props_ply( PlyFile *ply, PlyPropRules *rules )
+{
+  /*  PlyElement *elem  = rules->elem; */
+
+  /* save pointer to the rules in the PLY object */
+  ply->current_rules = rules;
+
+  /* get ready for new sets of properties to combine */
+  rules->nprops = 0;
+}
+
+
+/******************************************************************************
+Remember a set of properties and their weights for creating a new set of
+properties.
+
+Entry:
+weight      - weights for this set of properties
+other_props - the properties to use
+******************************************************************************/
+
+void weight_props_ply( PlyFile *ply, float weight, void *other_props )
+{
+  PlyPropRules *rules = ply->current_rules;
+
+  /* allocate space for properties and weights, if necessary */
+  if ( rules->max_props == 0 )
+  {
+    rules->max_props = 6;
+    rules->props = ( void * *  ) myalloc ( sizeof ( void * ) * rules->max_props );
+    rules->weights = ( float * ) myalloc ( sizeof ( float ) * rules->max_props );
+  }
+  if ( rules->nprops == rules->max_props )
+  {
+    rules->max_props *= 2;
+    rules->props = ( void * *  ) realloc ( rules->props,
+    sizeof ( void * ) * rules->max_props );
+    rules->weights = ( float * ) realloc ( rules->weights,
+    sizeof ( float ) * rules->max_props );
+  }
+
+  /* remember these new properties and their weights */
+
+  rules->props[rules->nprops] = other_props;
+  rules->weights[rules->nprops] = weight;
+  rules->nprops++;
+}
+
+
+/******************************************************************************
+Return a pointer to a new set of properties that have been created using
+a specified set of property combination rules and a given collection of
+"other" properties.
+
+Exit:
+returns a pointer to the new properties
+******************************************************************************/
+
+void *get_new_props_ply( PlyFile *ply )
+{
+  int             i,j;
+  static double  *vals;
+  static int      max_vals  = 0;
+  PlyPropRules   *rules     = ply->current_rules;
+  PlyElement     *elem      = rules->elem;
+  PlyProperty    *prop;
+  char           *data;
+  char           *new_data;
+  void           *ptr;
+  int             offset;
+  int             type;
+  double          double_val;
+  int             int_val;
+  unsigned int uint_val;
+  int random_pick;
+
+  /* return NULL if we've got no "other" properties */
+  if ( elem->other_size == 0 )
+  {
+    return ( NULL );
+  }
+
+  /* create room for combined other properties */
+  new_data = ( char * ) myalloc ( sizeof ( char ) * elem->other_size );
+
+  /* make sure there is enough room to store values we're to combine */
+
+  if ( max_vals == 0 )
+  {
+    max_vals = rules->nprops;
+    vals = ( double * ) myalloc ( sizeof ( double ) * rules->nprops );
+  }
+  if ( rules->nprops >= max_vals )
+  {
+    max_vals = rules->nprops;
+    vals = ( double * ) realloc ( vals, sizeof ( double ) * rules->nprops );
+  }
+
+  /* in case we need a random choice */
+  random_pick = ( int ) floor ( (double)rules->nprops ); //* drand48());
+
+  /* calculate the combination for each "other" property of the element */
+
+  for ( i = 0; i < elem->nprops; i++ )
+  {
+    /* don't bother with properties we've been asked to store explicitly */
+    if ( elem->store_prop[i] )
+      continue;
+
+    prop = elem->props[i];
+    offset = prop->offset;
+    type = prop->external_type;
+
+    /* collect together all the values we're to combine */
+
+    for ( j = 0; j < rules->nprops; j++ )
+    {
+      data = ( char * ) rules->props[j];
+      ptr = ( void * ) ( data + offset );
+      get_stored_item ( ( void * ) ptr, type, &int_val, &uint_val, &double_val );
+      vals[j] = double_val;
+    }
+
+    /* calculate the combined value */
+
+    switch ( rules->rule_list[i] )
+    {
+      case AVERAGE_RULE:
+        {
+        double  sum         = 0;
+        double  weight_sum  = 0;
+        for ( j = 0; j < rules->nprops; j++ )
+        {
+          sum += vals[j] * rules->weights[j];
+          weight_sum += rules->weights[j];
+        }
+        double_val = sum / weight_sum;
+        break;
+      }
+      case MINIMUM_RULE:
+        {
+        double_val = vals[0];
+        for ( j = 1; j < rules->nprops; j++ )
+          if ( double_val > vals[j] )
+            double_val = vals[j];
+        break;
+      }
+      case MAXIMUM_RULE:
+        {
+        double_val = vals[0];
+        for ( j = 1; j < rules->nprops; j++ )
+          if ( double_val < vals[j] )
+            double_val = vals[j];
+        break;
+      }
+      case RANDOM_RULE:
+        {
+        double_val = vals[random_pick];
+        break;
+      }
+      case SAME_RULE:
+        {
+        double_val = vals[0];
+        for ( j = 1; j < rules->nprops; j++ )
+          if ( double_val != vals[j] )
+          {
+            fprintf ( stderr,
+            "get_new_props_ply: Error combining properties that should be the same.\n" );
+            exit ( -1 );
+          }
+        break;
+      }
+      default:
+        fprintf ( stderr, "get_new_props_ply: Bad rule = %d\n",
+        rules->rule_list[i] );
+        exit ( -1 );
+    }
+
+    /* store the combined value */
+
+    int_val = ( int ) double_val;
+    uint_val = ( unsigned int ) double_val;
+    ptr = ( void * ) ( new_data + offset );
+    store_item ( ( char * ) ptr, type, int_val, uint_val, double_val );
+  }
+
+  return ( ( void * ) new_data );
+}
+
+
+/******************************************************************************
+Set the list of user-specified property combination rules.
+******************************************************************************/
+
+void set_prop_rules_ply( PlyFile *ply, PlyRuleList *prop_rules )
+{
+  ply->rule_list = prop_rules;
+}
+
+
+/******************************************************************************
+Append a property rule to a growing list of user-specified rules.
+
+Entry:
+rule_list - current rule list
+name      - name of property combination rule
+property  - "element.property" says which property the rule affects
+
+Exit:
+returns pointer to the new rule list
+******************************************************************************/
+
+PlyRuleList* append_prop_rule( PlyRuleList *rule_list, char *name, char *property )
+{
+  PlyRuleList  *rule;
+  PlyRuleList  *rule_ptr;
+  char         *str,*str2;
+  char         *ptr;
+
+  /* find . */
+  str = strdup ( property );
+  for ( ptr = str; *ptr != '\0' && *ptr != '.'; ptr++ )
+    ;
+
+  /* split string at . */
+  if ( *ptr == '.' )
+  {
+    *ptr = '\0';
+    str2 = ptr + 1;
+  }
+  else
+  {
+    fprintf ( stderr, "Can't find property '%s' for rule '%s'\n",
+    property, name );
+    return ( rule_list );
+  }
+
+  rule = ( PlyRuleList *  ) malloc ( sizeof ( PlyRuleList ) );
+  rule->name = name;
+  rule->element = str;
+  rule->property = str2;
+  rule->next = NULL;
+
+  /* either start rule list or append to it */
+
+  if ( rule_list == NULL )
+    rule_list = rule;
+  else
+  {
+    /* append new rule to current list */
+    rule_ptr = rule_list;
+    while ( rule_ptr->next != NULL )
+      rule_ptr = rule_ptr->next;
+    rule_ptr->next = rule;
+  }
+
+  /* return pointer to list */
+
+  return ( rule_list );
+}
+
+
+/******************************************************************************
+See if a name matches the name of any property combination rules.
+
+Entry:
+name - name of rule we're trying to match
+
+Exit:
+returns 1 if we find a match, 0 if not
+******************************************************************************/
+
+int matches_rule_name( char* name )
+{
+  int i;
+
+  for ( i = 0; rule_name_list[i].code != -1; i++ )
+    if ( equal_strings ( rule_name_list[i].name, name ) )
+      return ( 1 );
+
+  return ( 0 );
+}
+
+} //namespace
diff --git a/source/ThirdParty/MarchingCubes/McPly.h b/source/ThirdParty/MarchingCubes/McPly.h
new file mode 100644
index 0000000000000000000000000000000000000000..b1cca17280f0d0bff88969a097b03ca891b39fcb
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/McPly.h
@@ -0,0 +1,229 @@
+/*
+
+Header for PLY polygon files.
+
+- Greg Turk
+
+A PLY file contains a single polygonal _object_.
+
+An object is composed of lists of _elements_.  Typical elements are
+vertices, faces, edges and materials.
+
+Each type of element for a given object has one or more _properties_
+associated with the element type.  For instance, a vertex element may
+have as properties three floating-point values x,y,z and three unsigned
+chars for red, green and blue.
+
+-----------------------------------------------------------------------
+
+Copyright (c) 1998 Georgia Institute of Technology.  All rights reserved.
+
+Permission to use, copy, modify and distribute this software and its
+documentation for any purpose is hereby granted without fee, provided
+that the above copyright notice and this permission notice appear in
+all copies of this software and that you do not sell the software.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+*/
+#ifndef MCPLY_H
+#define MCPLY_H
+
+#include <cmath>
+#include <string>
+#include <cstring>
+#include <cstring>
+#include <cstdlib>
+
+namespace McCubes{ 
+
+static const int PLY_ASCII     =  1;  // ascii PLY file 
+static const int PLY_BINARY_BE =  2;  // binary PLY file, big endian 
+static const int PLY_BINARY_LE =  3;  // binary PLY file, little endian 
+
+static const int PLY_OKAY      =  0;  // ply routine worked okay 
+static const int PLY_ERROR     = -1;  // error in ply routine 
+
+/* scalar data types supported by PLY format */
+
+static const int StartType  = 0;
+static const int Int8       = 1;
+static const int Int16      = 2;
+static const int Int32      = 3;
+static const int Uint8      = 4;
+static const int Uint16     = 5;
+static const int Uint32     = 6;
+static const int Float32    = 7;
+static const int Float64    = 8;
+static const int EndType    = 9;
+
+static const int PLY_SCALAR =  0;
+static const int PLY_LIST   =  1;
+static const int PLY_STRING =  2;
+
+
+typedef struct PlyProperty {    /* description of a property */
+
+char *name;                   /* property name */
+int external_type;            /* file's data type */
+int internal_type;            /* program's data type */
+int offset;                   /* offset bytes of prop in a struct */
+
+int is_list;                  /* 0 = scalar, 1 = list, 2 = char string */
+int count_external;           /* file's count type */
+int count_internal;           /* program's count type */
+int count_offset;             /* offset byte for list count */
+
+} PlyProperty;
+
+typedef struct PlyElement {     /* description of an element */
+char *name;                   /* element name */
+int num;                      /* number of elements in this object */
+int size;                     /* size of element (bytes) or -1 if variable */
+int nprops;                   /* number of properties for this element */
+PlyProperty **props;          /* list of properties in the file */
+char *store_prop;             /* flags: property wanted by user? */
+int other_offset;             /* offset to un-asked-for props, or -1 if none*/
+int other_size;               /* size of other_props structure */
+} PlyElement;
+
+typedef struct PlyOtherProp {   /* describes other properties in an element */
+char *name;                   /* element name */
+int size;                     /* size of other_props */
+int nprops;                   /* number of properties in other_props */
+PlyProperty **props;          /* list of properties in other_props */
+} PlyOtherProp;
+
+typedef struct OtherData { /* for storing other_props for an other element */
+void *other_props;
+} OtherData;
+
+typedef struct OtherElem {     /* data for one "other" element */
+char *elem_name;             /* names of other elements */
+int elem_count;              /* count of instances of each element */
+OtherData **other_data;      /* actual property data for the elements */
+PlyOtherProp *other_props;   /* description of the property data */
+} OtherElem;
+
+typedef struct PlyOtherElems {  /* "other" elements, not interpreted by user */
+int num_elems;                /* number of other elements */
+OtherElem *other_list;        /* list of data for other elements */
+} PlyOtherElems;
+
+static const int AVERAGE_RULE  = 1;
+static const int MAJORITY_RULE = 2;
+static const int MINIMUM_RULE  = 3;
+static const int MAXIMUM_RULE  = 4;
+static const int SAME_RULE     = 5;
+static const int RANDOM_RULE   = 6;
+
+typedef struct PlyPropRules {   /* rules for combining "other" properties */
+PlyElement *elem;      /* element whose rules we are making */
+int *rule_list;        /* types of rules (AVERAGE_PLY, MAJORITY_PLY, etc.) */
+int nprops;            /* number of properties we're combining so far */
+int max_props;         /* maximum number of properties we have room for now */
+void **props;          /* list of properties we're combining */
+float *weights;        /* list of weights of the properties */
+} PlyPropRules;
+
+typedef struct PlyRuleList {
+char *name;                  /* name of the rule */
+char *element;               /* name of element that rule applies to */
+char *property;              /* name of property that rule applies to */
+struct PlyRuleList *next;    /* pointer for linked list of rules */
+} PlyRuleList;
+
+typedef struct PlyFile {        /* description of PLY file */
+FILE *fp;                     /* file pointer */
+int file_type;                /* ascii or binary */
+float version;                /* version number of file */
+int num_elem_types;           /* number of element types of object */
+PlyElement **elems;           /* list of elements */
+int num_comments;             /* number of comments */
+char **comments;              /* list of comments */
+int num_obj_info;             /* number of items of object information */
+char **obj_info;              /* list of object info items */
+PlyElement *which_elem;       /* element we're currently reading or writing */
+PlyOtherElems *other_elems;   /* "other" elements from a PLY file */
+PlyPropRules *current_rules;  /* current propagation rules */
+PlyRuleList *rule_list;       /* rule list from user */
+} PlyFile;
+
+// memory allocation 
+//extern char *my_alloc();
+#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
+
+
+// old routines 
+
+#if 0
+extern PlyFile *ply_write(FILE *, int, char **, int);
+extern PlyFile *ply_read(FILE *, int *, char ***);
+extern PlyFile *ply_open_for_reading( const char *, int *, char ***, int *, float *);
+extern void ply_close(PlyFile *);
+extern PlyOtherProp *ply_get_other_properties(PlyFile *, const char *, int);
+#endif
+
+extern void     ply_describe_property( PlyFile * , const char * , PlyProperty * );
+extern void     ply_get_property( PlyFile * , const char * , PlyProperty * );
+extern void     ply_get_element( PlyFile * , void * );
+
+
+//--- delcaration of routines ---
+
+PlyOtherElems  *get_other_element_ply( PlyFile * );
+
+PlyFile        *read_ply( FILE * );
+PlyFile        *write_ply( FILE * , int, char ** , int );
+extern PlyFile *open_for_writing_ply( const char * , int, char ** , int );
+void            close_ply( PlyFile * );
+void            free_ply( PlyFile * );
+
+void            get_info_ply( PlyFile * , float * , int * );
+void            free_other_elements_ply( PlyOtherElems * );
+
+void            append_comment_ply( PlyFile *, const char * );
+void            append_obj_info_ply( PlyFile * , const char * );
+void            copy_comments_ply( PlyFile * , PlyFile * );
+void            copy_obj_info_ply( PlyFile * , PlyFile * );
+char*          *get_comments_ply( PlyFile * , int * );
+char*          *get_obj_info_ply( PlyFile * , int * );
+
+char*          *get_element_list_ply( PlyFile * , int * );
+int             setup_property_ply( PlyFile * , PlyProperty * );
+void            get_element_ply( PlyFile * , void * );
+char           *setup_element_read_ply( PlyFile * , int, int * );
+PlyOtherProp   *get_other_properties_ply( PlyFile * , int );
+
+void            element_count_ply( PlyFile * , const char * , int );
+void            describe_element_ply( PlyFile * , const char * , int );
+void            describe_property_ply( PlyFile * , PlyProperty * );
+void            describe_other_properties_ply( PlyFile * , PlyOtherProp * , int );
+void            describe_other_elements_ply( PlyFile * , PlyOtherElems * );
+void            get_element_setup_ply( PlyFile * , const char * , int, PlyProperty * );
+PlyProperty*   *get_element_description_ply( PlyFile * , const char * , int * , int * );
+void            element_layout_ply( PlyFile * , const char * , int, int, PlyProperty * );
+
+void            header_complete_ply( PlyFile * );
+void            put_element_setup_ply( PlyFile * ,const  char * );
+void            put_element_ply( PlyFile * , void * );
+void            put_other_elements_ply( PlyFile * );
+
+PlyPropRules   *init_rule_ply( PlyFile * , const char * );
+void            modify_rule_ply( PlyPropRules * , const char * , int );
+void            start_props_ply( PlyFile * , PlyPropRules * );
+void            weight_props_ply( PlyFile * , float, void * );
+void           *get_new_props_ply( PlyFile * );
+void            set_prop_rules_ply( PlyFile * , PlyRuleList * );
+PlyRuleList    *append_prop_rule( PlyRuleList * , const char * , const char * );
+int             matches_rule_name( const char * );
+
+int             equal_strings( const char * , const char * );
+char           *recreate_command_line( int, char *argv[] );
+
+} //namespace McCubes
+
+#endif // PLY_H__ 
+
diff --git a/source/ThirdParty/MarchingCubes/McTypes.h b/source/ThirdParty/MarchingCubes/McTypes.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ff91d5a0b4f8457a6843ce0e957d383c04a2d9e
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/McTypes.h
@@ -0,0 +1,37 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MCTYPES_H
+#define MCTYPES_H
+
+//extension by CAB
+#include <vector>
+#include <string>
+#include <fstream>
+
+#include <basics/utilities/UbException.h>
+#include <basics/container/CbArray3D.h>
+#include <basics/container/CbArray4D.h>
+
+namespace McCubes
+{ 
+
+   #if !defined(WIN32) || defined(__CYGWIN__)
+   #pragma interface
+   #endif // WIN32
+
+   //_____________________________________________________________________________
+   // types
+   /** unsigned char alias */
+   typedef unsigned char   uchar;
+   /** signed char alias */
+   typedef   signed char   schar;
+   /** isovalue alias */
+   typedef          double real;
+
+} //namespace McCubes
+
+#endif //MCTYPES_H
diff --git a/source/ThirdParty/MarchingCubes/McWrapper.h b/source/ThirdParty/MarchingCubes/McWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..a60f18b6bc11cb867fe7d32352dfa221765f9f10
--- /dev/null
+++ b/source/ThirdParty/MarchingCubes/McWrapper.h
@@ -0,0 +1,305 @@
+// _    ___      __              __________      _     __
+//| |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+//| | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+//| |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+//|___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+//#ifndef MCWRAPPER_H
+//#define MCWRAPPER_H
+//
+//extension by CAB
+//#include <vector>
+//#include <string>
+//#include <fstream>
+//
+//#include <basics/utilities/UbException.h>
+//#include <basics/container/CbUniformMatrix3D.h>
+//#include <basics/container/CbUniformMatrix4D.h>
+//
+//#include <3rdParty/MarchingCubes/McTypes.h>
+//
+//namespace McCubes{
+//
+//////////////////////////////////////////////////////////////////////////
+//Standard-Wrapper
+//  MarchingCubes<DataWrapper> mc( 10,8,5 );
+//  for(int z=0; z<mc.size_z(); z++)
+//   for(int y=0; y<mc.size_y(); y++)
+//     for(int x=0; x<mc.size_x(); x++)
+//       mc.set_data(x,x,y,z);
+//
+//  //mc.set_method(false) //<-MC methode, STD=false
+//  mc.init_all();
+//
+//  mc.run(3.5);
+//  mc.writeUCD("c:/temp/triangles.inp");
+//  mc.clean_all();
+
+//template< typename T=real >
+//class McDataWrapper
+//{
+//public:
+//   typedef T                                                   value_type;
+//   typedef typename std::vector< value_type >::reference       reference;
+//   typedef typename std::vector< value_type >::const_reference const_reference;
+//   typedef typename std::vector< value_type >::pointer         pointer;
+//   typedef typename std::vector< value_type >::const_pointer   const_pointer;
+//
+//public:
+//   McDataWrapper() : size_x1(-1), size_x2(-1), size_x3(-1)
+//   {
+//   }
+//   /*==========================================================*/
+//   McDataWrapper(const int& size_x1, const int& size_x2, const int& size_x3, const T& initVal=T())
+//   {
+//      this->resize(size_x1,size_x2,size_x3,initVal);
+//   }
+//   /*=======================================================================*/
+//   reference operator() (const int& x1, const int& x2, const int& x3)
+//   {
+//      #ifdef _DEBUG
+//         return this->data.at(x1 + x2*size_x1 + x3*size_x1*size_x2);
+//      #else
+//         return this->data[x1 + x2*size_x1 + x3*size_x1*size_x2];
+//      #endif
+//   }
+//   /*=======================================================================*/
+//   const_reference operator() (const int& x1, const int& x2, const int& x3)	const
+//   {
+//      #ifdef _DEBUG
+//         return this->data.at(x1 + x2*size_x1 + x3*size_x1*size_x2);
+//      #else
+//         return this->data[x1 + x2*size_x1 + x3*size_x1*size_x2];
+//      #endif
+//   }
+//   /*==========================================================*/
+//   inline void setData( const T& val, const int& x1, const int& x2, const int& x3 )
+//   {
+//      #ifdef _DEBUG
+//         this->data.at(x1 + x2*size_x1 + x3*size_x1*size_x2) = val;
+//      #else
+//         this->data[x1 + x2*size_x1 + x3*size_x1*size_x2] = val;
+//      #endif
+//   }
+//   /*==========================================================*/
+//   inline value_type getData(const int& x1, const int& x2, const int& x3 ) const
+//   {
+//      #ifdef _DEBUG
+//         return this->data.at(x1 + x2*size_x1 + x3*size_x1*size_x2);
+//      #else
+//         return this->data[x1 + x2*size_x1 + x3*size_x1*size_x2];
+//      #endif
+//   }
+//   /*==========================================================*/
+//   inline void resize(const int& size_x1, const int& size_x2, const int& size_x3)
+//   {
+//      if(size_x1>0 && size_x2>0 && size_x3>0)
+//      {
+//         this->size_x1 = size_x1;
+//         this->size_x2 = size_x2;
+//         this->size_x3 = size_x3;
+//         this->data.resize(size_x1*size_x2*size_x3);
+//      }
+//   }
+//   /*==========================================================*/
+//   inline void resize(const int& size_x1, const int& size_x2, const int& size_x3, const T& initVal)
+//   {
+//      if(size_x1>0 && size_x2>0 && size_x3>0)
+//      {
+//         this->size_x1 = size_x1;
+//         this->size_x2 = size_x2;
+//         this->size_x3 = size_x3;
+//         this->data.resize(size_x1*size_x2*size_x3,initVal);
+//      }
+//   }
+//   /*==========================================================*/
+//   int getNX1() const { return size_x1; }
+//   int getNX2() const { return size_x2; }
+//   int getNX3() const { return size_x3; }
+//
+//protected:
+//   std::vector<T> data;
+//   int size_x1, size_x2, size_x3;
+//};
+//
+//////////////////////////////////////////////////////////////////////////
+//Matrix4DWrapper-Wrapper
+//example:
+//  int indexForDataValue = 1;
+//  CbUniformMatrix4D<double> data(10,8,5,2);
+//  for(int x3=0; x3<data.getNX3(); x3++)
+//   for(int x2=0; x2<data.getNX2(); x2++)
+//     for(int x1=0; x1<data.getNX1(); x1++)
+//       data(x1,x2,x3,indexForDataValue) = x1;
+//
+//  Matrix4DWrapper< CbUniformMatrix4D<double> > wrapper(&data,indexForDataValue);
+//  MarchingCubes< Matrix4DWrapper< CbUniformMatrix4D<double> > > mc( wrapper );
+//
+//  mc.init_all();
+//  mc.run(3.5);
+//  mc.writeUCD("c:/temp/triangles.inp");
+//  mc.clean_all();
+//template< typename Matrix4D >
+//class Matrix4DWrapper
+//{
+//public:
+//   typedef typename Matrix4D::value_type value_type;
+//
+//public:
+//   Matrix4DWrapper() : valIndex(-1), matrix(NULL), minX1(-1), minX2(-1), minX3(-1), maxX1(-1), maxX2(-1), maxX3(-1)
+//   {
+//      //wird benötigt, damit MarchingCubes generell eine membervariabel erstellen kann
+//   }
+//   /*==========================================================*/
+//   //fuer beliebige matrizen
+//   Matrix4DWrapper( Matrix4D* matrix, const int& valIndex)
+//      : valIndex(valIndex), matrix(matrix)
+//   {
+//
+//   }
+//   /*==========================================================*/
+//   Matrix4DWrapper( Matrix4D* matrix, const int& valIndex,const int& n1, const int& nx2, const int& nx3)
+//      : valIndex(valIndex), matrix(matrix), nx1(nx1), nx2(nx2), nx3(nx3)
+//   {
+//      minX1 = minX2 = minX3 = 0;
+//      maxX1 = nx1-1;
+//      maxX2 = nx2-1;
+//      maxX3 = nx3-1;
+//   }
+//   /*==========================================================*/
+//   //wenn man z.B. matrixX1 von[0..10] geht und man nur den bereich 1..9 fuer MC
+//   //verwenden möchte -> minX1=1 und maxX2=2
+//   Matrix4DWrapper( Matrix4D* matrix, const int& valIndex, const int& minX1, const int& minX2, const int& minX3,
+//                                                           const int& maxX1, const int& maxX2, const int& maxX3)
+//       : valIndex(valIndex), matrix(matrix), minX1(minX1), minX2(minX2), minX3(minX3), maxX1(maxX1), maxX2(maxX2), maxX3(maxX3)
+//   {
+//      nx1 = matrix->getNX1()-1;
+//      nx2 = matrix->getNX2()-1;
+//      nx3 = matrix->getNX3()-1;
+//
+//      if(minX1<0 || minX2<0 || minX3<0 || maxX1>=nx1 || maxX2>=nx2 || maxX3>=nx3)
+//         throw UbException(UB_EXARGS,"range error");
+//   }
+//   /*==========================================================*/
+//   inline void setData( const real& val, const int& x1, const int& x2, const int& x3 )
+//   {
+//      (*matrix)(minX1+x1, minX2+x2, minX3+x3, valIndex) = static_cast<value_type>(val);
+//   }
+//   /*==========================================================*/
+//   inline value_type getData(const int& x1, const int& x2, const int& x3 ) const
+//   {
+//      return (*matrix)(minX1+x1, minX2+x2, minX3+x3, valIndex);
+//   }
+//   /*==========================================================*/
+//   inline void resize(const int& size_x1, const int& size_x2, const int& size_x3)
+//   {
+//      throw UbException("Matrix4DWrapper::resize(int,int,int) - mit diesem wrapper nicht erlaubt");
+//   }
+//   /*==========================================================*/
+//   inline int getMinX1() const { return minX1; }  
+//   inline int getMinX2() const { return minX2; }  
+//   inline int getMinX3() const { return minX3; }  
+//
+//   inline int getMaxX1() const { return maxX1; }  
+//   inline int getMaxX2() const { return maxX2; }  
+//   inline int getMaxX3() const { return maxX3; }  
+//
+//   inline int getNX1()   const { nx1; }  
+//   inline int getNX2()   const { nx2; }  
+//   inline int getNX3()   const { nx3; }  
+//
+//protected:
+//   int valIndex;
+//   Matrix4D* matrix;
+//   int minX1, minX2, minX3, maxX1, maxX2, maxX3, nx1, nx2, nx3;
+//};
+//
+//////////////////////////////////////////////////////////////////////////
+//Matrix3DWrapper-Wrapper
+//  CbUniformMatrix3D<double> data(10,8,5);
+//  for(int x3=0; x3<data.getNX3(); x3++)
+//   for(int x2=0; x2<data.getNX2(); x2++)
+//     for(int x1=0; x1<data.getNX1(); x1++)
+//       data(x1,x2,x3) = x1;
+//
+//  Matrix3DWrapper< CbUniformMatrix3D<double> > wrapper(&data);
+//  MarchingCubes< Matrix3DWrapper< CbUniformMatrix3D<double> > > mc( wrapper );
+//
+//  mc.init_all();
+//  mc.run(3.5);
+//  mc.writeUCD("c:/temp/triangles.inp");
+//  mc.clean_all();
+//template< typename Matrix3D >
+//class Matrix3DWrapper
+//{
+//public:
+//   typedef typename Matrix3D::value_type value_type;
+//
+//public:
+//   Matrix3DWrapper() : matrix(NULL), minX1(-1), minX2(-1), minX3(-1), maxX1(-1), maxX2(-1), maxX3(-1)
+//   {
+//      //wird benötigt, damit MarchingCubes generell eine membervariabel erstellen kann
+//   }
+//   /*==========================================================*/
+//   Matrix3DWrapper( Matrix3D* matrix)
+//      : matrix(matrix)
+//   {
+//      minX1 = minX2 = minX3 = 0;
+//      maxX1 = matrix->getNX1();
+//      maxX2 = matrix->getNX2();
+//      maxX3 = matrix->getNX3();
+//
+//      minX1 = minX2 = minX3 = 0;
+//      maxX1 = nx1-1;
+//      maxX2 = nx2-1;
+//      maxX3 = nx3-1;
+//
+//   }
+//   /*==========================================================*/
+//   Matrix3DWrapper( Matrix3D* matrix, const int& minX1, const int& minX2, const int& minX3
+//                                    , const int& maxX1, const int& maxX2, const int& maxX3 )
+//      : matrix(matrix), minX1(minX1), minX2(minX2), minX3(minX3), maxX1(maxX1), maxX2(maxX2), maxX3(maxX3)
+//   {
+//
+//   }
+//   /*==========================================================*/
+//   Matrix3DWrapper(const int& size_x1, const int& size_x2, const int& size_x3)
+//   {
+//      throw UbException("Matrix3DWrapper(int,int,int) - mit diesem wrapper nicht erlaubt");
+//   }
+//   /*==========================================================*/
+//   inline void setData( const real& val, const int& x1, const int& x2, const int& x3 )
+//   {
+//      (*matrix)(minX1+x1, minX2+x2, minX3+x3) = static_cast<value_type>(val);
+//   }
+//   /*==========================================================*/
+//   inline value_type getData(const int& x1, const int& x2, const int& x3 ) const
+//   {
+//      return (*matrix)(minX1+x1, minX2+x2, minX3+x3);
+//   }
+//   /*==========================================================*/
+//   inline void resize(const int& size_x1, const int& size_x2, const int& size_x3)
+//   {
+//      throw UbException("Matrix3DWrapper::resize(int,int,int) - mit diesem wrapper nicht erlaubt");
+//   }
+//   /*==========================================================*/
+//   inline int getMinX1() const { return minX1; }  
+//   inline int getMinX2() const { return minX2; }  
+//   inline int getMinX3() const { return minX3; }  
+//
+//   inline int getMaxX1() const { return maxX1; }  
+//   inline int getMaxX2() const { return maxX2; }  
+//   inline int getMaxX3() const { return maxX3; }  
+//
+//   inline int getNX1()   const { nx1; }  
+//   inline int getNX2()   const { nx2; }  
+//   inline int getNX3()   const { nx3; }  
+//
+//protected:
+//   Matrix3D* matrix;
+//   int minX1, minX2, minX3, maxX1, maxX2, maxX3, nx1, nx2, nx3;
+//};
+//
+//} //namespace McCubes
+//
+//#endif //MCWRAPPER_H
diff --git a/source/ThirdParty/MuParser/CMakePackage.txt b/source/ThirdParty/MuParser/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..06a4d0073321441f85313c250a29581a31e1852c
--- /dev/null
+++ b/source/ThirdParty/MuParser/CMakePackage.txt
@@ -0,0 +1,36 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH)
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES outOption outSourceGroupName)
+
+IF( ${outOption} )
+
+   #verzeichnis als std-include adden
+   INCLUDE_DIRECTORIES( ${CURRENT_DIR}/include )
+
+   OPTION(USE_MUPARSER_AS_LIB "MuParser will be compiled as lib" ON)
+
+   IF(USE_MUPARSER_AS_LIB)
+     FILE( GLOB muparser_HEADER_FILES ${CURRENT_DIR}/include/*.h   )
+     FILE( GLOB muparser_CXX_FILES    ${CURRENT_DIR}/src/*.cpp )
+
+     SET(MUPARSER_SRC_FILES ${muparser_HEADER_FILES} ${muparser_CXX_FILES})
+
+     ADD_LIBRARY(muParserLib ${MUPARSER_SRC_FILES})
+     
+     #lib projekt hinzufuegen	  
+     LIST(APPEND CAB_ADDITIONAL_LINK_LIBRARIES muParserLib)
+     
+     ADD_TARGET_PROPERTIES(muParserLib COMPILE_FLAGS "-I${CURRENT_DIR}/include")
+     
+     #compilerflags aktuellem projekt hinzufuegen	  
+     ADD_COMPILER_FLAGS_TO_PROJECT(${CAB_COMPILER} "muParserLib" "CXX" "STATIC")
+
+   ELSE() #not as lib
+      SET( CURRENT_DIR_TMP ${CURRENT_DIR} ) #wird im nächsten befehl geaendert
+      INCLUDE( ${CURRENT_DIR_TMP}/include/CMakePackage.txt)
+      INCLUDE( ${CURRENT_DIR_TMP}/src/CMakePackage.txt)
+   ENDIF()
+
+ENDIF( ${outOption} )
+
+
+
diff --git a/source/ThirdParty/MuParser/Changes.txt b/source/ThirdParty/MuParser/Changes.txt
new file mode 100644
index 0000000000000000000000000000000000000000..abe969770b09170a50d8f9dfb8d26bfa2d3ba1fa
--- /dev/null
+++ b/source/ThirdParty/MuParser/Changes.txt
@@ -0,0 +1,557 @@
+#######################################################################
+#                                                                     #
+#                                                                     #
+#                 __________                                          #
+#    _____   __ __\______   \_____  _______  ______  ____ _______     #
+#   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \    #
+#  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/    #
+#  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|       #
+#        \/                       \/            \/      \/            #
+#					  Fast math parser Library                        #
+#                                                                     #
+#  Copyright (C) 2015 Ingo Berg                                       #
+#                                                                     #
+#  Web:     muparser.beltoforion.de                                   #
+#  e-mail:  muparser@beltoforion.de                                   #
+#                                                                     #
+#                                                                     #
+#######################################################################
+ 
+
+History:
+--------
+
+Rev 2.2.5: 27.04.2015
+---------------------
+  Changes:
+   * example2 extended to work with UNICODE character set
+   * Applied patch from Issue 9
+   
+  Bugfixes:
+   * muChar_t in muParserDLL.h was not set properly when UNICODE was used
+   * muparser.dll did not build on UNICODE systems
+   
+Rev 2.2.4: 02.10.2014
+---------------------
+  Changes:
+   * explicit positive sign allowed
+
+  Bugfixes:
+   * Fix for Issue 6 (https://code.google.com/p/muparser/issues/detail?id=6)
+   * String constants did not work properly. Using more than a single one 
+     was impossible.
+   * Project Files for VS2008 and VS2010 removed from the repository 
+   * Fix for Issue 4 (https://code.google.com/p/muparser/issues/detail?id=4)
+   * Fix for VS2013 64 bit build option
+   * return type of ParserError::GetPos changed to int
+   * OpenMP support enabled in the VS2013 project files and precompiled windows DLL's
+   * Bulkmode did not evaluate properly if "=" and "," operator was used in the expression
+	
+Rev 2.2.3: 22.12.2012
+---------------------
+
+  Removed features:
+   * build files for msvc2005, borland and watcom compiler were removed
+
+  Bugfixes:
+   * Bugfix for Intel Compilers added: The power operator did not work properly 
+     with Intel C++ composer XE 2011.
+     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5117983/index/page/1)
+   * Issue 3509860: Callbacks of functions with string parameters called twice
+     (see http://sourceforge.net/tracker/?func=detail&aid=3509860&group_id=137191&atid=737979)
+   * Issue 3570423: example1 shows slot number in hexadecimal
+     (see https://sourceforge.net/tracker/?func=detail&aid=3570423&group_id=137191&atid=737979)
+   * Fixes for compiling with the "MUP_MATH_EXCEPTIONS" macro definition:
+ 	- division by zero in constant expressions was reported with the code "ec_GENERIC" 
+          instead of "ecDIV_BY_ZERO"
+        - added throwing of "ecDOMAIN_ERROR" to sqrt and log functions
+
+
+Rev 2.2.2: 18.02.2012
+---------------------
+  Bugfixes:
+   * Optimizer did'nt work properly for division:
+     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825)
+
+Rev 2.2.1: 22.01.2012
+---------------------
+  Bugfixes:
+   * Optimizer bug in 64 bit systems fixed
+     (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/4977977/index/page/1)
+	 
+Rev 2.2.0: 22.01.2012
+---------------------
+  Improvements:
+   * Optimizer rewritten and improved. In general: more optimizations are 
+     now applied to the bytecode. The downside is that callback Functions 
+     can no longer be flagged as non-optimizable. (The flag is still present 
+     but ignored) This is necessary since the optimizer had to call the 
+     functions in order to precalculate the result (see Bugfixes). These calls 
+     posed a problems for callback functions with side  effects and if-then-else 
+     clauses in general since they undermined the shortcut evaluation prinziple.
+
+  Bugfixes:
+   * Infix operators where not properly detected in the presence of a constant 
+     name starting with an underscore which is a valid character for infix 
+     operators too (i.e. "-_pi").
+   * Issue 3463353: Callback functions are called twice during the first call to eval.
+   * Issue 3447007: GetUsedVar unnecessaryly executes callback functions.
+
+
+Rev 2.1.0: 19.11.2011
+---------------------
+  New feature:
+   * Function atan2 added
+
+  Bugfixes:
+   * Issue 3438380:  Changed behaviour of tellg with GCC >4.6 led to failures  
+                     in value detection callbacks.
+   * Issue 3438715:  only "double" is a valid MUP_BASETYPE 
+                     MUP_BASETYPE can now be any of:
+                       float, 
+                       double, 
+                       long double, 
+                       short, 
+                       unsigned short, 
+                       unsigned int, 
+                       long,
+                       unsigned long. 
+                     Previousely only floating point types were allowed. 
+                     Using "int" is still not allowed!
+   * Compiler issues with GCC 4.6 fixed
+   * Custom value recognition callbacks added with AddValIdent had lower
+     priority than built in functions. This was causing problems with 
+     hex value recognition since detection of non hex values had priority
+     over the detection of hex values. The "0" in the hex prefix "0x" would 
+     be read as a separate non-hex number leaving the rest of the expression
+     unparseable.
+
+Rev 2.0.0: 04.09.2011
+---------------------
+This release introduces a new version numbering scheme in order to make
+future changes in the ABI apparent to users of the library. The number is
+now based on the SONAME property as used by GNU/Linux. 
+
+  Changes:
+   * Beginning with this version all version numbers will be SONAME compliant
+   * Project files for MSVC2010 added
+   * Project files for MSVC2003 removed
+   * Bytecode parsing engine cleaned up and rewritten
+   * Retrieving all results of expressions made up of comma separate 
+     subexpressions is now possible with a new Eval overload.
+   * Callback functions with fixed number of arguments can now have up to 10 
+     Parameters (previous limit was 5)
+
+  New features:
+   * ternary if-then-else operator added (C++ like; "(...) ? ... : ..." )
+   * new intrinsic binary operators: "&&", "||" (logical and, or)
+   * A new bulkmode allows submitting large arrays as variables to compute large 
+     numbers of expressions with a single call. This can drastically improve 
+     parsing performance when interfacing the library from managed languages like 
+     C#. (It doesn't bring any performance benefit for C++ users though...)
+
+  Removed features:
+   * intrinsic "and", "or" and "xor" operators have been removed. I'd like to let 
+     users the freedom of defining them on their own versions (either as logical or bitwise 
+     operators).
+   * Implementation for complex numbers removed. This was merely a hack. If you 
+     need complex numbers try muParserX which provides native support for them.
+     (see: http://beltoforion.de/muparserx/math_expression_parser_en.html)
+
+  Bugfixes:
+   * User defined operators could collide with built in operators that entirely 
+     contained their identifier. i.e. user defined "&" would not work with the built 
+     in "&&" operator since the user defined operator was detected with a higher 
+     priority resulting in a syntax error.
+   * Detection of unknown variables did not work properly in case a postfix operator
+     was defined which was part of the undefined variable.
+     i.e. If a postfix operator "m" was defined expressions like "multi*1.0" did
+     not detect "multi" as an undefined variable.
+     (Reference:  http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979)
+   * Postfix operators sharing the first few characters were causing bogus parsing exception.
+     (Reference: https://sourceforge.net/tracker/?func=detail&aid=3358571&group_id=137191&atid=737979)
+
+Rev 1.34: 04.09.2010
+--------------------
+  Changes:
+   * The prefix needed for parsing hex values is now "0x" and no longer "$". 
+   * AddValIdent reintroduced into the DLL interface
+
+  New features:
+   * The associativity of binary operators can now be changed. The pow operator 
+     is now right associative. (This is what Mathematica is using) 
+   * Seperator can now be used outside of functions. This allows compound 
+     expressions like:
+     "a=10,b=20,c=a*b" The last "argument" will be taken as the return value
+
+  Bugfixes:	
+   * The copy constructor did not copy binary operator definitions. Those were lost
+     in the copied parser instance.
+   * Mixing special characters and alphabetic characters in binary operator names 
+     led to inconsistent parsing behaviour when parsing expressions like "a ++ b" 
+     and "a++b" when "++" is defined as a binary operator. Binary operators must 
+     now consist entirely of special characters or of alphabetic ones.
+     (original bug report: https://sourceforge.net/projects/muparser/forums/forum/462843/topic/3696881/index/page/1)
+   * User defined operators were not exactly handled like built in operators. This 
+     led to inconsistencies in expression evaluation when using them. The results 
+     differed due to slightly different precedence rules.
+   * Using empty string arguments ("") would cause a crash of muParser
+
+
+Rev 1.32: 29.01.2010 
+--------------------
+
+  Changes:
+   * "example3" renamed to "example2"
+   * Project/Makefiles files are now provided for:
+           - msvc2003 
+           - msvc2005 
+           - msvc2008
+           - watcom   (makefile)
+           - mingw    (makefile)
+           - bcc      (makefile)
+   * Project files for borland cpp builder were removed
+
+
+  New features:
+   * Added function returning muparsers version number
+   * Added function for resetting the locale
+
+
+  Bugfixes:	
+   * Changes example1 in order to fix issues with irritating memory leak reports. 
+     Added conditional code for memory leak detection with MSVC in example1.
+     (see: http://www.codeproject.com/KB/recipes/FastMathParser.aspx?msg=3286367#xx3286367xx)
+   * Fixed some warnings for gcc
+
+
+
+Rev 1.31cp: 15.01.2010  (Maintainance release for CodeProject)
+----------------------
+
+  Changes:
+   * Archive structure changed
+   * C# wrapper added
+   * Fixed issued that prevented compiling with VS2010 Beta2
+    
+
+Rev 1.30: 09.06.2008
+--------------------
+
+  Changes:
+   * Epsilon of the numerical differentiation algorithm changed to allow greater accuracy.
+
+  New features:
+   * Setting thousands separator and decimal separator is now possible
+
+  Bugfixes:
+   * The dll interface did not provide a callback for functions without any arguments.	 
+	
+
+Rev 1.29: Januar 2008
+---------------------
+
+  Unrelease Version available only via SVN.
+
+
+Rev 1.28: 02. July, 2007
+---------------------------
+ 
+  Library changes:
+  * Interface for the dynamic library changed and extended to create an interface 
+    using pure C functions only. 
+  * mupInit() removed
+
+  Build system:
+   * MSVC7 Project files removed in favor of MSVC8
+
+  Bugfixes:
+   * The dynamic library did not build on other systems than linux due to a misplaced 
+     preprocessor definition. This is fixed now.
+
+
+Rev 1.27:
+---------------------------
+
+  Build system:
+   * Modified build\ directory layout introducing some subfolders 
+     for the various IDE supported
+   * Project files for BCB and MSVC7 added
+   * Switched to use bakefile 0.2.1 which now correctly creates the 
+     "make uninstall" target for autoconf's Makefile.in
+   * Now the library debug builds are named "muparserd" instead of "muparser"
+     to allow multiple mixed release/debug builds to coexist; so e.g. on Windows
+     when building with DEBUG=1, you'll get "muparserd.lib" instead of "muparser.lib"
+
+  New Features:
+   * Factory functions can now take a user defined pointer
+   * String functions can now be used with up to two additional 
+     double parameters
+   * Support for UNICODE character types added
+   * Infix operator priority can now be changed by the user
+
+  Bugfixes:
+   * An internal error was raised when evaluating an empty 
+     expressions
+   * The error message raised in case of name collisions between 
+     implicitely defined variables and postfix operators did contain
+     misleading data.
+
+
+Rev 1.26: (unofficial release)
+------------------------------
+
+  New Features:
+   * Unary operator precedence can now be changed by the user.
+
+
+Rev 1.25: 5. February, 2006
+---------------------------
+
+  Build system: (special thanks to Francesco Montorsi for implementing it!)
+    * created a bakefile-based build system which adds support for the following win32 compilers:
+      -> MS visual C++ (6 and .NET)
+      -> BorlandC++ (5 or greater)
+      -> Mingw32 (tested with gcc 3.2)
+      -> Watcom (not tested)
+      and for GCC on Unix (using a standard autoconf's configure script).
+
+  Compatibility improvements:
+    * fixed some small warnings when using -Wall with GCC on Unix
+    * added inclusion guards for win32-specific portions of code
+    * added fixes that remove compiler warnings on Intel C++ and the Solaris C++ compiler.
+
+
+Rev 1.24: 29. October, 2005
+---------------------------
+
+Changes:
+
+  Compatibility improvements:
+    * parser now works on 64 bit compilers
+    * (bytecode base datatype can now be changed freely)
+
+
+Rev 1.23: 19. October, 2005
+---------------------------
+
+Changes:
+
+  Bugfixes:
+    * Variable factory examples in Example1.cpp and Example3.cpp contained a subtle bug.
+
+  New features:
+    * Added a MSVC6 project file and introduced muParserFixes.h in order to make it compile with MSVC6
+
+
+Rev 1.22: October, 2005
+-----------------------
+
+Release notes:
+
+All features of Version 1.22 are similar to Version 1.21. Version 1.22 fixes a compilation issue with
+gcc 4.0. In order to fix this issue I rewrote part of the library to remove some unnecessary templates. 
+This should make the code cleaner. The Borland Project files were removed. If you want to use it 
+with Borland either use the dll version or create your own project files. I can't support it since I don't 
+have this compiler at hand.
+
+Changes:
+
+  Project Changes:
+    * Borland project files removed
+      (The code should still compile with BCB but I cant provide you with project files)
+
+  Internal Changes:
+    * unnecessary template files have been removed:
+        - new files: muParserError.cpp, muParserTokenReader.cpp, muParserCallback.cpp
+        - removed Files: muIParserTypes.h
+
+
+Rev 1.2 / 1.21: April, 2005
+---------------------------
+
+Release Notes:
+First of all the interface has changed so this version is not backwards compatible.
+After receiving a couple of questions about it, this version features support for
+user defined binary operators. Consequently the built in operators can now be 
+turned off, thus you can deactivate them and write complete customized parser
+subclasses that only contain the functionality you want. Another new feature is 
+the introduction of callback functions taking string arguments, implicit 
+generation of variables and the Assignement operator.
+
+  Functionality
+    * New built in operator: xor; Logical xor.
+    * New built in operator: Assignement operator; Defining variables in terms of 
+                             other variables/constants
+    * New feature: Strings as arguments for callback functions
+    * New feature: User defined binary operators
+    * New feature: ParserInt a class with a sample implementation for
+                     integer numbers.
+    * New feature: Callbacks to value regognition functions.
+
+    * Removed:  all predefined postfix operators have been removed.
+    * New project file:  Now comes with a ready to use windows DLL.
+    * New project file:  Makefile for cygwin now included.
+    * New example:  Example3 shows usage of the DLL.
+
+  Interface changes
+    * New member function: DefineOprt For adding user defined binary operators.
+    * New member function: EnableBuiltInOprt(bool) Enables/Disables built in 
+                           binary operators.
+    * New member function: AddValIdent(...) to add callbacks for custom value 
+                           recognition functions.
+    * Removed: SetVar(), SetConst().
+    * Renamed: Most interface functions have been renamed
+    * Changed: The type for multiargument callbacks multfun_type has changed. 
+               It no longer takes a std::vector as input.
+
+  Internal changes
+    * new class muParserTokenReader.h encapsulates the token identification 
+      and token assignement.
+    * Internal handling of function callbacks unified as a result the performance 
+      of the bytecode evaluation increased.
+
+
+Rev 1.10 : December 30, 2004
+----------------------------
+
+Release Notes:
+This version does not contain major new feature compared to V1.07 but its internal structure has
+changed significantly. The String parsing routine is slower than the one of V1.07 but bytecode
+parsing is equally fast. On the other hand the error messages of V1.09 are more flexible and you
+can change its value datatype. It should work on 64-bit systems. For this reason I supply both
+versions for download. If you use V1.07 and are happy with it there is no need for updating
+your version.
+
+    * New example program: Archive now contains two demo programs: One for standard C++ and one for
+                           managed C++.
+    * New member function: RemoveVar(...) can be used for removing a single variable from the internal 
+                           storage.
+    * New member function: GetVar() can be used for querying the variable names and pointers of all
+                           variables defined in the parser.
+    * New member function: GetConst() can be used for querying all defined constants and their values.
+    * New member function: GetFunDef() can be used for querying all defined functions and the number of
+                           arguments they expect.
+    * Internal structure changed; hanging base datatype at compile time is now possible.
+    * Bugfix: Postfix operator parsing could fail in certain cases; This has been fixed now.
+    * Bugfix: Variable names must will now be tested if they conflict with constant or function names.
+    * Internal change:  Removed most dependencies from the C-string libraries.
+    * Internal change:  Bytecode is now stored in a separate class: ParserByteCode.h
+    * Internal change:  GetUsedVar() does no longer require that variables are defined at time of call.
+    * Internal change:  Error treatment changed. ParserException is no longer derived from
+                        std::runtime_error; Internal treatment of Error messages changed.
+    * New functions in Parser interface: ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()
+                        they are used for defining the charset allowed for variable-, operator- and
+                        function names.
+
+
+Rev 1.09 : November 20, 2004
+----------------------------
+
+    * New member function:  RemoveVar(...) can be used for removing a single variable from the internal 
+                            storage.
+    * Internal structure changed; changing base datatype at compile time is now possible.
+    * Bug fix: Postfix operator parsing could fail in certain cases; This has been fixed now.
+    * Internal change:  Removed most dependencies from the C-string libraries.
+    * Internal change:  Bytecode is now stored in a seperate class: ParserByteCode.h.
+    * Internal change:  GetUsedVar() does no longer require that variables are defined at time of call.
+    * Internal change:  Error treatment changed. ParserException is no longer derived from 
+                        std::runtime_error; Internal treatment of Error messages changed.
+    * New functions in Parser interface; ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()
+      they are used for defining the charset allowed for variable-, operator- and function names.
+
+
+Rev 1.08 : November, 2004 
+-------------------------
+
+    * unpublished; experimental template version with respect to data type and underlying string
+      type (string <-> widestring). The idea was dropped...
+
+
+Rev 1.07 : September 4 2004
+---------------------------
+
+    * Improved portability; Changes to make life for MSVC 6 user easier, there are probably still some
+      issues left.
+    * Improved portability; Changes in order to allow compiling on BCB.
+    * New function; value_type Diff(value_type *a_Var, value_type a_fPos) 4th order Differentiation with
+      respect to a certain variable; added in muParser.h.
+
+
+Rev 1.06 : August 20 2004
+-------------------------
+
+    * Volatile functions added; All overloaded AddFun(...) functions can now take a third parameter
+      indicating that the function can not be optimized.
+    * Internal changes: muParserStack.h simplified; refactorings
+    * Parser is now distributed under the MIT License; all comments changed accordingly.
+
+
+Rev 1.05 : August 20 2004
+-------------------------
+
+    * Variable/constant names will now be checked for invalid characters.
+    * Querying the names of all variables used in an expression is now possible; new function: GetUsedVar().
+    * Disabling bytecode parsing is now possible; new function: EnableByteCode(bool bStat).
+    * Predefined functions with variable number of arguments added: sum, avg, min, max.
+    * Unary prefix operators added; new functions: AddPrefixOp(...), ClearPrefixOp().
+    * Postfix operator interface names changed; new function names: AddPostfixOp(...), ClearPostfixOp().
+    * Hardcoded sign operators removed in favor of prefix operators; bytecode format changed accordingly.
+    * Internal changes: static array removed in Command code calculation routine; misc. changes.
+
+
+Rev 1.04 : August 16 2004
+-------------------------
+
+    * Support for functions with variable number of arguments added.
+    * Internal structure changed; new: ParserBase.h, ParserBase.cpp; removed: ParserException.h;
+      changed: Parser.h, Parser.cpp.
+    * Bug in the bytecode calculation function fixed (affected the unary minus operator).
+    * Optimizer can be deactivated; new function: EnableOptimizer(bool bStat).
+
+
+Rev 1.03 : August 10 2004
+-------------------------
+
+    * Support for user-defined unary postfix operators added; new functions: AddPostOp(), InitPostOp(),
+      ClearPostOp().
+    * Minor changes to the bytecode parsing routine.
+    * User defined functions can now have up to four parameters.
+    * Performance optimized: simple formula optimization added; (precalculation of constant parts of the
+      expression).
+    * Bug fixes: Multi-arg function parameters, constant name lookup and unary minus did not work properly.
+
+
+Rev 1.02 : July 30 2004
+-----------------------
+
+    * Support for user defined constants added; new functions: InitConst(), AddConst(), SetConst(),
+      ClearConst().
+    * Single variables can now be added using AddVar(); you have now the choice of adding them either
+      one by one or all at the same time using SetVar(const varmap_type &a_vVar).
+    * Internal handling of variables changed, is now similar to function handling.
+    * Virtual destructor added; InitFun(), InitConst() are now virtual too thus making it possible to
+      derive new parsers with a modified set of default functions and constants.
+    * Support for user defined functions with 2 or 3 parameters added; bytecode format changed to hold
+      function parameter count.
+
+
+Rev 1.01 : July 23 2004
+-----------------------
+
+    * Support for user defined functions has been added; new functions: AddFun(), ClearFun(),
+      InitFunctions().
+    * Built in constants have been removed; the parser contained undocumented built in
+      constants pi, e.
+      There was the possibility of name conflicts with user defined variables.
+    * Setting multiple variables with SetVar can now be done with a map of names and pointers as the only
+      argument. For this reason, a new type Parser::varmap_type was added. The old version that took 3
+      arguments (array of names, array of pointers, and array length) is now marked as deprecated.
+    * The names of logarithm functions have changed. The new names are: log2 for base 2, log10 or log for
+      base 10, and ln for base e.
+
+
+Rev 1.00 : July 21 2004
+-----------------------
+
+    * Initial release
diff --git a/source/ThirdParty/MuParser/Install.txt b/source/ThirdParty/MuParser/Install.txt
new file mode 100644
index 0000000000000000000000000000000000000000..95d365de3ccd03b52a8ff3346fa6e4276346c3a2
--- /dev/null
+++ b/source/ThirdParty/MuParser/Install.txt
@@ -0,0 +1,133 @@
+#######################################################################
+#                                                                     #
+#                                                                     #
+#                 __________                                          #
+#    _____   __ __\______   \_____  _______  ______  ____ _______     #
+#   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \    #
+#  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/    #
+#  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|       #
+#        \/                       \/            \/      \/            #
+#					  Fast math parser Library    #
+#                                                                     #
+#  Copyright (C) 2012 Ingo Berg                                       #
+#                                                                     #
+#  Web:     muparser.beltoforion.de                                   #
+#  e-mail:  muparser@beltoforion.de                                   #
+#                                                                     #
+#                                                                     #
+#######################################################################
+
+
+
+ Contents
+ ========
+
+ 1. Installation on win32
+ 2. Installation on unix
+    2.1 Other miscellaneous info Unix-specific
+ 3. Where to ask for help
+
+
+
+ 1. Installation on win32
+ ========================
+
+ muParser supports various win32 command-line compilers:
+ -> mingw
+ -> watcom
+ -> microsoft CL
+ and provides also the project files for MSVC6 IDE.
+
+ In order to compile muParser from makefiles, open an MSDOS
+ prompt and then move to the muParser/build directory and
+ type:
+   
+   mingw32-make -fmakefile.mingw    for mingw
+   nmake -fmakefile.vc              for msvc
+   make -fmakefile.bcc              for borland
+   wmake -fmakefile.wat             for watcom
+
+ All makefiles supports the following options:
+
+        # Set to 1 to build debug version [0,1]
+        #   0 - Release
+        #   1 - Debug
+        DEBUG = 0
+
+        # Set to 1 to build shared (DLL) version [0,1]
+        #   0 - Static
+        #   1 - DLL
+        SHARED = 0
+
+        # Set to 1 to compile samples [0,1]
+        SAMPLES = 1
+
+ The muParser library is created in the 'lib' folder and the sample
+ binaries are created in samples\example1 or samples\example2.
+
+ NOTE: samples\example1 can be compiled *only* when building
+       muParser as a STATIC library (SHARED=0).
+       samples\example2 can be compiled *only* when building
+       muParser as a SHARED library (SHARED=1).
+
+
+
+ 2. Installation on Unix/Linux
+ =============================
+
+ muParser can be installed just extracting the sources somewhere
+ and then, from a terminal, typing:
+
+   cd [path to muParser]
+   ./configure [--enable-shared=yes/no] [--enable-samples=yes/no]
+               [--enable-debug=yes/no]
+   make
+   [sudo*] make install
+   [sudo*] ldconfig
+   cd samples/example1
+   ./example1
+
+ * = this command must be executed with root permissions and thus
+     you have to use 'sudo' or just 'su' to gain root access.
+     Note that installation and ldconfig are not strictly required unless
+     you built in shared mode.
+
+ The "make" step will create the muParser library in 'lib' and the
+ sample binary in samples/example1.
+ The samples/example2 is win32-specific and thus won't be built.
+
+
+
+ 2.1 Other miscellaneous info Unix-specific
+ ==========================================
+
+ If you don't like to have your muParser folder filled by temporary
+ files created by GCC, then you can do the following:
+
+    mkdir mybuild && cd mybuild && ../configure && make
+
+ to put all object files in the "mybuild" directory.
+
+ If you want to use muParser library in your programs, you can use
+ the pkg-config program (this works only if muParser was installed
+ with 'make install' !). The commands:
+
+   pkg-config muparser --cflags
+   pkg-config muparser --libs
+
+ will return all useful info you need to build your programs against
+ muParser !
+
+
+
+ 3. Where to ask for help
+ ========================
+
+ If you find problems with either compilation, installation or usage
+ of muParser, then you can ask in the muParser forum at:
+
+  https://sourceforge.net/forum/forum.php?forum_id=462843
+
+ For more info about muParser, visit:
+  http://sourceforge.net/projects/muparser/
+  http://muparser.sourceforge.net
diff --git a/source/ThirdParty/MuParser/License.txt b/source/ThirdParty/MuParser/License.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c4c0d2b1313f5530c7357a6df9998fd0c418c49d
--- /dev/null
+++ b/source/ThirdParty/MuParser/License.txt
@@ -0,0 +1,35 @@
+#######################################################################
+#                                                                     #
+#                                                                     #
+#                 __________                                          #
+#    _____   __ __\______   \_____  _______  ______  ____ _______     #
+#   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \    #
+#  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/    #
+#  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|       #
+#        \/                       \/            \/      \/            #
+#					  Fast math parser Library    #
+#                                                                     #
+#  Copyright (C) 2011 Ingo Berg                                       #
+#                                                                     #
+#  Web:     muparser.beltoforion.de                                   #
+#  e-mail:  muparser@beltoforion.de                                   #
+#                                                                     #
+#                                                                     #
+#######################################################################
+
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+  OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/source/ThirdParty/MuParser/docs/Doxyfile b/source/ThirdParty/MuParser/docs/Doxyfile
new file mode 100644
index 0000000000000000000000000000000000000000..9793afe34369e1dc4c9300d19984a89952d06ee1
--- /dev/null
+++ b/source/ThirdParty/MuParser/docs/Doxyfile
@@ -0,0 +1,1563 @@
+# Doxyfile 1.6.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "muParser API -"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 1.35
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = html/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = YES
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, 
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 16
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses. 
+# With this tag you can assign which parser to use for a given extension. 
+# Doxygen has a built-in mapping, but you can override or extend it using this tag. 
+# The format is ext=language, where ext is a file extension, and language is one of 
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, 
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat 
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), 
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set
+# FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to 
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen to replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk. 
+# When the cache is full, less often used symbols will be written to disk. 
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penality. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will rougly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen 
+# will list include files with double quotes in the documentation 
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = NO
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index 
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by 
+# doxygen. The layout file controls the global structure of the generated output files 
+# in an output format independent way. The create the layout file that represents 
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a 
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name 
+# of the layout file.
+
+LAYOUT_FILE            = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = html/misc/Main.txt \
+                         html/misc/example.txt \
+                         ../src/ \
+                         ../include/
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = html/misc/
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
+# link to the source code.  Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = classdocu/
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = html/misc/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML 
+# page will contain the date and time when the page was generated. Setting 
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER 
+# are set, an additional index file will be generated that can be used as input for 
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated 
+# HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. 
+# For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's 
+# filter section matches. 
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file.
+
+QHG_LOCATION           = 
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files  
+# will be generated, which together with the HTML files, form an Eclipse help  
+# plugin. To install this plugin and make it available under the help contents 
+# menu in Eclipse, the contents of the directory containing the HTML and XML 
+# files needs to be copied into the plugins directory of eclipse. The name of 
+# the directory within the plugins directory should be the same as 
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin 
+# the directory name containing the HTML and XML files should also have 
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
+# structure should be generated to display hierarchical information. 
+# If the tag value is set to YES, a side panel will be generated 
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript 
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should 
+# typically be disabled. For large projects the javascript based search engine 
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index 
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvances is that it is more difficult to setup 
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name. 
+# Note that when enabling USE_PDFLATEX this option is only used for 
+# generating bitmaps for formulas in the HTML output, but not in the 
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links. 
+# Note that each tag file must have a unique name 
+# (where the name does NOT include the path) 
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = NO
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include 
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif 
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = jpg
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = "C:\Program Files (x86)\Graphviz2.20\bin"
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
diff --git a/source/ThirdParty/MuParser/docs/muparser_doc.html b/source/ThirdParty/MuParser/docs/muparser_doc.html
new file mode 100644
index 0000000000000000000000000000000000000000..09dbba14393dc6c06a6a64d126f8ad29439e4146
--- /dev/null
+++ b/source/ThirdParty/MuParser/docs/muparser_doc.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html style="height:100%;">
+<head>
+</head>
+
+<body style="height:100%; overflow:hidden;"> 
+
+  <div style="border: 0px; position:absolute; top:0px; left:0px; width:100%; bottom:0px; padding:0px; margin:0px;"> 
+    <iframe src="http://muparser.beltoforion.de" style="border: 0px; width:100%; height:100%;">
+    Sorry, your browser doesn't support IFrames. Click <a href="http://muparser.beltoforion.de">here</a> to load the muparser documentation directly.
+    </iframe>
+  </div>
+</body>
+
+</html>
diff --git a/source/ThirdParty/MuParser/include/muParser.h b/source/ThirdParty/MuParser/include/muParser.h
new file mode 100644
index 0000000000000000000000000000000000000000..39fe137fe7386dc793aef31bff94296cfe6b6e12
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParser.h
@@ -0,0 +1,115 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+#ifndef MU_PARSER_H
+#define MU_PARSER_H
+
+//--- Standard includes ------------------------------------------------------------------------
+#include <vector>
+
+//--- Parser includes --------------------------------------------------------------------------
+#include "muParserBase.h"
+#include "muParserTemplateMagic.h"
+
+/** \file
+    \brief Definition of the standard floating point parser.
+*/
+
+namespace mu
+{
+  /** \brief Mathematical expressions parser.
+    
+    Standard implementation of the mathematical expressions parser. 
+    Can be used as a reference implementation for subclassing the parser.
+
+    <small>
+    (C) 2011 Ingo Berg<br>
+    muparser(at)beltoforion.de
+    </small>
+  */
+  /* final */ class Parser : public ParserBase
+  {
+  public:
+
+    Parser();
+
+    virtual void InitCharSets();
+    virtual void InitFun();
+    virtual void InitConst();
+    virtual void InitOprt();
+    virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);
+
+    value_type Diff(value_type *a_Var, 
+                    value_type a_fPos, 
+                    value_type a_fEpsilon = 0) const;
+
+  protected:
+
+    // Trigonometric functions
+    static value_type  Sin(value_type);
+    static value_type  Cos(value_type);
+    static value_type  Tan(value_type);
+    static value_type  Tan2(value_type, value_type);
+    // arcus functions
+    static value_type  ASin(value_type);
+    static value_type  ACos(value_type);
+    static value_type  ATan(value_type);
+    static value_type  ATan2(value_type, value_type);
+
+    // hyperbolic functions
+    static value_type  Sinh(value_type);
+    static value_type  Cosh(value_type);
+    static value_type  Tanh(value_type);
+    // arcus hyperbolic functions
+    static value_type  ASinh(value_type);
+    static value_type  ACosh(value_type);
+    static value_type  ATanh(value_type);
+    // Logarithm functions
+    static value_type  Log2(value_type);  // Logarithm Base 2
+    static value_type  Log10(value_type); // Logarithm Base 10
+    static value_type  Ln(value_type);    // Logarithm Base e (natural logarithm)
+    // misc
+    static value_type  Exp(value_type);
+    static value_type  Abs(value_type);
+    static value_type  Sqrt(value_type);
+    static value_type  Rint(value_type);
+    static value_type  Sign(value_type);
+
+    // Prefix operators
+    // !!! Unary Minus is a MUST if you want to use negative signs !!!
+    static value_type  UnaryMinus(value_type);
+    static value_type  UnaryPlus(value_type);
+
+    // Functions with variable number of arguments
+    static value_type Sum(const value_type*, int);  // sum
+    static value_type Avg(const value_type*, int);  // mean value
+    static value_type Min(const value_type*, int);  // minimum
+    static value_type Max(const value_type*, int);  // maximum
+
+    static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal);
+  };
+} // namespace mu
+
+#endif
+
diff --git a/source/ThirdParty/MuParser/include/muParserBase.h b/source/ThirdParty/MuParser/include/muParserBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..beb15bb198080beb26543f131c65c7625b3134b3
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserBase.h
@@ -0,0 +1,317 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+#ifndef MU_PARSER_BASE_H
+#define MU_PARSER_BASE_H
+
+//--- Standard includes ------------------------------------------------------------------------
+#include <cmath>
+#include <string>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <locale>
+#include <limits.h>
+
+//--- Parser includes --------------------------------------------------------------------------
+#include "muParserDef.h"
+#include "muParserStack.h"
+#include "muParserTokenReader.h"
+#include "muParserBytecode.h"
+#include "muParserError.h"
+
+
+namespace mu
+{
+/** \file
+    \brief This file contains the class definition of the muparser engine.
+*/
+
+//--------------------------------------------------------------------------------------------------
+/** \brief Mathematical expressions parser (base parser engine).
+    \author (C) 2013 Ingo Berg
+
+  This is the implementation of a bytecode based mathematical expressions parser. 
+  The formula will be parsed from string and converted into a bytecode. 
+  Future calculations will be done with the bytecode instead the formula string
+  resulting in a significant performance increase. 
+  Complementary to a set of internally implemented functions the parser is able to handle 
+  user defined functions and variables. 
+*/
+class ParserBase 
+{
+friend class ParserTokenReader;
+
+private:
+
+    /** \brief Typedef for the parse functions. 
+    
+      The parse function do the actual work. The parser exchanges
+      the function pointer to the parser function depending on 
+      which state it is in. (i.e. bytecode parser vs. string parser)
+    */
+    typedef value_type (ParserBase::*ParseFunction)() const;  
+
+    /** \brief Type used for storing an array of values. */
+    typedef std::vector<value_type> valbuf_type;
+
+    /** \brief Type for a vector of strings. */
+    typedef std::vector<string_type> stringbuf_type;
+
+    /** \brief Typedef for the token reader. */
+    typedef ParserTokenReader token_reader_type;
+    
+    /** \brief Type used for parser tokens. */
+    typedef ParserToken<value_type, string_type> token_type;
+
+    /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */
+    static const int s_MaxNumOpenMPThreads = 16;
+
+ public:
+
+    /** \brief Type of the error class. 
+    
+      Included for backwards compatibility.
+    */
+    typedef ParserError exception_type;
+
+    static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
+
+    ParserBase(); 
+    ParserBase(const ParserBase &a_Parser);
+    ParserBase& operator=(const ParserBase &a_Parser);
+
+    virtual ~ParserBase();
+    
+	  value_type  Eval() const;
+    value_type* Eval(int &nStackSize) const;
+    void Eval(value_type *results, int nBulkSize);
+
+    int GetNumResults() const;
+
+    void SetExpr(const string_type &a_sExpr);
+    void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);
+
+    void SetDecSep(char_type cDecSep);
+    void SetThousandsSep(char_type cThousandsSep = 0);
+    void ResetLocale();
+
+    void EnableOptimizer(bool a_bIsOn=true);
+    void EnableBuiltInOprt(bool a_bIsOn=true);
+
+    bool HasBuiltInOprt() const;
+    void AddValIdent(identfun_type a_pCallback);
+
+    /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) 
+        \brief Define a parser function without arguments.
+        \param a_strName Name of the function
+        \param a_pFun Pointer to the callback function
+        \param a_bAllowOpt A flag indicating this function may be optimized
+    */
+    template<typename T>
+    void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true)
+    {
+      AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() );
+    }
+
+    void DefineOprt(const string_type &a_strName, 
+                    fun_type2 a_pFun, 
+                    unsigned a_iPri=0, 
+                    EOprtAssociativity a_eAssociativity = oaLEFT,
+                    bool a_bAllowOpt = false);
+    void DefineConst(const string_type &a_sName, value_type a_fVal);
+    void DefineStrConst(const string_type &a_sName, const string_type &a_strVal);
+    void DefineVar(const string_type &a_sName, value_type *a_fVar);
+    void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);
+    void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true);
+
+    // Clear user defined variables, constants or functions
+    void ClearVar();
+    void ClearFun();
+    void ClearConst();
+    void ClearInfixOprt();
+    void ClearPostfixOprt();
+    void ClearOprt();
+    
+    void RemoveVar(const string_type &a_strVarName);
+    const varmap_type& GetUsedVar() const;
+    const varmap_type& GetVar() const;
+    const valmap_type& GetConst() const;
+    const string_type& GetExpr() const;
+    const funmap_type& GetFunDef() const;
+    string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;
+
+    const char_type ** GetOprtDef() const;
+    void DefineNameChars(const char_type *a_szCharset);
+    void DefineOprtChars(const char_type *a_szCharset);
+    void DefineInfixOprtChars(const char_type *a_szCharset);
+
+    const char_type* ValidNameChars() const;
+    const char_type* ValidOprtChars() const;
+    const char_type* ValidInfixOprtChars() const;
+
+    void SetArgSep(char_type cArgSep);
+    char_type GetArgSep() const;
+    
+    void  Error(EErrorCodes a_iErrc, 
+                int a_iPos = (int)mu::string_type::npos, 
+                const string_type &a_strTok = string_type() ) const;
+
+ protected:
+	  
+    void Init();
+
+    virtual void InitCharSets() = 0;
+    virtual void InitFun() = 0;
+    virtual void InitConst() = 0;
+    virtual void InitOprt() = 0; 
+
+    virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);
+
+    static const char_type *c_DefaultOprt[]; 
+    static std::locale s_locale;  ///< The locale used by the parser
+    static bool g_DbgDumpCmdCode;
+    static bool g_DbgDumpStack;
+
+    /** \brief A facet class used to change decimal and thousands separator. */
+    template<class TChar>
+    class change_dec_sep : public std::numpunct<TChar>
+    {
+    public:
+      
+      explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
+        :std::numpunct<TChar>()
+        ,m_nGroup(nGroup)
+        ,m_cDecPoint(cDecSep)
+        ,m_cThousandsSep(cThousandsSep)
+      {}
+      
+    protected:
+      
+      virtual char_type do_decimal_point() const
+      {
+        return m_cDecPoint;
+      }
+
+      virtual char_type do_thousands_sep() const
+      {
+        return m_cThousandsSep;
+      }
+
+      virtual std::string do_grouping() const 
+      { 
+		// fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
+		// courtesy of Jens Bartsch
+		// original code:
+		//        return std::string(1, (char)m_nGroup); 
+		// new code:
+		return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
+      }
+
+    private:
+
+      int m_nGroup;
+      char_type m_cDecPoint;  
+      char_type m_cThousandsSep;
+    };
+
+ private:
+
+    void Assign(const ParserBase &a_Parser);
+    void InitTokenReader();
+    void ReInit() const;
+
+    void AddCallback( const string_type &a_strName, 
+                      const ParserCallback &a_Callback, 
+                      funmap_type &a_Storage,
+                      const char_type *a_szCharSet );
+
+    void ApplyRemainingOprt(ParserStack<token_type> &a_stOpt,
+                                ParserStack<token_type> &a_stVal) const;
+    void ApplyBinOprt(ParserStack<token_type> &a_stOpt,
+                      ParserStack<token_type> &a_stVal) const;
+
+    void ApplyIfElse(ParserStack<token_type> &a_stOpt,
+                     ParserStack<token_type> &a_stVal) const;
+
+    void ApplyFunc(ParserStack<token_type> &a_stOpt,
+                   ParserStack<token_type> &a_stVal, 
+                   int iArgCount) const; 
+
+    token_type ApplyStrFunc(const token_type &a_FunTok,
+                            const std::vector<token_type> &a_vArg) const;
+
+    int GetOprtPrecedence(const token_type &a_Tok) const;
+    EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const;
+
+    void CreateRPN() const;
+
+    value_type ParseString() const; 
+    value_type ParseCmdCode() const;
+    value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;
+
+    void  CheckName(const string_type &a_strName, const string_type &a_CharSet) const;
+    void  CheckOprt(const string_type &a_sName,
+                    const ParserCallback &a_Callback,
+                    const string_type &a_szCharSet) const;
+
+    void StackDump(const ParserStack<token_type > &a_stVal, 
+                   const ParserStack<token_type > &a_stOprt) const;
+
+    /** \brief Pointer to the parser function. 
+    
+      Eval() calls the function whose address is stored there.
+    */
+    mutable ParseFunction  m_pParseFormula;
+    mutable ParserByteCode m_vRPN;        ///< The Bytecode class.
+    mutable stringbuf_type  m_vStringBuf; ///< String buffer, used for storing string function arguments
+    stringbuf_type  m_vStringVarBuf;
+
+    std::auto_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
+
+    funmap_type  m_FunDef;         ///< Map of function names and pointers.
+    funmap_type  m_PostOprtDef;    ///< Postfix operator callbacks
+    funmap_type  m_InfixOprtDef;   ///< unary infix operator.
+    funmap_type  m_OprtDef;        ///< Binary operator callbacks
+    valmap_type  m_ConstDef;       ///< user constants.
+    strmap_type  m_StrVarDef;      ///< user defined string constants
+    varmap_type  m_VarDef;         ///< user defind variables.
+
+    bool m_bBuiltInOp;             ///< Flag that can be used for switching built in operators on and off
+
+    string_type m_sNameChars;      ///< Charset for names
+    string_type m_sOprtChars;      ///< Charset for postfix/ binary operator tokens
+    string_type m_sInfixOprtChars; ///< Charset for infix operator tokens
+    
+    mutable int m_nIfElseCounter;  ///< Internal counter for keeping track of nested if-then-else clauses
+
+    // items merely used for caching state information
+    mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
+    mutable int m_nFinalResultIdx;
+};
+
+} // namespace mu
+
+#endif
+
diff --git a/source/ThirdParty/MuParser/include/muParserBytecode.h b/source/ThirdParty/MuParser/include/muParserBytecode.h
new file mode 100644
index 0000000000000000000000000000000000000000..39ab39d52d4afac1ffc766baa1cfe490e5d870e8
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserBytecode.h
@@ -0,0 +1,141 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2004-2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+#ifndef MU_PARSER_BYTECODE_H
+#define MU_PARSER_BYTECODE_H
+
+#include <cassert>
+#include <string>
+#include <stack>
+#include <vector>
+
+#include "muParserDef.h"
+#include "muParserError.h"
+#include "muParserToken.h"
+
+/** \file
+    \brief Definition of the parser bytecode class.
+*/
+
+
+namespace mu
+{
+  struct SToken
+  {
+    ECmdCode Cmd;
+    int StackPos;
+
+    union
+    {
+      struct //SValData
+      {
+        value_type *ptr;
+        value_type  data;
+        value_type  data2;
+      } Val;
+
+      struct //SFunData
+      {
+        // Note: generic_fun_type is merely a placeholder. The real type could be 
+        //       anything between gun_type1 and fun_type9. I can't use a void
+        //       pointer due to constraints in the ANSI standard which allows
+        //       data pointers and function pointers to differ in size.
+        generic_fun_type ptr;
+        int   argc;
+        int   idx;
+      } Fun;
+
+      struct //SOprtData
+      {
+        value_type *ptr;
+        int offset;
+      } Oprt;
+    };
+  };
+  
+  
+  /** \brief Bytecode implementation of the Math Parser.
+
+  The bytecode contains the formula converted to revers polish notation stored in a continious
+  memory area. Associated with this data are operator codes, variable pointers, constant 
+  values and function pointers. Those are necessary in order to calculate the result.
+  All those data items will be casted to the underlying datatype of the bytecode.
+
+  \author (C) 2004-2013 Ingo Berg 
+*/
+class ParserByteCode
+{
+private:
+
+    /** \brief Token type for internal use only. */
+    typedef ParserToken<value_type, string_type> token_type;
+
+    /** \brief Token vector for storing the RPN. */
+    typedef std::vector<SToken> rpn_type;
+
+    /** \brief Position in the Calculation array. */
+    unsigned m_iStackPos;
+
+    /** \brief Maximum size needed for the stack. */
+    std::size_t m_iMaxStackSize;
+    
+    /** \brief The actual rpn storage. */
+    rpn_type  m_vRPN;
+
+    bool m_bEnableOptimizer;
+
+    void ConstantFolding(ECmdCode a_Oprt);
+
+public:
+
+    ParserByteCode();
+    ParserByteCode(const ParserByteCode &a_ByteCode);
+    ParserByteCode& operator=(const ParserByteCode &a_ByteCode);
+    void Assign(const ParserByteCode &a_ByteCode);
+
+    void AddVar(value_type *a_pVar);
+    void AddVal(value_type a_fVal);
+    void AddOp(ECmdCode a_Oprt);
+    void AddIfElse(ECmdCode a_Oprt);
+    void AddAssignOp(value_type *a_pVar);
+    void AddFun(generic_fun_type a_pFun, int a_iArgc);
+    void AddBulkFun(generic_fun_type a_pFun, int a_iArgc);
+    void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx);
+
+    void EnableOptimizer(bool bStat);
+
+    void Finalize();
+    void clear();
+    std::size_t GetMaxStackSize() const;
+    std::size_t GetSize() const;
+
+    const SToken* GetBase() const;
+    void AsciiDump();
+};
+
+} // namespace mu
+
+#endif
+
+
diff --git a/source/ThirdParty/MuParser/include/muParserCallback.h b/source/ThirdParty/MuParser/include/muParserCallback.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef32b4989e34b92c82ad06daf50014022781657c
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserCallback.h
@@ -0,0 +1,118 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2004-2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#ifndef MU_PARSER_CALLBACK_H
+#define MU_PARSER_CALLBACK_H
+
+#include "muParserDef.h"
+
+/** \file
+    \brief Definition of the parser callback class.
+*/
+
+namespace mu
+{
+
+/** \brief Encapsulation of prototypes for a numerical parser function.
+
+    Encapsulates the prototyp for numerical parser functions. The class
+    stores the number of arguments for parser functions as well
+    as additional flags indication the function is non optimizeable.
+    The pointer to the callback function pointer is stored as void* 
+    and needs to be casted according to the argument count.
+    Negative argument counts indicate a parser function with a variable number
+    of arguments. 
+
+    \author (C) 2004-2011 Ingo Berg
+*/
+class ParserCallback
+{
+public:
+    ParserCallback(fun_type0  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type1  a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC);
+    ParserCallback(fun_type2  a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity);
+    ParserCallback(fun_type2  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type3  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type4  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type5  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type6  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type7  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type8  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type9  a_pFun, bool a_bAllowOpti);
+    ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti);
+
+    ParserCallback(bulkfun_type0  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type1  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type2  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type3  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type4  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type5  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type6  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type7  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type8  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type9  a_pFun, bool a_bAllowOpti);
+    ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti);
+
+    ParserCallback(multfun_type a_pFun, bool a_bAllowOpti);
+    ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti);
+    ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti);
+    ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti);
+    ParserCallback();
+    ParserCallback(const ParserCallback &a_Fun);
+    
+    ParserCallback* Clone() const;
+
+    bool  IsOptimizable() const;
+    void* GetAddr() const;
+    ECmdCode  GetCode() const;
+    ETypeCode GetType() const;
+    int GetPri()  const;
+    EOprtAssociativity GetAssociativity() const;
+    int GetArgc() const;
+
+private:
+    void *m_pFun;                   ///< Pointer to the callback function, casted to void
+    
+    /** \brief Number of numeric function arguments
+    
+        This number is negative for functions with variable number of arguments. in this cases
+        they represent the actual number of arguments found.
+    */
+    int   m_iArgc;      
+    int   m_iPri;                   ///< Valid only for binary and infix operators; Operator precedence.
+    EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators 
+    ECmdCode  m_iCode;
+    ETypeCode m_iType;
+    bool  m_bAllowOpti;             ///< Flag indication optimizeability 
+};
+
+//------------------------------------------------------------------------------
+/** \brief Container for Callback objects. */
+typedef std::map<string_type, ParserCallback> funmap_type; 
+
+} // namespace mu
+
+#endif
+
diff --git a/source/ThirdParty/MuParser/include/muParserDLL.h b/source/ThirdParty/MuParser/include/muParserDLL.h
new file mode 100644
index 0000000000000000000000000000000000000000..155ef8a06c449a3e834cb6c484f94a5398a7f9f8
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserDLL.h
@@ -0,0 +1,241 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+#ifndef MU_PARSER_DLL_H
+#define MU_PARSER_DLL_H
+
+#if defined(WIN32) || defined(_WIN32)
+    #ifdef MUPARSERLIB_EXPORTS
+        #define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl
+    #else
+        #define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl
+    #endif
+#else
+    #define API_EXPORT(TYPE) TYPE
+#endif
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** \file 
+    \brief This file contains the DLL interface of muparser.
+*/
+
+// Basic types
+typedef void*  muParserHandle_t;    // parser handle
+
+#ifndef _UNICODE
+    typedef char   muChar_t;            // character type
+#else
+    typedef wchar_t   muChar_t;            // character type
+#endif
+
+typedef int    muBool_t;            // boolean type
+typedef int    muInt_t;             // integer type 
+typedef double muFloat_t;           // floating point type
+
+// function types for calculation
+typedef muFloat_t (*muFun0_t )(); 
+typedef muFloat_t (*muFun1_t )(muFloat_t); 
+typedef muFloat_t (*muFun2_t )(muFloat_t, muFloat_t); 
+typedef muFloat_t (*muFun3_t )(muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muFun4_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muFun5_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muFun6_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muFun7_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muFun8_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muFun9_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+
+// Function prototypes for bulkmode functions
+typedef muFloat_t (*muBulkFun0_t )(int, int); 
+typedef muFloat_t (*muBulkFun1_t )(int, int, muFloat_t); 
+typedef muFloat_t (*muBulkFun2_t )(int, int, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muBulkFun3_t )(int, int, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muBulkFun4_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muBulkFun5_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muBulkFun6_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muBulkFun7_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muBulkFun8_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muBulkFun9_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); 
+
+typedef muFloat_t (*muMultFun_t)(const muFloat_t*, muInt_t);
+typedef muFloat_t (*muStrFun1_t)(const muChar_t*);
+typedef muFloat_t (*muStrFun2_t)(const muChar_t*, muFloat_t);
+typedef muFloat_t (*muStrFun3_t)(const muChar_t*, muFloat_t, muFloat_t);
+
+// Functions for parser management
+typedef void (*muErrorHandler_t)(muParserHandle_t a_hParser);           // [optional] callback to an error handler
+typedef muFloat_t* (*muFacFun_t)(const muChar_t*, void*);               // [optional] callback for creating new variables
+typedef muInt_t (*muIdentFun_t)(const muChar_t*, muInt_t*, muFloat_t*); // [optional] value identification callbacks
+
+//-----------------------------------------------------------------------------------------------------
+// Constants
+static const int muOPRT_ASCT_LEFT  = 0;
+static const int muOPRT_ASCT_RIGHT = 1;
+
+static const int muBASETYPE_FLOAT  = 0;
+static const int muBASETYPE_INT    = 1;
+
+//-----------------------------------------------------------------------------------------------------
+//
+//
+// muParser C compatible bindings
+//
+//
+//-----------------------------------------------------------------------------------------------------
+
+
+// Basic operations / initialization  
+API_EXPORT(muParserHandle_t) mupCreate(int nBaseType);
+API_EXPORT(void) mupRelease(muParserHandle_t a_hParser);
+API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser);
+API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t *a_szExpr);
+API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData);
+API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser);
+API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser);
+API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum);
+API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize);
+
+// Defining callbacks / variables / constants
+API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, muBool_t a_bOptimize);
+API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, muBool_t a_bOptimize);
+
+// Defining bulkmode functions
+API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun);
+API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun);
+
+// string functions
+API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun);
+API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun);
+API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun);
+
+API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser, 
+                                   const muChar_t* a_szName, 
+                                   muMultFun_t a_pFun, 
+                                   muBool_t a_bOptimize);
+
+API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser, 
+                                const muChar_t* a_szName, 
+                                muFun2_t a_pFun, 
+                                muInt_t a_nPrec, 
+                                muInt_t a_nOprtAsct,
+                                muBool_t a_bOptimize);
+
+API_EXPORT(void) mupDefineConst( muParserHandle_t a_hParser, 
+                                 const muChar_t* a_szName, 
+                                 muFloat_t a_fVal );
+
+API_EXPORT(void) mupDefineStrConst( muParserHandle_t a_hParser, 
+                                    const muChar_t* a_szName, 
+                                    const muChar_t *a_sVal );
+
+API_EXPORT(void) mupDefineVar( muParserHandle_t a_hParser, 
+                               const muChar_t* a_szName, 
+                               muFloat_t *a_fVar);
+
+API_EXPORT(void) mupDefineBulkVar( muParserHandle_t a_hParser, 
+                               const muChar_t* a_szName, 
+                               muFloat_t *a_fVar);
+
+API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser, 
+                                       const muChar_t* a_szName, 
+                                       muFun1_t a_pOprt, 
+                                       muBool_t a_bOptimize);
+
+
+API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser, 
+                                     const muChar_t* a_szName, 
+                                     muFun1_t a_pOprt, 
+                                     muBool_t a_bOptimize);
+
+// Define character sets for identifiers
+API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);
+API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);
+API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);
+
+// Remove all / single variables
+API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName);
+API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser);
+API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser);
+API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser);
+API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser);
+
+// Querying variables / expression variables / constants
+API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser);
+API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser);
+API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser);
+API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar);
+API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar);
+API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_pVar);
+API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
+API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
+API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep);
+API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser);
+
+// Add value recognition callbacks
+API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t);
+
+// Error handling
+API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser);
+API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser);
+API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler);
+API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser);
+API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser);
+API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser);
+API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser);
+//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser);
+
+// This is used for .NET only. It creates a new variable allowing the dll to
+// manage the variable rather than the .NET garbage collector.
+API_EXPORT(muFloat_t*) mupCreateVar();
+API_EXPORT(void) mupReleaseVar(muFloat_t*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // include guard
diff --git a/source/ThirdParty/MuParser/include/muParserDef.h b/source/ThirdParty/MuParser/include/muParserDef.h
new file mode 100644
index 0000000000000000000000000000000000000000..437f2eaf572c1971292e8ffe7df4b55f53b77ea3
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserDef.h
@@ -0,0 +1,368 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2014 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+#ifndef MUP_DEF_H
+#define MUP_DEF_H
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <map>
+
+#include "muParserFixes.h"
+
+/** \file
+    \brief This file contains standard definitions used by the parser.
+*/
+
+#define MUP_VERSION _T("2.2.5")
+#define MUP_VERSION_DATE _T("20150427; GC")
+
+#define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
+
+/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */
+//#define MUP_MATH_EXCEPTIONS
+
+/** \brief Define the base datatype for values.
+
+  This datatype must be a built in value type. You can not use custom classes.
+  It should be working with all types except "int"!
+*/
+#define MUP_BASETYPE double
+
+/** \brief Activate this option in order to compile with OpenMP support. 
+
+  OpenMP is used only in the bulk mode it may increase the performance a bit. 
+*/
+//#define MUP_USE_OPENMP
+
+#if defined(_UNICODE)
+  /** \brief Definition of the basic parser string type. */
+  #define MUP_STRING_TYPE std::wstring
+
+  #if !defined(_T)
+    #define _T(x) L##x
+  #endif // not defined _T
+#else
+  #ifndef _T
+  #define _T(x) x
+  #endif
+  
+  /** \brief Definition of the basic parser string type. */
+  #define MUP_STRING_TYPE std::string
+#endif
+
+#if defined(_DEBUG)
+  /** \brief Debug macro to force an abortion of the programm with a certain message.
+  */
+  #define MUP_FAIL(MSG)     \
+          {                 \
+            bool MSG=false; \
+            assert(MSG);    \
+          }
+
+    /** \brief An assertion that does not kill the program.
+
+        This macro is neutralised in UNICODE builds. It's
+        too difficult to translate.
+    */
+    #define MUP_ASSERT(COND)                         \
+            if (!(COND))                             \
+            {                                        \
+              stringstream_type ss;                  \
+              ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \
+                 << __FILE__ << _T(" line ")         \
+                 << __LINE__ << _T(".");             \
+              throw ParserError( ss.str() );         \
+            }
+#else
+  #define MUP_FAIL(MSG)
+  #define MUP_ASSERT(COND)
+#endif
+
+
+namespace mu
+{
+#if defined(_UNICODE)
+
+  //------------------------------------------------------------------------------
+  /** \brief Encapsulate wcout. */
+  inline std::wostream& console()
+  {
+    return std::wcout;
+  }
+
+  /** \brief Encapsulate cin. */
+  inline std::wistream& console_in()
+  {
+    return std::wcin;
+  }
+
+#else
+
+  /** \brief Encapsulate cout. 
+  
+    Used for supporting UNICODE more easily.
+  */
+  inline std::ostream& console()
+  {
+    return std::cout;
+  }
+
+  /** \brief Encapsulate cin. 
+
+    Used for supporting UNICODE more easily.
+  */
+  inline std::istream& console_in()
+  {
+    return std::cin;
+  }
+
+#endif
+
+  //------------------------------------------------------------------------------
+  /** \brief Bytecode values.
+
+      \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!
+  */
+  enum ECmdCode
+  {
+    // The following are codes for built in binary operators
+    // apart from built in operators the user has the opportunity to
+    // add user defined operators.
+    cmLE            = 0,   ///< Operator item:  less or equal
+    cmGE            = 1,   ///< Operator item:  greater or equal
+    cmNEQ           = 2,   ///< Operator item:  not equal
+    cmEQ            = 3,   ///< Operator item:  equals
+    cmLT            = 4,   ///< Operator item:  less than
+    cmGT            = 5,   ///< Operator item:  greater than
+    cmADD           = 6,   ///< Operator item:  add
+    cmSUB           = 7,   ///< Operator item:  subtract
+    cmMUL           = 8,   ///< Operator item:  multiply
+    cmDIV           = 9,   ///< Operator item:  division
+    cmPOW           = 10,  ///< Operator item:  y to the power of ...
+    cmLAND          = 11,
+    cmLOR           = 12,
+    cmASSIGN        = 13,  ///< Operator item:  Assignment operator
+    cmBO            = 14,  ///< Operator item:  opening bracket
+    cmBC            = 15,  ///< Operator item:  closing bracket
+    cmIF            = 16,  ///< For use in the ternary if-then-else operator
+    cmELSE          = 17,  ///< For use in the ternary if-then-else operator
+    cmENDIF         = 18,  ///< For use in the ternary if-then-else operator
+    cmARG_SEP       = 19,  ///< function argument separator
+    cmVAR           = 20,  ///< variable item
+    cmVAL           = 21,  ///< value item
+
+    // For optimization purposes
+    cmVARPOW2,
+    cmVARPOW3,
+    cmVARPOW4,
+    cmVARMUL,
+    cmPOW2,
+
+    // operators and functions
+    cmFUNC,                ///< Code for a generic function item
+    cmFUNC_STR,            ///< Code for a function with a string parameter
+    cmFUNC_BULK,           ///< Special callbacks for Bulk mode with an additional parameter for the bulk index 
+    cmSTRING,              ///< Code for a string token
+    cmOPRT_BIN,            ///< user defined binary operator
+    cmOPRT_POSTFIX,        ///< code for postfix operators
+    cmOPRT_INFIX,          ///< code for infix operators
+    cmEND,                 ///< end of formula
+    cmUNKNOWN              ///< uninitialized item
+  };
+
+  //------------------------------------------------------------------------------
+  /** \brief Types internally used by the parser.
+  */
+  enum ETypeCode
+  {
+    tpSTR  = 0,     ///< String type (Function arguments and constants only, no string variables)
+    tpDBL  = 1,     ///< Floating point variables
+    tpVOID = 2      ///< Undefined type.
+  };
+
+  //------------------------------------------------------------------------------
+  enum EParserVersionInfo
+  {
+    pviBRIEF,
+    pviFULL
+  };
+
+  //------------------------------------------------------------------------------
+  /** \brief Parser operator precedence values. */
+  enum EOprtAssociativity
+  {
+    oaLEFT  = 0,
+    oaRIGHT = 1,
+    oaNONE  = 2
+  };
+
+  //------------------------------------------------------------------------------
+  /** \brief Parser operator precedence values. */
+  enum EOprtPrecedence
+  {
+    // binary operators
+    prLOR     = 1,
+    prLAND    = 2,
+    prLOGIC   = 3,  ///< logic operators
+    prCMP     = 4,  ///< comparsion operators
+    prADD_SUB = 5,  ///< addition
+    prMUL_DIV = 6,  ///< multiplication/division
+    prPOW     = 7,  ///< power operator priority (highest)
+
+    // infix operators
+    prINFIX   = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator
+    prPOSTFIX = 6  ///< Postfix operator priority (currently unused)
+  };
+
+  //------------------------------------------------------------------------------
+  // basic types
+
+  /** \brief The numeric datatype used by the parser. 
+  
+    Normally this is a floating point type either single or double precision.
+  */
+  typedef MUP_BASETYPE value_type;
+
+  /** \brief The stringtype used by the parser. 
+
+    Depends on wether UNICODE is used or not.
+  */
+  typedef MUP_STRING_TYPE string_type;
+
+  /** \brief The character type used by the parser. 
+  
+    Depends on wether UNICODE is used or not.
+  */
+  typedef string_type::value_type char_type;
+
+  /** \brief Typedef for easily using stringstream that respect the parser stringtype. */
+  typedef std::basic_stringstream<char_type,
+                                  std::char_traits<char_type>,
+                                  std::allocator<char_type> > stringstream_type;
+
+  // Data container types
+
+  /** \brief Type used for storing variables. */
+  typedef std::map<string_type, value_type*> varmap_type;
+  
+  /** \brief Type used for storing constants. */
+  typedef std::map<string_type, value_type> valmap_type;
+  
+  /** \brief Type for assigning a string name to an index in the internal string table. */
+  typedef std::map<string_type, std::size_t> strmap_type;
+
+  // Parser callbacks
+  
+  /** \brief Callback type used for functions without arguments. */
+  typedef value_type (*generic_fun_type)();
+
+  /** \brief Callback type used for functions without arguments. */
+  typedef value_type (*fun_type0)();
+
+  /** \brief Callback type used for functions with a single arguments. */
+  typedef value_type (*fun_type1)(value_type);
+
+  /** \brief Callback type used for functions with two arguments. */
+  typedef value_type (*fun_type2)(value_type, value_type);
+
+  /** \brief Callback type used for functions with three arguments. */
+  typedef value_type (*fun_type3)(value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with four arguments. */
+  typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions without arguments. */
+  typedef value_type (*bulkfun_type0)(int, int);
+
+  /** \brief Callback type used for functions with a single arguments. */
+  typedef value_type (*bulkfun_type1)(int, int, value_type);
+
+  /** \brief Callback type used for functions with two arguments. */
+  typedef value_type (*bulkfun_type2)(int, int, value_type, value_type);
+
+  /** \brief Callback type used for functions with three arguments. */
+  typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with four arguments. */
+  typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with five arguments. */
+  typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);
+
+  /** \brief Callback type used for functions with a variable argument list. */
+  typedef value_type (*multfun_type)(const value_type*, int);
+
+  /** \brief Callback type used for functions taking a string as an argument. */
+  typedef value_type (*strfun_type1)(const char_type*);
+
+  /** \brief Callback type used for functions taking a string and a value as arguments. */
+  typedef value_type (*strfun_type2)(const char_type*, value_type);
+
+  /** \brief Callback type used for functions taking a string and two values as arguments. */
+  typedef value_type (*strfun_type3)(const char_type*, value_type, value_type);
+
+  /** \brief Callback used for functions that identify values in a string. */
+  typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal);
+
+  /** \brief Callback used for variable creation factory functions. */
+  typedef value_type* (*facfun_type)(const char_type*, void*);
+} // end of namespace
+
+#endif
+
diff --git a/source/ThirdParty/MuParser/include/muParserError.h b/source/ThirdParty/MuParser/include/muParserError.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f88e99192ebf61d3b546a17892681af53a4f5f9
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserError.h
@@ -0,0 +1,176 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2004-2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#ifndef MU_PARSER_ERROR_H
+#define MU_PARSER_ERROR_H
+
+#include <cassert>
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <memory>
+
+#include "muParserDef.h"
+
+/** \file 
+    \brief This file defines the error class used by the parser.
+*/
+
+namespace mu
+{
+
+/** \brief Error codes. */
+enum EErrorCodes
+{
+  // Formula syntax errors
+  ecUNEXPECTED_OPERATOR    = 0,  ///< Unexpected binary operator found
+  ecUNASSIGNABLE_TOKEN     = 1,  ///< Token cant be identified.
+  ecUNEXPECTED_EOF         = 2,  ///< Unexpected end of formula. (Example: "2+sin(")
+  ecUNEXPECTED_ARG_SEP     = 3,  ///< An unexpected comma has been found. (Example: "1,23")
+  ecUNEXPECTED_ARG         = 4,  ///< An unexpected argument has been found
+  ecUNEXPECTED_VAL         = 5,  ///< An unexpected value token has been found
+  ecUNEXPECTED_VAR         = 6,  ///< An unexpected variable token has been found
+  ecUNEXPECTED_PARENS      = 7,  ///< Unexpected Parenthesis, opening or closing
+  ecUNEXPECTED_STR         = 8,  ///< A string has been found at an inapropriate position
+  ecSTRING_EXPECTED        = 9,  ///< A string function has been called with a different type of argument
+  ecVAL_EXPECTED           = 10, ///< A numerical function has been called with a non value type of argument
+  ecMISSING_PARENS         = 11, ///< Missing parens. (Example: "3*sin(3")
+  ecUNEXPECTED_FUN         = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)")
+  ecUNTERMINATED_STRING    = 13, ///< unterminated string constant. (Example: "3*valueof("hello)")
+  ecTOO_MANY_PARAMS        = 14, ///< Too many function parameters
+  ecTOO_FEW_PARAMS         = 15, ///< Too few function parameters. (Example: "ite(1<2,2)")
+  ecOPRT_TYPE_CONFLICT     = 16, ///< binary operators may only be applied to value items of the same type
+  ecSTR_RESULT             = 17, ///< result is a string
+
+  // Invalid Parser input Parameters
+  ecINVALID_NAME           = 18, ///< Invalid function, variable or constant name.
+  ecINVALID_BINOP_IDENT    = 19, ///< Invalid binary operator identifier
+  ecINVALID_INFIX_IDENT    = 20, ///< Invalid function, variable or constant name.
+  ecINVALID_POSTFIX_IDENT  = 21, ///< Invalid function, variable or constant name.
+
+  ecBUILTIN_OVERLOAD       = 22, ///< Trying to overload builtin operator
+  ecINVALID_FUN_PTR        = 23, ///< Invalid callback function pointer 
+  ecINVALID_VAR_PTR        = 24, ///< Invalid variable pointer 
+  ecEMPTY_EXPRESSION       = 25, ///< The Expression is empty
+  ecNAME_CONFLICT          = 26, ///< Name conflict
+  ecOPT_PRI                = 27, ///< Invalid operator priority
+  // 
+  ecDOMAIN_ERROR           = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused)
+  ecDIV_BY_ZERO            = 29, ///< Division by zero (currently unused)
+  ecGENERIC                = 30, ///< Generic error
+  ecLOCALE                 = 31, ///< Conflict with current locale
+
+  ecUNEXPECTED_CONDITIONAL = 32,
+  ecMISSING_ELSE_CLAUSE    = 33, 
+  ecMISPLACED_COLON        = 34,
+
+  ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35,
+
+  // internal errors
+  ecINTERNAL_ERROR         = 36, ///< Internal error of any kind.
+  
+  // The last two are special entries 
+  ecCOUNT,                      ///< This is no error code, It just stores just the total number of error codes
+  ecUNDEFINED              = -1  ///< Undefined message, placeholder to detect unassigned error messages
+};
+
+//---------------------------------------------------------------------------
+/** \brief A class that handles the error messages.
+*/
+class ParserErrorMsg
+{
+public:
+    typedef ParserErrorMsg self_type;
+
+    ParserErrorMsg& operator=(const ParserErrorMsg &);
+    ParserErrorMsg(const ParserErrorMsg&);
+    ParserErrorMsg();
+
+   ~ParserErrorMsg();
+
+    static const ParserErrorMsg& Instance();
+    string_type operator[](unsigned a_iIdx) const;
+
+private:
+    std::vector<string_type>  m_vErrMsg;  ///< A vector with the predefined error messages
+    static const self_type m_Instance;    ///< The instance pointer
+};
+
+//---------------------------------------------------------------------------
+/** \brief Error class of the parser. 
+    \author Ingo Berg
+
+  Part of the math parser package.
+*/
+class ParserError
+{
+private:
+
+    /** \brief Replace all ocuurences of a substring with another string. */
+    void ReplaceSubString( string_type &strSource, 
+                           const string_type &strFind,
+                           const string_type &strReplaceWith);
+    void Reset();
+
+public:
+
+    ParserError();
+    explicit ParserError(EErrorCodes a_iErrc);
+    explicit ParserError(const string_type &sMsg);
+    ParserError( EErrorCodes a_iErrc,
+                 const string_type &sTok,
+                 const string_type &sFormula = string_type(),
+                 int a_iPos = -1);
+    ParserError( EErrorCodes a_iErrc, 
+                 int a_iPos, 
+                 const string_type &sTok);
+    ParserError( const char_type *a_szMsg, 
+                 int a_iPos = -1, 
+                 const string_type &sTok = string_type());
+    ParserError(const ParserError &a_Obj);
+    ParserError& operator=(const ParserError &a_Obj);
+   ~ParserError();
+
+    void SetFormula(const string_type &a_strFormula);
+    const string_type& GetExpr() const;
+    const string_type& GetMsg() const;
+    int GetPos() const;
+    const string_type& GetToken() const;
+    EErrorCodes GetCode() const;
+
+private:
+    string_type m_strMsg;     ///< The message string
+    string_type m_strFormula; ///< Formula string
+    string_type m_strTok;     ///< Token related with the error
+    int m_iPos;               ///< Formula position related to the error 
+    EErrorCodes m_iErrc;      ///< Error code
+    const ParserErrorMsg &m_ErrMsg;
+};		
+
+} // namespace mu
+
+#endif
+
diff --git a/source/ThirdParty/MuParser/include/muParserFixes.h b/source/ThirdParty/MuParser/include/muParserFixes.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cd15e02edbf1af43c24a5490eca51e5e45bd05d
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserFixes.h
@@ -0,0 +1,62 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#ifndef MU_PARSER_FIXES_H
+#define MU_PARSER_FIXES_H
+
+/** \file
+    \brief This file contains compatibility fixes for some platforms.
+*/
+
+//
+// Compatibility fixes
+//
+
+//---------------------------------------------------------------------------
+//
+// Intel Compiler
+//
+//---------------------------------------------------------------------------
+
+#ifdef __INTEL_COMPILER
+
+// remark #981: operands are evaluated in unspecified order
+// disabled -> completely pointless if the functions do not have side effects
+//
+#pragma warning(disable:981)
+
+// remark #383: value copied to temporary, reference to temporary used
+#pragma warning(disable:383)
+
+// remark #1572: floating-point equality and inequality comparisons are unreliable
+// disabled -> everyone knows it, the parser passes this problem
+//             deliberately to the user
+#pragma warning(disable:1572)
+
+#endif
+
+#endif // include guard
+
+
diff --git a/source/ThirdParty/MuParser/include/muParserInt.h b/source/ThirdParty/MuParser/include/muParserInt.h
new file mode 100644
index 0000000000000000000000000000000000000000..136de339714588c26d48430d9e17778d367d0a26
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserInt.h
@@ -0,0 +1,140 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2004-2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#ifndef MU_PARSER_INT_H
+#define MU_PARSER_INT_H
+
+#include "muParserBase.h"
+#include <vector>
+
+
+/** \file
+    \brief Definition of a parser using integer value.
+*/
+
+
+namespace mu
+{
+
+/** \brief Mathematical expressions parser.
+  
+  This version of the parser handles only integer numbers. It disables the built in operators thus it is 
+  slower than muParser. Integer values are stored in the double value_type and converted if needed.
+*/
+class ParserInt : public ParserBase
+{
+private:
+    static int  Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); };
+  
+    static value_type  Abs(value_type);
+    static value_type  Sign(value_type);
+    static value_type  Ite(value_type, value_type, value_type);
+    // !! The unary Minus is a MUST, otherwise you cant use negative signs !!
+    static value_type  UnaryMinus(value_type);
+    // Functions with variable number of arguments
+    static value_type  Sum(const value_type* a_afArg, int a_iArgc);  // sum
+    static value_type  Min(const value_type* a_afArg, int a_iArgc);  // minimum
+    static value_type  Max(const value_type* a_afArg, int a_iArgc);  // maximum
+    // binary operator callbacks
+    static value_type  Add(value_type v1, value_type v2);
+    static value_type  Sub(value_type v1, value_type v2);
+    static value_type  Mul(value_type v1, value_type v2);
+    static value_type  Div(value_type v1, value_type v2);
+    static value_type  Mod(value_type v1, value_type v2);
+    static value_type  Pow(value_type v1, value_type v2);
+    static value_type  Shr(value_type v1, value_type v2);
+    static value_type  Shl(value_type v1, value_type v2);
+    static value_type  LogAnd(value_type v1, value_type v2);
+    static value_type  LogOr(value_type v1, value_type v2);
+    static value_type  And(value_type v1, value_type v2);
+    static value_type  Or(value_type v1, value_type v2);
+    static value_type  Xor(value_type v1, value_type v2);
+    static value_type  Less(value_type v1, value_type v2);
+    static value_type  Greater(value_type v1, value_type v2);
+    static value_type  LessEq(value_type v1, value_type v2);
+    static value_type  GreaterEq(value_type v1, value_type v2);
+    static value_type  Equal(value_type v1, value_type v2);
+    static value_type  NotEqual(value_type v1, value_type v2);
+    static value_type  Not(value_type v1);
+
+    static int IsHexVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);
+    static int IsBinVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);
+    static int IsVal   (const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);
+
+    /** \brief A facet class used to change decimal and thousands separator. */
+    template<class TChar>
+    class change_dec_sep : public std::numpunct<TChar>
+    {
+    public:
+      
+      explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
+        :std::numpunct<TChar>()
+        ,m_cDecPoint(cDecSep)
+        ,m_cThousandsSep(cThousandsSep)
+        ,m_nGroup(nGroup)
+      {}
+      
+    protected:
+      
+      virtual char_type do_decimal_point() const
+      {
+        return m_cDecPoint;
+      }
+
+      virtual char_type do_thousands_sep() const
+      {
+        return m_cThousandsSep;
+      }
+
+      virtual std::string do_grouping() const 
+      { 
+        // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
+        // courtesy of Jens Bartsch
+        // original code:
+        //        return std::string(1, (char)m_nGroup); 
+        // new code:
+        return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
+      }
+
+    private:
+
+      int m_nGroup;
+      char_type m_cDecPoint;  
+      char_type m_cThousandsSep;
+    };
+
+public:
+    ParserInt();
+
+    virtual void InitFun();
+    virtual void InitOprt();
+    virtual void InitConst();
+    virtual void InitCharSets();
+};
+
+} // namespace mu
+
+#endif
+
diff --git a/source/ThirdParty/MuParser/include/muParserStack.h b/source/ThirdParty/MuParser/include/muParserStack.h
new file mode 100644
index 0000000000000000000000000000000000000000..f8437e30e43cec17465c09da0d10641d251dc550
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserStack.h
@@ -0,0 +1,125 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2004-2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#ifndef MU_PARSER_STACK_H
+#define MU_PARSER_STACK_H
+
+#include <cassert>
+#include <string>
+#include <stack>
+#include <vector>
+
+#include "muParserError.h"
+#include "muParserToken.h"
+
+/** \file 
+    \brief This file defines the stack used by muparser.
+*/
+
+namespace mu
+{
+
+  /** \brief Parser stack implementation. 
+
+      Stack implementation based on a std::stack. The behaviour of pop() had been
+      slightly changed in order to get an error code if the stack is empty.
+      The stack is used within the Parser both as a value stack and as an operator stack.
+
+      \author (C) 2004-2011 Ingo Berg 
+  */
+  template <typename TValueType>
+  class ParserStack 
+  {
+    private:
+
+      /** \brief Type of the underlying stack implementation. */
+      typedef std::stack<TValueType, std::vector<TValueType> > impl_type;
+      
+      impl_type m_Stack;  ///< This is the actual stack.
+
+    public:	
+  	 
+      //---------------------------------------------------------------------------
+      ParserStack()
+        :m_Stack()
+      {}
+
+      //---------------------------------------------------------------------------
+      virtual ~ParserStack()
+      {}
+
+      //---------------------------------------------------------------------------
+      /** \brief Pop a value from the stack.
+       
+        Unlike the standard implementation this function will return the value that
+        is going to be taken from the stack.
+
+        \throw ParserException in case the stack is empty.
+        \sa pop(int &a_iErrc)
+      */
+	    TValueType pop()
+      {
+        if (empty())
+          throw ParserError( _T("stack is empty.") );
+
+        TValueType el = top();
+        m_Stack.pop();
+        return el;
+      }
+
+      /** \brief Push an object into the stack. 
+
+          \param a_Val object to push into the stack.
+          \throw nothrow
+      */
+      void push(const TValueType& a_Val) 
+      { 
+        m_Stack.push(a_Val); 
+      }
+
+      /** \brief Return the number of stored elements. */
+      unsigned size() const
+      { 
+        return (unsigned)m_Stack.size(); 
+      }
+
+      /** \brief Returns true if stack is empty false otherwise. */
+      bool empty() const
+      {
+        return m_Stack.empty(); 
+      }
+       
+      /** \brief Return reference to the top object in the stack. 
+       
+          The top object is the one pushed most recently.
+      */
+      TValueType& top() 
+      { 
+        return m_Stack.top(); 
+      }
+  };
+} // namespace MathUtils
+
+#endif
diff --git a/source/ThirdParty/MuParser/include/muParserTemplateMagic.h b/source/ThirdParty/MuParser/include/muParserTemplateMagic.h
new file mode 100644
index 0000000000000000000000000000000000000000..1626caea4eeee2238d2eb874e9173e079c9d4853
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserTemplateMagic.h
@@ -0,0 +1,113 @@
+#ifndef MU_PARSER_TEMPLATE_MAGIC_H
+#define MU_PARSER_TEMPLATE_MAGIC_H
+
+#include <cmath>
+#include "muParserError.h"
+
+
+namespace mu
+{
+  //-----------------------------------------------------------------------------------------------
+  //
+  // Compile time type detection
+  //
+  //-----------------------------------------------------------------------------------------------
+
+  /** \brief A class singling out integer types at compile time using 
+             template meta programming.
+  */
+  template<typename T>
+  struct TypeInfo
+  {
+    static bool IsInteger() { return false; }
+  };
+
+  template<>
+  struct TypeInfo<char>
+  {
+    static bool IsInteger() { return true;  }
+  };
+
+  template<>
+  struct TypeInfo<short>
+  {
+    static bool IsInteger() { return true;  }
+  };
+
+  template<>
+  struct TypeInfo<int>
+  {
+    static bool IsInteger() { return true;  }
+  };
+
+  template<>
+  struct TypeInfo<long>
+  {
+    static bool IsInteger() { return true;  }
+  };
+
+  template<>
+  struct TypeInfo<unsigned char>
+  {
+    static bool IsInteger() { return true;  }
+  };
+
+  template<>
+  struct TypeInfo<unsigned short>
+  {
+    static bool IsInteger() { return true;  }
+  };
+
+  template<>
+  struct TypeInfo<unsigned int>
+  {
+    static bool IsInteger() { return true;  }
+  };
+
+  template<>
+  struct TypeInfo<unsigned long>
+  {
+    static bool IsInteger() { return true;  }
+  };
+
+
+  //-----------------------------------------------------------------------------------------------
+  //
+  // Standard math functions with dummy overload for integer types
+  //
+  //-----------------------------------------------------------------------------------------------
+
+  /** \brief A template class for providing wrappers for essential math functions.
+
+    This template is spezialized for several types in order to provide a unified interface
+    for parser internal math function calls regardless of the data type.
+  */
+  template<typename T>
+  struct MathImpl
+  {
+    static T Sin(T v)   { return sin(v);  }
+    static T Cos(T v)   { return cos(v);  }
+    static T Tan(T v)   { return tan(v);  }
+    static T ASin(T v)  { return asin(v); }
+    static T ACos(T v)  { return acos(v); }
+    static T ATan(T v)  { return atan(v); }
+    static T ATan2(T v1, T v2) { return atan2(v1, v2); }
+    static T Sinh(T v)  { return sinh(v); }
+    static T Cosh(T v)  { return cosh(v); }
+    static T Tanh(T v)  { return tanh(v); }
+    static T ASinh(T v) { return log(v + sqrt(v * v + 1)); }
+    static T ACosh(T v) { return log(v + sqrt(v * v - 1)); }
+    static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); }
+    static T Log(T v)   { return log(v); } 
+    static T Log2(T v)  { return log(v)/log((T)2); } // Logarithm base 2
+    static T Log10(T v) { return log10(v); }         // Logarithm base 10
+    static T Exp(T v)   { return exp(v);   }
+    static T Abs(T v)   { return (v>=0) ? v : -v; }
+    static T Sqrt(T v)  { return sqrt(v); }
+    static T Rint(T v)  { return floor(v + (T)0.5); }
+    static T Sign(T v)  { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); }
+    static T Pow(T v1, T v2) { return std::pow(v1, v2); }
+  };
+}
+
+#endif
diff --git a/source/ThirdParty/MuParser/include/muParserTest.h b/source/ThirdParty/MuParser/include/muParserTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..c02b0218a9b5a320f7e16d680d7e7def13a00eec
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserTest.h
@@ -0,0 +1,214 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#ifndef MU_PARSER_TEST_H
+#define MU_PARSER_TEST_H
+
+#include <string>
+#include <cstdlib>
+#include <numeric> // for accumulate
+#include "muParser.h"
+#include "muParserInt.h"
+
+/** \file
+    \brief This file contains the parser test class.
+*/
+
+namespace mu
+{
+  /** \brief Namespace for test cases. */
+  namespace Test
+  {
+    //------------------------------------------------------------------------------
+    /** \brief Test cases for unit testing.
+
+      (C) 2004-2011 Ingo Berg
+    */
+    class ParserTester // final
+    {
+    private:
+        static int c_iCount;
+
+        // Multiarg callbacks
+        static value_type f1of1(value_type v) { return v;};
+      	
+        static value_type f1of2(value_type v, value_type  ) {return v;};
+        static value_type f2of2(value_type  , value_type v) {return v;};
+
+        static value_type f1of3(value_type v, value_type  , value_type  ) {return v;};
+        static value_type f2of3(value_type  , value_type v, value_type  ) {return v;};
+        static value_type f3of3(value_type  , value_type  , value_type v) {return v;};
+      	
+        static value_type f1of4(value_type v, value_type,   value_type  , value_type  ) {return v;}
+        static value_type f2of4(value_type  , value_type v, value_type  , value_type  ) {return v;}
+        static value_type f3of4(value_type  , value_type,   value_type v, value_type  ) {return v;}
+        static value_type f4of4(value_type  , value_type,   value_type  , value_type v) {return v;}
+
+        static value_type f1of5(value_type v, value_type,   value_type  , value_type  , value_type  ) { return v; }
+        static value_type f2of5(value_type  , value_type v, value_type  , value_type  , value_type  ) { return v; }
+        static value_type f3of5(value_type  , value_type,   value_type v, value_type  , value_type  ) { return v; }
+        static value_type f4of5(value_type  , value_type,   value_type  , value_type v, value_type  ) { return v; }
+        static value_type f5of5(value_type  , value_type,   value_type  , value_type  , value_type v) { return v; }
+
+        static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1<a_fVal2) ? a_fVal1 : a_fVal2; }
+  	    static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1>a_fVal2) ? a_fVal1 : a_fVal2; }
+
+        static value_type plus2(value_type v1) { return v1+2; }
+        static value_type times3(value_type v1) { return v1*3; }
+        static value_type sqr(value_type v1) { return v1*v1; }
+        static value_type sign(value_type v) { return -v; }
+        static value_type add(value_type v1, value_type v2) { return v1+v2; }
+        static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; }
+        
+
+        static value_type FirstArg(const value_type* a_afArg, int a_iArgc)
+        {
+          if (!a_iArgc)	
+            throw mu::Parser::exception_type( _T("too few arguments for function FirstArg.") );
+
+          return  a_afArg[0];
+        }
+
+        static value_type LastArg(const value_type* a_afArg, int a_iArgc)
+        {
+          if (!a_iArgc)	
+            throw mu::Parser::exception_type( _T("too few arguments for function LastArg.") );
+
+          return  a_afArg[a_iArgc-1];
+        }
+
+        static value_type Sum(const value_type* a_afArg, int a_iArgc)
+        { 
+          if (!a_iArgc)	
+            throw mu::Parser::exception_type( _T("too few arguments for function sum.") );
+
+          value_type fRes=0;
+          for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
+          return fRes;
+        }
+
+        static value_type Rnd(value_type v)
+        {
+          return (value_type)(1+(v*std::rand()/(RAND_MAX+1.0)));
+        }
+
+        static value_type RndWithString(const char_type*)
+        {
+          return (value_type)( 1 + (1000.0f * std::rand() / (RAND_MAX + 1.0) ) );
+        }
+
+        static value_type Ping()
+        { 
+          return 10; 
+        }
+
+        static value_type ValueOf(const char_type*)      
+        { 
+          return 123; 
+        }
+
+        static value_type StrFun1(const char_type* v1)                               
+        { 
+          int val(0);
+          stringstream_type(v1) >> val;
+          return (value_type)val;
+        }
+
+        static value_type StrFun2(const char_type* v1, value_type v2)                
+        { 
+          int val(0);
+          stringstream_type(v1) >> val;
+          return (value_type)(val + v2);
+        }
+        
+        static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) 
+        { 
+          int val(0);
+          stringstream_type(v1) >> val;
+          return val + v2 + v3;
+        }
+
+        static value_type StrToFloat(const char_type* a_szMsg)
+        {
+          value_type val(0);
+          stringstream_type(a_szMsg) >> val;
+          return val;
+        }
+
+        // postfix operator callback
+        static value_type Mega(value_type a_fVal)  { return a_fVal * (value_type)1e6; }
+        static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; }
+        static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; }
+
+        // Custom value recognition
+        static int IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal);
+
+        int TestNames();
+        int TestSyntax();
+        int TestMultiArg();
+        int TestPostFix();
+        int TestExpression();
+        int TestInfixOprt();
+        int TestBinOprt();
+        int TestVarConst();
+        int TestInterface();
+        int TestException();
+        int TestStrArg();
+        int TestIfThenElse();
+        int TestBulkMode();
+
+        void Abort() const;
+
+    public:
+        typedef int (ParserTester::*testfun_type)();
+
+	      ParserTester();
+	      void Run();
+
+    private:
+        std::vector<testfun_type> m_vTestFun;
+	      void AddTest(testfun_type a_pFun);
+
+        // Test Double Parser
+        int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass);
+        int EqnTestWithVarChange(const string_type& a_str, 
+                                 double a_fRes1, 
+                                 double a_fVar1, 
+                                 double a_fRes2, 
+                                 double a_fVar2);
+        int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true);
+
+        // Test Int Parser
+        int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass);
+
+        // Test Bulkmode
+        int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass);
+    };
+  } // namespace Test
+} // namespace mu
+
+#endif
+
+
diff --git a/source/ThirdParty/MuParser/include/muParserToken.h b/source/ThirdParty/MuParser/include/muParserToken.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc91d7818c0648e8a79cecd489195e4ade5b927d
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserToken.h
@@ -0,0 +1,401 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2004-2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#ifndef MU_PARSER_TOKEN_H
+#define MU_PARSER_TOKEN_H
+
+#include <cassert>
+#include <string>
+#include <stack>
+#include <vector>
+#include <memory>
+
+#include "muParserError.h"
+#include "muParserCallback.h"
+
+/** \file
+    \brief This file contains the parser token definition.
+*/
+
+namespace mu
+{
+  /** \brief Encapsulation of the data for a single formula token. 
+
+    Formula token implementation. Part of the Math Parser Package.
+    Formula tokens can be either one of the following:
+    <ul>
+      <li>value</li>
+      <li>variable</li>
+      <li>function with numerical arguments</li>
+      <li>functions with a string as argument</li>
+      <li>prefix operators</li>
+      <li>infix operators</li>
+	    <li>binary operator</li>
+    </ul>
+
+   \author (C) 2004-2013 Ingo Berg 
+  */
+  template<typename TBase, typename TString>
+  class ParserToken
+  {
+  private:
+
+      ECmdCode  m_iCode;  ///< Type of the token; The token type is a constant of type #ECmdCode.
+      ETypeCode m_iType;
+      void  *m_pTok;      ///< Stores Token pointer; not applicable for all tokens
+      int  m_iIdx;        ///< An otional index to an external buffer storing the token data
+      TString m_strTok;   ///< Token string
+      TString m_strVal;   ///< Value for string variables
+      value_type m_fVal;  ///< the value 
+      std::auto_ptr<ParserCallback> m_pCallback;
+
+  public:
+
+      //---------------------------------------------------------------------------
+      /** \brief Constructor (default).
+        
+          Sets token to an neutral state of type cmUNKNOWN.
+          \throw nothrow
+          \sa ECmdCode
+      */
+      ParserToken()
+        :m_iCode(cmUNKNOWN)
+        ,m_iType(tpVOID)
+        ,m_pTok(0)
+        ,m_iIdx(-1)
+        ,m_strTok()
+		,m_strVal()
+		,m_fVal(0)
+        ,m_pCallback()
+      {}
+
+      //------------------------------------------------------------------------------
+      /** \brief Create token from another one.
+      
+          Implemented by calling Assign(...)
+          \throw nothrow
+          \post m_iType==cmUNKNOWN
+          \sa #Assign
+      */
+      ParserToken(const ParserToken &a_Tok)
+      {
+        Assign(a_Tok);
+      }
+      
+      //------------------------------------------------------------------------------
+      /** \brief Assignement operator. 
+      
+          Copy token state from another token and return this.
+          Implemented by calling Assign(...).
+          \throw nothrow
+      */
+      ParserToken& operator=(const ParserToken &a_Tok)
+      {
+        Assign(a_Tok);
+        return *this;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Copy token information from argument.
+      
+          \throw nothrow
+      */
+      void Assign(const ParserToken &a_Tok)
+      {
+        m_iCode = a_Tok.m_iCode;
+        m_pTok = a_Tok.m_pTok;
+        m_strTok = a_Tok.m_strTok;
+        m_iIdx = a_Tok.m_iIdx;
+        m_strVal = a_Tok.m_strVal;
+        m_iType = a_Tok.m_iType;
+        m_fVal = a_Tok.m_fVal;
+        // create new callback object if a_Tok has one 
+        m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Assign a token type. 
+
+        Token may not be of type value, variable or function. Those have seperate set functions. 
+
+        \pre [assert] a_iType!=cmVAR
+        \pre [assert] a_iType!=cmVAL
+        \pre [assert] a_iType!=cmFUNC
+        \post m_fVal = 0
+        \post m_pTok = 0
+      */
+      ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString())
+      {
+        // The following types cant be set this way, they have special Set functions
+        assert(a_iType!=cmVAR);
+        assert(a_iType!=cmVAL);
+        assert(a_iType!=cmFUNC);
+
+        m_iCode = a_iType;
+        m_iType = tpVOID;
+        m_pTok = 0;
+        m_strTok = a_strTok;
+        m_iIdx = -1;
+
+        return *this;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Set Callback type. */
+      ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok)
+      {
+        assert(a_pCallback.GetAddr());
+
+        m_iCode = a_pCallback.GetCode();
+        m_iType = tpVOID;
+        m_strTok = a_sTok;
+        m_pCallback.reset(new ParserCallback(a_pCallback));
+
+        m_pTok = 0;
+        m_iIdx = -1;
+        
+        return *this;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Make this token a value token. 
+      
+          Member variables not necessary for value tokens will be invalidated.
+          \throw nothrow
+      */
+      ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString())
+      {
+        m_iCode = cmVAL;
+        m_iType = tpDBL;
+        m_fVal = a_fVal;
+        m_strTok = a_strTok;
+        m_iIdx = -1;
+        
+        m_pTok = 0;
+        m_pCallback.reset(0);
+
+        return *this;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief make this token a variable token. 
+      
+          Member variables not necessary for variable tokens will be invalidated.
+          \throw nothrow
+      */
+      ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok)
+      {
+        m_iCode = cmVAR;
+        m_iType = tpDBL;
+        m_strTok = a_strTok;
+        m_iIdx = -1;
+        m_pTok = (void*)a_pVar;
+        m_pCallback.reset(0);
+        return *this;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Make this token a variable token. 
+      
+          Member variables not necessary for variable tokens will be invalidated.
+          \throw nothrow
+      */
+      ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize)
+      {
+        m_iCode = cmSTRING;
+        m_iType = tpSTR;
+        m_strTok = a_strTok;
+        m_iIdx = static_cast<int>(a_iSize);
+
+        m_pTok = 0;
+        m_pCallback.reset(0);
+        return *this;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Set an index associated with the token related data. 
+      
+          In cmSTRFUNC - This is the index to a string table in the main parser.
+          \param a_iIdx The index the string function result will take in the bytecode parser.
+          \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
+      */
+      void SetIdx(int a_iIdx)
+      {
+        if (m_iCode!=cmSTRING || a_iIdx<0)
+	        throw ParserError(ecINTERNAL_ERROR);
+        
+        m_iIdx = a_iIdx;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Return Index associated with the token related data. 
+      
+          In cmSTRFUNC - This is the index to a string table in the main parser.
+
+          \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
+          \return The index the result will take in the Bytecode calculatin array (#m_iIdx).
+      */
+      int GetIdx() const
+      {
+        if (m_iIdx<0 || m_iCode!=cmSTRING )
+          throw ParserError(ecINTERNAL_ERROR);
+
+        return m_iIdx;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Return the token type.
+      
+          \return #m_iType
+          \throw nothrow
+      */
+      ECmdCode GetCode() const
+      {
+        if (m_pCallback.get())
+        {
+          return m_pCallback->GetCode();
+        }
+        else
+        {
+          return m_iCode;
+        }
+      }
+
+      //------------------------------------------------------------------------------
+      ETypeCode GetType() const
+      {
+        if (m_pCallback.get())
+        {
+          return m_pCallback->GetType();
+        }
+        else
+        {
+          return m_iType;
+        }
+      }
+      
+      //------------------------------------------------------------------------------
+      int GetPri() const
+      {
+        if ( !m_pCallback.get())
+	        throw ParserError(ecINTERNAL_ERROR);
+            
+        if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX)
+	        throw ParserError(ecINTERNAL_ERROR);
+
+        return m_pCallback->GetPri();
+      }
+
+      //------------------------------------------------------------------------------
+      EOprtAssociativity GetAssociativity() const
+      {
+        if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN)
+	        throw ParserError(ecINTERNAL_ERROR);
+
+        return m_pCallback->GetAssociativity();
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Return the address of the callback function assoziated with
+                 function and operator tokens.
+
+          \return The pointer stored in #m_pTok.
+          \throw exception_type if token type is non of:
+                 <ul>
+                   <li>cmFUNC</li>
+                   <li>cmSTRFUNC</li>
+                   <li>cmPOSTOP</li>
+                   <li>cmINFIXOP</li>
+                   <li>cmOPRT_BIN</li>
+                 </ul>
+          \sa ECmdCode
+      */
+      generic_fun_type GetFuncAddr() const
+      {
+        return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \biref Get value of the token.
+        
+          Only applicable to variable and value tokens.
+          \throw exception_type if token is no value/variable token.
+      */
+      TBase GetVal() const
+      {
+        switch (m_iCode)
+        {
+          case cmVAL:  return m_fVal;
+          case cmVAR:  return *((TBase*)m_pTok);
+          default:     throw ParserError(ecVAL_EXPECTED);
+        }
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Get address of a variable token.
+
+        Valid only if m_iType==CmdVar.
+        \throw exception_type if token is no variable token.
+      */
+      TBase* GetVar() const
+      {
+        if (m_iCode!=cmVAR)
+	        throw ParserError(ecINTERNAL_ERROR);
+
+        return (TBase*)m_pTok;
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Return the number of function arguments. 
+
+        Valid only if m_iType==CmdFUNC.
+      */
+      int GetArgCount() const
+      {
+        assert(m_pCallback.get());
+
+        if (!m_pCallback->GetAddr())
+	        throw ParserError(ecINTERNAL_ERROR);
+
+        return m_pCallback->GetArgc();
+      }
+
+      //------------------------------------------------------------------------------
+      /** \brief Return the token identifier. 
+          
+          If #m_iType is cmSTRING the token identifier is the value of the string argument
+          for a string function.
+          \return #m_strTok
+          \throw nothrow
+          \sa m_strTok
+      */
+      const TString& GetAsString() const
+      {
+        return m_strTok;
+      }
+  };
+} // namespace mu
+
+#endif
diff --git a/source/ThirdParty/MuParser/include/muParserTokenReader.h b/source/ThirdParty/MuParser/include/muParserTokenReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d96225d9a64c0c6e36c17dbad6c7624fe0ee1f2
--- /dev/null
+++ b/source/ThirdParty/MuParser/include/muParserTokenReader.h
@@ -0,0 +1,161 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2004-2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#ifndef MU_PARSER_TOKEN_READER_H
+#define MU_PARSER_TOKEN_READER_H
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <list>
+#include <map>
+#include <memory>
+#include <stack>
+#include <string>
+
+#include "muParserDef.h"
+#include "muParserToken.h"
+
+/** \file
+    \brief This file contains the parser token reader definition.
+*/
+
+
+namespace mu
+{
+  // Forward declaration
+  class ParserBase;
+
+  /** \brief Token reader for the ParserBase class.
+
+  */
+  class ParserTokenReader 
+  {
+  private:
+
+      typedef ParserToken<value_type, string_type> token_type;
+
+  public:
+
+      ParserTokenReader(ParserBase *a_pParent);
+      ParserTokenReader* Clone(ParserBase *a_pParent) const;
+
+      void AddValIdent(identfun_type a_pCallback);
+      void SetVarCreator(facfun_type a_pFactory, void *pUserData);
+      void SetFormula(const string_type &a_strFormula);
+      void SetArgSep(char_type cArgSep);
+
+      int GetPos() const;
+      const string_type& GetExpr() const;
+      varmap_type& GetUsedVar();
+      char_type GetArgSep() const;
+
+      void IgnoreUndefVar(bool bIgnore);
+      void ReInit();
+      token_type ReadNextToken();
+
+  private:
+
+      /** \brief Syntax codes. 
+  	
+	        The syntax codes control the syntax check done during the first time parsing of 
+          the expression string. They are flags that indicate which tokens are allowed next
+          if certain tokens are identified.
+  	  */
+      enum ESynCodes
+      {
+        noBO      = 1 << 0,  ///< to avoid i.e. "cos(7)(" 
+        noBC      = 1 << 1,  ///< to avoid i.e. "sin)" or "()"
+        noVAL     = 1 << 2,  ///< to avoid i.e. "tan 2" or "sin(8)3.14"
+        noVAR     = 1 << 3,  ///< to avoid i.e. "sin a" or "sin(8)a"
+        noARG_SEP = 1 << 4,  ///< to avoid i.e. ",," or "+," ...
+        noFUN     = 1 << 5,  ///< to avoid i.e. "sqrt cos" or "(1)sin"	
+        noOPT     = 1 << 6,  ///< to avoid i.e. "(+)"
+        noPOSTOP  = 1 << 7,  ///< to avoid i.e. "(5!!)" "sin!"
+	      noINFIXOP = 1 << 8,  ///< to avoid i.e. "++4" "!!4"
+        noEND     = 1 << 9,  ///< to avoid unexpected end of formula
+        noSTR     = 1 << 10, ///< to block numeric arguments on string functions
+        noASSIGN  = 1 << 11, ///< to block assignement to constant i.e. "4=7"
+        noIF      = 1 << 12,
+        noELSE    = 1 << 13,
+        sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,
+        noANY     = ~0       ///< All of he above flags set
+      };	
+
+      ParserTokenReader(const ParserTokenReader &a_Reader);
+      ParserTokenReader& operator=(const ParserTokenReader &a_Reader);
+      void Assign(const ParserTokenReader &a_Reader);
+
+      void SetParent(ParserBase *a_pParent);
+      int ExtractToken(const char_type *a_szCharSet, 
+                       string_type &a_strTok, 
+                       int a_iPos) const;
+      int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const;
+
+      bool IsBuiltIn(token_type &a_Tok);
+      bool IsArgSep(token_type &a_Tok);
+      bool IsEOF(token_type &a_Tok);
+      bool IsInfixOpTok(token_type &a_Tok);
+      bool IsFunTok(token_type &a_Tok);
+      bool IsPostOpTok(token_type &a_Tok);
+      bool IsOprt(token_type &a_Tok);
+      bool IsValTok(token_type &a_Tok);
+      bool IsVarTok(token_type &a_Tok);
+      bool IsStrVarTok(token_type &a_Tok);
+      bool IsUndefVarTok(token_type &a_Tok);
+      bool IsString(token_type &a_Tok);
+      void Error(EErrorCodes a_iErrc, 
+                 int a_iPos = -1, 
+                 const string_type &a_sTok = string_type() ) const;
+
+      token_type& SaveBeforeReturn(const token_type &tok);
+
+      ParserBase *m_pParser;
+      string_type m_strFormula;
+      int  m_iPos;
+      int  m_iSynFlags;
+      bool m_bIgnoreUndefVar;
+
+      const funmap_type *m_pFunDef;
+      const funmap_type *m_pPostOprtDef;
+      const funmap_type *m_pInfixOprtDef;
+      const funmap_type *m_pOprtDef;
+      const valmap_type *m_pConstDef;
+      const strmap_type *m_pStrVarDef;
+      varmap_type *m_pVarDef;  ///< The only non const pointer to parser internals
+      facfun_type m_pFactory;
+      void *m_pFactoryData;
+      std::list<identfun_type> m_vIdentFun; ///< Value token identification function
+      varmap_type m_UsedVar;
+      value_type m_fZero;      ///< Dummy value of zero, referenced by undefined variables
+      int m_iBrackets;
+      token_type m_lastTok;
+      char_type m_cArgSep;     ///< The character used for separating function arguments
+  };
+} // namespace mu
+
+#endif
+
+
diff --git a/source/ThirdParty/MuParser/src/muParser.cpp b/source/ThirdParty/MuParser/src/muParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..39ea8610c779ea6061ba1fde8f3c4497f56d63e6
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParser.cpp
@@ -0,0 +1,397 @@
+/* 
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+
+  Copyright (C) 2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+#include "muParser.h"
+#include "muParserTemplateMagic.h"
+
+//--- Standard includes ------------------------------------------------------------------------
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+/** \brief Pi (what else?). */
+#define PARSER_CONST_PI  3.141592653589793238462643
+
+/** \brief The Eulerian number. */
+#define PARSER_CONST_E   2.718281828459045235360287
+
+using namespace std;
+
+/** \file
+    \brief Implementation of the standard floating point parser.
+*/
+
+
+
+/** \brief Namespace for mathematical applications. */
+namespace mu
+{
+
+
+  //---------------------------------------------------------------------------
+  // Trigonometric function
+  value_type Parser::Sin(value_type v)   { return MathImpl<value_type>::Sin(v);  }
+  value_type Parser::Cos(value_type v)   { return MathImpl<value_type>::Cos(v);  }
+  value_type Parser::Tan(value_type v)   { return MathImpl<value_type>::Tan(v);  }
+  value_type Parser::ASin(value_type v)  { return MathImpl<value_type>::ASin(v); }
+  value_type Parser::ACos(value_type v)  { return MathImpl<value_type>::ACos(v); }
+  value_type Parser::ATan(value_type v)  { return MathImpl<value_type>::ATan(v); }
+  value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl<value_type>::ATan2(v1, v2); }
+  value_type Parser::Sinh(value_type v)  { return MathImpl<value_type>::Sinh(v); }
+  value_type Parser::Cosh(value_type v)  { return MathImpl<value_type>::Cosh(v); }
+  value_type Parser::Tanh(value_type v)  { return MathImpl<value_type>::Tanh(v); }
+  value_type Parser::ASinh(value_type v) { return MathImpl<value_type>::ASinh(v); }
+  value_type Parser::ACosh(value_type v) { return MathImpl<value_type>::ACosh(v); }
+  value_type Parser::ATanh(value_type v) { return MathImpl<value_type>::ATanh(v); }
+
+  //---------------------------------------------------------------------------
+  // Logarithm functions
+
+  // Logarithm base 2
+  value_type Parser::Log2(value_type v)  
+  { 
+    #ifdef MUP_MATH_EXCEPTIONS
+        if (v<=0)
+          throw ParserError(ecDOMAIN_ERROR, _T("Log2"));
+    #endif
+
+    return MathImpl<value_type>::Log2(v);  
+  }  
+
+  // Logarithm base 10
+  value_type Parser::Log10(value_type v) 
+  { 
+    #ifdef MUP_MATH_EXCEPTIONS
+        if (v<=0)
+          throw ParserError(ecDOMAIN_ERROR, _T("Log10"));
+    #endif
+
+    return MathImpl<value_type>::Log10(v); 
+  } 
+
+// Logarithm base e (natural logarithm)
+  value_type Parser::Ln(value_type v)    
+  { 
+    #ifdef MUP_MATH_EXCEPTIONS
+        if (v<=0)
+          throw ParserError(ecDOMAIN_ERROR, _T("Ln"));
+    #endif
+
+    return MathImpl<value_type>::Log(v);   
+  } 
+
+  //---------------------------------------------------------------------------
+  //  misc
+  value_type Parser::Exp(value_type v)  { return MathImpl<value_type>::Exp(v);  }
+  value_type Parser::Abs(value_type v)  { return MathImpl<value_type>::Abs(v);  }
+  value_type Parser::Sqrt(value_type v) 
+  { 
+    #ifdef MUP_MATH_EXCEPTIONS
+        if (v<0)
+          throw ParserError(ecDOMAIN_ERROR, _T("sqrt"));
+    #endif
+
+    return MathImpl<value_type>::Sqrt(v); 
+  }
+  value_type Parser::Rint(value_type v) { return MathImpl<value_type>::Rint(v); }
+  value_type Parser::Sign(value_type v) { return MathImpl<value_type>::Sign(v); }
+
+  //---------------------------------------------------------------------------
+  /** \brief Callback for the unary minus operator.
+      \param v The value to negate
+      \return -v
+  */
+  value_type Parser::UnaryMinus(value_type v) 
+  { 
+    return -v; 
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Callback for the unary minus operator.
+      \param v The value to negate
+      \return -v
+  */
+  value_type Parser::UnaryPlus(value_type v) 
+  { 
+    return v; 
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Callback for adding multiple values. 
+      \param [in] a_afArg Vector with the function arguments
+      \param [in] a_iArgc The size of a_afArg
+  */
+  value_type Parser::Sum(const value_type *a_afArg, int a_iArgc)
+  { 
+    if (!a_iArgc)	
+      throw exception_type(_T("too few arguments for function sum."));
+
+    value_type fRes=0;
+    for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
+    return fRes;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Callback for averaging multiple values. 
+      \param [in] a_afArg Vector with the function arguments
+      \param [in] a_iArgc The size of a_afArg
+  */
+  value_type Parser::Avg(const value_type *a_afArg, int a_iArgc)
+  { 
+    if (!a_iArgc)	
+      throw exception_type(_T("too few arguments for function sum."));
+
+    value_type fRes=0;
+    for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
+    return fRes/(value_type)a_iArgc;
+  }
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Callback for determining the minimum value out of a vector. 
+      \param [in] a_afArg Vector with the function arguments
+      \param [in] a_iArgc The size of a_afArg
+  */
+  value_type Parser::Min(const value_type *a_afArg, int a_iArgc)
+  { 
+    if (!a_iArgc)	
+      throw exception_type(_T("too few arguments for function min."));
+
+    value_type fRes=a_afArg[0];
+    for (int i=0; i<a_iArgc; ++i) 
+      fRes = std::min(fRes, a_afArg[i]);
+
+    return fRes;
+  }
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Callback for determining the maximum value out of a vector. 
+      \param [in] a_afArg Vector with the function arguments
+      \param [in] a_iArgc The size of a_afArg
+  */
+  value_type Parser::Max(const value_type *a_afArg, int a_iArgc)
+  { 
+    if (!a_iArgc)	
+      throw exception_type(_T("too few arguments for function min."));
+
+    value_type fRes=a_afArg[0];
+    for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);
+
+    return fRes;
+  }
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Default value recognition callback. 
+      \param [in] a_szExpr Pointer to the expression
+      \param [in, out] a_iPos Pointer to an index storing the current position within the expression
+      \param [out] a_fVal Pointer where the value should be stored in case one is found.
+      \return 1 if a value was found 0 otherwise.
+  */
+  int Parser::IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal)
+  {
+    value_type fVal(0);
+
+    stringstream_type stream(a_szExpr);
+    stream.seekg(0);        // todo:  check if this really is necessary
+    stream.imbue(Parser::s_locale);
+    stream >> fVal;
+    stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
+
+    if (iEnd==(stringstream_type::pos_type)-1)
+      return 0;
+
+    *a_iPos += (int)iEnd;
+    *a_fVal = fVal;
+    return 1;
+  }
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Constructor. 
+
+    Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
+  */
+  Parser::Parser()
+    :ParserBase()
+  {
+    AddValIdent(IsVal);
+
+    InitCharSets();
+    InitFun();
+    InitConst();
+    InitOprt();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Define the character sets. 
+      \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars
+    
+    This function is used for initializing the default character sets that define
+    the characters to be useable in function and variable names and operators.
+  */
+  void Parser::InitCharSets()
+  {
+    DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );
+    DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") );
+    DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") );
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Initialize the default functions. */
+  void Parser::InitFun()
+  {
+    if (mu::TypeInfo<mu::value_type>::IsInteger())
+    {
+      // When setting MUP_BASETYPE to an integer type
+      // Place functions for dealing with integer values here
+      // ...
+      // ...
+      // ...
+    }
+    else
+    {
+      // trigonometric functions
+      DefineFun(_T("sin"), Sin);
+      DefineFun(_T("cos"), Cos);
+      DefineFun(_T("tan"), Tan);
+      // arcus functions
+      DefineFun(_T("asin"), ASin);
+      DefineFun(_T("acos"), ACos);
+      DefineFun(_T("atan"), ATan);
+      DefineFun(_T("atan2"), ATan2);
+      // hyperbolic functions
+      DefineFun(_T("sinh"), Sinh);
+      DefineFun(_T("cosh"), Cosh);
+      DefineFun(_T("tanh"), Tanh);
+      // arcus hyperbolic functions
+      DefineFun(_T("asinh"), ASinh);
+      DefineFun(_T("acosh"), ACosh);
+      DefineFun(_T("atanh"), ATanh);
+      // Logarithm functions
+      DefineFun(_T("log2"), Log2);
+      DefineFun(_T("log10"), Log10);
+      DefineFun(_T("log"), Ln);
+      DefineFun(_T("ln"), Ln);
+      // misc
+      DefineFun(_T("exp"), Exp);
+      DefineFun(_T("sqrt"), Sqrt);
+      DefineFun(_T("sign"), Sign);
+      DefineFun(_T("rint"), Rint);
+      DefineFun(_T("abs"), Abs);
+      // Functions with variable number of arguments
+      DefineFun(_T("sum"), Sum);
+      DefineFun(_T("avg"), Avg);
+      DefineFun(_T("min"), Min);
+      DefineFun(_T("max"), Max);
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Initialize constants.
+  
+    By default the parser recognizes two constants. Pi ("pi") and the Eulerian
+    number ("_e").
+  */
+  void Parser::InitConst()
+  {
+    DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI);
+    DefineConst(_T("_e"), (value_type)PARSER_CONST_E);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Initialize operators. 
+  
+    By default only the unary minus operator is added.
+  */
+  void Parser::InitOprt()
+  {
+    DefineInfixOprt(_T("-"), UnaryMinus);
+    DefineInfixOprt(_T("+"), UnaryPlus);
+  }
+
+  //---------------------------------------------------------------------------
+  void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)
+  {
+    // this is just sample code to illustrate modifying variable names on the fly.
+    // I'm not sure anyone really needs such a feature...
+    /*
+
+
+    string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);
+    string sRepl = std::string("_") + sVar + "_";
+  
+    int nOrigVarEnd = nEnd;
+    cout << "variable detected!\n";
+    cout << "  Expr: " << *pExpr << "\n";
+    cout << "  Start: " << nStart << "\n";
+    cout << "  End: " << nEnd << "\n";
+    cout << "  Var: \"" << sVar << "\"\n";
+    cout << "  Repl: \"" << sRepl << "\"\n";
+    nEnd = nStart + sRepl.length();
+    cout << "  End: " << nEnd << "\n";
+    pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);
+    cout << "  New expr: " << *pExpr << "\n";
+    */
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Numerically differentiate with regard to a variable. 
+      \param [in] a_Var Pointer to the differentiation variable.
+      \param [in] a_fPos Position at which the differentiation should take place.
+      \param [in] a_fEpsilon Epsilon used for the numerical differentiation.
+
+    Numerical differentiation uses a 5 point operator yielding a 4th order 
+    formula. The default value for epsilon is 0.00074 which is
+    numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muparser
+    forum:
+
+    http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843
+  */
+  value_type Parser::Diff(value_type *a_Var, 
+                          value_type  a_fPos, 
+                          value_type  a_fEpsilon) const
+  {
+    value_type fRes(0), 
+               fBuf(*a_Var),
+               f[4] = {0,0,0,0},
+               fEpsilon(a_fEpsilon);
+
+    // Backwards compatible calculation of epsilon inc case the user doesn't provide
+    // his own epsilon
+    if (fEpsilon==0)
+      fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;
+
+    *a_Var = a_fPos+2 * fEpsilon;  f[0] = Eval();
+    *a_Var = a_fPos+1 * fEpsilon;  f[1] = Eval();
+    *a_Var = a_fPos-1 * fEpsilon;  f[2] = Eval();
+    *a_Var = a_fPos-2 * fEpsilon;  f[3] = Eval();
+    *a_Var = fBuf; // restore variable
+
+    fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon);
+    return fRes;
+  }
+} // namespace mu
diff --git a/source/ThirdParty/MuParser/src/muParserBase.cpp b/source/ThirdParty/MuParser/src/muParserBase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea3699a12fc02cf7973adc145c1ce5667f4b5715
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParserBase.cpp
@@ -0,0 +1,1778 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#include "muParserBase.h"
+#include "muParserTemplateMagic.h"
+
+//--- Standard includes ------------------------------------------------------------------------
+#include <cassert>
+#include <algorithm>
+#include <cmath>
+#include <memory>
+#include <vector>
+#include <deque>
+#include <sstream>
+#include <locale>
+
+#ifdef MUP_USE_OPENMP
+  #include <omp.h>
+#endif
+
+using namespace std;
+
+/** \file
+    \brief This file contains the basic implementation of the muparser engine.
+*/
+
+namespace mu
+{
+  std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.'));
+
+  bool ParserBase::g_DbgDumpCmdCode = false;
+  bool ParserBase::g_DbgDumpStack = false;
+
+  //------------------------------------------------------------------------------
+  /** \brief Identifiers for built in binary operators. 
+
+      When defining custom binary operators with #AddOprt(...) make sure not to choose 
+      names conflicting with these definitions. 
+  */
+  const char_type* ParserBase::c_DefaultOprt[] = 
+  { 
+    _T("<="), _T(">="),  _T("!="), 
+    _T("=="), _T("<"),   _T(">"), 
+    _T("+"),  _T("-"),   _T("*"), 
+    _T("/"),  _T("^"),   _T("&&"), 
+    _T("||"), _T("="),   _T("("),  
+    _T(")"),   _T("?"),  _T(":"), 0 
+  };
+
+  //------------------------------------------------------------------------------
+  /** \brief Constructor.
+      \param a_szFormula the formula to interpret.
+      \throw ParserException if a_szFormula is null.
+  */
+  ParserBase::ParserBase()
+    :m_pParseFormula(&ParserBase::ParseString)
+    ,m_vRPN()
+    ,m_vStringBuf()
+    ,m_pTokenReader()
+    ,m_FunDef()
+    ,m_PostOprtDef()
+    ,m_InfixOprtDef()
+    ,m_OprtDef()
+    ,m_ConstDef()
+    ,m_StrVarDef()
+    ,m_VarDef()
+    ,m_bBuiltInOp(true)
+    ,m_sNameChars()
+    ,m_sOprtChars()
+    ,m_sInfixOprtChars()
+    ,m_nIfElseCounter(0)
+    ,m_vStackBuffer()
+    ,m_nFinalResultIdx(0)
+  {
+    InitTokenReader();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Copy constructor. 
+
+    The parser can be safely copy constructed but the bytecode is reset during
+    copy construction.
+  */
+  ParserBase::ParserBase(const ParserBase &a_Parser)
+    :m_pParseFormula(&ParserBase::ParseString)
+    ,m_vRPN()
+    ,m_vStringBuf()
+    ,m_pTokenReader()
+    ,m_FunDef()
+    ,m_PostOprtDef()
+    ,m_InfixOprtDef()
+    ,m_OprtDef()
+    ,m_ConstDef()
+    ,m_StrVarDef()
+    ,m_VarDef()
+    ,m_bBuiltInOp(true)
+    ,m_sNameChars()
+    ,m_sOprtChars()
+    ,m_sInfixOprtChars()
+    ,m_nIfElseCounter(0)
+  {
+    m_pTokenReader.reset(new token_reader_type(this));
+    Assign(a_Parser);
+  }
+
+  //---------------------------------------------------------------------------
+  ParserBase::~ParserBase()
+  {}
+
+  //---------------------------------------------------------------------------
+  /** \brief Assignment operator. 
+
+    Implemented by calling Assign(a_Parser). Self assignment is suppressed.
+    \param a_Parser Object to copy to this.
+    \return *this
+    \throw nothrow
+  */
+  ParserBase& ParserBase::operator=(const ParserBase &a_Parser)
+  {
+    Assign(a_Parser);
+    return *this;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Copy state of a parser object to this. 
+
+    Clears Variables and Functions of this parser.
+    Copies the states of all internal variables.
+    Resets parse function to string parse mode.
+
+    \param a_Parser the source object.
+  */
+  void ParserBase::Assign(const ParserBase &a_Parser)
+  {
+    if (&a_Parser==this)
+      return;
+
+    // Don't copy bytecode instead cause the parser to create new bytecode
+    // by resetting the parse function.
+    ReInit();
+
+    m_ConstDef        = a_Parser.m_ConstDef;         // Copy user define constants
+    m_VarDef          = a_Parser.m_VarDef;           // Copy user defined variables
+    m_bBuiltInOp      = a_Parser.m_bBuiltInOp;
+    m_vStringBuf      = a_Parser.m_vStringBuf;
+    m_vStackBuffer    = a_Parser.m_vStackBuffer;
+    m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;
+    m_StrVarDef       = a_Parser.m_StrVarDef;
+    m_vStringVarBuf   = a_Parser.m_vStringVarBuf;
+    m_nIfElseCounter  = a_Parser.m_nIfElseCounter;
+    m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this));
+
+    // Copy function and operator callbacks
+    m_FunDef = a_Parser.m_FunDef;             // Copy function definitions
+    m_PostOprtDef = a_Parser.m_PostOprtDef;   // post value unary operators
+    m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation
+    m_OprtDef = a_Parser.m_OprtDef;           // binary operators
+
+    m_sNameChars = a_Parser.m_sNameChars;
+    m_sOprtChars = a_Parser.m_sOprtChars;
+    m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Set the decimal separator.
+      \param cDecSep Decimal separator as a character value.
+      \sa SetThousandsSep
+
+      By default muparser uses the "C" locale. The decimal separator of this
+      locale is overwritten by the one provided here.
+  */
+  void ParserBase::SetDecSep(char_type cDecSep)
+  {
+    char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();
+    s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
+  }
+  
+  //---------------------------------------------------------------------------
+  /** \brief Sets the thousands operator. 
+      \param cThousandsSep The thousands separator as a character
+      \sa SetDecSep
+
+      By default muparser uses the "C" locale. The thousands separator of this
+      locale is overwritten by the one provided here.
+  */
+  void ParserBase::SetThousandsSep(char_type cThousandsSep)
+  {
+    char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();
+    s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Resets the locale. 
+
+    The default locale used "." as decimal separator, no thousands separator and
+    "," as function argument separator.
+  */
+  void ParserBase::ResetLocale()
+  {
+    s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));
+    SetArgSep(',');
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Initialize the token reader. 
+
+    Create new token reader object and submit pointers to function, operator,
+    constant and variable definitions.
+
+    \post m_pTokenReader.get()!=0
+    \throw nothrow
+  */
+  void ParserBase::InitTokenReader()
+  {
+    m_pTokenReader.reset(new token_reader_type(this));
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Reset parser to string parsing mode and clear internal buffers.
+
+      Clear bytecode, reset the token reader.
+      \throw nothrow
+  */
+  void ParserBase::ReInit() const
+  {
+    m_pParseFormula = &ParserBase::ParseString;
+    m_vStringBuf.clear();
+    m_vRPN.clear();
+    m_pTokenReader->ReInit();
+    m_nIfElseCounter = 0;
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)
+  {}
+
+  //---------------------------------------------------------------------------
+  /** \brief Returns the version of muparser. 
+      \param eInfo A flag indicating whether the full version info should be 
+                   returned or not.
+
+    Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS
+    are returned only if eInfo==pviFULL.
+  */
+  string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const
+  {
+    stringstream_type ss;
+
+    ss << MUP_VERSION;
+
+    if (eInfo==pviFULL)
+    {
+      ss << _T(" (") << MUP_VERSION_DATE;
+      ss << std::dec << _T("; ") << sizeof(void*)*8 << _T("BIT");
+
+#ifdef _DEBUG
+      ss << _T("; DEBUG");
+#else 
+      ss << _T("; RELEASE");
+#endif
+
+#ifdef _UNICODE
+      ss << _T("; UNICODE");
+#else
+  #ifdef _MBCS
+      ss << _T("; MBCS");
+  #else
+      ss << _T("; ASCII");
+  #endif
+#endif
+
+#ifdef MUP_USE_OPENMP
+      ss << _T("; OPENMP");
+//#else
+//      ss << _T("; NO_OPENMP");
+#endif
+
+#if defined(MUP_MATH_EXCEPTIONS)
+      ss << _T("; MATHEXC");
+//#else
+//      ss << _T("; NO_MATHEXC");
+#endif
+
+      ss << _T(")");
+    }
+
+    return ss.str();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a value parsing function. 
+      
+      When parsing an expression muParser tries to detect values in the expression
+      string using different valident callbacks. Thus it's possible to parse
+      for hex values, binary values and floating point values. 
+  */
+  void ParserBase::AddValIdent(identfun_type a_pCallback)
+  {
+    m_pTokenReader->AddValIdent(a_pCallback);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Set a function that can create variable pointer for unknown expression variables. 
+      \param a_pFactory A pointer to the variable factory.
+      \param pUserData A user defined context pointer.
+  */
+  void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData)
+  {
+    m_pTokenReader->SetVarCreator(a_pFactory, pUserData);  
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a function or operator callback to the parser. */
+  void ParserBase::AddCallback( const string_type &a_strName,
+                                const ParserCallback &a_Callback, 
+                                funmap_type &a_Storage,
+                                const char_type *a_szCharSet )
+  {
+    if (a_Callback.GetAddr()==0)
+        Error(ecINVALID_FUN_PTR);
+
+    const funmap_type *pFunMap = &a_Storage;
+
+    // Check for conflicting operator or function names
+    if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() )
+      Error(ecNAME_CONFLICT, -1, a_strName);
+
+    if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() )
+      Error(ecNAME_CONFLICT, -1, a_strName);
+
+    if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() )
+      Error(ecNAME_CONFLICT, -1, a_strName);
+
+    if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() )
+      Error(ecNAME_CONFLICT, -1, a_strName);
+
+    CheckOprt(a_strName, a_Callback, a_szCharSet);
+    a_Storage[a_strName] = a_Callback;
+    ReInit();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check if a name contains invalid characters. 
+
+      \throw ParserException if the name contains invalid characters.
+  */
+  void ParserBase::CheckOprt(const string_type &a_sName,
+                             const ParserCallback &a_Callback,
+                             const string_type &a_szCharSet) const
+  {
+    if ( !a_sName.length() ||
+        (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||
+        (a_sName[0]>='0' && a_sName[0]<='9'))
+    {
+      switch(a_Callback.GetCode())
+      {
+      case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName);
+      case cmOPRT_INFIX:   Error(ecINVALID_INFIX_IDENT, -1, a_sName);
+      default:             Error(ecINVALID_NAME, -1, a_sName);
+      }
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check if a name contains invalid characters. 
+
+      \throw ParserException if the name contains invalid characters.
+  */
+  void ParserBase::CheckName(const string_type &a_sName,
+                             const string_type &a_szCharSet) const
+  {
+    if ( !a_sName.length() ||
+        (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||
+        (a_sName[0]>='0' && a_sName[0]<='9'))
+    {
+      Error(ecINVALID_NAME);
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Set the formula. 
+      \param a_strFormula Formula as string_type
+      \throw ParserException in case of syntax errors.
+
+      Triggers first time calculation thus the creation of the bytecode and
+      scanning of used variables.
+  */
+  void ParserBase::SetExpr(const string_type &a_sExpr)
+  {
+    // Check locale compatibility
+    std::locale loc;
+    if (m_pTokenReader->GetArgSep()==std::use_facet<numpunct<char_type> >(loc).decimal_point())
+      Error(ecLOCALE);
+
+    // <ibg> 20060222: Bugfix for Borland-Kylix:
+    // adding a space to the expression will keep Borlands KYLIX from going wild
+    // when calling tellg on a stringstream created from the expression after 
+    // reading a value at the end of an expression. (mu::Parser::IsVal function)
+    // (tellg returns -1 otherwise causing the parser to ignore the value)
+    string_type sBuf(a_sExpr + _T(" ") );
+    m_pTokenReader->SetFormula(sBuf);
+    ReInit();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Get the default symbols used for the built in operators. 
+      \sa c_DefaultOprt
+  */
+  const char_type** ParserBase::GetOprtDef() const
+  {
+    return (const char_type **)(&c_DefaultOprt[0]);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Define the set of valid characters to be used in names of
+             functions, variables, constants.
+  */
+  void ParserBase::DefineNameChars(const char_type *a_szCharset)
+  {
+    m_sNameChars = a_szCharset;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Define the set of valid characters to be used in names of
+             binary operators and postfix operators.
+  */
+  void ParserBase::DefineOprtChars(const char_type *a_szCharset)
+  {
+    m_sOprtChars = a_szCharset;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Define the set of valid characters to be used in names of
+             infix operators.
+  */
+  void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset)
+  {
+    m_sInfixOprtChars = a_szCharset;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Virtual function that defines the characters allowed in name identifiers. 
+      \sa #ValidOprtChars, #ValidPrefixOprtChars
+  */ 
+  const char_type* ParserBase::ValidNameChars() const
+  {
+    assert(m_sNameChars.size());
+    return m_sNameChars.c_str();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Virtual function that defines the characters allowed in operator definitions. 
+      \sa #ValidNameChars, #ValidPrefixOprtChars
+  */
+  const char_type* ParserBase::ValidOprtChars() const
+  {
+    assert(m_sOprtChars.size());
+    return m_sOprtChars.c_str();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Virtual function that defines the characters allowed in infix operator definitions.
+      \sa #ValidNameChars, #ValidOprtChars
+  */
+  const char_type* ParserBase::ValidInfixOprtChars() const
+  {
+    assert(m_sInfixOprtChars.size());
+    return m_sInfixOprtChars.c_str();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a user defined operator. 
+      \post Will reset the Parser to string parsing mode.
+  */
+  void ParserBase::DefinePostfixOprt(const string_type &a_sName, 
+                                     fun_type1 a_pFun,
+                                     bool a_bAllowOpt)
+  {
+    AddCallback(a_sName, 
+                ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX),
+                m_PostOprtDef, 
+                ValidOprtChars() );
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Initialize user defined functions. 
+   
+    Calls the virtual functions InitFun(), InitConst() and InitOprt().
+  */
+  void ParserBase::Init()
+  {
+    InitCharSets();
+    InitFun();
+    InitConst();
+    InitOprt();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a user defined operator. 
+      \post Will reset the Parser to string parsing mode.
+      \param [in] a_sName  operator Identifier 
+      \param [in] a_pFun  Operator callback function
+      \param [in] a_iPrec  Operator Precedence (default=prSIGN)
+      \param [in] a_bAllowOpt  True if operator is volatile (default=false)
+      \sa EPrec
+  */
+  void ParserBase::DefineInfixOprt(const string_type &a_sName, 
+                                  fun_type1 a_pFun, 
+                                  int a_iPrec, 
+                                  bool a_bAllowOpt)
+  {
+    AddCallback(a_sName, 
+                ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), 
+                m_InfixOprtDef, 
+                ValidInfixOprtChars() );
+  }
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Define a binary operator. 
+      \param [in] a_sName The identifier of the operator.
+      \param [in] a_pFun Pointer to the callback function.
+      \param [in] a_iPrec Precedence of the operator.
+      \param [in] a_eAssociativity The associativity of the operator.
+      \param [in] a_bAllowOpt If this is true the operator may be optimized away.
+      
+      Adds a new Binary operator the the parser instance. 
+  */
+  void ParserBase::DefineOprt( const string_type &a_sName, 
+                               fun_type2 a_pFun, 
+                               unsigned a_iPrec, 
+                               EOprtAssociativity a_eAssociativity,
+                               bool a_bAllowOpt )
+  {
+    // Check for conflicts with built in operator names
+    for (int i=0; m_bBuiltInOp && i<cmENDIF; ++i)
+      if (a_sName == string_type(c_DefaultOprt[i]))
+        Error(ecBUILTIN_OVERLOAD, -1, a_sName);
+
+    AddCallback(a_sName, 
+                ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), 
+                m_OprtDef, 
+                ValidOprtChars() );
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Define a new string constant.
+      \param [in] a_strName The name of the constant.
+      \param [in] a_strVal the value of the constant. 
+  */
+  void ParserBase::DefineStrConst(const string_type &a_strName, const string_type &a_strVal)
+  {
+    // Test if a constant with that names already exists
+    if (m_StrVarDef.find(a_strName)!=m_StrVarDef.end())
+      Error(ecNAME_CONFLICT);
+
+    CheckName(a_strName, ValidNameChars());
+    
+    m_vStringVarBuf.push_back(a_strVal);                // Store variable string in internal buffer
+    m_StrVarDef[a_strName] = m_vStringVarBuf.size()-1;  // bind buffer index to variable name
+
+    ReInit();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a user defined variable. 
+      \param [in] a_sName the variable name
+      \param [in] a_pVar A pointer to the variable value.
+      \post Will reset the Parser to string parsing mode.
+      \throw ParserException in case the name contains invalid signs or a_pVar is NULL.
+  */
+  void ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar)
+  {
+    if (a_pVar==0)
+      Error(ecINVALID_VAR_PTR);
+
+    // Test if a constant with that names already exists
+    if (m_ConstDef.find(a_sName)!=m_ConstDef.end())
+      Error(ecNAME_CONFLICT);
+
+    CheckName(a_sName, ValidNameChars());
+    m_VarDef[a_sName] = a_pVar;
+    ReInit();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a user defined constant. 
+      \param [in] a_sName The name of the constant.
+      \param [in] a_fVal the value of the constant.
+      \post Will reset the Parser to string parsing mode.
+      \throw ParserException in case the name contains invalid signs.
+  */
+  void ParserBase::DefineConst(const string_type &a_sName, value_type a_fVal)
+  {
+    CheckName(a_sName, ValidNameChars());
+    m_ConstDef[a_sName] = a_fVal;
+    ReInit();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Get operator priority.
+      \throw ParserException if a_Oprt is no operator code
+  */
+  int ParserBase::GetOprtPrecedence(const token_type &a_Tok) const
+  {
+    switch (a_Tok.GetCode())
+    {
+    // built in operators
+    case cmEND:      return -5;
+    case cmARG_SEP:  return -4;
+    case cmASSIGN:   return -1;               
+    case cmELSE:
+    case cmIF:       return  0;
+    case cmLAND:     return  prLAND;
+    case cmLOR:      return  prLOR;
+    case cmLT:
+    case cmGT:
+    case cmLE:
+    case cmGE:
+    case cmNEQ:
+    case cmEQ:       return  prCMP; 
+    case cmADD:
+    case cmSUB:      return  prADD_SUB;
+    case cmMUL:
+    case cmDIV:      return  prMUL_DIV;
+    case cmPOW:      return  prPOW;
+
+    // user defined binary operators
+    case cmOPRT_INFIX: 
+    case cmOPRT_BIN: return a_Tok.GetPri();
+    default:  Error(ecINTERNAL_ERROR, 5);
+              return 999;
+    }  
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Get operator priority.
+      \throw ParserException if a_Oprt is no operator code
+  */
+  EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) const
+  {
+    switch (a_Tok.GetCode())
+    {
+    case cmASSIGN:
+    case cmLAND:
+    case cmLOR:
+    case cmLT:
+    case cmGT:
+    case cmLE:
+    case cmGE:
+    case cmNEQ:
+    case cmEQ: 
+    case cmADD:
+    case cmSUB:
+    case cmMUL:
+    case cmDIV:      return oaLEFT;
+    case cmPOW:      return oaRIGHT;
+    case cmOPRT_BIN: return a_Tok.GetAssociativity();
+    default:         return oaNONE;
+    }  
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return a map containing the used variables only. */
+  const varmap_type& ParserBase::GetUsedVar() const
+  {
+    try
+    {
+      m_pTokenReader->IgnoreUndefVar(true);
+      CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it
+                   // may contain references to nonexisting variables.
+      m_pParseFormula = &ParserBase::ParseString;
+      m_pTokenReader->IgnoreUndefVar(false);
+    }
+    catch(exception_type & /*e*/)
+    {
+      // Make sure to stay in string parse mode, dont call ReInit()
+      // because it deletes the array with the used variables
+      m_pParseFormula = &ParserBase::ParseString;
+      m_pTokenReader->IgnoreUndefVar(false);
+      throw;
+    }
+    
+    return m_pTokenReader->GetUsedVar();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return a map containing the used variables only. */
+  const varmap_type& ParserBase::GetVar() const
+  {
+    return m_VarDef;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return a map containing all parser constants. */
+  const valmap_type& ParserBase::GetConst() const
+  {
+    return m_ConstDef;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return prototypes of all parser functions.
+      \return #m_FunDef
+      \sa FunProt
+      \throw nothrow
+      
+      The return type is a map of the public type #funmap_type containing the prototype
+      definitions for all numerical parser functions. String functions are not part of 
+      this map. The Prototype definition is encapsulated in objects of the class FunProt
+      one per parser function each associated with function names via a map construct.
+  */
+  const funmap_type& ParserBase::GetFunDef() const
+  {
+    return m_FunDef;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Retrieve the formula. */
+  const string_type& ParserBase::GetExpr() const
+  {
+    return m_pTokenReader->GetExpr();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Execute a function that takes a single string argument.
+      \param a_FunTok Function token.
+      \throw exception_type If the function token is not a string function
+  */
+  ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok,
+                                                  const std::vector<token_type> &a_vArg) const
+  {
+    if (a_vArg.back().GetCode()!=cmSTRING)
+      Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
+
+    token_type  valTok;
+    generic_fun_type pFunc = a_FunTok.GetFuncAddr();
+    assert(pFunc);
+
+    try
+    {
+      // Check function arguments; write dummy value into valtok to represent the result
+      switch(a_FunTok.GetArgCount())
+      {
+      case 0: valTok.SetVal(1); a_vArg[0].GetAsString();  break;
+      case 1: valTok.SetVal(1); a_vArg[1].GetAsString();  a_vArg[0].GetVal();  break;
+      case 2: valTok.SetVal(1); a_vArg[2].GetAsString();  a_vArg[1].GetVal();  a_vArg[0].GetVal();  break;
+      default: Error(ecINTERNAL_ERROR);
+      }
+    }
+    catch(ParserError& )
+    {
+      Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
+    }
+
+    // string functions won't be optimized
+    m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
+    
+    // Push dummy value representing the function result to the stack
+    return valTok;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Apply a function token. 
+      \param iArgCount Number of Arguments actually gathered used only for multiarg functions.
+      \post The result is pushed to the value stack
+      \post The function token is removed from the stack
+      \throw exception_type if Argument count does not match function requirements.
+  */
+  void ParserBase::ApplyFunc( ParserStack<token_type> &a_stOpt,
+                              ParserStack<token_type> &a_stVal, 
+                              int a_iArgCount) const
+  { 
+    assert(m_pTokenReader.get());
+
+    // Operator stack empty or does not contain tokens with callback functions
+    if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 )
+      return;
+
+    token_type funTok = a_stOpt.pop();
+    assert(funTok.GetFuncAddr());
+
+    // Binary operators must rely on their internal operator number
+    // since counting of operators relies on commas for function arguments
+    // binary operators do not have commas in their expression
+    int iArgCount = (funTok.GetCode()==cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;
+
+    // determine how many parameters the function needs. To remember iArgCount includes the 
+    // string parameter whilst GetArgCount() counts only numeric parameters.
+    int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==tpSTR) ? 1 : 0);
+
+    // Thats the number of numerical parameters
+    int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0);
+
+    if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1)
+      Error(ecINTERNAL_ERROR);
+
+    if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) 
+      Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());
+
+    if (funTok.GetCode()!=cmOPRT_BIN && iArgCount<iArgRequired )
+      Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());
+
+    if (funTok.GetCode()==cmFUNC_STR && iArgCount>iArgRequired )
+      Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());
+
+    // Collect the numeric function arguments from the value stack and store them
+    // in a vector
+    std::vector<token_type> stArg;  
+    for (int i=0; i<iArgNumerical; ++i)
+    {
+      stArg.push_back( a_stVal.pop() );
+      if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )
+        Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
+    }
+
+    switch(funTok.GetCode())
+    {
+    case  cmFUNC_STR:  
+          stArg.push_back(a_stVal.pop());
+          
+          if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )
+            Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
+
+          ApplyStrFunc(funTok, stArg); 
+          break;
+
+    case  cmFUNC_BULK: 
+          m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); 
+          break;
+
+    case  cmOPRT_BIN:
+    case  cmOPRT_POSTFIX:
+    case  cmOPRT_INFIX:
+    case  cmFUNC:
+          if (funTok.GetArgCount()==-1 && iArgCount==0)
+            Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString());
+
+          m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical);
+          break;
+    }
+
+    // Push dummy value representing the function result to the stack
+    token_type token;
+    token.SetVal(1);  
+    a_stVal.push(token);
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserBase::ApplyIfElse(ParserStack<token_type> &a_stOpt,
+                               ParserStack<token_type> &a_stVal) const
+  {
+    // Check if there is an if Else clause to be calculated
+    while (a_stOpt.size() && a_stOpt.top().GetCode()==cmELSE)
+    {
+      token_type opElse = a_stOpt.pop();
+      MUP_ASSERT(a_stOpt.size()>0);
+
+      // Take the value associated with the else branch from the value stack
+      token_type vVal2 = a_stVal.pop();
+
+      MUP_ASSERT(a_stOpt.size()>0);
+      MUP_ASSERT(a_stVal.size()>=2);
+
+      // it then else is a ternary operator Pop all three values from the value s
+      // tack and just return the right value
+      token_type vVal1 = a_stVal.pop();
+      token_type vExpr = a_stVal.pop();
+
+      a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2);
+
+      token_type opIf = a_stOpt.pop();
+      MUP_ASSERT(opElse.GetCode()==cmELSE);
+      MUP_ASSERT(opIf.GetCode()==cmIF);
+
+      m_vRPN.AddIfElse(cmENDIF);
+    } // while pending if-else-clause found
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Performs the necessary steps to write code for
+             the execution of binary operators into the bytecode. 
+  */
+  void ParserBase::ApplyBinOprt(ParserStack<token_type> &a_stOpt,
+                                ParserStack<token_type> &a_stVal) const
+  {
+    // is it a user defined binary operator?
+    if (a_stOpt.top().GetCode()==cmOPRT_BIN)
+    {
+      ApplyFunc(a_stOpt, a_stVal, 2);
+    }
+    else
+    {
+      MUP_ASSERT(a_stVal.size()>=2);
+      token_type valTok1 = a_stVal.pop(),
+                 valTok2 = a_stVal.pop(),
+                 optTok  = a_stOpt.pop(),
+                 resTok; 
+
+      if ( valTok1.GetType()!=valTok2.GetType() || 
+          (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) )
+        Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());
+
+      if (optTok.GetCode()==cmASSIGN)
+      {
+        if (valTok2.GetCode()!=cmVAR)
+          Error(ecUNEXPECTED_OPERATOR, -1, _T("="));
+                      
+        m_vRPN.AddAssignOp(valTok2.GetVar());
+      }
+      else
+        m_vRPN.AddOp(optTok.GetCode());
+
+      resTok.SetVal(1);
+      a_stVal.push(resTok);
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Apply a binary operator. 
+      \param a_stOpt The operator stack
+      \param a_stVal The value stack
+  */
+  void ParserBase::ApplyRemainingOprt(ParserStack<token_type> &stOpt,
+                                      ParserStack<token_type> &stVal) const
+  {
+    while (stOpt.size() && 
+           stOpt.top().GetCode() != cmBO &&
+           stOpt.top().GetCode() != cmIF)
+    {
+      token_type tok = stOpt.top();
+      switch (tok.GetCode())
+      {
+      case cmOPRT_INFIX:
+      case cmOPRT_BIN:
+      case cmLE:
+      case cmGE:
+      case cmNEQ:
+      case cmEQ:
+      case cmLT:
+      case cmGT:
+      case cmADD:
+      case cmSUB:
+      case cmMUL:
+      case cmDIV:
+      case cmPOW:
+      case cmLAND:
+      case cmLOR:
+      case cmASSIGN:
+          if (stOpt.top().GetCode()==cmOPRT_INFIX)
+            ApplyFunc(stOpt, stVal, 1);
+          else
+            ApplyBinOprt(stOpt, stVal);
+          break;
+
+      case cmELSE:
+          ApplyIfElse(stOpt, stVal);
+          break;
+
+      default:
+          Error(ecINTERNAL_ERROR);
+      }
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Parse the command code.
+      \sa ParseString(...)
+
+      Command code contains precalculated stack positions of the values and the
+      associated operators. The Stack is filled beginning from index one the 
+      value at index zero is not used at all.
+  */
+  value_type ParserBase::ParseCmdCode() const
+  {
+    return ParseCmdCodeBulk(0, 0);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Evaluate the RPN. 
+      \param nOffset The offset added to variable addresses (for bulk mode)
+      \param nThreadID OpenMP Thread id of the calling thread
+  */
+  value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const
+  {
+    assert(nThreadID<=s_MaxNumOpenMPThreads);
+
+    // Note: The check for nOffset==0 and nThreadID here is not necessary but 
+    //       brings a minor performance gain when not in bulk mode.
+    value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];
+    value_type buf;
+    int sidx(0);
+    for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=cmEND ; ++pTok)
+    {
+      switch (pTok->Cmd)
+      {
+      // built in binary operators
+      case  cmLE:   --sidx; Stack[sidx]  = Stack[sidx] <= Stack[sidx+1]; continue;
+      case  cmGE:   --sidx; Stack[sidx]  = Stack[sidx] >= Stack[sidx+1]; continue;
+      case  cmNEQ:  --sidx; Stack[sidx]  = Stack[sidx] != Stack[sidx+1]; continue;
+      case  cmEQ:   --sidx; Stack[sidx]  = Stack[sidx] == Stack[sidx+1]; continue;
+      case  cmLT:   --sidx; Stack[sidx]  = Stack[sidx] < Stack[sidx+1];  continue;
+      case  cmGT:   --sidx; Stack[sidx]  = Stack[sidx] > Stack[sidx+1];  continue;
+      case  cmADD:  --sidx; Stack[sidx] += Stack[1+sidx]; continue;
+      case  cmSUB:  --sidx; Stack[sidx] -= Stack[1+sidx]; continue;
+      case  cmMUL:  --sidx; Stack[sidx] *= Stack[1+sidx]; continue;
+      case  cmDIV:  --sidx;
+
+  #if defined(MUP_MATH_EXCEPTIONS)
+                  if (Stack[1+sidx]==0)
+                    Error(ecDIV_BY_ZERO);
+  #endif
+                  Stack[sidx] /= Stack[1+sidx]; 
+                  continue;
+
+      case  cmPOW: 
+              --sidx; Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1+sidx]);
+              continue;
+
+      case  cmLAND: --sidx; Stack[sidx]  = Stack[sidx] && Stack[sidx+1]; continue;
+      case  cmLOR:  --sidx; Stack[sidx]  = Stack[sidx] || Stack[sidx+1]; continue;
+
+      case  cmASSIGN: 
+          // Bugfix for Bulkmode:
+          // for details see:
+          //    https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws
+          --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; continue;
+          // original code:
+          //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue;
+
+      //case  cmBO:  // unused, listed for compiler optimization purposes
+      //case  cmBC:
+      //      MUP_FAIL(INVALID_CODE_IN_BYTECODE);
+      //      continue;
+
+      case  cmIF:
+            if (Stack[sidx--]==0)
+              pTok += pTok->Oprt.offset;
+            continue;
+
+      case  cmELSE:
+            pTok += pTok->Oprt.offset;
+            continue;
+
+      case  cmENDIF:
+            continue;
+
+      //case  cmARG_SEP:
+      //      MUP_FAIL(INVALID_CODE_IN_BYTECODE);
+      //      continue;
+
+      // value and variable tokens
+      case  cmVAR:    Stack[++sidx] = *(pTok->Val.ptr + nOffset);  continue;
+      case  cmVAL:    Stack[++sidx] =  pTok->Val.data2;  continue;
+      
+      case  cmVARPOW2: buf = *(pTok->Val.ptr + nOffset);
+                       Stack[++sidx] = buf*buf;
+                       continue;
+
+      case  cmVARPOW3: buf = *(pTok->Val.ptr + nOffset);
+                       Stack[++sidx] = buf*buf*buf;
+                       continue;
+
+      case  cmVARPOW4: buf = *(pTok->Val.ptr + nOffset);
+                       Stack[++sidx] = buf*buf*buf*buf;
+                       continue;
+      
+      case  cmVARMUL:  Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2;
+                       continue;
+
+      // Next is treatment of numeric functions
+      case  cmFUNC:
+            {
+              int iArgCount = pTok->Fun.argc;
+
+              // switch according to argument count
+              switch(iArgCount)  
+              {
+              case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)(); continue;
+              case 1:            Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]);   continue;
+              case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1]); continue;
+              case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue;
+              case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue;
+              case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue;
+              case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue;
+              case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue;
+              case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue;
+              case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue;
+              case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue;
+              default:
+                if (iArgCount>0) // function with variable arguments store the number as a negative value
+                  Error(ecINTERNAL_ERROR, 1);
+
+                sidx -= -iArgCount - 1;
+                Stack[sidx] =(*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount);
+                continue;
+              }
+            }
+
+      // Next is treatment of string functions
+      case  cmFUNC_STR:
+            {
+              sidx -= pTok->Fun.argc -1;
+
+              // The index of the string argument in the string table
+              int iIdxStack = pTok->Fun.idx;  
+              MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() );
+
+              switch(pTok->Fun.argc)  // switch according to argument count
+              {
+              case 0: Stack[sidx] = (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue;
+              case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue;
+              case 2: Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue;
+              }
+
+              continue;
+            }
+
+        case  cmFUNC_BULK:
+              {
+                int iArgCount = pTok->Fun.argc;
+
+                // switch according to argument count
+                switch(iArgCount)  
+                {
+                case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0 )pTok->Fun.ptr)(nOffset, nThreadID); continue;
+                case 1:            Stack[sidx] = (*(bulkfun_type1 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue;
+                case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]); continue;
+                case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue;
+                case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue;
+                case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue;
+                case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue;
+                case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue;
+                case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue;
+                case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue;
+                case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue;
+                default:
+                  Error(ecINTERNAL_ERROR, 2);
+                  continue;
+                }
+              }
+
+        default:
+              Error(ecINTERNAL_ERROR, 3);
+              return 0;
+      } // switch CmdCode
+    } // for all bytecode tokens
+
+    return Stack[m_nFinalResultIdx];  
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserBase::CreateRPN() const
+  {
+    if (!m_pTokenReader->GetExpr().length())
+      Error(ecUNEXPECTED_EOF, 0);
+
+    ParserStack<token_type> stOpt, stVal;
+    ParserStack<int> stArgCount;
+    token_type opta, opt;  // for storing operators
+    token_type val, tval;  // for storing value
+
+    ReInit();
+    
+    // The outermost counter counts the number of separated items
+    // such as in "a=10,b=20,c=c+a"
+    stArgCount.push(1);
+    
+    for(;;)
+    {
+      opt = m_pTokenReader->ReadNextToken();
+
+      switch (opt.GetCode())
+      {
+        //
+        // Next three are different kind of value entries
+        //
+        case cmSTRING:
+                opt.SetIdx((int)m_vStringBuf.size());      // Assign buffer index to token 
+                stVal.push(opt);
+		            m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer
+                break;
+   
+        case cmVAR:
+                stVal.push(opt);
+                m_vRPN.AddVar( static_cast<value_type*>(opt.GetVar()) );
+                break;
+
+        case cmVAL:
+		        stVal.push(opt);
+                m_vRPN.AddVal( opt.GetVal() );
+                break;
+
+        case cmELSE:
+                m_nIfElseCounter--;
+                if (m_nIfElseCounter<0)
+                  Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
+
+                ApplyRemainingOprt(stOpt, stVal);
+                m_vRPN.AddIfElse(cmELSE);
+                stOpt.push(opt);
+                break;
+
+
+        case cmARG_SEP:
+                if (stArgCount.empty())
+                  Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
+
+                ++stArgCount.top();
+                // fallthrough intentional (no break!)
+
+        case cmEND:
+                ApplyRemainingOprt(stOpt, stVal);
+                break;
+
+       case cmBC:
+                {
+                  // The argument count for parameterless functions is zero
+                  // by default an opening bracket sets parameter count to 1
+                  // in preparation of arguments to come. If the last token
+                  // was an opening bracket we know better...
+                  if (opta.GetCode()==cmBO)
+                    --stArgCount.top();
+                  
+                  ApplyRemainingOprt(stOpt, stVal);
+
+                  // Check if the bracket content has been evaluated completely
+                  if (stOpt.size() && stOpt.top().GetCode()==cmBO)
+                  {
+                    // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check
+                    // if there is either a function or a sign pending
+                    // neither the opening nor the closing bracket will be pushed back to
+                    // the operator stack
+                    // Check if a function is standing in front of the opening bracket, 
+                    // if yes evaluate it afterwards check for infix operators
+                    assert(stArgCount.size());
+                    int iArgCount = stArgCount.pop();
+                    
+                    stOpt.pop(); // Take opening bracket from stack
+
+                    if (iArgCount>1 && ( stOpt.size()==0 || 
+                                        (stOpt.top().GetCode()!=cmFUNC && 
+                                         stOpt.top().GetCode()!=cmFUNC_BULK && 
+                                         stOpt.top().GetCode()!=cmFUNC_STR) ) )
+                      Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());
+                    
+                    // The opening bracket was popped from the stack now check if there
+                    // was a function before this bracket
+                    if (stOpt.size() && 
+                        stOpt.top().GetCode()!=cmOPRT_INFIX && 
+                        stOpt.top().GetCode()!=cmOPRT_BIN && 
+                        stOpt.top().GetFuncAddr()!=0)
+                    {
+                      ApplyFunc(stOpt, stVal, iArgCount);
+                    }
+                  }
+                } // if bracket content is evaluated
+                break;
+
+        //
+        // Next are the binary operator entries
+        //
+        //case cmAND:   // built in binary operators
+        //case cmOR:
+        //case cmXOR:
+        case cmIF:
+                m_nIfElseCounter++;
+                // fallthrough intentional (no break!)
+
+        case cmLAND:
+        case cmLOR:
+        case cmLT:
+        case cmGT:
+        case cmLE:
+        case cmGE:
+        case cmNEQ:
+        case cmEQ:
+        case cmADD:
+        case cmSUB:
+        case cmMUL:
+        case cmDIV:
+        case cmPOW:
+        case cmASSIGN:
+        case cmOPRT_BIN:
+
+                // A binary operator (user defined or built in) has been found. 
+                while ( stOpt.size() && 
+                        stOpt.top().GetCode() != cmBO &&
+                        stOpt.top().GetCode() != cmELSE &&
+                        stOpt.top().GetCode() != cmIF)
+                {
+                  int nPrec1 = GetOprtPrecedence(stOpt.top()),
+                      nPrec2 = GetOprtPrecedence(opt);
+
+                  if (stOpt.top().GetCode()==opt.GetCode())
+                  {
+
+                    // Deal with operator associativity
+                    EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt);
+                    if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || 
+                         (eOprtAsct==oaLEFT  && (nPrec1 <  nPrec2)) )
+                    {
+                      break;
+                    }
+                  }
+                  else if (nPrec1 < nPrec2)
+                  {
+                    // In case the operators are not equal the precedence decides alone...
+                    break;
+                  }
+                  
+                  if (stOpt.top().GetCode()==cmOPRT_INFIX)
+                    ApplyFunc(stOpt, stVal, 1);
+                  else
+                    ApplyBinOprt(stOpt, stVal);
+                } // while ( ... )
+
+                if (opt.GetCode()==cmIF)
+                  m_vRPN.AddIfElse(opt.GetCode());
+
+    			      // The operator can't be evaluated right now, push back to the operator stack
+                stOpt.push(opt);
+                break;
+
+        //
+        // Last section contains functions and operators implicitly mapped to functions
+        //
+        case cmBO:
+                stArgCount.push(1);
+                stOpt.push(opt);
+                break;
+
+        case cmOPRT_INFIX:
+        case cmFUNC:
+        case cmFUNC_BULK:
+        case cmFUNC_STR:  
+                stOpt.push(opt);
+                break;
+
+        case cmOPRT_POSTFIX:
+                stOpt.push(opt);
+                ApplyFunc(stOpt, stVal, 1);  // this is the postfix operator
+                break;
+
+        default:  Error(ecINTERNAL_ERROR, 3);
+      } // end of switch operator-token
+
+      opta = opt;
+
+      if ( opt.GetCode() == cmEND )
+      {
+        m_vRPN.Finalize();
+        break;
+      }
+
+      if (ParserBase::g_DbgDumpStack)
+      {
+        StackDump(stVal, stOpt);
+        m_vRPN.AsciiDump();
+      }
+    } // while (true)
+
+    if (ParserBase::g_DbgDumpCmdCode)
+      m_vRPN.AsciiDump();
+
+    if (m_nIfElseCounter>0)
+      Error(ecMISSING_ELSE_CLAUSE);
+
+    // get the last value (= final result) from the stack
+    MUP_ASSERT(stArgCount.size()==1);
+    m_nFinalResultIdx = stArgCount.top();
+    if (m_nFinalResultIdx==0)
+      Error(ecINTERNAL_ERROR, 9);
+
+    if (stVal.size()==0)
+      Error(ecEMPTY_EXPRESSION);
+
+    if (stVal.top().GetType()!=tpDBL)
+      Error(ecSTR_RESULT);
+
+    m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief One of the two main parse functions.
+      \sa ParseCmdCode(...)
+
+    Parse expression from input string. Perform syntax checking and create 
+    bytecode. After parsing the string and creating the bytecode the function 
+    pointer #m_pParseFormula will be changed to the second parse routine the 
+    uses bytecode instead of string parsing.
+  */
+  value_type ParserBase::ParseString() const
+  {
+    try
+    {
+      CreateRPN();
+      m_pParseFormula = &ParserBase::ParseCmdCode;
+      return (this->*m_pParseFormula)(); 
+    }
+    catch(ParserError &exc)
+    {
+      exc.SetFormula(m_pTokenReader->GetExpr());
+      throw;
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Create an error containing the parse error position.
+
+    This function will create an Parser Exception object containing the error text and
+    its position.
+
+    \param a_iErrc [in] The error code of type #EErrorCodes.
+    \param a_iPos [in] The position where the error was detected.
+    \param a_strTok [in] The token string representation associated with the error.
+    \throw ParserException always throws thats the only purpose of this function.
+  */
+  void  ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const
+  {
+    throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Clear all user defined variables.
+      \throw nothrow
+
+      Resets the parser to string parsing mode by calling #ReInit.
+  */
+  void ParserBase::ClearVar()
+  {
+    m_VarDef.clear();
+    ReInit();
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Remove a variable from internal storage.
+      \throw nothrow
+
+      Removes a variable if it exists. If the Variable does not exist nothing will be done.
+  */
+  void ParserBase::RemoveVar(const string_type &a_strVarName)
+  {
+    varmap_type::iterator item = m_VarDef.find(a_strVarName);
+    if (item!=m_VarDef.end())
+    {
+      m_VarDef.erase(item);
+      ReInit();
+    }
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Clear all functions.
+      \post Resets the parser to string parsing mode.
+      \throw nothrow
+  */
+  void ParserBase::ClearFun()
+  {
+    m_FunDef.clear();
+    ReInit();
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Clear all user defined constants.
+
+      Both numeric and string constants will be removed from the internal storage.
+      \post Resets the parser to string parsing mode.
+      \throw nothrow
+  */
+  void ParserBase::ClearConst()
+  {
+    m_ConstDef.clear();
+    m_StrVarDef.clear();
+    ReInit();
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Clear all user defined postfix operators.
+      \post Resets the parser to string parsing mode.
+      \throw nothrow
+  */
+  void ParserBase::ClearPostfixOprt()
+  {
+    m_PostOprtDef.clear();
+    ReInit();
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Clear all user defined binary operators.
+      \post Resets the parser to string parsing mode.
+      \throw nothrow
+  */
+  void ParserBase::ClearOprt()
+  {
+    m_OprtDef.clear();
+    ReInit();
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Clear the user defined Prefix operators. 
+      \post Resets the parser to string parser mode.
+      \throw nothrow
+  */
+  void ParserBase::ClearInfixOprt()
+  {
+    m_InfixOprtDef.clear();
+    ReInit();
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Enable or disable the formula optimization feature. 
+      \post Resets the parser to string parser mode.
+      \throw nothrow
+  */
+  void ParserBase::EnableOptimizer(bool a_bIsOn)
+  {
+    m_vRPN.EnableOptimizer(a_bIsOn);
+    ReInit();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Enable the dumping of bytecode and stack content on the console. 
+      \param bDumpCmd Flag to enable dumping of the current bytecode to the console.
+      \param bDumpStack Flag to enable dumping of the stack content is written to the console.
+
+     This function is for debug purposes only!
+  */
+  void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack)
+  {
+    ParserBase::g_DbgDumpCmdCode = bDumpCmd;
+    ParserBase::g_DbgDumpStack   = bDumpStack;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Enable or disable the built in binary operators.
+      \throw nothrow
+      \sa m_bBuiltInOp, ReInit()
+
+    If you disable the built in binary operators there will be no binary operators
+    defined. Thus you must add them manually one by one. It is not possible to
+    disable built in operators selectively. This function will Reinitialize the
+    parser by calling ReInit().
+  */
+  void ParserBase::EnableBuiltInOprt(bool a_bIsOn)
+  {
+    m_bBuiltInOp = a_bIsOn;
+    ReInit();
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Query status of built in variables.
+      \return #m_bBuiltInOp; true if built in operators are enabled.
+      \throw nothrow
+  */
+  bool ParserBase::HasBuiltInOprt() const
+  {
+    return m_bBuiltInOp;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Get the argument separator character. 
+  */
+  char_type ParserBase::GetArgSep() const
+  {
+    return m_pTokenReader->GetArgSep();
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Set argument separator. 
+      \param cArgSep the argument separator character.
+  */
+  void ParserBase::SetArgSep(char_type cArgSep)
+  {
+    m_pTokenReader->SetArgSep(cArgSep);
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Dump stack content. 
+
+      This function is used for debugging only.
+  */
+  void ParserBase::StackDump(const ParserStack<token_type> &a_stVal, 
+                             const ParserStack<token_type> &a_stOprt) const
+  {
+    ParserStack<token_type> stOprt(a_stOprt), 
+                            stVal(a_stVal);
+
+    mu::console() << _T("\nValue stack:\n");
+    while ( !stVal.empty() ) 
+    {
+      token_type val = stVal.pop();
+      if (val.GetType()==tpSTR)
+        mu::console() << _T(" \"") << val.GetAsString() << _T("\" ");
+      else
+        mu::console() << _T(" ") << val.GetVal() << _T(" ");
+    }
+    mu::console() << "\nOperator stack:\n";
+
+    while ( !stOprt.empty() )
+    {
+      if (stOprt.top().GetCode()<=cmASSIGN) 
+      {
+        mu::console() << _T("OPRT_INTRNL \"")
+                      << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] 
+                      << _T("\" \n");
+      }
+      else
+      {
+        switch(stOprt.top().GetCode())
+        {
+        case cmVAR:   mu::console() << _T("VAR\n");  break;
+        case cmVAL:   mu::console() << _T("VAL\n");  break;
+        case cmFUNC:  mu::console() << _T("FUNC \"") 
+                                    << stOprt.top().GetAsString() 
+                                    << _T("\"\n");   break;
+        case cmFUNC_BULK:  mu::console() << _T("FUNC_BULK \"") 
+                                         << stOprt.top().GetAsString() 
+                                         << _T("\"\n");   break;
+        case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"")
+                                         << stOprt.top().GetAsString() 
+                                         << _T("\"\n");      break;
+        case cmOPRT_BIN:   mu::console() << _T("OPRT_BIN \"") 
+                                         << stOprt.top().GetAsString() 
+                                         << _T("\"\n");           break;
+        case cmFUNC_STR: mu::console() << _T("FUNC_STR\n");       break;
+        case cmEND:      mu::console() << _T("END\n");            break;
+        case cmUNKNOWN:  mu::console() << _T("UNKNOWN\n");        break;
+        case cmBO:       mu::console() << _T("BRACKET \"(\"\n");  break;
+        case cmBC:       mu::console() << _T("BRACKET \")\"\n");  break;
+        case cmIF:       mu::console() << _T("IF\n");  break;
+        case cmELSE:     mu::console() << _T("ELSE\n");  break;
+        case cmENDIF:    mu::console() << _T("ENDIF\n");  break;
+        default:         mu::console() << stOprt.top().GetCode() << _T(" ");  break;
+        }
+      }	
+      stOprt.pop();
+    }
+
+    mu::console() << dec << endl;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Evaluate an expression containing comma separated subexpressions 
+      \param [out] nStackSize The total number of results available
+      \return Pointer to the array containing all expression results
+
+      This member function can be used to retrieve all results of an expression
+      made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)")
+  */
+  value_type* ParserBase::Eval(int &nStackSize) const
+  {
+    (this->*m_pParseFormula)(); 
+    nStackSize = m_nFinalResultIdx;
+
+    // (for historic reasons the stack starts at position 1)
+    return &m_vStackBuffer[1];
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return the number of results on the calculation stack. 
+  
+    If the expression contains comma separated subexpressions (i.e. "sin(y), x+y"). 
+    There may be more than one return value. This function returns the number of 
+    available results.
+  */
+  int ParserBase::GetNumResults() const
+  {
+    return m_nFinalResultIdx;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Calculate the result.
+
+    A note on const correctness: 
+    I consider it important that Calc is a const function.
+    Due to caching operations Calc changes only the state of internal variables with one exception
+    m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making
+    Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update. 
+
+    \pre A formula must be set.
+    \pre Variables must have been set (if needed)
+
+    \sa #m_pParseFormula
+    \return The evaluation result
+    \throw ParseException if no Formula is set or in case of any other error related to the formula.
+  */
+  value_type ParserBase::Eval() const
+  {
+    return (this->*m_pParseFormula)(); 
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserBase::Eval(value_type *results, int nBulkSize)
+  {
+/* <ibg 2014-09-24/> Commented because it is making a unit test impossible
+
+    // Parallelization does not make sense for fewer than 10000 computations 
+    // due to thread creation overhead. If the bulk size is below 2000
+    // computation is refused. 
+    if (nBulkSize<2000)
+    {
+      throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS);
+    }
+*/
+    CreateRPN();
+
+    int i = 0;
+
+#ifdef MUP_USE_OPENMP
+//#define DEBUG_OMP_STUFF
+    #ifdef DEBUG_OMP_STUFF
+    int *pThread = new int[nBulkSize];
+    int *pIdx = new int[nBulkSize];
+    #endif
+
+    int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
+	int nThreadID = 0, ct = 0;
+    omp_set_num_threads(nMaxThreads);
+
+    #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID)
+    for (i=0; i<nBulkSize; ++i)
+    {
+      nThreadID = omp_get_thread_num();
+      results[i] = ParseCmdCodeBulk(i, nThreadID);
+
+      #ifdef DEBUG_OMP_STUFF
+      #pragma omp critical
+      {
+        pThread[ct] = nThreadID;  
+        pIdx[ct] = i; 
+        ct++;
+      }
+      #endif
+    }
+
+#ifdef DEBUG_OMP_STUFF
+    FILE *pFile = fopen("bulk_dbg.txt", "w");
+    for (i=0; i<nBulkSize; ++i)
+    {
+      fprintf(pFile, "idx: %d  thread: %d \n", pIdx[i], pThread[i]);
+    }
+    
+    delete [] pIdx;
+    delete [] pThread;
+
+    fclose(pFile);
+#endif
+
+#else
+    for (i=0; i<nBulkSize; ++i)
+    {
+      results[i] = ParseCmdCodeBulk(i, 0);
+    }
+#endif
+
+  }
+} // namespace mu
diff --git a/source/ThirdParty/MuParser/src/muParserBytecode.cpp b/source/ThirdParty/MuParser/src/muParserBytecode.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3964998fdd27fa6a4484b3900b16e589298dfa54
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParserBytecode.cpp
@@ -0,0 +1,588 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#include "muParserBytecode.h"
+
+#include <algorithm>
+#include <cassert>
+#include <string>
+#include <stack>
+#include <vector>
+#include <iostream>
+
+#include "muParserDef.h"
+#include "muParserError.h"
+#include "muParserToken.h"
+#include "muParserStack.h"
+#include "muParserTemplateMagic.h"
+
+
+namespace mu
+{
+  //---------------------------------------------------------------------------
+  /** \brief Bytecode default constructor. */
+  ParserByteCode::ParserByteCode()
+    :m_iStackPos(0)
+    ,m_iMaxStackSize(0)
+    ,m_vRPN()
+    ,m_bEnableOptimizer(true)
+  {
+    m_vRPN.reserve(50);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Copy constructor. 
+    
+      Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
+  */
+  ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode)
+  {
+    Assign(a_ByteCode);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Assignment operator.
+    
+      Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
+  */
+  ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode)
+  {
+    Assign(a_ByteCode);
+    return *this;
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserByteCode::EnableOptimizer(bool bStat)
+  {
+    m_bEnableOptimizer = bStat;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Copy state of another object to this. 
+    
+      \throw nowthrow
+  */
+  void ParserByteCode::Assign(const ParserByteCode &a_ByteCode)
+  {
+    if (this==&a_ByteCode)    
+      return;
+
+    m_iStackPos = a_ByteCode.m_iStackPos;
+    m_vRPN = a_ByteCode.m_vRPN;
+    m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
+	m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a Variable pointer to bytecode. 
+      \param a_pVar Pointer to be added.
+      \throw nothrow
+  */
+  void ParserByteCode::AddVar(value_type *a_pVar)
+  {
+    ++m_iStackPos;
+    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+
+    // optimization does not apply
+    SToken tok;
+    tok.Cmd       = cmVAR;
+    tok.Val.ptr   = a_pVar;
+    tok.Val.data  = 1;
+    tok.Val.data2 = 0;
+    m_vRPN.push_back(tok);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a Variable pointer to bytecode. 
+
+      Value entries in byte code consist of:
+      <ul>
+        <li>value array position of the value</li>
+        <li>the operator code according to ParserToken::cmVAL</li>
+        <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>
+      </ul>
+
+      \param a_pVal Value to be added.
+      \throw nothrow
+  */
+  void ParserByteCode::AddVal(value_type a_fVal)
+  {
+    ++m_iStackPos;
+    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+
+    // If optimization does not apply
+    SToken tok;
+    tok.Cmd = cmVAL;
+    tok.Val.ptr   = NULL;
+    tok.Val.data  = 0;
+    tok.Val.data2 = a_fVal;
+    m_vRPN.push_back(tok);
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserByteCode::ConstantFolding(ECmdCode a_Oprt)
+  {
+    std::size_t sz = m_vRPN.size();
+    value_type &x = m_vRPN[sz-2].Val.data2,
+               &y = m_vRPN[sz-1].Val.data2;
+    switch (a_Oprt)
+    {
+    case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break;
+    case cmLOR:  x = (int)x || (int)y; m_vRPN.pop_back(); break;
+    case cmLT:   x = x < y;  m_vRPN.pop_back();  break;
+    case cmGT:   x = x > y;  m_vRPN.pop_back();  break;
+    case cmLE:   x = x <= y; m_vRPN.pop_back();  break;
+    case cmGE:   x = x >= y; m_vRPN.pop_back();  break;
+    case cmNEQ:  x = x != y; m_vRPN.pop_back();  break;
+    case cmEQ:   x = x == y; m_vRPN.pop_back();  break;
+    case cmADD:  x = x + y;  m_vRPN.pop_back();  break;
+    case cmSUB:  x = x - y;  m_vRPN.pop_back();  break;
+    case cmMUL:  x = x * y;  m_vRPN.pop_back();  break;
+    case cmDIV: 
+
+#if defined(MUP_MATH_EXCEPTIONS)
+        if (y==0)
+          throw ParserError(ecDIV_BY_ZERO, _T("0"));
+#endif
+
+        x = x / y;   
+        m_vRPN.pop_back();
+        break;
+
+    case cmPOW: x = MathImpl<value_type>::Pow(x, y); 
+                m_vRPN.pop_back();
+                break;
+
+    default:
+        break;
+    } // switch opcode
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add an operator identifier to bytecode. 
+    
+      Operator entries in byte code consist of:
+      <ul>
+        <li>value array position of the result</li>
+        <li>the operator code according to ParserToken::ECmdCode</li>
+      </ul>
+
+      \sa  ParserToken::ECmdCode
+  */
+  void ParserByteCode::AddOp(ECmdCode a_Oprt)
+  {
+    bool bOptimized = false;
+
+    if (m_bEnableOptimizer)
+    {
+      std::size_t sz = m_vRPN.size();
+
+      // Check for foldable constants like:
+      //   cmVAL cmVAL cmADD 
+      // where cmADD can stand fopr any binary operator applied to
+      // two constant values.
+      if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL)
+      {
+        ConstantFolding(a_Oprt);
+        bOptimized = true;
+      }
+      else
+      {
+        switch(a_Oprt)
+        {
+        case  cmPOW:
+              // Optimization for polynomials of low order
+              if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)
+              {
+                if (m_vRPN[sz-1].Val.data2==2)
+                  m_vRPN[sz-2].Cmd = cmVARPOW2;
+                else if (m_vRPN[sz-1].Val.data2==3)
+                  m_vRPN[sz-2].Cmd = cmVARPOW3;
+                else if (m_vRPN[sz-1].Val.data2==4)
+                  m_vRPN[sz-2].Cmd = cmVARPOW4;
+                else
+                  break;
+
+                m_vRPN.pop_back();
+                bOptimized = true;
+              }
+              break;
+
+        case  cmSUB:
+        case  cmADD:
+              // Simple optimization based on pattern recognition for a shitload of different
+              // bytecode combinations of addition/subtraction
+              if ( (m_vRPN[sz-1].Cmd == cmVAR    && m_vRPN[sz-2].Cmd == cmVAL)    ||
+                   (m_vRPN[sz-1].Cmd == cmVAL    && m_vRPN[sz-2].Cmd == cmVAR)    || 
+                   (m_vRPN[sz-1].Cmd == cmVAL    && m_vRPN[sz-2].Cmd == cmVARMUL) ||
+                   (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL)    ||
+                   (m_vRPN[sz-1].Cmd == cmVAR    && m_vRPN[sz-2].Cmd == cmVAR    && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
+                   (m_vRPN[sz-1].Cmd == cmVAR    && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
+                   (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR    && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
+                   (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) )
+              {
+                assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) ||
+                        (m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) || 
+                        (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) );
+
+                m_vRPN[sz-2].Cmd = cmVARMUL;
+                m_vRPN[sz-2].Val.ptr    = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));    // variable
+                m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2;  // offset
+                m_vRPN[sz-2].Val.data  += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data;   // multiplicand
+                m_vRPN.pop_back();
+                bOptimized = true;
+              } 
+              break;
+
+        case  cmMUL:
+              if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||
+                   (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) 
+              {
+                m_vRPN[sz-2].Cmd        = cmVARMUL;
+                m_vRPN[sz-2].Val.ptr    = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
+                m_vRPN[sz-2].Val.data   = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2;
+                m_vRPN[sz-2].Val.data2  = 0;
+                m_vRPN.pop_back();
+                bOptimized = true;
+              } 
+              else if ( (m_vRPN[sz-1].Cmd == cmVAL    && m_vRPN[sz-2].Cmd == cmVARMUL) ||
+                        (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) )
+              {
+                // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
+                m_vRPN[sz-2].Cmd     = cmVARMUL;
+                m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
+                if (m_vRPN[sz-1].Cmd == cmVAL)
+                {
+                  m_vRPN[sz-2].Val.data  *= m_vRPN[sz-1].Val.data2;
+                  m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2;
+                }
+                else
+                {
+                  m_vRPN[sz-2].Val.data  = m_vRPN[sz-1].Val.data  * m_vRPN[sz-2].Val.data2;
+                  m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2;
+                }
+                m_vRPN.pop_back();
+                bOptimized = true;
+              }
+              else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR &&
+                       m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr)
+              {
+                // Optimization: a*a -> a^2
+                m_vRPN[sz-2].Cmd = cmVARPOW2;
+                m_vRPN.pop_back();
+                bOptimized = true;
+              }
+              break;
+
+        case cmDIV:
+              if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0)
+              {
+                // Optimization: 4*a/2 -> 2*a
+                m_vRPN[sz-2].Val.data  /= m_vRPN[sz-1].Val.data2;
+                m_vRPN[sz-2].Val.data2 /= m_vRPN[sz-1].Val.data2;
+                m_vRPN.pop_back();
+                bOptimized = true;
+              }
+              break;
+              
+        } // switch a_Oprt
+      }
+    }
+
+    // If optimization can't be applied just write the value
+    if (!bOptimized)
+    {
+      --m_iStackPos;
+      SToken tok;
+      tok.Cmd = a_Oprt;
+      m_vRPN.push_back(tok);
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserByteCode::AddIfElse(ECmdCode a_Oprt)
+  {
+    SToken tok;
+    tok.Cmd = a_Oprt;
+    m_vRPN.push_back(tok);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add an assignment operator
+    
+      Operator entries in byte code consist of:
+      <ul>
+        <li>cmASSIGN code</li>
+        <li>the pointer of the destination variable</li>
+      </ul>
+
+      \sa  ParserToken::ECmdCode
+  */
+  void ParserByteCode::AddAssignOp(value_type *a_pVar)
+  {
+    --m_iStackPos;
+
+    SToken tok;
+    tok.Cmd = cmASSIGN;
+    tok.Oprt.ptr = a_pVar;
+    m_vRPN.push_back(tok);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add function to bytecode. 
+
+      \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
+      \param a_pFun Pointer to function callback.
+  */
+  void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc)
+  {
+    if (a_iArgc>=0)
+    {
+      m_iStackPos = m_iStackPos - a_iArgc + 1; 
+    }
+    else
+    {
+      // function with unlimited number of arguments
+      m_iStackPos = m_iStackPos + a_iArgc + 1; 
+    }
+    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+
+    SToken tok;
+    tok.Cmd = cmFUNC;
+    tok.Fun.argc = a_iArgc;
+    tok.Fun.ptr = a_pFun;
+    m_vRPN.push_back(tok);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add a bulk function to bytecode. 
+
+      \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
+      \param a_pFun Pointer to function callback.
+  */
+  void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
+  {
+    m_iStackPos = m_iStackPos - a_iArgc + 1; 
+    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+
+    SToken tok;
+    tok.Cmd = cmFUNC_BULK;
+    tok.Fun.argc = a_iArgc;
+    tok.Fun.ptr = a_pFun;
+    m_vRPN.push_back(tok);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add Strung function entry to the parser bytecode. 
+      \throw nothrow
+
+      A string function entry consists of the stack position of the return value,
+      followed by a cmSTRFUNC code, the function pointer and an index into the 
+      string buffer maintained by the parser.
+  */
+  void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
+  {
+    m_iStackPos = m_iStackPos - a_iArgc + 1;
+
+    SToken tok;
+    tok.Cmd = cmFUNC_STR;
+    tok.Fun.argc = a_iArgc;
+    tok.Fun.idx = a_iIdx;
+    tok.Fun.ptr = a_pFun;
+    m_vRPN.push_back(tok);
+
+    m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Add end marker to bytecode.
+      
+      \throw nothrow 
+  */
+  void ParserByteCode::Finalize()
+  {
+    SToken tok;
+    tok.Cmd = cmEND;
+    m_vRPN.push_back(tok);
+    rpn_type(m_vRPN).swap(m_vRPN);     // shrink bytecode vector to fit
+
+    // Determine the if-then-else jump offsets
+    ParserStack<int> stIf, stElse;
+    int idx;
+    for (int i=0; i<(int)m_vRPN.size(); ++i)
+    {
+      switch(m_vRPN[i].Cmd)
+      {
+      case cmIF:
+            stIf.push(i);
+            break;
+
+      case  cmELSE:
+            stElse.push(i);
+            idx = stIf.pop();
+            m_vRPN[idx].Oprt.offset = i - idx;
+            break;
+      
+      case cmENDIF:
+            idx = stElse.pop();
+            m_vRPN[idx].Oprt.offset = i - idx;
+            break;
+
+      default:
+            break;
+      }
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  const SToken* ParserByteCode::GetBase() const
+  {
+    if (m_vRPN.size()==0)
+      throw ParserError(ecINTERNAL_ERROR);
+    else
+      return &m_vRPN[0];
+  }
+
+  //---------------------------------------------------------------------------
+  std::size_t ParserByteCode::GetMaxStackSize() const
+  {
+    return m_iMaxStackSize+1;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Returns the number of entries in the bytecode. */
+  std::size_t ParserByteCode::GetSize() const
+  {
+    return m_vRPN.size();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Delete the bytecode. 
+  
+      \throw nothrow
+
+      The name of this function is a violation of my own coding guidelines
+      but this way it's more in line with the STL functions thus more 
+      intuitive.
+  */
+  void ParserByteCode::clear()
+  {
+    m_vRPN.clear();
+    m_iStackPos = 0;
+    m_iMaxStackSize = 0;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Dump bytecode (for debugging only!). */
+  void ParserByteCode::AsciiDump()
+  {
+    if (!m_vRPN.size()) 
+    {
+      mu::console() << _T("No bytecode available\n");
+      return;
+    }
+
+    mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n");
+    for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)
+    {
+      mu::console() << std::dec << i << _T(" : \t");
+      switch (m_vRPN[i].Cmd)
+      {
+      case cmVAL:   mu::console() << _T("VAL \t");
+                    mu::console() << _T("[") << m_vRPN[i].Val.data2 << _T("]\n");
+                    break;
+
+      case cmVAR:   mu::console() << _T("VAR \t");
+	                  mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); 
+                    break;
+
+      case cmVARPOW2: mu::console() << _T("VARPOW2 \t");
+	                    mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); 
+                      break;
+
+      case cmVARPOW3: mu::console() << _T("VARPOW3 \t");
+	                    mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); 
+                      break;
+
+      case cmVARPOW4: mu::console() << _T("VARPOW4 \t");
+	                    mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); 
+                      break;
+
+      case cmVARMUL:  mu::console() << _T("VARMUL \t");
+	                    mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]"); 
+                      mu::console() << _T(" * [") << m_vRPN[i].Val.data << _T("]");
+                      mu::console() << _T(" + [") << m_vRPN[i].Val.data2 << _T("]\n");
+                      break;
+
+      case cmFUNC:  mu::console() << _T("CALL\t");
+                    mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]"); 
+                    mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Fun.ptr << _T("]"); 
+                    mu::console() << _T("\n");
+                    break;
+
+      case cmFUNC_STR:
+                    mu::console() << _T("CALL STRFUNC\t");
+                    mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]");
+                    mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].Fun.idx << _T("]");
+                    mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Fun.ptr << _T("]\n"); 
+                    break;
+
+      case cmLT:    mu::console() << _T("LT\n");  break;
+      case cmGT:    mu::console() << _T("GT\n");  break;
+      case cmLE:    mu::console() << _T("LE\n");  break;
+      case cmGE:    mu::console() << _T("GE\n");  break;
+      case cmEQ:    mu::console() << _T("EQ\n");  break;
+      case cmNEQ:   mu::console() << _T("NEQ\n"); break;
+      case cmADD:   mu::console() << _T("ADD\n"); break;
+      case cmLAND:  mu::console() << _T("&&\n"); break;
+      case cmLOR:   mu::console() << _T("||\n"); break;
+      case cmSUB:   mu::console() << _T("SUB\n"); break;
+      case cmMUL:   mu::console() << _T("MUL\n"); break;
+      case cmDIV:   mu::console() << _T("DIV\n"); break;
+      case cmPOW:   mu::console() << _T("POW\n"); break;
+
+      case cmIF:    mu::console() << _T("IF\t");
+                    mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n");
+                    break;
+
+      case cmELSE:  mu::console() << _T("ELSE\t");
+                    mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n");
+                    break;
+
+      case cmENDIF: mu::console() << _T("ENDIF\n"); break;
+
+      case cmASSIGN: 
+                    mu::console() << _T("ASSIGN\t");
+                    mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Oprt.ptr << _T("]\n"); 
+                    break; 
+
+      default:      mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n"); 
+                    break;
+      } // switch cmdCode
+    } // while bytecode
+
+    mu::console() << _T("END") << std::endl;
+  }
+} // namespace mu
diff --git a/source/ThirdParty/MuParser/src/muParserCallback.cpp b/source/ThirdParty/MuParser/src/muParserCallback.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2044fe1c38a543bd3513b6fc24789754a9a45227
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParserCallback.cpp
@@ -0,0 +1,463 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2004-2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#include "muParserCallback.h"
+
+/** \file
+    \brief Implementation of the parser callback class.
+*/
+
+
+namespace mu
+{
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(0)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(1)
+    ,m_iPri(a_iPrec)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(a_iCode)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Constructor for constructing function callbacks taking two arguments. 
+      \throw nothrow
+  */
+  ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(2)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  /** \brief Constructor for constructing binary operator callbacks. 
+      \param a_pFun Pointer to a static function taking two arguments
+      \param a_bAllowOpti A flag indicating this function can be optimized
+      \param a_iPrec The operator precedence
+      \param a_eOprtAsct The operators associativity
+      \throw nothrow
+  */
+  ParserCallback::ParserCallback(fun_type2 a_pFun, 
+                                 bool a_bAllowOpti, 
+                                 int a_iPrec, 
+                                 EOprtAssociativity a_eOprtAsct)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(2)
+    ,m_iPri(a_iPrec)
+    ,m_eOprtAsct(a_eOprtAsct)
+    ,m_iCode(cmOPRT_BIN)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(3)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(4)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(5)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(6)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(7)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(8)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(9)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(10)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(0)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(1)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Constructor for constructing function callbacks taking two arguments. 
+      \throw nothrow
+  */
+  ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(2)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(3)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(4)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(5)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(6)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(7)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(8)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(9)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(10)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_BULK)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(-1)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC)
+    ,m_iType(tpDBL)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(0)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_STR)
+    ,m_iType(tpSTR)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(1)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_STR)
+    ,m_iType(tpSTR)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti)
+    :m_pFun((void*)a_pFun)
+    ,m_iArgc(2)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmFUNC_STR)
+    ,m_iType(tpSTR)
+    ,m_bAllowOpti(a_bAllowOpti)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Default constructor. 
+      \throw nothrow
+  */
+  ParserCallback::ParserCallback()
+    :m_pFun(0)
+    ,m_iArgc(0)
+    ,m_iPri(-1)
+    ,m_eOprtAsct(oaNONE)
+    ,m_iCode(cmUNKNOWN)
+    ,m_iType(tpVOID)
+    ,m_bAllowOpti(0)
+  {}
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Copy constructor. 
+      \throw nothrow
+  */
+  ParserCallback::ParserCallback(const ParserCallback &ref)
+  {
+    m_pFun       = ref.m_pFun;
+    m_iArgc      = ref.m_iArgc;
+    m_bAllowOpti = ref.m_bAllowOpti;
+    m_iCode      = ref.m_iCode;
+    m_iType      = ref.m_iType;
+    m_iPri       = ref.m_iPri;
+    m_eOprtAsct  = ref.m_eOprtAsct;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Clone this instance and return a pointer to the new instance. */
+  ParserCallback* ParserCallback::Clone() const
+  {
+    return new ParserCallback(*this);
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return tru if the function is conservative.
+
+      Conservative functions return always the same result for the same argument.
+      \throw nothrow
+  */
+  bool ParserCallback::IsOptimizable() const  
+  { 
+    return m_bAllowOpti; 
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Get the callback address for the parser function. 
+  
+      The type of the address is void. It needs to be recasted according to the
+      argument number to the right type.
+
+      \throw nothrow
+      \return #pFun
+  */
+  void* ParserCallback::GetAddr() const 
+  { 
+    return m_pFun;  
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return the callback code. */
+  ECmdCode  ParserCallback::GetCode() const 
+  { 
+    return m_iCode; 
+  }
+  
+  //---------------------------------------------------------------------------
+  ETypeCode ParserCallback::GetType() const 
+  { 
+    return m_iType; 
+  }
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Return the operator precedence. 
+      \throw nothrown
+
+     Only valid if the callback token is an operator token (binary or infix).
+  */
+  int ParserCallback::GetPri()  const 
+  { 
+    return m_iPri;  
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return the operators associativity. 
+      \throw nothrown
+
+     Only valid if the callback token is a binary operator token.
+  */
+  EOprtAssociativity ParserCallback::GetAssociativity() const
+  {
+    return m_eOprtAsct;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Returns the number of function Arguments. */
+  int ParserCallback::GetArgc() const 
+  { 
+    return m_iArgc; 
+  }
+} // namespace mu
diff --git a/source/ThirdParty/MuParser/src/muParserDLL.cpp b/source/ThirdParty/MuParser/src/muParserDLL.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..15c88003cb907ad54740145190a48c53776bbbac
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParserDLL.cpp
@@ -0,0 +1,1096 @@
+/*
+                 __________
+                 _____   __ __\______   \_____  _______  ______  ____ _______
+                 /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+                 |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+                 |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|
+                 \/                       \/            \/      \/
+                 Copyright (C) 2004-2011 Ingo Berg
+
+                 Permission is hereby granted, free of charge, to any person obtaining a copy of this
+                 software and associated documentation files (the "Software"), to deal in the Software
+                 without restriction, including without limitation the rights to use, copy, modify,
+                 merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+                 permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+                 The above copyright notice and this permission notice shall be included in all copies or
+                 substantial portions of the Software.
+
+                 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+                 NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+                 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+                 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+                 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+                 */
+#if defined(MUPARSER_DLL) 
+
+#if defined(_WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "muParserDLL.h"
+#include "muParser.h"
+#include "muParserInt.h"
+#include "muParserError.h"
+
+
+#define MU_TRY  \
+    try     \
+        {
+
+#define MU_CATCH                                                 \
+        }                                                        \
+        catch (muError_t &e)                                      \
+        {                                                        \
+        ParserTag *pTag = static_cast<ParserTag*>(a_hParser);  \
+        pTag->exc = e;                                         \
+        pTag->bError = true;                                   \
+if (pTag->errHandler)                                  \
+    (pTag->errHandler)(a_hParser);                       \
+        }                                                        \
+        catch (...)                                               \
+        {                                                        \
+        ParserTag *pTag = static_cast<ParserTag*>(a_hParser);  \
+        pTag->exc = muError_t(mu::ecINTERNAL_ERROR);           \
+        pTag->bError = true;                                   \
+if (pTag->errHandler)                                  \
+    (pTag->errHandler)(a_hParser);                       \
+        }
+
+/** \file
+    \brief This file contains the implementation of the DLL interface of muparser.
+    */
+
+//---------------------------------------------------------------------------
+// private types
+typedef mu::ParserBase::exception_type muError_t;
+typedef mu::ParserBase muParser_t;
+
+int g_nBulkSize;
+
+//---------------------------------------------------------------------------
+class ParserTag
+{
+public:
+    ParserTag(int nType)
+        :pParser((nType == muBASETYPE_FLOAT) ? (mu::ParserBase*)new mu::Parser() :
+        (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : NULL)
+        , exc()
+        , errHandler(NULL)
+        , bError(false)
+        , m_nParserType(nType)
+    {}
+
+    ~ParserTag()
+    {
+        delete pParser;
+    }
+
+    mu::ParserBase *pParser;
+    mu::ParserBase::exception_type exc;
+    muErrorHandler_t errHandler;
+    bool bError;
+
+private:
+    ParserTag(const ParserTag &ref);
+    ParserTag& operator=(const ParserTag &ref);
+
+    int m_nParserType;
+};
+
+static muChar_t s_tmpOutBuf[2048];
+
+//---------------------------------------------------------------------------
+//
+//
+//  unexported functions
+//
+//
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+muParser_t* AsParser(muParserHandle_t a_hParser)
+{
+    return static_cast<ParserTag*>(a_hParser)->pParser;
+}
+
+//---------------------------------------------------------------------------
+ParserTag* AsParserTag(muParserHandle_t a_hParser)
+{
+    return static_cast<ParserTag*>(a_hParser);
+}
+
+//---------------------------------------------------------------------------
+#if defined(_WIN32)
+#define _CRT_SECURE_NO_DEPRECATE
+
+BOOL APIENTRY DllMain(HANDLE /*hModule*/,
+    DWORD ul_reason_for_call,
+    LPVOID /*lpReserved*/)
+{
+    switch (ul_reason_for_call)
+    {
+    case  DLL_PROCESS_ATTACH:
+        break;
+
+    case  DLL_THREAD_ATTACH:
+    case  DLL_THREAD_DETACH:
+    case  DLL_PROCESS_DETACH:
+        break;
+    }
+
+    return TRUE;
+}
+
+#endif
+
+//---------------------------------------------------------------------------
+//
+//
+//  exported functions
+//
+//
+//---------------------------------------------------------------------------
+
+API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData)
+{
+    MU_TRY
+        muParser_t* p(AsParser(a_hParser));
+    p->SetVarFactory(a_pFactory, pUserData);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Create a new Parser instance and return its handle.
+*/
+API_EXPORT(muParserHandle_t) mupCreate(int nBaseType)
+{
+    switch (nBaseType)
+    {
+    case  muBASETYPE_FLOAT:   return (void*)(new ParserTag(muBASETYPE_FLOAT));
+    case  muBASETYPE_INT:     return (void*)(new ParserTag(muBASETYPE_INT));
+    default:                  return NULL;
+    }
+}
+
+//---------------------------------------------------------------------------
+/** \brief Release the parser instance related with a parser handle.
+*/
+API_EXPORT(void) mupRelease(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        ParserTag* p = static_cast<ParserTag*>(a_hParser);
+    delete p;
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+
+#ifndef _UNICODE
+    sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str());
+#else
+    wsprintf(s_tmpOutBuf, _T("%s"), p->GetVersion().c_str());
+#endif
+
+    return s_tmpOutBuf;
+    MU_CATCH
+
+        return _T("");
+}
+
+//---------------------------------------------------------------------------
+/** \brief Evaluate the expression.
+*/
+API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    return p->Eval();
+    MU_CATCH
+
+        return 0;
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum)
+{
+    MU_TRY
+        assert(nNum != NULL);
+
+    muParser_t* const p(AsParser(a_hParser));
+    return p->Eval(*nNum);
+    MU_CATCH
+
+        return 0;
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_res, int nSize)
+{
+    MU_TRY
+        muParser_t* p(AsParser(a_hParser));
+    p->Eval(a_res, nSize);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->SetExpr(a_szExpr);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->RemoveVar(a_szName);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Release all parser variables.
+    \param a_hParser Handle to the parser instance.
+    */
+API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->ClearVar();
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Release all parser variables.
+    \param a_hParser Handle to the parser instance.
+    */
+API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->ClearConst();
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Clear all user defined operators.
+    \param a_hParser Handle to the parser instance.
+    */
+API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->ClearOprt();
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->ClearFun();
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muFun0_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muFun1_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muFun2_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFun3_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFun4_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFun5_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFun6_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFun7_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFun8_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFun9_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFun10_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muBulkFun0_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muBulkFun1_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muBulkFun2_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muBulkFun3_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muBulkFun4_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muBulkFun5_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muBulkFun6_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muBulkFun7_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muBulkFun8_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muBulkFun9_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muBulkFun10_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muStrFun1_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muStrFun2_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muStrFun3_t a_pFun)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, false);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineMultFun(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muMultFun_t a_pFun,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muFun2_t a_pFun,
+    muInt_t a_nPrec,
+    muInt_t a_nOprtAsct,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineOprt(a_szName,
+        a_pFun,
+        a_nPrec,
+        (mu::EOprtAssociativity)a_nOprtAsct,
+        a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFloat_t *a_pVar)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineVar(a_szName, a_pVar);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFloat_t *a_pVar)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineVar(a_szName, a_pVar);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    muFloat_t a_fVal)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineConst(a_szName, a_fVal);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser,
+    const muChar_t *a_szName,
+    const muChar_t *a_szVal)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineStrConst(a_szName, a_szVal);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+
+    // C# explodes when pMsg is returned directly. For some reason it can't access
+    // the memory where the message lies directly.
+#ifndef _UNICODE
+    sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str());
+#else
+    wsprintf(s_tmpOutBuf, _T("%s"), p->GetExpr().c_str());
+#endif
+
+    return s_tmpOutBuf;
+
+    MU_CATCH
+
+        return _T("");
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muFun1_t a_pOprt,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineInfixOprt(muParserHandle_t a_hParser,
+    const muChar_t* a_szName,
+    muFun1_t a_pOprt,
+    muBool_t a_bAllowOpt)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0);
+    MU_CATCH
+}
+
+// Define character sets for identifiers
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser,
+    const muChar_t* a_szCharset)
+{
+    muParser_t* const p(AsParser(a_hParser));
+    p->DefineNameChars(a_szCharset);
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser,
+    const muChar_t* a_szCharset)
+{
+    muParser_t* const p(AsParser(a_hParser));
+    p->DefineOprtChars(a_szCharset);
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser,
+    const muChar_t *a_szCharset)
+{
+    muParser_t* const p(AsParser(a_hParser));
+    p->DefineInfixOprtChars(a_szCharset);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Get the number of variables defined in the parser.
+    \param a_hParser [in] Must be a valid parser handle.
+    \return The number of used variables.
+    \sa mupGetExprVar
+    */
+API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    const mu::varmap_type VarMap = p->GetVar();
+    return (int)VarMap.size();
+    MU_CATCH
+
+        return 0; // never reached
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return a variable that is used in an expression.
+    \param a_hParser [in] A valid parser handle.
+    \param a_iVar [in] The index of the variable to return.
+    \param a_szName [out] Pointer to the variable name.
+    \param a_pVar [out] Pointer to the variable.
+    \throw nothrow
+
+    Prior to calling this function call mupGetExprVarNum in order to get the
+    number of variables in the expression. If the parameter a_iVar is greater
+    than the number of variables both a_szName and a_pVar will be set to zero.
+    As a side effect this function will trigger an internal calculation of the
+    expression undefined variables will be set to zero during this calculation.
+    During the calculation user defined callback functions present in the expression
+    will be called, this is unavoidable.
+    */
+API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser,
+    unsigned a_iVar,
+    const muChar_t **a_szName,
+    muFloat_t **a_pVar)
+{
+    // A static buffer is needed for the name since i cant return the
+    // pointer from the map.
+    static muChar_t  szName[1024];
+
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    const mu::varmap_type VarMap = p->GetVar();
+
+    if (a_iVar >= VarMap.size())
+    {
+        *a_szName = 0;
+        *a_pVar = 0;
+        return;
+    }
+    mu::varmap_type::const_iterator item;
+
+    item = VarMap.begin();
+    for (unsigned i = 0; i < a_iVar; ++i)
+        ++item;
+
+#ifndef _UNICODE
+    strncpy(szName, item->first.c_str(), sizeof(szName));
+#else
+    wcsncpy(szName, item->first.c_str(), sizeof(szName));
+#endif
+
+    szName[sizeof(szName)-1] = 0;
+
+    *a_szName = &szName[0];
+    *a_pVar = item->second;
+    return;
+
+    MU_CATCH
+
+        *a_szName = 0;
+    *a_pVar = 0;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Get the number of variables used in the expression currently set in the parser.
+    \param a_hParser [in] Must be a valid parser handle.
+    \return The number of used variables.
+    \sa mupGetExprVar
+    */
+API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    const mu::varmap_type VarMap = p->GetUsedVar();
+    return (int)VarMap.size();
+    MU_CATCH
+
+        return 0; // never reached
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return a variable that is used in an expression.
+
+    Prior to calling this function call mupGetExprVarNum in order to get the
+    number of variables in the expression. If the parameter a_iVar is greater
+    than the number of variables both a_szName and a_pVar will be set to zero.
+    As a side effect this function will trigger an internal calculation of the
+    expression undefined variables will be set to zero during this calculation.
+    During the calculation user defined callback functions present in the expression
+    will be called, this is unavoidable.
+
+    \param a_hParser [in] A valid parser handle.
+    \param a_iVar [in] The index of the variable to return.
+    \param a_szName [out] Pointer to the variable name.
+    \param a_pVar [out] Pointer to the variable.
+    \throw nothrow
+    */
+API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser,
+    unsigned a_iVar,
+    const muChar_t **a_szName,
+    muFloat_t **a_pVar)
+{
+    // A static buffer is needed for the name since i cant return the
+    // pointer from the map.
+    static muChar_t  szName[1024];
+
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    const mu::varmap_type VarMap = p->GetUsedVar();
+
+    if (a_iVar >= VarMap.size())
+    {
+        *a_szName = 0;
+        *a_pVar = 0;
+        return;
+    }
+    mu::varmap_type::const_iterator item;
+
+    item = VarMap.begin();
+    for (unsigned i = 0; i < a_iVar; ++i)
+        ++item;
+
+#ifndef _UNICODE
+    strncpy(szName, item->first.c_str(), sizeof(szName));
+#else
+    wcsncpy(szName, item->first.c_str(), sizeof(szName));
+#endif
+
+    szName[sizeof(szName)-1] = 0;
+
+    *a_szName = &szName[0];
+    *a_pVar = item->second;
+    return;
+
+    MU_CATCH
+
+        *a_szName = 0;
+    *a_pVar = 0;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the number of constants defined in a parser. */
+API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    const mu::valmap_type ValMap = p->GetConst();
+    return (int)ValMap.size();
+    MU_CATCH
+
+        return 0; // never reached
+}
+
+//-----------------------------------------------------------------------------------------------------
+API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->SetArgSep(cArgSep);
+    MU_CATCH
+}
+
+//-----------------------------------------------------------------------------------------------------
+API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->ResetLocale();
+    MU_CATCH
+}
+
+//-----------------------------------------------------------------------------------------------------
+API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->SetDecSep(cDecSep);
+    MU_CATCH
+}
+
+//-----------------------------------------------------------------------------------------------------
+API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep)
+{
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    p->SetThousandsSep(cThousandsSep);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Retrieve name and value of a single parser constant.
+    \param a_hParser [in] a valid parser handle
+    \param a_iVar [in] Index of the constant to query
+    \param a_pszName [out] pointer to a null terminated string with the constant name
+    \param [out] The constant value
+    */
+API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser,
+    unsigned a_iVar,
+    const muChar_t **a_pszName,
+    muFloat_t *a_fVal)
+{
+    // A static buffer is needed for the name since i cant return the
+    // pointer from the map.
+    static muChar_t szName[1024];
+
+    MU_TRY
+        muParser_t* const p(AsParser(a_hParser));
+    const mu::valmap_type ValMap = p->GetConst();
+
+    if (a_iVar >= ValMap.size())
+    {
+        *a_pszName = 0;
+        *a_fVal = 0;
+        return;
+    }
+
+    mu::valmap_type::const_iterator item;
+    item = ValMap.begin();
+    for (unsigned i = 0; i < a_iVar; ++i)
+        ++item;
+
+#ifndef _UNICODE
+    strncpy(szName, item->first.c_str(), sizeof(szName));
+#else
+    wcsncpy(szName, item->first.c_str(), sizeof(szName));
+#endif
+
+    szName[sizeof(szName)-1] = 0;
+
+    *a_pszName = &szName[0];
+    *a_fVal = item->second;
+    return;
+
+    MU_CATCH
+
+        *a_pszName = 0;
+    *a_fVal = 0;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Add a custom value recognition function.
+*/
+API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser,
+    muIdentFun_t a_pFun)
+{
+    MU_TRY
+        muParser_t* p(AsParser(a_hParser));
+    p->AddValIdent(a_pFun);
+    MU_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Query if an error occurred.
+
+    After querying the internal error bit will be reset. So a consecutive call
+    will return false.
+    */
+API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser)
+{
+    bool bError(AsParserTag(a_hParser)->bError);
+    AsParserTag(a_hParser)->bError = false;
+    return bError;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Reset the internal error flag.
+*/
+API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser)
+{
+    AsParserTag(a_hParser)->bError = false;
+}
+
+//---------------------------------------------------------------------------
+API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler)
+{
+    AsParserTag(a_hParser)->errHandler = a_pHandler;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the message associated with the last error.
+*/
+API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser)
+{
+    ParserTag* const p(AsParserTag(a_hParser));
+    const muChar_t *pMsg = p->exc.GetMsg().c_str();
+
+    // C# explodes when pMsg is returned directly. For some reason it can't access
+    // the memory where the message lies directly.
+#ifndef _UNICODE
+    sprintf(s_tmpOutBuf, "%s", pMsg);
+#else
+    wsprintf(s_tmpOutBuf, _T("%s"), pMsg);
+#endif
+
+    return s_tmpOutBuf;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the message associated with the last error.
+*/
+API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser)
+{
+    ParserTag* const p(AsParserTag(a_hParser));
+    const muChar_t *pToken = p->exc.GetToken().c_str();
+
+    // C# explodes when pMsg is returned directly. For some reason it can't access
+    // the memory where the message lies directly.
+#ifndef _UNICODE
+    sprintf(s_tmpOutBuf, "%s", pToken);
+#else
+    wsprintf(s_tmpOutBuf, _T("%s"), pToken);
+#endif
+
+    return s_tmpOutBuf;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the code associated with the last error.
+*/
+API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser)
+{
+    return AsParserTag(a_hParser)->exc.GetCode();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the position associated with the last error. */
+API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser)
+{
+    return (int)AsParserTag(a_hParser)->exc.GetPos();
+}
+
+////-----------------------------------------------------------------------------------------------------
+//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser)
+//{
+//  return AsParserTag(a_hParser)->exc.GetExpr().c_str();
+//}
+
+//-----------------------------------------------------------------------------------------------------
+API_EXPORT(muFloat_t*) mupCreateVar()
+{
+    return new muFloat_t(0);
+}
+
+//-----------------------------------------------------------------------------------------------------
+API_EXPORT(void) mupReleaseVar(muFloat_t *ptr)
+{
+    delete ptr;
+}
+
+#endif      // MUPARSER_DLL
diff --git a/source/ThirdParty/MuParser/src/muParserError.cpp b/source/ThirdParty/MuParser/src/muParserError.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6fe4e1d2cca91e2cd8bcc8a25677f52317f72fe4
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParserError.cpp
@@ -0,0 +1,337 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+#include "muParserError.h"
+
+
+namespace mu
+{
+  const ParserErrorMsg ParserErrorMsg::m_Instance;
+
+  //------------------------------------------------------------------------------
+  const ParserErrorMsg& ParserErrorMsg::Instance()
+  {
+    return m_Instance;
+  }
+
+  //------------------------------------------------------------------------------
+  string_type ParserErrorMsg::operator[](unsigned a_iIdx) const
+  {
+    return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();
+  }
+
+  //---------------------------------------------------------------------------
+  ParserErrorMsg::~ParserErrorMsg()
+  {}
+
+  //---------------------------------------------------------------------------
+  /** \brief Assignement operator is deactivated.
+  */
+  ParserErrorMsg& ParserErrorMsg::operator=(const ParserErrorMsg& )
+  {
+    assert(false);
+    return *this;
+  }
+
+  //---------------------------------------------------------------------------
+  ParserErrorMsg::ParserErrorMsg(const ParserErrorMsg&)
+  {}
+
+  //---------------------------------------------------------------------------
+  ParserErrorMsg::ParserErrorMsg()
+    :m_vErrMsg(0)
+  {
+    m_vErrMsg.resize(ecCOUNT);
+
+    m_vErrMsg[ecUNASSIGNABLE_TOKEN]     = _T("Unexpected token \"$TOK$\" found at position $POS$.");
+    m_vErrMsg[ecINTERNAL_ERROR]         = _T("Internal error");
+    m_vErrMsg[ecINVALID_NAME]           = _T("Invalid function-, variable- or constant name: \"$TOK$\".");
+    m_vErrMsg[ecINVALID_BINOP_IDENT]    = _T("Invalid binary operator identifier: \"$TOK$\".");
+    m_vErrMsg[ecINVALID_INFIX_IDENT]    = _T("Invalid infix operator identifier: \"$TOK$\".");
+    m_vErrMsg[ecINVALID_POSTFIX_IDENT]  = _T("Invalid postfix operator identifier: \"$TOK$\".");
+    m_vErrMsg[ecINVALID_FUN_PTR]        = _T("Invalid pointer to callback function.");
+    m_vErrMsg[ecEMPTY_EXPRESSION]       = _T("Expression is empty.");
+    m_vErrMsg[ecINVALID_VAR_PTR]        = _T("Invalid pointer to variable.");
+    m_vErrMsg[ecUNEXPECTED_OPERATOR]    = _T("Unexpected operator \"$TOK$\" found at position $POS$");
+    m_vErrMsg[ecUNEXPECTED_EOF]         = _T("Unexpected end of expression at position $POS$");
+    m_vErrMsg[ecUNEXPECTED_ARG_SEP]     = _T("Unexpected argument separator at position $POS$");
+    m_vErrMsg[ecUNEXPECTED_PARENS]      = _T("Unexpected parenthesis \"$TOK$\" at position $POS$");
+    m_vErrMsg[ecUNEXPECTED_FUN]         = _T("Unexpected function \"$TOK$\" at position $POS$");
+    m_vErrMsg[ecUNEXPECTED_VAL]         = _T("Unexpected value \"$TOK$\" found at position $POS$");
+    m_vErrMsg[ecUNEXPECTED_VAR]         = _T("Unexpected variable \"$TOK$\" found at position $POS$");
+    m_vErrMsg[ecUNEXPECTED_ARG]         = _T("Function arguments used without a function (position: $POS$)");
+    m_vErrMsg[ecMISSING_PARENS]         = _T("Missing parenthesis");
+    m_vErrMsg[ecTOO_MANY_PARAMS]        = _T("Too many parameters for function \"$TOK$\" at expression position $POS$");
+    m_vErrMsg[ecTOO_FEW_PARAMS]         = _T("Too few parameters for function \"$TOK$\" at expression position $POS$");
+    m_vErrMsg[ecDIV_BY_ZERO]            = _T("Divide by zero");
+    m_vErrMsg[ecDOMAIN_ERROR]           = _T("Domain error");
+    m_vErrMsg[ecNAME_CONFLICT]          = _T("Name conflict");
+    m_vErrMsg[ecOPT_PRI]                = _T("Invalid value for operator priority (must be greater or equal to zero).");
+    m_vErrMsg[ecBUILTIN_OVERLOAD]       = _T("user defined binary operator \"$TOK$\" conflicts with a built in operator.");
+    m_vErrMsg[ecUNEXPECTED_STR]         = _T("Unexpected string token found at position $POS$.");
+    m_vErrMsg[ecUNTERMINATED_STRING]    = _T("Unterminated string starting at position $POS$.");
+    m_vErrMsg[ecSTRING_EXPECTED]        = _T("String function called with a non string type of argument.");
+    m_vErrMsg[ecVAL_EXPECTED]           = _T("String value used where a numerical argument is expected.");
+    m_vErrMsg[ecOPRT_TYPE_CONFLICT]     = _T("No suitable overload for operator \"$TOK$\" at position $POS$.");
+    m_vErrMsg[ecSTR_RESULT]             = _T("Function result is a string.");
+    m_vErrMsg[ecGENERIC]                = _T("Parser error.");
+    m_vErrMsg[ecLOCALE]                 = _T("Decimal separator is identic to function argument separator.");
+    m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$TOK$\" operator must be preceeded by a closing bracket.");
+    m_vErrMsg[ecMISSING_ELSE_CLAUSE]    = _T("If-then-else operator is missing an else clause");
+    m_vErrMsg[ecMISPLACED_COLON]        = _T("Misplaced colon at position $POS$");
+    m_vErrMsg[ecUNREASONABLE_NUMBER_OF_COMPUTATIONS] = _T("Number of computations to small for bulk mode. (Vectorisation overhead too costly)");
+    
+    #if defined(_DEBUG)
+      for (int i=0; i<ecCOUNT; ++i)
+        if (!m_vErrMsg[i].length())
+          assert(false);
+    #endif
+  }
+
+  //---------------------------------------------------------------------------
+  //
+  //  ParserError class
+  //
+  //---------------------------------------------------------------------------
+
+  /** \brief Default constructor. */
+  ParserError::ParserError()
+    :m_strMsg()
+    ,m_strFormula()
+    ,m_strTok()
+    ,m_iPos(-1)
+    ,m_iErrc(ecUNDEFINED)
+    ,m_ErrMsg(ParserErrorMsg::Instance())
+  {
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief This Constructor is used for internal exceptions only. 
+      
+    It does not contain any information but the error code.
+  */
+  ParserError::ParserError(EErrorCodes a_iErrc) 
+    :m_strMsg()
+    ,m_strFormula()
+    ,m_strTok()
+    ,m_iPos(-1)
+    ,m_iErrc(a_iErrc)
+    ,m_ErrMsg(ParserErrorMsg::Instance())
+  {
+    m_strMsg = m_ErrMsg[m_iErrc];
+    stringstream_type stream;
+    stream << (int)m_iPos;
+    ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+    ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Construct an error from a message text. */
+  ParserError::ParserError(const string_type &sMsg) 
+    :m_ErrMsg(ParserErrorMsg::Instance())
+  {
+    Reset();
+    m_strMsg = sMsg;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Construct an error object. 
+      \param [in] a_iErrc the error code.
+      \param [in] sTok The token string related to this error.
+      \param [in] sExpr The expression related to the error.
+      \param [in] a_iPos the position in the expression where the error occurred. 
+  */
+  ParserError::ParserError( EErrorCodes iErrc,
+                            const string_type &sTok,
+                            const string_type &sExpr,
+                            int iPos )
+    :m_strMsg()
+    ,m_strFormula(sExpr)
+    ,m_strTok(sTok)
+    ,m_iPos(iPos)
+    ,m_iErrc(iErrc)
+    ,m_ErrMsg(ParserErrorMsg::Instance())
+  {
+    m_strMsg = m_ErrMsg[m_iErrc];
+    stringstream_type stream;
+    stream << (int)m_iPos;
+    ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+    ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Construct an error object. 
+      \param [in] iErrc the error code.
+      \param [in] iPos the position in the expression where the error occurred. 
+      \param [in] sTok The token string related to this error.
+  */
+  ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) 
+    :m_strMsg()
+    ,m_strFormula()
+    ,m_strTok(sTok)
+    ,m_iPos(iPos)
+    ,m_iErrc(iErrc)
+    ,m_ErrMsg(ParserErrorMsg::Instance())
+  {
+    m_strMsg = m_ErrMsg[m_iErrc];
+    stringstream_type stream;
+    stream << (int)m_iPos;
+    ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+    ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Construct an error object. 
+      \param [in] szMsg The error message text.
+      \param [in] iPos the position related to the error.
+      \param [in] sTok The token string related to this error.
+  */
+  ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sTok) 
+    :m_strMsg(szMsg)
+    ,m_strFormula()
+    ,m_strTok(sTok)
+    ,m_iPos(iPos)
+    ,m_iErrc(ecGENERIC)
+    ,m_ErrMsg(ParserErrorMsg::Instance())
+  {
+    stringstream_type stream;
+    stream << (int)m_iPos;
+    ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+    ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Copy constructor. */
+  ParserError::ParserError(const ParserError &a_Obj)
+    :m_strMsg(a_Obj.m_strMsg)
+    ,m_strFormula(a_Obj.m_strFormula)
+    ,m_strTok(a_Obj.m_strTok)
+    ,m_iPos(a_Obj.m_iPos)
+    ,m_iErrc(a_Obj.m_iErrc)
+    ,m_ErrMsg(ParserErrorMsg::Instance())
+  {
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Assignment operator. */
+  ParserError& ParserError::operator=(const ParserError &a_Obj)
+  {
+    if (this==&a_Obj)
+      return *this;
+
+    m_strMsg = a_Obj.m_strMsg;
+    m_strFormula = a_Obj.m_strFormula;
+    m_strTok = a_Obj.m_strTok;
+    m_iPos = a_Obj.m_iPos;
+    m_iErrc = a_Obj.m_iErrc;
+    return *this;
+  }
+
+  //------------------------------------------------------------------------------
+  ParserError::~ParserError()
+  {}
+
+  //------------------------------------------------------------------------------
+  /** \brief Replace all occurrences of a substring with another string. 
+      \param strFind The string that shall be replaced.
+      \param strReplaceWith The string that should be inserted instead of strFind
+  */
+  void ParserError::ReplaceSubString( string_type &strSource,
+                                      const string_type &strFind,
+                                      const string_type &strReplaceWith)
+  {
+    string_type strResult;
+    string_type::size_type iPos(0), iNext(0);
+
+    for(;;)
+    {
+      iNext = strSource.find(strFind, iPos);
+      strResult.append(strSource, iPos, iNext-iPos);
+
+      if( iNext==string_type::npos )
+        break;
+
+      strResult.append(strReplaceWith);
+      iPos = iNext + strFind.length();
+    } 
+
+    strSource.swap(strResult);
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Reset the erro object. */
+  void ParserError::Reset()
+  {
+    m_strMsg = _T("");
+    m_strFormula = _T("");
+    m_strTok = _T("");
+    m_iPos = -1;
+    m_iErrc = ecUNDEFINED;
+  }
+      
+  //------------------------------------------------------------------------------
+  /** \brief Set the expression related to this error. */
+  void ParserError::SetFormula(const string_type &a_strFormula)
+  {
+    m_strFormula = a_strFormula;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief gets the expression related tp this error.*/
+  const string_type& ParserError::GetExpr() const 
+  {
+    return m_strFormula;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Returns the message string for this error. */
+  const string_type& ParserError::GetMsg() const
+  {
+    return m_strMsg;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Return the formula position related to the error. 
+
+    If the error is not related to a distinct position this will return -1
+  */
+  int ParserError::GetPos() const
+  {
+    return m_iPos;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Return string related with this token (if available). */
+  const string_type& ParserError::GetToken() const
+  {
+    return m_strTok;
+  }
+
+  //------------------------------------------------------------------------------
+  /** \brief Return the error code. */
+  EErrorCodes ParserError::GetCode() const
+  {
+    return m_iErrc;
+  }
+} // namespace mu
diff --git a/source/ThirdParty/MuParser/src/muParserInt.cpp b/source/ThirdParty/MuParser/src/muParserInt.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8b5aae60346f3e87a3d539282fe1944c0d80f184
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParserInt.cpp
@@ -0,0 +1,280 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2011 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#include "muParserInt.h"
+
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+using namespace std;
+
+/** \file
+    \brief Implementation of a parser using integer value.
+*/
+
+/** \brief Namespace for mathematical applications. */
+namespace mu
+{
+value_type ParserInt::Abs(value_type v)  { return (value_type)Round(fabs((double)v)); }
+value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; }
+value_type ParserInt::Ite(value_type v1, 
+                          value_type v2, 
+                          value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); }
+value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1)  + Round(v2); }
+value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1)  - Round(v2); }
+value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1)  * Round(v2); }
+value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1)  / Round(v2); }
+value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1)  % Round(v2); }
+value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }
+value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }
+value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }
+value_type ParserInt::LogOr(value_type v1, value_type v2)  { return Round(v1) | Round(v2); }
+value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }
+value_type ParserInt::Or(value_type v1, value_type v2)  { return Round(v1) || Round(v2); }
+value_type ParserInt::Less(value_type v1, value_type v2)      { return Round(v1)  < Round(v2); }
+value_type ParserInt::Greater(value_type v1, value_type v2)   { return Round(v1)  > Round(v2); }
+value_type ParserInt::LessEq(value_type v1, value_type v2)    { return Round(v1) <= Round(v2); }
+value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }
+value_type ParserInt::Equal(value_type v1, value_type v2)     { return Round(v1) == Round(v2); }
+value_type ParserInt::NotEqual(value_type v1, value_type v2)  { return Round(v1) != Round(v2); }
+value_type ParserInt::Not(value_type v) { return !Round(v); }
+
+value_type ParserInt::Pow(value_type v1, value_type v2) 
+{ 
+  return std::pow((double)Round(v1), (double)Round(v2)); 
+}
+
+//---------------------------------------------------------------------------
+// Unary operator Callbacks: Infix operators
+value_type ParserInt::UnaryMinus(value_type v) 
+{ 
+  return -Round(v); 
+}
+
+//---------------------------------------------------------------------------
+value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)
+{ 
+  if (!a_iArgc)	
+    throw ParserError(_T("too few arguments for function sum."));
+
+  value_type fRes=0;
+  for (int i=0; i<a_iArgc; ++i) 
+    fRes += a_afArg[i];
+
+  return fRes;
+}
+
+//---------------------------------------------------------------------------
+value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)
+{ 
+  if (!a_iArgc)	
+    throw ParserError( _T("too few arguments for function min.") );
+
+  value_type fRes=a_afArg[0];
+  for (int i=0; i<a_iArgc; ++i) 
+    fRes = std::min(fRes, a_afArg[i]);
+
+  return fRes;
+}
+
+//---------------------------------------------------------------------------
+value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)
+{ 
+  if (!a_iArgc)	
+    throw ParserError(_T("too few arguments for function min."));
+
+  value_type fRes=a_afArg[0];
+  for (int i=0; i<a_iArgc; ++i) 
+    fRes = std::max(fRes, a_afArg[i]);
+
+  return fRes;
+}
+
+//---------------------------------------------------------------------------
+// Default value recognition callback
+int ParserInt::IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
+{
+  string_type buf(a_szExpr);
+  std::size_t pos = buf.find_first_not_of(_T("0123456789"));
+
+  if (pos==std::string::npos)
+    return 0;
+
+  stringstream_type stream( buf.substr(0, pos ) );
+  int iVal(0);
+
+  stream >> iVal;
+  if (stream.fail())
+    return 0;
+      
+  stringstream_type::pos_type iEnd = stream.tellg();   // Position after reading
+  if (stream.fail())
+    iEnd = stream.str().length();  
+
+  if (iEnd==(stringstream_type::pos_type)-1)
+    return 0;
+
+  *a_iPos += (int)iEnd;
+  *a_fVal = (value_type)iVal;
+  return 1;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Check a given position in the expression for the presence of 
+           a hex value. 
+    \param a_szExpr Pointer to the expression string
+    \param [in/out] a_iPos Pointer to an integer value holding the current parsing 
+           position in the expression.
+    \param [out] a_fVal Pointer to the position where the detected value shall be stored.
+
+  Hey values must be prefixed with "0x" in order to be detected properly.
+*/
+int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
+{
+  if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) 
+    return 0;
+
+  unsigned iVal(0);
+
+  // New code based on streams for UNICODE compliance:
+  stringstream_type::pos_type nPos(0);
+  stringstream_type ss(a_szExpr + 2);
+  ss >> std::hex >> iVal;
+  nPos = ss.tellg();
+
+  if (nPos==(stringstream_type::pos_type)0)
+    return 1;
+
+  *a_iPos += (int)(2 + nPos);
+  *a_fVal = (value_type)iVal;
+  return 1;
+}
+
+//---------------------------------------------------------------------------
+int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
+{
+  if (a_szExpr[0]!='#') 
+    return 0;
+
+  unsigned iVal(0), 
+           iBits(sizeof(iVal)*8),
+           i(0);
+
+  for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i<iBits; ++i)
+    iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);
+
+  if (i==0) 
+    return 0;
+
+  if (i==iBits)
+    throw exception_type(_T("Binary to integer conversion error (overflow)."));
+
+  *a_fVal = (unsigned)(iVal >> (iBits-i) );
+  *a_iPos += i+1;
+
+  return 1;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Constructor. 
+
+  Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
+*/
+ParserInt::ParserInt()
+  :ParserBase()
+{
+  AddValIdent(IsVal);    // lowest priority
+  AddValIdent(IsBinVal);
+  AddValIdent(IsHexVal); // highest priority
+
+  InitCharSets();
+  InitFun();
+  InitOprt();
+}
+
+//---------------------------------------------------------------------------
+void ParserInt::InitConst()
+{
+}
+
+//---------------------------------------------------------------------------
+void ParserInt::InitCharSets()
+{
+  DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );
+  DefineOprtChars( _T("+-*^/?<>=!%&|~'_") );
+  DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") );
+}
+
+//---------------------------------------------------------------------------
+/** \brief Initialize the default functions. */
+void ParserInt::InitFun()
+{
+  DefineFun( _T("sign"), Sign);
+  DefineFun( _T("abs"), Abs);
+  DefineFun( _T("if"), Ite);
+  DefineFun( _T("sum"), Sum);
+  DefineFun( _T("min"), Min);
+  DefineFun( _T("max"), Max);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Initialize operators. */
+void ParserInt::InitOprt()
+{
+  // disable all built in operators, not all of them useful for integer numbers
+  // (they don't do rounding of values)
+  EnableBuiltInOprt(false);
+
+  // Disable all built in operators, they wont work with integer numbers
+  // since they are designed for floating point numbers
+  DefineInfixOprt( _T("-"), UnaryMinus);
+  DefineInfixOprt( _T("!"), Not);
+
+  DefineOprt( _T("&"), LogAnd, prLOGIC);
+  DefineOprt( _T("|"), LogOr, prLOGIC);
+  DefineOprt( _T("&&"), And, prLOGIC);
+  DefineOprt( _T("||"), Or, prLOGIC);
+
+  DefineOprt( _T("<"), Less, prCMP);
+  DefineOprt( _T(">"), Greater, prCMP);
+  DefineOprt( _T("<="), LessEq, prCMP);
+  DefineOprt( _T(">="), GreaterEq, prCMP);
+  DefineOprt( _T("=="), Equal, prCMP);
+  DefineOprt( _T("!="), NotEqual, prCMP);
+
+  DefineOprt( _T("+"), Add, prADD_SUB);
+  DefineOprt( _T("-"), Sub, prADD_SUB);
+
+  DefineOprt( _T("*"), Mul, prMUL_DIV);
+  DefineOprt( _T("/"), Div, prMUL_DIV);
+  DefineOprt( _T("%"), Mod, prMUL_DIV);
+
+  DefineOprt( _T("^"), Pow, prPOW, oaRIGHT);
+  DefineOprt( _T(">>"), Shr, prMUL_DIV+1);
+  DefineOprt( _T("<<"), Shl, prMUL_DIV+1);
+}
+
+} // namespace mu
diff --git a/source/ThirdParty/MuParser/src/muParserTest.cpp b/source/ThirdParty/MuParser/src/muParserTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4006b27c716b14342b5f3ebee61fb9c4c14aa29f
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParserTest.cpp
@@ -0,0 +1,1552 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+
+#include "muParserTest.h"
+
+#include <cstdio>
+#include <cmath>
+#include <iostream>
+#include <limits>
+
+#define PARSER_CONST_PI  3.141592653589793238462643
+#define PARSER_CONST_E   2.718281828459045235360287
+
+using namespace std;
+
+/** \file
+    \brief This file contains the implementation of parser test cases.
+*/
+
+namespace mu
+{
+  namespace Test
+  {
+    int ParserTester::c_iCount = 0;
+
+    //---------------------------------------------------------------------------------------------
+    ParserTester::ParserTester()
+      :m_vTestFun()
+    {
+      AddTest(&ParserTester::TestNames);
+      AddTest(&ParserTester::TestSyntax);
+      AddTest(&ParserTester::TestPostFix);
+      AddTest(&ParserTester::TestInfixOprt);
+      AddTest(&ParserTester::TestVarConst);
+      AddTest(&ParserTester::TestMultiArg);
+      AddTest(&ParserTester::TestExpression);
+      AddTest(&ParserTester::TestIfThenElse);
+      AddTest(&ParserTester::TestInterface);
+      AddTest(&ParserTester::TestBinOprt);
+      AddTest(&ParserTester::TestException);
+      AddTest(&ParserTester::TestStrArg);
+      AddTest(&ParserTester::TestBulkMode);
+
+      ParserTester::c_iCount = 0;
+    }
+
+    //---------------------------------------------------------------------------------------------
+    int ParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
+    {
+      if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) 
+        return 0;
+
+      unsigned iVal(0);
+
+      // New code based on streams for UNICODE compliance:
+      stringstream_type::pos_type nPos(0);
+      stringstream_type ss(a_szExpr + 2);
+      ss >> std::hex >> iVal;
+      nPos = ss.tellg();
+
+      if (nPos==(stringstream_type::pos_type)0)
+        return 1;
+
+      *a_iPos += (int)(2 + nPos);
+      *a_fVal = (value_type)iVal;
+      return 1;
+    }
+
+    //---------------------------------------------------------------------------------------------
+    int ParserTester::TestInterface()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing member functions...");
+   
+      // Test RemoveVar
+      value_type afVal[3] = {1,2,3};
+      Parser p;
+  
+      try
+      {
+        p.DefineVar( _T("a"), &afVal[0]);
+        p.DefineVar( _T("b"), &afVal[1]);
+        p.DefineVar( _T("c"), &afVal[2]);
+        p.SetExpr( _T("a+b+c") );
+        p.Eval();
+      }
+      catch(...)
+      {
+        iStat += 1;  // this is not supposed to happen 
+      }
+
+      try
+      {
+        p.RemoveVar( _T("c") );
+        p.Eval();
+        iStat += 1;  // not supposed to reach this, nonexisting variable "c" deleted...
+      }
+      catch(...)
+      {
+        // failure is expected...
+      }
+
+      if (iStat==0) 
+        mu::console() << _T("passed") << endl;
+      else 
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+    //---------------------------------------------------------------------------------------------
+    int ParserTester::TestStrArg()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing string arguments...");
+ 
+      iStat += EqnTest(_T("valueof(\"\")"), 123, true);   // empty string arguments caused a crash
+      iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\")  "), 246, true);
+      iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true);
+      // use in expressions with variables
+      iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true);
+      iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true);
+      // string + numeric arguments
+      iStat += EqnTest(_T("strfun1(\"100\")"), 100, true);
+      iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true);
+      iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true);
+      // string constants
+      iStat += EqnTest(_T("atof(str1)+atof(str2)"), 3.33, true);
+
+      if (iStat==0)
+        mu::console() << _T("passed") << endl;
+      else 
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+    //---------------------------------------------------------------------------------------------
+    int ParserTester::TestBulkMode()
+    {
+        int iStat = 0;
+        mu::console() << _T("testing bulkmode...");
+
+#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \
+        { \
+          double res[] = { R1, R2, R3, R4 }; \
+          iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \
+        }
+
+        // Bulk Variables for the test:
+        // a: 1,2,3,4
+        // b: 2,2,2,2
+        // c: 3,3,3,3
+        // d: 5,4,3,2
+        EQN_TEST_BULK("a",   1, 1, 1, 1, false)
+        EQN_TEST_BULK("a",   1, 2, 3, 4, true)
+        EQN_TEST_BULK("b=a", 1, 2, 3, 4, true)
+        EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true)
+        EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true)
+        EQN_TEST_BULK("a+b", 3, 4, 5, 6, true)
+        EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true)
+#undef EQN_TEST_BULK
+
+        if (iStat == 0)
+            mu::console() << _T("passed") << endl;
+        else
+            mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+        return iStat;
+    }
+
+    //---------------------------------------------------------------------------------------------
+    int ParserTester::TestBinOprt()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing binary operators...");
+   
+      // built in operators
+      // xor operator
+
+      iStat += EqnTest(_T("a++b"), 3, true);
+      iStat += EqnTest(_T("a ++ b"), 3, true);
+      iStat += EqnTest(_T("1++2"), 3, true);
+      iStat += EqnTest(_T("1 ++ 2"), 3, true);
+      iStat += EqnTest(_T("a add b"), 3, true);
+      iStat += EqnTest(_T("1 add 2"), 3, true);
+      iStat += EqnTest(_T("a<b"), 1, true);
+      iStat += EqnTest(_T("b>a"), 1, true);
+      iStat += EqnTest(_T("a>a"), 0, true);
+      iStat += EqnTest(_T("a<a"), 0, true);
+      iStat += EqnTest(_T("a>a"), 0, true);
+      iStat += EqnTest(_T("a<=a"), 1, true);
+      iStat += EqnTest(_T("a<=b"), 1, true);
+      iStat += EqnTest(_T("b<=a"), 0, true);
+      iStat += EqnTest(_T("a>=a"), 1, true);
+      iStat += EqnTest(_T("b>=a"), 1, true);
+      iStat += EqnTest(_T("a>=b"), 0, true);
+
+      // Test logical operators, especially if user defined "&" and the internal "&&" collide
+      iStat += EqnTest(_T("1 && 1"), 1, true); 
+      iStat += EqnTest(_T("1 && 0"), 0, true); 
+      iStat += EqnTest(_T("(a<b) && (b>a)"), 1, true); 
+      iStat += EqnTest(_T("(a<b) && (a>b)"), 0, true); 
+      //iStat += EqnTest(_T("12 and 255"), 12, true); 
+      //iStat += EqnTest(_T("12 and 0"), 0, true); 
+      iStat += EqnTest(_T("12 & 255"), 12, true); 
+      iStat += EqnTest(_T("12 & 0"), 0, true); 
+      iStat += EqnTest(_T("12&255"), 12, true); 
+      iStat += EqnTest(_T("12&0"), 0, true); 
+
+      // Assignment operator
+      iStat += EqnTest(_T("a = b"), 2, true); 
+      iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); 
+      iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true);
+      iStat += EqnTest(_T("(a=b)*2"), 4, true);
+      iStat += EqnTest(_T("2*(a=b)"), 4, true);
+      iStat += EqnTest(_T("2*(a=b+1)"), 6, true);
+      iStat += EqnTest(_T("(a=b+1)*2"), 6, true);
+      iStat += EqnTest(_T("a=c, a*10"), 30, true);
+
+      iStat += EqnTest(_T("2^2^3"), 256, true); 
+      iStat += EqnTest(_T("1/2/3"), 1.0/6.0, true); 
+
+      // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3
+      iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); 
+
+      // Test user defined binary operators
+      iStat += EqnTestInt(_T("1 | 2"), 3, true);          
+      iStat += EqnTestInt(_T("1 || 2"), 1, true);          
+      iStat += EqnTestInt(_T("123 & 456"), 72, true);          
+      iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true);
+      iStat += EqnTestInt(_T("1 && 0"), 0, true);          
+      iStat += EqnTestInt(_T("123 && 456"), 1, true);          
+      iStat += EqnTestInt(_T("1 << 3"), 8, true);          
+      iStat += EqnTestInt(_T("8 >> 3"), 1, true);          
+      iStat += EqnTestInt(_T("9 / 4"), 2, true);  
+      iStat += EqnTestInt(_T("9 % 4"), 1, true);  
+      iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true);
+      iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true);
+      iStat += EqnTestInt(_T("-10+1"), -9, true);
+      iStat += EqnTestInt(_T("1+2*3"), 7, true);
+      iStat += EqnTestInt(_T("const1 != const2"), 1, true);
+      iStat += EqnTestInt(_T("const1 != const2"), 0, false);
+      iStat += EqnTestInt(_T("const1 == const2"), 0, true);
+      iStat += EqnTestInt(_T("const1 == 1"), 1, true);
+      iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true);
+      iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true);
+      iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false);
+      iStat += EqnTestInt(_T("const1 < const2"), 1, true);
+      iStat += EqnTestInt(_T("const2 > const1"), 1, true);
+      iStat += EqnTestInt(_T("const1 <= 1"), 1, true);
+      iStat += EqnTestInt(_T("const2 >= 2"), 1, true);
+      iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true);
+      iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true);
+      iStat += EqnTestInt(_T("a != b"), 1, true);
+      iStat += EqnTestInt(_T("a != b"), 0, false);
+      iStat += EqnTestInt(_T("a == b"), 0, true);
+      iStat += EqnTestInt(_T("a == 1"), 1, true);
+      iStat += EqnTestInt(_T("10*(a == 1)"), 10, true);
+      iStat += EqnTestInt(_T("2*(a | b)"), 6, true);
+      iStat += EqnTestInt(_T("2*(a | b)"), 7, false);
+      iStat += EqnTestInt(_T("a < b"), 1, true);
+      iStat += EqnTestInt(_T("b > a"), 1, true);
+      iStat += EqnTestInt(_T("a <= 1"), 1, true);
+      iStat += EqnTestInt(_T("b >= 2"), 1, true);
+      iStat += EqnTestInt(_T("2*(a + b)"), 6, true);
+      iStat += EqnTestInt(_T("2*(a - b)"), -2, true);
+      iStat += EqnTestInt(_T("a + (a << b)"), 5, true);
+      iStat += EqnTestInt(_T("-2^2"), -4, true);
+      iStat += EqnTestInt(_T("3--a"), 4, true);
+      iStat += EqnTestInt(_T("3+-3^2"), -6, true);
+
+      // Test reading of hex values:
+      iStat += EqnTestInt(_T("0xff"), 255, true);
+      iStat += EqnTestInt(_T("10+0xff"), 265, true);
+      iStat += EqnTestInt(_T("0xff+10"), 265, true);
+      iStat += EqnTestInt(_T("10*0xff"), 2550, true);
+      iStat += EqnTestInt(_T("0xff*10"), 2550, true);
+      iStat += EqnTestInt(_T("10+0xff+1"), 266, true);
+      iStat += EqnTestInt(_T("1+0xff+10"), 266, true);
+
+// incorrect: '^' is yor here, not power
+//    iStat += EqnTestInt("-(1+2)^2", -9, true);
+//    iStat += EqnTestInt("-1^3", -1, true);          
+
+      // Test precedence
+      // a=1, b=2, c=3
+      iStat += EqnTestInt(_T("a + b * c"), 7, true);
+      iStat += EqnTestInt(_T("a * b + c"), 5, true);
+      iStat += EqnTestInt(_T("a<b && b>10"), 0, true);
+      iStat += EqnTestInt(_T("a<b && b<10"), 1, true);
+
+      iStat += EqnTestInt(_T("a + b << c"), 17, true);
+      iStat += EqnTestInt(_T("a << b + c"), 7, true);
+      iStat += EqnTestInt(_T("c * b < a"), 0, true);
+      iStat += EqnTestInt(_T("c * b == 6 * a"), 1, true);
+      iStat += EqnTestInt(_T("2^2^3"), 256, true); 
+
+
+      if (iStat==0)
+        mu::console() << _T("passed") << endl;
+      else 
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+    //---------------------------------------------------------------------------------------------
+    /** \brief Check muParser name restriction enforcement. */
+    int ParserTester::TestNames()
+    {
+      int  iStat= 0,
+           iErr = 0;
+
+      mu::console() << "testing name restriction enforcement...";
+    
+      Parser p;
+
+  #define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \
+      iErr = 0;                                      \
+      ParserTester::c_iCount++;                      \
+      try                                            \
+      {                                              \
+        p.Define##DOMAIN(EXPR, ARG);                 \
+      }                                              \
+      catch(Parser::exception_type&)                 \
+      {                                              \
+        iErr = (FAIL==false) ? 0 : 1;                \
+      }                                              \
+      iStat += iErr;      
+      
+      // constant names
+      PARSER_THROWCHECK(Const, false, _T("0a"), 1)
+      PARSER_THROWCHECK(Const, false, _T("9a"), 1)
+      PARSER_THROWCHECK(Const, false, _T("+a"), 1)
+      PARSER_THROWCHECK(Const, false, _T("-a"), 1)
+      PARSER_THROWCHECK(Const, false, _T("a-"), 1)
+      PARSER_THROWCHECK(Const, false, _T("a*"), 1)
+      PARSER_THROWCHECK(Const, false, _T("a?"), 1)
+      PARSER_THROWCHECK(Const, true, _T("a"), 1)
+      PARSER_THROWCHECK(Const, true, _T("a_min"), 1)
+      PARSER_THROWCHECK(Const, true, _T("a_min0"), 1)
+      PARSER_THROWCHECK(Const, true, _T("a_min9"), 1)
+      // variable names
+      value_type a;
+      p.ClearConst();
+      PARSER_THROWCHECK(Var, false, _T("123abc"), &a)
+      PARSER_THROWCHECK(Var, false, _T("9a"), &a)
+      PARSER_THROWCHECK(Var, false, _T("0a"), &a)
+      PARSER_THROWCHECK(Var, false, _T("+a"), &a)
+      PARSER_THROWCHECK(Var, false, _T("-a"), &a)
+      PARSER_THROWCHECK(Var, false, _T("?a"), &a)
+      PARSER_THROWCHECK(Var, false, _T("!a"), &a)
+      PARSER_THROWCHECK(Var, false, _T("a+"), &a)
+      PARSER_THROWCHECK(Var, false, _T("a-"), &a)
+      PARSER_THROWCHECK(Var, false, _T("a*"), &a)
+      PARSER_THROWCHECK(Var, false, _T("a?"), &a)
+      PARSER_THROWCHECK(Var, true, _T("a"), &a)
+      PARSER_THROWCHECK(Var, true, _T("a_min"), &a)
+      PARSER_THROWCHECK(Var, true, _T("a_min0"), &a)
+      PARSER_THROWCHECK(Var, true, _T("a_min9"), &a)
+      PARSER_THROWCHECK(Var, false, _T("a_min9"), 0)
+      // Postfix operators
+      // fail
+      PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1)
+      PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1)
+      PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0)
+      // pass
+      PARSER_THROWCHECK(PostfixOprt, true, _T("-a"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("?a"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("_"),   f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("#"),   f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("&&"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("||"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("&"),   f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("|"),   f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("++"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("--"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("?>"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("?<"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("**"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("or"),  f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1)
+      PARSER_THROWCHECK(PostfixOprt, true, _T("!"),   f1of1)
+      // Binary operator
+      // The following must fail with builtin operators activated
+      // p.EnableBuiltInOp(true); -> this is the default
+      p.ClearPostfixOprt();
+      PARSER_THROWCHECK(Oprt, false, _T("+"),  f1of2)
+      PARSER_THROWCHECK(Oprt, false, _T("-"),  f1of2)
+      PARSER_THROWCHECK(Oprt, false, _T("*"),  f1of2)
+      PARSER_THROWCHECK(Oprt, false, _T("/"),  f1of2)
+      PARSER_THROWCHECK(Oprt, false, _T("^"),  f1of2)
+      PARSER_THROWCHECK(Oprt, false, _T("&&"),  f1of2)
+      PARSER_THROWCHECK(Oprt, false, _T("||"),  f1of2)
+      // without activated built in operators it should work
+      p.EnableBuiltInOprt(false);
+      PARSER_THROWCHECK(Oprt, true, _T("+"),  f1of2)
+      PARSER_THROWCHECK(Oprt, true, _T("-"),  f1of2)
+      PARSER_THROWCHECK(Oprt, true, _T("*"),  f1of2)
+      PARSER_THROWCHECK(Oprt, true, _T("/"),  f1of2)
+      PARSER_THROWCHECK(Oprt, true, _T("^"),  f1of2)
+      PARSER_THROWCHECK(Oprt, true, _T("&&"),  f1of2)
+      PARSER_THROWCHECK(Oprt, true, _T("||"),  f1of2)
+  #undef PARSER_THROWCHECK
+
+      if (iStat==0) 
+        mu::console() << _T("passed") << endl;
+      else 
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+    //---------------------------------------------------------------------------
+    int ParserTester::TestSyntax()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing syntax engine...");
+
+      iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF);  // incomplete hex definition
+      iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF);  // incomplete hex definition
+      iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF);  // incomplete hex definition
+      iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF);  // incomplete hex definition
+      iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF);  // incomplete hex definition
+
+      iStat += EqnTest(_T("(1+ 2*a)"), 3, true);   // Spaces within formula
+      iStat += EqnTest(_T("sqrt((4))"), 2, true);  // Multiple brackets
+      iStat += EqnTest(_T("sqrt((2)+2)"), 2, true);// Multiple brackets
+      iStat += EqnTest(_T("sqrt(2+(2))"), 2, true);// Multiple brackets
+      iStat += EqnTest(_T("sqrt(a+(3))"), 2, true);// Multiple brackets
+      iStat += EqnTest(_T("sqrt((3)+a)"), 2, true);// Multiple brackets
+      iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or"
+      iStat += EqnTest(_T("(2+"), 0, false);       // missing closing bracket 
+      iStat += EqnTest(_T("2++4"), 0, false);      // unexpected operator
+      iStat += EqnTest(_T("2+-4"), 0, false);      // unexpected operator
+      iStat += EqnTest(_T("(2+)"), 0, false);      // unexpected closing bracket
+      iStat += EqnTest(_T("--2"), 0, false);       // double sign
+      iStat += EqnTest(_T("ksdfj"), 0, false);     // unknown token
+      iStat += EqnTest(_T("()"), 0, false);        // empty bracket without a function
+      iStat += EqnTest(_T("5+()"), 0, false);      // empty bracket without a function
+      iStat += EqnTest(_T("sin(cos)"), 0, false);  // unexpected function
+      iStat += EqnTest(_T("5t6"), 0, false);       // unknown token
+      iStat += EqnTest(_T("5 t 6"), 0, false);     // unknown token
+      iStat += EqnTest(_T("8*"), 0, false);        // unexpected end of formula
+      iStat += EqnTest(_T(",3"), 0, false);        // unexpected comma
+      iStat += EqnTest(_T("3,5"), 0, false);       // unexpected comma
+      iStat += EqnTest(_T("sin(8,8)"), 0, false);  // too many function args
+      iStat += EqnTest(_T("(7,8)"), 0, false);     // too many function args
+      iStat += EqnTest(_T("sin)"), 0, false);      // unexpected closing bracket
+      iStat += EqnTest(_T("a)"), 0, false);        // unexpected closing bracket
+      iStat += EqnTest(_T("pi)"), 0, false);       // unexpected closing bracket
+      iStat += EqnTest(_T("sin(())"), 0, false);   // unexpected closing bracket
+      iStat += EqnTest(_T("sin()"), 0, false);     // unexpected closing bracket
+
+      if (iStat==0)
+        mu::console() << _T("passed") << endl;
+      else 
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+    //---------------------------------------------------------------------------
+    int ParserTester::TestVarConst()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing variable/constant detection...");
+
+      // Test if the result changes when a variable changes
+      iStat += EqnTestWithVarChange( _T("a"), 1, 1, 2, 2 );
+      iStat += EqnTestWithVarChange( _T("2*a"), 2, 4, 3, 6 );
+
+      // distinguish constants with same basename
+      iStat += EqnTest( _T("const"), 1, true);
+      iStat += EqnTest( _T("const1"), 2, true);
+      iStat += EqnTest( _T("const2"), 3, true);
+      iStat += EqnTest( _T("2*const"), 2, true);
+      iStat += EqnTest( _T("2*const1"), 4, true);
+      iStat += EqnTest( _T("2*const2"), 6, true);
+      iStat += EqnTest( _T("2*const+1"), 3, true);
+      iStat += EqnTest( _T("2*const1+1"), 5, true);
+      iStat += EqnTest( _T("2*const2+1"), 7, true);
+      iStat += EqnTest( _T("const"), 0, false);
+      iStat += EqnTest( _T("const1"), 0, false);
+      iStat += EqnTest( _T("const2"), 0, false);
+
+      // distinguish variables with same basename
+      iStat += EqnTest( _T("a"), 1, true);
+      iStat += EqnTest( _T("aa"), 2, true);
+      iStat += EqnTest( _T("2*a"), 2, true);
+      iStat += EqnTest( _T("2*aa"), 4, true);
+      iStat += EqnTest( _T("2*a-1"), 1, true);
+      iStat += EqnTest( _T("2*aa-1"), 3, true);
+
+      // custom value recognition
+      iStat += EqnTest( _T("0xff"), 255, true);
+      iStat += EqnTest( _T("0x97 + 0xff"), 406, true);
+
+      // Finally test querying of used variables
+      try
+      {
+        int idx;
+        mu::Parser p;
+        mu::value_type vVarVal[] = { 1, 2, 3, 4, 5};
+        p.DefineVar( _T("a"), &vVarVal[0]);
+        p.DefineVar( _T("b"), &vVarVal[1]);
+        p.DefineVar( _T("c"), &vVarVal[2]);
+        p.DefineVar( _T("d"), &vVarVal[3]);
+        p.DefineVar( _T("e"), &vVarVal[4]);
+
+        // Test lookup of defined variables
+        // 4 used variables
+        p.SetExpr( _T("a+b+c+d") );
+        mu::varmap_type UsedVar = p.GetUsedVar();
+        int iCount = (int)UsedVar.size();
+        if (iCount!=4) 
+          throw false;
+        
+        // the next check will fail if the parser 
+        // erroneously creates new variables internally
+        if (p.GetVar().size()!=5)
+          throw false;
+
+        mu::varmap_type::const_iterator item = UsedVar.begin();
+        for (idx=0; item!=UsedVar.end(); ++item)
+        {
+          if (&vVarVal[idx++]!=item->second) 
+            throw false;
+        }
+
+        // Test lookup of undefined variables
+        p.SetExpr( _T("undef1+undef2+undef3") );
+        UsedVar = p.GetUsedVar();
+        iCount = (int)UsedVar.size();
+        if (iCount!=3) 
+          throw false;
+
+        // the next check will fail if the parser 
+        // erroneously creates new variables internally
+        if (p.GetVar().size()!=5)
+          throw false;
+
+        for (item = UsedVar.begin(); item!=UsedVar.end(); ++item)
+        {
+          if (item->second!=0) 
+            throw false; // all pointers to undefined variables must be null
+        }
+
+        // 1 used variables
+        p.SetExpr( _T("a+b") );
+        UsedVar = p.GetUsedVar();
+        iCount = (int)UsedVar.size();
+        if (iCount!=2) throw false;
+        item = UsedVar.begin();
+        for (idx=0; item!=UsedVar.end(); ++item)
+          if (&vVarVal[idx++]!=item->second) throw false;
+
+      }
+      catch(...)
+      {
+        iStat += 1;
+      }
+
+      if (iStat==0)  
+        mu::console() << _T("passed") << endl;
+      else
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+    //---------------------------------------------------------------------------
+    int ParserTester::TestMultiArg()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing multiarg functions...");
+    
+      // Compound expressions
+      iStat += EqnTest( _T("1,2,3"), 3, true);
+      iStat += EqnTest( _T("a,b,c"), 3, true);
+      iStat += EqnTest( _T("a=10,b=20,c=a*b"), 200, true);
+      iStat += EqnTest( _T("1,\n2,\n3"), 3, true);
+      iStat += EqnTest( _T("a,\nb,\nc"), 3, true);
+      iStat += EqnTest( _T("a=10,\nb=20,\nc=a*b"), 200, true);
+      iStat += EqnTest( _T("1,\r\n2,\r\n3"), 3, true);
+      iStat += EqnTest( _T("a,\r\nb,\r\nc"), 3, true);
+      iStat += EqnTest( _T("a=10,\r\nb=20,\r\nc=a*b"), 200, true);
+
+      // picking the right argument
+      iStat += EqnTest( _T("f1of1(1)"), 1, true);
+      iStat += EqnTest( _T("f1of2(1, 2)"), 1, true);
+      iStat += EqnTest( _T("f2of2(1, 2)"), 2, true);
+      iStat += EqnTest( _T("f1of3(1, 2, 3)"), 1, true);
+      iStat += EqnTest( _T("f2of3(1, 2, 3)"), 2, true);
+      iStat += EqnTest( _T("f3of3(1, 2, 3)"), 3, true);
+      iStat += EqnTest( _T("f1of4(1, 2, 3, 4)"), 1, true);
+      iStat += EqnTest( _T("f2of4(1, 2, 3, 4)"), 2, true);
+      iStat += EqnTest( _T("f3of4(1, 2, 3, 4)"), 3, true);
+      iStat += EqnTest( _T("f4of4(1, 2, 3, 4)"), 4, true);
+      iStat += EqnTest( _T("f1of5(1, 2, 3, 4, 5)"), 1, true);
+      iStat += EqnTest( _T("f2of5(1, 2, 3, 4, 5)"), 2, true);
+      iStat += EqnTest( _T("f3of5(1, 2, 3, 4, 5)"), 3, true);
+      iStat += EqnTest( _T("f4of5(1, 2, 3, 4, 5)"), 4, true);
+      iStat += EqnTest( _T("f5of5(1, 2, 3, 4, 5)"), 5, true);
+      // Too few arguments / Too many arguments
+      iStat += EqnTest( _T("1+ping()"), 11, true);
+      iStat += EqnTest( _T("ping()+1"), 11, true);
+      iStat += EqnTest( _T("2*ping()"), 20, true);
+      iStat += EqnTest( _T("ping()*2"), 20, true);
+      iStat += EqnTest( _T("ping(1,2)"), 0, false);
+      iStat += EqnTest( _T("1+ping(1,2)"), 0, false);
+      iStat += EqnTest( _T("f1of1(1,2)"), 0, false);
+      iStat += EqnTest( _T("f1of1()"), 0, false);
+      iStat += EqnTest( _T("f1of2(1, 2, 3)"), 0, false);
+      iStat += EqnTest( _T("f1of2(1)"), 0, false);
+      iStat += EqnTest( _T("f1of3(1, 2, 3, 4)"), 0, false);
+      iStat += EqnTest( _T("f1of3(1)"), 0, false);
+      iStat += EqnTest( _T("f1of4(1, 2, 3, 4, 5)"), 0, false);
+      iStat += EqnTest( _T("f1of4(1)"), 0, false);
+      iStat += EqnTest( _T("(1,2,3)"), 0, false);
+      iStat += EqnTest( _T("1,2,3"), 0, false);
+      iStat += EqnTest( _T("(1*a,2,3)"), 0, false);
+      iStat += EqnTest( _T("1,2*a,3"), 0, false);
+     
+      // correct calculation of arguments
+      iStat += EqnTest( _T("min(a, 1)"),  1, true);
+      iStat += EqnTest( _T("min(3*2, 1)"),  1, true);
+      iStat += EqnTest( _T("min(3*2, 1)"),  6, false);
+      iStat += EqnTest( _T("firstArg(2,3,4)"), 2, true);
+      iStat += EqnTest( _T("lastArg(2,3,4)"), 4, true);
+      iStat += EqnTest( _T("min(3*a+1, 1)"),  1, true);
+      iStat += EqnTest( _T("max(3*a+1, 1)"),  4, true);
+      iStat += EqnTest( _T("max(3*a+1, 1)*2"),  8, true);
+      iStat += EqnTest( _T("2*max(3*a+1, 1)+2"),  10, true);
+
+      // functions with Variable argument count
+      iStat += EqnTest( _T("sum(a)"), 1, true);
+      iStat += EqnTest( _T("sum(1,2,3)"),  6, true);
+      iStat += EqnTest( _T("sum(a,b,c)"),  6, true);
+      iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"),  4, true);
+      iStat += EqnTest( _T("2*sum(1,2,3)"),  12, true);
+      iStat += EqnTest( _T("2*sum(1,2,3)+2"),  14, true);
+      iStat += EqnTest( _T("2*sum(-1,2,3)+2"),  10, true);
+      iStat += EqnTest( _T("2*sum(-1,2,-(-a))+2"),  6, true);
+      iStat += EqnTest( _T("2*sum(-1,10,-a)+2"),  18, true);
+      iStat += EqnTest( _T("2*sum(1,2,3)*2"),  24, true);
+      iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"),  4, true);
+      iStat += EqnTest( _T("sum(1*3, 4, a+2)"),  10, true);
+      iStat += EqnTest( _T("sum(1*3, 2*sum(1,2,2), a+2)"),  16, true);
+      iStat += EqnTest( _T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true);
+
+      // some failures
+      iStat += EqnTest( _T("sum()"),  0, false);
+      iStat += EqnTest( _T("sum(,)"),  0, false);
+      iStat += EqnTest( _T("sum(1,2,)"),  0, false);
+      iStat += EqnTest( _T("sum(,1,2)"),  0, false);
+
+      if (iStat==0) 
+        mu::console() << _T("passed") << endl;
+      else
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+  
+      return iStat;
+    }
+
+
+    //---------------------------------------------------------------------------
+    int ParserTester::TestInfixOprt()
+    {
+      int iStat(0);
+      mu::console() << "testing infix operators...";
+
+      iStat += EqnTest( _T("+1"),    +1, true);
+      iStat += EqnTest( _T("-(+1)"), -1, true);
+      iStat += EqnTest( _T("-(+1)*2"),  -2, true);
+      iStat += EqnTest( _T("-(+2)*sqrt(4)"),  -4, true);
+      iStat += EqnTest( _T("3-+a"), 2, true);
+      iStat += EqnTest( _T("+1*3"),  3, true);
+
+      iStat += EqnTest( _T("-1"),    -1, true);
+      iStat += EqnTest( _T("-(-1)"),  1, true);
+      iStat += EqnTest( _T("-(-1)*2"),  2, true);
+      iStat += EqnTest( _T("-(-2)*sqrt(4)"),  4, true);
+      iStat += EqnTest( _T("-_pi"), -PARSER_CONST_PI, true);
+      iStat += EqnTest( _T("-a"),  -1, true);
+      iStat += EqnTest( _T("-(a)"),  -1, true);
+      iStat += EqnTest( _T("-(-a)"),  1, true);
+      iStat += EqnTest( _T("-(-a)*2"),  2, true);
+      iStat += EqnTest( _T("-(8)"), -8, true);
+      iStat += EqnTest( _T("-8"), -8, true);
+      iStat += EqnTest( _T("-(2+1)"), -3, true);
+      iStat += EqnTest( _T("-(f1of1(1+2*3)+1*2)"), -9, true);
+      iStat += EqnTest( _T("-(-f1of1(1+2*3)+1*2)"), 5, true);
+      iStat += EqnTest( _T("-sin(8)"), -0.989358, true);
+      iStat += EqnTest( _T("3-(-a)"), 4, true);
+      iStat += EqnTest( _T("3--a"), 4, true);
+      iStat += EqnTest( _T("-1*3"),  -3, true);
+
+      // Postfix / infix priorities
+      iStat += EqnTest( _T("~2#"), 8, true);
+      iStat += EqnTest( _T("~f1of1(2)#"), 8, true);
+      iStat += EqnTest( _T("~(b)#"), 8, true);
+      iStat += EqnTest( _T("(~b)#"), 12, true);
+      iStat += EqnTest( _T("~(2#)"), 8, true);
+      iStat += EqnTest( _T("~(f1of1(2)#)"), 8, true);
+      //
+      iStat += EqnTest( _T("-2^2"),-4, true);
+      iStat += EqnTest( _T("-(a+b)^2"),-9, true);
+      iStat += EqnTest( _T("(-3)^2"),9, true);
+      iStat += EqnTest( _T("-(-2^2)"),4, true);
+      iStat += EqnTest( _T("3+-3^2"),-6, true);
+      // The following assumes use of sqr as postfix operator ("§") together
+      // with a sign operator of low priority:
+      iStat += EqnTest( _T("-2'"), -4, true);
+      iStat += EqnTest( _T("-(1+1)'"),-4, true);
+      iStat += EqnTest( _T("2+-(1+1)'"),-2, true);
+      iStat += EqnTest( _T("2+-2'"), -2, true);
+      // This is the classic behaviour of the infix sign operator (here: "$") which is
+      // now deprecated:
+      iStat += EqnTest( _T("$2^2"),4, true);
+      iStat += EqnTest( _T("$(a+b)^2"),9, true);
+      iStat += EqnTest( _T("($3)^2"),9, true);
+      iStat += EqnTest( _T("$($2^2)"),-4, true);
+      iStat += EqnTest( _T("3+$3^2"),12, true);
+
+      // infix operators sharing the first few characters
+      iStat += EqnTest( _T("~ 123"),  123+2, true);
+      iStat += EqnTest( _T("~~ 123"),  123+2, true);
+
+      if (iStat==0)
+        mu::console() << _T("passed") << endl;
+      else
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+
+    //---------------------------------------------------------------------------
+    int ParserTester::TestPostFix()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing postfix operators...");
+
+      // application
+      iStat += EqnTest( _T("3{m}+5"), 5.003, true);
+      iStat += EqnTest( _T("1000{m}"), 1, true);
+      iStat += EqnTest( _T("1000 {m}"), 1, true);
+      iStat += EqnTest( _T("(a){m}"), 1e-3, true);
+      iStat += EqnTest( _T("a{m}"), 1e-3, true);
+      iStat += EqnTest( _T("a {m}"), 1e-3, true);
+      iStat += EqnTest( _T("-(a){m}"), -1e-3, true);
+      iStat += EqnTest( _T("-2{m}"), -2e-3, true);
+      iStat += EqnTest( _T("-2 {m}"), -2e-3, true);
+      iStat += EqnTest( _T("f1of1(1000){m}"), 1, true);
+      iStat += EqnTest( _T("-f1of1(1000){m}"), -1, true);
+      iStat += EqnTest( _T("-f1of1(-1000){m}"), 1, true);
+      iStat += EqnTest( _T("f4of4(0,0,0,1000){m}"), 1, true);
+      iStat += EqnTest( _T("2+(a*1000){m}"), 3, true);
+
+      // can postfix operators "m" und "meg" be told apart properly?
+      iStat += EqnTest( _T("2*3000meg+2"), 2*3e9+2, true);   
+
+      // some incorrect results
+      iStat += EqnTest( _T("1000{m}"), 0.1, false);
+      iStat += EqnTest( _T("(a){m}"), 2, false);
+      // failure due to syntax checking
+      iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN);  // incomplete hex definition
+      iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);
+      iStat += ThrowTest( _T("4 + {m}"), ecUNASSIGNABLE_TOKEN);
+      iStat += ThrowTest( _T("{m}4"), ecUNASSIGNABLE_TOKEN);
+      iStat += ThrowTest( _T("sin({m})"), ecUNASSIGNABLE_TOKEN);
+      iStat += ThrowTest( _T("{m} {m}"), ecUNASSIGNABLE_TOKEN);
+      iStat += ThrowTest( _T("{m}(8)"), ecUNASSIGNABLE_TOKEN);
+      iStat += ThrowTest( _T("4,{m}"), ecUNASSIGNABLE_TOKEN);
+      iStat += ThrowTest( _T("-{m}"), ecUNASSIGNABLE_TOKEN);
+      iStat += ThrowTest( _T("2(-{m})"), ecUNEXPECTED_PARENS);
+      iStat += ThrowTest( _T("2({m})"), ecUNEXPECTED_PARENS);
+ 
+      iStat += ThrowTest( _T("multi*1.0"), ecUNASSIGNABLE_TOKEN);
+
+      if (iStat==0)
+        mu::console() << _T("passed") << endl;
+      else
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+    //---------------------------------------------------------------------------
+    int ParserTester::TestExpression()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing expression samples...");
+
+      value_type b = 2;
+
+      // Optimization
+      iStat += EqnTest( _T("2*b*5"), 20, true);
+      iStat += EqnTest( _T("2*b*5 + 4*b"), 28, true);
+      iStat += EqnTest( _T("2*a/3"), 2.0/3.0, true);
+
+      // Addition auf cmVARMUL 
+      iStat += EqnTest( _T("3+b"), b+3, true);
+      iStat += EqnTest( _T("b+3"), b+3, true);
+      iStat += EqnTest( _T("b*3+2"), b*3+2, true);
+      iStat += EqnTest( _T("3*b+2"), b*3+2, true);
+      iStat += EqnTest( _T("2+b*3"), b*3+2, true);
+      iStat += EqnTest( _T("2+3*b"), b*3+2, true);
+      iStat += EqnTest( _T("b+3*b"), b+3*b, true);
+      iStat += EqnTest( _T("3*b+b"), b+3*b, true);
+
+      iStat += EqnTest( _T("2+b*3+b"), 2+b*3+b, true);
+      iStat += EqnTest( _T("b+2+b*3"), b+2+b*3, true);
+
+      iStat += EqnTest( _T("(2*b+1)*4"), (2*b+1)*4, true);
+      iStat += EqnTest( _T("4*(2*b+1)"), (2*b+1)*4, true);
+
+      // operator precedences
+      iStat += EqnTest( _T("1+2-3*4/5^6"), 2.99923, true);
+      iStat += EqnTest( _T("1^2/3*4-5+6"), 2.33333333, true);
+      iStat += EqnTest( _T("1+2*3"), 7, true);
+      iStat += EqnTest( _T("1+2*3"), 7, true);
+      iStat += EqnTest( _T("(1+2)*3"), 9, true);
+      iStat += EqnTest( _T("(1+2)*(-3)"), -9, true);
+      iStat += EqnTest( _T("2/4"), 0.5, true);
+
+      iStat += EqnTest( _T("exp(ln(7))"), 7, true);
+      iStat += EqnTest( _T("e^ln(7)"), 7, true);
+      iStat += EqnTest( _T("e^(ln(7))"), 7, true);
+      iStat += EqnTest( _T("(e^(ln(7)))"), 7, true);
+      iStat += EqnTest( _T("1-(e^(ln(7)))"), -6, true);
+      iStat += EqnTest( _T("2*(e^(ln(7)))"), 14, true);
+      iStat += EqnTest( _T("10^log(5)"), pow(10.0, log(5.0)), true);
+      iStat += EqnTest( _T("10^log10(5)"), 5, true);
+      iStat += EqnTest( _T("2^log2(4)"), 4, true);
+      iStat += EqnTest( _T("-(sin(0)+1)"), -1, true);
+      iStat += EqnTest( _T("-(2^1.1)"), -2.14354692, true);
+
+      iStat += EqnTest( _T("(cos(2.41)/b)"), -0.372056, true);
+      iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true);
+      iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true);
+      iStat += EqnTest( _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true);
+
+      // long formula (Reference: Matlab)
+      iStat += EqnTest(
+        _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))")
+        _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/")
+        _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-")
+        _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6")
+        _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e")
+        _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true);
+
+      // long formula (Reference: Matlab)
+      iStat += EqnTest(
+          _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e")
+          _T(")+a)))*2.77)"), -2.16995656, true);
+
+      // long formula (Reference: Matlab)
+      iStat += EqnTest( _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true);
+	  
+      if (iStat==0) 
+        mu::console() << _T("passed") << endl;  
+      else 
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+
+
+    //---------------------------------------------------------------------------
+    int ParserTester::TestIfThenElse()
+    {
+      int iStat = 0;
+      mu::console() << _T("testing if-then-else operator...");
+
+      // Test error detection
+      iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); 
+      iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); 
+      iStat += ThrowTest(_T("(a<b) ? (b<c) ? 1 : 2"), ecMISSING_ELSE_CLAUSE); 
+      iStat += ThrowTest(_T("(a<b) ? 1"), ecMISSING_ELSE_CLAUSE); 
+      iStat += ThrowTest(_T("(a<b) ? a"), ecMISSING_ELSE_CLAUSE); 
+      iStat += ThrowTest(_T("(a<b) ? a+b"), ecMISSING_ELSE_CLAUSE); 
+      iStat += ThrowTest(_T("a : b"), ecMISPLACED_COLON); 
+      iStat += ThrowTest(_T("1 : 2"), ecMISPLACED_COLON); 
+      iStat += ThrowTest(_T("(1) ? 1 : 2 : 3"), ecMISPLACED_COLON); 
+      iStat += ThrowTest(_T("(true) ? 1 : 2 : 3"), ecUNASSIGNABLE_TOKEN); 
+
+      iStat += EqnTest(_T("1 ? 128 : 255"), 128, true);
+      iStat += EqnTest(_T("1<2 ? 128 : 255"), 128, true);
+      iStat += EqnTest(_T("a<b ? 128 : 255"), 128, true);
+      iStat += EqnTest(_T("(a<b) ? 128 : 255"), 128, true);
+      iStat += EqnTest(_T("(1) ? 10 : 11"), 10, true);
+      iStat += EqnTest(_T("(0) ? 10 : 11"), 11, true);
+      iStat += EqnTest(_T("(1) ? a+b : c+d"), 3, true);
+      iStat += EqnTest(_T("(0) ? a+b : c+d"), 1, true);
+      iStat += EqnTest(_T("(1) ? 0 : 1"), 0, true);
+      iStat += EqnTest(_T("(0) ? 0 : 1"), 1, true);
+      iStat += EqnTest(_T("(a<b) ? 10 : 11"), 10, true);
+      iStat += EqnTest(_T("(a>b) ? 10 : 11"), 11, true);
+      iStat += EqnTest(_T("(a<b) ? c : d"), 3, true);
+      iStat += EqnTest(_T("(a>b) ? c : d"), -2, true);
+
+      iStat += EqnTest(_T("(a>b) ? 1 : 0"), 0, true);
+      iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true);
+      iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true);
+      iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true);
+
+      iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true);
+      iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true);
+      iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true);
+      iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true);
+      iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true);
+      iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)"), 6, true);
+      iStat += EqnTest(_T("10*sum(3, (a>b) ? 3 : 10)"), 130, true);
+      iStat += EqnTest(_T("10*sum(3, (a<b) ? 3 : 10)"), 60, true);
+      iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)*10"), 130, true);
+      iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)*10"), 60, true);
+      iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 60, true);
+      iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 99, true);
+      iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 360, true);
+      iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 99, true);
+      iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : sum(3, (a<b) ? 3 : 10)*10"), 60, true);
+
+      // todo: auch für muParserX hinzufügen!
+      iStat += EqnTest(_T("(a<b)&&(a<b) ? 128 : 255"), 128, true);
+      iStat += EqnTest(_T("(a>b)&&(a<b) ? 128 : 255"), 255, true);
+      iStat += EqnTest(_T("(1<2)&&(1<2) ? 128 : 255"), 128, true);
+      iStat += EqnTest(_T("(1>2)&&(1<2) ? 128 : 255"), 255, true);
+      iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true);
+      iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true);
+      iStat += EqnTest(_T("((a<b)&&(a<b)) ? 128 : 255"), 128, true);
+      iStat += EqnTest(_T("((a>b)&&(a<b)) ? 128 : 255"), 255, true);
+
+      iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true);
+      iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true);
+      iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true);
+      iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true);
+      iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true);
+      iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true);
+      iStat += EqnTest(_T("1>0 ? 50 :  1>0 ? 128 : 255"), 50, true);
+      iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true);
+      iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true);
+      iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true);
+      iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true);
+      iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :  1>0 ? 32 :1>2 ? 64 : 16"), 255, true);
+      iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true);
+      iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true);
+
+      // assignment operators
+      iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true);
+      iStat += EqnTest(_T("a=((a>b)&&(a<b)) ? 128 : 255, a"), 255, true);
+      iStat += EqnTest(_T("c=(a<b)&&(a<b) ? 128 : 255, c"), 128, true);
+      iStat += EqnTest(_T("0 ? a=a+1 : 666, a"), 1, true);
+      iStat += EqnTest(_T("1?a=10:a=20, a"), 10, true);
+      iStat += EqnTest(_T("0?a=10:a=20, a"), 20, true);
+      iStat += EqnTest(_T("0?a=sum(3,4):10, a"), 1, true);  // a should not change its value due to lazy calculation
+      
+      iStat += EqnTest(_T("a=1?b=1?3:4:5, a"), 3, true);
+      iStat += EqnTest(_T("a=1?b=1?3:4:5, b"), 3, true);
+      iStat += EqnTest(_T("a=0?b=1?3:4:5, a"), 5, true);
+      iStat += EqnTest(_T("a=0?b=1?3:4:5, b"), 2, true);
+
+      iStat += EqnTest(_T("a=1?5:b=1?3:4, a"), 5, true);
+      iStat += EqnTest(_T("a=1?5:b=1?3:4, b"), 2, true);
+      iStat += EqnTest(_T("a=0?5:b=1?3:4, a"), 3, true);
+      iStat += EqnTest(_T("a=0?5:b=1?3:4, b"), 3, true);
+
+      if (iStat==0) 
+        mu::console() << _T("passed") << endl;  
+      else 
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+    //---------------------------------------------------------------------------
+    int ParserTester::TestException()
+    {
+      int  iStat = 0;
+      mu::console() << _T("testing error codes...");
+
+      iStat += ThrowTest(_T("3+"),           ecUNEXPECTED_EOF);
+      iStat += ThrowTest(_T("3+)"),          ecUNEXPECTED_PARENS);
+      iStat += ThrowTest(_T("()"),           ecUNEXPECTED_PARENS);
+      iStat += ThrowTest(_T("3+()"),         ecUNEXPECTED_PARENS);
+      iStat += ThrowTest(_T("sin(3,4)"),     ecTOO_MANY_PARAMS);
+      iStat += ThrowTest(_T("sin()"),        ecTOO_FEW_PARAMS);
+      iStat += ThrowTest(_T("(1+2"),         ecMISSING_PARENS);
+      iStat += ThrowTest(_T("sin(3)3"),      ecUNEXPECTED_VAL);
+      iStat += ThrowTest(_T("sin(3)xyz"),    ecUNASSIGNABLE_TOKEN);
+      iStat += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN);
+      iStat += ThrowTest(_T("a+b+c=10"),     ecUNEXPECTED_OPERATOR);
+      iStat += ThrowTest(_T("a=b=3"),        ecUNEXPECTED_OPERATOR);
+      
+#if defined(MUP_MATH_EXCEPTIONS)
+      // divide by zero whilst constant folding
+      iStat += ThrowTest(_T("1/0"),          ecDIV_BY_ZERO);
+      // square root of a negative number
+      iStat += ThrowTest(_T("sqrt(-1)"),     ecDOMAIN_ERROR);
+      // logarithms of zero
+      iStat += ThrowTest(_T("ln(0)"),        ecDOMAIN_ERROR);
+      iStat += ThrowTest(_T("log2(0)"),      ecDOMAIN_ERROR);
+      iStat += ThrowTest(_T("log10(0)"),     ecDOMAIN_ERROR);
+      iStat += ThrowTest(_T("log(0)"),       ecDOMAIN_ERROR);
+      // logarithms of negative values
+      iStat += ThrowTest(_T("ln(-1)"),       ecDOMAIN_ERROR);
+      iStat += ThrowTest(_T("log2(-1)"),     ecDOMAIN_ERROR);
+      iStat += ThrowTest(_T("log10(-1)"),    ecDOMAIN_ERROR);
+      iStat += ThrowTest(_T("log(-1)"),      ecDOMAIN_ERROR);
+#endif
+
+      // functions without parameter
+      iStat += ThrowTest( _T("3+ping(2)"),    ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("3+ping(a+2)"),  ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("3+ping(sin(a)+2)"),  ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("3+ping(1+sin(a))"),  ecTOO_MANY_PARAMS);
+
+      // String function related
+      iStat += ThrowTest( _T("valueof(\"xxx\")"),  999, false);
+      iStat += ThrowTest( _T("valueof()"),          ecUNEXPECTED_PARENS);
+      iStat += ThrowTest( _T("1+valueof(\"abc\""),  ecMISSING_PARENS);
+      iStat += ThrowTest( _T("valueof(\"abc\""),    ecMISSING_PARENS);
+      iStat += ThrowTest( _T("valueof(\"abc"),      ecUNTERMINATED_STRING);
+      iStat += ThrowTest( _T("valueof(\"abc\",3)"), ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("valueof(3)"),         ecSTRING_EXPECTED);
+      iStat += ThrowTest( _T("sin(\"abc\")"),       ecVAL_EXPECTED);
+      iStat += ThrowTest( _T("valueof(\"\\\"abc\\\"\")"),  999, false);
+      iStat += ThrowTest( _T("\"hello world\""),    ecSTR_RESULT);
+      iStat += ThrowTest( _T("(\"hello world\")"),  ecSTR_RESULT);
+      iStat += ThrowTest( _T("\"abcd\"+100"),       ecOPRT_TYPE_CONFLICT);
+      iStat += ThrowTest( _T("\"a\"+\"b\""),        ecOPRT_TYPE_CONFLICT);
+      iStat += ThrowTest( _T("strfun1(\"100\",3)"),     ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("strfun2(\"100\",3,5)"),   ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("strfun3(\"100\",3,5,6)"), ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("strfun2(\"100\")"),       ecTOO_FEW_PARAMS);
+      iStat += ThrowTest( _T("strfun3(\"100\",6)"),   ecTOO_FEW_PARAMS);
+      iStat += ThrowTest( _T("strfun2(1,1)"),         ecSTRING_EXPECTED);
+      iStat += ThrowTest( _T("strfun2(a,1)"),         ecSTRING_EXPECTED);
+      iStat += ThrowTest( _T("strfun2(1,1,1)"),       ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("strfun2(a,1,1)"),       ecTOO_MANY_PARAMS);
+      iStat += ThrowTest( _T("strfun3(1,2,3)"),         ecSTRING_EXPECTED);
+      iStat += ThrowTest( _T("strfun3(1, \"100\",3)"),  ecSTRING_EXPECTED);
+      iStat += ThrowTest( _T("strfun3(\"1\", \"100\",3)"),  ecVAL_EXPECTED);
+      iStat += ThrowTest( _T("strfun3(\"1\", 3, \"100\")"),  ecVAL_EXPECTED);
+      iStat += ThrowTest( _T("strfun3(\"1\", \"100\", \"100\", \"100\")"),  ecTOO_MANY_PARAMS);
+
+      // assignment operator
+      iStat += ThrowTest( _T("3=4"), ecUNEXPECTED_OPERATOR);
+      iStat += ThrowTest( _T("sin(8)=4"), ecUNEXPECTED_OPERATOR);
+      iStat += ThrowTest( _T("\"test\"=a"), ecUNEXPECTED_OPERATOR);
+
+      // <ibg 20090529>
+      // this is now legal, for reference see:
+      // https://sourceforge.net/forum/message.php?msg_id=7411373
+      //      iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR);    
+      // </ibg>
+
+      iStat += ThrowTest( _T("(8)=5"), ecUNEXPECTED_OPERATOR);
+      iStat += ThrowTest( _T("(a)=5"), ecUNEXPECTED_OPERATOR);
+      iStat += ThrowTest( _T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT);
+
+      if (iStat==0) 
+        mu::console() << _T("passed") << endl;
+      else 
+        mu::console() << _T("\n  failed with ") << iStat << _T(" errors") << endl;
+
+      return iStat;
+    }
+
+
+    //---------------------------------------------------------------------------
+    void ParserTester::AddTest(testfun_type a_pFun)
+    {
+      m_vTestFun.push_back(a_pFun);
+    }
+
+    //---------------------------------------------------------------------------
+    void ParserTester::Run()
+    {
+      int iStat = 0;
+      try
+      {
+        for (int i=0; i<(int)m_vTestFun.size(); ++i)
+          iStat += (this->*m_vTestFun[i])();
+      }
+      catch(Parser::exception_type &e)
+      {
+        mu::console() << "\n" << e.GetMsg() << endl;
+        mu::console() << e.GetToken() << endl;
+        Abort();
+      }
+      catch(std::exception &e)
+      {
+        mu::console() << e.what() << endl;
+        Abort();
+      }
+      catch(...)
+      {
+        mu::console() << "Internal error";
+        Abort();
+      }
+
+      if (iStat==0) 
+      {
+        mu::console() << "Test passed (" <<  ParserTester::c_iCount << " expressions)" << endl;
+      }
+      else 
+      {
+        mu::console() << "Test failed with " << iStat 
+                  << " errors (" <<  ParserTester::c_iCount 
+                  << " expressions)" << endl;
+      }
+      ParserTester::c_iCount = 0;
+    }
+
+
+    //---------------------------------------------------------------------------
+    int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)
+    {
+      ParserTester::c_iCount++;
+
+      try
+      {
+        value_type fVal[] = {1,1,1};
+        Parser p;
+
+        p.DefineVar( _T("a"), &fVal[0]);
+        p.DefineVar( _T("b"), &fVal[1]);
+        p.DefineVar( _T("c"), &fVal[2]);
+        p.DefinePostfixOprt( _T("{m}"), Milli);
+        p.DefinePostfixOprt( _T("m"), Milli);
+        p.DefineFun( _T("ping"), Ping);
+        p.DefineFun( _T("valueof"), ValueOf);
+        p.DefineFun( _T("strfun1"), StrFun1);
+        p.DefineFun( _T("strfun2"), StrFun2);
+        p.DefineFun( _T("strfun3"), StrFun3);
+        p.SetExpr(a_str);
+        p.Eval();
+      }
+      catch(ParserError &e)
+      {
+        // output the formula in case of an failed test
+        if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) )
+        {
+          mu::console() << _T("\n  ") 
+                        << _T("Expression: ") << a_str 
+                        << _T("  Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")")
+                        << _T("  Expected:") << a_iErrc;
+        }
+
+        return (a_iErrc==e.GetCode()) ? 0 : 1;
+      }
+
+      // if a_bFail==false no exception is expected
+      bool bRet((a_bFail==false) ? 0 : 1);
+      if (bRet==1)
+      {
+        mu::console() << _T("\n  ") 
+                      << _T("Expression: ") << a_str 
+                      << _T("  did evaluate; Expected error:") << a_iErrc;
+      }
+
+      return bRet; 
+    }
+
+    //---------------------------------------------------------------------------
+    /** \brief Evaluate a tet expression. 
+
+        \return 1 in case of a failure, 0 otherwise.
+    */
+    int ParserTester::EqnTestWithVarChange(const string_type &a_str, 
+                                           double a_fVar1, 
+                                           double a_fRes1, 
+                                           double a_fVar2, 
+                                           double a_fRes2)
+    {
+      ParserTester::c_iCount++;
+
+      try
+      {
+        value_type fVal[2] = {-999, -999 }; // should be equal
+	  
+        Parser  p;
+        value_type var = 0;
+
+        // variable
+        p.DefineVar( _T("a"), &var);
+        p.SetExpr(a_str);
+
+        var = a_fVar1;
+        fVal[0] = p.Eval();
+
+        var = a_fVar2;
+        fVal[1] = p.Eval();
+        
+        if ( fabs(a_fRes1-fVal[0]) > 0.0000000001)
+          throw std::runtime_error("incorrect result (first pass)");
+
+        if ( fabs(a_fRes2-fVal[1]) > 0.0000000001)
+          throw std::runtime_error("incorrect result (second pass)");
+      }
+      catch(Parser::exception_type &e)
+      {
+        mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");
+        return 1;
+      }
+      catch(std::exception &e)
+      {
+        mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");
+        return 1;  // always return a failure since this exception is not expected
+      }
+      catch(...)
+      {
+        mu::console() << _T("\n  fail: ") << a_str.c_str() <<  _T(" (unexpected exception)");
+        return 1;  // exceptions other than ParserException are not allowed
+      }
+
+      return 0;
+    }
+
+    //---------------------------------------------------------------------------
+    /** \brief Evaluate a tet expression. 
+
+        \return 1 in case of a failure, 0 otherwise.
+    */
+    int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
+    {
+      ParserTester::c_iCount++;
+      int iRet(0);
+      value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different
+
+      try
+      {
+        std::auto_ptr<Parser> p1;
+        Parser  p2, p3;   // three parser objects
+                          // they will be used for testing copy and assignment operators
+        // p1 is a pointer since i'm going to delete it in order to test if
+        // parsers after copy construction still refer to members of it.
+        // !! If this is the case this function will crash !!
+      
+        p1.reset(new mu::Parser()); 
+        // Add constants
+        p1->DefineConst( _T("pi"), (value_type)PARSER_CONST_PI);
+        p1->DefineConst( _T("e"), (value_type)PARSER_CONST_E);
+        p1->DefineConst( _T("const"), 1);
+        p1->DefineConst( _T("const1"), 2);
+        p1->DefineConst( _T("const2"), 3);
+        // string constants
+        p1->DefineStrConst( _T("str1"), _T("1.11"));
+        p1->DefineStrConst( _T("str2"), _T("2.22"));
+        // variables
+        value_type vVarVal[] = { 1, 2, 3, -2};
+        p1->DefineVar( _T("a"), &vVarVal[0]);
+        p1->DefineVar( _T("aa"), &vVarVal[1]);
+        p1->DefineVar( _T("b"), &vVarVal[1]);
+        p1->DefineVar( _T("c"), &vVarVal[2]);
+        p1->DefineVar( _T("d"), &vVarVal[3]);
+        
+        // custom value ident functions
+        p1->AddValIdent(&ParserTester::IsHexVal);        
+
+        // functions
+        p1->DefineFun( _T("ping"), Ping);
+        p1->DefineFun( _T("f1of1"), f1of1);  // one parameter
+        p1->DefineFun( _T("f1of2"), f1of2);  // two parameter
+        p1->DefineFun( _T("f2of2"), f2of2);
+        p1->DefineFun( _T("f1of3"), f1of3);  // three parameter
+        p1->DefineFun( _T("f2of3"), f2of3);
+        p1->DefineFun( _T("f3of3"), f3of3);
+        p1->DefineFun( _T("f1of4"), f1of4);  // four parameter
+        p1->DefineFun( _T("f2of4"), f2of4);
+        p1->DefineFun( _T("f3of4"), f3of4);
+        p1->DefineFun( _T("f4of4"), f4of4);
+        p1->DefineFun( _T("f1of5"), f1of5);  // five parameter
+        p1->DefineFun( _T("f2of5"), f2of5);
+        p1->DefineFun( _T("f3of5"), f3of5);
+        p1->DefineFun( _T("f4of5"), f4of5);
+        p1->DefineFun( _T("f5of5"), f5of5);
+
+        // binary operators
+        p1->DefineOprt( _T("add"), add, 0);
+        p1->DefineOprt( _T("++"), add, 0);
+        p1->DefineOprt( _T("&"), land, prLAND);
+
+        // sample functions
+        p1->DefineFun( _T("min"), Min);
+        p1->DefineFun( _T("max"), Max);
+        p1->DefineFun( _T("sum"), Sum);
+        p1->DefineFun( _T("valueof"), ValueOf);
+        p1->DefineFun( _T("atof"), StrToFloat);
+        p1->DefineFun( _T("strfun1"), StrFun1);
+        p1->DefineFun( _T("strfun2"), StrFun2);
+        p1->DefineFun( _T("strfun3"), StrFun3);
+        p1->DefineFun( _T("lastArg"), LastArg);
+        p1->DefineFun( _T("firstArg"), FirstArg);
+        p1->DefineFun( _T("order"), FirstArg);
+
+        // infix / postfix operator
+        // Note: Identifiers used here do not have any meaning 
+        //       they are mere placeholders to test certain features.
+        p1->DefineInfixOprt( _T("$"), sign, prPOW+1);  // sign with high priority
+        p1->DefineInfixOprt( _T("~"), plus2);          // high priority
+        p1->DefineInfixOprt( _T("~~"), plus2);
+        p1->DefinePostfixOprt( _T("{m}"), Milli);
+        p1->DefinePostfixOprt( _T("{M}"), Mega);
+        p1->DefinePostfixOprt( _T("m"), Milli);
+        p1->DefinePostfixOprt( _T("meg"), Mega);
+        p1->DefinePostfixOprt( _T("#"), times3);
+        p1->DefinePostfixOprt( _T("'"), sqr); 
+        p1->SetExpr(a_str);
+
+        // Test bytecode integrity
+        // String parsing and bytecode parsing must yield the same result
+        fVal[0] = p1->Eval(); // result from stringparsing
+        fVal[1] = p1->Eval(); // result from bytecode
+        if (fVal[0]!=fVal[1])
+          throw Parser::exception_type( _T("Bytecode / string parsing mismatch.") );
+
+        // Test copy and assignment operators
+        try
+        {
+          // Test copy constructor
+          std::vector<mu::Parser> vParser;
+          vParser.push_back(*(p1.get()));
+          mu::Parser p2 = vParser[0];   // take parser from vector
+        
+          // destroy the originals from p2
+          vParser.clear();              // delete the vector
+          p1.reset(0);
+
+          fVal[2] = p2.Eval();
+
+          // Test assignment operator
+          // additionally  disable Optimizer this time
+          mu::Parser p3;
+          p3 = p2;
+          p3.EnableOptimizer(false);
+          fVal[3] = p3.Eval();
+
+          // Test Eval function for multiple return values
+          // use p2 since it has the optimizer enabled!
+          int nNum;
+          value_type *v = p2.Eval(nNum);
+          fVal[4] = v[nNum-1];
+        }
+        catch(std::exception &e)
+        {
+          mu::console() << _T("\n  ") << e.what() << _T("\n");
+        }
+
+        // limited floating point accuracy requires the following test
+        bool bCloseEnough(true);
+        for (unsigned i=0; i<sizeof(fVal)/sizeof(value_type); ++i)
+        {
+          bCloseEnough &= (fabs(a_fRes-fVal[i]) <= fabs(fVal[i]*0.00001));
+
+          // The tests equations never result in infinity, if they do thats a bug.
+          // reference:
+          // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825
+          #pragma warning(push)
+          #pragma warning(disable:4127)
+		  if (std::numeric_limits<value_type>::has_infinity)
+          #pragma warning(pop)
+		  {
+            bCloseEnough &= (fabs(fVal[i]) != numeric_limits<value_type>::infinity());
+		  }
+		}
+
+        iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;
+        
+        
+        if (iRet==1)
+        {
+          mu::console() << _T("\n  fail: ") << a_str.c_str() 
+                        << _T(" (incorrect result; expected: ") << a_fRes
+                        << _T(" ;calculated: ") << fVal[0] << _T(",") 
+                                                << fVal[1] << _T(",")
+                                                << fVal[2] << _T(",")
+                                                << fVal[3] << _T(",")
+                                                << fVal[4] << _T(").");
+        }
+      }
+      catch(Parser::exception_type &e)
+      {
+        if (a_fPass)
+        {
+          if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998)
+            mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (copy construction)");
+          else
+            mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");
+          return 1;
+        }
+      }
+      catch(std::exception &e)
+      {
+        mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");
+        return 1;  // always return a failure since this exception is not expected
+      }
+      catch(...)
+      {
+        mu::console() << _T("\n  fail: ") << a_str.c_str() <<  _T(" (unexpected exception)");
+        return 1;  // exceptions other than ParserException are not allowed
+      }
+
+      return iRet;
+    }
+
+    //---------------------------------------------------------------------------
+    int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass)
+    {
+      ParserTester::c_iCount++;
+
+      value_type vVarVal[] = {1, 2, 3};   // variable values
+      int iRet(0);
+
+      try
+      {
+        value_type fVal[2] = {-99, -999};   // results: initially should be different
+        ParserInt p;
+        p.DefineConst( _T("const1"), 1);
+        p.DefineConst( _T("const2"), 2);
+        p.DefineVar( _T("a"), &vVarVal[0]);
+        p.DefineVar( _T("b"), &vVarVal[1]);
+        p.DefineVar( _T("c"), &vVarVal[2]);
+
+        p.SetExpr(a_str);
+        fVal[0] = p.Eval(); // result from stringparsing
+        fVal[1] = p.Eval(); // result from bytecode
+
+        if (fVal[0]!=fVal[1])
+          throw Parser::exception_type( _T("Bytecode corrupt.") );
+
+        iRet =  ( (a_fRes==fVal[0] &&  a_fPass) || 
+                  (a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1;
+        if (iRet==1)
+        {
+          mu::console() << _T("\n  fail: ") << a_str.c_str() 
+                        << _T(" (incorrect result; expected: ") << a_fRes 
+                        << _T(" ;calculated: ") << fVal[0]<< _T(").");
+        }
+      }
+      catch(Parser::exception_type &e)
+      {
+        if (a_fPass)
+        {
+          mu::console() << _T("\n  fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();
+          iRet = 1;
+        }
+      }
+      catch(...)
+      {
+        mu::console() << _T("\n  fail: ") << a_str.c_str() <<  _T(" (unexpected exception)");
+        iRet = 1;  // exceptions other than ParserException are not allowed
+      }
+
+      return iRet;
+    }
+
+    //---------------------------------------------------------------------------
+    /** \brief Test an expression in Bulk Mode. */
+    int ParserTester::EqnTestBulk(const string_type &a_str, double a_fRes[4], bool a_fPass)
+    {
+        ParserTester::c_iCount++;
+
+        // Define Bulk Variables
+        int nBulkSize = 4;
+        value_type vVariableA[] = { 1, 2, 3, 4 };   // variable values
+        value_type vVariableB[] = { 2, 2, 2, 2 };   // variable values
+        value_type vVariableC[] = { 3, 3, 3, 3 };   // variable values
+        value_type vResults[] = { 0, 0, 0, 0 };   // variable values
+        int iRet(0);
+
+        try
+        {
+            Parser p;
+            p.DefineConst(_T("const1"), 1);
+            p.DefineConst(_T("const2"), 2);
+            p.DefineVar(_T("a"), vVariableA);
+            p.DefineVar(_T("b"), vVariableB);
+            p.DefineVar(_T("c"), vVariableC);
+
+            p.SetExpr(a_str);
+            p.Eval(vResults, nBulkSize);
+
+            bool bCloseEnough(true);
+            for (int i = 0; i < nBulkSize; ++i)
+            {
+                bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001));
+            }
+
+            iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;
+            if (iRet == 1)
+            {
+                mu::console() << _T("\n  fail: ") << a_str.c_str()
+                    << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}")
+                    << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}");
+            }
+        }
+        catch (Parser::exception_type &e)
+        {
+            if (a_fPass)
+            {
+                mu::console() << _T("\n  fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();
+                iRet = 1;
+            }
+        }
+        catch (...)
+        {
+            mu::console() << _T("\n  fail: ") << a_str.c_str() << _T(" (unexpected exception)");
+            iRet = 1;  // exceptions other than ParserException are not allowed
+        }
+
+        return iRet;
+    }
+
+    //---------------------------------------------------------------------------
+    /** \brief Internal error in test class Test is going to be aborted. */
+    void ParserTester::Abort() const
+    {
+      mu::console() << _T("Test failed (internal error in test class)") << endl;
+      while (!getchar());
+      exit(-1);
+    }
+  } // namespace test
+} // namespace mu
diff --git a/source/ThirdParty/MuParser/src/muParserTokenReader.cpp b/source/ThirdParty/MuParser/src/muParserTokenReader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8da1e40247b638bafbd1be328575bf98bf32d87b
--- /dev/null
+++ b/source/ThirdParty/MuParser/src/muParserTokenReader.cpp
@@ -0,0 +1,958 @@
+/*
+                 __________                                      
+    _____   __ __\______   \_____  _______  ______  ____ _______ 
+   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
+  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
+  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
+        \/                       \/            \/      \/        
+  Copyright (C) 2013 Ingo Berg
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+  software and associated documentation files (the "Software"), to deal in the Software
+  without restriction, including without limitation the rights to use, copy, modify, 
+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+  permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all copies or 
+  substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
+  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+*/
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <map>
+#include <stack>
+#include <string>
+
+#include "muParserTokenReader.h"
+#include "muParserBase.h"
+
+/** \file
+    \brief This file contains the parser token reader implementation.
+*/
+
+
+namespace mu
+{
+
+  // Forward declaration
+  class ParserBase;
+
+  //---------------------------------------------------------------------------
+  /** \brief Copy constructor.
+
+      \sa Assign
+      \throw nothrow
+  */
+  ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) 
+  { 
+    Assign(a_Reader);
+  }
+    
+  //---------------------------------------------------------------------------
+  /** \brief Assignment operator.
+
+      Self assignment will be suppressed otherwise #Assign is called.
+
+      \param a_Reader Object to copy to this token reader.
+      \throw nothrow
+  */
+  ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader) 
+  {
+    if (&a_Reader!=this)
+      Assign(a_Reader);
+
+    return *this;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Assign state of a token reader to this token reader. 
+      
+      \param a_Reader Object from which the state should be copied.
+      \throw nothrow
+  */
+  void ParserTokenReader::Assign(const ParserTokenReader &a_Reader)
+  {
+    m_pParser = a_Reader.m_pParser;
+    m_strFormula = a_Reader.m_strFormula;
+    m_iPos = a_Reader.m_iPos;
+    m_iSynFlags = a_Reader.m_iSynFlags;
+    
+    m_UsedVar         = a_Reader.m_UsedVar;
+    m_pFunDef         = a_Reader.m_pFunDef;
+    m_pConstDef       = a_Reader.m_pConstDef;
+    m_pVarDef         = a_Reader.m_pVarDef;
+    m_pStrVarDef      = a_Reader.m_pStrVarDef;
+    m_pPostOprtDef    = a_Reader.m_pPostOprtDef;
+    m_pInfixOprtDef   = a_Reader.m_pInfixOprtDef;
+    m_pOprtDef        = a_Reader.m_pOprtDef;
+    m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar;
+    m_vIdentFun       = a_Reader.m_vIdentFun;
+    m_pFactory        = a_Reader.m_pFactory;
+    m_pFactoryData    = a_Reader.m_pFactoryData;
+    m_iBrackets       = a_Reader.m_iBrackets;
+    m_cArgSep         = a_Reader.m_cArgSep;
+	m_fZero           = a_Reader.m_fZero;
+	m_lastTok         = a_Reader.m_lastTok;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Constructor. 
+      
+      Create a Token reader and bind it to a parser object. 
+
+      \pre [assert] a_pParser may not be NULL
+      \post #m_pParser==a_pParser
+      \param a_pParent Parent parser object of the token reader.
+  */
+  ParserTokenReader::ParserTokenReader(ParserBase *a_pParent)
+    :m_pParser(a_pParent)
+    ,m_strFormula()
+    ,m_iPos(0)
+    ,m_iSynFlags(0)
+    ,m_bIgnoreUndefVar(false)
+    ,m_pFunDef(NULL)
+    ,m_pPostOprtDef(NULL)
+    ,m_pInfixOprtDef(NULL)
+    ,m_pOprtDef(NULL)
+    ,m_pConstDef(NULL)
+    ,m_pStrVarDef(NULL)
+    ,m_pVarDef(NULL)
+    ,m_pFactory(NULL)
+    ,m_pFactoryData(NULL)
+    ,m_vIdentFun()
+    ,m_UsedVar()
+    ,m_fZero(0)
+    ,m_iBrackets(0)
+    ,m_lastTok()
+    ,m_cArgSep(',')
+  {
+    assert(m_pParser);
+    SetParent(m_pParser);
+  }
+    
+  //---------------------------------------------------------------------------
+  /** \brief Create instance of a ParserTokenReader identical with this 
+              and return its pointer. 
+
+      This is a factory method the calling function must take care of the object destruction.
+
+      \return A new ParserTokenReader object.
+      \throw nothrow
+  */
+  ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const
+  {
+    std::auto_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));
+    ptr->SetParent(a_pParent);
+    return ptr.release();
+  }
+
+  //---------------------------------------------------------------------------
+  ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok)
+  {
+    m_lastTok = tok;
+    return m_lastTok;
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserTokenReader::AddValIdent(identfun_type a_pCallback)
+  {
+    // Use push_front is used to give user defined callbacks a higher priority than
+    // the built in ones. Otherwise reading hex numbers would not work
+    // since the "0" in "0xff" would always be read first making parsing of 
+    // the rest impossible.
+    // reference:
+    // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956
+    m_vIdentFun.push_front(a_pCallback);
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData)
+  {
+    m_pFactory = a_pFactory;
+    m_pFactoryData = pUserData;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return the current position of the token reader in the formula string. 
+
+      \return #m_iPos
+      \throw nothrow
+  */
+  int ParserTokenReader::GetPos() const
+  {
+    return m_iPos;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return a reference to the formula. 
+
+      \return #m_strFormula
+      \throw nothrow
+  */
+  const string_type& ParserTokenReader::GetExpr() const
+  {
+    return m_strFormula;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Return a map containing the used variables only. */
+  varmap_type& ParserTokenReader::GetUsedVar() 
+  {
+    return m_UsedVar;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Initialize the token Reader. 
+  
+      Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.
+      \pre [assert] triggered if a_szFormula==0
+  */
+  void ParserTokenReader::SetFormula(const string_type &a_strFormula)
+  {
+    m_strFormula = a_strFormula;
+    ReInit();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Set Flag that controls behaviour in case of undefined variables being found. 
+  
+    If true, the parser does not throw an exception if an undefined variable is found. 
+    otherwise it does. This variable is used internally only!
+    It suppresses a "undefined variable" exception in GetUsedVar().  
+    Those function should return a complete list of variables including 
+    those the are not defined by the time of it's call.
+  */
+  void ParserTokenReader::IgnoreUndefVar(bool bIgnore)
+  {
+    m_bIgnoreUndefVar = bIgnore;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Reset the token reader to the start of the formula. 
+
+      The syntax flags will be reset to a value appropriate for the 
+      start of a formula.
+      \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR
+      \throw nothrow
+      \sa ESynCodes
+  */
+  void ParserTokenReader::ReInit()
+  {
+    m_iPos = 0;
+    m_iSynFlags = sfSTART_OF_LINE;
+    m_iBrackets = 0;
+    m_UsedVar.clear();
+    m_lastTok = token_type();
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Read the next token from the string. */ 
+  ParserTokenReader::token_type ParserTokenReader::ReadNextToken()
+  {
+    assert(m_pParser);
+
+    const char_type *szFormula = m_strFormula.c_str();
+    token_type tok;
+
+    // Ignore all non printable characters when reading the expression
+    while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) 
+      ++m_iPos;
+
+    if ( IsEOF(tok) )        return SaveBeforeReturn(tok); // Check for end of formula
+    if ( IsOprt(tok) )       return SaveBeforeReturn(tok); // Check for user defined binary operator
+    if ( IsFunTok(tok) )     return SaveBeforeReturn(tok); // Check for function token
+    if ( IsBuiltIn(tok) )    return SaveBeforeReturn(tok); // Check built in operators / tokens
+    if ( IsArgSep(tok) )     return SaveBeforeReturn(tok); // Check for function argument separators
+    if ( IsValTok(tok) )     return SaveBeforeReturn(tok); // Check for values / constant tokens
+    if ( IsVarTok(tok) )     return SaveBeforeReturn(tok); // Check for variable tokens
+    if ( IsStrVarTok(tok) )  return SaveBeforeReturn(tok); // Check for string variables
+    if ( IsString(tok) )     return SaveBeforeReturn(tok); // Check for String tokens
+    if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators
+    if ( IsPostOpTok(tok) )  return SaveBeforeReturn(tok); // Check for unary operators
+
+    // Check String for undefined variable token. Done only if a 
+    // flag is set indicating to ignore undefined variables.
+    // This is a way to conditionally avoid an error if 
+    // undefined variables occur. 
+    // (The GetUsedVar function must suppress the error for
+    // undefined variables in order to collect all variable 
+    // names including the undefined ones.)
+    if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) )  
+      return SaveBeforeReturn(tok);
+
+    // Check for unknown token
+    // 
+    // !!! From this point on there is no exit without an exception possible...
+    // 
+    string_type strTok;
+    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+    if (iEnd!=m_iPos)
+      Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);
+
+    Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));
+    return token_type(); // never reached
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserTokenReader::SetParent(ParserBase *a_pParent)
+  {
+    m_pParser       = a_pParent; 
+    m_pFunDef       = &a_pParent->m_FunDef;
+    m_pOprtDef      = &a_pParent->m_OprtDef;
+    m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;
+    m_pPostOprtDef  = &a_pParent->m_PostOprtDef;
+    m_pVarDef       = &a_pParent->m_VarDef;
+    m_pStrVarDef    = &a_pParent->m_StrVarDef;
+    m_pConstDef     = &a_pParent->m_ConstDef;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Extract all characters that belong to a certain charset.
+
+    \param a_szCharSet [in] Const char array of the characters allowed in the token. 
+    \param a_strTok [out]  The string that consists entirely of characters listed in a_szCharSet.
+    \param a_iPos [in] Position in the string from where to start reading.
+    \return The Position of the first character not listed in a_szCharSet.
+    \throw nothrow
+  */
+  int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, 
+                                      string_type &a_sTok, 
+                                      int a_iPos) const
+  {
+    int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);
+
+    if (iEnd==(int)string_type::npos)
+        iEnd = (int)m_strFormula.length();
+    
+    // Assign token string if there was something found
+    if (a_iPos!=iEnd)
+      a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);
+
+    return iEnd;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check Expression for the presence of a binary operator token.
+  
+    Userdefined binary operator "++" gives inconsistent parsing result for
+    the equations "a++b" and "a ++ b" if alphabetic characters are allowed
+    in operator tokens. To avoid this this function checks specifically
+    for operator tokens.
+  */
+  int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, 
+                                              int a_iPos) const
+  {
+    // Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6
+    int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos);
+    if (iEnd==(int)string_type::npos)
+      iEnd = (int)m_strFormula.length();
+
+    // Assign token string if there was something found
+    if (a_iPos!=iEnd)
+    {
+      a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
+      return iEnd;
+    }
+    else
+    {
+      // There is still the chance of having to deal with an operator consisting exclusively
+      // of alphabetic characters.
+      return ExtractToken(MUP_CHARS, a_sTok, a_iPos);
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check if a built in operator or other token can be found
+      \param a_Tok  [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
+      \return true if an operator token has been found.
+  */
+  bool ParserTokenReader::IsBuiltIn(token_type &a_Tok)
+  {
+    const char_type **const pOprtDef = m_pParser->GetOprtDef(),
+                     *const szFormula = m_strFormula.c_str();
+
+    // Compare token with function and operator strings
+    // check string for operator/function
+    for (int i=0; pOprtDef[i]; i++)
+    {
+      std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );
+      if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )
+      {
+        switch(i)
+        {
+        //case cmAND:
+        //case cmOR:
+        //case cmXOR:
+        case cmLAND:
+        case cmLOR:
+        case cmLT:
+        case cmGT:
+        case cmLE:
+        case cmGE:
+        case cmNEQ:  
+        case cmEQ:
+        case cmADD:
+        case cmSUB:
+        case cmMUL:
+        case cmDIV:
+        case cmPOW:
+        case cmASSIGN:
+              //if (len!=sTok.length())
+              //  continue;
+
+              // The assignment operator need special treatment
+              if (i==cmASSIGN && m_iSynFlags & noASSIGN)
+                Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
+
+              if (!m_pParser->HasBuiltInOprt()) continue;
+              if (m_iSynFlags & noOPT) 
+              {
+                // Maybe its an infix operator not an operator
+                // Both operator types can share characters in 
+                // their identifiers
+                if ( IsInfixOpTok(a_Tok) ) 
+                  return true;
+
+                Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
+              }
+
+              m_iSynFlags  = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND;
+              break;
+
+		    case cmBO:
+              if (m_iSynFlags & noBO)
+	              Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+              
+              if (m_lastTok.GetCode()==cmFUNC)
+                m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
+              else
+                m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE;
+
+              ++m_iBrackets;
+              break;
+
+		    case cmBC:
+              if (m_iSynFlags & noBC)
+                Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+
+              m_iSynFlags  = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;
+
+              if (--m_iBrackets<0)
+                Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+              break;
+
+        case cmELSE:
+              if (m_iSynFlags & noELSE)
+                Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
+
+              m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
+              break;
+
+        case cmIF:
+              if (m_iSynFlags & noIF)
+                Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
+
+              m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
+              break;
+
+		    default:      // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...
+              Error(ecINTERNAL_ERROR);
+        } // switch operator id
+
+        m_iPos += (int)len;
+        a_Tok.Set( (ECmdCode)i, pOprtDef[i] );
+        return true;
+	    } // if operator string found
+    } // end of for all operator strings
+  
+    return false;
+  }
+
+  //---------------------------------------------------------------------------
+  bool ParserTokenReader::IsArgSep(token_type &a_Tok)
+  {
+    const char_type* szFormula = m_strFormula.c_str();
+
+    if (szFormula[m_iPos]==m_cArgSep)
+    {
+      // copy the separator into null terminated string
+      char_type szSep[2];
+      szSep[0] = m_cArgSep;
+      szSep[1] = 0;
+
+      if (m_iSynFlags & noARG_SEP)
+        Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);
+
+      m_iSynFlags  = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;
+      m_iPos++;
+      a_Tok.Set(cmARG_SEP, szSep);
+      return true;
+    }
+
+    return false;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check for End of Formula.
+
+      \return true if an end of formula is found false otherwise.
+      \param a_Tok [out] If an eof is found the corresponding token will be stored there.
+      \throw nothrow
+      \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok
+  */
+  bool ParserTokenReader::IsEOF(token_type &a_Tok)
+  {
+    const char_type* szFormula = m_strFormula.c_str();
+
+    // check for EOF
+    if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/)
+    {
+      if ( m_iSynFlags & noEND )
+        Error(ecUNEXPECTED_EOF, m_iPos);
+
+      if (m_iBrackets>0)
+        Error(ecMISSING_PARENS, m_iPos, _T(")"));
+
+      m_iSynFlags = 0;
+      a_Tok.Set(cmEND);
+      return true;
+    }
+
+    return false;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check if a string position contains a unary infix operator. 
+      \return true if a function token has been found false otherwise.
+  */
+  bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok)
+  {
+    string_type sTok;
+    int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);
+    if (iEnd==m_iPos)
+      return false;
+
+    // iterate over all postfix operator strings
+    funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();
+    for ( ; it!=m_pInfixOprtDef->rend(); ++it)
+    {
+      if (sTok.find(it->first)!=0)
+        continue;
+
+      a_Tok.Set(it->second, it->first);
+      m_iPos += (int)it->first.length();
+
+      if (m_iSynFlags & noINFIXOP) 
+        Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
+
+      m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;
+      return true;
+    }
+
+    return false;
+
+/*
+    a_Tok.Set(item->second, sTok);
+    m_iPos = (int)iEnd;
+
+    if (m_iSynFlags & noINFIXOP) 
+      Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
+
+    m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; 
+    return true;
+*/
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check whether the token at a given position is a function token.
+      \param a_Tok [out] If a value token is found it will be placed here.
+      \throw ParserException if Syntaxflags do not allow a function at a_iPos
+      \return true if a function token has been found false otherwise.
+      \pre [assert] m_pParser!=0
+  */
+  bool ParserTokenReader::IsFunTok(token_type &a_Tok)
+  {
+    string_type strTok;
+    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+    if (iEnd==m_iPos)
+      return false;
+
+    funmap_type::const_iterator item = m_pFunDef->find(strTok);
+    if (item==m_pFunDef->end())
+      return false;
+
+    // Check if the next sign is an opening bracket
+    const char_type *szFormula = m_strFormula.c_str();
+    if (szFormula[iEnd]!='(')
+      return false;
+
+    a_Tok.Set(item->second, strTok);
+
+    m_iPos = (int)iEnd;
+    if (m_iSynFlags & noFUN)
+      Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
+
+    m_iSynFlags = noANY ^ noBO;
+    return true;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check if a string position contains a binary operator.
+      \param a_Tok  [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
+      \return true if an operator token has been found.
+  */
+  bool ParserTokenReader::IsOprt(token_type &a_Tok)
+  {
+    const char_type *const szExpr = m_strFormula.c_str();
+    string_type strTok;
+
+    int iEnd = ExtractOperatorToken(strTok, m_iPos);
+    if (iEnd==m_iPos)
+      return false;
+
+    // Check if the operator is a built in operator, if so ignore it here
+    const char_type **const pOprtDef = m_pParser->GetOprtDef();
+    for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)
+    {
+      if (string_type(pOprtDef[i])==strTok)
+        return false;
+    }
+
+    // Note:
+    // All tokens in oprt_bin_maptype are have been sorted by their length
+    // Long operators must come first! Otherwise short names (like: "add") that
+    // are part of long token names (like: "add123") will be found instead 
+    // of the long ones.
+    // Length sorting is done with ascending length so we use a reverse iterator here.
+    funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();
+    for ( ; it!=m_pOprtDef->rend(); ++it)
+    {
+      const string_type &sID = it->first;
+      if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) )
+      {
+        a_Tok.Set(it->second, strTok);
+
+        // operator was found
+        if (m_iSynFlags & noOPT) 
+        {
+          // An operator was found but is not expected to occur at
+          // this position of the formula, maybe it is an infix 
+          // operator, not a binary operator. Both operator types
+          // can share characters in their identifiers.
+          if ( IsInfixOpTok(a_Tok) ) 
+            return true;
+          else
+          {
+            // nope, no infix operator
+            return false;
+            //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); 
+          }
+
+        }
+
+        m_iPos += (int)sID.length();
+        m_iSynFlags  = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN;
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check if a string position contains a unary post value operator. */
+  bool ParserTokenReader::IsPostOpTok(token_type &a_Tok)
+  {
+    // <ibg 20110629> Do not check for postfix operators if they are not allowed at
+    //                the current expression index.
+    //
+    //  This will fix the bug reported here:  
+    //
+    //  http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979
+    //
+    if (m_iSynFlags & noPOSTOP)
+      return false;
+    // </ibg>
+
+    // Tricky problem with equations like "3m+5":
+    //     m is a postfix operator, + is a valid sign for postfix operators and 
+    //     for binary operators parser detects "m+" as operator string and 
+    //     finds no matching postfix operator.
+    // 
+    // This is a special case so this routine slightly differs from the other
+    // token readers.
+    
+    // Test if there could be a postfix operator
+    string_type sTok;
+    int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);
+    if (iEnd==m_iPos)
+      return false;
+
+    // iterate over all postfix operator strings
+    funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();
+    for ( ; it!=m_pPostOprtDef->rend(); ++it)
+    {
+      if (sTok.find(it->first)!=0)
+        continue;
+
+      a_Tok.Set(it->second, sTok);
+  	  m_iPos += (int)it->first.length();
+
+      m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;
+      return true;
+    }
+
+    return false;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check whether the token at a given position is a value token.
+
+    Value tokens are either values or constants.
+
+    \param a_Tok [out] If a value token is found it will be placed here.
+    \return true if a value token has been found.
+  */
+  bool ParserTokenReader::IsValTok(token_type &a_Tok)
+  {
+    assert(m_pConstDef);
+    assert(m_pParser);
+
+    string_type strTok;
+    value_type fVal(0);
+    int iEnd(0);
+    
+    // 2.) Check for user defined constant
+    // Read everything that could be a constant name
+    iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+    if (iEnd!=m_iPos)
+    {
+      valmap_type::const_iterator item = m_pConstDef->find(strTok);
+      if (item!=m_pConstDef->end())
+      {
+        m_iPos = iEnd;
+        a_Tok.SetVal(item->second, strTok);
+
+        if (m_iSynFlags & noVAL)
+          Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
+
+        m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; 
+        return true;
+      }
+    }
+
+    // 3.call the value recognition functions provided by the user
+    // Call user defined value recognition functions
+    std::list<identfun_type>::const_iterator item = m_vIdentFun.begin();
+    for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item)
+    {
+      int iStart = m_iPos;
+      if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 )
+      {
+        // 2013-11-27 Issue 2:  https://code.google.com/p/muparser/issues/detail?id=2
+        strTok.assign(m_strFormula.c_str(), iStart, m_iPos-iStart);
+
+        if (m_iSynFlags & noVAL)
+          Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
+
+        a_Tok.SetVal(fVal, strTok);
+        m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Check wheter a token at a given position is a variable token. 
+      \param a_Tok [out] If a variable token has been found it will be placed here.
+	    \return true if a variable token has been found.
+  */
+  bool ParserTokenReader::IsVarTok(token_type &a_Tok)
+  {
+    if (m_pVarDef->empty())
+      return false;
+
+    string_type strTok;
+    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+    if (iEnd==m_iPos)
+      return false;
+
+    varmap_type::const_iterator item =  m_pVarDef->find(strTok);
+    if (item==m_pVarDef->end())
+      return false;
+
+    if (m_iSynFlags & noVAR)
+      Error(ecUNEXPECTED_VAR, m_iPos, strTok);
+
+    m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd);
+
+    m_iPos = iEnd;
+    a_Tok.SetVar(item->second, strTok);
+    m_UsedVar[item->first] = item->second;  // Add variable to used-var-list
+
+    m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR;
+
+//  Zur Info hier die SynFlags von IsVal():
+//    m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; 
+    return true;
+  }
+
+  //---------------------------------------------------------------------------
+  bool ParserTokenReader::IsStrVarTok(token_type &a_Tok)
+  {
+    if (!m_pStrVarDef || m_pStrVarDef->empty())
+      return false;
+
+    string_type strTok;
+    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+    if (iEnd==m_iPos)
+      return false;
+
+    strmap_type::const_iterator item =  m_pStrVarDef->find(strTok);
+    if (item==m_pStrVarDef->end())
+      return false;
+
+    if (m_iSynFlags & noSTR)
+      Error(ecUNEXPECTED_VAR, m_iPos, strTok);
+
+    m_iPos = iEnd;
+    if (!m_pParser->m_vStringVarBuf.size())
+      Error(ecINTERNAL_ERROR);
+
+    a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() );
+
+    m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP);
+    return true;
+  }
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Check wheter a token at a given position is an undefined variable. 
+
+      \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.
+	    \return true if a variable token has been found.
+      \throw nothrow
+  */
+  bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok)
+  {
+    string_type strTok;
+    int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) );
+    if ( iEnd==m_iPos )
+      return false;
+
+    if (m_iSynFlags & noVAR)
+    {
+      // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the 
+      //                 token identifier. 
+      // related bug report:
+      // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979
+      Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);
+    }
+
+    // If a factory is available implicitely create new variables
+    if (m_pFactory)
+    {
+      value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData);
+      a_Tok.SetVar(fVar, strTok );
+
+      // Do not use m_pParser->DefineVar( strTok, fVar );
+      // in order to define the new variable, it will clear the
+      // m_UsedVar array which will kill previously defined variables
+      // from the list
+      // This is safe because the new variable can never override an existing one
+      // because they are checked first!
+      (*m_pVarDef)[strTok] = fVar;
+      m_UsedVar[strTok] = fVar;  // Add variable to used-var-list
+    }
+    else
+    {
+      a_Tok.SetVar((value_type*)&m_fZero, strTok);
+      m_UsedVar[strTok] = 0;  // Add variable to used-var-list
+    }
+
+    m_iPos = iEnd;
+
+    // Call the variable factory in order to let it define a new parser variable
+    m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;
+    return true;
+  }
+
+
+  //---------------------------------------------------------------------------
+  /** \brief Check wheter a token at a given position is a string.
+      \param a_Tok [out] If a variable token has been found it will be placed here.
+  	  \return true if a string token has been found.
+      \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok
+      \throw nothrow
+  */
+  bool ParserTokenReader::IsString(token_type &a_Tok)
+  {
+    if (m_strFormula[m_iPos]!='"') 
+      return false;
+
+    string_type strBuf(&m_strFormula[m_iPos+1]);
+    std::size_t iEnd(0), iSkip(0);
+
+    // parser over escaped '\"' end replace them with '"'
+    for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd))
+    {
+      if (strBuf[iEnd-1]!='\\') break;
+      strBuf.replace(iEnd-1, 2, _T("\"") );
+      iSkip++;
+    }
+
+    if (iEnd==string_type::npos)
+      Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") );
+
+    string_type strTok(strBuf.begin(), strBuf.begin()+iEnd);
+
+    if (m_iSynFlags & noSTR)
+      Error(ecUNEXPECTED_STR, m_iPos, strTok);
+
+		m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer
+    a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
+
+    m_iPos += (int)strTok.length() + 2 + (int)iSkip;  // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen
+    m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND );
+
+    return true;
+  }
+
+  //---------------------------------------------------------------------------
+  /** \brief Create an error containing the parse error position.
+
+    This function will create an Parser Exception object containing the error text and its position.
+
+    \param a_iErrc [in] The error code of type #EErrorCodes.
+    \param a_iPos [in] The position where the error was detected.
+    \param a_strTok [in] The token string representation associated with the error.
+    \throw ParserException always throws thats the only purpose of this function.
+  */
+  void  ParserTokenReader::Error( EErrorCodes a_iErrc, 
+                                  int a_iPos, 
+                                  const string_type &a_sTok) const
+  {
+    m_pParser->Error(a_iErrc, a_iPos, a_sTok);
+  }
+
+  //---------------------------------------------------------------------------
+  void ParserTokenReader::SetArgSep(char_type cArgSep)
+  {
+    m_cArgSep = cArgSep;
+  }
+
+  //---------------------------------------------------------------------------
+  char_type ParserTokenReader::GetArgSep() const
+  {
+    return m_cArgSep;
+  }
+} // namespace mu
+
diff --git a/source/VirtualFluids.h b/source/VirtualFluids.h
new file mode 100644
index 0000000000000000000000000000000000000000..a5aed55ac8103a5ea38249046a7ff23f774af395
--- /dev/null
+++ b/source/VirtualFluids.h
@@ -0,0 +1,320 @@
+//VirtualFluids header files
+ 
+#if defined VF_FETOL
+#define WIN32_LEAN_AND_MEAN
+#include <JM.h>
+#endif
+
+ 
+#include <MuParser/include/muParser.h>
+#include <MuParser/include/muParserBase.h>
+#include <MuParser/include/muParserBytecode.h>
+#include <MuParser/include/muParserCallback.h>
+#include <MuParser/include/muParserDef.h>
+#include <MuParser/include/muParserDLL.h>
+#include <MuParser/include/muParserError.h>
+#include <MuParser/include/muParserFixes.h>
+#include <MuParser/include/muParserInt.h>
+#include <MuParser/include/muParserStack.h>
+#include <MuParser/include/muParserTemplateMagic.h>
+#include <MuParser/include/muParserTest.h>
+#include <MuParser/include/muParserToken.h>
+#include <MuParser/include/muParserTokenReader.h>
+#include <basics/container/CbArray2D.h>
+#include <basics/container/CbArray3D.h>
+#include <basics/container/CbArray4D.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+//#include <basics/container/examples/CbVectorPool/functions.h>
+//#include <basics/memory/MbChessMemPool2D.h>
+//#include <basics/memory/MbChessMemPool3D.h>
+#include <basics/memory/MbMemPool.h>
+#include <basics/memory/MbSharedPointerDefines.h>
+#include <basics/memory/MbSmartPtr.h>
+#include <basics/memory/MbSmartPtrBase.h>
+#include <basics/objects/ObCreator.h>
+#include <basics/objects/ObFactory.h>
+#include <basics/objects/ObObject.h>
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/objects/ObObjectFactory.h>
+#include <basics/objects/ObObjectManager.h>
+// #include <basics/parallel/PbMpi.h>
+// #include <basics/parallel/PbMpiTools.h>
+// #include <basics/parallel/examples/simpleMPI/functions.h>
+// #include <basics/relation/RbAggregation.h>
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/transmitter/TbTransmitterLocal.h>
+#include <basics/transmitter/TbTransmitterMpi.h>
+// #include <basics/transmitter/TbTransmitterMpiCPPB.h>
+#include <basics/transmitter/TbTransmitterMpiPool.h>
+//#include <basics/transmitter/TbTransmitterMpiPool2.h>
+// #include <basics/transmitter/TbTransmitterRcf.h>
+// #include <basics/transmitter/TbTransmitterRcfPool.h>
+#include <basics/utilities/UbAutoRun.hpp>
+#include <basics/utilities/UbComparators.h>
+#include <basics/utilities/UbConverter.h>
+#include <basics/utilities/UbEqual.h>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+#include <basics/utilities/UbFileInputASCII.h>
+#include <basics/utilities/UbFileInputBinary.h>
+#include <basics/utilities/UbFileOutput.h>
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <basics/utilities/UbFileOutputBinary.h>
+#include <basics/utilities/UbInfinity.h>
+#include <basics/utilities/UbKeys.h>
+#include <basics/utilities/UbLimits.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbNupsTimer.h>
+#include <basics/utilities/UbObservable.h>
+#include <basics/utilities/UbObserver.h>
+#include <basics/utilities/UbPointerWrapper.h>
+#include <basics/utilities/UbRandom.h>
+#include <basics/utilities/UbScheduler.h>
+#include <basics/utilities/UbStaticPathMap.h>
+#include <basics/utilities/UbString.h>
+#include <basics/utilities/UbStringInputASCII.h>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbTableModel.h>
+#include <basics/utilities/UbTiming.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/writer/WbWriter.h>
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/writer/WbWriterAvsBinary.h>
+#include <basics/writer/WbWriterBOBJ.h>
+#include <basics/writer/WbWriterSunflow.h>
+#include <basics/writer/WbWriterTecPlotASCII.h>
+#include <basics/writer/WbWriterVtkASCII.h>
+#include <basics/writer/WbWriterVtkBinary.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterX3D.h>
+// #include <BoundaryCondition/BCArray.h>
+#include <BoundaryCondition/BCArray3D.h>
+#include <BoundaryCondition/BCProcessor.h>
+#include <BoundaryCondition/BoundaryCondition.h>
+#include <BoundaryCondition/D3Q27BCFunction.h>
+#include <BoundaryCondition/D3Q27BoundaryCondition.h>
+#include <BoundaryCondition/D3Q27BoundaryConditionAdapter.h>
+#include <BoundaryCondition/D3Q27DensityBCAdapter.h>
+#include <BoundaryCondition/D3Q27ETBCProcessor.h>
+#include <BoundaryCondition/D3Q27ETForThinWallBCProcessor.h>
+#include <BoundaryCondition/D3Q27NoSlipBCAdapter.h>
+#include <BoundaryCondition/D3Q27SlipBCAdapter.h>
+#include <BoundaryCondition/D3Q27VelocityBCAdapter.h>
+
+#include <BoundaryCondition/BoundaryConditionProcessor.h>
+#include <BoundaryCondition/BoundaryCondition.h>
+#include <BoundaryCondition/VelocityBoundaryCondition.h>
+#include <BoundaryCondition/NonEqDensityBoundaryCondition.h>
+#include <BoundaryCondition/EqDensityBoundaryCondition.h>
+#include <BoundaryCondition/NoSlipBoundaryCondition.h>
+#include <BoundaryCondition/ThinWallNoSlipBoundaryCondition.h>
+#include <BoundaryCondition/HighViscosityNoSlipBoundaryCondition.h>
+#include <BoundaryCondition/SlipBoundaryCondition.h>
+#include <BoundaryCondition/NonReflectingDensityBoundaryCondition.h>
+#include <BoundaryCondition/NonReflectingVelocityBoundaryCondition.h>
+
+#include <Connectors/Block3DConnector.h>
+#include <Connectors/D3Q27ETCFOffVectorConnector.h>
+#include <Connectors/D3Q27ETCFVectorConnector.h>
+#include <Connectors/D3Q27ETDirectConnector.h>
+#include <Connectors/D3Q27ETDirectConnector2.h>
+#include <Connectors/D3Q27ETFCOffVectorConnector.h>
+#include <Connectors/D3Q27ETFCVectorConnector.h>
+#include <Connectors/D3Q27ETFullDirectConnector.h>
+#include <Connectors/D3Q27ETFullDirectConnector2.h>
+#include <Connectors/D3Q27ETFullVectorConnector.h>
+#include <Connectors/D3Q27ETVectorConnector.h>
+#include <Connectors/D3Q27ETWithInvDirectConnector.h>
+#include <Connectors/LocalBlock3DConnector.h>
+#include <Connectors/RemoteBlock3DConnector.h>
+#include <Connectors/CoarseToFineBlock3DConnector.h>
+#include <Connectors/CoarseToFineNodeSetBlock3DConnector.h>
+#include <Connectors/FineToCoarseBlock3DConnector.h>
+#include <Connectors/FineToCoarseNodeSetBlock3DConnector.h>
+#include <Connectors/ConnectorFactory.h>
+#include <Connectors/Block3DConnectorFactory.h>
+#include <Data/D3Q27EsoTwist3DSplittedVector.h>
+#include <Data/D3Q27EsoTwist3DSplittedVectorEx.h>
+#include <Data/DataSet3D.h>
+#include <Data/DistributionArray3D.h>
+#include <Data/EsoTwist3D.h>
+#include <Data/EsoTwistD3Q27System.h>
+#include <Data/EsoTwistD3Q27SparseData.h>
+#include <Grid/Block3D.h>
+//#include <Grid/BoostSerializationClassExportHelper.h>
+#include <Grid/CalculationManager.h>
+#include <Grid/Calculator.h>
+#include <Grid/Calculator2.h>
+#include <Grid/Grid3D.h>
+#include <Grid/Grid3DSystem.h>
+#include <Interactors/D3Q27Interactor.h>
+#include <Interactors/D3Q27TriFaceMeshInteractor.h>
+#include <Interactors/Interactor3D.h>
+#include <Interactors/InteractorsHelper.h>
+#include <CoProcessors/BlocksPostprocessor.h>
+#include <CoProcessors/D3Q27AdjustForcingPostprocessor.h>
+#include <CoProcessors/D3Q27ForcesPostprocessor.h>
+#include <CoProcessors/D3Q27MacroscopicQuantitiesPostprocessor.h>
+#include <CoProcessors/D3Q27PathLinePostprocessor.h>
+#include <CoProcessors/D3Q27PathLinePostprocessorMcpart.h>
+#include <CoProcessors/D3Q27PressureDifferencePostprocessor.h>
+#include <CoProcessors/EmergencyExitPostprocessor.h>
+#include <CoProcessors/NUPSCounterPostprocessor.h>
+#include <CoProcessors/Particles.h>
+#include <CoProcessors/Postprocessor.h>
+#include <CoProcessors/RestartPostprocessor.h>
+#include <CoProcessors/TurbulenceIntensityPostprocessor.h>
+#include <CoProcessors/AverageValuesPostprocessor.h>
+#include <CoProcessors/DecreaseViscosityPostprocessor.h>
+#include <CoProcessors/TimeseriesPostprocessor.h>
+#include <CoProcessors/D3Q27ShearStressPostprocessor.h>
+#include <CoProcessors/QCriterionPostprocessor.h>
+#include <CoProcessors/InSituVTKPostprocessor.h>
+#include <CoProcessors/D3Q27MeanValuesPostprocessor.h>
+#include <CoProcessors/TimeAveragedValuesPostprocessor.h>
+#include <CoProcessors/InSituCatalystPostprocessor.h>
+#include <LBM/D3Q27CompactInterpolationProcessor.h>
+#include <LBM/D3Q27IncompressibleOffsetInterpolationProcessor.h>
+#include <LBM/D3Q27IntegrateValuesHelper.h>
+#include <LBM/D3Q27InterpolationHelper.h>
+#include <LBM/D3Q27InterpolationProcessor.h>
+#include <LBM/D3Q27OffsetInterpolationProcessor.h>
+#include <LBM/D3Q27System.h>
+#include <LBM/ICell.h>
+#include <LBM/InterpolationProcessor.h>
+#include <LBM/LBMKernel3D.h>
+#include <LBM/LBMKernelESD3Q27CCLB.h>
+#include <LBMKernelETD3Q27CCLBWithSpongeLayer.h>
+#include <LBM/LBMKernelETD3Q27.h>
+#include <LBM/LBMKernelETD3Q27BGK.h>
+#include <LBM/LBMKernelETD3Q27Cascaded.h>
+#include <LBM/LBMKernelETD3Q27CascadedTI.h>
+#include <LBM/LBMKernelETD3Q27CCLB.h>
+#include <LBM/LBMKernelETD3Q27CCLBSparse.h>
+#include <LBM/LBMKernelETD3Q27CCLBex.h>
+#include <LBM/LBMKernelETD3Q27CCLBex2.h>
+#include <LBM/LBMSystem.h>
+#include <LBM/LBMSystems.h>
+#include <LBM/LBMUnitConverter.h>
+#include <LBM/SimulationParameters.h>
+#include <numerics/geometry3d/CoordinateTransformation3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/GbCylinder3D.h>
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+#include <numerics/geometry3d/GbHalfSpaceKrischan3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbMeshTools3D.h>
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbObject3DManager.h>
+#include <numerics/geometry3d/GbObjectGroup3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbPolygon3D.h>
+#include <numerics/geometry3d/GbQuadFaceMesh3D.h>
+#include <numerics/geometry3d/GbSphere3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/GbTriangularMesh3D.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <numerics/geometry3d/GbVector3D.h>
+#include <numerics/geometry3d/GbVoxelMatrix3D.h>
+#include <numerics/geometry3d/creator/GbCuboid3DCreator.h>
+#include <numerics/geometry3d/creator/GbCylinder3DCreator.h>
+#include <numerics/geometry3d/creator/GbLine3DCreator.h>
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/creator/GbObject3DFactory.h>
+#include <numerics/geometry3d/creator/GbPoint3DCreator.h>
+#include <numerics/geometry3d/creator/GbPolygon3DCreator.h>
+#include <numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.h>
+#include <numerics/geometry3d/creator/GbSphere3DCreator.h>
+#include <numerics/geometry3d/creator/GbTriangle3DCreator.h>
+#include <numerics/geometry3d/creator/GbTriangularMesh3DCreator.h>
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+#include <numerics/geometry3d/creator/GbVoxelMatrix3DCreator.h>
+// #include <numerics/geometry3d/examples/stl2inp/QDefineUniformMesh.h>
+// #include <numerics/geometry3d/examples/stl2inp/stl2inp.h>
+// #include <numerics/geometry3d/fem/FeAdhocTriFaceMesh3D.h>
+// #include <numerics/geometry3d/fem/FeHalfDisc3D.h>
+// #include <numerics/geometry3d/fem/FePlateTriangularMesh3D.h>
+// #include <numerics/geometry3d/fem/FePoint3D.h>
+// #include <numerics/geometry3d/fem/FeRing3D.h>
+// #include <numerics/geometry3d/fem/FeTriFaceMesh3D.h>
+// #include <numerics/geometry3d/fem/creator/FeTriFaceMesh3DCreator.h>
+#include <numerics/geometry3d/KdTree/KdNode.h>
+#include <numerics/geometry3d/KdTree/KdRay.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidateManager.h>
+#include <numerics/geometry3d/KdTree/KdTree.h>
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdRayIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+// #include <numerics/geometry3d/presentation/QGbCuboid3DInstrument.h>
+// #include <numerics/geometry3d/presentation/QGbCylinder3DInstrument.h>
+// #include <numerics/geometry3d/presentation/QGbObject3DInstrument.h>
+// #include <numerics/geometry3d/presentation/QGbSphere3DInstrument.h>
+// #include <numerics/geometry3d/presentation/QVTKGbObject3DViewer.h>
+// #include <numerics/geometry3d/presentation/vtkGbCuboid3D.h>
+// #include <numerics/geometry3d/presentation/vtkGbCylinder3D.h>
+// #include <numerics/geometry3d/presentation/vtkGbSphere3D.h>
+// #include <numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h>
+
+#include <Parallel/Communicator.h>
+#include <Parallel/LoadBalancer.h>
+#include <Parallel/MetisPartitioner.h>
+#include <Parallel/MPICommunicator.h>
+#include <Parallel/NullCommunicator.h>
+#include <Parallel/PriorityQueueDecompositor.h>
+#include <Parallel/SimpleGeometricPartitioner.h>
+#include <Parallel/Synchronizer.h>
+#include <Parallel/ZoltanPartitioner.h>
+#include <Parallel/BlocksDistributor.h>
+#include <ZoltanPartitioningGridVisitor.h>
+#include <Utilities/MathUtil.hpp>
+#include <Utilities/MemoryUtil.h>
+#include <Utilities/StringUtil.hpp>
+#include <Utilities/ConfigurationFile.hpp>
+#include <Utilities/VoxelMatrixUtil.hpp>
+#include <Utilities/ChangeRandomQs.hpp>
+#include <Utilities/ConfigFileReader.h>
+#include <Visitors/Block3DVisitor.h>
+#include <Visitors/CreateTransmittersHelper.h>
+#include <Visitors/D3Q27ETInitDistributionsBlockVisitor.h>
+#include <Visitors/D3Q27SetConnectorsBlockVisitor.h>
+#include <Visitors/D3Q27SetUndefinedNodesBlockVisitor.h>
+#include <Visitors/GenBlocksGridVisitor.h>
+#include <Visitors/Grid3DVisitor.h>
+#include <Visitors/MetisPartitioningGridVisitor.h>
+#include <Visitors/OverlapBlockVisitor.h>
+#include <Visitors/PQueuePartitioningGridVisitor.h>
+#include <Visitors/RatioBlockVisitor.h>
+#include <Visitors/RatioSmoothBlockVisitor.h>
+#include <Visitors/RefineCrossAndInsideGbObjectBlockVisitor.h>
+#include <Visitors/RefineInterGbObjectsVisitor.h>
+#include <Visitors/SetInterpolationDirsBlockVisitor.h>
+#include <Visitors/SetKernelBlockVisitor.h>
+#include <Visitors/SetForcingBlockVisitor.h>
+#include <Visitors/SetSpongeLayerBlockVisitor.h>
+#include <Visitors/SetSolidOrTransBlockVisitor.h>
+#include <Visitors/RenumberBlockVisitor.h>
+#include <Visitors/ConnectorBlockVisitor.h>
+#include <Visitors/ViscosityBlockVisitor.h>
+#include <Visitors/BoundaryConditionBlockVisitor.h>
+#include <Visitors/ChangeBoundaryDensityBlockVisitor.h>
+
+#include <Visitors/RefineCrossAndInsideGbObjectHelper.h>
+#include <RefineAroundGbObjectHelper.h>
+
+#if defined VF_FETOL
+   #include <FETOL/FETOLCalculator.h>
+   #include <FETOL/FETOLCommunicator.h>
+   #include <FETOL/FETOLSetConnectorsBlockVisitor.h>
+   #include <FETOL/FETOLTransmitterBondPool.h>   
+#endif
+
diff --git a/source/VirtualFluidsCore/Basics/container/CMakePackage.txt b/source/VirtualFluidsCore/Basics/container/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f7766736561db92faa97bdef5d1c1a6a40533148
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/CMakePackage.txt
@@ -0,0 +1,4 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
+
+
diff --git a/source/VirtualFluidsCore/Basics/container/CbArray2D.h b/source/VirtualFluidsCore/Basics/container/CbArray2D.h
new file mode 100644
index 0000000000000000000000000000000000000000..2dc54329b868a760d1803d4c03ba7099c52b4b44
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/CbArray2D.h
@@ -0,0 +1,414 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBARRAY2D_H
+#define CBARRAY2D_H
+
+//////////////////////////////////////////////////////////////////////////
+// 4D Array
+// die Daten werden in einem Vector gehalten
+//
+// Ver 1.2
+// Nov. 2003 muffmolch@gmx.de
+// Ver 1.3
+// Aug. 2006 - Kosmetik
+// Ver 1.4
+// Sep. 2006 - indexer eingefuehrt
+// Ver 1.5
+// Jul. 2006 - size_t + range check bei getIndex
+// Ver 1.6
+// Mrz. 2008 - typedefs, new index checks, NO_CB_RANGECHECK, no base class
+//             assigmetcomparison between Matrices with different value_type and/or index-class
+// Oct. 2008 - +isEmpty()
+//
+// Rangecheck aktiv, wenn:
+// -debug  : not defined "NO_CB_RANGECHECK"
+// -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK"
+//////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbEqual.h>
+#include <algorithm>
+#include <typeinfo>
+
+#ifdef CAB_RCF
+  #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// IndexClasses
+
+//IndexerX2X1:
+//        4 5 6
+// Array  1 2 3  -->  vector 1 2 3 4 5 6
+//optimaler schleifendurchlauf
+//for(alle X2)
+//  for(alle X1)
+class IndexerX2X1
+{
+public:
+   typedef int size_type;
+public:
+   inline std::size_t getIndex(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const
+   {
+      return nx1* x2 + x1;
+   }
+   inline std::size_t getStartIndexOfSortedArray(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const
+   {
+      return  nx1* x2;
+   }
+};
+
+//IndexerX1X2:
+//        4 5 6
+// Array  1 2 3  -->  vector 1 4 2 5 3 6
+//optimaler schleifendurchlauf
+//for(alle X1)
+//  for(alle X2)
+class IndexerX1X2
+{
+public:
+   typedef int size_type;
+public:
+   inline std::size_t getIndex(const size_type& x1, const size_type& x2, const size_type& nx1,const size_type& nx2) const
+   {
+      return nx2* x1+ x2;
+   }
+   inline std::size_t getStartIndexOfSortedArray(const size_type& x1, const size_type& x2, const size_type& nx1, const size_type& nx2) const
+   {
+      return  nx2* x1;
+   }
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// CbArray2D
+
+template<typename T, typename IndexClass = IndexerX2X1>
+class CbArray2D
+{
+public:
+   typedef T                                                   value_type;
+   typedef IndexClass                                          indexer_type;
+   typedef typename IndexClass::size_type                      size_type;
+   typedef typename std::vector< value_type >::reference       reference;
+   typedef typename std::vector< value_type >::const_reference const_reference;
+   typedef typename std::vector< value_type >::pointer         pointer;
+   typedef typename std::vector< value_type >::const_pointer   const_pointer;
+
+private:
+   template< typename value_type2, typename IndexClass2 > friend class CbArray2D;
+
+public:
+   /*=======================================================================*/
+   CbArray2D()
+   {
+      this->resize(0,0);
+   }
+   /*=======================================================================*/
+   CbArray2D(const size_type& nx2, const size_type& nx1)
+   {
+      this->resize(nx2,nx1);
+   }
+   /*=======================================================================*/
+   CbArray2D(const size_type& nx2, const size_type& nx1, const value_type& val)
+   {
+      this->resize(nx2,nx1,val);
+   }
+   /*=======================================================================*/
+   CbArray2D(const size_type& uniformDimensionSize /*nx1==nx2*/)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   //übernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird)
+   CbArray2D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2)
+   {
+      assert( (nx1*nx2)==vec.size() );
+      this->data.swap(vec);
+      this->resize(nx1,nx2);
+   }
+   /*=======================================================================*/
+   CbArray2D(const CbArray2D& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , data(src.data)
+   {
+   }
+   /*=======================================================================*/
+   template< typename value_type2 >
+   CbArray2D(const CbArray2D< value_type2 >& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+   {
+      //Sourcedaten kopieren
+      this->data.resize( src.data.size() );
+      for(std::size_t i=0; i<data.size(); ++i)
+         this->data[i] = src.data[i];
+   }
+   /*=======================================================================*/
+   virtual ~CbArray2D()
+   {
+      //vector wird automatisch zerstoert
+   }
+   /*=======================================================================*/
+   CbArray2D& operator= (const CbArray2D& rhs)
+   {
+      if(this == &rhs) return *this;
+
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+
+      //Sourcedaten kopieren
+      this->data  = rhs.data;
+
+      return *this;
+   }
+   /*=======================================================================*/
+   //durch value_type2 kann man z.B. ein float array einem double array zuweisen!
+   template< typename value_type2, typename IndexClass2 >
+   CbArray2D& operator= (const CbArray2D< value_type2, IndexClass2 >& rhs)
+   {
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+
+      //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      //ACHTUNG: für diese Konvertierung muss bei Klassen der demenstrechende operator
+      //         implementiert sein, e.g.: class value_type2 {public: inline operator value_type2() const { return value_type2(); }
+      for(int x1=0; x1<this->nx1; x1++)
+         for(int x2=0; x2<this->nx2; x2++)
+               this->operator()(x1,x2) = static_cast< value_type >( rhs.operator()(x1,x2) );
+
+      return *this;
+   }
+   /*=======================================================================*/
+   bool operator== (const CbArray2D& rhs) const
+   {
+      if( this == &rhs ) return true;
+
+      if(   this->nx1!=rhs.nx1
+         || this->nx2!=rhs.nx2
+         || this->data.size() != rhs.data.size() )
+      {
+         return false;
+      }
+
+      return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() );
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator== (const CbArray2D< value_type2, IndexClass2 >& rhs) const
+   {
+      if( this->data.size() != rhs.data.size() ) return false;
+
+      //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x1=0; x1<this->nx1; x1++)
+         for(int x2=0; x2<this->nx2; x2++)
+            if( !isUbEqual(this->operator()(x1,x2), rhs.operator()(x1,x2)) )
+               return false;
+
+      return true;
+   }
+   /*=======================================================================*/
+   bool operator!= (const CbArray2D& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator!= (const CbArray2D< value_type2, IndexClass2 >& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   reference operator() (const size_type& x1,const size_type& x2)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,nx1,nx2)];
+   }
+   /*=======================================================================*/
+   const_reference operator() (const size_type& x1,const size_type& x2)	const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,nx1,nx2)];
+   }
+   /*=======================================================================*/
+   pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,nx1,nx2)];
+   }
+   /*=======================================================================*/
+   const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,nx1,nx2)];
+   }
+   /*=======================================================================*/
+   void setObject(const size_type& x1,const size_type& x2,const value_type& value)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+      this->data[indexer.getIndex(x1,x2,nx1,nx2)] = value;
+   }
+   /*=======================================================================*/
+   reference getObject(const size_type& x1, const size_type& x2)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+      return this->data[indexer.getIndex(x1,x2,nx1,nx2)] ;
+   }
+   /*=======================================================================*/
+   typename std::vector<value_type>::const_reference getObject(const size_type& x1, const size_type& x2) const
+   {
+      return this->operator()(x1,x2);
+   }
+   /*=======================================================================*/
+   bool      isEmpty() const { return data.empty(); }
+   size_type getNX1()  const { return this->nx1;    }
+   size_type getNX2()  const { return this->nx2;    }
+   /*=======================================================================*/
+   void reset(const T& val)
+   {
+      std::fill( this->data.begin(), this->data.end(), val );
+   }
+   /*=======================================================================*/
+   std::string toString() const
+   {
+      std::stringstream text;
+      for(size_type x2=0; x2<this->nx2; x2++)
+      {
+         for(size_type x1=0; x1<this->nx1; x1++)
+         {
+            //hier kommts zum Konflikt ab  und an ...
+            text<<this->getObject(x1,x2)<<", ";
+         }
+         text<<"\n";
+      }
+
+      return text.str();
+   }
+   /*=======================================================================*/
+   std::string getInfo() const
+   {
+      std::stringstream text;
+      text<<"CbArray2D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >";
+      text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<")";
+      return text.str();
+   }
+   /*=======================================================================*/
+   void resize(const size_type& uniformDimensionSize)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1,const size_type& nx2)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->data.resize(nx1*nx2);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1, const size_type& nx2, const value_type& initVal )
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->data.resize(nx1*nx2,initVal);
+   }
+   /*=======================================================================*/
+   void clear()
+   {
+      this->nx1 = 0;
+      this->nx2 = 0;
+      this->data.clear();
+   }
+   /*=======================================================================*/
+   std::vector< value_type >& getDataVector() { return this->data; }
+   /*=======================================================================*/
+   const std::vector< value_type >& getDataVector() const { return this->data; }
+   /*=======================================================================*/
+   inline size_type getDataVectorIndex(const size_type& x1, const size_type& x2) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2)) );
+      #endif
+
+      return indexer.getIndex(x1,x2,nx1,nx2);
+   }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & data;
+   }
+#endif //CAB_RCF
+
+protected:
+   /*=======================================================================*/
+   //success -> true
+   //else    -> false
+   inline bool indicesInRange(const size_type& x1, const size_type& x2) const
+   {
+      if(   x1 < 0 || x1 >= this->nx1
+         || x2 < 0 || x2 >= this->nx2 )
+      {
+         return false;
+      }
+      return true;
+   }
+   /*=======================================================================*/
+   std::string getExceptionErrorString(const size_type& x1, const size_type& x2) const
+   {
+      std::stringstream out("index out of range - ");
+      out<<"("<<x1<<","<<x2<<") not in ("<<nx1<<","<<nx2<<")";
+      return out.str();
+   }
+   /*=======================================================================*/
+
+protected:
+   size_type    nx1;
+   size_type    nx2;
+   indexer_type indexer;
+   std::vector< value_type > data;
+};
+
+#endif //CBARRAY2D_H
diff --git a/source/VirtualFluidsCore/Basics/container/CbArray3D.h b/source/VirtualFluidsCore/Basics/container/CbArray3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..e3a172a379ccaa01a26ba06e16b9e6d18a235b67
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/CbArray3D.h
@@ -0,0 +1,479 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBARRAY3D_H
+#define CBARRAY3D_H
+
+//////////////////////////////////////////////////////////////////////////
+// 3D Array
+// die Daten werden in einem Vector gehalten
+//
+// Ver 1.2
+// Nov. 2003 muffmolch@gmx.de
+// Ver 1.3
+// Aug. 2006 - Kosmetik
+// Ver 1.4
+// Sep. 2006 - indexer eingefuehrt
+// Ver 1.5
+// Jul. 2006 - size_t + range check bei getIndex
+// Ver 1.2
+// Mrz. 2008 - typedefs, new index checks, NO_CB_RANGECHECK, no base class
+//             assigmetcomparison between Matrices with different value_type and/or index-class
+// Oct. 2008 - +isEmpty()
+//
+// Rangecheck aktiv, wenn:
+// -debug  : not defined "NO_CB_RANGECHECK"
+// -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK"
+//////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbEqual.h>
+#include <algorithm>
+#include <typeinfo>
+#include <boost/serialization/serialization.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// IndexClasses
+
+//IndexerX3X2X1:
+//                4 5 6          10 11 12
+// Array  ebene A 1 2 3  ebene B  7  8  9 -->  vector 1 2 3 4 5 6 7 8 9 10 11 12
+//x1-reihen "liegen am stueck" im speicher
+//optimaler schleifendurchlauf
+//for(alle X3)
+//  for(alle X2)
+//    for(alle X1)
+class IndexerX3X2X1// FunctorX1SortedForX1X2Plane
+{
+public:
+   typedef size_t size_type;
+public:
+   inline std::size_t getIndex(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                               , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx1 * ( nx2 * x3 + x2) + x1 ;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                                                 , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx1 * ( nx2 * x3 + x2);
+   }
+};
+
+//IndexerX1X2X3:
+//                4 5 6          10 11 12
+// Array  ebene A 1 2 3  ebene B  7  8  9 -->
+//optimaler schleifendurchlauf
+//for(alle X1)
+//  for(alle X2)
+//    for(alle X3)
+class IndexerX1X2X3 //FunctorX3SortedForX3X2Plane
+{
+public:
+   typedef size_t size_type;
+public:
+   inline std::size_t getIndex(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                               , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx3 * ( nx2 * x1 + x2) + x3 ;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                                                 , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx3 * ( nx2 * x1 + x2);
+   }
+};
+
+//IndexerX2X1X3:
+//                4 5 6          10 11 12
+// Array  ebene A 1 2 3  ebene B  7  8  9 -->  vector 1 7 2 8 3 9 4 10 5 11 6 12
+//optimaler schleifendurchlauf
+//for(alle X2)
+//  for(alle X1)
+//    for(alle X3)
+class IndexerX2X1X3
+{
+public:
+   typedef size_t size_type;
+public:
+   inline std::size_t getIndex(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                               , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx3* ( nx1 * x2 + x1) + x3 ;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3
+                                                 , const size_type& nx1, const size_type& nx2, const size_type& nx3 ) const
+   {
+      return  nx3* ( nx1 * x2 + x1);
+   }
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// CbArray3D
+template<typename T, typename IndexClass = IndexerX3X2X1>
+class CbArray3D
+{
+public:
+   typedef boost::shared_ptr< CbArray3D <T,IndexClass> > CbArray3DPtr;
+
+   typedef T                                                   value_type;
+   typedef IndexClass                                          indexer_type;
+   typedef typename IndexClass::size_type                      size_type;
+   typedef typename std::vector< value_type >::reference       reference;
+   typedef typename std::vector< value_type >::const_reference const_reference;
+   typedef typename std::vector< value_type >::pointer         pointer;
+   typedef typename std::vector< value_type >::const_pointer   const_pointer;
+
+private:
+   template< typename value_type2, typename IndexClass2 > friend class CbArray3D;
+
+public:
+   /*=======================================================================*/
+   CbArray3D()
+   {
+      this->resize(0,0,0);
+   }
+   /*=======================================================================*/
+   CbArray3D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const value_type& val)
+   {
+      this->resize(nx1,nx2,nx3,val);
+   }
+   /*=======================================================================*/
+    CbArray3D(const size_type& nx1,const size_type& nx2, const size_type& nx3)
+    {
+       this->resize(nx1,nx2,nx3);
+    }
+   /*=======================================================================*/
+   CbArray3D(const size_type& uniformDimensionSize /*nx1==nx2==nx3*/)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   //übernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird)
+   CbArray3D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2, const size_type& nx3)
+   {
+      assert( (nx1*nx2*nx3)==vec.size() );
+      this->data.swap(vec);
+      this->resize(nx1,nx2,nx3);
+   }
+   /*=======================================================================*/
+   CbArray3D(const CbArray3D& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , nx3(src.nx3)
+       , data(src.data)
+   {
+   }
+   /*=======================================================================*/
+   template< typename value_type2 >
+   CbArray3D(const CbArray3D< value_type2 >& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , nx3(src.nx3)
+   {
+      //Sourcedaten kopieren
+      this->data.resize( src.data.size() );
+      for(std::size_t i=0; i<data.size(); ++i)
+         this->data[i] = src.data[i];
+   }
+   /*=======================================================================*/
+   virtual ~CbArray3D()
+   {
+      //vector wird automatisch zerstoert
+   }
+   /*=======================================================================*/
+   CbArray3D& operator= (const CbArray3D& rhs)
+   {
+      if(this == &rhs) return *this;
+
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+      this->nx3 = rhs.nx3;
+
+      //gespeicherte Datenelemente loeschen
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+
+      //Sourcedaten kopieren
+      this->data = rhs.data;
+
+      return *this;
+   }
+   /*=======================================================================*/
+   //durch value_type2 kann man z.B. ein float array einer double array zuweisen!
+   template< typename value_type2, typename IndexClass2 >
+   CbArray3D& operator= (const CbArray3D< value_type2, IndexClass2 >& rhs)
+   {
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+      this->nx3 = rhs.nx3;
+
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+
+      //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x3=0; x3<this->nx3; x3++)
+         for(int x2=0; x2<this->nx2; x2++)
+            for(int x1=0; x1<this->nx1; x1++)
+               this->operator()(x1,x2,x3) = static_cast< value_type >( rhs.operator()(x1,x2,x3) );
+
+      return *this;
+   }
+   /*=======================================================================*/
+   bool operator== (const CbArray3D& rhs) const
+   {
+      if(this == &rhs) return true;
+
+      if(   this->nx1!=rhs.nx1
+         || this->nx2!=rhs.nx2
+         || this->nx3!=rhs.nx3
+         || this->data.size() != rhs.data.size() )
+      {
+         return false;
+      }
+
+      return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() );
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator== (const CbArray3D< value_type2, IndexClass2 >& rhs) const
+   {
+      if( this->data.size() != rhs.data.size() ) return false;
+
+      //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x3=0; x3<this->nx3; x3++)
+         for(int x2=0; x2<this->nx2; x2++)
+            for(int x1=0; x1<this->nx1; x1++)
+               if( !isUbEqual(this->operator()(x1,x2,x3), rhs.operator()(x1,x2,x3)) )
+               return false;
+
+      return true;
+   }
+   /*=======================================================================*/
+   bool operator!= (const CbArray3D& src) const
+   {
+      return !(*this==src);
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator!= (const CbArray3D< value_type2, IndexClass2 >& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   reference operator() (const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ];
+   }
+   /*=======================================================================*/
+   const_reference operator() (const size_type& x1, const size_type& x2, const size_type& x3)	const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ];
+   }
+   /*=======================================================================*/
+   pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,nx1,nx2,nx3)];
+   }
+   /*=======================================================================*/
+   const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3)  const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,nx1,nx2,nx3)];
+   }
+   /*=======================================================================*/
+   void setObject(const size_type& x1, const size_type& x2, const size_type& x3, const value_type& value)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ] = value;
+   }
+   /*=======================================================================*/
+   reference getObject(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return this->data[ indexer.getIndex(x1,x2,x3,nx1,nx2,nx3) ] ;
+   }
+   /*=======================================================================*/
+   const_reference getObject(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return (*this)(x1,x2,x3);
+   }
+   /*=======================================================================*/
+   bool      isEmpty() const { return data.empty(); }
+   size_type getNX1()  const { return this->nx1;    }
+   size_type getNX2()  const { return this->nx2;    }
+   size_type getNX3()  const { return this->nx3;    }
+   /*=======================================================================*/
+   void reset(const value_type& val)
+   {
+      std::fill( this->data.begin(), this->data.end(), val );
+   }
+   /*=======================================================================*/
+   std::string toString() const
+   {
+      std::stringstream text;
+      for(size_type x1=0; x1<this->nx1; x1++)
+      {
+      	for(size_type x2=0; x2<this->nx2; x2++)
+      	{
+         	for(size_type x3=0; x3<this->nx3; x3++)
+         	{
+            	text<<(*this)(x1,x2,x3)<<", ";
+         	}
+         	text<<std::endl;
+      	}
+      	text<<std::endl<<std::endl;
+      }
+
+      return text.str();
+   }
+   /*=======================================================================*/
+   std::string getInfo() const
+   {
+      std::stringstream text;
+      text<<"CbArray3D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >";
+      text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<", nx3="<<this->nx3<<")";
+      return text.str();
+   }
+   /*=======================================================================*/
+   void resize(const int& uniformDimensionSize)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1,const size_type& nx2, const size_type& nx3)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->nx3 = nx3;
+      this->data.resize(nx1*nx2*nx3);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1,const size_type& nx2, const size_type& nx3,const value_type& val)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->nx3 = nx3;
+      this->data.resize(nx1*nx2*nx3,val);
+   }
+   /*=======================================================================*/
+   void clear()
+   {
+      this->nx1 = 0;
+      this->nx2 = 0;
+      this->nx3 = 0;
+      this->data.clear();
+   }
+   /*=======================================================================*/
+   std::vector< value_type >& getDataVector() { return this->data; }
+   /*=======================================================================*/
+   const std::vector< value_type >& getDataVector() const { return this->data; }
+   /*=======================================================================*/
+   inline std::size_t getDataVectorIndex(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3)) );
+      #endif
+
+      return indexer.getIndex(x1,x2,x3,nx1,nx2,nx3);
+   }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & data;
+   }
+#endif //CAB_RCF
+
+
+   /*=======================================================================*/
+   //success -> true
+   //else    -> false
+   inline bool indicesInRange(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      if(   x1 < 0 || x1 >= this->nx1
+         || x2 < 0 || x2 >= this->nx2
+         || x3 < 0 || x3 >= this->nx3 )
+      {
+         return false;
+      }
+      return true;
+   }
+protected:
+   /*=======================================================================*/
+   std::string getExceptionErrorString(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      std::stringstream out("index out of range - ");
+      out<<"("<<x1<<","<<x2<<","<<x3<<") not in ("<<nx1<<","<<nx2<<","<<nx3<<")";
+      return out.str();
+   }
+   /*=======================================================================*/
+
+protected:
+   size_type    nx1;
+   size_type    nx2;
+   size_type    nx3;
+   indexer_type indexer;
+   std::vector< value_type > data;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & data;
+   }
+};
+
+#endif //CBARRAY3D_H
diff --git a/source/VirtualFluidsCore/Basics/container/CbArray4D.h b/source/VirtualFluidsCore/Basics/container/CbArray4D.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed2e6aa778efa366d182c5180c20e4e11186cbab
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/CbArray4D.h
@@ -0,0 +1,463 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBARRAY4D_H
+#define CBARRAY4D_H
+
+//////////////////////////////////////////////////////////////////////////
+// 4D Array
+// die Daten werden in einem Vector gehalten
+//
+// Ver 1.0
+// Sept. 2006 muffmolch@gmx.de
+// Ver 1.1
+// Jul. 2006 - size_t + range check bei getIndex
+// Ver 1.2
+// Mrz. 2008 - typedefs, new index checks, NO_CB_RANGECHECK, no base class
+//             assigmetcomparison between Matrices with different value_type and/or index-class
+// Oct. 2008 - +isEmpty()
+//
+// Rangecheck aktiv, wenn:
+// -debug  : not defined "NO_CB_RANGECHECK"
+// -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK"
+//////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbEqual.h>
+#include <algorithm>
+#include <typeinfo>
+#include <boost/serialization/serialization.hpp>
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// IndexClasses
+
+//IndexerX1X2X3X4:
+//x4-reihen "liegen am stueck" im speicher
+//optimaler schleifendurchlauf
+//for(alle X1)
+//  for(alle X2)
+//    for(alle X3)
+//      for(alle X4)
+class IndexerX1X2X3X4
+{
+public:
+   typedef int size_type;
+public:
+   inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4
+                            , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 )  const
+   {
+      return nx4*(nx3*(nx2*x1+ x2)+x3)+x4 ;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4
+                                               , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 )  const
+   {
+      return  nx4*(nx3*(nx2*x1+ x2)+x3);
+   }
+};
+//////////////////////////////////////////////////////////////////////////
+// IndexClasses
+
+//IndexerX4X3X2X1:
+//x1-reihen "liegen am stueck" im speicher
+//optimaler schleifendurchlauf
+//for(alle X4)
+//  for(alle X3)
+//    for(alle X2)
+//      for(alle X1)
+class IndexerX4X3X2X1
+{
+public:
+   typedef size_t size_type;
+public:
+   inline std::size_t getIndex( const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4
+      , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 )  const
+   {
+      return nx1*(nx2*(nx3*x4+ x3)+x2)+x1;
+   }
+   inline std::size_t getStartIndexOfSortedArray(  const size_type& x1 , const size_type& x2 , const size_type& x3 , const size_type& x4
+      , const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4 )  const
+   {
+      return  nx1*(nx2*(nx3*x4+ x3)+x2);
+   }
+};
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// CbArray4D
+template<typename T, typename IndexClass = IndexerX4X3X2X1>
+class CbArray4D
+{
+public:
+   typedef boost::shared_ptr< CbArray4D <T,IndexClass> > CbArray4DPtr;
+
+   typedef T                                                   value_type;
+   typedef IndexClass                                          indexer_type;
+   typedef typename IndexClass::size_type                      size_type;
+   typedef typename std::vector< value_type >::reference       reference;
+   typedef typename std::vector< value_type >::const_reference const_reference;
+   typedef typename std::vector< value_type >::pointer         pointer;
+   typedef typename std::vector< value_type >::const_pointer   const_pointer;
+
+private:
+   template< typename value_type2, typename IndexClass2 > friend class CbArray4D;
+
+public:
+   /*=======================================================================*/
+   CbArray4D()
+   {
+      this->resize(0,0,0,0);
+   }
+   /*=======================================================================*/
+   CbArray4D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4)
+   {
+      this->resize(nx1,nx2,nx3,nx4);
+   }
+   /*=======================================================================*/
+   CbArray4D(const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4, const value_type& val)
+   {
+      this->resize(nx1,nx2,nx3,nx4,val);
+   }
+   /*=======================================================================*/
+   CbArray4D(const size_type& uniformDimensionSize /*nx1=nx2=nx3=nx4*/)
+   {
+      this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize,uniformDimensionSize);
+   }
+   /*=======================================================================*/
+   //ubernimmt vector als daten vector! (erstellt KEINE kopie!!!, vec ist anschließend leer, da swap verwendet wird)
+   CbArray4D(std::vector<value_type>& vec, const size_type& nx1,const size_type& nx2, const size_type& nx3, const size_type& nx4)
+   {
+      assert( (nx1*nx2*nx3*nx4)==vec.size() );
+      this->data.swap(vec);
+      this->resize(nx1,nx2,nx3,nx4);
+   }
+   /*=======================================================================*/
+   CbArray4D(const CbArray4D& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , nx3(src.nx3)
+       , nx4(src.nx4)
+       , data(src.data)
+   {
+   }
+   /*=======================================================================*/
+   template< typename value_type2 >
+   CbArray4D(const CbArray4D< value_type2 >& src)
+      :  nx1(src.nx1)
+       , nx2(src.nx2)
+       , nx3(src.nx3)
+       , nx4(src.nx4)
+   {
+      //Sourcedaten kopieren
+      this->data.resize( src.data.size() );
+      for(std::size_t i=0; i<data.size(); ++i)
+         this->data[i] = src.data[i];
+   }
+   /*=======================================================================*/
+   virtual ~CbArray4D()
+   {
+      //vector wird automatisch zerstoert
+   }
+   /*=======================================================================*/
+   CbArray4D& operator= (const CbArray4D& rhs)
+   {
+      if(this == &rhs) return *this;
+
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+      this->nx3 = rhs.nx3;
+      this->nx4 = rhs.nx4;
+
+      //gespeicherte Datenelemente loeschen
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+
+      //Sourcedaten kopieren
+      this->data = rhs.data;
+
+      return *this;
+   }
+   /*=======================================================================*/
+   //durch value_type2 kann man z.B. ein float Array einem double Array zuweisen!
+   template< typename value_type2, typename IndexClass2 >
+   CbArray4D& operator= (const CbArray4D< value_type2, IndexClass2 >& rhs)
+   {
+      this->nx1 = rhs.nx1;
+      this->nx2 = rhs.nx2;
+      this->nx3 = rhs.nx3;
+      this->nx4 = rhs.nx4;
+
+      //gespeicherte Datenelemente loeschen
+      this->data.clear();
+      //Laenge anpassen
+      this->data.resize(rhs.data.size());
+
+      //Sourcedaten kopieren (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x1=0; x1<this->nx1; x1++)
+         for(int x2=0; x2<this->nx2; x2++)
+            for(int x3=0; x3<this->nx3; x3++)
+               for(int x4=0; x4<this->nx4; x4++)
+                  this->operator()(x1,x2,x3,x4) = static_cast< value_type >( rhs.operator()(x1,x2,x3,x4));
+
+      return *this;
+   }
+   /*=======================================================================*/
+   bool operator== (const CbArray4D& rhs) const
+   {
+      if( this == &rhs ) return true;
+
+      if(   this->nx1!=rhs.nx1
+         || this->nx2!=rhs.nx2
+         || this->nx3!=rhs.nx3
+         || this->nx4!=rhs.nx4
+         || this->data.size() != rhs.data.size() )
+      {
+         return false;
+      }
+
+      return std::equal( this->data.begin(), this->data.end(), rhs.data.begin(), UbEqual<value_type, value_type >() );
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator== (const CbArray4D< value_type2, IndexClass2 >& rhs) const
+   {
+      if( this->data.size() != rhs.data.size() ) return false;
+
+      //Sourcedaten einzeln checken (!! koennte anderen Indexer besitzen!!! -> operator() benutzen)
+      for(int x4=0; x4<this->nx4; x4++)
+         for(int x3=0; x3<this->nx3; x3++)
+            for(int x2=0; x2<this->nx2; x2++)
+             for(int x1=0; x1<this->nx1; x1++)
+               if( !isUbEqual(this->operator()(x1,x2,x3,x4), rhs.operator()(x1,x2,x3,x4)) )
+                  return false;
+
+      return true;
+   }
+   /*=======================================================================*/
+   bool operator!= (const CbArray4D& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   template< typename value_type2, typename IndexClass2 >
+   bool operator!= (const CbArray4D< value_type2, IndexClass2 >& rhs) const
+   {
+      return !(*this==rhs);
+   }
+   /*=======================================================================*/
+   reference operator() (const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   const_reference operator() (const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)	const
+   {
+      #ifdef CbArray4D_RANGECHECKING
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   const_pointer getStartAdressOfSortedArray(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)  const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return &this->data[indexer.getStartIndexOfSortedArray(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   void setObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4, const value_type& value)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)] = value;
+   }
+   /*=======================================================================*/
+   reference getObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return this->data[indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4)];
+   }
+   /*=======================================================================*/
+   const_reference getObject(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+      return (*this)(x1,x2,x3,x4,nx1,nx2,nx3,nx4);
+   }
+   /*=======================================================================*/
+   bool      isEmpty() const { return data.empty(); }
+   size_type getNX1()  const { return this->nx1;    }
+   size_type getNX2()  const { return this->nx2;    }
+   size_type getNX3()  const { return this->nx3;    }
+   size_type getNX4()  const { return this->nx4;    }
+   /*=======================================================================*/
+   void reset(const value_type& val)
+   {
+      std::fill( this->data.begin(), this->data.end(), val );
+   }
+   /*=======================================================================*/
+   std::string toString() const
+   {
+      std::stringstream text;
+      text<<std::setprecision(19);
+      for(size_type x1=0; x1<this->nx1; x1++)
+      {
+      	for(size_type x2=0; x2<this->nx2; x2++)
+      	{
+         	for(size_type x3=0; x3<this->nx3; x3++)
+         	{
+               for(size_type x4=0; x4<this->nx4; x4++)
+               {
+                 	text<<(*this)(x1,x2,x3,x4)<<", ";
+               }
+               text<<std::endl;
+         	}
+         	text<<std::endl;
+      	}
+      	text<<std::endl<<std::endl;
+      }
+
+      return text.str();
+   }
+   /*=======================================================================*/
+   std::string getInfo() const
+   {
+      std::stringstream text;
+      text<<"CbArray4D< storageType="<<typeid(T).name()<<", indexer="<<typeid(IndexClass).name()<<" >";
+      text<<"( nx1="<<this->nx1<<", nx2="<<this->nx2<<", nx3="<<this->nx3<<", nx4="<<this->nx4<<")";
+      return text.str();
+   }
+   /*=======================================================================*/
+   void resize(const size_type& uniformDimensionSize) { this->resize(uniformDimensionSize,uniformDimensionSize,uniformDimensionSize); }
+   /*=======================================================================*/
+   void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->nx3 = nx3;
+      this->nx4 = nx4;
+      this->data.resize(nx1*nx2*nx3*nx4);
+   }
+   /*=======================================================================*/
+   void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3, const size_type& nx4, const value_type& val)
+   {
+      this->nx1 = nx1;
+      this->nx2 = nx2;
+      this->nx3 = nx3;
+      this->nx4 = nx4;
+      this->data.resize(nx1*nx2*nx3*nx4,val);
+   }
+   /*=======================================================================*/
+   std::vector< value_type >& getDataVector() { return this->data; }
+   /*=======================================================================*/
+   const std::vector< value_type >& getDataVector() const { return this->data; }
+   /*=======================================================================*/
+   inline std::size_t getDataVectorIndex(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if( !this->indicesInRange(x1,x2,x3,x4) )
+            UB_THROW( UbException(UB_EXARGS,getExceptionErrorString(x1,x2,x3,x4)) );
+      #endif
+
+      return indexer.getIndex(x1,x2,x3,x4,nx1,nx2,nx3,nx4);
+   }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & nx4;
+      ar & data;
+   }
+#endif //CAB_RCF
+
+protected:
+   /*=======================================================================*/
+   //success -> true
+   //else    -> false
+   inline bool indicesInRange(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const
+   {
+      if(   x1 < 0 || x1 >= this->nx1
+         || x2 < 0 || x2 >= this->nx2
+         || x3 < 0 || x3 >= this->nx3
+         || x4 < 0 || x4 >= this->nx4 )
+      {
+         return false;
+      }
+      return true;
+   }
+   /*=======================================================================*/
+   std::string getExceptionErrorString(const size_type& x1, const size_type& x2, const size_type& x3, const size_type& x4) const
+   {
+      std::stringstream out("index out of range - ");
+      out<<"("<<x1<<","<<x2<<","<<x3<<","<<x4<<") not in ("<<nx1<<","<<nx2<<","<<nx3<<","<<nx4<<")";
+      return out.str();
+   }
+   /*=======================================================================*/
+
+protected:
+   size_type    nx1;
+   size_type    nx2;
+   size_type    nx3;
+   size_type    nx4;
+   indexer_type indexer;
+   std::vector< value_type > data;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & nx4;
+      ar & data;
+   }
+};
+
+#endif //CBARRAY4D_H
diff --git a/source/VirtualFluidsCore/Basics/container/CbVector.h b/source/VirtualFluidsCore/Basics/container/CbVector.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b16e077308c2773a71530845ed5f98c6243144a
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/CbVector.h
@@ -0,0 +1,365 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBVECTOR_H
+#define CBVECTOR_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+   #include <RCF/ByteBuffer.hpp>
+#endif
+
+#include <vector>
+#include <algorithm> //for std::swap
+#include <typeinfo>  //for typeid
+#include <memory>    //for memcopy
+
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbEqual.h>
+
+/*=========================================================================*/
+/*  CbVector                                                               */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+@version 1.1 - 09.02.08
+@version 1.2 - 23.04.08 - swap added
+@version 1.3 - 08.05.08 - boosting up serialization performance!
+*/
+
+/*
+usage: ...
+Da es Voraussetzun bei doeser Klasse war, dass lediglich der Typ als
+template-parameter miteingeht, muss der allcocator eine abstrakte klasse sein
+ansonsten hätte sich hier der allokator als zweites argument
+wie beim STL vector angeboten, womit man auch keinen pointer speichern muesste.
+Im letzteren Fall würde aber jeweils ein bestimmeter Klassentyp in Abhaengigkeit
+des allokators zur compilezeit erzeugt. Problem wir wollen ein und denselben
+typ benutzen und nur der allokator innerhalb der klasse soll sich unterscheiden
+//
+// Rangecheck aktiv, wenn:
+// -debug  : not defined "NO_CB_RANGECHECK"
+// -release: not defined "NO_CB_RANGECHECK" && defined "CB_RANGECHECK"
+*/
+
+template< typename T > class CbVectorAllocator;
+template< typename T > class CbVectorAllocatorStd;
+
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+class CbVector
+{
+public:
+   typedef T           value_type;
+   typedef value_type* pointer;
+   typedef std::size_t size_type;
+
+   friend class CbVectorAllocator<value_type>; //um auf ptrData und dataSize zugreifen zu koennen!
+
+public:
+   /*==========================================================*/
+   CbVector( CbVectorAllocator<value_type>* const& allocator = new CbVectorAllocatorStd<value_type> )
+      :  ptrData(NULL)
+       , dataSize(0)
+       , allocator(allocator)
+   {
+      this->allocator->alloc(*this,0,value_type());
+   }
+   /*==========================================================*/
+   CbVector( const size_type size, CbVectorAllocator<value_type>* const& allocator = new CbVectorAllocatorStd<value_type>, const value_type& value=value_type() )
+      :  ptrData(NULL)
+       , dataSize(0)
+       , allocator(allocator)
+   {
+      this->allocator->alloc(*this,size,value);
+   }
+   /*==========================================================*/
+   virtual ~CbVector()
+   {
+      if(allocator)
+      {
+         this->allocator->dealloc(*this);
+         delete allocator;
+         allocator=NULL;
+      }
+   }
+   /*=======================================================================*/
+   CbVector& operator= (const CbVector& src)
+   {
+      if(this == &src) return *this;
+
+      //gespeicherte Datenelemente loeschen
+      //Laenge anpassen
+      this->allocator->resize(*this, src.size());
+
+      //gespeicherte Datenelemente kopieren
+      if( !src.empty() ) 
+      {
+         memcpy( (char*)ptrData, (char*)&src[0], src.size()*sizeof(value_type) ); 
+         //for(size_type i=0; i<src.size(); i++)
+         //   (*this)[i] = src[i];
+      }
+
+      return *this;
+   }
+   /*=======================================================================*/
+   CbVector& operator= (const std::vector< value_type >& src)
+   {
+      //gespeicherte Datenelemente loeschen
+      //Laenge anpassen
+      this->allocator->resize(*this, src.size());
+
+      //gespeicherte Datenelemente kopieren
+      if( !src.empty() ) 
+      {
+         memcpy( (char*)ptrData, (char*)&src[0], src.size()*sizeof(value_type) ); 
+         //for(size_type i=0; i<src.size(); i++)
+         //   (*this)[i] = src[i];
+      }
+      
+      return *this;
+   }
+   /*=======================================================================*/
+   bool operator== (const CbVector& rhs) const
+   {
+      if( this           == &rhs         ) return true;
+      if( this->dataSize != rhs.dataSize ) return false;
+
+      for(size_type i=0; i<rhs.size(); i++)
+         if( !isUbEqual( this->operator[](i), rhs.operator[](i) ) )
+            return false;
+
+      return true;
+   }
+   /*==========================================================*/
+   void setAllocator( CbVectorAllocator<value_type>* const& allocator )
+   {
+      if(this->allocator)
+      {
+         if(this->allocator==allocator) return;
+         this->allocator->dealloc(*this);
+         delete this->allocator;
+      }
+      this->allocator = allocator;
+      this->allocator->alloc(*this,0);
+   }
+   /*==========================================================*/
+   size_type size() const { return dataSize; }
+   /*==========================================================*/
+   bool empty() const { return dataSize==0; }
+   /*==========================================================*/
+   bool resize(const size_type& dataSize)
+   {
+      return allocator->resize(*this, dataSize);
+   }
+   /*==========================================================*/
+   bool resize(const size_type& dataSize, const value_type& value)
+   {
+      return allocator->resize(*this, dataSize, value);
+   }
+   /*==========================================================*/
+   void swap(CbVector& rhs)
+   {
+      if( this == &rhs ) return;
+
+      std::swap( this->ptrData  , rhs.ptrData   );
+      std::swap( this->dataSize , rhs.dataSize  );
+      std::swap( this->allocator, rhs.allocator );
+   }
+   /*==========================================================*/
+   value_type& operator[](const size_type& i)
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if(i>=dataSize) 
+            UB_THROW( UbException(UB_EXARGS,"T="+(std::string)typeid(*this).name()+UbSystem::toString(i)+" out of range (size="+UbSystem::toString(dataSize)+")") );
+      #endif // _DEBUG
+
+      return ptrData[i];
+   }
+   /*==========================================================*/
+   const value_type& operator[](const size_type& i) const
+   {
+      #if !defined(NO_CB_RANGECHECK) && ( defined(_DEBUG) || defined(CB_RANGECHECK) )
+         if(i>=dataSize) 
+            UB_THROW( UbException(UB_EXARGS,"T="+(std::string)typeid(*this).name()+UbSystem::toString(i)+" out of range (size="+UbSystem::toString(dataSize)+")") );
+      #endif // _DEBUG
+
+      return ptrData[i];
+   }
+   /*==========================================================*/
+   CbVectorAllocator<value_type>* getAllocator() const { return allocator; }
+   /*==========================================================*/
+   #ifdef CAB_RCF
+      template<typename Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         if( ArchiveTools::isWriting(ar) )
+         {
+            ar & allocator;
+            ar & dataSize; //!!!erst hier
+
+            //old:
+            //for(size_type i=0; i<dataSize; i++)
+            // ar & ptrData[i];
+
+            //new and boosting to the sky:
+            RCF::ByteBuffer byteBuffer( (char*) &ptrData[0], dataSize*sizeof(value_type) );
+            ar & byteBuffer;
+         }
+         else
+         {
+            CbVectorAllocator<value_type>* tmpCbVectorAllocator(NULL);
+            size_type tmpInteger;
+            ar & tmpCbVectorAllocator;
+            ar & tmpInteger;
+            this->setAllocator(tmpCbVectorAllocator);
+            allocator->resize(*this,tmpInteger);
+
+            //old:
+            //for(size_type i=0; i<dataSize; i++)
+            // ar & ptrData[i];
+
+            //new and boosting to the sky:
+            RCF::ByteBuffer byteBuffer;
+            ar & byteBuffer;
+            memcpy( (char*)ptrData, byteBuffer.getPtr(), byteBuffer.getLength() ); 
+         }
+      }
+   #endif //CAB_RCF
+
+private:
+   value_type* ptrData;
+   size_type   dataSize;
+   CbVectorAllocator<value_type>* allocator;
+   CbVector<value_type>(const CbVector<value_type>& src);
+   //CbVector<value_type>& operator=(const CbVector<value_type>& src);
+};
+
+//////////////////////////////////////////////////////////////////////////
+// CbVectorAllocator-Interface
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+class CbVectorAllocator
+{
+public:
+   typedef typename CbVector<T>::value_type          value_type;
+   typedef typename CbVector<value_type>::size_type  size_type;
+
+public:
+   CbVectorAllocator() {}
+   virtual ~CbVectorAllocator() {}
+
+   virtual bool alloc(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type()) = 0;
+   virtual bool resize(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type()) = 0;
+   virtual bool dealloc(CbVector< value_type >& vec) = 0;
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+   }
+#endif //CAB_RCF
+
+protected:
+   //folgende Methoden ersparen eine friend Deklaierung aller moeglichen Allocatoren
+   //denn durch diese beiden Methoden haben sie exklusive Zugriffsrechte!
+   //**********************************************************************************//
+   inline value_type*& ptrDataOf( CbVector< value_type >& vec )
+   {
+      if( vec.getAllocator()!=this ) UB_THROW( UbException(UB_EXARGS,"allocator is not member of vec!") );
+      return vec.ptrData;
+   }
+   //**********************************************************************************//
+   inline size_type& dataSizeOf( CbVector< value_type >& vec )
+   {
+      if( vec.getAllocator()!=this ) UB_THROW( UbException(UB_EXARGS,"allocator is not member of vec!") );
+      return vec.dataSize;
+   }
+};
+
+#ifdef RCF_USE_SF_SERIALIZATION
+SF_NO_CTOR(CbVectorAllocator<double>);
+SF_NO_CTOR(CbVectorAllocator<float>);
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+//////////////////////////////////////////////////////////////////////////
+// CbVectorAllocatorStd
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+class CbVectorAllocatorStd : public CbVectorAllocator<T>
+{
+public:
+   //typedefs wiederholen, da Basisklasse = template -> "Dependent-Base"-Problem
+   typedef typename CbVector<T>::value_type          value_type;
+   typedef typename CbVector<value_type>::size_type  size_type;
+
+public:
+   CbVectorAllocatorStd() : CbVectorAllocator<value_type>()
+   {
+
+   }
+   /*==========================================================*/
+   bool alloc(CbVector< value_type >& src, const size_type& dataSize, const value_type& value=value_type())
+   {
+      return this->resize(src,dataSize,value);
+   }
+   /*==========================================================*/
+   bool resize(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type())
+   {
+      if( CbVectorAllocatorStd< value_type >::dataSizeOf(vec) == dataSize) return false;
+
+      //new array
+      value_type* new_data = new value_type[dataSize];
+      //copy existing data to array
+      if( this->ptrDataOf(vec) )
+      {
+         for(size_type i=0; (i<vec.size() && i<dataSize); ++i) new_data[i] = CbVectorAllocatorStd< value_type >::ptrDataOf(vec)[i];
+         delete[] this->ptrDataOf(vec);
+      }
+      this->ptrDataOf(vec) = new_data;
+      //new value for new items
+      for(size_type i=this->dataSizeOf(vec); i<dataSize; ++i) this->ptrDataOf(vec)[i] = value;
+      //assign new dataSize
+      this->dataSizeOf(vec) = dataSize;
+
+      return true;
+   }
+   /*==========================================================*/
+   bool dealloc(CbVector< value_type >& vec)
+   {
+      if( this->ptrDataOf(vec) )
+      {
+         delete[] this->ptrDataOf(vec);
+         this->ptrDataOf(vec) = NULL;
+      }
+      this->dataSizeOf(vec) = 0;
+      return true;
+   }
+   /*==========================================================*/
+   #ifdef CAB_RCF
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         serializeParent< CbVectorAllocator<value_type> >(ar, *this);
+      }
+   #endif //CAB_RCF
+
+private:
+};
+
+
+#ifdef RCF_USE_SF_SERIALIZATION
+   UB_AUTO_RUN_NAMED(   SF::registerType< CbVectorAllocatorStd<double> >(" CbVectorAllocatorStd<double> ")       , SF_CbVectorAllocatorStd_double );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< CbVectorAllocator<double>, CbVectorAllocatorStd<double> >() ), SF_CbVectorAllocatorStd_double_BD1 );
+
+   UB_AUTO_RUN_NAMED(   SF::registerType< CbVectorAllocatorStd<float> >(" CbVectorAllocatorStd<float> "  )       , SF_CbVectorAllocatorStd_float  );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< CbVectorAllocator<float> , CbVectorAllocatorStd<float> >()  ), SF_CbVectorAllocatorStd_float_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //CBVECTOR_H
diff --git a/source/VirtualFluidsCore/Basics/container/CbVectorPool.h b/source/VirtualFluidsCore/Basics/container/CbVectorPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..000fe51593997759bee3446501750eb2eb87db8c
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/CbVectorPool.h
@@ -0,0 +1,465 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef CBVECTORPOOL_H
+#define CBVECTORPOOL_H
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <limits>
+#include <typeinfo>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/container/CbVector.h>
+
+//#include "MPICommunicator.h"
+//
+//#include <execinfo.h>
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <unistd.h>
+
+/*=========================================================================*/
+/*  CbVectorPool                                                               */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+@version 1.1 - 09.02.08
+*/
+
+/*
+Durch Verwendung eines CbVectors in Verbindung mit einem CbVectorAllocatorPool
+wird der Datenvector nicht direkt im CbVector gehalten, sondern ist ein Teil
+des Datenvectors des Übergabe-CbVectorPools.
+Die Methoden der von CbVectors funktionieren fehlerfrei
+Es mss einem jedoch bewußt sein, dass die "resize"-Methoden länger benötigen, da
+u.U. viele Elemente im Speicher verschoeben werden muessen.
+Der Poolvector enthaelt KEINE gaps, so dass er z.B. gut zur Übertragung via MPI
+geeignet ist...
+
+Verhaltensweise bei Zerstören des Pools:
+wird der Pool zerstört bevor man die CbVectoren zerstört, so wird beim nächsten
+Datenzugriffsversuch eine entsprechende Exception geworfen, denn alle DatenElemente
+des CbVEctors werden restet und der Pool dort zu NULL gesetzt.
+
+Verhaltensweise bei Zerstören eines CbVectors:
+hier ganz normal der Datenspeicher wieder freigegen und der Poolvektor verkürzt
+*/
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+
+template<typename T> class CbVectorAllocatorPool;
+
+/*==================================================================*/
+template<typename T>
+class CbVectorPool
+{
+public:
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned int CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+public:
+   //////////////////////////////////////////////////////////////////////////
+   CbVectorPool( const size_type& startPoolSize = 20000) //startPoolSize*sizeof(T)/1024/1024 [MB]
+      :  poolStartAdress(NULL)
+       , nextCbVectorStartIndexInPool(0)
+       , nextCbVectorKey(0)
+   {
+      pool.reserve(startPoolSize);
+   }
+   /*==================================================================*/
+   virtual ~CbVectorPool()
+   {
+      //hier werden lediglich ihre datenvektoren "resetet"
+      for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+      {
+         CbVector< value_type >& vec = *it->second;
+         CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+         if(allocator.ptrVectorPool != this) UB_THROW( UbException(UB_EXARGS,"CbVectorAllocator is part of different Pool") );
+
+         //allocator daten reseten
+         allocator.ptrVectorPool    = NULL;
+         allocator.key              = 0;
+         allocator.startIndexInPool = 0;
+
+         //Datenzeiger/-groessen reseten
+         allocator.ptrDataOf(vec)  = NULL;
+         allocator.dataSizeOf(vec) = 0;
+      }
+   }
+   /*==========================================================*/
+   CbVectorKey getNextCbVectorKey() const
+   {
+      return this->nextCbVectorKey;
+   }
+   /*==================================================================*/
+   bool allocVectorData(CbVector<value_type>& vec, const size_type& dataSize, const value_type& value=value_type() )
+   {
+      //pool-allocator holen
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+      if(allocator.ptrVectorPool != this) UB_THROW( UbException(UB_EXARGS,"CbVectorAllocator is part of different Pool") );
+
+      //alloc nur wenn cbVector noch kein Element von Pool!
+      if( cbVectorMap.find(allocator.key)==cbVectorMap.end()   )
+      {
+         return this->allocData(allocator, vec, dataSize, value );
+      }
+
+      UB_THROW( UbException(UB_EXARGS,"vector-key="+UbSystem::toString(allocator.key)+" bereits vergeben!") );
+   }
+   /*==================================================================*/
+   bool resizeVectorData(CbVector<value_type>& vec, const size_type& dataSize, const value_type& value=value_type() )
+   {
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+      if(allocator.ptrVectorPool != this) UB_THROW( UbException(UB_EXARGS,"CbVectorAllocator is part of different Pool") );
+
+      //cbVector noch nicht in map?
+      CbVectorMapIter pos = cbVectorMap.find(allocator.key);
+
+      if( pos!=cbVectorMap.end()  ) //cbVector vorhanden
+      {
+         //wenn bei alloc keine Laenge zugewiesen wurde, so erfolgt das nun
+         if( allocator.startIndexInPool==0 && allocator.ptrDataOf(vec)==NULL )
+            return this->allocData(allocator, vec, dataSize, value ) ;
+         else
+            return this->resizeData(allocator, vec, dataSize, value );
+      }
+
+      UB_THROW( UbException(UB_EXARGS,"vector gehoert laut allocator zum pool aber den key gibt s nicht... wie kann das sein?") );
+   }
+   /*==================================================================*/
+   bool deallocVectorData(CbVector<value_type>& vec)
+   {
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+      if(allocator.ptrVectorPool != this) UB_THROW( UbException(UB_EXARGS,"CbVectorAllocator is part of different Pool") );
+
+      //nur wenn vector auch teil des
+      if( cbVectorMap.erase(allocator.key) > 0 )
+      {
+         if( this->resizeData(allocator,vec,0,0) )
+         {
+            allocator.ptrVectorPool    = NULL;
+            allocator.key              = 0;
+            allocator.startIndexInPool = 0;
+
+            //das Datenzeiger/-groessen reseten wird bereits in resize durchgefuehrt
+            return true;
+         }
+         else UB_THROW( UbException(UB_EXARGS,"unknown error") );
+      }
+
+      
+      //CommunicatorPtr comm = MPICommunicator::getInstance();
+      //int myid = comm->getProcessID();
+
+//      // Get the name of the processor
+//      char machinename[MPI_MAX_PROCESSOR_NAME];
+//      int name_len;
+//      MPI_Get_processor_name(machinename, &name_len);
+//      UBLOG(logINFO, "PID = " << myid << " host name: " << machinename);
+//
+//      int j, nptrs;
+//#define SIZE 100
+//      void *buffer[100];
+//      char **strings;
+//
+//      nptrs = backtrace(buffer, SIZE);
+//      printf("backtrace() returned %d addresses\n", nptrs);
+//
+//      /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
+//      would produce similar output to the following: */
+//
+//      strings = backtrace_symbols(buffer, nptrs);
+//      if (strings == NULL)
+//      {
+//         perror("backtrace_symbols");
+//         exit(EXIT_FAILURE);
+//      }
+//
+//      for (j = 0; j < nptrs; j++)
+//         printf("%s\n", strings[j]);
+//
+//      free(strings);
+
+      UB_THROW(UbException(UB_EXARGS, "vector gehoert laut allocator zum pool aber den key gibt s nicht... wie kann das sein?"));
+   }
+   /*==================================================================*/
+   friend std::ostream& operator<<(std::ostream& os, const CbVectorPool& cbPool)
+   {
+      os<<"map"<<std::endl;
+      for(CbVectorMapIter pos=cbPool.cbVectorMap.begin(); pos!=cbPool.cbVectorMap.end(); ++pos)
+      {
+         CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool<value_type>& >(*pos->second->getAllocator());
+         os<<"vector-size="<<pos->second->size()<<"vector-Adress="<<tmpAllocator->ptrDataOf(*pos->second)<<", allocator(key="<<tmpAllocator.key<<", startIndex="<<tmpAllocator.startIndexInPool<<")"<<std::endl;
+         for(size_type i=0; i<pos->second->size(); i++) os<<(*pos->second)[i]<<","; 
+         os<<std::endl;
+      }
+      os<<"pool"<<std::endl;
+      for(size_type i=0; i<cbPool.pool.size(); i++)
+            os<<cbPool.pool[i]<<","; os<<std::endl;
+
+      return os;
+   }
+   /*==================================================================*/
+   typename CbVectorMap::size_type getNofStoredVectors() const
+   {
+      return this->cbVectorMap.size();
+   }
+   /*==================================================================*/
+   typename Pool::size_type getPoolSize() const
+   {
+      return this->pool.size();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   bool consistencyCheck()
+   {
+      std::vector<int> pool2(pool.size(),0);
+      for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+      {
+         CbVector< value_type >& tmpVec = *it->second;
+         CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool<value_type>& >(*tmpVec.getAllocator());
+         for(size_type i=tmpAllocator.startIndexInPool; i<tmpAllocator.startIndexInPool+tmpVec.size(); ++i)
+         {
+            pool2.at(i)++;
+         }
+      }
+      for( size_type i=0; i<pool2.size(); ++i )
+      {
+         if(pool2.at(i) > 1 ) { UBLOG(logERROR,UB_FUNCTION<<" - test failed typo 1"); return false; }
+         if(pool2.at(i) < 1 ) { UBLOG(logERROR,UB_FUNCTION<<" - test failed typo 2"); return false; }
+      }
+      return true;
+   }
+protected:
+   /*==================================================================*/
+   inline bool allocData(CbVectorAllocatorPool< value_type >& allocator, CbVector< value_type >& vec, const size_type& dataSize, const value_type& value )
+   {
+      //safety checks
+      if(    allocator.startIndexInPool!=0
+          || allocator.ptrDataOf(vec)!=NULL
+          || allocator.dataSizeOf(vec)!=0   )
+      {
+         UB_THROW( UbException(UB_EXARGS,"zu allokierender vector ist nicht ganz sauber!!") );
+      }
+
+      //poolVector vergroessern
+      if( dataSize>0 )
+      {
+         pool.resize( pool.size() + dataSize, value );
+
+         //Zeiger der vorhandenen CbVectoren neu setzen, wenn Pool im Speicher verschoben wurde
+         if( poolStartAdress != &pool.front() )
+         {
+            poolStartAdress = &pool.front();
+            for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+            {
+               CbVector< value_type >& tmpVec = *it->second;
+               CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*tmpVec.getAllocator());
+
+               if( !tmpAllocator.ptrDataOf(tmpVec) ) continue; //Fall: CbVector hat noch keinen Datenbereich (data zeigt auf NULL)
+               tmpAllocator.ptrDataOf(tmpVec) = &pool[ tmpAllocator.startIndexInPool];
+            }
+            //std::cout<<"CbVectorPoolMpi::allocVectorData vector wurde im speicher verschoben - adressen angepasst!!!"<<std::endl;
+         }
+
+         //aktuellem element adresse zuweisen (wurde evtl schon inder schleife zuvor gemacht)
+         allocator.ptrDataOf(vec) = &pool.at(nextCbVectorStartIndexInPool);
+         allocator.startIndexInPool = nextCbVectorStartIndexInPool;
+
+         //neuen StartIndex fuer naechstes Element berechnen
+         nextCbVectorStartIndexInPool += dataSize;
+         if(nextCbVectorStartIndexInPool!=pool.size())
+            UB_THROW( UbException(UB_EXARGS,"index Problem... Annahme falsch?") );
+      }
+
+      //vector zu map hinzufügen (speicher wird dann anschliessend zugwiesen)
+      cbVectorMap.insert( std::make_pair( allocator.key, &vec ) ); // ist angeblich performanter als  cbVectorMap[ allocator.key ] = cbVector; //aus Effective STL von Scott Meyer
+      allocator.dataSizeOf(vec) = dataSize;
+
+      //dummDoof nextKey-Generung...
+      if( allocator.key >= this->nextCbVectorKey ) this->nextCbVectorKey = allocator.key + 1;
+
+      return true;
+   }
+   /*==========================================================*/
+   bool resizeData(CbVectorAllocatorPool< value_type >& allocator, CbVector<value_type>& vec, const size_type& dataSize, const value_type& value )
+   {
+      //datenvector verlaengern/-kuerzen
+      typename Pool::iterator startPos = pool.begin()+allocator.startIndexInPool; //startPosition der cbVector-Daten im Pool
+      if( vec.size() > dataSize ) pool.erase( startPos+dataSize, startPos+vec.size());
+      else                        pool.insert( startPos+vec.size(), dataSize-vec.size(), value );
+
+      //////////////////////////////////////////////////////////////////////////
+      //adressen und laengen der einzelnen vectoren anpassen
+      if( !pool.empty() )
+      {
+         bool poolMoved   = ( poolStartAdress != &pool.front() );
+         poolStartAdress  = &pool.front();
+
+         for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+         {
+            CbVector< value_type >& tmpVec = *it->second;
+
+            if( tmpVec.size()>0 )
+            {
+               CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool<value_type>& >(*tmpVec.getAllocator());
+               //liegt CbVector VOR verändertem CbVector?
+               if( tmpAllocator.startIndexInPool <= allocator.startIndexInPool ) //ja: anpassung NUR wenn pool verschoben wurde!
+               {
+                  if(poolMoved && tmpVec.size()>0 ) tmpAllocator.ptrDataOf(tmpVec) = &pool[ tmpAllocator.startIndexInPool];
+               }
+               else //nein: -> Adresse + Index MUSS immer angepasst werden
+               {
+                  tmpAllocator.startIndexInPool += dataSize-vec.size();
+                  tmpAllocator.ptrDataOf(tmpVec) = &pool[ tmpAllocator.startIndexInPool ];
+               }
+            }
+         }
+      }
+      else //Sonderfall: alle Elemente haben Laenge 0 -> kein pool -> alle Feld-Adressen auf NULL setzen!
+      {
+         poolStartAdress = NULL;
+         for(CbVectorMapIter it=cbVectorMap.begin(); it!=cbVectorMap.end(); ++it)
+         {
+            CbVector< value_type >& tmpVec = *it->second;
+            CbVectorAllocatorPool< value_type >& tmpAllocator = dynamic_cast< CbVectorAllocatorPool<value_type>& >(*tmpVec.getAllocator());
+            tmpAllocator.startIndexInPool = 0;
+         }
+
+      }
+
+      //restliche Daten von cbVector + allocator aktualisieren
+      allocator.dataSizeOf(vec) = dataSize;
+      if(dataSize==0)
+      {
+         allocator.ptrDataOf(vec)   = NULL;
+         allocator.startIndexInPool = 0;
+      }
+
+      nextCbVectorStartIndexInPool = pool.size();
+
+      return true;
+   }
+
+protected:
+   /*==================================================================*/
+   void getCbVectorData(const CbVector< value_type >& vec, CbVectorKey& vectorKey, size_type& startIndexInPool, size_type& dataSize )
+   {
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+
+      startIndexInPool  = allocator.startIndexInPool;
+      vectorKey         = allocator.key;
+      dataSize          = vec.size();
+   }
+   /*==================================================================*/
+   void setCbVectorData(CbVector< value_type >& vec, const CbVectorKey& vectorKey, const size_type& startIndexInPool, const size_type& dataSize )
+   {
+      CbVectorAllocatorPool< value_type >& allocator = dynamic_cast< CbVectorAllocatorPool< value_type >& >(*vec.getAllocator() );
+
+      allocator.startIndexInPool = startIndexInPool;
+      allocator.key              = vectorKey;
+      allocator.dataSizeOf(vec)  = dataSize;
+      allocator.ptrDataOf(vec)   = &this->pool[ startIndexInPool ];
+   }
+   /*==================================================================*/
+
+   CbVectorMap                cbVectorMap;                      //informationsmap fuer MPIData und zugewiesener vector
+
+   Pool                       pool;                             //globaler Datenvector
+   typename Pool::pointer     poolStartAdress;                  //StartAdresse des aktuellen Datenvektors
+   typename Pool::size_type   nextCbVectorStartIndexInPool;     //StartIndex fuer den naechsten CbVector
+
+   //key - erstmal dummdoof
+   CbVectorKey nextCbVectorKey;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//  CbVectorAllocatorPool
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+class CbVectorAllocatorPool : public CbVectorAllocator<T>
+{
+public:
+   //typedefs wiederholen, da Basisklasse = template -> "Dependent-Base"-Problem
+   typedef typename CbVector<T>::value_type          value_type;
+   typedef typename CbVector<value_type>::size_type  size_type;
+
+   friend class CbVectorPool< value_type >;
+
+public:
+   /*==========================================================*/
+   CbVectorAllocatorPool(const typename CbVectorPool< value_type >::CbVectorKey& key, CbVectorPool<value_type>* const& ptrVectorPool)
+      :  CbVectorAllocator<value_type>()
+       , key(key)
+       , startIndexInPool(0)
+       , ptrVectorPool(ptrVectorPool)
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"ptrVectorPool==NULL") );
+   }
+   /*==========================================================*/
+   //hier wird der key automatisch erzeugt!
+   CbVectorAllocatorPool(CbVectorPool<value_type>* const& ptrVectorPool)
+      :  CbVectorAllocator<value_type>()
+       , startIndexInPool(0)
+       , ptrVectorPool(ptrVectorPool)
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"ptrVectorPool==NULL") );
+      key = ptrVectorPool->getNextCbVectorKey();
+   }
+   /*==========================================================*/
+   bool alloc(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type())
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"vectorPool seems to be destroyed, ptrVectorPool==NULL") );
+      return ptrVectorPool->allocVectorData(vec, dataSize, value);
+   }
+   /*==========================================================*/
+   bool resize(CbVector< value_type >& vec, const size_type& dataSize, const value_type& value=value_type())
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"vectorPool seems to be destroyed, ptrVectorPool==NULL") );
+      return ptrVectorPool->resizeVectorData(vec, dataSize, value);
+   }
+   /*==========================================================*/
+   bool dealloc(CbVector< value_type >& vec)
+   {
+      if(ptrVectorPool) return this->ptrVectorPool->deallocVectorData(vec);
+      //wenn kein ptrVectorPool -> wurde bereits deallokiert
+      return true;
+   }
+   /*==========================================================*/
+   const CbVectorPool< value_type >& getCbVectorPool()
+   {
+      if(!ptrVectorPool) UB_THROW( UbException(UB_EXARGS,"vectorPool seems to be destroyed, ptrVectorPool==NULL") );
+      return *ptrVectorPool;
+   }
+   /*==========================================================*/
+
+private:
+   typename CbVectorPool< value_type >::CbVectorKey     key;
+   typename CbVectorPool< value_type >::Pool::size_type startIndexInPool;
+
+   CbVectorPool< value_type >* ptrVectorPool;
+
+   CbVectorAllocatorPool( const CbVectorAllocatorPool& );                 //no copy allowed
+   const CbVectorAllocatorPool& operator=( const CbVectorAllocatorPool& );//no copy allowed
+};
+
+
+#endif //CBVECTORPOOL_H
diff --git a/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/CMakeLists.txt b/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6cf6d2526048573fa4bbf1426f28279b0dc46bb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(CbVectorPoolTests)
+
+#################################################################
+# MACHINE_SPECIFIC CMAKE_CONFIG_FILE
+#################################################################
+INCLUDE("../../../../../../../CMake/CMakeCABMacros.txt")
+
+#################################################################
+###   PACKAGES                                               ###
+#################################################################
+INCLUDE(${SOURCE_ROOT}/basics/container/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/memory/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/objects/CMakePackage.txt)
+
+#################################################################
+###   OWN DEFINES 						###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${SOURCE_ROOT}/basics/container/examples/CbVectorPool/*.h
+                         ${SOURCE_ROOT}/basics/container/examples/CbVectorPool/*.cpp ) 
+
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(z_specific FILES ${SPECIFIC_FILES})
+
+#################################################################
+###  PROJECT ERSTELLEN                                        ###
+#################################################################
+CREATE_CAB_PROJECT()
diff --git a/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/functions.h b/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/functions.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9e376731e5581c75efbfa093122afc42f2405ad
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/functions.h
@@ -0,0 +1,190 @@
+#include <iostream>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string>
+#include <fstream>
+
+#include <basics/utilities/UbTuple.h>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <basics/utilities/UbTiming.h>
+
+#include <basics/memory/MbSmartPtr.h>
+
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+
+typedef long double value_type;
+typedef MbSmartPtr<CbVector< value_type > > CbVectorPtr;
+typedef MbSmartPtr<vector< value_type > >   StlVectorPtr;
+
+/*==========================================================*/
+template<typename T>
+inline void setValues(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec)
+{
+   if(stlvec.size() != cbvec.size() || stlvec.size() != cbpoolvec.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvec.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvec.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvec.size()<<endl;
+      throw UB_THROW( UbException("setValues - sizeCheck failed") );
+   }
+   static value_type stlVal    = 1;
+   static value_type cbVal     = 1;
+   static value_type cbPoolVal = 1;
+
+   for(size_t i=0; i<cbvec.size(); i++) stlvec[i]    = stlVal   ++;
+   for(size_t i=0; i<cbvec.size(); i++) cbvec[i]     = cbVal    ++;
+   for(size_t i=0; i<cbvec.size(); i++) cbpoolvec[i] = cbPoolVal++;
+}
+/*==========================================================*/
+template<typename T>
+inline void setValues(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      throw UB_THROW( UbException("setValues glob - sizeCheck failed") );
+   }
+
+   for(size_t i=0; i<cbvecs.size(); i++)
+      setValues(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i]);
+}
+/*==========================================================*/
+template<typename T>
+inline void resize(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec, std::size_t size, const T& val)
+{
+   stlvec.resize(size,val);
+   cbvec.resize(size,val);
+   cbpoolvec.resize(size,val);
+}
+/*==========================================================*/
+template<typename T>
+inline void resize(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, std::size_t size, const value_type& val, bool timed=false)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      throw UB_THROW( UbException("resize glob - sizeCheck failed") );
+   }
+
+   if(timed)
+   {
+      UbTimer timer;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) stlvecs[i]->resize(size,val);    if(timed) cout<<"stl-resize    in "<<timer.stop()<<"s"<<endl;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) cbvecs[i]->resize(size,val);     if(timed) cout<<"cbStd-resize  in "<<timer.stop()<<"s"<<endl;
+      timer.start(); for(size_t i=0; i<cbvecs.size(); i++) cbpoolvecs[i]->resize(size,val); if(timed) cout<<"cbPool-resize in "<<timer.stop()<<"s"<<endl;
+   }
+   else
+   {
+      for(size_t i=0; i<cbvecs.size(); i++)
+         resize(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i],size,val);
+   }
+}
+/*==========================================================*/
+inline void createVecs(size_t number, int size,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, CbVectorPool<value_type>*& pool, bool timed=false)
+{
+   UbTimer timer;
+   timer.start(); for(size_t i=0; i<number; i++) stlvecs.push_back(StlVectorPtr(new vector<value_type>(size)));                                                  if(timed) cout<<"stl-createVecs    in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbvecs.push_back(CbVectorPtr(new CbVector<value_type>(size)));                                                  if(timed) cout<<"cbStd-createVecs  in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbpoolvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorPool<value_type>(pool))));  if(timed) cout<<"cbPool-createVecs in "<<timer.stop()<<"s"<<endl;
+
+   for(size_t i=0; i<cbvecs.size(); i++) setValues(*stlvecs.back(),*cbvecs.back(),*cbpoolvecs.back());
+}
+/*==========================================================*/
+inline void createVecs(size_t number, size_t size, const value_type& val,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs, CbVectorPool<value_type>*& pool, bool timed=false)
+{
+   UbTimer timer;
+   timer.start(); for(size_t i=0; i<number; i++) stlvecs.push_back(StlVectorPtr(new vector<value_type>(size,val)));                                                  if(timed) cout<<"stl-createVecs    in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorStd<value_type>(),val)));           if(timed) cout<<"cbStd-createVecs  in "<<timer.stop()<<"s"<<endl;
+   timer.start(); for(size_t i=0; i<number; i++) cbpoolvecs.push_back(CbVectorPtr(new CbVector<value_type>(size,new CbVectorAllocatorPool<value_type>(pool),val)));  if(timed) cout<<"cbPool-createVecs in "<<timer.stop()<<"s"<<endl;
+}
+/*==========================================================*/
+template<typename T>
+inline void equalCheck(vector<T>& stlvec, CbVector<T>& cbvec, CbVector<T>& cbpoolvec)
+{
+   if(stlvec.size() != cbvec.size() || stlvec.size() != cbpoolvec.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvec.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvec.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvec.size()<<endl;
+      throw UB_THROW( UbException("equalCheck - sizeCheck failed") );
+   }
+
+   bool check=true;
+   for(size_t i=0; i<cbvec.size(); i++)
+      if(stlvec[i] != cbvec[i] || stlvec[i] != cbpoolvec[i]  )
+         check=false;
+
+   if(!check)
+   {
+      cerr<<"\nstl - "; for(size_t i=0; i<cbvec.size(); i++) cout<<stlvec[i]<<" ";    cout<<endl;
+      cerr<<  "cbv - "; for(size_t i=0; i<cbvec.size(); i++) cout<<cbvec[i]<<" ";     cout<<endl;
+      cerr<<  "cbp - "; for(size_t i=0; i<cbvec.size(); i++) cout<<cbpoolvec[i]<<" "; cout<<endl;
+      throw UB_THROW( UbException("equalCheck - equalCheck failed") );
+   }
+}
+/*==========================================================*/
+template<typename T>
+void equalCheck(vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   if(stlvecs.size() != cbvecs.size() || stlvecs.size() != cbpoolvecs.size() )
+   {
+      cerr<<"sizes:"<<endl;
+      cerr<<"stlvec... = "<<(int)stlvecs.size()<<endl;
+      cerr<<"cbvec.... = "<<(int)cbvecs.size()<<endl;
+      cerr<<"cbpoolvec = "<<(int)cbpoolvecs.size()<<endl;
+      throw UB_THROW( UbException("equalCheck - sizeCheck failed") );
+   }
+
+   for(size_t i=0; i<cbvecs.size(); i++)
+   {
+      //cout<<"equalCheck i="<<i<<"/"<<cbvecs.size()-1;
+      equalCheck(*stlvecs[i],*cbvecs[i],*cbpoolvecs[i]);
+      //cout<<" passed"<<endl;
+   }
+}
+/*==========================================================*/
+void accessCheck(int times,vector< StlVectorPtr >& stlvecs, vector< CbVectorPtr >& cbvecs, vector< CbVectorPtr >& cbpoolvecs)
+{
+   UbTimer timer;
+   timer.start();
+   for(size_t i=0; i<stlvecs.size(); i++)
+   {
+      vector<value_type>& vec = *stlvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"stl-accessCheck       in "<<timer.stop()<<"s"<<endl;
+   timer.start();
+   for(size_t i=0; i<cbvecs.size(); i++)
+   {
+      CbVector<value_type>& vec = *cbvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"cbStd-accessCheck     in "<<timer.stop()<<"s"<<endl;
+   timer.start();
+   for(size_t i=0; i<cbpoolvecs.size(); i++)
+   {
+      CbVector<value_type>& vec = *cbpoolvecs[i];
+      for(int m=0; m<times; m++)
+         for(vector<value_type>::size_type k=0; k<vec.size(); k++) vec[k] = k;
+   }
+   cout<<"cbPool-accessCheck    in "<<timer.stop()<<"s"<<endl;
+}
diff --git a/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/main.cpp b/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b3fe50b252cacff1c0484a54a77ee4427316d748
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/container/examples/CbVectorPool/main.cpp
@@ -0,0 +1,277 @@
+#include "./functions.h"
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char** argv)
+{
+   try
+   {
+       {
+         CbVectorPool<float>* floatPool = new CbVectorPool<float>(0);
+         CbVector<float> v1,v2,v3;
+         CbVector<float> v0(new CbVectorAllocatorPool<float>(104,floatPool) );
+         v0.resize(20);
+         v0[3] = 60000;
+         v0.resize(40);
+         v0[3] = 90000;
+         v1.setAllocator( new CbVectorAllocatorPool<float>(100,floatPool) );
+         v2.setAllocator( new CbVectorAllocatorPool<float>(101,floatPool) );
+         v3.setAllocator( new CbVectorAllocatorPool<float>(102,floatPool) );
+         v1.resize(20, 0.0);
+         v1.resize(30, 0.0);
+         v2.resize(0);
+         v2.resize(40, 0.0);
+         v3.resize(30, 0.0);
+         v3.resize(50, 0.0);
+
+         for(CbVector<float>::size_type i=v1.size()-1; i>=15; i--)
+            v1[i] = (CbVector<float>::value_type)i;
+         for(CbVector<float>::size_type i=v2.size()-1; i>=35; i--)
+            v2[i] = (CbVector<float>::value_type)i;
+         for(CbVector<float>::size_type i=v3.size()-1; i>=10; i--)
+            v3[i] = (CbVector<float>::value_type)i;
+         v1.size(); 
+         v2.size();
+         v3.size();
+         for(CbVector<float>::size_type i=0; i<v1.size(); i++)  v1[i];
+         v1.size();
+         v2.size();
+         v3.size();
+         for(CbVector<float>::size_type i=0; i<v2.size(); i++) v2[i];
+         v1.size();
+         v2.size();
+         v3.size();
+         for(CbVector<float>::size_type i=0; i<v3.size(); i++) v3[i];
+      }
+      
+     CbVectorPool<value_type>* vectorPool = new CbVectorPool<value_type>(0);
+
+     vector< StlVectorPtr > stlVecs;
+     vector< CbVectorPtr >  cbVecs;
+     vector< CbVectorPtr >  cbPoolVecs;
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(10,12,0,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,0,2);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,3,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(8,5,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,7);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,0,7);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(4,3,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,0,7);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     //dealloc check
+     stlVecs.resize(5);
+     cbVecs.resize(5);
+     cbPoolVecs.resize(5);
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(4,3,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(4,3,stlVecs,cbVecs,cbPoolVecs,vectorPool);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+
+     //operator= check
+     CbVector<value_type> testPool1(10, new CbVectorAllocatorPool<value_type>(vectorPool));
+     CbVector<value_type> testPool2(1 , new CbVectorAllocatorPool<value_type>(vectorPool));
+     CbVector<value_type> testPool3(8 , new CbVectorAllocatorPool<value_type>(vectorPool));
+     CbVector<value_type> testPool4(8 , new CbVectorAllocatorPool<value_type>(vectorPool));
+     CbVector<value_type> testStd1(10);
+
+     for(CbVector<value_type>::size_type i=0; i<testStd1.size(); i++ )
+        testStd1[i] = (value_type)i*10;
+
+     testPool1 = testStd1;
+     testPool4 = testStd1;
+     testPool3 = testPool4;
+     testPool2 = testPool3;
+
+     for(CbVector<value_type>::size_type i=0; i<testStd1.size(); i++ )
+        cout<<testStd1[i]<<" "; cout<<endl;
+     for(CbVector<value_type>::size_type i=0; i<testPool1.size(); i++ )
+        cout<<testPool1[i]<<" "; cout<<endl;
+     for(CbVector<value_type>::size_type i=0; i<testPool2.size(); i++ )
+        cout<<testPool2[i]<<" "; cout<<endl;
+     for(CbVector<value_type>::size_type i=0; i<testPool3.size(); i++ )
+        cout<<testPool3[i]<<" "; cout<<endl;
+     for(CbVector<value_type>::size_type i=0; i<testPool4.size(); i++ )
+        cout<<testPool4[i]<<" "; cout<<endl;
+    ///end
+
+
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"// access test - start"<<endl;
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"check"<<__LINE__<<endl;
+     createVecs(1000,1000,stlVecs,cbVecs,cbPoolVecs,vectorPool,true);
+
+     CbVectorPool<value_type>* pool2 = new CbVectorPool<value_type>(1);
+     vector< StlVectorPtr > stlVecs2;
+     vector< CbVectorPtr >  cbVecs2;
+     vector< CbVectorPtr >  cbPoolVecs2;
+     createVecs(1000,1000,stlVecs2,cbVecs2,cbPoolVecs2,pool2,true);
+
+     cout<<"access check\n";
+     //accessCheck(1000,stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     setValues(stlVecs,cbVecs,cbPoolVecs);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"check"<<__LINE__<<endl;
+     resize(stlVecs,cbVecs,cbPoolVecs,120,3,true);
+     equalCheck(stlVecs,cbVecs,cbPoolVecs);
+
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"// access test - end"<<endl;
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"// EXCEPTION TEST - start"<<endl;
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     delete vectorPool;
+     vectorPool = NULL;
+     try
+     {
+        resize(stlVecs,cbVecs,cbPoolVecs,20,3);
+     }
+     catch(UbException& e)
+     {
+        cout<<"if exception tells something about \"vectorPool==NULL\" -> test successfully passed:"<<endl;
+        cout<<e<<endl;
+     }
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+     cout<<"// EXCEPTION TEST - end"<<endl;
+     cout<<"//////////////////////////////////////////////////////////////////////////"<<endl;
+
+     cout<<"\n\n\nALL TESTS PASSED\n";
+   }
+   catch(UbException& e)
+   {
+      std::cerr<<e<<std::endl;
+   }
+   catch(const std::exception &e)
+   {
+      std::cerr << "Caught exception:\n";
+      std::cerr << "Type: " << typeid(e).name() << "\n";
+      std::cerr << "What: " << e.what() << "\n";
+   }
+   catch(...)
+   {
+      std::cerr<<" **            Verdammte Scheisse - mal wieder Mist gebaut!                **"<<endl;
+   }
+    return 0;
+}
+
+// #include <functional>
+// #include <iostream>
+// #include <vector>
+// #include <algorithm>
+// #include <typeinfo>
+//
+// struct bar
+// {
+//    bar()
+//       : data(0)
+//    {}
+//
+//    void foo(const std::size_t value) { std::cout << "data = " << value << " (old: " << data << ");" << std::endl; data = value; }
+//
+// private:
+//    std::size_t data;
+// };
+//
+// int main()
+// {
+//    std::vector<bar> data(10);
+//
+//    /* operator[] => Indexoperator */
+//    for (std::size_t i(0); i < data.size(); ++i)
+//       data[i].foo(2);
+//
+//    /* begin(), end() => Iterator */
+//    const std::vector<bar>::iterator it_end(data.end());
+//    for (std::vector<bar>::iterator it(data.begin()); it != it_end; ++it)
+//       it->foo(3);
+//
+//    /* for_each => Algorithm | Iterator */
+//    std::for_each(data.begin(), data.end(), std::bind2nd(std::mem_fun_ref(&bar::foo), 2));
+// }
diff --git a/source/VirtualFluidsCore/Basics/memory/CMakePackage.txt b/source/VirtualFluidsCore/Basics/memory/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/memory/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Basics/memory/MbChessMemPool2D.h b/source/VirtualFluidsCore/Basics/memory/MbChessMemPool2D.h
new file mode 100644
index 0000000000000000000000000000000000000000..c665f7798f096fd9bc95d70e6d45e7b4f2716b30
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/memory/MbChessMemPool2D.h
@@ -0,0 +1,519 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBCHESSMEMPOOL2D_H
+#define MBCHESSMEMPOOL2D_H
+
+#include <map>
+#include <vector>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <cmath>
+#include <typeinfo>
+
+#include <basics/utilities/UbException.h>
+
+
+template <class TData, std::size_t cachSize>
+class MbChessMemPool2D;
+
+//////////////////////////////////////////////////////////////////////////
+//class MbChessMap2DKey
+//key zum Auffinden der ChessMem2DBlocks
+class MbChessMap2DKey
+{
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //Konstruktoren
+   MbChessMap2DKey(): mVectorPos(0),mFirstCriteria(0),mSecondCriteria(0)
+   {
+
+   }
+   /*==========================================================*/
+   MbChessMap2DKey(std::size_t vectorPos, std::size_t firstCriteria, std::size_t secondCriteria)
+      : mVectorPos(vectorPos), mFirstCriteria(firstCriteria), mSecondCriteria(secondCriteria)
+   {
+   }
+   /*==========================================================*/
+   MbChessMap2DKey& operator=(const MbChessMap2DKey& srcKey)
+   {
+      if(this == &srcKey ) return *this;
+
+      mVectorPos      = srcKey.mVectorPos;
+      mFirstCriteria  = srcKey.mFirstCriteria;
+      mSecondCriteria = srcKey.mSecondCriteria;
+
+      return *this;
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //global ueberladene Operatoren
+   friend inline bool operator<(const MbChessMap2DKey& lhsKey,const MbChessMap2DKey& rhsKey)
+   {
+      if(lhsKey.mFirstCriteria  < rhsKey.mFirstCriteria ) return true;
+      if(lhsKey.mFirstCriteria  > rhsKey.mFirstCriteria ) return false;
+      if(lhsKey.mSecondCriteria < rhsKey.mSecondCriteria) return true;
+
+      return false;
+   }
+   /*==========================================================*/
+   friend inline bool operator==(const MbChessMap2DKey& lhsKey,const MbChessMap2DKey& rhsKey)
+   {
+      if(lhsKey.mVectorPos      != rhsKey.mVectorPos      ) return false;
+      if(lhsKey.mFirstCriteria  != rhsKey.mFirstCriteria  ) return false;
+      if(lhsKey.mSecondCriteria != rhsKey.mSecondCriteria ) return false;
+
+      return true;
+   }
+   //ueberladene Operatoren
+   friend inline bool operator!=(const MbChessMap2DKey& lhsKey,const MbChessMap2DKey& rhsKey)
+   {
+      return !(lhsKey==rhsKey);
+   }
+   //ueberladene Operatoren
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const MbChessMap2DKey& key)
+   {
+      os<<"VectorPos,first-,second-,third Criteria) (";
+      os<<key.mVectorPos<<","<<key.mFirstCriteria<<","<<key.mSecondCriteria<<")";
+      return os;
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //public Methoden
+   std::size_t getVectorPos() {return mVectorPos;}
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private Member
+   std::size_t mVectorPos;
+   std::size_t mFirstCriteria;
+   std::size_t mSecondCriteria;
+};
+
+
+
+template<class T,std::size_t cachSize>
+class MbChessMem2DBlock
+{
+   friend class MbChessMemPool2D<T,cachSize>;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //Konstruktoren
+   MbChessMem2DBlock()
+   {
+      mUsedElements = 0;
+      std::size_t arrayLength = mBlockWidth*mBlockWidth;
+      //mDataElements = new T[arrayLength];
+      mDataElements = operator new(arrayLength*sizeof(T));
+      mFlagVector   = new bool[arrayLength];
+      for(std::size_t i=0;i<arrayLength;i++) mFlagVector[i] = false;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //Destruktor
+   ~MbChessMem2DBlock()
+   {
+      //if(mDataElements) delete[] mDataElements;
+      if(mDataElements) operator delete(mDataElements);
+      if(mFlagVector)   delete[] mFlagVector;
+   }
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private Methoden
+   void* getReference(std::size_t chessX1, std::size_t chessX2)
+   {
+      std::size_t arrayIndex = chessX2*mBlockWidth + chessX1;
+      #ifdef _DEBUG
+         if(arrayIndex>=mBlockWidth*mBlockWidth) UB_THROW( UbException(UB_EXARGS,"index out of range") );
+      #endif
+
+      if(mFlagVector[arrayIndex]==true) UB_THROW( UbException(UB_EXARGS,"memory already allocated!") );
+
+      mUsedElements++;
+      mFlagVector[arrayIndex]=true;
+
+      return (void*)((T*)(mDataElements)+arrayIndex);//&(mDataElements[arrayIndex]);
+   }
+   /*==========================================================*/
+   std::size_t freeReference(void* p)
+   {
+      //std::size_t arrayIndex = static_cast<std::size_t>(static_cast<T*>(p) - mDataElements); //mDataElements = &mDataElements[0]
+      std::size_t arrayIndex = static_cast<std::size_t>(static_cast<T*>(p) - static_cast<T*>(mDataElements));
+
+      #ifdef _DEBUG
+         if(arrayIndex>=mBlockWidth*mBlockWidth) UB_THROW( UbException(UB_EXARGS,"index out of range") );
+      #endif
+
+      if(mFlagVector[arrayIndex]==false) UB_THROW( UbException(UB_EXARGS,"memory not allocated!") );
+
+      mFlagVector[arrayIndex]=false;
+
+      return --mUsedElements;
+   }
+   /*==========================================================*/
+   std::size_t getNofUsedElements()   { return mUsedElements; }
+   /*==========================================================*/
+   void addPointerToTElementsToVector(std::vector<T*>& tdataVector)
+   {
+      std::size_t arrayLength = mBlockWidth*mBlockWidth;
+      for(std::size_t arrayIndex=0;arrayIndex<arrayLength;arrayIndex++)
+      {
+         //if(mFlagVector[arrayIndex]) tdataVector.push_back(&mDataElements[arrayIndex]);
+         if(mFlagVector[arrayIndex]) tdataVector.push_back(static_cast<T*>(mDataElements)+arrayIndex);
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   void addPointerToTElementsToVector(std::vector<T*>& tdataVector, Pred& pred)
+   {
+      std::size_t arrayLength = mBlockWidth*mBlockWidth;
+      T* tmp;
+      for(std::size_t arrayIndex=0;arrayIndex<arrayLength;arrayIndex++)
+      {
+         if(mFlagVector[arrayIndex])
+         {
+            //tmp = &mDataElements[arrayIndex];
+            tmp = (static_cast<T*>(mDataElements))+arrayIndex;
+            if( pred(*tmp) ) tdataVector.push_back(tmp);
+         }
+      }
+   }
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //static Member
+   static const std::size_t   mBlockWidth;
+
+   //////////////////////////////////////////////////////////////////////////
+   //private Member
+   std::size_t   mUsedElements;
+   //T*    mDataElements;
+   void* mDataElements;
+   bool* mFlagVector;
+
+};
+
+//////////////////////////////////////////////////////////////////////////
+//class MbChessMemPool2D
+//zum Verwalten von TData Elementen in einer Schabrett-artigen Struktur
+//die ChessMemBloecke haben hier eine Groesse von ~cachSize
+template <class TData, std::size_t cachSize>
+class MbChessMemPool2D
+{
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //protected static const Member
+   const static std::size_t mCacheSize;
+
+   //////////////////////////////////////////////////////////////////////////
+   //protected Member
+   static std::vector< std::map< MbChessMap2DKey , MbChessMem2DBlock< TData,cachSize >* > > mMapVector;
+   static std::map< void*, MbChessMap2DKey > mPointerKeyMap;
+
+   //////////////////////////////////////////////////////////////////////////
+   //protected Konstrukoren
+   MbChessMemPool2D() //protected, um max einmal vererbt werden zu koennen!!!
+   {              //zudem kann man so keine elmente von TreeBasedMemPool erstellen
+
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //Destruktor
+    ~MbChessMemPool2D()
+   {
+   }
+
+public:
+
+   //////////////////////////////////////////////////////////////////////////
+   //static public Methoden
+   static void* getReference(std::size_t level, std::size_t ix1, std::size_t ix2)
+   {
+      if(!MbChessMem2DBlock< TData,cachSize >::mBlockWidth)
+      {
+         std::stringstream ss;
+         ss<<"TreeBasedMemPool() - InitialisationError\n";
+         ss<<"\t size of StorageData ("<<typeid(TData).name()<<", "<<sizeof(TData)<<" byte)\n";
+         ss<<"\t exceeds user-specifyed cache-zize ("<<mCacheSize<<" byte)\n";
+         ss<<"\t cache-size has to be larger than data-size";
+         UB_THROW( UbException(ss.str()) );
+      }
+
+      if( mMapVector.size()<=level ) mMapVector.resize(level+1);
+
+      std::size_t chessX1 = ix1/(MbChessMem2DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t chessX2 = ix2/(MbChessMem2DBlock<TData,cachSize>::mBlockWidth);
+
+      MbChessMap2DKey mapKey(level,chessX1,chessX2);
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos = mMapVector[level].find(mapKey);
+
+      MbChessMem2DBlock<TData,cachSize>* memBlock = NULL;
+
+      if(pos==mMapVector[level].end())
+      {
+         memBlock = new MbChessMem2DBlock<TData,cachSize>;
+         (mMapVector[level])[mapKey] = memBlock;
+      }
+      else memBlock = pos->second;
+
+      std::size_t internalChessX1 = ix1%(MbChessMem2DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t internalChessX2 = ix2%(MbChessMem2DBlock<TData,cachSize>::mBlockWidth);
+
+      void* p = memBlock->getReference(internalChessX1,internalChessX2);
+
+      mPointerKeyMap[p]=mapKey;
+
+      return p;
+   }
+   /*==========================================================*/
+   static void freeReference(void *p)
+   {
+      typename std::map<void*,MbChessMap2DKey>::iterator posPointerKeyMap = mPointerKeyMap.find(p);
+
+      if(posPointerKeyMap==mPointerKeyMap.end()) UB_THROW( UbException(UB_EXARGS,"pointer not in map") );
+
+      MbChessMap2DKey mapKey = posPointerKeyMap->second;
+      mPointerKeyMap.erase(posPointerKeyMap);
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator posMemBlockMap;
+      posMemBlockMap = mMapVector[mapKey.getVectorPos()].find(mapKey);
+
+      if(posMemBlockMap == mMapVector[mapKey.getVectorPos()].end())
+         UB_THROW( UbException(UB_EXARGS,"mapKey not in ChessMem2DBlockMap") );
+
+      std::size_t leftElements = posMemBlockMap->second->freeReference(p);
+      if(!leftElements)
+      {
+         MbChessMem2DBlock<TData,cachSize>* tmp = posMemBlockMap->second;
+         mMapVector[mapKey.getVectorPos()].erase(posMemBlockMap);
+         delete tmp;
+      }
+   }
+   /*==========================================================*/
+   static void fillVectorWithPointerToTDataElements(std::size_t level,std::vector<TData*>& tdataVector)
+   {
+      tdataVector.clear();
+
+      if(level>=mMapVector.size()) return;
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+      for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+      {
+         pos->second->addPointerToTElementsToVector(tdataVector);
+      }
+   }
+   /*==========================================================*/
+   static void fillVectorWithPointerToTDataElements(std::vector<TData*>& tdataVector)
+   {
+      tdataVector.clear();
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t vecIndex=0; vecIndex<mMapVector.size(); vecIndex++ )
+      {
+         for(pos=mMapVector[vecIndex].begin();pos!=mMapVector[vecIndex].end();++pos)
+         {
+            pos->second->addPointerToTElementsToVector(tdataVector);
+         }
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   static void fillVectorWithPointerToTDataElements(std::size_t level,std::vector<TData*>& tdataVector, Pred pred)
+   {
+      tdataVector.clear();
+
+      if(level>=mMapVector.size()) return;
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+      for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+      {
+         pos->second->addPointerToTElementsToVector(tdataVector,pred);
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   static void fillVectorWithPointerToTDataElements(std::vector<TData*>& tdataVector, Pred pred)
+   {
+      tdataVector.clear();
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t vecIndex=0; vecIndex<mMapVector.size(); vecIndex++ )
+      {
+         for(pos=mMapVector[vecIndex].begin();pos!=mMapVector[vecIndex].end();++pos)
+         {
+            pos->second->addPointerToTElementsToVector(tdataVector,pred);
+         }
+      }
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfChessMemoryBlocks()
+   {
+      std::size_t nofElements = 0;
+      for(std::size_t i=0; i<mMapVector.size(); i++)
+      {
+         nofElements+=mMapVector[i].size();
+      }
+      return nofElements;
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfChessMemoryBlocks(std::size_t level)
+   {
+      if(level<mMapVector.size() )return mMapVector[level].size();
+      return 0;
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfStoredDataElements()
+   {
+      return mPointerKeyMap.size();
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfStoredDataElements(std::size_t level)
+   {
+      if(level<mMapVector.size() )
+      {
+         std::size_t nofElements = 0;
+         typename std::map< MbChessMap2DKey , MbChessMem2DBlock< TData,cachSize >* >::iterator pos;
+
+         for(pos=mMapVector[level].begin(); pos!=mMapVector[level].end(); ++pos)
+         {
+            nofElements += pos->second->getNofUsedElements();
+         }
+         return nofElements;
+      }
+      return 0;
+
+   }
+   /*==========================================================*/
+   static std::string toString()
+   {
+      long double capaticityPerBlock   = (std::size_t)pow((double)MbChessMem2DBlock<TData,cachSize>::mBlockWidth,2.0);
+      std::size_t storedElements       = MbChessMemPool2D<TData,cachSize>::getNumberOfStoredDataElements();
+      std::size_t initialisedMemBlocks = MbChessMemPool2D<TData,cachSize>::getNumberOfChessMemoryBlocks();
+
+      std::stringstream ss;
+      ss<<std::endl;
+      ss<<"****************** MbChessMemPool2D-Info (BEGIN) ******************"<<std::endl;
+      ss<<"type of Storage-Data.................. : "<<typeid(TData).name()<<std::endl;
+      ss<<"size of Storage-Data........... [bytes]: "<<sizeof(TData)<<std::endl;
+      ss<<"specified cache-size........... [bytes]: "<<mCacheSize<<std::endl;
+      ss<<"#elements per MbChessMem2DBlock [bytes]: "<<capaticityPerBlock<<std::endl;
+      ss<<"mem per MbChessMem2DBlock...... [bytes]: "<<capaticityPerBlock*sizeof(TData)<<std::endl;
+      ss<<"used cache-size[%]............. [bytes]: "<<capaticityPerBlock*sizeof(TData)/(double)mCacheSize*100<<std::endl;
+      ss<<"\n";
+      ss<<"#stored Elements  = "<<storedElements<<std::endl;
+      ss<<"#ChessMem2DBlocks = "<<initialisedMemBlocks<<std::endl;
+      ss<<std::endl;
+      ss<<"level | #ChessMem2DBlocks | #stored Elements | used capaticity [%] \n";
+      ss<<"----------------------------------------------------------------\n";
+      for(std::size_t level=0;level<mMapVector.size();level++)
+      {
+         std::size_t nofStoredElements = MbChessMemPool2D<TData,cachSize>::getNumberOfStoredDataElements(level);
+         std::size_t nofChessMem2DBlocks = MbChessMemPool2D<TData,cachSize>::getNumberOfChessMemoryBlocks(level);
+
+         ss<<std::left<<" "<<std::setw(5)<<level<<"| "
+            <<std::setw(16)<<nofChessMem2DBlocks<<"| "
+            <<std::setw(17)<<nofStoredElements<<"| ";
+         if(nofStoredElements)
+            ss<<setw(15)<<nofStoredElements/(double)(capaticityPerBlock*nofChessMem2DBlocks)*100<<std::endl;
+         else ss<<"-"<<std::endl;
+      }
+      ss<<std::endl;
+      ss<<"called memory..... [bytes]: "<<storedElements*sizeof(TData)<<std::endl;
+      ss<<"initialised memory [bytes]: "<<initialisedMemBlocks*capaticityPerBlock*sizeof(TData)<<std::endl;
+      double denominator = (double)(initialisedMemBlocks*capaticityPerBlock*sizeof(TData));
+      if(fabs(denominator)>1.E-13) ss<<"used.............. [%]    : "<<100.*storedElements*sizeof(TData)/denominator<<std::endl;
+      else                         ss<<"used.............. [%]    : 0.0"<<std::endl;
+      ss<<"****************** MbChessMemPool2D-Info (END)  *******************"<<std::endl;
+      return ss.str();
+   }
+   /*==========================================================*/
+   static void writeStatisticFiles(const std::string& filename)
+   {
+      //liefert Statistik ueber aufuellung der einzelnen bloecke (gesamt und pro level)
+      //x-Achse: 0... max moegliche Anzahl von moeglichen Elementen pro MemBlock
+      //y-Achse: Anzahl an Bloecken, die die Anzahl an Elementen beinhalten
+      std::ofstream spreadingFile(((std::string)(filename+"_spreading.txt")).c_str());
+      if(!spreadingFile) UB_THROW( UbException(UB_EXARGS,"couldn't open file") );
+
+      std::size_t initialisedMemBlocks       =   MbChessMemPool2D<TData,cachSize>::getNumberOfChessMemoryBlocks();
+      std::size_t maxNofDataElementsPerBlock =   MbChessMem2DBlock<TData,cachSize>::mBlockWidth
+                                               * MbChessMem2DBlock<TData,cachSize>::mBlockWidth
+                                               * MbChessMem2DBlock<TData,cachSize>::mBlockWidth;
+      std::vector<std::size_t> spreading;
+      spreading.resize(maxNofDataElementsPerBlock+1,0);
+      std::vector< std::vector<std::size_t> > spreadingPerLevel;
+      spreadingPerLevel.resize(mMapVector.size());
+
+      typename std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t level=0; level<mMapVector.size(); level++ )
+      {
+         spreadingPerLevel[level].resize(maxNofDataElementsPerBlock+1,0);
+         for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+         {
+            std::size_t number = pos->second->getNofUsedElements();
+            spreading[number]++;
+            spreadingPerLevel[level][number]++;
+         }
+      }
+      spreadingFile<<"#BlockUsage nofBlocks(all Level) ";
+      for(std::size_t level=0; level<mMapVector.size(); level++ )
+         spreadingFile<<"nofBlockLevel"<<level<<" ";
+      spreadingFile<<std::endl;
+
+      for(std::size_t i=0; i<spreading.size(); i++)
+      {
+         spreadingFile<<i<<" "<<spreading[i];
+         for(std::size_t level=0; level<mMapVector.size(); level++ )
+            spreadingFile<<" "<<spreadingPerLevel[level][i];
+         spreadingFile<<std::endl;
+      }
+      spreadingFile.flush();
+      spreadingFile.close();
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //ueberladene operatoren
+   void* operator new(size_t size, std::size_t level, std::size_t ix1, std::size_t ix2)
+   {
+      if(level<0) UB_THROW( UbException(UB_EXARGS,"level ist negativ!") );
+      void *p = getReference(level,ix1,ix2);
+      return p;
+   }
+   /*==========================================================*/
+   void operator delete(void* p, std::size_t level, std::size_t ix1, std::size_t ix2)
+   {
+      //ACHTUNG: wenn man hier ne Exception schmeisst, dann gibts einen BoeSEN compilerFehler!!!
+      //UB_THROW( UbException(UB_EXARGS,"Scheisse noch nicht gerafft, wie das geht!") );
+      std::cerr<<"MbChessMemPool2D::delete(void* p, std::size_t level, std::size_t ix1, std::size_t ix2) - Scheisse noch nicht gerafft, wie das geht!\n";
+   }
+
+   /*==========================================================*/
+   void operator delete(void* p)
+   {
+      freeReference(p);
+   }
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private statische Methoden
+};
+
+//statische Variablen initialisieren
+template <class TData, std::size_t cachSize>
+std::vector< std::map<MbChessMap2DKey,MbChessMem2DBlock<TData,cachSize>* > > MbChessMemPool2D<TData,cachSize>::mMapVector;
+
+template <class TData, std::size_t cachSize>
+std::map<void*,MbChessMap2DKey >  MbChessMemPool2D< TData, cachSize>::mPointerKeyMap;
+
+template <class TData, std::size_t cachSize>
+const std::size_t  MbChessMemPool2D<TData,cachSize>::mCacheSize=cachSize;
+
+template <class TData,std::size_t cachSize>
+const std::size_t  MbChessMem2DBlock<TData,cachSize>::mBlockWidth=static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1./3.));
+
+#endif
diff --git a/source/VirtualFluidsCore/Basics/memory/MbChessMemPool3D.h b/source/VirtualFluidsCore/Basics/memory/MbChessMemPool3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..99fef93f6c79612e298e08dc3f504df7b0cd695d
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/memory/MbChessMemPool3D.h
@@ -0,0 +1,537 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBCHESSMEMPOOL3D_H
+#define MBCHESSMEMPOOL3D_H
+
+#include <map>
+#include <vector>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <cmath>
+
+#include <basics/utilities/UbException.h>
+
+template <class TData, std::size_t cachSize>
+class MbChessMemPool3D;
+
+//////////////////////////////////////////////////////////////////////////
+//class MbChessMap3DKey
+//key zum Auffinden der ChessMem3DBlocks
+class MbChessMap3DKey
+{
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //Konstruktoren
+   MbChessMap3DKey(): mVectorPos(0),mFirstCriteria(0),mSecondCriteria(0),mThirdCriteria(0)
+   {
+   }
+   /*==========================================================*/
+   MbChessMap3DKey(std::size_t vectorPos,std::size_t firstCriteria,std::size_t secondCriteria,std::size_t thirdCriteria)
+      : mVectorPos(vectorPos), mFirstCriteria(firstCriteria), mSecondCriteria(secondCriteria), mThirdCriteria(thirdCriteria)
+   {
+   }
+   /*==========================================================*/
+   MbChessMap3DKey& operator=(const MbChessMap3DKey& srcKey)
+   {
+      if(this == &srcKey ) return *this;
+
+      mVectorPos      = srcKey.mVectorPos;
+      mFirstCriteria  = srcKey.mFirstCriteria;
+      mSecondCriteria = srcKey.mSecondCriteria;
+      mThirdCriteria  = srcKey.mThirdCriteria;
+
+      return *this;
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //global ueberladene Operatoren
+   friend inline bool operator<(const MbChessMap3DKey& lhsKey,const MbChessMap3DKey& rhsKey)
+   {
+      if(lhsKey.mFirstCriteria  < rhsKey.mFirstCriteria ) return true;
+      if(lhsKey.mFirstCriteria  > rhsKey.mFirstCriteria ) return false;
+      if(lhsKey.mSecondCriteria < rhsKey.mSecondCriteria) return true;
+      if(lhsKey.mSecondCriteria > rhsKey.mSecondCriteria) return false;
+      if(lhsKey.mThirdCriteria  < rhsKey.mThirdCriteria ) return true;
+
+      return false;
+   }
+   /*==========================================================*/
+   friend inline bool operator==(const MbChessMap3DKey& lhsKey,const MbChessMap3DKey& rhsKey)
+   {
+      if(lhsKey.mVectorPos      != rhsKey.mVectorPos      ) return false;
+      if(lhsKey.mFirstCriteria  != rhsKey.mFirstCriteria  ) return false;
+      if(lhsKey.mSecondCriteria != rhsKey.mSecondCriteria ) return false;
+      if(lhsKey.mThirdCriteria  != rhsKey.mThirdCriteria  ) return false;
+
+      return true;
+   }
+   //ueberladene Operatoren
+   friend inline bool operator!=(const MbChessMap3DKey& lhsKey,const MbChessMap3DKey& rhsKey)
+   {
+      return !(lhsKey==rhsKey);
+   }
+   //ueberladene Operatoren
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const MbChessMap3DKey& key)
+   {
+      os<<"VectorPos,first-,second-,third Criteria) (";
+      os<<key.mVectorPos<<","<<key.mFirstCriteria<<","<<key.mSecondCriteria<<","<<key.mThirdCriteria<<")";
+      return os;
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //public Methoden
+   std::size_t getVectorPos() {return mVectorPos;}
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private Member
+   std::size_t mVectorPos;
+   std::size_t mFirstCriteria;
+   std::size_t mSecondCriteria;
+   std::size_t mThirdCriteria;
+};
+
+
+
+template<class T,std::size_t cachSize>
+class MbChessMem3DBlock
+{
+   friend class MbChessMemPool3D<T,cachSize>;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //Konstruktoren
+   MbChessMem3DBlock()
+   {
+      mUsedElements = 0;
+      std::size_t arrayLength = mBlockWidth*mBlockWidth*mBlockWidth;
+      //mDataElements = new T[arrayLength];
+      mDataElements = operator new(arrayLength*sizeof(T));
+      if(!mDataElements) UB_THROW( UbException(UB_EXARGS,"out of memeory!") );
+      mFlagVector   = new bool[arrayLength];
+      if(!mFlagVector) UB_THROW( UbException(UB_EXARGS,"out of memeory!") );
+      for(std::size_t i=0;i<arrayLength;i++) mFlagVector[i] = false;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //Destruktor
+   ~MbChessMem3DBlock()
+   {
+      //if(mDataElements) delete[] mDataElements;
+      if(mDataElements) operator delete(mDataElements);
+      if(mFlagVector)   delete[] mFlagVector;
+   }
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private Methoden
+   void* getReference(std::size_t chessX1, std::size_t chessX2, std::size_t chessX3)
+   {
+      //std::size_t arrayIndex = (chessX1*mBlockWidth+chessX2)*mBlockWidth + chessX3;
+      std::size_t arrayIndex = (chessX3*mBlockWidth+chessX2)*mBlockWidth + chessX1;
+      #ifdef _DEBUG
+         if(arrayIndex>=mBlockWidth*mBlockWidth*mBlockWidth) UB_THROW( UbException(UB_EXARGS,"index out of range") );
+      #endif
+
+      if(mFlagVector[arrayIndex]==true) UB_THROW( UbException(UB_EXARGS,"memory already allocated!") );
+
+      mUsedElements++;
+      mFlagVector[arrayIndex]=true;
+
+      return (void*)((T*)(mDataElements)+arrayIndex);//&(mDataElements[arrayIndex]);
+   }
+   /*==========================================================*/
+   std::size_t freeReference(void* p)
+   {
+      //std::size_t arrayIndex = static_cast<std::size_t>(static_cast<T*>(p) - mDataElements); //mDataElements = &mDataElements[0]
+      std::size_t arrayIndex = static_cast<std::size_t>(static_cast<T*>(p) - static_cast<T*>(mDataElements));
+
+      #ifdef _DEBUG
+        if(arrayIndex>=mBlockWidth*mBlockWidth*mBlockWidth) UB_THROW( UbException(UB_EXARGS,"index out of range") );
+      #endif
+
+      if(mFlagVector[arrayIndex]==false) UB_THROW( UbException(UB_EXARGS,"memory not allocated!") );
+
+      mFlagVector[arrayIndex]=false;
+
+      return --mUsedElements;
+   }
+   /*==========================================================*/
+   std::size_t  getNofUsedElements()   { return mUsedElements; }
+   /*==========================================================*/
+   void addPointerToTElementsToVector(std::vector<T*>& tdataVector)
+   {
+      std::size_t arrayLength = mBlockWidth*mBlockWidth*mBlockWidth;
+      for(std::size_t arrayIndex=0; arrayIndex<arrayLength; arrayIndex++)
+      {
+         //if(mFlagVector[arrayIndex]) tdataVector.push_back(&mDataElements[arrayIndex]);
+         if(mFlagVector[arrayIndex]) tdataVector.push_back(static_cast<T*>(mDataElements)+arrayIndex);
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   void addPointerToTElementsToVector(std::vector<T*>& tdataVector,Pred& pred )
+   {
+      std::size_t arrayLength = mBlockWidth*mBlockWidth*mBlockWidth;
+      T* tmp;
+      for(std::size_t arrayIndex=0;arrayIndex<arrayLength;arrayIndex++)
+      {
+         if(mFlagVector[arrayIndex])
+         {
+            //tmp = &mDataElements[arrayIndex];
+            tmp = static_cast<T*>(mDataElements)+arrayIndex;
+            if( pred(*tmp) ) tdataVector.push_back(tmp);
+         }
+      }
+   }
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //static Member
+   static const std::size_t  mBlockWidth;
+
+   //////////////////////////////////////////////////////////////////////////
+   //private Member
+   std::size_t mUsedElements;
+   //T*    mDataElements;
+   void* mDataElements;
+   bool* mFlagVector;
+
+};
+
+//////////////////////////////////////////////////////////////////////////
+//class MbChessMemPool3D
+//zum Verwalten von TData Elementen in einer Schabrett-artigen Struktur
+//die ChessMemBloecke haben hier eine Groesse von ~cachSize
+template <class TData, std::size_t cachSize>
+class MbChessMemPool3D
+{
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //protected static const Member
+   const static std::size_t mCacheSize;
+
+   //////////////////////////////////////////////////////////////////////////
+   //protected Member
+   static std::vector< std::map< MbChessMap3DKey , MbChessMem3DBlock< TData,cachSize >* > > mMapVector;
+   static std::map< void*, MbChessMap3DKey > mPointerKeyMap;
+
+   //////////////////////////////////////////////////////////////////////////
+   //protected Konstrukoren
+   MbChessMemPool3D() //private, da NUR static erlaubt!!!
+   {
+
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //Destruktor
+   ~MbChessMemPool3D()
+   {
+   }
+
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //static public Methoden
+   static void* getReference(std::size_t level, std::size_t ix1, std::size_t ix2, std::size_t ix3)
+   {
+      if(!MbChessMem3DBlock< TData,cachSize >::mBlockWidth)
+      {
+         std::stringstream ss;
+         ss<<"TreeBasedMemPool() - InitialisationError\n";
+         ss<<"\t size of StorageData ("<<typeid(TData).name()<<", "<<sizeof(TData)<<" byte)\n";
+         ss<<"\t exceeds user-specifyed cache-zize ("<<mCacheSize<<" byte)\n";
+         ss<<"\t cache-size has to be larger than data-size";
+         UB_THROW( UbException(UB_EXARGS,ss.str()) );
+      }
+
+      if( mMapVector.size()<=level ) mMapVector.resize(level+1);
+
+      std::size_t chessX1 = ix1/(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t chessX2 = ix2/(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t chessX3 = ix3/(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+
+      MbChessMap3DKey mapKey(level,chessX1,chessX2,chessX3);
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos = mMapVector[level].find(mapKey);
+
+      MbChessMem3DBlock<TData,cachSize>* memBlock = NULL;
+
+      if(pos==mMapVector[level].end())
+      {
+         memBlock = new MbChessMem3DBlock<TData,cachSize>;
+         (mMapVector[level])[mapKey] = memBlock;
+      }
+      else memBlock = pos->second;
+
+      std::size_t internalChessX1 = ix1%(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t internalChessX2 = ix2%(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+      std::size_t internalChessX3 = ix3%(MbChessMem3DBlock<TData,cachSize>::mBlockWidth);
+
+      void* p = memBlock->getReference(internalChessX1,internalChessX2,internalChessX3);
+
+      mPointerKeyMap[p]=mapKey;
+
+      return p;
+   }
+   static void freeReference(void *p)
+   {
+      typename std::map<void*,MbChessMap3DKey>::iterator posPointerKeyMap = mPointerKeyMap.find(p);
+
+      if(posPointerKeyMap==mPointerKeyMap.end()) UB_THROW( UbException(UB_EXARGS,"pointer not in map") );
+
+      MbChessMap3DKey mapKey = posPointerKeyMap->second;
+      mPointerKeyMap.erase(posPointerKeyMap);
+
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator posMemBlockMap;
+      posMemBlockMap = mMapVector[mapKey.getVectorPos()].find(mapKey);
+
+
+      if(posMemBlockMap == mMapVector[mapKey.getVectorPos()].end())
+         UB_THROW( UbException(UB_EXARGS,"mapKey not in ChessMem3DBlockMap") );
+
+      std::size_t leftElements = posMemBlockMap->second->freeReference(p);
+      if(!leftElements)
+      {
+         MbChessMem3DBlock<TData,cachSize>* tmp = posMemBlockMap->second;
+         mMapVector[mapKey.getVectorPos()].erase(posMemBlockMap);
+         try{ delete tmp; }
+         catch(...){UB_THROW( UbException(UB_EXARGS,"could not delete MbChessMem3DBlock") );}
+      }
+   }
+   /*==========================================================*/
+   static void fillVectorWithPointerToTDataElements(std::size_t level,std::vector<TData*>& tdataVector)
+   {
+      tdataVector.clear();
+
+      if(level>=mMapVector.size()) return;
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+      for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+      {
+         pos->second->addPointerToTElementsToVector(tdataVector);
+      }
+   }
+   /*==========================================================*/
+   static void fillVectorWithPointerToTDataElements(std::vector<TData*>& tdataVector)
+   {
+      tdataVector.clear();
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t vecIndex=0; vecIndex<mMapVector.size(); vecIndex++ )
+      {
+         for(pos=mMapVector[vecIndex].begin();pos!=mMapVector[vecIndex].end();++pos)
+         {
+            pos->second->addPointerToTElementsToVector(tdataVector);
+         }
+      }
+   }
+   /*==========================================================*/
+   template<class Pred>
+   static void fillVectorWithPointerToTDataElements(std::size_t level,std::vector<TData*>& tdataVector, Pred pred)
+   {
+      tdataVector.clear();
+
+      if(level>=mMapVector.size()) return;
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+      for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+      {
+         pos->second->addPointerToTElementsToVector(tdataVector,pred);
+      }
+   }
+   /*==========================================================*/
+   template<typename Pred>
+   static void fillVectorWithPointerToTDataElements(std::vector<TData*>& tdataVector, Pred pred)
+   {
+      tdataVector.clear();
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t vecIndex=0; vecIndex<mMapVector.size(); vecIndex++ )
+      {
+         for(pos=mMapVector[vecIndex].begin();pos!=mMapVector[vecIndex].end();++pos)
+         {
+            pos->second->addPointerToTElementsToVector(tdataVector,pred);
+         }
+      }
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfChessMemoryBlocks()
+   {
+      std::size_t nofElements = 0;
+      for(std::size_t i=0;i<mMapVector.size();i++)
+      {
+         nofElements+=mMapVector[i].size();
+      }
+      return nofElements;
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfChessMemoryBlocks(std::size_t level)
+   {
+      if(level<mMapVector.size() ) return mMapVector[level].size();
+      return 0;
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfStoredDataElements()
+   {
+      return mPointerKeyMap.size();
+   }
+   /*==========================================================*/
+   static std::size_t getNumberOfStoredDataElements(std::size_t level)
+   {
+      if(level<mMapVector.size() )
+      {
+         std::size_t nofElements = 0;
+         typename std::map< MbChessMap3DKey , MbChessMem3DBlock< TData,cachSize >* >::iterator pos;
+
+         for(pos=mMapVector[level].begin(); pos!=mMapVector[level].end(); ++pos)
+         {
+            nofElements+= pos->second->getNofUsedElements();
+         }
+         return nofElements;
+      }
+      return 0;
+   }
+   /*==========================================================*/
+   static std::string toString()
+   {
+      long double capaticityPerBlock   = pow((double)MbChessMem3DBlock<TData,cachSize>::mBlockWidth,3.0);
+      std::size_t storedElements       = MbChessMemPool3D<TData,cachSize>::getNumberOfStoredDataElements();
+      std::size_t initialisedMemBlocks = MbChessMemPool3D<TData,cachSize>::getNumberOfChessMemoryBlocks();
+
+      std::stringstream ss;
+      ss<<std::endl;
+      ss<<"****************** MbChessMemPool3D-Info (BEGIN) ******************"<<std::endl;
+      ss<<"type of Storage-Data.................. : "<<typeid(TData).name()<<std::endl;
+      ss<<"size of Storage-Data........... [bytes]: "<<sizeof(TData)<<std::endl;
+      ss<<"specified cache-size........... [bytes]: "<<mCacheSize<<std::endl;
+      ss<<"#elements per MbChessMem3DBlock [bytes]: "<<capaticityPerBlock<<std::endl;
+      ss<<"mem per MbChessMem3DBlock...... [bytes]: "<<capaticityPerBlock*sizeof(TData)<<std::endl;
+      ss<<"used cache-size[%]............. [bytes]: "<<capaticityPerBlock*sizeof(TData)/(double)mCacheSize*100<<std::endl;
+      ss<<"\n";
+      ss<<"#stored Elements   = "<<storedElements<<std::endl;
+      ss<<"#ChessMem3DBlocks  = "<<initialisedMemBlocks<<std::endl;
+      ss<<std::endl;
+      ss<<"level | #ChessMem3DBlocks | #stored Elements | used capaticity [%] \n";
+      ss<<"----------------------------------------------------------------\n";
+      for(std::size_t level=0;level<mMapVector.size();level++)
+      {
+         std::size_t nofStoredElements   = MbChessMemPool3D<TData,cachSize>::getNumberOfStoredDataElements(level);
+         std::size_t nofChessMem3DBlocks = MbChessMemPool3D<TData,cachSize>::getNumberOfChessMemoryBlocks(level);
+
+         ss<<std::left<<" "<<std::setw(5)<<level<<"| "
+            <<std::setw(16)<<nofChessMem3DBlocks<<"| "
+            <<std::setw(17)<<nofStoredElements<<"| ";
+         if(nofStoredElements)
+            ss<<std::setw(15)<<nofStoredElements/(double)(capaticityPerBlock*nofChessMem3DBlocks)*100<<std::endl;
+         else ss<<"-"<<std::endl;
+      }
+      ss<<std::endl;
+      ss<<"called memory..... [bytes]: "<<storedElements*sizeof(TData)<<std::endl;
+      ss<<"initialised memory [bytes]: "<<initialisedMemBlocks*capaticityPerBlock*sizeof(TData)<<std::endl;
+      double denominator = (double)(initialisedMemBlocks*capaticityPerBlock*sizeof(TData));
+      if(fabs(denominator)>1.E-13) ss<<"used.............. [%]    : "<<100.*storedElements*sizeof(TData)/denominator<<std::endl;
+      else                         ss<<"used.............. [%]    : 0.0"<<std::endl;
+      ss<<"****************** MbChessMemPool3D-Info (END)  *******************"<<std::endl;
+      return ss.str();
+   }
+   /*==========================================================*/
+   static void writeStatisticFiles(const std::string& filename)
+   {
+      //liefert Statistik ueber aufuellung der einzelnen bloecke (gesamt und pro level)
+      //x-Achse: 0... max moegliche Anzahl von moeglichen Elementen pro MemBlock
+      //y-Achse: Anzahl an Bloecken, die die Anzahl an Elementen beinhalten
+      std::ofstream spreadingFile(((std::string)(filename+"_spreading.txt")).c_str());
+      if(!spreadingFile) UB_THROW( UbException(UB_EXARGS,"couldn't open file") );
+
+      //std::size_t initialisedMemBlocks       =  MbChessMemPool3D<TData,cachSize>::getNumberOfChessMemoryBlocks();
+      std::size_t maxNofDataElementsPerBlock =  MbChessMem3DBlock<TData,cachSize>::mBlockWidth
+                                               *MbChessMem3DBlock<TData,cachSize>::mBlockWidth
+                                               *MbChessMem3DBlock<TData,cachSize>::mBlockWidth;
+      std::vector<std::size_t> spreading;
+      spreading.resize(maxNofDataElementsPerBlock+1,0);
+      std::vector< std::vector<std::size_t> > spreadingPerLevel;
+      spreadingPerLevel.resize(mMapVector.size());
+
+      typename std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* >::iterator pos;
+
+      for(std::size_t level=0; level<mMapVector.size(); level++ )
+      {
+         spreadingPerLevel[level].resize(maxNofDataElementsPerBlock+1,0);
+         for(pos=mMapVector[level].begin();pos!=mMapVector[level].end();++pos)
+         {
+            std::size_t number = pos->second->getNofUsedElements();
+            spreading[number]++;
+            spreadingPerLevel[level][number]++;
+         }
+      }
+      spreadingFile<<"#BlockUsage nofBlocks(all Level) ";
+      for(std::size_t level=0; level<mMapVector.size(); level++ )
+         spreadingFile<<"nofBlockLevel"<<level<<" ";
+      spreadingFile<<std::endl;
+
+      for(std::size_t i=0;i<spreading.size();i++)
+      {
+         spreadingFile<<i<<" "<<spreading[i];
+         for(std::size_t level=0; level<mMapVector.size(); level++ )
+            spreadingFile<<" "<<spreadingPerLevel[level][i];
+         spreadingFile<<std::endl;
+      }
+      spreadingFile.flush();
+      spreadingFile.close();
+   }
+
+   ////////////////////////////////////////////////////////////////////////////
+   ////ueberladene operatoren
+   //void* operator new(size_t size, std::size_t level, std::size_t ix1, std::size_t ix2, std::size_t ix3)
+   //{
+   //   if(level<0) UB_THROW( UbException(UB_EXARGS,"level ist negativ!") );
+   //   void *p = getReference(level,ix1,ix2,ix3);
+   //   return p;
+   //}
+   ///*==========================================================*/
+   //void operator delete(void* p, std::size_t level, std::size_t ix1, std::size_t ix2, std::size_t ix3)
+   //{
+   //   //ACHTUNG: wenn man hier ne Exception schmeisst, dann gibts einen BoeSEN compilerFehler!!!
+   //   //UB_THROW( UbException(__FILE__, __LINE__, "MbChessMemPool3D::delete - Scheisse noch nicht gerafft, wie das geht!") );
+   //   cout<<"MbChessMemPool3D::delete(void* p, std::size_t level, std::size_t ix1, std::size_t ix2, std::size_t ix3) - Scheisse noch nicht gerafft, wie das geht!\n";
+   //}
+
+   ///*==========================================================*/
+   //void operator delete(void* p)
+   //{
+   //   freeReference(p);
+   //}
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   //private statische Methoden
+};
+
+
+//statische Variablen initialisieren
+template <class TData, std::size_t cachSize>
+std::vector< std::map<MbChessMap3DKey,MbChessMem3DBlock<TData,cachSize>* > > MbChessMemPool3D<TData,cachSize>::mMapVector;
+
+template <class TData, std::size_t cachSize>
+std::map<void*,MbChessMap3DKey >  MbChessMemPool3D< TData, cachSize>::mPointerKeyMap;
+
+template <class TData, std::size_t cachSize>
+const std::size_t  MbChessMemPool3D<TData,cachSize>::mCacheSize=cachSize;
+
+//template <class TData, std::size_t cachSize>
+//const std::size_t  MbChessMemPool3D<TData,cachSize>::mNofElementsWidthMemBlock=static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1./3.));
+
+//template <class TData, std::size_t cachSize>
+//const std::size_t  MbChessMemPool3D<TData,cachSize>::mNofElementsInMemBlock=static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1./3.))),3.0));
+
+template <class TData,std::size_t cachSize>
+const std::size_t  MbChessMem3DBlock<TData,cachSize>::mBlockWidth=static_cast<std::size_t>(std::pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1./3.));
+
+//template <class TData,std::size_t cachSize>
+//const std::size_t  MbChessMem3DBlock<TData,cachSize>::mMaxElements=static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(pow(static_cast<double>(static_cast<std::size_t>(cachSize/sizeof(TData))),1.0/3.0))),3.0))),3.0));
+
+#endif
diff --git a/source/VirtualFluidsCore/Basics/memory/MbMemPool.h b/source/VirtualFluidsCore/Basics/memory/MbMemPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a835596a9c717e4e31bf3f6570b7615759a754b
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/memory/MbMemPool.h
@@ -0,0 +1,87 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBMEMPOOL_H
+#define MBMEMPOOL_H
+
+#include <queue>
+#include <list>
+
+
+template <typename TData, int asize>
+class MbMemPool
+{
+
+protected:
+   MbMemPool(){}
+   // Alle 3 Attribute sind Singleton-Objekte !
+   // Allokiere Blocke der Groesse m_asize
+   static int m_asize;       
+   // Halte alle freien Pointer (jedes einzelne Element)  in eine FIFO Liste
+   static std::queue<void*> m_queue;
+   // Pointer auf Bloecke zum Loeschen !
+   static std::list<TData*> m_list;
+
+public:
+
+   
+   ~MbMemPool(){}
+
+   // Daten-Bloecke Loeschen, damit wird der gesamte Speicher freigegeben,
+   // erst aufrufen, wenn die objekte nicht mehr gebraucht werden!
+   static void	deallocatePool();
+
+   void* operator new(std::size_t size)
+   {
+      void*  pNew;
+      TData* feld;	
+      int i;
+
+      //i=m_queue.size();
+      //pNew = m_queue.front();
+      if(m_queue.size()==0) 
+      {
+         //Wenn kein freier Speicher mehr vorhanden, Block anlegen
+         feld = new TData[m_asize];
+         m_list.push_back(feld);
+         for(i=0 ; i<m_asize ; i++)
+         {
+            pNew = (void*) &(feld[i]);
+            m_queue.push( pNew );
+         }
+      }
+      pNew = m_queue.front();
+      m_queue.pop();
+      return pNew;
+
+   }
+
+   void  operator delete(void* p)
+   {
+      m_queue.push(p);
+   }
+};
+
+
+template <typename TData, int asize> 
+std::queue<void*>  MbMemPool<TData,asize>::m_queue;
+
+template <typename TData, int asize> 
+std::list<TData*>  MbMemPool<TData,asize>::m_list;
+
+template <typename TData, int asize> 
+int  MbMemPool<TData,asize>::m_asize=asize;
+
+template <typename TData, int asize> 
+void MbMemPool<TData,asize>::deallocatePool()
+{	
+   for(typename std::list<TData*>::iterator pos=m_list.begin() ; pos!=m_list.end(); ++pos)
+   {
+      delete[] pos;
+   }
+}
+
+#endif //MBMEMPOOL_H
diff --git a/source/VirtualFluidsCore/Basics/memory/MbSharedPointerDefines.h b/source/VirtualFluidsCore/Basics/memory/MbSharedPointerDefines.h
new file mode 100644
index 0000000000000000000000000000000000000000..25c9311e7e5ec10585c96c3cd70792cb7b330ef3
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/memory/MbSharedPointerDefines.h
@@ -0,0 +1,39 @@
+
+#ifndef MBSHAREDPOINTERDEFINES_H
+#define MBSHAREDPOINTERDEFINES_H
+
+
+// Boost includes
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#define VFSharedFromThis boost::enable_shared_from_this
+#define VFSharedPtr boost::shared_ptr
+#define VFWeakPtr   boost::weak_ptr
+#define VFDynamicPtrCast boost::dynamic_pointer_cast
+
+template<typename T>
+class VFPtrDeleter
+{
+public:
+   void operator()(T* p) { delete p; }
+};
+
+
+
+// std includes
+#include <vector>
+
+//#ifdef WIN32
+//#  include <memory>
+//#else
+//#  include<tr1/memory>
+//#endif
+
+//#  define DCSharedFromThis std::tr1::enable_shared_from_this
+//#  define DCSharedPtr std::tr1::shared_ptr
+//#  define DCWeakPtr   std::tr1::weak_ptr
+//#  define DCDynamicPtrCast std::tr1::dynamic_pointer_cast
+
+#endif
diff --git a/source/VirtualFluidsCore/Basics/memory/MbSmartPtr.h b/source/VirtualFluidsCore/Basics/memory/MbSmartPtr.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f2bf7631745b9940817d41014205f0a5b6e1077
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/memory/MbSmartPtr.h
@@ -0,0 +1,147 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBSMARTPTR_H
+#define MBSMARTPTR_H
+
+#include <basics/memory/MbSmartPtrBase.h>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+//=====================================================
+// Globale Funktion, um das Loeschen des referenzierten
+// Objektes flexibler zu gestalten.
+//
+template<class ObjType>
+void deleteRefPtr(ObjType* ptr)
+{
+   delete ptr;
+}
+
+//======================================================
+// Die Reference-Pointer Klasse:
+//
+// Beim Referenzieren eines Objektes ueber einen SmartPointer wird ein Zaehler fuer die referezierte Objekt-
+// adresse inkrementiert. Wird der Pointer wieder einem anderen Objekt zugewiesen, so wird der Zaehler fuer das
+// urspruenglich referenzierte Objekt wieder dekremtiert, ebenfalls beim Destruktor des Reference-Pointers.
+// Tatsaechlich geloescht wird das referenzierte Objekt erst, wenn der zugehoerige Zaehler auf 0 ist. Dies geschieht
+// ueber die globale Template-Funktion deleteRefPtr(), die bei Bedarf ueberschrieben werden kann.
+// Der Reference-Pointer verfuegt also sozusagen ueber eine automatische Garbage Collection
+
+template<class ObjType>
+class MbSmartPtr  : public MbSmartPtrBase
+{
+public:
+   // Konstruktoren //bei explicit geht der implizite cast nicht mehr, aber um keinen stress zu verursachen
+   /*explicit*/ MbSmartPtr<ObjType>(const ObjType* pPtr=NULL)
+      : MbSmartPtrBase(), mpPtr(NULL)
+	{
+		init(pPtr);
+	}
+	template<class ParamType>
+	MbSmartPtr<ObjType>(const MbSmartPtr<ParamType>& ptr)
+      : MbSmartPtrBase(), mpPtr(NULL)
+	{
+		init(ptr.get());
+	}
+	// Destruktor
+   ~MbSmartPtr<ObjType>()
+	{
+      init(NULL);
+	}
+   //---------------------------------------------------
+   // Kopierkonstruktor
+   MbSmartPtr<ObjType>(const MbSmartPtr<ObjType>& ptr)
+     : MbSmartPtrBase(), mpPtr(NULL)
+	{
+		init(ptr.get());
+	}
+   //---------------------------------------------------
+   // Zuweisungsoperatoren
+	template<class ParamType>
+	const MbSmartPtr<ObjType>& operator =(const MbSmartPtr<ParamType>& ptr)
+	{
+   	init(ptr.get());
+		return *this;
+	}
+	const MbSmartPtr<ObjType>& operator =(const MbSmartPtr<ObjType>& ptr)
+	{
+		init(ptr.get());
+		return *this;
+	}
+
+	const MbSmartPtr<ObjType>& operator =(const ObjType *pPtr)
+	{
+		init(pPtr);
+		return *this;
+	}
+   //---------------------------------------------------
+   // Dereferenzierung-Operatoren
+	ObjType& operator *() const  { return *mpPtr; }
+   ObjType* operator ->() const { return mpPtr;  }
+   bool operator !() const      { return !mpPtr; }
+   operator ObjType *() const   { return mpPtr;  }
+   //---------------------------------------------------
+	// Methoden
+	ObjType* get() const
+   {
+      return mpPtr;
+   }
+   //---------------------------------------------------
+   int ref_count() const
+   {
+      return MbSmartPtrBase::ref_count(mpPtr);
+   }
+   //---------------------------------------------------
+   bool release() const
+   {
+      return MbSmartPtrBase::removeFromGC(mpPtr);
+   }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      if(ArchiveTools::isWriting(ar))
+      {
+         ar & mpPtr;
+      }
+      else
+      {
+         ObjType* ptr;
+         ar & ptr;
+
+         mpPtr=NULL;
+         init(ptr);
+      }
+   }
+#endif //CAB_RCF
+
+private:
+   void init(const ObjType* pPtr)
+	{
+      // Nur was tun, wenn wirklich noetig
+		if(pPtr==mpPtr) return;
+
+      // Aktuell referenziertes Objekt freigeben, dabei ueberpruefen, ob letztes Release
+		if(mpPtr && releaseRef(mpPtr))
+		{
+         // referenziertes Objekt loeschen
+			deleteRefPtr(mpPtr);
+		}
+
+      // Wenn pPtr ein neues Objekt ist, Zugriffszaehler auf neues Objekt erhoehen
+		mpPtr=const_cast<ObjType*>(pPtr);
+	   if(mpPtr) addRef(mpPtr);
+	}
+
+private:
+   ObjType* mpPtr;
+};
+
+#endif //MBSMARTPTR_H
diff --git a/source/VirtualFluidsCore/Basics/memory/MbSmartPtrBase.cpp b/source/VirtualFluidsCore/Basics/memory/MbSmartPtrBase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d0e07fa9503fe01f94128543d84927804505b97a
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/memory/MbSmartPtrBase.cpp
@@ -0,0 +1,44 @@
+#include <basics/memory/MbSmartPtrBase.h>
+
+using namespace std;
+
+bool MbSmartPtrBase::addRef(void* ptr)
+{
+   MbSmartPtrBaseMap::getInstance()->getMap()[ptr]++;
+	return true;
+}
+//-------------------------------------------------
+bool MbSmartPtrBase::releaseRef(void* ptr)
+{
+   map<void*,int>& ptrMap = MbSmartPtrBaseMap::getInstance()->getMap();
+   map<void*,int>::iterator pos=ptrMap.find(ptr);
+	
+   if( pos!=ptrMap.end() )
+	{
+		pos->second--;
+		
+      if(pos->second==0)
+		{
+			ptrMap.erase(pos);
+			return true;
+		}
+	}
+	return false;
+}
+//-------------------------------------------------
+bool MbSmartPtrBase::removeFromGC(void* ptr) const 
+{
+   if( MbSmartPtrBaseMap::getInstance()->getMap().erase(ptr) ) return true;
+   return false;
+}
+//-------------------------------------------------
+int MbSmartPtrBase::ref_count(void* ptr) const 
+{
+   map<void*,int>& ptrMap = MbSmartPtrBaseMap::getInstance()->getMap();
+   map<void*,int>::iterator pos=ptrMap.find(ptr);
+
+   if( pos!=ptrMap.end() ) return pos->second;
+   else                    return 0;
+}
+
+
diff --git a/source/VirtualFluidsCore/Basics/memory/MbSmartPtrBase.h b/source/VirtualFluidsCore/Basics/memory/MbSmartPtrBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1bf281ce1f7fe8b41c19cd0d6deac9dd43f9574
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/memory/MbSmartPtrBase.h
@@ -0,0 +1,50 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef MBSMARTPTRBASE_H
+#define MBSMARTPTRBASE_H
+
+#include <iostream>
+#include <map>
+
+//============================================================
+// Klasse MbSmartPtrBase
+//
+// Basisklasse, speziell fuer MbSmartPtr, die das eigentliche
+// Reference-Counting uebernimmt.
+//
+class MbSmartPtrBase
+{
+   //Ursprung:
+   // mpCntrMap ist ein Pointer, weil sichergestellt sein muss, dass die
+   // Map existiert, wenn das erste mal darauf zugegriffen wird.
+   // Ein Zugriff zwischen zwei statischen Objekten kann zum Fehler fuehren, da
+   // die Reihenfolge der Konstruktorenaufrufe dann vom Linker bestimmt wird.
+
+   //Anpassung a la UbWriter mit SingletonMap
+   class MbSmartPtrBaseMap
+   {
+   private:
+      MbSmartPtrBaseMap() { }
+      MbSmartPtrBaseMap( const MbSmartPtrBaseMap& );                  //no copy allowed
+      const MbSmartPtrBaseMap& operator=( const MbSmartPtrBaseMap& ); //no copy allowed
+
+      std::map<void*,int> mpCntrMap;
+   public:
+      static MbSmartPtrBaseMap* getInstance() { static MbSmartPtrBaseMap instance; return &instance; }
+      std::map<void*,int>& getMap()           { return mpCntrMap;                                    }
+   };
+
+protected:
+   MbSmartPtrBase() {}
+   virtual ~MbSmartPtrBase() {}
+   bool addRef(void* p);
+	bool releaseRef(void* p);
+   bool removeFromGC(void* ptr) const;
+   int  ref_count(void* ptr) const;
+};
+
+#endif //MBSMARTPTRBASE_H
diff --git a/source/VirtualFluidsCore/Basics/objects/CMakePackage.txt b/source/VirtualFluidsCore/Basics/objects/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Basics/objects/ObCreator.h b/source/VirtualFluidsCore/Basics/objects/ObCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..253fc616e2f1d9c2b279423ce93462095e698774
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObCreator.h
@@ -0,0 +1,112 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBCREATOR_H
+#define OBCREATOR_H
+
+#include <string>
+
+/*=========================================================================*/
+/*  ObCreator / ObCreatorImpl                                              */
+/*                                                                         */
+/**
+generic factory
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 14.06.07
+@version 1.1 - 12.04.08
+*/ 
+
+/*
+usage: see bottom of file "./ObFactory.h"
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// ObCreator
+// Um in der Factory verschiedene Typen von Creaors in einer 
+// std::map<std::string,ObCreator<BaseT>*> halten zu koennen
+// muss eine gemeinsame Basisklasse existieren
+//////////////////////////////////////////////////////////////////////////
+template< class BaseT >
+class ObCreator
+{
+public:
+   virtual std::string  getObjectTypeID()=0;
+   virtual BaseT*       createObject() = 0;
+
+   virtual ~ObCreator() {  }
+
+protected:
+   ObCreator() {}
+private:
+   ObCreator( const ObCreator< BaseT >& );         //no copy allowed 
+   const ObCreator& operator=( const ObCreator& ); //no copy allowed
+};
+
+//////////////////////////////////////////////////////////////////////////
+// ObCreatorImpl
+// Implementierung des speziellen Creators 
+//////////////////////////////////////////////////////////////////////////
+template< class T, class BaseT=T >
+class ObCreatorImpl : public ObCreator< BaseT >
+{
+public:
+   static ObCreator<BaseT >* getInstance()
+   {
+      static ObCreatorImpl< T, BaseT > instance;
+      return &instance;
+   }
+
+public:
+   ~ObCreatorImpl() {}
+
+   //aus portabilitaetsgruenden kann man nicht typeinfo nehmen, da diese compilerabhaengig ist
+   std::string getObjectTypeID()  { return T::getStaticClassObjectTypeID();  } 
+   
+   virtual T*  createObject() { return new T(); }
+
+protected:
+	ObCreatorImpl() {}
+private:
+	ObCreatorImpl( const ObCreatorImpl< T, BaseT >& );      //no copy allowed 
+   const ObCreatorImpl& operator=( const ObCreatorImpl& ); //no copy allowed
+};
+
+//////////////////////////////////////////////////////////////////////////
+// ObCreatorImpl
+// Implementierung des speziellen Creators fuer Singletons
+//////////////////////////////////////////////////////////////////////////
+template< class T, class BaseT=T >
+class ObSingletonCreatorImpl : public ObCreator< BaseT >
+{
+public:
+   static ObCreator<BaseT >* getInstance()
+   {
+      static ObSingletonCreatorImpl< T, BaseT > instance;
+      return &instance;
+   }
+public:
+   ~ObSingletonCreatorImpl() {}
+
+   //aus portabilitaetsgruenden kann man nicht typeinfo nehmen, da diese compilerabhaengig ist
+   std::string getObjectTypeID()  { return T::getStaticClassObjectTypeID();  } 
+
+   virtual T* createObject() { return T::getInstance(); }
+
+protected:
+   ObSingletonCreatorImpl() {}
+private:
+   ObSingletonCreatorImpl( const ObSingletonCreatorImpl< T, BaseT >& );      //no copy allowed 
+   const ObSingletonCreatorImpl& operator=( const ObSingletonCreatorImpl& ); //no copy allowed
+};
+
+//workaround for the not perfect C++ world. typeinfo::name is not usable for this purpose!
+//see Andrei Alexandrescu, "Modern C++ Design: Generic Programming and Design Patterns Applied", Chapter 8.5
+#define OBCREATOR_EXT( ClassObject ) \
+   static  std::string  getStaticClassObjectTypeID() { return #ClassObject;                 } \
+   virtual std::string  getClassObjectTypeID()       { return getStaticClassObjectTypeID(); } 
+
+#endif //OBCREATOR_H
diff --git a/source/VirtualFluidsCore/Basics/objects/ObFactory.h b/source/VirtualFluidsCore/Basics/objects/ObFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b51787819b0548efc89960be450d129753aa0b3
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObFactory.h
@@ -0,0 +1,174 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBFACTORY_H
+#define OBFACTORY_H
+
+
+#include <string>
+#include <map>
+#include <sstream>
+#include <iomanip>
+#include <typeinfo>
+
+#include <basics/objects/ObCreator.h>
+
+/*=========================================================================*/
+/*  ObFactory                                                            */
+/*                                                                         */
+/**
+generic factory
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 14.06.07
+@version 1.1 - 12.04.08
+*/ 
+
+/*
+usage:  T       = zu erzeugende Klasse
+        Creator = Erzeugerklasse
+//////////////////////////////////////////////////////////////////////////
+//example
+//////////////////////////////////////////////////////////////////////////
+//  class Base{ 
+//  public:
+//        OBCREATOR_EXT(Base)
+//  };
+//  //automatisches registrieren:
+//  UB_AUTO_RUN_NAMED(ObFactory<Base>::getInstance()->addObCreator(ObCreatorImpl<Base,Base>::getInstance()), CAB_Base);
+//  class Derived : public Base 
+//  {
+//   public:
+//        OBCREATOR_EXT(Derived)
+//};
+//  //automatisches registrieren:
+//  UB_AUTO_RUN_NAMED(ObFactory<Base>::getInstance()->addObCreator(ObCreatorImpl<Base,Derived>::getInstance()), CAB_Derived);
+////////////////////////////////////////////////////////////////////////////
+//  int main()
+//  {
+//       //Alternativ zu UB_AUTO_RUN_NAMED: haendisches registrieren
+//       ObFactory<Base>::getInstance()->addObCreator(ObCreatorImpl<Base>::getInstance());
+//       ObFactory<Base>::getInstance()->addObCreator(ObCreatorImpl<Derived,Base>::getInstance());
+// 
+//       //create objects - method1
+//       Base* test1 = ObFactory<Base>::getInstance()->createObject<Base>();
+//       Base* test2 = ObFactory<Base>::getInstance()->createObject<Derived>();
+// 
+//       //create objects - method2
+//       Base* test1 = ObFactory<Base>::getInstance()->createObject(Base::getStaticClassObjectTypeID()    );
+//       Base* test2 = ObFactory<Base>::getInstance()->createObject(Derived::getStaticClassObjectTypeID() );
+//   //...
+// }
+*/
+
+
+template<class  T, typename Creator = ObCreator< T > >
+class ObFactory
+{
+   typedef std::map<  std::string, Creator* > CreatorMap;
+   typedef typename CreatorMap::iterator      CreatorMapIt;
+   typedef std::pair< std::string, Creator* > CreatorMapElement;
+
+protected:
+   ObFactory() {}  //so ist vererbung gewahrleistet
+
+private:
+   ObFactory( const ObFactory< T, Creator >& );    //no copy allowed 
+   const ObFactory& operator=( const ObFactory& ); //no copy allowed
+
+
+public:
+   virtual ~ObFactory() {}
+
+   static ObFactory< T, Creator >* getInstance() 
+   {
+      static ObFactory< T, Creator > instance;
+      return &instance;
+   }
+
+   bool addObCreator(Creator* creator);
+   bool removeObCreator(Creator* creator);
+
+   T* createObject(const std::string& objectTypeID);
+   
+   template< typename T2 > 
+   T* createObject() { return this->createObject( T2::getStaticClassObjectTypeID() ); }
+   
+   Creator* getCreator(const std::string& objectTypeID);
+
+   virtual std::string toString();
+  
+private:
+   CreatorMap creatorMap;
+};
+
+//////////////////////////////////////////////////////////////////////////
+//Implementation
+template<class  T, typename Creator >
+bool ObFactory< T, Creator >::addObCreator(Creator* creator)
+{
+	if(creatorMap.insert( CreatorMapElement(creator->getObjectTypeID(), creator) ).second )
+   {
+      //insert succeeded
+      return true;
+   }
+   //insert fails
+   return false;
+}
+/*======================================================================*/
+template<class  T, typename Creator >
+bool ObFactory< T, Creator >::removeObCreator(Creator* creator)
+{
+   if(creator && creatorMap->erase( creator->getClassObjectTypeID() ) ) 
+      return true;
+
+   return false;
+}
+/*======================================================================*/
+template<class  T, typename Creator >
+Creator* ObFactory< T, Creator >::getCreator(const std::string& obtypeID)
+{
+   CreatorMapIt it = creatorMap.find(obtypeID);
+   if(it == creatorMap.end()) return NULL;
+
+   Creator* creator = it->second;
+   if(!creator) return NULL;
+
+   return creator;
+}
+/*======================================================================*/
+ template<class  T, typename Creator >
+ T* ObFactory< T, Creator >::createObject(const std::string& objectTypeID)
+ {
+    Creator* creator = this->getCreator(objectTypeID);
+    
+    if(!creator) 
+    {
+       UB_THROW( UbException(UB_EXARGS,"no creator avaivlable for ID="+objectTypeID ) );
+    }
+ 
+    return creator->createObject();
+ }
+/*======================================================================*/
+template<class  T, typename Creator >
+std::string ObFactory< T, Creator >::toString() 
+{
+   std::size_t maxL = 6;
+   for(CreatorMapIt it=creatorMap.begin(); it!=creatorMap.end(); ++it)
+      if( it->first.size() > maxL ) 
+         maxL = it->first.size();
+   
+   std::stringstream os;
+   os<<(std::string)typeid(*this).name()<<" - info:"<<std::endl;
+   os<<"   "<<std::left<<std::setw(maxL)<<"object"<<" <-> "<<"creator "<<std::endl;
+   for(CreatorMapIt it=creatorMap.begin(); it!=creatorMap.end(); ++it)
+      os<< " - " << std::setw(maxL) << it->first << " <-> " << (std::string)typeid(*it->second).name() << std::endl;
+
+   return os.str();
+}
+/*======================================================================*/
+
+#endif //OBFACTORY_H
diff --git a/source/VirtualFluidsCore/Basics/objects/ObObject.cpp b/source/VirtualFluidsCore/Basics/objects/ObObject.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..452791ad8f43507c069ea9e90e59193fd39334f6
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObObject.cpp
@@ -0,0 +1,10 @@
+//#include <basics/objects/ObObject.h>
+
+// ObObject::ObObject()
+// { 
+// }
+// /*=======================================*/
+// std::string ObObject::getName()
+// {
+//    return name;
+// }
diff --git a/source/VirtualFluidsCore/Basics/objects/ObObject.h b/source/VirtualFluidsCore/Basics/objects/ObObject.h
new file mode 100644
index 0000000000000000000000000000000000000000..aeb3ed9c48bb7bbe0b58fc534c6c2313d17ce35b
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObObject.h
@@ -0,0 +1,60 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBOBJECT_H
+#define OBOBJECT_H
+
+#include <string>
+
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/utilities/UbObservable.h>
+
+#ifdef CAB_RCF
+#include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+
+class ObObjectCreator;
+
+class ObObject : public UbObservable
+{
+public:
+   ObObject() : name("") { }
+   ObObject(const std::string& name) : name(name) { }
+
+   virtual ~ObObject() { }
+
+   virtual ObObject*   clone()=0;
+   virtual std::string getTypeID()=0;
+
+   virtual std::string getName()  { return name; }
+   void setName(std::string name) { this->name=name; }
+
+   virtual std::string toString()=0;
+
+   virtual ObObjectCreator* getCreator()=0;
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar) 
+   {
+      //SF::SF_SERIALIZE_PARENT<UbObservable>(ar, *this);
+      SF_SERIALIZE_PARENT<UbObservable>(ar, *this);
+      ar & name;
+   }
+#endif //CAB_RCF
+
+private:
+   std::string name;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+SF_NO_CTOR(ObObject);
+UB_AUTO_RUN_NAMED( ( SF::registerType<ObObject>("ObObject") ),                SF_ObObject     );
+UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived<UbObservable, ObObject >() ), SF_ObObject_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/VirtualFluidsCore/Basics/objects/ObObjectCreator.h b/source/VirtualFluidsCore/Basics/objects/ObObjectCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..540f422d5ddc6ef9320743bfbee4432a85225796
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObObjectCreator.h
@@ -0,0 +1,58 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBOBJECTCREATOR_H
+#define OBOBJECTCREATOR_H
+
+#include <string>
+
+class ObObject;
+class ObObjectManager;
+
+class Presentator;
+class QViewer;
+
+#ifdef CAB_QT 
+class QObObjectSpecificInstrument;
+class QWidget;
+class QActionGroup;
+#endif
+
+class ObObjectCreator
+{
+public:
+   virtual ~ObObjectCreator() {}
+
+	virtual ObObject* createObObject()=0;
+
+	virtual std::string getTypeID()	{ return "ObObject"; }
+	virtual std::string toString()	{ return "ObObjectCreator"; }
+   
+#ifdef CAB_QT 
+   //virtual Presentator* createObjectPresentator(ObObject *object)=0;
+   virtual Presentator* createObjectPresentator(ObObject *object) { return NULL; }
+   virtual QActionGroup* getSpecificPresentatorGroup(ObObject* object, QViewer *viewer, QWidget* parent) { return NULL; }
+   virtual QActionGroup* getSpecificActionGroup(ObObjectManager* manager, ObObject* object, QWidget* parent) 
+   { 
+      return NULL; 
+   }
+
+   virtual ObObject* createObObjectWithQt() { return NULL; }
+   virtual void showSpecificInstrument(ObObject* object, QWidget* parent=0) {}
+   virtual QObObjectSpecificInstrument* getSpecificInstrument() { return NULL; }
+   
+   //virtual QActionGroup *getSpecificContextMenuActionGroup() { return NULL; }
+#endif
+
+protected:
+	ObObjectCreator() {}
+
+private:
+   ObObjectCreator( const ObObjectCreator& );                  //no copy allowed 
+   const ObObjectCreator& operator=( const ObObjectCreator& ); //no copy allowed
+
+};
+#endif
diff --git a/source/VirtualFluidsCore/Basics/objects/ObObjectFactory.cpp b/source/VirtualFluidsCore/Basics/objects/ObObjectFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5cc03a78f2b2d550406e14a95cdbcffe22157e9c
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObObjectFactory.cpp
@@ -0,0 +1,54 @@
+#include <basics/objects/ObObjectFactory.h>
+
+/**** Eigene ****/
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/utilities/UbException.h>
+
+using namespace std;
+
+//ObObjectFactory::ObObjectFactory()
+//{
+//}
+//
+//ObObjectFactory::~ObObjectFactory()
+//{
+//}
+/*======================================================================*/  
+//ObObjectFactory* ObObjectFactory::getInstance()
+//{
+//	static ObObjectFactory instance;
+//	return &instance;
+//}
+/*======================================================================*/
+void ObObjectFactory::addObObjectCreator(ObObjectCreator *creator)
+{
+	//cout<<"Meth:"<<creator->toString()<<" Meth-ID:"<<creator->getTypeID()<<endl;
+	creatorSet.insert(std::pair<string, ObObjectCreator*>(creator->getTypeID(), creator));
+}
+/*======================================================================*/
+void ObObjectFactory::removeObObjectCreator(ObObjectCreator *creator)
+{
+	UB_THROW( UbException(UB_EXARGS,"not implemented") );
+}
+/*======================================================================*/
+ObObjectCreator* ObObjectFactory::getCreator(string objectType) 
+{
+	std::map<string, ObObjectCreator*>::iterator creatorIterator = creatorSet.find(objectType);
+	if(creatorIterator == creatorSet.end()) UB_THROW( UbException(UB_EXARGS,"factory has no creator for "+objectType) );
+	ObObjectCreator *creator = creatorIterator->second;
+	if(!creator) UB_THROW( UbException(UB_EXARGS,"no time series creator for type available") );
+	return creator;
+}
+/*======================================================================*/
+string ObObjectFactory::toString() 
+{
+   stringstream text;
+
+   std::map<string, ObObjectCreator*>::iterator creatorIterator;
+   std::map<string, ObObjectCreator*>* creatorSet = this->getCreatorSet();
+
+   for(creatorIterator = creatorSet->begin(); creatorIterator!=creatorSet->end(); ++creatorIterator)
+      text<<"   - "<<(creatorIterator->second)->toString()<<" for "<<(creatorIterator->first)<<endl;
+
+   return text.str();
+}
diff --git a/source/VirtualFluidsCore/Basics/objects/ObObjectFactory.h b/source/VirtualFluidsCore/Basics/objects/ObObjectFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..da8ef389c6ef433d96be6663eefaf34c9c99bd1c
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObObjectFactory.h
@@ -0,0 +1,42 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBOBJECTFACTORY_H
+#define OBOBJECTFACTORY_H
+
+#include <string>
+#include <map>
+
+class ObObjectCreator; 
+
+class ObObjectFactory
+{
+public:
+   ObObjectFactory() {}
+   virtual ~ObObjectFactory() {}
+
+   //static geht nicht, da abgeleitete Factories existieren ...
+   //static ObObjectFactory* getInstance();
+   //virtual ObObjectFactory* getInstance()=0;
+
+   ObObjectCreator* getCreator(std::string objectType);
+
+	void addObObjectCreator(ObObjectCreator* creator);
+	void removeObObjectCreator(ObObjectCreator* creator);
+
+   std::map<std::string, ObObjectCreator*>* getCreatorSet() { return &creatorSet;  }
+
+   virtual std::string toString();
+	
+private:
+   ObObjectFactory( const ObObjectFactory& );                  //no copy allowed 
+   const ObObjectFactory& operator=( const ObObjectFactory& ); //no copy allowed
+
+   std::map<std::string, ObObjectCreator*> creatorSet;
+};
+
+
+#endif //OBOBJECTFACTORY_H
diff --git a/source/VirtualFluidsCore/Basics/objects/ObObjectManager.cpp b/source/VirtualFluidsCore/Basics/objects/ObObjectManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..44bba546bf9e157bc21baff5d6e24aa8f3700786
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObObjectManager.cpp
@@ -0,0 +1,216 @@
+#include <basics/objects/ObObjectManager.h>
+#include <basics/objects/ObObject.h>
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/utilities/UbTableModel.h>
+#include <basics/utilities/UbException.h>
+
+using namespace std;
+
+ObObjectEntry::ObObjectEntry(ObObjectManager *parent, ObObject *object)
+{
+   this->parent = parent;
+   this->object = object;
+}
+/*======================================================*/
+ObObjectManager::ObObjectManager()
+{
+	this->selectedObject = NULL;
+	this->tableModel = NULL;
+}
+
+/*======================================================*/
+ObObjectManager::~ObObjectManager()
+{
+	//cerr<<"NEIN, notifyObserversObjectWillBeDeleted wird AUSSCHLIESSLICH von BasisKlasse aufgerufen!!!"<<endl;
+ //  cerr<<"das muss so sein, denn ansonsten duerfte diese funktion nur in der speziellen klasse stehen, da\n";
+ //  cerr<<"virtuelle destruktoren sich rekursiv vom speziellen ins allg. aufrufen --> notify.. wuerde\n";
+ //  cerr<<"oefters aufgerufen werden...\n";
+
+	this->objectList.clear();
+	if(this->tableModel) delete this->tableModel;
+}
+/*======================================================*/
+UbTableModel* ObObjectManager::getTableModel()
+{ 
+	return tableModel; 
+}
+/*======================================================*/
+//bool ObObjectManager::addObObject(ObObject *object)
+//{
+//   cout<<"ObObjectManager::addObObject "<<object->toString()<<endl;
+//	for(int pos=0; pos<(int)this->objectList.size(); pos++)
+//		if(this->objectList[pos]->object==object) 
+//			return false;
+//
+//	this->objectList.push_back(new ObObjectEntry(this,object));
+//	//object->addObserver(this);
+//	this->selectObObject(object);
+//	return true;
+//}
+/*======================================================*/
+bool ObObjectManager::addObObjectEntry(ObObjectEntry* objectEntry)
+{
+   for(int pos=0; pos<(int)this->objectList.size(); pos++)
+      if(this->objectList[pos]->object==objectEntry->object) 
+         return false;
+
+   this->objectList.push_back(objectEntry);
+//   objectEntry->getObject()->addObserver(this);
+   this->selectObObject(objectEntry->object);
+   return true;
+}
+/*======================================================*/
+bool ObObjectManager::removeObObject(ObObject* object)
+{
+	if (this->selectedObject == object) this->selectedObject=NULL;
+	for(int pos=0; pos<(int)this->objectList.size(); pos++)
+	{
+
+		if(this->objectList[pos]->object==object) 
+		{
+         return this->removeObObject(pos);
+//			this->objectList.erase(objectList.begin()+pos);
+//			//this->removeObserver(this);
+//			return true;
+		}
+	}
+	return false;
+}
+/*======================================================*/
+bool ObObjectManager::removeObObject(int index)
+{
+	try
+	{
+		if ( objectList[index]->object == this->selectedObject ) this->selectedObject=NULL;
+      //den entry loeschen ... das object im Entry ??? erstmal ausserhalb ...
+      delete objectList[index]; 
+		objectList.erase(objectList.begin()+index);
+   	this->notifyObserversObjectChanged();
+   	return true;
+	}
+	catch(const std::exception& e)  {  cerr<<e.what()<<endl;    }
+   catch(...)                      {  cerr<<"Fehler in ObObjectManager::removeObObject"<<endl; }
+   return false;
+}
+/*======================================================*/
+void ObObjectManager::removeAllObObjects() 
+{  
+	//TODO: implementieren!!
+	//foreach grid:
+	//grid->removeObserver(this);
+	//vector<ObObject*>::iterator it;
+	//for(it=objectList.begin();  it!=objectList.end(); it++)
+	//{
+	//	it->removeObserver(this);
+	//}
+// 	for(int i=0; i<(int)objectList.size(); i++)
+// 	{
+// 		delete objectList[i]->object->removeObserver(this);
+// 	} 
+	this->objectList.clear();
+	this->selectedObject = NULL;
+	this->notifyObserversObjectChanged();
+}
+/*======================================================*/
+int ObObjectManager::getNumberOfObObjects()
+{ 
+	return (int)this->objectList.size();
+}
+/*======================================================*/
+vector<ObObject*>* ObObjectManager::getAllObObjects()  
+{ 
+   UB_THROW( UbException(UB_EXARGS,"hier muss noch was getan werden") );
+//	return this->objectList;  
+}
+vector<ObObjectEntry*>* ObObjectManager::getAllObObjectEntries()
+{
+   return &this->objectList;  
+}
+/*======================================================*/
+ObObject* ObObjectManager::getObObject(int index)
+{
+	if(index <  0)                            return NULL;
+	if(index >= (int)this->objectList.size()) return NULL;
+
+	return(this->objectList[index]->object);
+}
+/*======================================================*/
+ObObjectEntry* ObObjectManager::getObObjectEntry(int index)
+{
+   if(index <  0)                            return NULL;
+   if(index >= (int)this->objectList.size()) return NULL;
+
+   return(this->objectList[index]);
+}
+/*====================================================*/
+string ObObjectManager::toString()
+{
+	stringstream ss; ss<<endl;
+
+	for(int pos=0; pos<(int)this->objectList.size(); pos++)          
+	{
+		ObObject* object = this->objectList[pos]->object;
+		ss<<(pos+1)<<". "<<object->toString()<<endl;
+	}
+	return ss.str();
+}
+/*======================================================*/
+void ObObjectManager::objectChanged(UbObservable* observable)
+{
+   //cout<<"ObObjectManager::objectChanged ??";
+	this->notifyObserversObjectChanged();
+}
+/*======================================================*/
+void ObObjectManager::objectWillBeDeleted(UbObservable* observable)
+{
+   cout<<"ObObjectManager::objectWillBeDeleted ??";
+	//observable->removeObserver(this);
+}
+/*======================================================*/
+bool ObObjectManager::selectObObject(int index)
+{
+   if((int)this->objectList.size()==0) 
+   {
+      this->selectedObject = NULL; return false; 
+   }
+	if (index > (int)this->objectList.size()-1 || index < 0) return false; 
+	if ( this->selectedObject == this->getObObject(index) ) return true;
+   
+	this->selectedObject = this->getObObject(index);
+   //cout<<this->getObserverList()->size()<<endl;
+
+	this->notifyObserversObjectChanged();
+	return true;
+}
+/*======================================================*/
+bool ObObjectManager::selectObObject(ObObject* object)
+{
+   if((int)this->objectList.size()==0) { this->selectedObject = NULL; return false; }
+	for(int pos=0; pos<(int)this->objectList.size(); pos++)
+	{
+		if(this->objectList[pos]->object==object) 
+		{
+			return this->selectObObject(pos);
+		}
+	}
+	return false;
+}
+/*======================================================*/
+ObObject* ObObjectManager::getSelectedObObject()
+{
+	return this->selectedObject;
+}
+/*======================================================*/
+int ObObjectManager::getSelectedIndex()
+{
+	for(int pos=0; pos<(int)this->objectList.size(); pos++)
+	{
+		if(this->objectList[pos]->object==this->selectedObject) 
+		{
+			return pos;
+		}
+	}
+	return -1;
+}
+/*======================================================*/
+
diff --git a/source/VirtualFluidsCore/Basics/objects/ObObjectManager.h b/source/VirtualFluidsCore/Basics/objects/ObObjectManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..632e124bf72f3a259f638f12116eeac2b661e61f
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/objects/ObObjectManager.h
@@ -0,0 +1,79 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef OBOBJECTMANAGER_H
+#define OBOBJECTMANAGER_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <basics/utilities/UbObservable.h>
+#include <basics/utilities/UbObserver.h>
+
+class UbException;
+class UbTableModel;
+class ObObjectManager;
+class ObObjectFactory;
+class ObObject;
+
+
+class ObObjectEntry
+{
+   friend class ObObjectManager;
+public:
+   ObObjectManager* getParent() { return parent; }
+   ObObject*        getObject() { return object; }
+   
+   ObObjectEntry(ObObjectManager* parent, ObObject* object);
+   virtual ~ObObjectEntry() {  }
+
+protected:
+   ObObjectManager* parent;
+   ObObject* object;
+};
+
+
+class ObObjectManager : public UbObservable, public UbObserver
+{
+public:
+	ObObjectManager();
+	~ObObjectManager();
+	
+   //virtual bool addObObject(ObObject* object);   
+   virtual bool addObObjectEntry(ObObjectEntry* objectEntry);
+
+   virtual ObObjectEntry* createNewObObjectEntry(ObObject* obj) { return new ObObjectEntry(this, obj); }
+
+	bool removeObObject(ObObject* object);
+	bool removeObObject(int index);
+	void removeAllObObjects();
+	bool selectObObject(int index);
+	bool selectObObject(ObObject* object);
+	ObObject* getSelectedObObject();
+	int getSelectedIndex();
+
+	int getNumberOfObObjects();                 
+   std::vector<ObObject*>* getAllObObjects();
+   std::vector<ObObjectEntry*>* getAllObObjectEntries();
+	ObObject* getObObject(int index);
+   ObObjectEntry* getObObjectEntry(int index);
+
+	std::string toString();
+
+	virtual void objectChanged(UbObservable* observable);
+	virtual void objectWillBeDeleted(UbObservable* observable);
+
+	UbTableModel* getTableModel();
+   virtual ObObjectFactory* getObObjectFactory()=0;
+
+protected:
+	 std::vector<ObObjectEntry*> objectList;
+	 ObObject* selectedObject;
+	 UbTableModel* tableModel;
+};
+
+#endif //OBOBJECTMANAGER_H
diff --git a/source/VirtualFluidsCore/Basics/transmitter/CMakePackage.txt b/source/VirtualFluidsCore/Basics/transmitter/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de1dc5a88225180b8e40c6cf46f4a6fbb102778f
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
\ No newline at end of file
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitter.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitter.h
new file mode 100644
index 0000000000000000000000000000000000000000..9560e8a771c5c4892579aa38d119bca67c45a354
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitter.h
@@ -0,0 +1,69 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTER_H
+#define TBTRANSMITTER_H
+
+#include <string>
+
+/*================================================================================*/
+/*  TbTransmitter                                                                 */
+/*                                                                                */
+/**
+This Class provides the base for sending and receiving of data.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+*/ 
+
+/*
+usage: ...
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// Transmitter 
+// macht nichts ausser daten senden und empfangen
+template<typename T>
+class TbTransmitter
+{
+public:
+   typedef T value_type;
+
+public:
+   TbTransmitter() {}
+   virtual ~TbTransmitter()  {  /*std::cout<<typeid(*this).name()<<" dtor"<<std::endl;*/  }
+
+   virtual bool isLocalTransmitter()  const = 0;
+   virtual bool isRemoteTransmitter() const = 0;
+
+   //preprocess (e.g. synchronizing send-/receive-buffer)
+   virtual void sendDataSize()   = 0;
+   virtual void receiveDataSize()= 0; 
+   
+   //calculation
+   virtual void        prepareForSend() {}
+   virtual void        sendData()=0;
+   virtual void        prepareForReceive() {}
+   virtual value_type& receiveData()=0;
+   virtual void        saveData() {}
+
+   //data-access
+   inline value_type&       getData()       { return this->data; }
+   inline const value_type& getData() const { return this->data; }
+
+   //info-section (usable for remote transmitter)
+   virtual int  getSendToRank()   const { return  -1; }
+   virtual int  getSendToTag()    const { return  -1; }
+   virtual int  getRecvFromRank() const { return  -1; }
+   virtual int  getRecvFromTag()  const { return  -1; }
+
+   virtual std::string toString() const = 0;
+
+protected:
+   value_type data;
+};
+
+#endif //TBTRANSMITTER_H 
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterLocal.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterLocal.h
new file mode 100644
index 0000000000000000000000000000000000000000..981f880c143d4ed614dfc8cc2c20e6684de91f8a
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterLocal.h
@@ -0,0 +1,130 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TOTRANSMITTERLOCAL_H
+#define TOTRANSMITTERLOCAL_H
+
+#include <basics/utilities/UbException.h>
+#include <basics/transmitter/TbTransmitter.h>
+
+#include <boost/shared_ptr.hpp>
+
+/*================================================================================*/
+/*   TbLocalTransmitter, TbVectorSenderLocal, TbVectorReceiverLocal               */
+/*                                                                                */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+*/ 
+
+/*
+usage: ...
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// LocalTransmitter lokalen Datenaustausch
+// data = send- und zugleich receive-buffer
+template<typename T>
+class TbLocalTransmitter : public TbTransmitter<T>
+{
+public:
+   typedef boost::shared_ptr< TbLocalTransmitter<T> > TbLocalTransmitterPtr;
+
+   typedef T value_type;
+
+public:
+   TbLocalTransmitter() : TbTransmitter<T>() 
+   {
+
+   }
+   
+   bool isLocalTransmitter()  const { return true;                         }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   //send buffer wird autom resized
+   void sendDataSize()    { }
+   //reiceive braucht nichts machen, da send==receive buffer ;-)
+   void receiveDataSize() { } 
+
+   void        sendData()    { }
+   value_type& receiveData() { return this->data; }
+
+   std::string toString()  const { return "TbLocalTransmitter"+(std::string)typeid(T).name(); }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSender/ReceiverLocal lokalen Datenaustausch ueber ZWEI vektoren
+template<typename T>
+class TbVectorReceiverLocal : public TbTransmitter<T>
+{
+public:
+   typedef T value_type;
+
+public:
+   TbVectorReceiverLocal() : TbTransmitter<value_type>() 
+   {
+
+   }
+   //virtual ~TbVectorReceiverLocal() { std::cout<<typeid(*this).name()<<" tot"<<std::endl;   }
+
+   bool isLocalTransmitter()  const { return true;                         }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   //send buffer wird autom resized
+   void sendDataSize()    { UB_THROW( UbException(UB_EXARGS,"empfaengt nur") ); }
+   //reiceive braucht nichts machen, das macht der sender :-)
+   void receiveDataSize() { } 
+
+   void         sendData()    { UB_THROW( UbException(UB_EXARGS,"empfaengt nur") ); }
+   value_type&  receiveData() { return this->data; }
+
+   std::string toString() const { return "TbVectorReceiverLocal<"+(std::string)typeid(T).name()+">"; }
+};
+
+template<typename T>
+class TbVectorSenderLocal : public TbTransmitter<T>
+{
+public:
+   typedef T value_type;
+
+public:
+   TbVectorSenderLocal(boost::shared_ptr< TbVectorReceiverLocal< value_type > > receiver) 
+      : TbTransmitter< value_type >(), receiver(receiver) 
+   {
+
+   }
+   //virtual ~TbVectorSenderLocal() { std::cout<<typeid(*this).name()<<" tot"<<std::endl;   }
+
+   bool isLocalTransmitter()  const { return true;                         }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   //send buffer wird autom resized
+   void sendDataSize()  
+   { 
+      assert(receiver!=NULL); 
+      receiver->getData().resize( this->data.size() ); 
+   }
+   //reiceive braucht nichts machen, da send==receive buffer ;-)
+   void receiveDataSize()  { UB_THROW( UbException(UB_EXARGS,"sendet nur") ); } 
+   
+   void sendData()    
+   { 
+      assert( this->data.size() == receiver->getData().size() );
+      receiver->getData() = this->data;
+//       for(int i=(int)this->data.size()-1; i>=0; --i)
+//          receiver->getData()[i]= this->data[i];
+   }
+   value_type& receiveData() { UB_THROW( UbException(UB_EXARGS,"sendet nur") ); }
+
+   std::string toString() const { return "TbVectorSenderLocal<"+(std::string)typeid(T).name()+">"; }
+
+protected:
+   boost::shared_ptr< TbVectorReceiverLocal< value_type > > receiver; 
+};
+                                        
+#endif //TOTRANSMITTERLOCAL_H 
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpi.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpi.h
new file mode 100644
index 0000000000000000000000000000000000000000..16d5f8c7f986b9b6832f999be80f6ee5dc81aa76
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpi.h
@@ -0,0 +1,237 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPI_H
+#define TBTRANSMITTERMPI_H
+
+#ifdef VF_MPI
+
+/*=========================================================================*/
+/*  MPI Transmitter                                                        */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+Old TbTransmitter was renamed in TbTransmitterCPPB (C++ binding in MPI is deprecated)
+Rewrite from K. Kucher with C binding
+<BR><BR>
+@author <A HREF="mailto:kucher@irmb.tu-bs.de">K. Kucher</A>
+@version 1.0 - 21.11.11
+*/ 
+
+/*
+usage: ...
+*/
+
+#include <iostream>
+#include <mpi.h>
+#include <basics/transmitter/TbTransmitter.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderMpiUnblocked
+template< typename Vector  >
+class TbVectorSenderMpiUnblocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorSenderMpiUnblocked(const int& sendTbRank, const int& sendTag, MPI_Comm comm) 
+      : comm(comm), request(MPI_REQUEST_NULL), sendTbRank(sendTbRank), sendTag(sendTag), dataSize(0)    
+   { 
+      //temporaeren vector erstellen um den datentyp zu ermittlen
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for type="+(std::string)typeid(typename Vector::value_type).name()) );
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()   
+   {
+      dataSize = (unsigned int)this->getData().size();
+      //MPI_Isend(&dataSize, 1, MPI_UNSIGNED, sendTbRank, sendTag, comm, &request);
+      MPI_Send(&dataSize, 1, MPI_UNSIGNED, sendTbRank, sendTag, comm);
+   }  
+   void receiveDataSize()   { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   void prepareForSend()    { if(request!=MPI_REQUEST_NULL) MPI_Wait(&request, &status); }
+   void sendData()          { MPI_Isend(&this->getData()[0],(int)this->getData().size(), mpiDataType, sendTbRank, sendTag, comm, &request);  }
+
+   void prepareForReceive() { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   Vector& receiveData()    { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  sendTbRank; }
+   int  getSendTbTag()    const { return  sendTag;    }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   std::string toString()  const { return "TbVectorSenderMpiUnblocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(sendTbRank)+"("+UbSystem::toString(sendTag)+")"; }
+
+protected:
+   MPI_Comm comm;
+   MPI_Request   request;
+   MPI_Datatype  mpiDataType;
+   MPI_Status    status;
+   int sendTbRank, sendTag;
+   unsigned dataSize;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderMpiBlocked
+template< typename Vector  >
+class TbVectorSenderMpiBlocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorSenderMpiBlocked(const int& sendTbRank, const int& sendTag, MPI_Comm comm) 
+      : comm(comm), request(MPI_REQUEST_NULL), sendTbRank(sendTbRank), sendTag(sendTag), dataSize(0)    
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector"+(std::string)typeid(Vector).name()) );
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()   
+   {
+      dataSize = (unsigned int)this->getData().size();
+      MPI_Isend(&dataSize, 1, MPI_UNSIGNED, sendTbRank, sendTag, comm, &request);
+   }  
+   void receiveDataSize()   { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   void sendData()          { MPI_Wait(&request, &status); MPI_Send(&this->getData()[0],(int)this->getData().size(), mpiDataType, sendTbRank, sendTag, comm); }
+
+   void prepareForReceive()  { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   value_type& receiveData() { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  sendTbRank; }
+   int  getSendTbTag()    const { return  sendTag;    }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   std::string toString() const { return "TbVectorSenderMpiBlocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(sendTbRank)+"("+UbSystem::toString(sendTag)+")"; }
+
+protected:
+   MPI_Comm comm;
+   MPI_Request   request;
+   MPI_Datatype  mpiDataType;
+   MPI_Status    status;
+   int sendTbRank, sendTag;
+   unsigned dataSize;
+};
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorReceiverMpiUnblocked
+template<typename Vector  >
+class TbVectorReceiverMpiUnblocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorReceiverMpiUnblocked(const int& receiveFromRank, const int& receiveTag, MPI_Comm comm) 
+      : comm(comm), request(MPI_REQUEST_NULL), receiveFromRank(receiveFromRank), receiveTag(receiveTag)       
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector"+(std::string)typeid(Vector).name()) );
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()     { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   void receiveDataSize()   
+   {
+      unsigned dataSize;
+      MPI_Recv(&dataSize, 1, MPI_UNSIGNED, receiveFromRank, receiveTag, comm, &status);
+      this->getData().resize(dataSize,0.0);
+   }  
+   void sendData()          { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+
+   void prepareForReceive() { MPI_Irecv(&this->getData()[0],(int)this->getData().size(), mpiDataType, receiveFromRank, receiveTag, comm, &request);  }
+   Vector& receiveData()    { MPI_Wait(&request, &status); return this->getData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getSendTbTag()    const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getRecvFromRank() const { return  receiveFromRank; }
+   int  getRecvFromTag()  const { return  receiveTag;      }
+
+   std::string toString() const { return "TbVectorReceiverMpiUnblocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(receiveFromRank)+"("+UbSystem::toString(receiveTag)+")"; }
+
+protected:
+   MPI_Comm comm;
+   MPI_Request   request;
+   MPI_Datatype  mpiDataType;
+   MPI_Status    status;
+   int receiveFromRank, receiveTag;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+template<typename Vector>
+class TbVectorReceiverMpiBlocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorReceiverMpiBlocked(const int& receiveFromRank, const int& receiveTag, MPI_Comm comm) 
+      : comm(comm), request(MPI_REQUEST_NULL), receiveFromRank(receiveFromRank), receiveTag(receiveTag)
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector+(std::string)typeid(Vector).name()") );
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()     { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   void receiveDataSize()   
+   {
+      unsigned dataSize;
+      MPI_Recv(&dataSize, 1, MPI_UNSIGNED, receiveFromRank, receiveTag, comm, &status);
+      this->getData().resize(dataSize,0.0);
+   }  
+   void sendData()         { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   Vector& receiveData()
+   {
+      MPI_Recv(&this->getData()[0],(int)this->getData().size(), mpiDataType, receiveFromRank, receiveTag, comm, &status);
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getSendTbTag()    const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getRecvFromRank() const { return  receiveFromRank; }
+   int  getRecvFromTag()  const { return  receiveTag;      }
+
+   std::string toString() const { return "TbVectorReceiverMpiBlocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(receiveFromRank)+"("+UbSystem::toString(receiveTag)+")"; }
+
+protected:
+   MPI_Comm comm;
+   MPI_Request   request;
+   MPI_Datatype  mpiDataType;
+   MPI_Status    status;
+   int receiveFromRank, receiveTag;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPI_H
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiCPPB.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiCPPB.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a08a867cb24be0dbbace7570756a5283daf953b
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiCPPB.h
@@ -0,0 +1,230 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPICPPB_H
+#define TBTRANSMITTERMPICPPB_H
+
+#ifdef VF_MPI
+
+/*=========================================================================*/
+/*  MPI Transmitter                                                        */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+*/ 
+
+/*
+usage: ...
+*/
+
+#include <iostream>
+#include <mpi.h>
+#include <basics/transmitter/TbTransmitter.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderMpiUnblocked
+template< typename Vector  >
+class TbVectorSenderMpiUnblocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorSenderMpiUnblocked(const int& sendTbRank, const int& sendTag, MPI::Intracomm comm) 
+      : comm(comm), request(MPI::REQUEST_NULL), sendTbRank(sendTbRank), sendTag(sendTag), dataSize(0)    
+   { 
+      //temporaeren vector erstellen um den datentyp zu ermittlen
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for type="+(std::string)typeid(typename Vector::value_type).name()) );
+   }
+   
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()   
+   {
+      dataSize = (unsigned int)this->getData().size();
+      request = comm.Isend(&dataSize, 1, MPI::UNSIGNED, sendTbRank, sendTag);
+   }  
+   void receiveDataSize()   { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   void prepareForSend()    { if(request!=MPI::REQUEST_NULL) request.Wait(); }
+   void sendData()          { request = comm.Isend(&this->getData()[0],(int)this->getData().size(), mpiDataType, sendTbRank, sendTag);  }
+   
+   void prepareForReceive() { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   Vector& receiveData()    { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  sendTbRank; }
+   int  getSendTbTag()    const { return  sendTag;    }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   std::string toString()  const { return "TbVectorSenderMpiUnblocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(sendTbRank)+"("+UbSystem::toString(sendTag)+")"; }
+
+protected:
+   MPI::Intracomm comm;
+   MPI::Request   request;
+   MPI::Datatype  mpiDataType;
+   int sendTbRank, sendTag;
+   unsigned dataSize;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderMpiBlocked
+template< typename Vector  >
+class TbVectorSenderMpiBlocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorSenderMpiBlocked(const int& sendTbRank, const int& sendTag, MPI::Intracomm comm) 
+      : comm(comm), request(MPI::REQUEST_NULL), sendTbRank(sendTbRank), sendTag(sendTag), dataSize(0)    
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector"+(std::string)typeid(Vector).name()) );
+   }
+   
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()   
+   {
+      dataSize = (unsigned int)this->getData().size();
+      request = comm.Isend(&dataSize, 1, MPI::UNSIGNED, sendTbRank, sendTag);
+   }  
+   void receiveDataSize()   { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   void sendData()          { request.Wait(); comm.Send(&this->getData()[0],(int)this->getData().size(), mpiDataType, sendTbRank, sendTag); }
+   
+   void prepareForReceive()  { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   value_type& receiveData() { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  sendTbRank; }
+   int  getSendTbTag()    const { return  sendTag;    }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"MPIVectorSender sends only") ); }
+
+   std::string toString() const { return "TbVectorSenderMpiBlocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(sendTbRank)+"("+UbSystem::toString(sendTag)+")"; }
+
+protected:
+   MPI::Intracomm comm;
+   MPI::Request   request;
+   MPI::Datatype  mpiDataType;
+   int sendTbRank, sendTag;
+   unsigned dataSize;
+};
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorReceiverMpiUnblocked
+template<typename Vector  >
+class TbVectorReceiverMpiUnblocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorReceiverMpiUnblocked(const int& receiveFromRank, const int& receiveTag, MPI::Intracomm comm) 
+      : comm(comm), request(MPI::REQUEST_NULL), receiveFromRank(receiveFromRank), receiveTag(receiveTag)       
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector"+(std::string)typeid(Vector).name()) );
+   }
+   
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()     { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   void receiveDataSize()   
+   {
+      unsigned dataSize;
+      comm.Recv(&dataSize, 1, MPI::UNSIGNED, receiveFromRank, receiveTag);
+      this->getData().resize(dataSize,0.0);
+   }  
+   void sendData()          { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   
+   void prepareForReceive() { request = comm.Irecv(&this->getData()[0],(int)this->getData().size(), mpiDataType, receiveFromRank, receiveTag);  }
+   Vector& receiveData()    { request.Wait(); return this->getData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getSendTbTag()    const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getRecvFromRank() const { return  receiveFromRank; }
+   int  getRecvFromTag()  const { return  receiveTag;      }
+
+   std::string toString() const { return "TbVectorReceiverMpiUnblocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(receiveFromRank)+"("+UbSystem::toString(receiveTag)+")"; }
+
+protected:
+   MPI::Intracomm comm;
+   MPI::Request   request;
+   MPI::Datatype  mpiDataType;
+   int receiveFromRank, receiveTag;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+template<typename Vector>
+class TbVectorReceiverMpiBlocked : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;
+
+public:
+   TbVectorReceiverMpiBlocked(const int& receiveFromRank, const int& receiveTag, MPI::Intracomm comm) 
+      : comm(comm), request(MPI::REQUEST_NULL), receiveFromRank(receiveFromRank), receiveTag(receiveTag)
+   { 
+      if     ( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(typename Vector::value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else UB_THROW( UbException(UB_EXARGS,"no MpiDataType for Vector+(std::string)typeid(Vector).name()") );
+   }
+   
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()     { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   void receiveDataSize()   
+   {
+      unsigned dataSize;
+      comm.Recv(&dataSize, 1, MPI::UNSIGNED, receiveFromRank, receiveTag);
+      this->getData().resize(dataSize,0.0);
+   }  
+   void sendData()         { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   Vector& receiveData()
+   {
+      comm.Recv(&this->getData()[0],(int)this->getData().size(), mpiDataType, receiveFromRank, receiveTag);
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getSendTbTag()    const { UB_THROW( UbException(UB_EXARGS,"MPIVectorReceiver receives only") ); }
+   int  getRecvFromRank() const { return  receiveFromRank; }
+   int  getRecvFromTag()  const { return  receiveTag;      }
+
+   std::string toString() const { return "TbVectorReceiverMpiBlocked<"+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name()+"> > to rank (tag)"+UbSystem::toString(receiveFromRank)+"("+UbSystem::toString(receiveTag)+")"; }
+
+protected:
+   MPI::Intracomm comm;
+   MPI::Request   request;
+   MPI::Datatype  mpiDataType;
+   int receiveFromRank, receiveTag;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPI_H
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd406ac49c4c49bd5245ea5a483bffb40fbbf75b
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool.h
@@ -0,0 +1,510 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPIPOOL_H
+#define TBTRANSMITTERMPIPOOL_H
+
+#ifdef VF_MPI
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+#include <boost/shared_ptr.hpp>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorMpiPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder MpiPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbMpiVectorPool verwaltet
+//MpiPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderMpiPool;
+template<typename T> class TbCbVectorReceiverMpiPool;
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorMpiPool : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorMpiPool< T > > MpiPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map<unsigned int, MpiPoolPtr >      MpiPoolPtrMap;
+   typedef typename MpiPoolPtrMap::iterator MpiPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned int CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderMpiPool< T >; 
+   friend class TbCbVectorReceiverMpiPool< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static MpiPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createTbCbVectorMpiPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   // mpiRemoteRank: mpi-rank des Empfaengers/Senders
+   // mpiTag       : mpi-tag mit dem empfangen/gesendet wird
+   static MpiPoolPtr createTbCbVectorMpiPool(CbVectorKey poolKey, int mpiRemoteRank, int mpiTag, MPI_Comm comm, size_type startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+
+      //pool erstellen
+      MpiPoolPtr mpiPool(new TbCbVectorMpiPool<T>(poolKey, mpiRemoteRank, mpiTag, comm, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorMpiPool< value_type >::poolMap[poolKey] = mpiPool;
+
+      return mpiPool; 
+   }
+   static void deleteTbCbVectorMpiPool(CbVectorKey poolKey)
+   {
+      MpiPoolPtrMapIter it = TbCbVectorMpiPool< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorMpiPool< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static MpiPoolPtr getTbCbVectorMpiPool(CbVectorKey poolKey)
+   {
+      MpiPoolPtrMapIter it;
+      if( (it=TbCbVectorMpiPool< T >::poolMap.find(poolKey))!=TbCbVectorMpiPool< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return MpiPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorMpiPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void eraseMap()
+   {
+      poolMap.clear();
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   TbCbVectorMpiPool(CbVectorKey poolKey, int mpiRemoteRank, int mpiTag, MPI_Comm comm, size_type startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI_REQUEST_NULL)
+      , sendRequest(MPI_REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+
+public:
+   /*==================================================================*/
+   //returns key of Pool in MpiPoolMap
+   CbVectorKey  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->mpiRemoteRank; }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->mpiTag;        }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         //allg.: bei MPI muss man darauf achten, dass bei unblocked operationen die puffer (aus dem oder in den 
+         //geschrieben wird auch noch vorhanden sind!!! wuerde man hier z.B. einen lokalen vector mit Isend() los-
+         //schicken, dann wurde der scope verlassen werden und der vector evtl geloescht werden, bevor mpi den
+         //vorgang abgeschlossen hat!!! ->  tmpOrderVec ist class-member!!!
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         unsigned index = 0;
+         tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+         MPI_Isend(&tmpSendOrderVec[0],(int)tmpSendOrderVec.size(), MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, &sendRequest);
+
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         //receiveRequest.Wait();
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+
+         //MPI_Status status;
+         MPI_Recv(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, MPI_STATUS_IGNORE);
+
+         if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+            throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+            //if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               //throw UbException(UB_EXARGS, "entweder hat map nicht die gleiche reihenfolge oder vectorKey = "+UbSystem::toString(vectorKey)+" nicht vorhanden");
+            if (it==this->cbVectorMap.end())
+               throw UbException(UB_EXARGS,"map ist leer");
+            else if (it->first != vectorKey)
+               throw UbException(UB_EXARGS, "vectorKey = "+UbSystem::toString(vectorKey)+" nicht vorhanden it->first =" + UbSystem::toString(it->first));
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&sendRequest, MPI_STATUS_IGNORE);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+
+
+      //A - non blocking
+      ////der ERSTE is entscheidend 
+      ////Grund: wenn man 
+      //// for(all trans) { trans->prepare(); trans->fillBuffer(); }
+      //// aufruft, dann wuerde u.U. der Buffer neu beschrieben werden obwohl noch nicht versendet wurde!!!
+      //counterPrepareForSend++;
+      //if(counterPrepareForSend==1)
+      //{
+      //   if(sendRequest != MPI::REQUEST_NULL) sendRequest.Wait();
+      //}
+      //
+      //if(counterPrepareForSend==nofStoredVectors)
+      //   counterPrepareForSend=0;  
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      //A - non blocking
+      //der LETZTE is entscheidend 
+      //counterSend++;
+      //if(counterSend==nofStoredVectors)
+      //{
+      //   //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+      //   sendRequest = comm.Isend(&pool[0],(int)nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //   counterSend=0;
+      //}
+      //B - blocking
+      //der LETZTE is entscheidend 
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+         //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         //synchronous send 
+         //comm.Ssend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+
+         //standard send
+         MPI_Send(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+////////////////////////////////////////////////////////////////////////////////////////////
+//DEBUG///////////////////////////////////////
+         //int irank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &irank);
+         //std::cout << "MPI_Send: " << irank <<  " "  << mpiRemoteRank << " "  <<mpiTag<<std::endl;
+///////////////////////////////////////////////////
+         counterSend=0;
+      }                           
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+      //A - non blocking
+      //sobald der Letzte kann man den den request holen.
+      //andernfalls kann nicht gewaehrleistet werden, dass evtl noch mit dem buffer gearbeitet wird!!!
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         MPI_Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         counterPrepareForReceive=0;
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      //A - non blocking
+      //sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      //denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      if(counterReceive==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+      counterReceive++;
+      if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+
+      ////B - blocking
+      ////sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      ////denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      //if(counterReceive==0)
+      //{
+      //   comm.Recv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //}
+      //counterReceive++;
+      //if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      //   counterReceive=0;
+   }
+
+protected:
+   CbVectorKey poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   std::vector< unsigned > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+
+   MPI_Comm     comm;
+   MPI_Request  receiveRequest;
+   MPI_Request  sendRequest;
+   //MPI_Status   sendStatus;
+   //MPI_Status   receiveStatus;
+   MPI_Datatype mpiDataType;
+
+   int mpiRemoteRank, mpiTag;
+
+#ifdef _DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorMpiPool<T>::MpiPoolPtrMap TbCbVectorMpiPool<T>::poolMap;
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderMpiPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderMpiPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;
+
+public:
+   TbCbVectorSenderMpiPool(unsigned int cbVectorKey, TbCbVectorMpiPool< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->mpiVectorPool) );
+   }
+   ~TbCbVectorSenderMpiPool()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->mpiVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }
+   void prepareForSend()        { this->mpiVectorPool->prepareForSendData(); }
+   void sendData()              { this->mpiVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->mpiVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->mpiVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool<T>* mpiVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverMpiPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverMpiPool(unsigned int cbVectorKey, TbCbVectorMpiPool< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->mpiVectorPool) );
+   }
+   ~TbCbVectorReceiverMpiPool()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only");  }   
+   void receiveDataSize()   { this->mpiVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   void prepareForReceive() { this->mpiVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->mpiVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getRecvFromRank() const { return  this->mpiVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->mpiVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool<T>* mpiVectorPool;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPIPOOL_H
+ 
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool2.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool2.h
new file mode 100644
index 0000000000000000000000000000000000000000..e09d9f4c295be8f1e95ed84eea90389f7fe22f98
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool2.h
@@ -0,0 +1,453 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPIPOOL2_H
+#define TBTRANSMITTERMPIPOOL2_H
+
+#ifdef VF_MPI
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorMpiPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder MpiPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbMpiVectorPool verwaltet
+//MpiPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderMpiPool2;
+template<typename T> class TbCbVectorReceiverMpiPool2;
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorMpiPool2 : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorMpiPool2< T > > MpiPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< int, MpiPoolPtr >      MpiPoolPtrMap;
+   typedef typename MpiPoolPtrMap::iterator MpiPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderMpiPool2< T >; 
+   friend class TbCbVectorReceiverMpiPool2< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static MpiPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createTbCbVectorMpiPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   // mpiRemoteRank: mpi-rank des Empfaengers/Senders
+   // mpiTag       : mpi-tag mit dem empfangen/gesendet wird
+static MpiPoolPtr createTbCbVectorMpiPool(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI_Comm comm, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+      //pool erstellen
+      MpiPoolPtr mpiPool(new TbCbVectorMpiPool2<T>(poolKey, mpiRemoteRank, mpiTag, comm, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorMpiPool2< value_type >::poolMap[poolKey] = mpiPool;
+
+      return mpiPool; 
+   }
+   static void deleteTbCbVectorMpiPool(const int& poolKey)
+   {
+      MpiPoolPtrMapIter it = TbCbVectorMpiPool2< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorMpiPool2< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static MpiPoolPtr getTbCbVectorMpiPool(const int& poolKey)
+   {
+      MpiPoolPtrMapIter it;
+      if( (it=TbCbVectorMpiPool2< T >::poolMap.find(poolKey))!=TbCbVectorMpiPool2< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return MpiPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorMpiPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+TbCbVectorMpiPool2(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI_Comm comm, const size_type& startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI_REQUEST_NULL)
+      , sendRequest(MPI_REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+
+public:
+   /*==================================================================*/
+   //returns key of Pool in MpiPoolMap
+   int  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->mpiRemoteRank; }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->mpiTag;        }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         //allg.: bei MPI muss man darauf achten, dass bei unblocked operationen die puffer (aus dem oder in den 
+         //geschrieben wird auch noch vorhanden sind!!! wuerde man hier z.B. einen lokalen vector mit Isend() los-
+         //schicken, dann wurde der scope verlassen werden und der vector evtl geloescht werden, bevor mpi den
+         //vorgang abgeschlossen hat!!! ->  tmpOrderVec ist class-member!!!
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         unsigned index = 0;
+         tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+
+         MPI_Isend(&tmpSendOrderVec[0],(int)tmpSendOrderVec.size(), MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, &sendRequest);
+
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+
+         MPI_Irecv(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+         //MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+
+         //if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+         //   throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         //unsigned index = 0;
+         //this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         //this->pool.resize(this->nextCbVectorStartIndexInPool);
+         //CbVectorMapIter it = this->cbVectorMap.begin();
+         //for(/*index*/; index<nofElements; index+=3, ++it)
+         //{
+         //   CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+         //   size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+         //   size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+         //   if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+         //      throw UbException(UB_EXARGS,"entweder hat map nicht die gleiche reihenfolge oder vectorKey nicht vorhanden");
+
+         //   this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         //}
+         //if(it!=this->cbVectorMap.end())
+         //   throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void saveDataOrder()
+   {
+      if(counterPrepareForSend==0)
+      {
+         if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&sendRequest, MPI_STATUS_IGNORE);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      //A - non blocking
+      //der LETZTE is entscheidend 
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+#ifdef DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         MPI_Isend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &sendRequest);
+////////////////////////////////////////////////////////////////////////////////////////////
+         counterSend=0;
+      }                           
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      //A - non blocking
+      //sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      //denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      //if(counterReceive==0)
+      //{
+      //   MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+      //}
+      //counterReceive++;
+      //if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      //{
+      //   counterReceive=0;
+      //}
+
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+#ifdef DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         MPI_Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+         MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+         counterPrepareForReceive=0;
+      }
+   }
+
+protected:
+   int       poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   std::vector< unsigned > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+
+   MPI_Comm     comm;
+   MPI_Request  receiveRequest;
+   MPI_Request  sendRequest;
+   MPI_Datatype mpiDataType;
+   int mpiRemoteRank, mpiTag;
+
+#ifdef DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorMpiPool2<T>::MpiPoolPtrMap TbCbVectorMpiPool2<T>::poolMap;
+
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderMpiPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderMpiPool2 : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorSenderMpiPool2(const unsigned int& cbVectorKey, TbCbVectorMpiPool2< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->mpiVectorPool) );
+   }
+   ~TbCbVectorSenderMpiPool2()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool2< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->mpiVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }
+   void prepareForSend()        { this->mpiVectorPool->prepareForSendData(); }
+   void sendData()              { this->mpiVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->mpiVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->mpiVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool2<T>* mpiVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverMpiPool2 : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverMpiPool2(const unsigned int& cbVectorKey, TbCbVectorMpiPool2< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->mpiVectorPool) );
+   }
+   ~TbCbVectorReceiverMpiPool2()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool2< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only");  }   
+   void receiveDataSize()   { this->mpiVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   void prepareForReceive() { this->mpiVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->mpiVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getRecvFromRank() const { return  this->mpiVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->mpiVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool2<T>* mpiVectorPool;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPIPOOL_H
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool3.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool3.h
new file mode 100644
index 0000000000000000000000000000000000000000..1666ecf080a9a4a1dceb22108eed952dddd1e0b0
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPool3.h
@@ -0,0 +1,530 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPIPOOL_H
+#define TBTRANSMITTERMPIPOOL_H
+
+#ifdef VF_MPI
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+#include <boost/shared_ptr.hpp>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorMpiPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder MpiPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbMpiVectorPool verwaltet
+//MpiPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderMpiPool;
+template<typename T> class TbCbVectorReceiverMpiPool;
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorMpiPool : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorMpiPool< T > > MpiPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< std::string, MpiPoolPtr >      MpiPoolPtrMap;
+   typedef typename MpiPoolPtrMap::iterator MpiPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef std::string CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderMpiPool< T >; 
+   friend class TbCbVectorReceiverMpiPool< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static MpiPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createTbCbVectorMpiPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   // mpiRemoteRank: mpi-rank des Empfaengers/Senders
+   // mpiTag       : mpi-tag mit dem empfangen/gesendet wird
+   static MpiPoolPtr createTbCbVectorMpiPool(CbVectorKey poolKey, int mpiRemoteRank, int mpiTag, MPI_Comm comm, size_type startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+
+      //pool erstellen
+      MpiPoolPtr mpiPool(new TbCbVectorMpiPool<T>(poolKey, mpiRemoteRank, mpiTag, comm, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorMpiPool< value_type >::poolMap[poolKey] = mpiPool;
+
+      return mpiPool; 
+   }
+   static void deleteTbCbVectorMpiPool(CbVectorKey poolKey)
+   {
+      MpiPoolPtrMapIter it = TbCbVectorMpiPool< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorMpiPool< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static MpiPoolPtr getTbCbVectorMpiPool(CbVectorKey poolKey)
+   {
+      MpiPoolPtrMapIter it;
+      if( (it=TbCbVectorMpiPool< T >::poolMap.find(poolKey))!=TbCbVectorMpiPool< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return MpiPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorMpiPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void eraseMap()
+   {
+      poolMap.clear();
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   TbCbVectorMpiPool(CbVectorKey poolKey, int mpiRemoteRank, int mpiTag, MPI_Comm comm, size_type startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI_REQUEST_NULL)
+      , sendRequest(MPI_REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+
+public:
+   /*==================================================================*/
+   //returns key of Pool in MpiPoolMap
+   CbVectorKey  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->mpiRemoteRank; }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->mpiTag;        }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         //allg.: bei MPI muss man darauf achten, dass bei unblocked operationen die puffer (aus dem oder in den 
+         //geschrieben wird auch noch vorhanden sind!!! wuerde man hier z.B. einen lokalen vector mit Isend() los-
+         //schicken, dann wurde der scope verlassen werden und der vector evtl geloescht werden, bevor mpi den
+         //vorgang abgeschlossen hat!!! ->  tmpOrderVec ist class-member!!!
+         //unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         //tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         //unsigned index = 0;
+         //tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         tmpSendOrderVec = "";
+         tmpSendOrderVec+= UbSystem::toString(this->pool.size()+"#";
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            //CbVectorKey vectorKey=0;
+            //size_type   dataSize=0, startIndexInPool=0;
+            //this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            //if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            //tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            //tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            //tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+
+            CbVectorKey vectorKey = "";
+            size_type   dataSize = 0, startIndexInPool = 0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize);
+            if (it->first != vectorKey) throw UbException(UB_EXARGS, "key mismatch!");
+            str += vectorKey+"#"+UbSystem::toString(startIndexInPool)+"#"+UbSystem::toString(dataSize);
+            
+         }
+
+         int vsize = tmpSendOrderVec.length();
+         MPI_Isend(&vsize, 1, MPI_INT, mpiRemoteRank, mpiTag, comm, &sendRequest[0]);
+
+         MPI_Isend(&tmpSendOrderVec.c_str(), vsize, MPI_CHAR, mpiRemoteRank, mpiTag, comm, &sendRequest[1]);
+
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         //receiveRequest.Wait();
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+
+         //MPI_Status status;
+         //MPI_Recv(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, MPI_STATUS_IGNORE);
+
+         MPI_Irecv(&rbuf.blocksSize, 1, MPI_INT, nProcessID, 0, mpi_comm, &request[rcount]);
+
+         if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+            throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+            //if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               //throw UbException(UB_EXARGS, "entweder hat map nicht die gleiche reihenfolge oder vectorKey = "+UbSystem::toString(vectorKey)+" nicht vorhanden");
+            if (it==this->cbVectorMap.end())
+               throw UbException(UB_EXARGS,"map ist leer");
+            else if (it->first != vectorKey)
+               throw UbException(UB_EXARGS, "vectorKey = "+UbSystem::toString(vectorKey)+" nicht vorhanden it->first =" + UbSystem::toString(it->first));
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&sendRequest, MPI_STATUS_IGNORE);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+
+
+      //A - non blocking
+      ////der ERSTE is entscheidend 
+      ////Grund: wenn man 
+      //// for(all trans) { trans->prepare(); trans->fillBuffer(); }
+      //// aufruft, dann wuerde u.U. der Buffer neu beschrieben werden obwohl noch nicht versendet wurde!!!
+      //counterPrepareForSend++;
+      //if(counterPrepareForSend==1)
+      //{
+      //   if(sendRequest != MPI::REQUEST_NULL) sendRequest.Wait();
+      //}
+      //
+      //if(counterPrepareForSend==nofStoredVectors)
+      //   counterPrepareForSend=0;  
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      //A - non blocking
+      //der LETZTE is entscheidend 
+      //counterSend++;
+      //if(counterSend==nofStoredVectors)
+      //{
+      //   //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+      //   sendRequest = comm.Isend(&pool[0],(int)nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //   counterSend=0;
+      //}
+      //B - blocking
+      //der LETZTE is entscheidend 
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+         //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         //synchronous send 
+         //comm.Ssend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+
+         //standard send
+         MPI_Send(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+////////////////////////////////////////////////////////////////////////////////////////////
+//DEBUG///////////////////////////////////////
+         //int irank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &irank);
+         //std::cout << "MPI_Send: " << irank <<  " "  << mpiRemoteRank << " "  <<mpiTag<<std::endl;
+///////////////////////////////////////////////////
+         counterSend=0;
+      }                           
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+      //A - non blocking
+      //sobald der Letzte kann man den den request holen.
+      //andernfalls kann nicht gewaehrleistet werden, dass evtl noch mit dem buffer gearbeitet wird!!!
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         MPI_Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         counterPrepareForReceive=0;
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      //A - non blocking
+      //sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      //denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      if(counterReceive==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+      counterReceive++;
+      if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+
+      ////B - blocking
+      ////sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      ////denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      //if(counterReceive==0)
+      //{
+      //   comm.Recv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //}
+      //counterReceive++;
+      //if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      //   counterReceive=0;
+   }
+
+protected:
+   CbVectorKey poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   //std::vector< char > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+   std::string tmpSendOrderVec;
+
+   MPI_Comm     comm;
+   MPI_Request  receiveRequest;
+   MPI_Request  sendRequest;
+   //MPI_Status   sendStatus;
+   //MPI_Status   receiveStatus;
+   MPI_Datatype mpiDataType;
+
+   int mpiRemoteRank, mpiTag;
+
+   std::vector<MPI_Request> request;
+   int rcount;
+
+#ifdef _DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorMpiPool<T>::MpiPoolPtrMap TbCbVectorMpiPool<T>::poolMap;
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderMpiPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderMpiPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;
+
+public:
+   TbCbVectorSenderMpiPool(std::string cbVectorKey, TbCbVectorMpiPool< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->mpiVectorPool) );
+   }
+   ~TbCbVectorSenderMpiPool()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->mpiVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }
+   void prepareForSend()        { this->mpiVectorPool->prepareForSendData(); }
+   void sendData()              { this->mpiVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->mpiVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->mpiVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool<T>* mpiVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverMpiPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverMpiPool(std::string cbVectorKey, TbCbVectorMpiPool< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->mpiVectorPool) );
+   }
+   ~TbCbVectorReceiverMpiPool()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPool< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only");  }   
+   void receiveDataSize()   { this->mpiVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   void prepareForReceive() { this->mpiVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->mpiVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getRecvFromRank() const { return  this->mpiVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->mpiVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorMpiPool<T>* mpiVectorPool;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPIPOOL_H
+ 
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPoolEx.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPoolEx.h
new file mode 100644
index 0000000000000000000000000000000000000000..dcb52d842363effe7dacca9ddbfb0c81efd50b9a
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterMpiPoolEx.h
@@ -0,0 +1,602 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERMPIPOOLEX_H
+#define TBTRANSMITTERMPIPOOLEX_H
+
+#ifdef VF_MPI
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+#include <boost/shared_ptr.hpp>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorMpiPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder MpiPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbMpiVectorPool verwaltet
+//MpiPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderMpiPoolEx;
+template<typename T> class TbCbVectorReceiverMpiPoolEx;
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorMpiPoolEx : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorMpiPoolEx< T > > MpiPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< int, MpiPoolPtr >      MpiPoolPtrMap;
+   typedef typename MpiPoolPtrMap::iterator MpiPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderMpiPoolEx< T >; 
+   friend class TbCbVectorReceiverMpiPoolEx< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static MpiPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createTbCbVectorMpiPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   // mpiRemoteRank: mpi-rank des Empfaengers/Senders
+   // mpiTag       : mpi-tag mit dem empfangen/gesendet wird
+#ifdef USE_MPI_CXX_SYNTAX 
+   static MpiPoolPtr createTbCbVectorMpiPool(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI::Intracomm comm, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+#else
+   static MpiPoolPtr createTbCbVectorMpiPool(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI_Comm comm, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+#endif 
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+
+      //pool erstellen
+      MpiPoolPtr mpiPool(new TbCbVectorMpiPoolEx<T>(poolKey, mpiRemoteRank, mpiTag, comm, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorMpiPoolEx< value_type >::poolMap[poolKey] = mpiPool;
+
+      return mpiPool; 
+   }
+   static void deleteTbCbVectorMpiPool(const int& poolKey)
+   {
+      MpiPoolPtrMapIter it = TbCbVectorMpiPoolEx< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorMpiPoolEx< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static MpiPoolPtr getTbCbVectorMpiPool(const int& poolKey)
+   {
+      MpiPoolPtrMapIter it;
+      if( (it=TbCbVectorMpiPoolEx< T >::poolMap.find(poolKey))!=TbCbVectorMpiPoolEx< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return MpiPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorMpiPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(MpiPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void eraseMap()
+   {
+      poolMap.clear();
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+#ifdef USE_MPI_CXX_SYNTAX 
+   TbCbVectorMpiPoolEx(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI::Intracomm comm, const size_type& startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI::REQUEST_NULL)
+      , sendRequest(MPI::REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI::DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI::FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI::INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+#else
+   TbCbVectorMpiPoolEx(const int& poolKey, const int& mpiRemoteRank, const int& mpiTag, MPI_Comm comm, const size_type& startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , comm(comm)                                 
+      , receiveRequest(MPI_REQUEST_NULL)
+      , sendRequest(MPI_REQUEST_NULL)
+      , mpiRemoteRank(mpiRemoteRank)               
+      , mpiTag(mpiTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no MpiDataType for T"+(std::string)typeid(T).name());
+   }
+#endif
+
+
+public:
+   /*==================================================================*/
+   //returns key of Pool in MpiPoolMap
+   int  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->mpiRemoteRank; }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->mpiTag;        }
+
+protected:
+   /*==================================================================*/
+   /*==================================================================*/
+   /*==================================================================*/
+   /*==================================================================*/
+   /*==================================================================*/
+   //void prepareTbReceiveDataOrder() 
+   //{
+   //counterPrepareReceiveDataOrder++;
+   //if(counterPrepareReceiveDataOrder==nofStoredVectors)
+   //{
+   //   unsigned nofElements = relationMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+   //   tmpOrderVec.resize(nofElements);
+   //   std::cout<<RcfSystem::getRank()<<" prepForRecv from rank="<<mpiRemoteRank<<" with tag="<<mpiTag<<"e="<<nofElements<<std::endl;
+   //   receiveRequest = comm.Irecv(&tmpOrderVec[0], nofElements, MPI::UNSIGNED, mpiRemoteRank, mpiTag);
+   //   counterPrepareReceiveDataOrder = 0;
+   //}
+   //}
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         //allg.: bei MPI muss man darauf achten, dass bei unblocked operationen die puffer (aus dem oder in den 
+         //geschrieben wird auch noch vorhanden sind!!! wuerde man hier z.B. einen lokalen vector mit Isend() los-
+         //schicken, dann wurde der scope verlassen werden und der vector evtl geloescht werden, bevor mpi den
+         //vorgang abgeschlossen hat!!! ->  tmpOrderVec ist class-member!!!
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         unsigned index = 0;
+         tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+         //std::cout<<RcfSystem::getRank()<<" send to rank="<<mpiRemoteRank<<" with tag="<<mpiTag<<" e="<<nofElements<<std::endl;
+         //comm.Send(&tmpOrderVec[0],nofElements, MPI::UNSIGNED, mpiRemoteRank, mpiTag);
+
+         ////////////////////////////
+         //int rank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+         //std::cout<<"rank = " << rank <<" sendDataOrder() nofElements = "<<nofElements<<std::endl;
+         ////////////////////////////
+
+#ifdef USE_MPI_CXX_SYNTAX 
+         sendRequest = comm.Isend(&tmpSendOrderVec[0],(int)tmpSendOrderVec.size(), MPI::UNSIGNED, mpiRemoteRank, mpiTag);
+#else
+         MPI_Isend(&tmpSendOrderVec[0],(int)tmpSendOrderVec.size(), MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, &sendRequest);
+#endif
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+#ifdef DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         //receiveRequest.Wait();
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         //////////////TODO////////////DEBUG
+         //int rank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+         //std::cout<<"rank = " << rank <<" receiveDataOrder() nofElements = "<<nofElements << " from " << mpiRemoteRank <<std::endl;
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveDataOrder()"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         //////////////////////////
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+
+#ifdef USE_MPI_CXX_SYNTAX 
+         comm.Recv(&tmpRecvOrderVec[0], nofElements, MPI::UNSIGNED, mpiRemoteRank, mpiTag);
+#else
+         //MPI_Status status;
+         MPI_Recv(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, mpiRemoteRank, mpiTag, comm, MPI_STATUS_IGNORE);
+#endif
+
+         if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+            throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+            if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               throw UbException(UB_EXARGS,"entweder hat map nicht die gleiche reihenfolge oder vectorKey nicht vorhanden");
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+#ifdef DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef USE_MPI_CXX_SYNTAX 
+         if(sendRequest != MPI::REQUEST_NULL) sendRequest.Wait();
+#else
+         //if(sendRequest != MPI_REQUEST_NULL) MPI_Wait(&sendRequest, MPI_STATUS_IGNORE);
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForSendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+
+
+      //A - non blocking
+      ////der ERSTE is entscheidend 
+      ////Grund: wenn man 
+      //// for(all trans) { trans->prepare(); trans->fillBuffer(); }
+      //// aufruft, dann wuerde u.U. der Buffer neu beschrieben werden obwohl noch nicht versendet wurde!!!
+      //counterPrepareForSend++;
+      //if(counterPrepareForSend==1)
+      //{
+      //   if(sendRequest != MPI::REQUEST_NULL) sendRequest.Wait();
+      //}
+      //
+      //if(counterPrepareForSend==nofStoredVectors)
+      //   counterPrepareForSend=0;  
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      //A - non blocking
+      //der LETZTE is entscheidend 
+      //counterSend++;
+      //if(counterSend==nofStoredVectors)
+      //{
+      //   //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+      //   sendRequest = comm.Isend(&pool[0],(int)nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //   counterSend=0;
+      //}
+      //B - blocking
+      //der LETZTE is entscheidend 
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+         //std::cout<<"Isend von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+
+         //synchronous send 
+         //comm.Ssend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#ifdef DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+
+         //standard send
+#ifdef USE_MPI_CXX_SYNTAX 
+         comm.Send(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#else
+         //MPI_Send(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm);
+         MPI_Isend(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &sendRequest);
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::sendData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+////////////////////////////////////////////////////////////////////////////////////////////
+//DEBUG///////////////////////////////////////
+         //int irank;
+         //MPI_Comm_rank(MPI_COMM_WORLD, &irank);
+         //std::cout << "MPI_Send: " << irank <<  " "  << mpiRemoteRank << " "  <<mpiTag<<std::endl;
+///////////////////////////////////////////////////
+         counterSend=0;
+      }                           
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+      //A - non blocking
+      //sobald der Letzte kann man den den request holen.
+      //andernfalls kann nicht gewaehrleistet werden, dass evtl noch mit dem buffer gearbeitet wird!!!
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         //std::cout<<"Irecv von "<<(int)nextStartIndex<<"elementen von "<<mpiRemoteRank<<" mit tag="<<mpiTag<<std::endl;
+#ifdef USE_MPI_CXX_SYNTAX 
+         receiveRequest = comm.Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+#else
+         //MPI_Irecv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, &receiveRequest);
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::prepareForReceiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+         counterPrepareForReceive=0;
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      //A - non blocking
+      //sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      //denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      if(counterReceive==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():start"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+#ifdef USE_MPI_CXX_SYNTAX 
+         receiveRequest.Wait();
+#else
+         //MPI_Wait(&receiveRequest, MPI_STATUS_IGNORE);
+         MPI_Recv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag, comm, MPI_STATUS_IGNORE);
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorMpiPool::receiveData():end"<<" mpiRemoteRank="<<mpiRemoteRank<<" mpiTag="<<mpiTag);
+      }
+      counterReceive++;
+      if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+
+      ////B - blocking
+      ////sobald der ERSTE reinkommt muss man warten, bis received wurde!!!
+      ////denn erst anschliessend stehen die empfangenen daten zur verfuegung
+      //if(counterReceive==0)
+      //{
+      //   comm.Recv(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, mpiRemoteRank, mpiTag);
+      //}
+      //counterReceive++;
+      //if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      //   counterReceive=0;
+   }
+
+protected:
+   int       poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   std::vector< unsigned > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+
+#ifdef USE_MPI_CXX_SYNTAX 
+   MPI::Intracomm comm;
+   MPI::Request   receiveRequest;
+   MPI::Request   sendRequest;
+   MPI::Datatype  mpiDataType;
+#else
+   MPI_Comm     comm;
+   MPI_Request  receiveRequest;
+   MPI_Request  sendRequest;
+   //MPI_Status   sendStatus;
+   //MPI_Status   receiveStatus;
+   MPI_Datatype mpiDataType;
+#endif
+
+   int mpiRemoteRank, mpiTag;
+
+#ifdef DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorMpiPoolEx<T>::MpiPoolPtrMap TbCbVectorMpiPoolEx<T>::poolMap;
+
+//   static MpiPoolPtrMap poolMap;
+
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderMpiPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderMpiPoolEx : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorSenderMpiPoolEx(const unsigned int& cbVectorKey, TbCbVectorMpiPoolEx< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->mpiVectorPool) );
+   }
+   ~TbCbVectorSenderMpiPoolEx()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPoolEx< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->mpiVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbMpiPoolSender sends only");  }
+   void prepareForSend()        { this->mpiVectorPool->prepareForSendData(); }
+   void sendData()              { this->mpiVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->mpiVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->mpiVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderMpiPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorMpiPoolEx<T>* mpiVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverMpiPoolEx : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverMpiPoolEx(const unsigned int& cbVectorKey, TbCbVectorMpiPoolEx< T >* mpiVectorPool)
+      : mpiVectorPool(mpiVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->mpiVectorPool) );
+   }
+   ~TbCbVectorReceiverMpiPoolEx()
+   {
+      if( this->mpiVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorMpiPoolEx< T >::deleteTbCbVectorMpiPool(this->mpiVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only");  }   
+   void receiveDataSize()   { this->mpiVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   void prepareForReceive() { this->mpiVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->mpiVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverMpiPool receives only"); }
+   int  getRecvFromRank() const { return  this->mpiVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->mpiVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverMpiPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorMpiPoolEx<T>* mpiVectorPool;
+};
+
+#endif //VF_MPI
+
+#endif //TBTRANSMITTERMPIPOOL_H
+ 
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterRcf.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterRcf.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ec1c25dddabe3aea4c87331df6536f3e2a58fdd
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterRcf.h
@@ -0,0 +1,326 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBTRANSMITTERRCF_H
+#define TBTRANSMITTERRCF_H
+
+/*=========================================================================*/
+/*  RCF Transmitter                                                        */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.11.07
+*/ 
+
+/*
+usage: ...
+*/
+
+#include <iostream>
+#include <vector>
+#include <map>
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/utilities/UbLogger.h>
+
+#ifdef CAB_RCF
+//////////////////////////////////////////////////////////////////////////
+// RCF STUFF
+//////////////////////////////////////////////////////////////////////////
+
+#include <RCF/Idl.hpp>
+#include <RCF/TcpEndpoint.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <3rdParty/rcf/RcfSerializationIncludes.h>
+#include <3rdParty/rcf/RcfSystem.h>
+#include <3rdParty/rcf/IRcfIpService.h>
+#include <3rdParty/rcf/RcfConnection.h>
+
+//zum ausstausch mittels RCF transmitter:
+RCF_BEGIN(IRcfTransmitterReceiverService, "IRcfTransmitterReceiverService")
+   RCF_METHOD_V2(void, receiveVectorForTransmitter,int /*tag*/, const std::vector<double>& /*data*/);
+   RCF_METHOD_V2(void, receiveVectorForTransmitter,int /*tag*/, const CbVector<double>& /*data*/);
+   RCF_METHOD_V2(void, receiveVectorForTransmitter,int /*tag*/, const std::vector<float>& /*data*/);
+   RCF_METHOD_V2(void, receiveVectorForTransmitter,int /*tag*/, const CbVector<float>& /*data*/);
+RCF_END(IRcfTransmitterReceiverService);
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorSenderRcf< Vector > 
+//////////////////////////////////////////////////////////////////////////
+template< typename Vector >
+class TbVectorSenderRcf : public TbTransmitter< Vector >
+{
+public:
+   typedef Vector value_type;   
+   
+   //static members
+private:
+   static std::vector< RcfClient<IRcfTransmitterReceiverService> >  recvServices;
+
+   static void setRcfClients(const std::string& recvServiceID);
+
+public:
+   TbVectorSenderRcf(const std::string& recvServiceName,const RcfConnection& receiveProcess, const int& tag) 
+      : TbTransmitter< Vector >()
+   { 
+      if( recvServices.empty() ) setRcfClients(recvServiceName);
+      this->receiveRank	   = receiveProcess.getRank();
+      this->tag            = tag;
+      this->receiveProcess = receiveProcess;
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()    { this->sendData(); }
+   void receiveDataSize() { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorSender sends only") ); } 
+
+   void sendData() 
+   { 
+      //remote prozess=client erhaelt daten
+      recvServices[receiveRank].receiveVectorForTransmitter(tag, TbTransmitter< Vector >::getData());
+   }
+   void prepareForReceive() { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorSender sends only") ); }
+   Vector& receiveData()    { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorSender sends only") ); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()    const { return  this->receiveRank; /*=der rank an den gesendet wird*/}
+   int  getSendTbTag()     const { return  this->tag;                                           }
+   int  getRecvFromRank()  const { UB_THROW( UbException(UB_EXARGS,"TbVectorSenderRcf sends only") ); }
+   int  getRecvFromTag()   const { UB_THROW( UbException(UB_EXARGS,"TbVectorSenderRcf sends only") ); }
+
+   std::string toString() const { return "TbVectorSenderRcf< "+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name() +"> > to rank (tag)"+UbSystem::toString(receiveRank)+"("+UbSystem::toString(tag)+") connection "+receiveProcess.toString(); }
+
+private:
+   RcfConnection receiveProcess;
+   int tag;
+   int receiveRank;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template< typename Vector >
+std::vector< RcfClient<IRcfTransmitterReceiverService> >  TbVectorSenderRcf< Vector >::recvServices;
+
+template< typename Vector >
+void TbVectorSenderRcf< Vector >::setRcfClients(const std::string& recvServiceID)
+{
+   UBLOG(logINFO,"invoked setRcfClients");
+   RcfConnection ipConnection = RcfSystem::getIpServiceConnection();
+   if(!ipConnection) UB_THROW( UbException(UB_EXARGS,"ups, no IpServiceConnection") );
+   RcfClient<IRcfIpService> ipService(RCF::TcpEndpoint(ipConnection.getIp(), ipConnection.getPort()));
+
+   //Mit RecvServices verbinden
+   std::vector<RcfConnection> connections = ipService.getServiceConnections(recvServiceID);
+   if(connections.empty()) 
+      UB_THROW( UbException(UB_EXARGS,"no existing RecvService with ID = "+recvServiceID) );
+   std::sort(connections.begin(),connections.end(),RcfConnection::compareRank());
+
+   for(std::size_t i=0; i<connections.size(); i++)
+   {
+      if( (int)i != connections[i].getRank() )
+         UB_THROW( UbException(UB_EXARGS,"recvServices must have continougs ranks sarting from 0") );
+      recvServices.push_back(RcfClient<IRcfTransmitterReceiverService>(RCF::TcpEndpoint(connections[i].getIp(), connections[i].getPort())) );
+   }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// TbVectorReceiverRcf
+//////////////////////////////////////////////////////////////////////////
+template< typename Vector >
+class TbVectorReceiverRcf : public TbTransmitter< Vector >
+{
+   typedef std::map<int, TbVectorReceiverRcf< Vector >* >  ReceiverMap;
+   typedef typename ReceiverMap::iterator                  ReceiverMapIt;
+   
+public:
+   typedef Vector value_type;
+
+   //static members
+private:
+   static ReceiverMap  receiverMap;
+   static boost::mutex staticReceiverMapMutex;
+
+public:
+   static void receiveVectorForTransmitter(int tag, const Vector& data)
+   {
+      TbVectorReceiverRcf< Vector >* receiver = NULL;
+      
+      //receiver ermitteln (map nicht thread-safe->lock! aber nur kurz, ansonsten ab einer gewissen anzahl an clients/blöcken->deadlock)
+      //vermutlich brauch man den nicht mal... (denn das registrieren sollte zu diesem zeitpunkt abgeschlossen sein)
+      //allerdings sollte man nicht gleichzeitig Suchoperationen in ner nich thread sicheren map durchführen!!!
+      {
+         boost::mutex::scoped_lock lock(staticReceiverMapMutex); //wenn man das ausserhalb macht, gibt es ab einer bestimmten anzahl an clients/bloecke einen deadlock
+         
+         ReceiverMapIt result = TbVectorReceiverRcf< Vector >::receiverMap.find(tag);
+         if( result == TbVectorReceiverRcf< Vector >::receiverMap.end() )
+            UB_THROW( UbException(UB_EXARGS,"receiver is not registered") );
+         
+         receiver = result->second;
+         if(!receiver) 
+            UB_THROW( UbException(UB_EXARGS,"receiver is NULL") );
+      }
+      
+      boost::mutex::scoped_lock lock(receiver->bufferMutex); 
+
+      // wait until buffer is empty 
+      while(receiver->isBufferFull) 
+         receiver->bufferEmptiedCondition.wait(lock); 
+
+      //////////////////////////////////////////////////////////////////////////
+      // put data in buffer 
+      //old: receiver->buffer = data;
+      
+      //new:
+      if( receiver->buffer.size() != data.size() )
+      {
+         receiver->buffer.resize( data.size() );
+      }
+      memcpy( (char*)&receiver->buffer[0], (char*)&data[0],  data.size()*sizeof(typename Vector::value_type) ); 
+      
+      //////////////////////////////////////////////////////////////////////////
+      //evtl wartende clients benachrichtigen
+      //notify "buffer filled" waiters 
+      receiver->isBufferFull = true; 
+      receiver->bufferFilledCondition.notify_all(); // notify_one muesste eigentlich reichen 
+   }
+
+public:
+   TbVectorReceiverRcf(const int& tag, const int& recvFromRank/*just for info section*/) 
+      : TbTransmitter< Vector >(), tag(tag), recvFromRank(recvFromRank)
+   {
+      {
+         //receiver registrieren
+         boost::mutex::scoped_lock lock( TbVectorReceiverRcf< Vector >::staticReceiverMapMutex ); 
+
+         std::pair< ReceiverMapIt, bool> result = receiverMap.insert(std::make_pair(tag, this));
+         if( !result.second )
+         {
+            ReceiverMapIt existingReceiver = TbVectorReceiverRcf< Vector >::receiverMap.find(tag);
+            TbVectorReceiverRcf< Vector >::receiverMap.erase(existingReceiver);
+            TbVectorReceiverRcf< Vector >::receiverMap.insert(std::pair<int, TbVectorReceiverRcf< Vector >* >(tag, this));
+         }
+      }
+      isBufferFull = false; 
+   }
+
+   ~TbVectorReceiverRcf()
+   {
+      ReceiverMapIt existingReceiver = receiverMap.find(tag);
+      TbVectorReceiverRcf< Vector >::receiverMap.erase(existingReceiver);
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()    { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorReceiver receives only") ); }
+   void receiveDataSize() { this->receiveData(); } 
+
+   void sendData()        { UB_THROW( UbException(UB_EXARGS,"TbRcfVectorReceiver receives only") ); }
+
+   Vector& receiveData()
+   {
+      boost::mutex::scoped_lock lock(bufferMutex); 
+
+      // wait until buffer is full 
+      while(!isBufferFull) 
+         bufferFilledCondition.wait(lock); 
+
+      // get data from buffer 
+      //std::size_t dataSize = this->buffer.size();
+      //if( this->getData().size()!=dataSize ) this->getData().resize(dataSize);
+      //for(std::size_t i=0; i<dataSize; ++i)
+      //   this->getData()[i]=buffer[i]; 
+      
+      //folgende assert schlaegt bei receiveDataSize(), das receiveData() aufgerufen wird fehl...
+      //daher ausdokumentiert
+      //assert( this->getData().size() == this->buffer.size() );
+      
+      this->getData().swap(this->buffer);
+      
+      isBufferFull = false; 
+
+      // notify "buffer emptied" waiters 
+      bufferEmptiedCondition.notify_all(); // notify_one sollte auch hier reichen 
+      return this->getData(); 
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()    const { UB_THROW( UbException(UB_EXARGS,"getSendTbRank  sends only") ); }
+   int  getSendTbTag()     const { UB_THROW( UbException(UB_EXARGS,"getSendTbTag  sends only") ); }
+   int  getRecvFromRank()  const { return  this->recvFromRank; /*=der rank an den gesendet wird*/ }
+   int  getRecvFromTag()   const { return  this->tag;                                             }
+
+   std::string toString() const { return "TbVectorReceiverRcf< "+(std::string)typeid(Vector).name()+"<"+(std::string)typeid(typename Vector::value_type).name() +"> > to rank (tag)"+UbSystem::toString(recvFromRank)+"("+UbSystem::toString(tag)+")"; }
+
+private:
+   int tag;
+   int recvFromRank; //just for info-section
+
+   boost::mutex     bufferMutex; 
+   boost::condition bufferFilledCondition; 
+   boost::condition bufferEmptiedCondition; 
+   bool isBufferFull; 
+
+   Vector buffer; 
+};
+
+//////////////////////////////////////////////////////////////////////////
+// template< typename Vector >
+// std::map<int, TbVectorReceiverRcf< Vector >* > TbVectorReceiverRcf< Vector >::receiverMap;
+template< typename Vector >
+typename TbVectorReceiverRcf< Vector >::ReceiverMap TbVectorReceiverRcf< Vector >::receiverMap;
+
+template< typename Vector >
+boost::mutex TbVectorReceiverRcf< Vector >::staticReceiverMapMutex;
+
+
+// 
+// 
+// 
+// 
+// //derzeit funzt es nur mit vector<double> dafuer gibt es weiter unten eine spezialisierung
+// //Grund: man muss  fuer jeden datentyp eine RCF methode beim service registrieren
+// //        und derzeit ist eben nur eine fuer vector<double> vorhanden
+// template< typename Vector >
+// class TbVectorSenderRcf : public TbTransmitter< Vector >
+// {
+// public:
+//    TbVectorSenderRcf(const std::string& calcServiceName, const RcfConnection& receiveProcess, const int& tag) 
+//       : TbTransmitter< Vector >()
+//    {  
+//       UB_THROW( UbException("TbVectorSenderRcf::TbVectorSenderRcf() - TbRcfVectorSender not implmeneted for that type ") );    
+//    }
+//    void sendDataSize()      { UB_THROW( UbException("TbVectorSenderRcf::sendDataSize() - not defined for that type") );         }
+//    void receiveDataSize()   { UB_THROW( UbException("TbVectorSenderRcf::receiveDataSize() - not defined for that type") );      } 
+//    void sendData()          { UB_THROW( UbException("TbVectorSenderRcf::sendData() - not defined for that type") );             }
+//    void prepareForReceive() { UB_THROW( UbException("TbVectorSenderRcf::prepareForReceive() - TbRcfVectorSender sends only") ); }
+//    Vector& receiveData()         { UB_THROW( UbException("TbVectorSenderRcf::receiveData() - TbRcfVectorSender sends only") );       } 
+//    std::string toString()   { return "undefined TbVectorSenderRcf"; }
+// };
+// 
+// template< typename Vector  >
+// class TbVectorReceiverRcf : public TbTransmitter< Vector >
+// {
+// public:
+//    TbVectorReceiverRcf(const int& tag, const int& receiveRank) : TbTransmitter< Vector >()
+//    {
+//       UB_THROW( UbException("TbVectorReceiverRcf::TbVectorReceiverRcf() - not defined for that type") );  
+//    }
+//    void sendDataSize()    { UB_THROW( UbException("TbVectorReceiverRcf::sendDataSize() - not defined for that type") );     }    
+//    void receiveDataSize() { UB_THROW( UbException("TbVectorReceiverRcf::receiveDataSize() - not defined for that type") );  } 
+//    void sendData()        { UB_THROW( UbException("TbVectorReceiverRcf::sendData() - TbRcfVectorReceiver receives only") ); }
+//    Vector& receiveData()       { UB_THROW( UbException("TbVectorReceiverRcf::receiveData() - not defined for that type") );      }
+//    std::string toString() { return "undefined TbVectorReceiverRcf"; }
+// };
+// 
+#endif // CAB_RCF
+
+#endif //TBTRANSMITTERRCF_H
diff --git a/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterRcfPool.h b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterRcfPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..361cd7a4475806aeb98bce5a82899147fffe1c65
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/transmitter/TbTransmitterRcfPool.h
@@ -0,0 +1,593 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef TBCBVECTORRCFPOOL_H
+#define TBCBVECTORRCFPOOL_H
+
+#ifdef CAB_RCF
+
+/*=========================================================================*/
+/*  ToCbVectorRcfPool                                                      */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 09.10.08
+*/ 
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+#include <cassert>
+
+#include <RCF/Idl.hpp>
+#include <RCF/TcpEndpoint.hpp>
+#include <RCF/ByteBuffer.hpp>
+
+#include <boost/shared_ptr.hpp>
+
+#include <3rdParty/rcf/RcfSerializationIncludes.h>
+#include <3rdParty/rcf/RcfSystem.h>
+#include <3rdParty/rcf/IRcfIpService.h>
+#include <3rdParty/rcf/RcfConnection.h>
+
+#include <basics/transmitter/ToTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/utilities/UbLogger.h>
+
+
+// zum ausstausch mittels RCF transmitter:
+RCF_BEGIN(IRcfTransmitterReceiverPoolService, "IRcfTransmitterReceiverPoolService")
+RCF_METHOD_V3(void, receiveRcfPoolData     , const float&  /*dummy*/, const int& /*poolKey*/, const RCF::ByteBuffer&         /*databuffer*/ )
+RCF_METHOD_V3(void, receiveRcfPoolDataOrder, const float&  /*dummy*/, const int& /*poolKey*/, const std::vector< unsigned >& /*dataOrder*/  )
+RCF_METHOD_V3(void, receiveRcfPoolData     , const double& /*dummy*/, const int& /*poolKey*/, const RCF::ByteBuffer&         /*databuffer*/ )
+RCF_METHOD_V3(void, receiveRcfPoolDataOrder, const double& /*dummy*/, const int& /*poolKey*/, const std::vector< unsigned >& /*dataOrder*/  )
+RCF_END(IRcfTransmitterReceiverPoolService);
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//ToRcfPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder RcfPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im ToRcfVectorPool verwaltet
+//RcfPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class ToCbVectorSenderRcfPool;
+template<typename T> class ToCbVectorReceiverRcfPool;
+
+/*==================================================================*/
+template<typename T>
+class ToCbVectorRcfPool : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< ToCbVectorRcfPool< T > > RcfPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< int, RcfPoolPtr >      RcfPoolPtrMap;
+   typedef typename RcfPoolPtrMap::iterator RcfPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class ToCbVectorSenderRcfPool< T >; 
+   friend class ToCbVectorReceiverRcfPool< T >; 
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   static RcfPoolPtrMap poolMap;
+
+//    //wenn pool als recevier fungiert
+//    static ReceiverPoolMap  receiverPoolMap;
+   static boost::mutex     staticPoolMapMutex;
+
+   //wenn pool als sender fungiert
+   static std::vector< RcfConnection >  recvConnections;   
+   static std::vector< RcfClient<IRcfTransmitterReceiverPoolService> >  recvServices;
+   static void setRcfSendToClients(const std::string& receiveServiceID, const int& rcfSendToRank);
+
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //createToCbVectorRcfPool:
+   // poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   //              : (dieser schluessel ist eindeutig und muss bei send und recevicePool uebereinstimmen (ersetzt Tag)
+   // rcfRemoteRank: rcf-rank des Empfaengers/Senders
+   // rcfTag       : rcf-tag mit dem empfangen/gesendet wird
+   static RcfPoolPtr createToCbVectorRcfSendPool(const std::string& rcfSendToServiceName, const int& poolKey, const int& rcfSendToRank, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+   {
+      if( poolMap.find(poolKey)!=ToCbVectorRcfPool< value_type >::poolMap.end() )
+      {
+         UB_THROW( UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!") );
+      }
+      //pool erstellen
+      RcfPoolPtr rcfPool(new ToCbVectorRcfPool<T>(rcfSendToServiceName, poolKey, rcfSendToRank, startPoolSize) ); 
+      
+      //pool "speichern"
+      ToCbVectorRcfPool< value_type >::poolMap[poolKey] = rcfPool;
+
+      ToCbVectorRcfPool::setRcfSendToClients(rcfSendToServiceName, rcfSendToRank);
+      
+      return rcfPool; 
+   }
+   /*==================================================================*/
+   static RcfPoolPtr createToCbVectorRcfRecvPool(const int& poolKey, const int& rcfRecvRank, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         UB_THROW( UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!") );
+      }
+      //pool erstellen
+      RcfPoolPtr rcfPool(new ToCbVectorRcfPool<T>( "", poolKey, rcfRecvRank, startPoolSize ) ); 
+                                                  
+      //pool "speichern"
+      ToCbVectorRcfPool< value_type >::poolMap[poolKey] = rcfPool;
+
+      return rcfPool; 
+   }
+   /*==================================================================*/
+   static void deleteToCbVectorRcfPool(const int& poolKey)
+   {
+      RcfPoolPtrMapIter it = ToCbVectorRcfPool< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         UB_THROW( UbException(UB_EXARGS,"kein Pool mit dem key vorhanden") );
+      }
+      ToCbVectorRcfPool< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static RcfPoolPtr getToCbVectorRcfPool(const int& poolKey)
+   {
+      RcfPoolPtrMapIter it;
+      if( (it=ToCbVectorRcfPool< T >::poolMap.find(poolKey))!=ToCbVectorRcfPool< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return NULL;
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"ToCbVectorRcfPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(RcfPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+             <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+             <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+             <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   // checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(RcfPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+      return true;
+   }
+   /*==================================================================*/
+   static void receiveDataOrder(int poolKey, const std::vector< unsigned >& dataOrder)
+   {
+      RcfPoolPtr receiverPool;
+
+      //receiver ermitteln (map nicht thread-safe->lock! aber nur kurz, ansonsten ab einer gewissen anzahl an clients/blöcken->deadlock)
+      //vermutlich brauch man den nicht mal... (denn das registrieren sollte zu diesem zeitpunkt abgeschlossen sein)
+      //allerdings sollte man nicht gleichzeitig Suchoperationen in ner nicht thread sicheren map durchführen!!!
+      {
+         boost::mutex::scoped_lock lock(staticPoolMapMutex); //wenn man das ausserhalb macht, gibt es ab einer bestimmten anzahl an clients/bloecke einen deadlock
+         receiverPool = getToCbVectorRcfPool(poolKey);
+         if(!receiverPool) UB_THROW( UbException(UB_EXARGS,"kein pool mit poolKey="+UbSystem::toString(poolKey)) );
+      }
+
+      boost::mutex::scoped_lock lock(receiverPool->receiveDataOrderMutex); 
+      
+      // wait until buffer is empty 
+      while(receiverPool->receivedDataOrderBufferIsFull) 
+         receiverPool->dataOrderVectorEmptiedCondition.wait(lock); 
+      
+      receiverPool->recvOrderVec = dataOrder;
+                
+      //////////////////////////////////////////////////////////////////////////
+      //evtl wartende clients benachrichtigen
+      //notify "buffer filled" waiters 
+     
+      receiverPool->receivedDataOrderBufferIsFull = true; 
+      receiverPool->dataOrderVectorFilledCondition.notify_all(); 
+   }
+   /*==================================================================*/
+   static void receivePoolData(const int& poolKey, const RCF::ByteBuffer& byteBuffer) //const typename CbVectorPool< T >::Pool& data)
+   {
+      RcfPoolPtr receiverPool;
+
+      //receiver ermitteln (map nicht thread-safe->lock! aber nur kurz, ansonsten ab einer gewissen anzahl an clients/blöcken->deadlock)
+      //vermutlich brauch man den nicht mal... (denn das registrieren sollte zu diesem zeitpunkt abgeschlossen sein)
+      //allerdings sollte man nicht gleichzeitig Suchoperationen in ner nich thread sicheren map durchführen!!!
+      {
+         boost::mutex::scoped_lock lock(staticPoolMapMutex); //wenn man das ausserhalb macht, gibt es ab einer bestimmten anzahl an clients/bloecke einen deadlock
+         receiverPool = getToCbVectorRcfPool(poolKey);
+         if(!receiverPool) UB_THROW( UbException(UB_EXARGS,"kein pool mit poolKey="+UbSystem::toString(poolKey)) );
+
+         //std::cout<<"poolMap.size()="<<poolMap.size()<<std::endl;
+      }
+
+      boost::mutex::scoped_lock lock(receiverPool->receiveMutex); 
+      //UBLOG(logDEBUG5,"receivePoolVector - entered, pool");
+      // wait until buffer is full 
+      while(!receiverPool->performPoolUpdate)
+         receiverPool->performPoolUpdateCond.wait(lock); 
+      //UBLOG(logDEBUG5,"receivePoolVector - es kann losgehen buggercopy");
+
+      //ACHTUNG! nie einen pool.swap(data) machen -> startadressen der "kleinen" vektoren passen sonst nimmer!
+      if( receiverPool->pool.size()*sizeof( T ) != byteBuffer.getLength() )
+      {
+         UB_THROW( UbException(UB_EXARGS,"pool.size()!=byteBuffer.size()") );
+      }
+      memcpy( (char*)&receiverPool->pool[0], byteBuffer.getPtr(),  byteBuffer.getLength() ); 
+//      memcpy( (char*)&receiverPool->pool[0], (char*)&data[0],  data.size()*sizeof( T ) ); 
+      //UBLOG(logDEBUG5,"receivePoolVector - nach memcopy");
+
+      receiverPool->poolWasUpdated    = true;
+      receiverPool->performPoolUpdate = false;
+      receiverPool->waitForPoolUpdateCond.notify_one(); // notify_one sollte auch hier reichen 
+   }
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   ToCbVectorRcfPool(const std::string& rcfReceiveServiceName, const int& poolKey, const int& rcfRank, const size_type& startPoolSize  )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+         , poolKey(poolKey)                           
+         , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+         , counterPrepareReceiveDataOrder(0)          
+         , counterSendDataOrder(0)                    
+         , counterReceiveDataOrder(0)                 
+         , counterPrepareForReceive(0)                
+         , counterReceive(0)                          
+         , counterSend(0)                             
+         , rcfReceiveServiceName(rcfReceiveServiceName)
+         , rcfRank(rcfRank)                                 
+         , receivedDataOrderBufferIsFull(false)
+         , performPoolUpdate(false)
+         , poolWasUpdated(false)
+   {
+   }
+
+public:
+   //returns key of Pool in RcfPoolMap
+   int  getPoolKey()    const { return  this->poolKey;  }
+   /*==================================================================*/
+   //returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->rcfRank;  }
+   /*==================================================================*/
+   //returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->rcfRank;  }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         std::vector< unsigned >localSendOrderVec(nofElements); 
+         unsigned index = 0;
+         localSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  UB_THROW( UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!") );
+         
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) UB_THROW( UbException(UB_EXARGS,"key mismatch!") );
+            
+            localSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            localSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            localSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+         
+         //remote prozess=client erhaelt daten
+         recvServices[this->rcfRank].receiveRcfPoolDataOrder(T(), this->poolKey, localSendOrderVec);
+         
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   { 
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         boost::mutex::scoped_lock lock(receiveDataOrderMutex); 
+         
+         // wait until buffer is full 
+         while(!receivedDataOrderBufferIsFull) 
+            dataOrderVectorFilledCondition.wait(lock); //wird in receivePoolVectorForTransmitter freigegeben :)
+         
+         //////////////////////////////////////////////////////////////////////////
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         if(nofElements!=(unsigned)recvOrderVec.size())
+            UB_THROW( UbException(UB_EXARGS,"error... vec size stimmt nicht") );
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = recvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)recvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)recvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)recvOrderVec.at(index+2);
+
+            if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               UB_THROW( UbException(UB_EXARGS,"entweder hat map nicht die gleiche reihenfolge oder vectorKey nicht vorhanden") );
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            UB_THROW( UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...") );
+
+         recvOrderVec.resize(0);
+
+         // notify "buffer emptied" waiters 
+         this->receivedDataOrderBufferIsFull = false; //->somit kann wieder neue reihenfolge empfangen werden
+         dataOrderVectorEmptiedCondition.notify_all(); // notify_one sollte auch hier reichen 
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData() {}
+   /*==================================================================*/
+   void sendData()
+   {
+      counterSend++;
+      if( counterSend == nofStoredVectors )
+      {
+         //remote prozess=client erhaelt daten
+         //T() -> auf der empfangsseite wird automatisch die methode für den entsprechenden ToCbVectorRcfPool< T >
+         //aufgerufen
+         RCF::ByteBuffer byteBuffer( (char*)&this->pool[0], this->pool.size()*sizeof( T ), true );
+         recvServices[this->rcfRank].receiveRcfPoolData( T(), this->poolKey, byteBuffer );
+         counterSend=0;
+      }
+   }                              
+   /*==================================================================*/
+   void prepareForReceiveData() 
+   {
+      counterPrepareForReceive++;
+      if( counterPrepareForReceive == this->nofStoredVectors )
+      {
+         boost::mutex::scoped_lock lock(receiveMutex); 
+         //UBLOG(logDEBUG5,"prepareForReceiveData - entered -> notfifiziere performPoolUpdateCond");
+
+         counterPrepareForReceive = 0;
+         this->performPoolUpdate = true;
+         performPoolUpdateCond.notify_one();
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      if( counterReceive == 0 )
+      {
+         boost::mutex::scoped_lock lock(receiveMutex); 
+         //UBLOG(logDEBUG5,"receiveData - wait for pool update");
+
+         while(!this->poolWasUpdated)
+            waitForPoolUpdateCond.wait(lock);
+         this->poolWasUpdated    = false;
+         //UBLOG(logDEBUG5,"receiveData - pool update seems to be finished");
+      }
+
+      counterReceive++;
+      if( counterReceive == this->nofStoredVectors ) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+   }
+
+protected:
+   int       poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterSend;
+
+   std::string rcfReceiveServiceName; //nur als SENDER wichtig!!
+   int         rcfRank; 
+
+   bool             receivedDataOrderBufferIsFull; 
+   boost::mutex     receiveDataOrderMutex; 
+   boost::condition dataOrderVectorFilledCondition; 
+   boost::condition dataOrderVectorEmptiedCondition;
+   std::vector< unsigned > recvOrderVec;
+
+   bool             performPoolUpdate;
+   boost::mutex     receiveMutex;
+   bool             poolWasUpdated;
+   boost::condition waitForPoolUpdateCond;
+   boost::condition performPoolUpdateCond;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+std::vector< RcfClient<IRcfTransmitterReceiverPoolService> >  ToCbVectorRcfPool< T >::recvServices;
+
+template< typename T >
+std::vector< RcfConnection >  ToCbVectorRcfPool< T >::recvConnections;
+
+template< typename T >                                              
+void ToCbVectorRcfPool< T >::setRcfSendToClients(const std::string& recvServiceID, const int& rcfSendToRank)
+{
+   UBLOG(logINFO,"ToCbVectorRcfPool< T >::setRcfSendToClients - invoked setRcfClients");
+   RcfConnection ipConnection = RcfSystem::getIpServiceConnection();
+   if(!ipConnection) UB_THROW( UbException(UB_EXARGS,"ups, no IpServiceConnection") );
+   RcfClient<IRcfIpService> ipService(RCF::TcpEndpoint(ipConnection.getIp(), ipConnection.getPort()));
+
+   //////////////////////////////////////////////////////////////////////////
+   //CalcService Verbindungsdaten holen und nach rank sortiere
+   std::vector<RcfConnection> connections = ipService.getServiceConnections(recvServiceID);
+   if(connections.empty()) UB_THROW( UbException(UB_EXARGS,"no existing RecvService with ID = "+recvServiceID) );
+   std::sort(connections.begin(),connections.end(),RcfConnection::compareRank());
+
+   //////////////////////////////////////////////////////////////////////////
+   //CalcServiceClient für rcfSendToRank übernehmen
+   assert( recvConnections.size() == recvServices.size() );
+
+   if( rcfSendToRank >= (int)recvConnections.size() ) 
+   {
+      recvConnections.resize(rcfSendToRank+1);
+      recvServices.resize( rcfSendToRank+1 );
+   }
+   
+   //Anm.: nur, wenn nicht schon vorhanden (hierfür merkt man sich zusätzlich die connection!
+   if( recvConnections[rcfSendToRank] != connections[rcfSendToRank] )
+   {
+      if( connections[rcfSendToRank].getRank() != rcfSendToRank )
+         UB_THROW( UbException(UB_EXARGS,"error - ranks ranks anscheinend nicht kontinierlich von [0..n]") );
+      
+      recvConnections[rcfSendToRank] = connections[rcfSendToRank];
+      recvServices[rcfSendToRank] = RcfClient<IRcfTransmitterReceiverPoolService>(RCF::TcpEndpoint(connections[rcfSendToRank].getIp(), connections[rcfSendToRank].getPort()));
+      UBLOG(logINFO,"ToCbVectorRcfPool< T >::setRcfSendToClients - rank="<<rcfSendToRank<<" : set RcfClient with connection = " << connections[rcfSendToRank] );
+   }
+   else
+   {
+       UBLOG(logINFO,"ToCbVectorRcfPool< T >::setRcfSendToClients - rank="<<rcfSendToRank<<" : RcfClient already exists with connection = " << connections[rcfSendToRank] );
+   }
+   //for(std::size_t i=0; i<connections.size(); i++)
+   //{
+   //   if( (int)i != connections[i].getRank() )
+   //      UB_THROW( UbException(UB_EXARGS,"recvServices must have continous ranks sarting from 0") );
+   //   recvServices[i] = RcfClient<IRcfTransmitterReceiverPoolService>(RCF::TcpEndpoint(connections[i].getIp(), connections[i].getPort()));
+   //   UBLOG(logINFO,"ToCbVectorRcfPool< T >::setRcfSendToClients - pos="<<i<<" : set RcfClient with connection = " << connections[i] );
+   //}
+}
+
+template<typename T>
+typename ToCbVectorRcfPool<T>::RcfPoolPtrMap ToCbVectorRcfPool<T>::poolMap;
+
+template< typename T >
+boost::mutex ToCbVectorRcfPool< T >::staticPoolMapMutex;
+
+
+//////////////////////////////////////////////////////////////////////////
+//  ToSenderRcfPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class ToCbVectorSenderRcfPool : public ToTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   ToCbVectorSenderRcfPool(const unsigned int& cbVectorKey, ToCbVectorRcfPool< T >* rcfVectorPool)
+      : rcfVectorPool(rcfVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->rcfVectorPool) );
+   }
+   ~ToCbVectorSenderRcfPool()
+   {
+      if( this->rcfVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         ToCbVectorRcfPool< T >::deleteToCbVectorRcfPool(this->rcfVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->rcfVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { UB_THROW( UbException(UB_EXARGS,"ToRcfPoolSender sends only") );  }   
+   CbVector< T >& receiveData() { UB_THROW( UbException(UB_EXARGS,"ToRcfPoolSender sends only") );  }
+   void prepareForSend()        { this->rcfVectorPool->prepareForSendData(); }
+   void sendData()              { this->rcfVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendToRank()   const { return  this->rcfVectorPool->getRemoteRank(); }
+   int  getSendToTag()    const { return  this->rcfVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { UB_THROW( UbException(UB_EXARGS,"ToCbVectorSenderRcfPool sends only") ); }
+   int  getRecvFromTag()  const { UB_THROW( UbException(UB_EXARGS,"ToCbVectorSenderRcfPool sends only") ); }
+
+   std::string toString() const { return "ToCbVectorSenderRcfPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendToRank())+"("+UbSystem::toString(getSendToTag())+")"; }
+
+protected:
+   ToCbVectorRcfPool<T>* rcfVectorPool;
+};
+
+/*==================================================================*/
+template<typename T>
+class ToCbVectorReceiverRcfPool : public ToTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   ToCbVectorReceiverRcfPool(const unsigned int& cbVectorKey, ToCbVectorRcfPool< T >* rcfVectorPool)
+      : rcfVectorPool(rcfVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->rcfVectorPool) );
+   }
+   ~ToCbVectorReceiverRcfPool()
+   {
+      if( this->rcfVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         UBLOG(logINFO,"ToCbVectorReceiverRcfPool - loesche map - poolKey "<<this->rcfVectorPool->getPoolKey());
+         ToCbVectorRcfPool< T >::deleteToCbVectorRcfPool(this->rcfVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                         }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();   }
+
+   void sendDataSize()      { UB_THROW( UbException(UB_EXARGS,"ToCbVectorReceiverRcfPool receives only") ); }   
+   void receiveDataSize()   { this->rcfVectorPool->receiveDataOrder();   }  
+   void sendData()          { UB_THROW( UbException(UB_EXARGS,"ToCbVectorReceiverRcfPool receives only") ); }
+   void prepareForReceive() { this->rcfVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()   { this->rcfVectorPool->receiveData(); return this->getData();  }
+
+   //info-section (usable for remote transmitter)
+   int  getSendToRank()   const { UB_THROW( UbException(UB_EXARGS,"ToCbVectorReceiverRcfPool receives only") ); }
+   int  getSendToTag()    const { UB_THROW( UbException(UB_EXARGS,"ToCbVectorReceiverRcfPool receives only") ); }
+   int  getRecvFromRank() const { return  this->rcfVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->rcfVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "ToCbVectorReceiverRcfPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   ToCbVectorRcfPool<T>* rcfVectorPool;
+};
+
+#endif //CAB_RCF
+
+#endif //TOCBVECTORRCFPOOL_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/CMakePackage.txt b/source/VirtualFluidsCore/Basics/utilities/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2bae505538e07aa6c724c29a4b8d472975ef29e0
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/CMakePackage.txt
@@ -0,0 +1,21 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES outOption)
+
+IF(${outOption})
+   IF(WIN32)
+      ADD_DEFINITIONS( -DNOMINMAX )
+   ENDIF(WIN32) 
+   
+   IF(BOOST_VERSION)
+    OPTION(USE_THREADSAFE_LOGGER "ON=thread safe, OFF=not thread safe" ON)
+    IF(NOT ${outOption})
+      ADD_DEFINITIONS( -DNO_THREADSAFE_LOGGING)
+    ELSE()
+      SET(NECESSARY_BOOST_LIBS ${NECESSARY_BOOST_LIBS} thread)
+    ENDIF()
+   ELSE()
+    #um die thread safe zu machen benoetigt man boost
+    ADD_DEFINITIONS( -DNO_THREADSAFE_LOGGING)
+   ENDIF()
+  
+ENDIF()
\ No newline at end of file
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbAutoRun.hpp b/source/VirtualFluidsCore/Basics/utilities/UbAutoRun.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c9ac45115bb4ff37c45d69e101e9a58d936e5d7e
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbAutoRun.hpp
@@ -0,0 +1,58 @@
+#ifndef UB_AUTORUN_HPP
+#define UB_AUTORUN_HPP
+
+#define UB_AUTO_RUN(func)                              UB_AUTO_RUN_(func,  __LINE__)
+#define UB_AUTO_RUN_(func, nID)                        UB_AUTO_RUN__(func, nID)
+#define UB_AUTO_RUN__(func, nID)                       UB_AUTO_RUN___(func, nID)
+#define UB_AUTO_RUN___(func, ID)                                                           \
+    namespace {                                                                         \
+        struct UbAutoRun##ID {                                                            \
+            UbAutoRun##ID() {                                                             \
+                func;                                                                   \
+            }                                                                           \
+        } UbAutoRunInst##ID;                                                              \
+    }
+
+    // More concise to implement UB_AUTO_RUN using the following, but BCB emits an ICE on it.
+    //static bool UB_AutoRun##ID = ( func , false);
+
+
+#define UB_AUTO_RUN_1(func)                            UB_AUTO_RUN_NAMED(func, 1)                   
+#define UB_AUTO_RUN_2(func)                            UB_AUTO_RUN_NAMED(func, 2)                   
+#define UB_AUTO_RUN_3(func)                            UB_AUTO_RUN_NAMED(func, 3)                   
+#define UB_AUTO_RUN_4(func)                            UB_AUTO_RUN_NAMED(func, 4)                   
+#define UB_AUTO_RUN_5(func)                            UB_AUTO_RUN_NAMED(func, 5)                   
+                                                       
+#define UB_AUTO_RUN_NAMED(func, name)                  UB_AUTO_RUN_NAMED_(func, name, __LINE__)
+#define UB_AUTO_RUN_NAMED_(func, name, nID)            UB_AUTO_RUN_NAMED__(func, name, nID)
+#define UB_AUTO_RUN_NAMED__(func, name, nID)           UB_AUTO_RUN___(func, _##name##_##nID)
+                                                       
+#define UB_AUTO_RUN_ONCE(func)                         UB_AUTO_RUN_ONCE_(func,  __LINE__)
+#define UB_AUTO_RUN_ONCE_(func, nID)                   UB_AUTO_RUN_ONCE__(func, nID)
+#define UB_AUTO_RUN_ONCE__(func, nID)                  UB_AUTO_RUN_ONCE___(func, nID)
+#define UB_AUTO_RUN_ONCE___(func, ID)                                                   \
+    struct UbAutoRunOnce##ID {                                                            \
+        UbAutoRunOnce##ID() {                                                             \
+            if (!init()) {                                                              \
+                init() = true;                                                          \
+                func;                                                                   \
+            }                                                                           \
+        }                                                                               \
+        static bool &init() {                                                           \
+            static bool bInit = false;                                                  \
+            return bInit;                                                               \
+        }                                                                               \
+    };                                                                                  \
+    static UbAutoRunOnce##ID AutoRunOnceInst##ID;
+
+#define UB_AUTO_RUN_ONCE_1(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 1)                   
+#define UB_AUTO_RUN_ONCE_2(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 2)                   
+#define UB_AUTO_RUN_ONCE_3(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 3)                   
+#define UB_AUTO_RUN_ONCE_4(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 4)                   
+#define UB_AUTO_RUN_ONCE_5(func)                           UB_AUTO_RUN_ONCE_NAMED(func, 5)                   
+                                                           
+#define UB_AUTO_RUN_ONCE_NAMED(func, name)                 UB_AUTO_RUN_ONCE_NAMED_(func, name, __LINE__)
+#define UB_AUTO_RUN_ONCE_NAMED_(func, name, nID)           UB_AUTO_RUN_ONCE_NAMED__(func, name, nID)
+#define UB_AUTO_RUN_ONCE_NAMED__(func, name, nID)          UB_AUTO_RUN_ONCE___(func, _##name##_##nID)
+
+#endif // ! UB_AUTORUN_HPP
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbComparators.h b/source/VirtualFluidsCore/Basics/utilities/UbComparators.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d1448c93b6c0ee2b6361aad87a379140ffa0f49
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbComparators.h
@@ -0,0 +1,208 @@
+#ifndef UBCOMPARATORS_H 
+#define UBCOMPARATORS_H
+
+#include <functional> 
+
+/*=========================================================================*/
+/*  UbComparators                                                             */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 16.08.2007
+*/ 
+
+namespace UbComparators
+{
+   //type_traits 
+   template <typename T> struct MemberInfo; //not defined for correct compiler errors!
+
+   // specialization for MemberFunctionsPtr
+   // C - class with return T method
+   template <typename T, typename C> 
+   struct MemberInfo<T C::*> 
+   { 
+      typedef T type; 
+      typedef C class_type; 
+
+      static       T& apply(       C& c, T C::* ptr ) { return c.*ptr; } 
+      static const T& apply( const C& c, T C::* ptr ) { return c.*ptr; } 
+   }; 
+   //specialization for MemberFunctionsPtr
+   //C - class with return T method
+   template <typename T, typename C> 
+   struct MemberInfo<T (C::*)()> 
+   { 
+      typedef T type; 
+      typedef C class_type; 
+
+      static T apply( C& c, T (C::*ptr)() ) { return (c.*ptr)(); } 
+   }; 
+   //specialization for const MemberFunctionsPtr
+   //C - class with return T method
+   template <typename T, typename C> 
+   struct MemberInfo<T (C::*)() const> 
+   { 
+      typedef T type; 
+      typedef C class_type; 
+
+      static T apply( const C& c, T (C::*ptr)() const ) { return (c.*ptr)(); } 
+   }; 
+
+   //MemberComparative-Class
+   template <typename Ptr, typename Comp = std::less<typename MemberInfo<Ptr>::type> > 
+   class MemComp 
+      : private Comp  // -> usage of Empty Base Class Optimization (EBCO) 
+   { 
+      typedef typename MemberInfo<Ptr>::class_type C; 
+
+   public: 
+      MemComp( Ptr ptr, Comp c = Comp() ) 
+         : Comp(c), mp_(ptr) 
+      {} 
+
+      bool operator()(C& lhs, C& rhs) 
+      { 
+         return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); 
+      } 
+      bool operator()(C& lhs, C& rhs) const 
+      { 
+         return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); 
+      } 
+      bool operator()(const C& lhs, const C& rhs) 
+      { 
+         return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); 
+      } 
+      bool operator()(const C& lhs, const C& rhs) const 
+      { 
+         return Comp::operator()( MemberInfo<Ptr>::apply(lhs, mp_), MemberInfo<Ptr>::apply(rhs, mp_) ); 
+      } 
+
+   private: 
+      Ptr mp_; 
+   }; 
+
+   // Factoryfunktionen 
+   template <typename Ptr> 
+   MemComp<Ptr> membercomp(Ptr p) 
+   { 
+      return MemComp<Ptr>(p); 
+   } 
+
+   template<typename Comp, typename Ptr> 
+   MemComp<Ptr, Comp> membercomp(Ptr p, Comp c = Comp()) 
+   { 
+      return MemComp<Ptr, Comp>(p, c); 
+   } 
+
+   template<template<typename> class Comp, typename Ptr> 
+   MemComp<Ptr, Comp<typename MemberInfo<Ptr>::type> > 
+      membercomp(Ptr p, Comp<typename MemberInfo<Ptr>::type> c = Comp<typename MemberInfo<Ptr>::type>()) 
+   {
+      return MemComp<Ptr, Comp<typename MemberInfo<Ptr>::type> >(p, c); 
+   } 
+
+    
+   //////////////////////////////////////////////////////////////////////////
+   //////////////////////////////////////////////////////////////////////////
+   //////////////////////////////////////////////////////////////////////////
+   //andere Variante (alerdings ist hier keine Deduction moeglich!!!)
+   //////////////////////////////////////////////////////////////////////////
+   //Vergleichs-Templates:
+   //Funktor zum "non-const" Methodenvergleich: liste.sort( compareMethods<Klasse, int, &Klasse::getVal1  );
+   template<typename K/*Klasse*/, typename M /*MethodenRueckgabeTyp*/, M (K::*fct)() /*MethodenPointer*/> // Allgemeiner Fall
+   struct compareMethods
+   {
+      bool operator()(K& r, K& l) const // da fct nicht const ist, kann auch K nicht const sein. das const hinter der deklaration besagt dass compareMethods const sein kann
+      { return (r.*fct)() < (l.*fct)();  }
+   };
+   //////////////////////////////////////////////////////////////////////////
+   //Funktor zum "const" Methodenvergleich: liste.sort( compareMethods<Klasse, int, &Klasse::getVal1  );
+   template<typename K/*Klasse*/, typename M /*MethodenRueckgabeTyp*/, M (K::*fct)() const /*MethodenPointer*/> // <- hier const 
+   struct compareConstMethods
+   {
+      bool operator()(const K& r, const K& l) const //hier koennen die K's auch const sein, muessen sie aber nicht (const hinzufuegen geht ja problemlos)
+      { return (r.*fct)() < (l.*fct)();  }
+   };
+   //////////////////////////////////////////////////////////////////////////
+   //Funktor zum Membervergleich: lise.sort( compareMember<Klasse, int, &Klasse::member>() );
+   template<typename K/*Klasse*/, typename M /*MemberTyp*/, M (K::*Member) /*MemberPointer*/> // <- hier const 
+   struct compareMember
+   { 
+      bool operator()(const K& r,const K& l) const
+      { return r.*Member < l.*Member; } 
+   };
+   //Bsp:
+   //class Klasse{ 
+   //public: 
+   //   Klasse(double val1, double val2 ) : val1(val1),val2(val2) {} 
+   //   double getVal1()       { return val1; } 
+   //   double getVal2() const { return val2; } // <- hier const
+   //   double val1, val2; 
+   //}; 
+   //int main(int argc, char** argv){ 
+   //   std::list<Klasse> l; 
+   //   l.push_back( Klasse(10,10) ); 
+   //   l.push_back( Klasse(1,5)   ); 
+   //   l.sort( compareMember<Klasse, double,  &Klasse::val1 >() ); 
+   //   l.sort( compareMethods<Klasse, double,  &Klasse::getVal1 >() ); 
+   //   l.sort( compareConstMethods<Klasse, double,  &Klasse::getVal1 >() ); 
+   //} 
+
+};
+
+#endif //UBCOMPARATOR_H
+
+//example
+// #include <basics/utilities/UbComparators.h" 
+// #include <list> 
+// using namespace std; 
+// using namespace UbComparators; 
+// 
+// struct S { 
+//    S(int i) :x(i) {} 
+//    int x; 
+//    float f() {return x;}; 
+//    double g() const {return x;} 
+// }; 
+// 
+// struct intComp { 
+//    bool operator()(int l, int r) const 
+//    { return l > r; } 
+// }; 
+// 
+// struct dblComp { 
+//    bool operator()(double l,  double r) const 
+//    { return l > r; } 
+// }; 
+// 
+// template <typename T> 
+// struct genComp { 
+//    bool operator()(const T& l, const T& r) const
+//    { return l > r; } 
+// }; 
+// 
+// 
+// int main() 
+// { 
+//    S a(1); 
+//    S b(2); 
+//    list<S> sList; 
+//    sList.push_back(a); 
+//    sList.push_back(b); 
+//    sList.sort(UbComparators::membercomp(&S::x,intComp()));  //calls overload (1) 
+//    sList.sort(UbComparators::membercomp<intComp>(&S::x));   //same 
+//    sList.sort(UbComparators::membercomp(&S::x));            //calls overload (5) 
+//    sList.sort(UbComparators::membercomp<genComp>(&S::x));   //calls overload(3) 
+//    sList.sort(UbComparators::membercomp(&S::x, genComp<int>())); //calls overload(1) 
+//    //same for nonconst function 
+//    sList.sort(UbComparators::membercomp(&S::f, dblComp())); //overload(2) 
+//    sList.sort(UbComparators::membercomp<dblComp>(&S::f));   //same      
+//    sList.sort(UbComparators::membercomp(&S::f));            //overload(6) 
+//    sList.sort(UbComparators::membercomp<genComp>(&S::f));   //overload(4) 
+//    //same for const function 
+//    sList.sort(UbComparators::membercomp(&S::g, dblComp())); //overload(2) 
+//    sList.sort(UbComparators::membercomp<dblComp>(&S::g));   //same      
+//    sList.sort(UbComparators::membercomp(&S::g));            //overload(6) 
+//    sList.sort(UbComparators::membercomp<genComp>(&S::g));   //overload(4) 
+// } 
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbConverter.cpp b/source/VirtualFluidsCore/Basics/utilities/UbConverter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad5a99923c0985192555d6ed95efd7502a0efe18
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbConverter.cpp
@@ -0,0 +1,96 @@
+#include <basics/utilities/UbConverter.h>
+
+const std::string UbConverter::base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                              "abcdefghijklmnopqrstuvwxyz"
+                                              "0123456789+/";
+
+
+std::string UbConverter::base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) 
+{
+   std::string ret;
+   int i = 0;
+   int j = 0;
+   unsigned char char_array_3[3];
+   unsigned char char_array_4[4];
+
+   while (in_len--)
+   {
+      char_array_3[i++] = *(bytes_to_encode++);
+      if( i==3)
+      {
+         char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2;
+         char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+         char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+         char_array_4[3] = char_array_3[2] & 0x3f;
+
+         for( i=0; i<4 ; i++)
+            ret += base64_chars[char_array_4[i]];
+         i=0;
+      }
+   }
+
+   if( i )
+   {
+      for( j=i; j<3; j++)
+         char_array_3[j] = '\0';
+
+      char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2;
+      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+      char_array_4[3] = char_array_3[2] & 0x3f;
+
+      for ( j=0; j<i+1; j++)
+         ret += base64_chars[char_array_4[j]];
+
+      while( i++<3 )
+         ret += '=';
+   }
+
+   return ret;
+}
+/*=======================================================*/
+std::string UbConverter::base64_decode(std::string const& encoded_string) 
+{
+   int in_len = (int)encoded_string.size();
+   int i = 0;
+   int j = 0;
+   int in_ = 0;
+   unsigned char char_array_4[4], char_array_3[3];
+   std::string ret;
+
+   while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) 
+   {
+      char_array_4[i++] = encoded_string[in_]; in_++;
+      if(i ==4)
+      {
+         for (i = 0; i <4; i++)
+            char_array_4[i] = (unsigned char)base64_chars.find(char_array_4[i]);
+
+         char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+         char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+         char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+         for (i = 0; (i < 3); i++)
+            ret += char_array_3[i];
+         i = 0;
+      }
+   }
+
+   if( i )
+   {
+      for(j = i; j <4; j++)
+         char_array_4[j] = 0;
+
+      for(j = 0; j <4; j++)
+         char_array_4[j] = (unsigned char)base64_chars.find(char_array_4[j]);
+
+      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+      for(j = 0; (j < i - 1); j++) 
+         ret += char_array_3[j];
+   }
+
+   return ret;
+}
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbConverter.h b/source/VirtualFluidsCore/Basics/utilities/UbConverter.h
new file mode 100644
index 0000000000000000000000000000000000000000..51e713cd47e832848d47a9db022078666222b3e6
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbConverter.h
@@ -0,0 +1,49 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBCONVERTER_H 
+#define UBCONVERTER_H 
+
+#include <cstdlib> 
+#include <ctime> 
+#include <cassert> 
+#include <string>
+
+/*=========================================================================*/
+/*  UBConverter                                                             */
+/*                                                                         */
+//
+// encodes  vals to   e.g. base64
+// dencodes vals from e.g. base64
+// author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+// version 1.0 - 22.10.2007
+
+
+class UbConverter
+{
+public:
+   static std::string base64_encode(unsigned char const* , unsigned int len);
+   static std::string base64_decode(std::string const& s);
+
+   static inline bool is_base64(const unsigned char& c)
+   {
+      return (isalnum(c) || (c == '+') || (c == '/'));
+   }
+
+protected:
+   UbConverter() {}
+   ~UbConverter() {}
+
+private:
+   UbConverter(const UbConverter&);  // not implemented.
+   void operator=(const UbConverter&);  //not implemented.
+
+   static const std::string base64_chars;
+};
+
+
+
+#endif //UBCONVERTER_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbEqual.h b/source/VirtualFluidsCore/Basics/utilities/UbEqual.h
new file mode 100644
index 0000000000000000000000000000000000000000..e838aca00223d0e0064784dc555ee51d13efe144
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbEqual.h
@@ -0,0 +1,120 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBEQUAL_H
+#define UBEQUAL_H
+
+#include<cmath>
+
+//////////////////////////////////////////////////////////////////////////
+//isUbEqual<T1,T2>(a,b)
+//vergleicht die gleichtheit der beiden werte a und b
+//
+//std-maessig wird hierfür der operator== verwendet
+//
+//Ausnahme: floating-points
+//hier wird jeweils der "genauere typ zum ungenaueren gecastet und dann verglichen"
+//e.g.: double d=1.2; int i=1; bool check = isUbEqual(d,i); -> true
+//
+//bei klassen muss hier operator== fuer const objecte implementiert sein!!!
+//e.g.: bool operator==(const Test&) const { if(blabla) return true; else return false; }
+//
+//
+//author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//version 1.0 - 25.03.2008
+//////////////////////////////////////////////////////////////////////////
+
+//std-trait, fuer alle nicht spezifischen typen:
+template < typename T1, typename T2 >
+struct UbEqualTrait
+{
+   typedef T1 High;
+   typedef T1 Low;
+};
+
+//std-trait, fuer gleiche T
+template < typename T >
+struct UbEqualTrait< T, T >
+{
+   typedef T High;
+   typedef T Low;
+};
+
+//spezialisierung für diverse Typen-Tuples
+template<> struct UbEqualTrait< short, int >          { typedef int         High; typedef short  Low; };
+template<> struct UbEqualTrait< short, long >         { typedef long        High; typedef short  Low; };
+template<> struct UbEqualTrait< short, float >        { typedef float       High; typedef short  Low; };
+template<> struct UbEqualTrait< short, double >       { typedef double      High; typedef short  Low; };
+template<> struct UbEqualTrait< short, long double >  { typedef long double High; typedef short  Low; };
+
+template<> struct UbEqualTrait< int, short >          { typedef int         High; typedef short  Low; };
+template<> struct UbEqualTrait< int, long >           { typedef long        High; typedef int    Low; };
+template<> struct UbEqualTrait< int, float >          { typedef float       High; typedef int    Low; };
+template<> struct UbEqualTrait< int, double >         { typedef double      High; typedef int    Low; };
+template<> struct UbEqualTrait< int, long double >    { typedef long double High; typedef int    Low; };
+
+template<> struct UbEqualTrait< long, short >         { typedef long        High; typedef short  Low; };
+template<> struct UbEqualTrait< long, int >           { typedef long        High; typedef int    Low; };
+template<> struct UbEqualTrait< long, float >         { typedef float       High; typedef long   Low; };
+template<> struct UbEqualTrait< long, double >        { typedef double      High; typedef long   Low; };
+template<> struct UbEqualTrait< long, long double >   { typedef long double High; typedef long   Low; };
+
+template<> struct UbEqualTrait< float, short >        { typedef float       High; typedef short  Low; };
+template<> struct UbEqualTrait< float, int >          { typedef float       High; typedef int    Low; };
+template<> struct UbEqualTrait< float, long >         { typedef float       High; typedef long   Low; };
+template<> struct UbEqualTrait< float, double >       { typedef double      High; typedef float  Low; };
+template<> struct UbEqualTrait< float, long double >  { typedef long double High; typedef float  Low; };
+
+template<> struct UbEqualTrait< double, short >       { typedef double      High; typedef short  Low; };
+template<> struct UbEqualTrait< double, int >         { typedef double      High; typedef int    Low; };
+template<> struct UbEqualTrait< double, long >        { typedef double      High; typedef long   Low; };
+template<> struct UbEqualTrait< double, float >       { typedef double      High; typedef float  Low; };
+template<> struct UbEqualTrait< double, long double > { typedef long double High; typedef double Low; };
+
+template<> struct UbEqualTrait< long double, short >  { typedef long double High; typedef short  Low; };
+template<> struct UbEqualTrait< long double, int >    { typedef long double High; typedef int    Low; };
+template<> struct UbEqualTrait< long double, long >   { typedef long double High; typedef long   Low; };
+template<> struct UbEqualTrait< long double, float >  { typedef long double High; typedef float  Low; };
+template<> struct UbEqualTrait< long double, double > { typedef long double High; typedef double Low; };
+
+//////////////////////////////////////////////////////////////////////////
+//fuer Allgmeine-Typen ( operator== ):
+template< typename T1, typename T2 >
+inline bool specific_equal(const T1& a, const T2& b) { return a==b; }
+
+//////////////////////////////////////////////////////////////////////////
+//fuer floating point build-in-type
+//float.float
+template< /*float,float*/>
+inline bool specific_equal< float, float >(const float& a, const float& b) {  return std::fabs( a - b ) < 1E-8; }
+
+template</*double,double*/>
+inline bool specific_equal< double, double >(const double& a, const double& b) { return std::fabs( a - b ) < 1E-13; }
+
+template</*long double,long double*/>
+inline bool specific_equal< long double, long double >(const long double& a, const long double& b) { return std::fabs( a - b ) < 1E-16; }
+
+//////////////////////////////////////////////////////////////////////////
+//globale isUbEqual - Funktion
+template< typename T1, typename T2 >
+inline bool isUbEqual(const T1& a, const T2& b)
+{
+   typedef typename UbEqualTrait<T1,T2>::Low Low;
+   return specific_equal< Low, Low >(static_cast< Low >( a ),static_cast< Low >( b ));
+};
+
+//////////////////////////////////////////////////////////////////////////
+//UbEqual-Functor
+template< typename T1, typename T2 >
+struct UbEqual
+{
+   bool operator()(const T1& a, const T2& b)
+   {
+      return isUbEqual(a,b);
+   }
+};
+
+#endif //UBEQUAL_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbException.h b/source/VirtualFluidsCore/Basics/utilities/UbException.h
new file mode 100644
index 0000000000000000000000000000000000000000..48d1e1a60065d6f6e057aafa59abded38b800664
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbException.h
@@ -0,0 +1,163 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBEXCEPTION_H
+#define UBEXCEPTION_H
+
+#include <vector>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <boost/exception/all.hpp>
+
+#include "./UbTuple.h"
+
+/*=========================================================================*/
+/*  UbException                                                             */
+/*                                                                         */
+/**
+This Class provides the base for exception handling.
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0  - 23.11.04
+@version 1.5  - 14.03.08
+@version 1.6  - 31.03.08 derivation from std::run_time_error
+@version 1.6a - helper marco UB_EXARGS
+*/ 
+
+/*
+usage: UB_THROW( UbException("error message") );
+       UB_THROW( UbException(__FILE__, __LINE__,"error message") );
+       UB_THROW( UbException(__FILE__, __LINE__,UB_FUNCTION,"error message") );
+       UB_THROW( UbException(UB_EXARGS,"error") ); //same as above
+*/
+
+//Macro UB_FUNCTION: figures out the method/function name (platform dependant)
+#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
+ # define UB_FUNCTION __PRETTY_FUNCTION__
+#elif defined(__DMC__) && (__DMC__ >= 0x810)
+ # define UB_FUNCTION __PRETTY_FUNCTION__
+#elif defined(__FUNCSIG__)
+ # define UB_FUNCTION __FUNCSIG__
+#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
+ # define UB_FUNCTION __FUNCTION__
+#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
+ # define UB_FUNCTION __FUNC__
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
+ # define UB_FUNCTION __func__
+#else
+ # define UB_FUNCTION "(unknown)"
+#endif
+
+//Helper Marco
+#define UB_EXARGS __FILE__,__LINE__,UB_FUNCTION
+
+#ifdef CAB_BOOST
+   #define UB_THROW(e) throw boost::enable_current_exception(e)
+#else
+   #define UB_THROW(e) throw e
+#endif
+
+class UbException : public std::runtime_error, public boost::exception
+{
+public:
+   typedef UbTuple< std::string, int, std::string, std::string > ExceptionData;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //constructors
+   UbException()
+      : std::runtime_error("")
+   { 
+   }
+   /*==========================================================*/
+   UbException(const std::string& str)
+      : std::runtime_error("")
+   {
+      this->addInfo(str);		
+   }
+   /*==========================================================*/
+   UbException(const std::string& file, const int& line, const std::string& err_str)
+      : std::runtime_error("")
+   {
+      this->addInfo(file,line,"unknown",err_str);		
+   }
+   /*==========================================================*/
+   //UbException(const char* file, const int& line, const char* function, const std::string& err_str)
+   UbException(const std::string& file, const int& line, const std::string& function, const std::string& err_str)
+      : std::runtime_error("")
+   {
+      this->addInfo(file,line,function,err_str);		
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //destructor
+   virtual ~UbException() throw() { }
+   //////////////////////////////////////////////////////////////////////////
+   //virtual public methods
+   //returns  exception-string
+   virtual const char* what() const throw()
+   {
+      exceptionString = this->toString();
+      return exceptionString.c_str();  //ansonsten ist das Verhalten anschließend undefiniert!
+   }
+   /*==========================================================*/
+   virtual void addInfo(const std::string& err_str)	 
+   { 
+      exceptionData.push_back( makeUbTuple( (std::string)"-", 0, (std::string)"unknown", err_str) ); 
+   }
+   /*==========================================================*/
+   //add exception
+   virtual void addInfo(const std::string& file, const int& line, const std::string& function, const std::string& err_str)	 
+   { 
+      exceptionData.push_back( makeUbTuple( file, line, function, err_str ) ); 
+   }
+   /*==========================================================*/
+   //returns exception-string with all calles exceptions
+   virtual const std::vector<std::string> getInfo() const
+   { 
+      std::vector<std::string> tmp;
+      for(std::size_t i=0; i<exceptionData.size(); i++)
+      {
+         std::stringstream str;
+         str << val<1>( exceptionData[i] ) << ", " 
+             << val<2>( exceptionData[i] ) << ", " 
+             << val<3>( exceptionData[i] ) << ", " 
+             << val<4>( exceptionData[i] );
+         tmp.push_back( str.str());
+      }
+      return tmp; 
+   }
+   /*==========================================================*/
+   //returns exception-string with all calles exceptions and detailes informations
+   virtual std::string toString() const
+   { 
+      std::stringstream str("UbExeption");
+      
+      for(std::size_t i=0; i<exceptionData.size(); i++)
+         str<<(std::string)"caller[" << i << "]\n"
+            <<"  - file:     "<< val<1>( exceptionData[i] )<<"\n"
+            <<"  - line:     "<< val<2>( exceptionData[i] )<<"\n"
+            <<"  - function: "<< val<3>( exceptionData[i] )<<"\n"
+            <<"  - what:     "<< val<4>( exceptionData[i] )<< std::endl; 
+
+      return str.str();
+   }
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   //protected member
+   std::vector< ExceptionData > exceptionData;
+   mutable std::string exceptionString;
+};
+
+//overlading operator <<
+inline std::ostream& operator<<(std::ostream& os, const UbException& e)
+{
+   return os<<e.toString();
+}
+
+#endif //UBEXCEPTION_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileInput.h b/source/VirtualFluidsCore/Basics/utilities/UbFileInput.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b08a7fdb532c3b5b45cc14d3315dd1eee52b379
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileInput.h
@@ -0,0 +1,97 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEINPUT_H
+#define UBFILEINPUT_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <cstdlib> //atoi
+#include <cstring> //strstr
+
+#include <basics/utilities/UbException.h>
+
+/*=========================================================================*/
+/*  UbFileInput                                                            */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/
+
+/*
+usage: ...
+*/
+
+class UbFileInput
+{
+public:
+   enum FILETYPE {ASCII, BINARY};      
+
+public:
+   UbFileInput() : filename(""), commentindicator('C') { }
+   virtual ~UbFileInput() { infile.close(); }
+
+   virtual bool        operator!() { return !(infile); }
+   virtual bool        isOpen()    { return !(!(infile)); }
+
+   virtual bool        open(std::string filename)=0;
+   virtual void        close() { infile.close(); }
+   virtual int         eof()   { return infile.eof(); }
+
+   virtual void        skipLine()=0;					// Springt zur naechsten Zeile
+	virtual void        readLine()=0;
+   virtual std::string readStringLine()=0;
+	virtual int		     readInteger()=0;				// Liest einen Int-Wert ein
+   virtual std::size_t readSize_t()=0;
+   virtual double	     readDouble()=0;				   // Liest einen double-Wert ein
+	virtual float	     readFloat()=0;				   // Liest einen float-Wert ein
+	virtual bool  	     readBool()=0;				   // Liest einen bool-Wert ein
+   virtual char  	     readChar()=0;				   // Liest einen char-Wert ein
+   virtual std::string readString()=0;			      // Liest ein Wort ein
+	virtual std::string readLineTill(char stop)=0;	// Liest gesamte Zeile ein bis zu einem bestimmten Zeichen
+	virtual std::string parseString()=0;	         // Liest
+
+   virtual void        setCommentIndicator(char commentindicator) {this->commentindicator = commentindicator;}
+
+   virtual bool        containsString( const std::string& var)=0;
+   virtual void        setPosAfterLineWithString( const std::string& var)=0;
+   virtual int		     readIntegerAfterString( const std::string& var)=0;
+   virtual double	     readDoubleAfterString( const std::string& var)=0;
+   virtual bool        readBoolAfterString( const std::string& var)=0;
+   virtual std::string readStringAfterString( const std::string& var)=0;
+
+   virtual std::string getFileName() {return this->filename;}
+
+   //returns file extension:
+   //e.g. "./../test/ich.inp" -> "inp", "./../test/ich" -> ""
+   virtual std::string getFileExtension()
+   {
+      std::size_t pos1 = filename.rfind("/");
+      if(pos1==std::string::npos) pos1 = 0;
+      std::size_t pos2 = filename.rfind(".");
+      if(pos2!=std::string::npos && pos2>pos1)
+         return filename.substr(pos2+1);
+
+      return "";
+   }
+
+   //returns "ASCII", "BINARY"
+   virtual FILETYPE getFileType()=0;
+
+protected:
+   std::ifstream infile;
+   std::string   filename;
+   char          commentindicator;
+};
+
+#endif //UBFILEINPUT_H
+
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileInputASCII.cpp b/source/VirtualFluidsCore/Basics/utilities/UbFileInputASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d17d69cf9c3555f3ab742ec5922e3872ba93b796
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileInputASCII.cpp
@@ -0,0 +1,227 @@
+#include <basics/utilities/UbFileInputASCII.h>
+#include <cstring>
+
+using namespace std;
+
+UbFileInputASCII::UbFileInputASCII(string filename)
+{
+	this->filename         = filename;
+   this->commentindicator = 'C';
+
+   infile.open(filename.c_str());
+
+   //if(!infile) UB_THROW( UbException((string)("UbFileInputASCII::UbFileInputASCII(string filename, int how) couldn't open file:\n "+filename)) );
+}
+/*==========================================================*/
+bool UbFileInputASCII::open(string filename)
+{
+   infile.close();
+   infile.clear(); //setzt flags zurueck
+
+   this->filename = filename;
+   infile.open(this->filename.c_str());
+
+   return infile.is_open();
+}
+/*==========================================================*/
+int UbFileInputASCII::readInteger()
+{
+	int dummy;
+	infile>>dummy;
+	return dummy;
+}
+/*==========================================================*/
+string UbFileInputASCII::getFileName()
+{
+	return this->filename;
+}
+
+/*==========================================================*/
+void UbFileInputASCII::skipLine()
+{
+	string dummy;
+	getline(infile, dummy);
+}
+/*==========================================================*/
+void UbFileInputASCII::readLine()
+{
+	string dummy;
+	getline(infile, dummy);
+}
+/*==========================================================*/
+string UbFileInputASCII::readStringLine()
+{
+   string dummy;
+   getline(infile, dummy);
+   return dummy;
+}
+/*==========================================================*/
+string UbFileInputASCII::readLineTill(char stop)
+{
+	string dummy;
+	getline(infile, dummy, stop);
+	return dummy;
+}
+/*==========================================================*/
+string UbFileInputASCII::parseString()
+{
+	string dummy;
+	getline(infile, dummy, ' ');
+	return dummy;
+}
+/*==========================================================*/
+double UbFileInputASCII::readDouble()
+{
+   double dummy;
+   infile>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+float UbFileInputASCII::readFloat()
+{
+   float dummy;
+   infile>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+string UbFileInputASCII::readString()
+{
+	string dummy;
+	infile>>dummy;
+	return dummy;
+}
+/*==========================================================*/
+char UbFileInputASCII::readChar()
+{
+   int dummy;
+   infile>>dummy;
+   return (char)dummy;
+}
+/*==========================================================*/
+std::size_t UbFileInputASCII::readSize_t()
+{
+   std::size_t dummy;
+   infile>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+void UbFileInputASCII::setPosAfterLineWithString(const string& var)
+{
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+   char line[512];
+   do
+   {
+      infile.getline(line,512);
+      if(infile.eof()) UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> string "+var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+}
+/*==========================================================*/
+bool UbFileInputASCII::containsString(const string& var)
+{
+   infile.clear(); // setzt den EOF-Status zurueck (wird durch infile.seekg() NICHT getan!!!)
+
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+   char line[512];
+   do
+   {
+      infile.getline(line,512);
+      if(infile.eof()) return false;
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+
+   return true;
+}
+/*==========================================================*/
+int UbFileInputASCII::readIntegerAfterString(const string& var)
+// last change [10.3.2004] at [9:46]
+//suchts in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. timesteps 9
+{
+   infile.clear(); // setzt den EOF-Status zurueck (wird durch infile.seekg() NICHT getan!!!)
+   
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];
+
+   do
+   {
+      infile.getline(line,512);
+      if(infile.eof()) UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> "+var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+
+   strcpy (line, (line+strlen(var.c_str())));	    // zeile um "varname" kuerzen
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   return(atoi(line));						// Umwandlung in int
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46]
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+double UbFileInputASCII::readDoubleAfterString(const string& var)
+{
+   infile.clear(); // setzt den EOF-Status zurueck (wird durch infile.seekg() NICHT getan!!!)
+   
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];
+
+   do
+   {
+      infile.getline(line,512);
+      if(infile.eof()) UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> "+var+" wasn't found in "+this->filename) );
+   }while (/*!strncmp(varname,line,sizeof(varname))==0*/strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+
+
+   strcpy (line, (line+strlen(var.c_str())));	    // zeile um "varname" kuerzen
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   return (atof(line));			// Umwandlung in double
+}
+/*==========================================================*/
+//  [9.9.2002]
+// liefert string-Wert der hinter dem uebergebenen char feld in der datei infile steht
+// zudem wird der wert in die uebergebene variable value uebertragen (falls man das ergebniss als char benoetig)
+string UbFileInputASCII::readStringAfterString(const string& var)//,char *value)
+{
+   infile.clear(); // setzt den EOF-Status zurueck (wird durch infile.seekg() NICHT getan!!!)
+   
+   infile.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];
+   //string line_copy[512];
+
+   do{
+      infile.getline(line,512);
+      if(infile.eof()) UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> "+var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt
+
+   strcpy (line, (line+strlen(var.c_str())));										// zeile um "varname" kuerzen
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   char *p;
+   p=strtok(line," "); //schneidet alles "ab und inklusive space " nach namen ab
+   p=strtok(line,"\t");//schneidet alles "ab und inklusive tab   " nach namen ab
+
+   return static_cast<string>(p);			// Umwandlung in string
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46]
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+bool UbFileInputASCII::readBoolAfterString(const string& var)
+{
+   if(this->readStringAfterString(var)      == "true" ) return true;
+   else if(this->readStringAfterString(var) == "false") return false;
+   else UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> expression after "+var+" is not equal to 'true' or 'false' in "+this->filename) );
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46]
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+bool UbFileInputASCII::readBool()
+{
+   string tmp = this->readString();
+   if(     tmp == "true" ) return true;
+   else if(tmp == "false") return false;
+   else UB_THROW( UbException(UB_EXARGS,"error at reading in file \""+filename+"\" -> expression=\""+tmp+"\" is not equal to 'true' or 'false' in "+this->filename) );
+}
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileInputASCII.h b/source/VirtualFluidsCore/Basics/utilities/UbFileInputASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..77c07137bbaf9c9b542ac1b1e939729af15dd85f
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileInputASCII.h
@@ -0,0 +1,73 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEINPUTASCII_H
+#define UBFILEINPUTASCII_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+
+/*=========================================================================*/
+/*  UbFileInputASCII                                                       */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileInputASCII : public UbFileInput
+{                               
+public:
+   UbFileInputASCII() : UbFileInput() { }
+   UbFileInputASCII(std::string filename);
+	
+   bool open(std::string filename);
+
+   std::string getFileName();				
+	void	      skipLine();					   // Springt zur naechsten Zeile
+
+   void        readLine();		 
+   std::string readStringLine();				
+	int		   readInteger();				   // Liest einen Int-Wert ein
+   std::size_t readSize_t();
+   double	   readDouble();				   // Liest einen double-Wert ein
+	float 	   readFloat();				   // Liest einen float-Wert ein
+	bool  	   readBool();				      // Liest einen bool-Wert ein
+   char        readChar();                // Liest einen char-Wert ein
+   std::string	readString();				   // Liest ein Wort ein
+	std::string	readLineTill(char stop);	// Liest gesamte Zeile ein bis zu einem bestimmten Zeichen
+	std::string	parseString();	
+
+   bool        containsString(const std::string& var);
+   void        setPosAfterLineWithString(const std::string& var);
+   int		   readIntegerAfterString(const std::string& var);
+   double	   readDoubleAfterString(const std::string& var);
+   bool        readBoolAfterString(const std::string& var);
+   std::string readStringAfterString(const std::string& var);
+
+   FILETYPE getFileType() { return ASCII; }
+
+   template< typename T >
+   friend inline UbFileInputASCII& operator>>(UbFileInputASCII& file, T& data) 
+   {
+      file.infile>>data;
+      return file;
+   }
+};
+
+#endif //UBFILEINPUTASCII_H
+
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileInputBinary.cpp b/source/VirtualFluidsCore/Basics/utilities/UbFileInputBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0bcf60ce0ca665403e95d6f0f5366e03c18382fb
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileInputBinary.cpp
@@ -0,0 +1,150 @@
+#include <basics/utilities/UbFileInputBinary.h>
+#include <cstring>
+
+using namespace std;
+
+/*==========================================================*/
+UbFileInputBinary::UbFileInputBinary(string filename)
+{
+	this->filename = filename;
+   infile.open(filename.c_str(), ios::in | ios::binary);
+}
+/*==========================================================*/
+bool UbFileInputBinary::open(string filename)
+{
+   infile.close();
+   infile.clear(); //setzt flags zurueck
+   
+   this->filename = filename;
+   infile.open(this->filename.c_str(), ios::in | ios::binary);
+
+   return infile.is_open();
+}
+/*==========================================================*/
+int UbFileInputBinary::readInteger()				
+{
+   int dummy;
+   infile.read((char*)&dummy,sizeof(int));
+   return dummy; 
+}
+/*==========================================================*/
+std::size_t UbFileInputBinary::readSize_t()				
+{
+   std::size_t dummy;
+   infile.read((char*)&dummy,sizeof(std::size_t));
+   return dummy;
+}
+/*==========================================================*/
+double UbFileInputBinary::readDouble()	
+{
+   double dummy;
+   infile.read((char*)&dummy,sizeof(double));
+   return dummy; 
+}
+/*==========================================================*/
+float UbFileInputBinary::readFloat()	
+{
+	float dummy;
+	infile.read((char*)&dummy,sizeof(float));
+	return dummy; 
+}
+/*==========================================================*/
+char UbFileInputBinary::readChar()	
+{
+   char dummy;
+   infile.read((char*)&dummy,sizeof(char));
+   return dummy; 
+}
+/*==========================================================*/
+string UbFileInputBinary::readString()	
+{
+   char c;
+   infile.read(&c,sizeof(char));
+   while(c==' ' || c=='\t') infile.read(&c,sizeof(char));  
+   
+   string dummy;
+   dummy+=c;
+
+   infile.read(&c,sizeof(char));
+   while(c!='\0' && c!=' ' && c!='\t' && c!='\n')
+   {
+      dummy+=c;
+      infile.read(&c,sizeof(char));
+   }
+   return dummy;
+}
+/*==========================================================*/
+bool UbFileInputBinary::readBool()	
+{
+   bool dummy;
+   infile.read((char*)&dummy,sizeof(bool));
+   return dummy; 
+}
+/*==========================================================*/
+void UbFileInputBinary::skipLine()				
+{
+   char c;
+   do{
+      infile.read(&c,sizeof(char));
+   }while(c!='\n');
+}
+/*==========================================================*/
+void UbFileInputBinary::readLine()				
+{
+   char c;
+   infile.read(&c,sizeof(char));
+   while(c!='\n') infile.read(&c,sizeof(char));
+}
+/*==========================================================*/
+string UbFileInputBinary::readStringLine()				
+{
+   char c;
+   string dummy;
+   infile.read(&c,sizeof(char));
+   while(c!='\n')
+   {
+      dummy+=c;
+      infile.read(&c,sizeof(char));
+   }
+   return dummy;
+}
+/*==========================================================*/
+string UbFileInputBinary::readLineTill(char stop)				
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+string UbFileInputBinary::parseString()				
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+bool UbFileInputBinary::containsString(const string& var)
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+void UbFileInputBinary::setPosAfterLineWithString(const string& var)
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+int UbFileInputBinary::readIntegerAfterString(const string& var)
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+double UbFileInputBinary::readDoubleAfterString(const string& var)	
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+string UbFileInputBinary::readStringAfterString(const string& var)	
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
+/*==========================================================*/
+bool UbFileInputBinary::readBoolAfterString(const string& var)	
+{
+   UB_THROW( UbException(UB_EXARGS,"method makes no sense for binary streams") );
+}
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileInputBinary.h b/source/VirtualFluidsCore/Basics/utilities/UbFileInputBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e994ba792ccf82941cd6cf2aba87e5edeb9f51e
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileInputBinary.h
@@ -0,0 +1,71 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEINPUTBINARY_H
+#define UBFILEINPUTBINARY_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+
+/*=========================================================================*/
+/*  UbFileInputBinary                                                      */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileInputBinary : public UbFileInput
+{                               
+public:
+   UbFileInputBinary() : UbFileInput() {  }
+   UbFileInputBinary(std::string filename);
+	
+	bool        open(std::string filename);
+
+   void	      skipLine();					   // Springt zur naechsten Zeile
+	void        readLine();		 
+   std::string readStringLine();				
+   std::size_t readSize_t();				
+   int		   readInteger();				   // Liest einen Int-Wert ein
+	double	   readDouble();				   // Liest einen double-Wert ein
+	float 	   readFloat();				   // Liest einen float-Wert ein
+	bool  	   readBool();				      // Liest einen bool-Wert ein
+   char        readChar();                // Liest einen char-Wert ein
+   std::string	readString();				   // Liest ein Wort ein
+	std::string	readLineTill(char stop);	// Liest gesamte Zeile ein bis zu einem bestimmten Zeichen
+	std::string	parseString();	// Liest 
+
+   bool        containsString(const std::string& var);
+   void        setPosAfterLineWithString(const std::string& var);
+   int		   readIntegerAfterString(const std::string& var);
+   double	   readDoubleAfterString(const std::string& var);
+   bool        readBoolAfterString(const std::string& var);
+   std::string readStringAfterString(const std::string& var);
+
+   FILETYPE getFileType() { return BINARY; }
+
+   template< typename T >
+   friend inline UbFileInputBinary& operator>>(UbFileInputBinary& file, T& data) 
+   {
+      file.infile.read((char*)&data,sizeof(T));
+      return file;
+   }
+};
+
+#endif
+
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileOutput.h b/source/VirtualFluidsCore/Basics/utilities/UbFileOutput.h
new file mode 100644
index 0000000000000000000000000000000000000000..c55dd82fcf5074e66f709fb662dd680732dacbc3
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileOutput.h
@@ -0,0 +1,93 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEOUTPUT_H
+#define UBFILEOUTPUT_H            
+
+#include <iomanip>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbException.h>
+
+/*=========================================================================*/
+/*  UbFileOutput                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileOutput
+{
+public:
+   enum CREATEOPTION {OUTFILE=0, INANDOUTFILE=1, APPENDFILE=2};      
+   enum FILETYPE {ASCII, BINARY};      
+
+public:
+   UbFileOutput() : filename(""), commentindicator('C') {  }
+   UbFileOutput(const std::string& filename)  : filename(filename), commentindicator('C') { }             
+   virtual ~UbFileOutput() { outfile.flush();outfile.close(); }
+
+   virtual bool open(const std::string& filename, CREATEOPTION opt=OUTFILE) = 0;
+
+   virtual bool operator!() { return !(outfile); }
+   virtual bool isOpen()    { return !(!(outfile)); }
+   
+   virtual void flush() { outfile.flush(); }
+   virtual void close() { outfile.close(); }
+   
+   virtual void writeInteger(const int& value, const int& width=0)=0;
+	virtual void writeDouble(const double& value, const int& width=0)=0;
+	virtual void writeFloat(const float& value, const int& width=0)=0;
+   virtual void writeBool(const bool& value, const int& width=0)=0;
+   virtual void writeSize_t(const std::size_t& value, const int& width=0)=0;
+   virtual void writeChar(const char& value, const int& width=0)=0;
+   virtual void writeString(const std::string& value, const int& width=0)=0;
+   virtual void writeStringOnly(const std::string& value)=0;
+	virtual void writeLine(const std::string& value, const int& width=0)=0;
+	virtual void writeLine()=0;
+
+	virtual void writeCommentLine(const std::string& line)=0;
+	virtual void writeCommentLine(char indicator, const std::string& line)=0;
+   virtual void writeCopyOfFile(const std::string& filename)=0;
+	
+   virtual void setCommentIndicator(char commentindicator) {this->commentindicator = commentindicator;} 
+   
+   virtual void setPrecision(const int& precision)=0;
+   virtual int  getPrecision()=0;
+
+   //returns "ASCII", "BINARY"
+   virtual FILETYPE getFileType()=0;
+
+   //returns file extension:
+   //e.g. "./../test/ich.inp" -> "inp", "./../test/ich" -> ""
+   virtual std::string getFileExtension()  
+   {
+	   std::size_t pos1 = filename.rfind("/");
+      if(pos1==std::string::npos) pos1 = 0;
+      std::size_t pos2 = filename.rfind(".");
+      if(pos2!=std::string::npos && pos2>pos1)
+         return filename.substr(pos2+1);
+
+      return "";
+   }				
+
+   virtual std::string  getFileName() {return this->filename;}
+protected:
+   std::ofstream outfile;
+   std::string   filename; 
+   char          commentindicator; 
+};
+
+#endif //UBFILEOUTPUT_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileOutputASCII.cpp b/source/VirtualFluidsCore/Basics/utilities/UbFileOutputASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d68a766be8622f1138f6a0e22863b0962141f0bc
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileOutputASCII.cpp
@@ -0,0 +1,177 @@
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbInfinity.h>
+#include <basics/utilities/UbMath.h>
+#include <cstring>
+
+using namespace std;
+
+UbFileOutputASCII::UbFileOutputASCII(const string& filename, const bool& createPath, const int& precision)
+   : UbFileOutput(filename)
+{
+	this->commentindicator = 'C'; 
+	this->setPrecision(20);
+
+   outfile.open(filename.c_str(),ios::out);
+   
+   if(!outfile && createPath) 
+   {
+      outfile.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0) 
+      {
+         UbSystem::makeDirectory(path);
+         outfile.open(filename.c_str(),ios::out);
+      }
+   }
+
+      if(!outfile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+}
+/*==========================================================*/
+UbFileOutputASCII::UbFileOutputASCII(const std::string& filename, CREATEOPTION opt, const bool& createPath, const int& precision)
+   : UbFileOutput(filename)
+{
+	this->commentindicator = 'C'; 
+   this->setPrecision(precision);
+	
+   if(!this->open(filename,opt) && createPath) 
+   {
+      outfile.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0) UbSystem::makeDirectory(path);
+
+      this->open(filename,opt);
+   }
+
+   if(!outfile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+}
+/*==========================================================*/
+bool UbFileOutputASCII::open(const std::string& filename, CREATEOPTION opt)
+{
+   outfile.close();
+   outfile.clear(); //setzt flags zurueck
+   this->filename = filename;
+
+   if     (opt==UbFileOutput::OUTFILE      ) outfile.open(this->filename.c_str(),ios::out); 
+   else if(opt==UbFileOutput::INANDOUTFILE ) outfile.open(this->filename.c_str(),ios::out | ios::in);
+   else if(opt==UbFileOutput::APPENDFILE   ) outfile.open(this->filename.c_str(),ios::app);
+   else UB_THROW( UbException(UB_EXARGS,"undefined CREATEOPTION") );
+
+   return outfile.is_open();
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeBool(const bool& value, const int& width)				
+{
+   outfile.width(width);
+   if(value) outfile<<"true ";
+   else      outfile<<"false ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeDouble(const double& value, const int& width)				
+{
+   outfile.width(width);
+   //Problem: Ub::inf wird gerundet 
+   //         -> beim Einlesen ist der Wert evtl zu gross und es kommt murks raus 
+   //         -> max Laenge darstellen und gut ist
+   if(UbMath::equal(value, (double)Ub::inf) )
+   {
+      ios_base::fmtflags flags = outfile.flags();
+      outfile<<setprecision(std::numeric_limits<double>::digits10+2);
+      outfile<<value<<" ";
+      outfile.flags(flags);
+      return;
+   }
+   outfile<<value<<" ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeFloat(const float& value, const int& width)				
+{
+   outfile.width(width);
+   //Problem: Ub::inf wird gerundet 
+   //         -> beim Einlesen ist der Wert evtl zu gross und es kommt murks raus 
+   //         -> max Laenge darstellen und gut ist
+   if(UbMath::equal(value, (float)Ub::inf) )
+   {
+      ios_base::fmtflags flags = outfile.flags();
+      outfile<<setprecision(std::numeric_limits<float>::digits10+2);
+      outfile<<value<<" ";
+      outfile.flags(flags);
+      return;
+   }
+   outfile<<value<<" ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::setPrecision(const int& precision)				
+{
+   outfile<<setprecision(precision);
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeInteger(const int& value, const int& width)				
+{
+   outfile.width(width);
+   outfile<<value<<" ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeSize_t(const std::size_t& value, const int& width)
+{
+   outfile.width(width);
+   outfile<<value<<" ";
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeChar(const char& value, const int& width)
+{
+   outfile.width(width);
+   outfile<<(int)value<<" ";	
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeString(const string& value, const int& width)				
+{
+   outfile.width(width);
+   outfile<<value.c_str()<<" ";	
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeStringOnly(const string& value)				
+{
+	outfile<<value.c_str();	
+}
+
+/*==========================================================*/
+void UbFileOutputASCII::writeLine(const string& value, const int& width)				
+{
+   outfile.width(width);
+   outfile<<value.c_str()<<endl;	
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeLine()				
+{
+	outfile<<endl;	
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeCommentLine(const string& line) 
+{
+   this->writeCommentLine(this->commentindicator, line); 
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeCommentLine(char indicator, const string& line) 
+{
+	this->outfile<<indicator<<line<<endl;
+}
+/*==========================================================*/
+void UbFileOutputASCII::writeCopyOfFile(const string& filename)
+{
+   ifstream infile(filename.c_str());
+   if(!infile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+
+   try
+   {
+      char c;
+      while(infile.get(c)) 
+      {
+         outfile.put(c);  //=out<<c;
+      }
+      outfile.flush();
+      infile.close();
+   }
+   catch(std::exception& e) { UB_THROW( UbException(UB_EXARGS,"catched std::exception, error: "+(std::string)e.what()) ); }
+   catch(...)               { UB_THROW( UbException(UB_EXARGS,"unknown error") ); }
+}
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileOutputASCII.h b/source/VirtualFluidsCore/Basics/utilities/UbFileOutputASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0accdfbefc4f78aefc4812ff6f10fbce7e13ac7
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileOutputASCII.h
@@ -0,0 +1,72 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEOUTPUTASCII_H
+#define UBFILEOUTPUTASCII_H
+
+#include <iomanip>
+#include <fstream>
+#include <iostream>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileOutput.h>
+
+/*=========================================================================*/
+/*  UbFileOutputASCII                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileOutputASCII : public UbFileOutput
+{
+public:
+   UbFileOutputASCII() : UbFileOutput() {}
+   UbFileOutputASCII(const std::string& filename, const bool& createPath=true,  const int& precision=15);             
+   UbFileOutputASCII(const std::string& filename, CREATEOPTION opt, const bool& createPath=true, const int& precision=15);
+   
+   bool open(const std::string& filename, CREATEOPTION opt=OUTFILE);
+   
+   void writeBool(const bool& value, const int& width=0);
+   void writeDouble(const double& value, const int& width=0);
+	void writeFloat(const float& value, const int& width=0);
+	void writeInteger(const int& value, const int& width=0);
+   void writeSize_t(const std::size_t& value, const int& width=0);
+   void writeChar(const char& value, const int& width=0);
+   void writeString(const std::string& value, const int& width=0);
+   void writeStringOnly(const std::string& value);
+   void writeLine(const std::string& value, const int& width=0);
+   void writeLine();
+  
+   void setPrecision(const int& precision);
+   int  getPrecision() { return (int)outfile.precision(); }
+
+   void setCommentIndicator(char commentindicator) {this->commentindicator = commentindicator;} 
+   
+   void writeCommentLine(const std::string& line);
+   void writeCommentLine(char indicator, const std::string& line);
+   void writeCopyOfFile(const std::string& filename);
+
+   FILETYPE getFileType() { return ASCII; }
+
+   template< typename T >
+   friend inline UbFileOutputASCII& operator<<(UbFileOutputASCII& file, const T& data) 
+   {
+      file.outfile<<data;
+      return file;
+   }
+};
+
+#endif
+
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileOutputBinary.cpp b/source/VirtualFluidsCore/Basics/utilities/UbFileOutputBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..144adbc76b1b020f049f237bbd23c496110ebd9a
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileOutputBinary.cpp
@@ -0,0 +1,180 @@
+#include <basics/utilities/UbFileOutputBinary.h>
+#include <basics/utilities/UbSystem.h>
+#include <cstring>
+
+using namespace std;
+
+/*==========================================================*/
+UbFileOutputBinary::UbFileOutputBinary(const string& filename, const bool& createPath)
+{
+   this->filename         = filename;
+   this->commentindicator = 'C'; 
+
+   outfile.open(filename.c_str(),ios::out | ios::binary);
+
+   if(!outfile && createPath) 
+   {
+      string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0)
+      {
+         outfile.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+         UbSystem::makeDirectory(path);
+         outfile.open(filename.c_str(),ios::out | ios::binary);
+      }
+   }
+
+   if(!outfile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+
+}
+/*==========================================================*/
+UbFileOutputBinary::UbFileOutputBinary(const string& filename,UbFileOutput::CREATEOPTION opt, const bool& createPath)
+{
+   this->filename         = filename;
+   this->commentindicator = 'C'; 
+
+   this->open(filename,opt);
+
+   if(!this->open(filename,opt) && createPath) 
+   {
+      string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0)
+      {
+         outfile.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+         UbSystem::makeDirectory(path,20);
+
+         this->open(filename,opt);     
+      }      
+   }
+
+   if(!outfile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+}
+/*==========================================================*/
+bool UbFileOutputBinary::open(const string& filename, UbFileOutput::CREATEOPTION opt)
+{
+   outfile.close();
+   outfile.clear(); //setzt flags zurueck
+
+   this->filename         = filename;
+
+   if     (opt==UbFileOutput::OUTFILE    )  outfile.open(this->filename.c_str(),ios::out | ios::binary);
+   else if(opt==UbFileOutput::APPENDFILE )  outfile.open(this->filename.c_str(),ios::app | ios::binary);
+   else if(opt==UbFileOutput::INANDOUTFILE) UB_THROW( UbException(UB_EXARGS,"undefined CREATEOPTION - INANDOUTFILE not possible for BINARY files") );
+   else UB_THROW( UbException(UB_EXARGS,"undefined CREATEOPTION") );
+
+   return outfile.is_open();
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeBool(const bool& value, const int& width)				
+{
+   outfile.write((char*)&value,sizeof(bool));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeDouble(const double& value, const int& width)				
+{
+   outfile.write((char*)&value,sizeof(double));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeFloat(const float& value, const int& width)				
+{
+	outfile.write((char*)&value,sizeof(float));
+}
+/*==========================================================*/
+void UbFileOutputBinary::setPrecision(const int& precision)				
+{
+   UB_THROW( UbException(UB_EXARGS,"no way") );
+}
+/*==========================================================*/
+int UbFileOutputBinary::getPrecision()				
+{
+   UB_THROW( UbException(UB_EXARGS,"no way") );
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeInteger(const int& value, const int& width)				
+{
+   outfile.write((char*)&value,sizeof(value));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeSize_t(const std::size_t& value, const int& width)
+{
+   outfile.write((char*)&value,sizeof(value));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeChar(const char& value, const int& width)				
+{
+   outfile.write((char*)&value,sizeof(value));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeString(const string& value, const int& width)				
+{
+   char c='\0';
+   unsigned int length = (unsigned)value.length();
+   
+   unsigned pos;
+   //whitespaces und tabs am stringanfang uebergehen
+   for(pos=0; pos<length; pos++)
+      if( value[pos]!=' ' && value[pos]!='\t' ) break;
+
+   while(pos<length)
+   {
+      while(pos<length && value[pos]!=' ' && value[pos]!='\t' && value[pos]!='\0')
+      {
+         outfile.write((char*)&(value[pos++]),sizeof(char));
+      }
+
+      outfile.write(&c,sizeof(char));
+      pos++;
+
+      while(pos<length && (value[pos]==' ' || value[pos]=='\t' || value[pos]=='\0') )
+      {
+         pos++;
+      }
+   }
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeStringOnly(const string& value)				
+{
+   UbException(UB_EXARGS,"no way... causes to many errors");
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeLine(const std::string& value, const int& width)				
+{
+   this->writeString(value);
+   char c='\n';
+   outfile.write(&c,sizeof(char));
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeLine()				
+{
+   char c='\n';
+   outfile.write(&c,sizeof(char));   
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeCommentLine(const string& line) 
+{
+   try        { this->writeCommentLine(this->commentindicator, line); }
+   catch(...) { UB_THROW( UbException(UB_EXARGS,"unknown error") ); }
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeCommentLine(char indicator, const string& line) 
+{
+   string dummy = indicator + line;
+   this->writeLine(dummy);
+}
+/*==========================================================*/
+void UbFileOutputBinary::writeCopyOfFile(const string& filename)
+{
+   ifstream infile(filename.c_str(),ios::in | ios::binary);
+   if(!infile) UB_THROW( UbException(UB_EXARGS,"couldn't open file:\n "+filename) );
+
+   try
+   {
+      char c;
+      while(infile.get(c)) 
+      {
+         outfile.put(c);  //=out<<c;
+      }
+      outfile.flush();
+      infile.close();
+   }
+   catch(...) {UB_THROW( UbException(UB_EXARGS,"unknown error") );}
+}
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbFileOutputBinary.h b/source/VirtualFluidsCore/Basics/utilities/UbFileOutputBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..fac53e7ac439f4fe55410043f5830ff72fc4c852
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbFileOutputBinary.h
@@ -0,0 +1,70 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBFILEOUTPUTBINARY_H
+#define UBFILEOUTPUTBINARY_H
+
+#include <iomanip>
+#include <fstream>
+#include <iostream>
+
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileOutput.h>
+
+/*=========================================================================*/
+/*  UbFileOutputBinary                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.11.04
+*/ 
+
+/*
+usage: ...
+*/
+
+class UbFileOutputBinary : public UbFileOutput
+{
+public:
+   UbFileOutputBinary() : UbFileOutput() {}
+   UbFileOutputBinary(const std::string& filename, const bool& createPath=true);
+   UbFileOutputBinary(const std::string& filename, UbFileOutput::CREATEOPTION opt, const bool& createPath);
+   
+   bool open(const std::string& filename, UbFileOutput::CREATEOPTION opt=OUTFILE);
+
+   void writeInteger(const int& value, const int& width=0);
+   void writeDouble(const double& value, const int& width=0);
+	void writeFloat(const float& value, const int& width=0);
+	void writeBool(const bool& value, const int& width=0);
+   void writeChar(const char& value, const int& width=0);
+   void writeSize_t(const std::size_t& value, const int& width=0);
+   void writeString(const std::string& value, const int& width=0);
+   void writeStringOnly(const std::string& value);
+   void writeLine(const std::string& value, const int& width=0);
+   void writeLine();
+   void writeCommentLine(const std::string& line);
+   void writeCommentLine(char indicator, const std::string& line);
+   void writeCopyOfFile(const std::string& filename);
+
+   void setPrecision(const int& precision);
+   int  getPrecision();
+
+   FILETYPE getFileType() { return BINARY; }
+
+   template< typename T >
+   friend inline UbFileOutputBinary& operator<<(UbFileOutputBinary& file, const T& data) 
+   {
+      file.outfile.write((char*)&data,sizeof(T));
+      return file;
+   }
+};
+
+#endif
+
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbInfinity.h b/source/VirtualFluidsCore/Basics/utilities/UbInfinity.h
new file mode 100644
index 0000000000000000000000000000000000000000..18546b8ad9d29c6c6119446243953ae235342724
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbInfinity.h
@@ -0,0 +1,180 @@
+#ifndef UB_INFINITY_H
+#define UB_INFINITY_H
+#include <limits>
+
+#include <basics/utilities/UbLimits.h>
+#include <basics/utilities/UbSystem.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+//  UbNegInfinity
+//  Anm: keine template klasse, da man am Ende eine Instanz "inf" verwendet
+//       die in "verschiedene"(!!!) Typen konvertiert werden kann und nicht 
+//       nur in den template Typ!
+//  Note: The UbNegInfinity class cannot be instantiated on its own, but works 
+//        as a base class for the Infinity class.
+//////////////////////////////////////////////////////////////////////////
+class UbNegInfinity
+{
+ public:
+   //name Conversion operators 
+   inline operator signed char() const { return UbLimits<signed char>::ninf(); }
+   inline operator char()        const { return UbLimits<char>::ninf();        }
+   inline operator wchar_t()     const { return UbLimits<wchar_t>::ninf();     }
+   inline operator short()       const { return UbLimits<short>::ninf();       }
+   inline operator int()         const { return UbLimits<int>::ninf();         }
+   inline operator long()        const { return UbLimits<long>::ninf();        }
+   inline operator float()       const { return UbLimits<float>::ninf();       }
+   inline operator double()      const { return UbLimits<double>::ninf();      }
+   inline operator long double() const { return UbLimits<long double>::ninf(); }
+
+   // This function compares built-in data types with their largest possible value. The function
+   // only works for built-in data types. The attempt to compare user-defined class types will
+   // result in a compile time error.
+   template< typename T >
+   inline bool equal( const T& rhs ) const
+   {
+      UB_STATIC_ASSERT( std::numeric_limits<T>::is_specialized );
+      return UbLimits<T>::ninf() == rhs;
+   }
+ protected:
+    inline UbNegInfinity() {}
+
+ private:
+   UbNegInfinity( const UbNegInfinity& ninf );             //copy constructor (private & undefined)
+   UbNegInfinity& operator=( const UbNegInfinity& ninf );  //copy assignment operator (private & undefined)
+   void* operator&() const;                                //address operator (private & undefined)
+};
+
+//=================================================================================================
+//
+//  GLOBAL OPERATORS
+//
+//=================================================================================================
+template< typename T >
+inline bool operator==( const UbNegInfinity& lhs, const T& rhs )
+{
+   return lhs.equal( rhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator==( const T& lhs, const UbNegInfinity& rhs )
+{
+   return rhs.equal( lhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator!=( const UbNegInfinity& lhs, const T& rhs )
+{
+   return !lhs.equal( rhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator!=( const T& lhs, const UbNegInfinity& rhs )
+{
+   return !rhs.equal( lhs );
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+//  UbInfinity
+//
+//////////////////////////////////////////////////////////////////////////
+class UbInfinity : public UbNegInfinity //um später -UbInfinity leichter zu implementieren!!!
+{
+ public:
+   inline UbInfinity() 
+      : UbNegInfinity()
+    {}
+   
+   inline operator unsigned char()  const  { return UbLimits<unsigned char>::inf();  }
+   inline operator signed char()    const  { return UbLimits<signed char>::inf();    }
+   inline operator char()           const  { return UbLimits<char>::inf();           }
+   inline operator wchar_t()        const  { return UbLimits<wchar_t>::inf();        }
+   inline operator unsigned short() const  { return UbLimits<unsigned short>::inf(); }
+   inline operator short()          const  { return UbLimits<short>::inf();          }
+   inline operator unsigned int()   const  { return UbLimits<unsigned int>::inf();   }
+   inline operator int()            const  { return UbLimits<int>::inf();            }
+   inline operator unsigned long()  const  { return UbLimits<unsigned long>::inf();  }
+   inline operator long()           const  { return UbLimits<long>::inf();           }
+   inline operator float()          const  { return UbLimits<float>::inf();          }
+   inline operator double()         const  { return UbLimits<double>::inf();         }
+   inline operator long double()    const  { return UbLimits<long double>::inf();    }
+
+   inline const UbNegInfinity& operator-() const { return static_cast<const UbNegInfinity&>( *this ); }
+
+   /*==========================================================*/
+   template< typename T >
+   inline bool equal( const T& rhs ) const
+   {
+      UB_STATIC_ASSERT( std::numeric_limits<T>::is_specialized );
+      return UbLimits<T>::inf() == rhs;
+   }
+
+ private:
+   UbInfinity( const UbInfinity& inf );             //Copy constructor (private & undefined)
+   UbInfinity& operator=( const UbInfinity& inf );  //Copy assignment operator (private & undefined)
+   void* operator&() const;                         //Address operator (private & undefined)
+};
+
+//////////////////////////////////////////////////////////////////////////
+//  GLOBAL OPERATORS
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+inline bool operator==( const UbInfinity& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator==( const T& lhs, const UbInfinity& rhs );
+
+template< typename T >
+inline bool operator!=( const UbInfinity& lhs, const T& rhs );
+
+template< typename T >
+inline bool operator!=( const T& lhs, const UbInfinity& rhs );
+//@}
+//*************************************************************************************************
+
+
+//*************************************************************************************************
+/*!\brief Equality comparison between an Infinity object and a built-in data type.
+// \ingroup util
+//
+// This operator works only for built-in data types. The attempt to compare user-defined class
+// types will result in a compile time error.
+*/
+template< typename T >
+inline bool operator==( const UbInfinity& lhs, const T& rhs )
+{
+   return lhs.equal( rhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator==( const T& lhs, const UbInfinity& rhs )
+{
+   return rhs.equal( lhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator!=( const UbInfinity& lhs, const T& rhs )
+{
+   return !lhs.equal( rhs );
+}
+//*************************************************************************************************
+template< typename T >
+inline bool operator!=( const T& lhs, const UbInfinity& rhs )
+{
+   return !rhs.equal( lhs );
+}
+//*************************************************************************************************
+
+//////////////////////////////////////////////////////////////////////////
+//  GLOBAL INFINITY VALUE
+//////////////////////////////////////////////////////////////////////////
+namespace Ub
+{
+   //e.g. double x = UbSystem::inf;  float x = -Ub::inf; 
+   const UbInfinity inf; 
+} 
+
+#endif //UB_INFINITY_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbKeys.h b/source/VirtualFluidsCore/Basics/utilities/UbKeys.h
new file mode 100644
index 0000000000000000000000000000000000000000..feaf5cab8c58e6fe2f26bd3ce6d63b2aee609ed5
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbKeys.h
@@ -0,0 +1,311 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBKEYS_H
+#define UBKEYS_H
+
+#include <iostream>
+
+#include <boost/serialization/serialization.hpp>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+/*=========================================================================*/
+/*  UbKeys                                                             */
+/*                                                                         */
+/**
+namespace for global Keys (e.g. for STL-maps)
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 08.08.07
+*/ 
+
+/*
+usage: ...
+*/
+
+namespace UbKeys
+{
+   //nested class
+   template< typename T1, typename T2 = T1 >
+   class Key2 
+   {
+   public:
+      //////////////////////////////////////////////////////////////////////////
+      //Konstruktoren
+      Key2(const T1& t1, const T2& t2) 
+         : t1(t1), t2(t2)
+      { 
+      }
+      /*==========================================================*/
+      Key2& operator=(const Key2& srcKey) 
+      {
+         if(this == &srcKey ) return *this;
+
+         t1    = srcKey.t1;
+         t2    = srcKey.t2;
+
+         return *this;
+      }
+      /*==========================================================*/
+      T1 getT1() const { return t1; }
+      T2 getT2() const { return t2; }
+
+      //////////////////////////////////////////////////////////////////////////
+      //global ueberladene Operatoren
+      friend inline bool operator<(const Key2& lhsKey,const Key2& rhsKey)  
+      {
+         if( lhsKey.t1 < rhsKey.t1 ) return true;
+         if( lhsKey.t1 > rhsKey.t1 ) return false;
+         if( lhsKey.t2 < rhsKey.t2 ) return true;
+
+         return false;
+      }
+      /*==========================================================*/
+      friend inline bool operator==(const Key2& lhsKey, const Key2& rhsKey)  
+      {
+         if(lhsKey.t1 != rhsKey.t1 ) return false;
+         if(lhsKey.t2 != rhsKey.t2 ) return false;
+
+         return true;
+      }
+      //ueberladene Operatoren
+      friend inline bool operator!=(const Key2& lhsKey, const Key2& rhsKey)  
+      {
+         return !(lhsKey == rhsKey); 
+      }
+      //ueberladene Operatoren
+      /*==========================================================*/
+      friend inline std::ostream& operator << (std::ostream& os, const Key2& key) 
+      {
+         os<<"Key2<"<<typeid(T1).name()<<","<<typeid(T2).name()<<">,("<<key.t1<<","<<key.t2<<")";
+         return os;
+      }
+      /*==========================================================*/
+      #ifdef CAB_RCF
+	      template<class Archive>
+	      void serialize(Archive & ar, const unsigned int version)
+	      {
+		      ar & t1;
+		      ar & t2;
+	      }
+      #endif //CAB_RCF
+
+   private:
+      //////////////////////////////////////////////////////////////////////////
+      //private Member
+      T1 t1;
+      T2 t2;
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & t1;
+         ar & t2;
+      }
+   };
+
+   //////////////////////////////////////////////////////////////////////////
+   //
+   //////////////////////////////////////////////////////////////////////////
+   template< typename T1, typename T2 = T1, typename T3 = T1 >
+   class Key3 
+   {
+   public:
+      //////////////////////////////////////////////////////////////////////////
+      //Konstruktoren
+      Key3() : t1(0), t2(0), t3(0)
+      {
+
+      }
+      Key3(const T1& t1, const T2& t2, const T3& t3) 
+         : t1(t1), t2(t2), t3(t3)
+      { 
+      }
+      /*==========================================================*/
+      T1 getT1() const { return t1; }
+      T2 getT2() const { return t2; }
+      T3 getT3() const { return t3; }
+      /*==========================================================*/
+      Key3& operator=(const Key3& srcKey) 
+      {
+         if(this == &srcKey ) return *this;
+
+         t1    = srcKey.t1;
+         t2    = srcKey.t2;
+         t3    = srcKey.t3;
+
+         return *this;
+      }
+
+      //////////////////////////////////////////////////////////////////////////
+      //global ueberladene Operatoren
+      friend inline bool operator<(const Key3& lhsKey,const Key3& rhsKey)  
+      {
+         if( lhsKey.t1 < rhsKey.t1 ) return true;
+         if( lhsKey.t1 > rhsKey.t1 ) return false;
+         if( lhsKey.t2 < rhsKey.t2 ) return true;
+         if( lhsKey.t2 > rhsKey.t2 ) return false;
+         if( lhsKey.t3 < rhsKey.t3 ) return true;
+
+         return false;
+      }
+      /*==========================================================*/
+      friend inline bool operator==(const Key3& lhsKey,const Key3& rhsKey)  
+      {
+         if(lhsKey.t1 != rhsKey.t1 ) return false;
+         if(lhsKey.t2 != rhsKey.t2 ) return false;
+         if(lhsKey.t3 != rhsKey.t3 ) return false;
+
+         return true;
+      }
+      /*==========================================================*/
+      //ueberladene Operatoren
+      friend inline bool operator!=(const Key3& lhsKey, const Key3& rhsKey) 
+      {
+         return !(lhsKey == rhsKey); 
+      }
+
+      //ueberladene Operatoren
+      /*==========================================================*/
+      friend inline std::ostream& operator << (std::ostream& os, const Key3& key) 
+      {
+         os<<"Key3<"<<typeid(T1).name()<<","<<typeid(T2).name()<<","<<typeid(T3).name();
+         os<<">,("<<key.t1<<","<<key.t2<<","<<key.t3<<")";
+         return os;
+      }
+      /*==========================================================*/
+      #ifdef CAB_RCF
+	      template<class Archive>
+	      void serialize(Archive & ar, const unsigned int version)
+	      {
+		      ar & t1;
+		      ar & t2;
+            ar & t3;
+         }
+      #endif //CAB_RCF
+
+   private:
+      //////////////////////////////////////////////////////////////////////////
+      //private Member
+      T1 t1;
+      T2 t2;
+      T3 t3;
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & t1;
+         ar & t2;
+         ar & t3;
+      }
+   };
+
+   //////////////////////////////////////////////////////////////////////////
+   //
+   //////////////////////////////////////////////////////////////////////////
+   template< typename T1, typename T2 = T1, typename T3 = T1, typename T4 = T1 >
+   class Key4 
+   {
+   public:
+      //////////////////////////////////////////////////////////////////////////
+      //Konstruktoren
+      Key4(const T1& t1, const T2& t2, const T3& t3, const T4& t4) 
+         : t1(t1), t2(t2), t3(t3), t4(t4)
+      { 
+      }
+      /*==========================================================*/
+      T1 getT1() const { return t1; }
+      T2 getT2() const { return t2; }
+      T3 getT3() const { return t3; }
+      T4 getT4() const { return t4; }
+      /*==========================================================*/
+      Key4& operator=(const Key4& srcKey) 
+      {
+         if(this == &srcKey ) return *this;
+
+         t1    = srcKey.t1;
+         t2    = srcKey.t2;
+         t3    = srcKey.t3;
+         t4    = srcKey.t4;
+
+         return *this;
+      }
+      //////////////////////////////////////////////////////////////////////////
+      //global ueberladene Operatoren
+      friend inline bool operator<(const Key4& lhsKey,const Key4& rhsKey)  
+      {
+         if( lhsKey.t1 < rhsKey.t1 ) return true;
+         if( lhsKey.t1 > rhsKey.t1 ) return false;
+         if( lhsKey.t2 < rhsKey.t2 ) return true;
+         if( lhsKey.t2 > rhsKey.t2 ) return false;
+         if( lhsKey.t3 < rhsKey.t3 ) return true;
+         if( lhsKey.t3 > rhsKey.t3 ) return false;
+         if( lhsKey.t4 < rhsKey.t4 ) return true;
+
+         return false;
+      }
+      /*==========================================================*/
+      friend inline bool operator==(const Key4& lhsKey,const Key4& rhsKey)  
+      {
+         if(lhsKey.t1 != rhsKey.t1 ) return false;
+         if(lhsKey.t2 != rhsKey.t2 ) return false;
+         if(lhsKey.t3 != rhsKey.t3 ) return false;
+         if(lhsKey.t4 != rhsKey.t4 ) return false;
+
+         return true;
+      }
+
+      //ueberladene Operatoren
+      friend inline bool operator!=(const Key4& lhsKey, const Key4& rhsKey) 
+      {
+         return !(lhsKey == rhsKey); 
+      }
+      //ueberladene Operatoren
+      /*==========================================================*/
+      friend inline std::ostream& operator << (std::ostream& os, const Key4& key) 
+      {
+         os<<"Key4<"<<typeid(T1).name()<<","<<typeid(T2).name()<<","<<typeid(T3).name()<<","<<typeid(T4).name();
+         os<<">,("<<key.t1<<","<<key.t2<<","<<key.t3<<","<<key.t4<<")";
+         return os;
+      }
+      /*==========================================================*/
+      #ifdef CAB_RCF
+	      template<class Archive>
+	      void serialize(Archive & ar, const unsigned int version)
+	      {
+		      ar & t1;
+		      ar & t2;
+            ar & t3;
+            ar & t4;
+         }
+      #endif //CAB_RCF
+
+   private:
+      //////////////////////////////////////////////////////////////////////////
+      //private Member
+      T1 t1;
+      T2 t2;
+      T3 t3;
+      T4 t4;
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & t1;
+         ar & t2;
+         ar & t3;
+         ar & t4;
+      }
+   };
+}
+
+#endif //UBKEYS_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbLimits.h b/source/VirtualFluidsCore/Basics/utilities/UbLimits.h
new file mode 100644
index 0000000000000000000000000000000000000000..9313f0620a138785dd9b7e6c334917806da93c30
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbLimits.h
@@ -0,0 +1,139 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UB_LIMITS_H
+#define UB_LIMITS_H
+
+
+//*************************************************************************************************
+// Includes
+//*************************************************************************************************
+
+#include <limits>
+
+//////////////////////////////////////////////////////////////////////////
+//  CLASS DEFINITION
+//////////////////////////////////////////////////////////////////////////
+template< typename T >
+struct UbLimits  {};
+
+//////////////////////////////////////////////////////////////////////////
+//  SPECIALIZATIONS
+//////////////////////////////////////////////////////////////////////////
+template<>
+struct UbLimits<unsigned char>
+{
+   //return the largest possible positive unsigned char value
+   static inline unsigned char inf() { return std::numeric_limits<unsigned char>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<char>
+{
+   //return the largest possible positive char value. */
+   static inline char inf () { return std::numeric_limits<char>::max(); }
+   //return the largest possible negative char value
+   static inline char ninf() { return std::numeric_limits<char>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<signed char>
+{
+   //return the largest possible positive signed char value
+   static inline signed char inf () { return std::numeric_limits<signed char>::max(); }
+
+   //return The largest possible negative signed char value
+   static inline signed char ninf() { return std::numeric_limits<signed char>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<wchar_t>
+{
+   //return The largest possible positive wchar_t value
+   static inline wchar_t inf () { return std::numeric_limits<wchar_t>::max(); }
+   //return The largest possible negative wchar_t value
+   static inline wchar_t ninf() { return std::numeric_limits<wchar_t>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<unsigned short>
+{
+   //return The largest possible positive unsigned short value
+   static inline unsigned short inf() { return std::numeric_limits<unsigned short>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<short>
+{
+   //return The largest possible positive short value
+   static inline short inf () { return std::numeric_limits<short>::max(); }
+   //return The largest possible negative short value
+   static inline short ninf() { return std::numeric_limits<short>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<unsigned int>
+{
+   //return The largest possible positive unsigned int value
+   static inline unsigned int inf() { return std::numeric_limits<unsigned int>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<int>
+{
+   //return The largest possible positive int value
+   static inline int inf () { return std::numeric_limits<int>::max(); }
+
+   //return The largest possible negative int value
+   static inline int ninf() { return std::numeric_limits<int>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<unsigned long>
+{
+   //return The largest possible positive unsigned long value
+   static inline unsigned long inf() { return std::numeric_limits<unsigned long>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<long>
+{
+   //return The largest possible positive long value
+   static inline long inf () { return std::numeric_limits<long>::max(); }
+
+   //return The largest possible negative long value
+   static inline long ninf() { return std::numeric_limits<long>::min(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<float>
+{
+   //return The largest possible positive float value
+   static inline float inf () { return  std::numeric_limits<float>::max(); }
+
+   //return The largest possible negative float value
+   static inline float ninf() { return -std::numeric_limits<float>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<double>
+{
+   //return The largest possible positive double value
+   static inline double inf () { return  std::numeric_limits<double>::max(); }
+   //return The largest possible negative double value
+   static inline double ninf() { return -std::numeric_limits<double>::max(); }
+};
+//*************************************************************************************************
+template<>
+struct UbLimits<long double>
+{
+   //return The largest possible positive long double value
+   static inline long double inf () { return  std::numeric_limits<long double>::max(); }
+   //return The largest possible negative long double value
+   static inline long double ninf() { return -std::numeric_limits<long double>::max(); }
+};
+
+#endif //UB_LIMITS_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbLogger.cpp b/source/VirtualFluidsCore/Basics/utilities/UbLogger.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f487a02ed08408d632ccab624b657f0283686ad5
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbLogger.cpp
@@ -0,0 +1,8 @@
+#include <basics/utilities/UbLogger.h>
+
+#if defined(CAB_BOOST) && !defined(NO_THREADSAFE_LOGGING)
+
+boost::mutex Output2Stream::mtx;
+
+#endif // CAB_BOOST
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbLogger.h b/source/VirtualFluidsCore/Basics/utilities/UbLogger.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d4e432ce7c4ec2284aba328cc7344d1db6aec4b
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbLogger.h
@@ -0,0 +1,362 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBLOGGER_H
+#define UBLOGGER_H
+
+#include <sstream>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <memory>
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)  || defined(_WIN64)  || defined(__WIN64__)
+   #include <windows.h>
+#else
+   #include <sys/time.h>
+#endif
+
+#if defined(CAB_BOOST) && !defined(NO_THREADSAFE_LOGGING)
+   #include <boost/thread.hpp>
+#endif // CAB_BOOST
+
+//////////////////////////////////////////////////////////////////////////
+// UbLogger
+// C++ Logger
+// Funktionsweise:
+// pro Logeintrag wird ein UbLogger-Objekt erstellt, der logstring uebergeben und beim "zerstroeren"
+// wird der logstring mittels der entsprechenden policy (=template paramter)  z.B. in eine Datei
+// oder auf dem Bildschirm ausgegeben. Es werden verschiedene LogLevel unterstuetzt 
+//
+// Hilfsmakro:  UBLOG
+// Bsp1:        UBLOG(logINFO) << "Klasse::foo entered"; //endl wir nicht benötigt
+//              --> Eintrag:
+//
+// Bsp2: siehe Dateiende!
+//
+//Idee basierend auf: 
+//Artikel von Dr. Dobbs Portal
+//September 05, 2007
+//Logging In C++
+//
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@version 1.0 - 12.10.2008
+
+enum LogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4, logDEBUG5};
+
+//////////////////////////////////////////////////////////////////////////
+// template <typename OutputPolicy> class Log  - declaration
+//////////////////////////////////////////////////////////////////////////
+template <typename OutputPolicy>
+class UbLogger
+{   
+public:
+   typedef OutputPolicy output_policy;
+public:
+    UbLogger();
+    virtual ~UbLogger();
+    std::ostringstream& get(const LogLevel& level = logINFO);
+public:
+   //static, weil man so später die ObjErstellunge ersparen kann,
+   //falls level kleiner als Level
+   static LogLevel&   reportingLevel();
+    
+    static std::string logLevelToString(const LogLevel& level);
+    static LogLevel    logLevelFromString(const std::string& level);
+
+    static std::string logTimeString();
+
+protected:
+    std::ostringstream os;
+
+private:
+    UbLogger(const UbLogger&);
+    UbLogger& operator =(const UbLogger&);
+};
+
+//////////////////////////////////////////////////////////////////////////
+// template <typename OutputPolicy> class Log  - implementation
+//////////////////////////////////////////////////////////////////////////
+template <typename OutputPolicy>
+UbLogger<OutputPolicy>::UbLogger()
+{
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+std::ostringstream& UbLogger<OutputPolicy>::get(const LogLevel& level) 
+{
+   os << logTimeString() << " " << std::setw(6) 
+#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING)
+      <<boost::this_thread::get_id() << " "
+#endif
+      << std::setw(8) << std::left << UbLogger<OutputPolicy>::logLevelToString(level) << ": "
+      << std::string(level > logDEBUG ? 3*(level - logDEBUG) : 0, ' '); //<baumartiger output :D
+   
+    return os;
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+UbLogger<OutputPolicy>::~UbLogger()
+{
+    os << std::endl;
+    OutputPolicy::output(os.str());
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+LogLevel& UbLogger<OutputPolicy>::reportingLevel()
+{
+    static LogLevel reportLevel = logINFO;
+    return reportLevel;
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+std::string UbLogger<OutputPolicy>::logLevelToString(const LogLevel& level)
+{
+   static std::string const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"};
+   return buffer[level];
+}
+/*==========================================================*/
+template <typename OutputPolicy>
+LogLevel UbLogger<OutputPolicy>::logLevelFromString(const std::string& level)
+{
+   if (level == "DEBUG5" ) return logDEBUG5;
+   if (level == "DEBUG4" ) return logDEBUG4;
+   if (level == "DEBUG3" ) return logDEBUG3;
+   if (level == "DEBUG2" ) return logDEBUG2;
+   if (level == "DEBUG1" ) return logDEBUG1;
+   if (level == "DEBUG"  ) return logDEBUG;
+   if (level == "INFO"   ) return logINFO;
+   if (level == "WARNING") return logWARNING;
+   if (level == "ERROR"  ) return logERROR;
+       
+   UbLogger<OutputPolicy>().get(logWARNING) << "UbLogger<OutputPolicy>::logLevelFromString(level) - unknown logging level '" << level << "'. Using INFO level as default.";
+   return logINFO;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// logTimeString
+//////////////////////////////////////////////////////////////////////////
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)  || defined(_WIN64)  || defined(__WIN64__)
+template <typename OutputPolicy>
+inline std::string UbLogger<OutputPolicy>::logTimeString()
+{
+   const int MAX_LEN = 200;
+   char buffer[MAX_LEN];
+   if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, "HH':'mm':'ss", buffer, MAX_LEN) == 0 )
+   {
+      return "Error in std::string UbLogger<OutputPolicy>::logTimeString()";
+   }
+
+   char result[100] = {0};
+   static DWORD first = GetTickCount();
+   std::sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % 1000); 
+   return result;
+}
+#else
+template <typename OutputPolicy>
+inline std::string UbLogger<OutputPolicy>::logTimeString()
+{
+   char buffer[11];
+   time_t t;
+   time(&t);
+   tm r = {0};
+   strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
+   struct timeval tv;
+   gettimeofday(&tv, 0);
+   char result[100] = {0};
+   std::sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000); 
+   return result;
+}
+#endif 
+
+
+//////////////////////////////////////////////////////////////////////////
+// Output2Stream (=implementation of OutputPolicy)
+//////////////////////////////////////////////////////////////////////////
+//Anm: die erste Version mit auto_ptr fuer den stream fuehrte zu
+//     exceptions bei Verwedung vom Logger in dtors stat. globaler
+//     Objekte. Aber auch die Pointer-Lsg. ist noch nicht die 
+//     optimale Lösung
+class Output2Stream // implementation of OutputPolicy
+{
+public:
+   static std::ostream*& getStream();
+   static void output(const std::string& msg);
+   
+   //creates output-file-stream (of file opening fails -> stream is set to std::cerr)
+   static void setStream(const std::string& filename);
+   
+   //direct set outputstream, gcControl = true -> object will be deleted by Output2Stream 
+   static void setStream(std::ostream* pStream, const bool& gcControl = false);
+
+protected:
+#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING)
+   static boost::mutex mtx;
+#endif
+};
+/*==========================================================*/
+inline std::ostream*& Output2Stream::getStream()
+{
+   static std::ostream* pStream = &std::clog;
+   return pStream;
+}
+/*==========================================================*/
+inline void Output2Stream::setStream(std::ostream* pFile, const bool& gcControl)
+{
+#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING)
+   boost::mutex::scoped_lock lock(mtx);
+#endif
+   static bool s_gcControl = false;
+   
+   if( s_gcControl && Output2Stream::getStream() ) 
+   {
+      delete Output2Stream::getStream();
+   }
+   
+   s_gcControl = gcControl;
+   
+   Output2Stream::getStream() = pFile;
+}
+/*==========================================================*/
+inline void Output2Stream::setStream(const std::string& filename)
+{
+   std::ofstream* file = new std::ofstream( filename.c_str() );
+   if( !(*file) ) 
+   {
+      delete file;
+      Output2Stream::setStream(&std::cerr, false);
+      UbLogger<Output2Stream>().get(logERROR) << " Output2Stream::setStream(const std::string& filename) could not open file "
+                                               << filename << " -> std::cerr is used instead " << std::endl;
+      return;
+   }
+   std::cout<<"UbLog writes to "<<filename<<std::endl;
+   Output2Stream::setStream(file,true);
+}
+/*==========================================================*/
+inline void Output2Stream::output(const std::string& msg)
+{
+#if defined(CAB_BOOST) && !defined(NO_MT_LOGGING)
+   boost::mutex::scoped_lock lock(mtx);
+#endif
+   std::ostream* pStream = getStream();
+   if (!pStream) return;
+   (*pStream) << msg << std::flush;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// UbLog
+//////////////////////////////////////////////////////////////////////////
+class UbLog : public UbLogger< Output2Stream > 
+{
+public:
+   typedef Output2Stream output_policy;
+};
+
+//Makro um compilerseitig maxLevel zu beschränken
+#ifndef UBLOG_MAX_LEVEL
+   #define UBLOG_MAX_LEVEL logDEBUG5
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//Hauptmakro fuers Loggen
+// example UBLOG(logINFO) << "das ist ein log eintrag";
+//////////////////////////////////////////////////////////////////////////
+#define UBLOG(level, logtext) \
+   if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \
+   else UbLog().get(level) << logtext;                                                             
+   
+//wieso dieses Macro (was der der scheaeaeaesss???)
+// z.B. UBLOG(logDEBUG2) << "Ich bin sooo toll " << username;
+//also, was macht der praeprozessor draus?:
+// if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ;
+// else // Log().Get(logINFO) << "Ich bin sooo toll " << username;
+//Ergo: das prinzip des logging beruht auf: Log-Objekt erstellen und rauschreiben beim zerstoeren
+//    -> ist der zu loggende Level < als der im UBLOG angegebene erspart man sich hier die
+//       Objekt erstellung -> optimale Performance -> laut Petru Marginean (dem Verfasser des
+//       Ursprungslogger ist der Performance Unterschied kaum messbar, wenn NICHT geloggt wird!
+
+//////////////////////////////////////////////////////////////////////////
+//makro 2 fuer korrekten MultiLineOutput (teuer!!)
+// example1: UBLOGML(logINFO, "line1"<<endl<<"line2"<<endl<<"line3" )
+// example2: UBLOGML(logINFO, "line1\nline2\nendl\nline3" )
+//////////////////////////////////////////////////////////////////////////
+#define UBLOGML(level, multiline) \
+   if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \
+   else                                                                                            \
+   {                                                                                               \
+      std::ostringstream output;                                                                   \
+      output << multiline;                                                                         \
+      std::istringstream input( output.str() );                                                    \
+      while(!input.eof())                                                                          \
+      {                                                                                            \
+         std::string dummy;                                                                        \
+         getline(input,dummy,'\n');                                                                \
+         UbLog().get(level) << dummy;                                                              \
+      }                                                                                            \
+   }                                                                                          
+//////////////////////////////////////////////////////////////////////////
+//makro3, falls auch bildschirmausgabe erwünscht
+//   -> es wird sowohl ins logfile als auch auf den "stream" geschrieben
+//      wenn reporting level und level passen :D
+//example1: UBLOG2ML(logINFO, std::cout,  "line1"<<endl<<"line2"<<endl<<"line3" ) 
+//example2: UBLOG2ML(logINFO, std::cout,  "line1\nline2\nendl\nline3" ) 
+//////////////////////////////////////////////////////////////////////////
+#define UBLOG2(level, stream,  text ) \
+   if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \
+   else { stream << text <<std::endl; UbLog().get(level) << text;   }                             
+
+//////////////////////////////////////////////////////////////////////////
+//makro4, wie 3 nur mit multiline
+//example: UBLOG2(logINFO, std::cout,  "test" ) 
+//////////////////////////////////////////////////////////////////////////
+#define UBLOG2ML(level, stream,  multiline ) \
+   if(level > UBLOG_MAX_LEVEL || level > UbLog::reportingLevel() || !Output2Stream::getStream()) ; \
+   else                                                                                            \
+   {                                                                                               \
+      stream << multiline << std::endl;                                                            \
+      std::ostringstream output;                                                                   \
+      output << multiline;                                                                         \
+      std::istringstream input( output.str() );                                                    \
+      while(!input.eof())                                                                          \
+      {                                                                                            \
+         std::string dummy;                                                                        \
+         getline(input,dummy,'\n');                                                                \
+         UbLog().get(level) << dummy;                                                              \
+      }                                                                                            \
+   }                                                                                               
+
+//////////////////////////////////////////////////////////////////////////
+// example 2
+//////////////////////////////////////////////////////////////////////////
+// try
+// {
+//    UbLog::reportingLevel() = UbLog::logLevelFromString("DEBUG3");
+//    //UbLog::output_policy::setStream(&std::cerr); //<- clog ist stdandard
+//    UbLog::output_policy::setStream("c:/temp/out.txt");  //kann man diese nicht oeffnen -> fehlermeldung -> Log wird in cerr ausgegben
+// 
+//    int count = 3;
+//    UBLOG(logINFO, "A loop with " << count << " iterations");
+//    for (int i = 0; i != count; ++i)
+//    {
+//        UBLOG(logERROR , "error  - the counter i = " << i );
+//        UBLOG(logDEBUG1, "debug1 - the counter i = " << i );
+//        UBLOG(logDEBUG2, "debug2 - the counter i = " << i );
+//        UBLOG(logDEBUG3, "debug3 - the counter i = " << i );
+//        //fuer MultiLine Eintraege: --> koerrekte formatierung im logfile
+//        UBLOGML(logDEBUG3, "debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i);
+//        UBLOGML(logDEBUG3, "debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i);
+//        UBLOG2ML(logDEBUG3,std:cout,"debug3 - the counter i = "<<endl<<" 2 zeile "<< "3. Zeile" << i);
+//    }
+//    return 0;
+// }
+// catch(const std::exception& e)
+// {
+//    UBLOG(logERROR) << e.what();
+// }
+
+
+#endif //UBLOGGER_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbMath.cpp b/source/VirtualFluidsCore/Basics/utilities/UbMath.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad38b9cf945d569e8f2d7bd6118c35b27fadd4fe
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbMath.cpp
@@ -0,0 +1,614 @@
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbInfinity.h>
+#include <cstring> //for memcmp
+
+// namespace UbMath
+// {
+//double UbMath::EPSILON  = 1.0E-10;           
+const double UbMath::PI = 4.0* std::atan(1.0);   //3.1415926535897932384626433832795
+//}
+namespace UbMath{
+
+//////////////////////////////////////////////////////////////////////////
+const Vector3D Vector3D::ZERO(0.0,0.0,0.0);
+const Vector3D Vector3D::UNIT_X1(1.0,0.0,0.0);
+const Vector3D Vector3D::UNIT_X2(0.0,1.0,0.0);
+const Vector3D Vector3D::UNIT_X3(0.0,0.0,1.0);
+
+/*=======================================================*/
+Vector3D::Vector3D() 
+{                                      
+   m_afTuple[0] = 0.0;
+   m_afTuple[1] = 0.0;
+   m_afTuple[2] = 0.0;
+}
+/*=======================================================*/
+Vector3D::Vector3D(const double& fX, const double& fY, const double& fZ) 
+{
+   m_afTuple[0] = fX;
+   m_afTuple[1] = fY;
+   m_afTuple[2] = fZ;
+}
+/*=======================================================*/
+Vector3D::Vector3D (const Vector3D& rkV) 
+{
+   m_afTuple[0] = rkV.m_afTuple[0];
+   m_afTuple[1] = rkV.m_afTuple[1];
+   m_afTuple[2] = rkV.m_afTuple[2];
+}
+/*=======================================================*/
+std::string Vector3D::toString()  const
+{
+   std::stringstream os;
+   os<< "Vector3D["<<m_afTuple[0]<<","<<m_afTuple[1]<<","<<m_afTuple[2]<<"]";
+   return os.str();
+}
+/*=======================================================*/
+Vector3D::operator const double*() const
+{
+   return m_afTuple;
+}
+/*=======================================================*/
+Vector3D::operator double*()
+{
+   return m_afTuple;
+}
+/*=======================================================*/
+double Vector3D::operator[](const int& i) const
+{
+   assert( i >= 0 && i <= 2 );
+   return m_afTuple[i];
+}
+/*=======================================================*/
+double& Vector3D::operator[](const int& i)
+{
+   assert( i >= 0 && i <= 2 );
+   return m_afTuple[i];
+}
+/*=======================================================*/
+double Vector3D::X1() const
+{
+   return m_afTuple[0];
+}
+/*=======================================================*/
+double& Vector3D::X1()
+{
+   return m_afTuple[0];
+}
+/*=======================================================*/
+double Vector3D::X2() const
+{
+   return m_afTuple[1];
+}
+/*=======================================================*/
+double& Vector3D::X2()
+{
+   return m_afTuple[1];
+}
+/*=======================================================*/
+double Vector3D::X3() const
+{
+   return m_afTuple[2];
+}
+/*=======================================================*/
+double& Vector3D::X3()
+{
+   return m_afTuple[2];
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator=(const Vector3D& rkV)
+{
+   m_afTuple[0] = rkV.m_afTuple[0];
+   m_afTuple[1] = rkV.m_afTuple[1];
+   m_afTuple[2] = rkV.m_afTuple[2];
+   return *this;
+}
+/*=======================================================*/
+int Vector3D::CompareArrays(const Vector3D& rkV) const
+{
+   return memcmp(m_afTuple,rkV.m_afTuple,3*sizeof(double));
+}
+/*=======================================================*/
+bool Vector3D::operator==(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) == 0;
+}
+/*=======================================================*/
+bool Vector3D::operator!=(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) != 0;
+}
+/*=======================================================*/
+bool Vector3D::operator<(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) < 0;
+}
+/*=======================================================*/
+bool Vector3D::operator<=(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) <= 0;
+}
+/*=======================================================*/
+bool Vector3D::operator> (const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) > 0;
+}
+/*=======================================================*/
+bool Vector3D::operator>=(const Vector3D& rkV) const
+{
+   return CompareArrays(rkV) >= 0;
+}
+/*=======================================================*/
+Vector3D Vector3D::operator+(const Vector3D& rkV) const
+{
+   return Vector3D( m_afTuple[0]+rkV.m_afTuple[0],
+                    m_afTuple[1]+rkV.m_afTuple[1],
+                    m_afTuple[2]+rkV.m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D Vector3D::Add(Vector3D& vector)
+{
+   return Vector3D( m_afTuple[0]+vector.m_afTuple[0],
+                    m_afTuple[1]+vector.m_afTuple[1],
+                    m_afTuple[2]+vector.m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D Vector3D::operator- (const Vector3D& rkV) const
+{
+   return Vector3D( m_afTuple[0]-rkV.m_afTuple[0],
+                    m_afTuple[1]-rkV.m_afTuple[1],
+                    m_afTuple[2]-rkV.m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D Vector3D::Subtract(Vector3D& vector)
+{
+   return Vector3D( m_afTuple[0]-vector.m_afTuple[0],
+                    m_afTuple[1]-vector.m_afTuple[1],
+                    m_afTuple[2]-vector.m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D Vector3D::operator*(const double& fScalar) const
+{
+   return Vector3D( fScalar*m_afTuple[0],
+                    fScalar*m_afTuple[1],
+                    fScalar*m_afTuple[2]  );
+}
+/*=======================================================*/
+Vector3D Vector3D::operator/(const double& fScalar) const
+{
+   Vector3D kQuot;
+
+   if ( fScalar != 0.0 )
+   {
+      double fInvScalar = 1.0/fScalar;
+      kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0];
+      kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1];
+      kQuot.m_afTuple[2] = fInvScalar*m_afTuple[2];
+   }
+   else
+   {
+      kQuot.m_afTuple[0] = Ub::inf;
+      kQuot.m_afTuple[1] = Ub::inf;
+      kQuot.m_afTuple[2] = Ub::inf;
+   }
+
+   return kQuot;
+}
+/*=======================================================*/
+Vector3D Vector3D::operator-() const
+{
+   return Vector3D( -m_afTuple[0],
+                    -m_afTuple[1],
+                    -m_afTuple[2] );
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator+=(const Vector3D& rkV)
+{
+   m_afTuple[0] += rkV.m_afTuple[0];
+   m_afTuple[1] += rkV.m_afTuple[1];
+   m_afTuple[2] += rkV.m_afTuple[2];
+   return *this;
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator-=(const Vector3D& rkV)
+{
+   m_afTuple[0] -= rkV.m_afTuple[0];
+   m_afTuple[1] -= rkV.m_afTuple[1];
+   m_afTuple[2] -= rkV.m_afTuple[2];
+   return *this;
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator*=(const double& fScalar)
+{
+   m_afTuple[0] *= fScalar;
+   m_afTuple[1] *= fScalar;
+   m_afTuple[2] *= fScalar;
+   return *this;
+}
+/*=======================================================*/
+Vector3D& Vector3D::operator/=(const double& fScalar)
+{
+   if ( !zero(fScalar) )
+   {
+      double fInvScalar = 1.0/fScalar;
+      m_afTuple[0] *= fInvScalar;
+      m_afTuple[1] *= fInvScalar;
+      m_afTuple[2] *= fInvScalar;
+   }
+   else
+   {
+      m_afTuple[0] = Ub::inf;
+      m_afTuple[1] = Ub::inf;
+      m_afTuple[2] = Ub::inf;
+   }
+
+   return *this;
+}
+/*=======================================================*/
+Vector3D Vector3D::Scale(const double& x)
+{
+   Vector3D PointA(0.0,0.0,0.0);
+   PointA.m_afTuple[0] = x * m_afTuple[0];
+   PointA.m_afTuple[1] = x * m_afTuple[1];
+   PointA.m_afTuple[2] = x * m_afTuple[2];
+   return PointA;	
+}
+/*=======================================================*/
+double Vector3D::Length() const
+{
+   return std::sqrt( m_afTuple[0]*m_afTuple[0] +
+                     m_afTuple[1]*m_afTuple[1] +
+                     m_afTuple[2]*m_afTuple[2] );
+}
+/*=======================================================*/
+double Vector3D::SquaredLength() const
+{
+   return m_afTuple[0]*m_afTuple[0] +
+          m_afTuple[1]*m_afTuple[1] +
+          m_afTuple[2]*m_afTuple[2];
+}
+/*=======================================================*/
+double Vector3D::Dot(const Vector3D& rkV) const
+{
+   return m_afTuple[0]*rkV.m_afTuple[0] +
+          m_afTuple[1]*rkV.m_afTuple[1] +
+          m_afTuple[2]*rkV.m_afTuple[2];
+}
+/*=======================================================*/
+double Vector3D::Normalize()
+{
+   double fLength = Length();
+
+   if( !zero(fLength) )
+   {
+      double fInvLength = 1.0/fLength;
+      m_afTuple[0] *= fInvLength;
+      m_afTuple[1] *= fInvLength;
+      m_afTuple[2] *= fInvLength;
+   }
+   else
+   {
+      fLength = 0.0;
+      m_afTuple[0] = 0.0;
+      m_afTuple[1] = 0.0;
+      m_afTuple[2] = 0.0;
+   }
+
+   return fLength;
+}
+/*=======================================================*/
+Vector3D Vector3D::Cross(const Vector3D& rkV) const
+{
+   return Vector3D( m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
+                    m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
+                    m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0] );
+}
+/*=======================================================*/
+Vector3D Vector3D::UnitCross(const Vector3D& rkV) const
+{
+   Vector3D kCross( m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
+                    m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
+                    m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0] );
+   kCross.Normalize();
+   return kCross;
+}
+/*=======================================================*/
+void Vector3D::GetBarycentrics(const Vector3D& rkV0,const Vector3D& rkV1, const Vector3D& rkV2,const Vector3D& rkV3, double afBary[4]) const
+{
+   // compute the vectors relative to V3 of the tetrahedron
+   Vector3D akDiff[4] = { rkV0  - rkV3,
+                          rkV1  - rkV3,
+                          rkV2  - rkV3,
+                          *this - rkV3 };
+
+   // If the vertices have large magnitude, the linear system of
+   // equations for computing barycentric coordinates can be
+   // ill-conditioned.  To avoid this, uniformly scale the tetrahedron
+   // edges to be of order 1.  The scaling of all differences does not
+   // change the barycentric coordinates.
+   double fMax = 0.0,fValue=0.0;
+   for(int i=0; i<3; i++)
+      for (int j=0; j<3; j++)
+      {
+         fValue = std::fabs(akDiff[i][j]);
+         if ( fValue > fMax )  fMax = fValue;
+      }
+   
+   // scale down only large data
+   if( greater(fMax,1.0) )
+   {
+      double fInvMax = ((double)1.0)/fMax;
+      for( int i=0; i<4; i++)
+         akDiff[i] *= fInvMax;
+   }
+
+   double     fDet = akDiff[0].Dot(akDiff[1].Cross(akDiff[2]));
+   Vector3D kE1cE2 = akDiff[1].Cross(akDiff[2]);
+   Vector3D kE2cE0 = akDiff[2].Cross(akDiff[0]);
+   Vector3D kE0cE1 = akDiff[0].Cross(akDiff[1]);
+   
+   if( !zero( fDet ) )
+   {
+      double fInvDet = 1.0/fDet;
+      afBary[0] = akDiff[3].Dot(kE1cE2)*fInvDet;
+      afBary[1] = akDiff[3].Dot(kE2cE0)*fInvDet;
+      afBary[2] = akDiff[3].Dot(kE0cE1)*fInvDet;
+      afBary[3] = 1.0 - afBary[0] - afBary[1] - afBary[2];
+   }
+   else
+   {
+      // The tetrahedron is potentially flat.  Determine the face of
+      // maximum area and compute barycentric coordinates with respect
+      // to that face.
+      Vector3D kE02 = rkV0 - rkV2;
+      Vector3D kE12 = rkV1 - rkV2;
+      Vector3D kE02cE12 = kE02.Cross(kE12);
+      double fMaxSqrArea = kE02cE12.SquaredLength();
+      int iMaxIndex = 3;
+      double fSqrArea = kE0cE1.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 0;
+         fMaxSqrArea = fSqrArea;
+      }
+      fSqrArea = kE1cE2.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 1;
+         fMaxSqrArea = fSqrArea;
+      }
+      fSqrArea = kE2cE0.SquaredLength();
+      if ( fSqrArea > fMaxSqrArea )
+      {
+         iMaxIndex = 2;
+         fMaxSqrArea = fSqrArea;
+      }
+
+      if ( greater(fMaxSqrArea,0.0)  )
+      {
+         double fInvSqrArea = 1.0/fMaxSqrArea;
+         Vector3D kTmp;
+         if( iMaxIndex==0 )
+         {
+            kTmp      = akDiff[3].Cross(akDiff[1]);
+            afBary[0] = kE0cE1.Dot(kTmp)*fInvSqrArea;
+            kTmp      = akDiff[0].Cross(akDiff[3]);
+            afBary[1] = kE0cE1.Dot(kTmp)*fInvSqrArea;
+            afBary[2] = 0.0;
+            afBary[3] = 1.0 - afBary[0] - afBary[1];
+         }
+         else if( iMaxIndex == 1 )
+         {
+            afBary[0] = 0.0;
+            kTmp      = akDiff[3].Cross(akDiff[2]);
+            afBary[1] = kE1cE2.Dot(kTmp)*fInvSqrArea;
+            kTmp      = akDiff[1].Cross(akDiff[3]);
+            afBary[2] = kE1cE2.Dot(kTmp)*fInvSqrArea;
+            afBary[3] = 1.0 - afBary[1] - afBary[2];
+         }
+         else if( iMaxIndex == 2 )
+         {
+            kTmp      = akDiff[2].Cross(akDiff[3]);
+            afBary[0] = kE2cE0.Dot(kTmp)*fInvSqrArea;
+            afBary[1] = 0.0;
+            kTmp      = akDiff[3].Cross(akDiff[0]);
+            afBary[2] = kE2cE0.Dot(kTmp)*fInvSqrArea;
+            afBary[3] = 1.0 - afBary[0] - afBary[2];
+         }
+         else
+         {
+            akDiff[3] = *this - rkV2;
+            kTmp      = akDiff[3].Cross(kE12);
+            afBary[0] = kE02cE12.Dot(kTmp)*fInvSqrArea;
+            kTmp      = kE02.Cross(akDiff[3]);
+            afBary[1] = kE02cE12.Dot(kTmp)*fInvSqrArea;
+            afBary[2] = 1.0 - afBary[0] - afBary[1];
+            afBary[3] = 0.0;
+         }
+      }
+      else
+      {
+         // The tetrahedron is potentially a sliver.  Determine the edge of
+         // maximum length and compute barycentric coordinates with respect
+         // to that edge.
+         double fMaxSqrLength = akDiff[0].SquaredLength();
+         iMaxIndex            = 0;  // <V0,V3>
+         double fSqrLength    = akDiff[1].SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 1;  // <V1,V3>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = akDiff[2].SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 2;  // <V2,V3>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = kE02.SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 3;  // <V0,V2>
+            fMaxSqrLength = fSqrLength;
+         }
+         fSqrLength = kE12.SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 4;  // <V1,V2>
+            fMaxSqrLength = fSqrLength;
+         }
+         
+         Vector3D kE01 = rkV0 - rkV1;
+         fSqrLength    = kE01.SquaredLength();
+         
+         if( fSqrLength > fMaxSqrLength )
+         {
+            iMaxIndex     = 5;  // <V0,V1>
+            fMaxSqrLength = fSqrLength;
+         }
+
+         if( greater(fMaxSqrLength, 0.0) )
+         {
+            double fInvSqrLength = 1.0/fMaxSqrLength;
+            if( iMaxIndex == 0 )
+            {
+               // P-V3 = t*(V0-V3)
+               afBary[0] = akDiff[3].Dot(akDiff[0])*fInvSqrLength;
+               afBary[1] = 0.0;
+               afBary[2] = 0.0;
+               afBary[3] = 1.0 - afBary[0];
+            }
+            else if( iMaxIndex == 1 )
+            {
+               // P-V3 = t*(V1-V3)
+               afBary[0] = 0.0;
+               afBary[1] = akDiff[3].Dot(akDiff[1])*fInvSqrLength;
+               afBary[2] = 0.0;
+               afBary[3] = 1.0 - afBary[1];
+            }
+            else if( iMaxIndex == 2 )
+            {
+               // P-V3 = t*(V2-V3)
+               afBary[0] = 0.0;
+               afBary[1] = 0.0;
+               afBary[2] = akDiff[3].Dot(akDiff[2])*fInvSqrLength;
+               afBary[3] = 1.0 - afBary[2];
+            }
+            else if( iMaxIndex == 3 )
+            {      
+               // P-V2 = t*(V0-V2)
+               akDiff[3] = *this - rkV2;
+               afBary[0] = akDiff[3].Dot(kE02)*fInvSqrLength;
+               afBary[1] = 0.0;
+               afBary[2] = 1.0 - afBary[0];
+               afBary[3] = 0.0;
+            }
+            else if( iMaxIndex == 4 )
+            {
+               // P-V2 = t*(V1-V2)
+               akDiff[3] = *this - rkV2;
+               afBary[0] = 0.0;
+               afBary[1] = akDiff[3].Dot(kE12)*fInvSqrLength;
+               afBary[2] = 1.0 - afBary[1];
+               afBary[3] = 0.0;
+            }
+            else
+            {
+               // P-V1 = t*(V0-V1)
+               akDiff[3] = *this - rkV1;
+               afBary[0] = akDiff[3].Dot(kE01)*fInvSqrLength;
+               afBary[1] = 1.0 - afBary[0];
+               afBary[2] = 0.0;
+               afBary[3] = 0.0;
+            }
+         }
+         else
+         {
+            // tetrahedron is a nearly a point, just return equal weights
+            afBary[0] = 0.25;
+            afBary[1] = afBary[0];
+            afBary[2] = afBary[0];
+            afBary[3] = afBary[0];
+         }
+      }
+   }
+}
+/*=======================================================*/
+void Vector3D::Orthonormalize(Vector3D& rkU, Vector3D& rkV, Vector3D& rkW)
+{
+   // If the input vectors are v0, v1, and v2, then the Gram-Schmidt
+   // orthonormalization produces vectors u0, u1, and u2 as follows,
+   //
+   //   u0 = v0/|v0|
+   //   u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
+   //   u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1|
+   //
+   // where |A| indicates length of vector A and A*B indicates dot
+   // product of vectors A and B.
+
+   // compute u0
+   rkU.Normalize();
+
+   // compute u1
+   double fDot0 = rkU.Dot(rkV); 
+   rkV -= fDot0*rkU;
+   rkV.Normalize();
+
+   // compute u2
+   double fDot1 = rkV.Dot(rkW);
+   fDot0 = rkU.Dot(rkW);
+   rkW  -= fDot0*rkU + fDot1*rkV;
+   rkW.Normalize();
+}
+/*=======================================================*/
+void Vector3D::Orthonormalize(Vector3D* akV)
+{
+   Orthonormalize(akV[0],akV[1],akV[2]);
+}
+/*=======================================================*/
+void Vector3D::GenerateOrthonormalBasis(Vector3D& rkU, Vector3D& rkV,Vector3D& rkW, bool bUnitLengthW)
+{
+   if ( !bUnitLengthW )
+      rkW.Normalize();
+
+   double fInvLength;
+
+   if ( greaterEqual( std::fabs(rkW.m_afTuple[0]),std::fabs(rkW.m_afTuple[1]) ) )
+   {
+      // W.x or W.z is the largest magnitude component, swap them
+      fInvLength = UbMath::invSqrt(rkW.m_afTuple[0]*rkW.m_afTuple[0] + rkW.m_afTuple[2]*rkW.m_afTuple[2]);
+      rkU.m_afTuple[0] = -rkW.m_afTuple[2]*fInvLength;
+      rkU.m_afTuple[1] = (double)0.0;
+      rkU.m_afTuple[2] = +rkW.m_afTuple[0]*fInvLength;
+   }
+   else
+   {
+      // W.y or W.z is the largest magnitude component, swap them
+      fInvLength = UbMath::invSqrt(rkW.m_afTuple[1]*rkW.m_afTuple[1] + rkW.m_afTuple[2]*rkW.m_afTuple[2]);
+      rkU.m_afTuple[0] = (double)0.0;
+      rkU.m_afTuple[1] = +rkW.m_afTuple[2]*fInvLength;
+      rkU.m_afTuple[2] = -rkW.m_afTuple[1]*fInvLength;
+   }
+
+   rkV = rkW.Cross(rkU);
+}
+/*=======================================================*/
+//globaler operator* 
+Vector3D operator*(const double& fScalar, const Vector3D& rkV)
+{
+   return Vector3D( fScalar*rkV[0],
+                    fScalar*rkV[1],
+                    fScalar*rkV[2] );
+}
+/*=======================================================*/
+std::ostream& operator* (std::ostream& os, const Vector3D& rkV)
+{
+   os<<rkV.toString();
+   return os;
+}
+} //end namespace UbMath
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbMath.h b/source/VirtualFluidsCore/Basics/utilities/UbMath.h
new file mode 100644
index 0000000000000000000000000000000000000000..4571514f86d3cc743008dd9b5d4ba1d5f687dd5e
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbMath.h
@@ -0,0 +1,548 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBMATH_H
+#define UBMATH_H
+
+#include <cmath>
+#include <limits>
+#include <iostream>
+#include <cassert>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbEqual.h>
+
+/*=========================================================================*/
+/*  UbMath                                                             */
+/*                                                                         */
+/**
+namespace for global math-functions
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.4 - 04.10.07
+*/ 
+
+/*
+usage: ...
+*/
+
+namespace UbMath 
+{
+   extern const double PI;
+   
+   
+   //////////////////////////////////////////////////////////////////////////
+   //Hilfsfunktion fuer Genauigkeit
+   template< typename T >
+   struct Epsilon {  };
+
+   //////////////////////////////////////////////////////////////////////////
+   //  SPECIALIZATIONS von Epsilon
+   //////////////////////////////////////////////////////////////////////////
+   template<>
+   struct Epsilon<double>        { static inline double      val() { return 1.0E-11; } };
+   template<>
+   struct Epsilon<float>         { static inline float       val() { return 1.0E-7f; } };
+   template<>
+   struct Epsilon<long double>   { static inline long double val() { return 1.0E-15; } };
+   template<>
+   struct Epsilon<int>           { static inline int         val() { return 0;       } };
+
+   /*=======================================================*/
+   // -------------------------------------------------------------------------------------------------
+   // Funktion berechnet den Logarithmus einer Zahl z bzgl. der Basis b
+   // -------------------------------------------------------------------------------------------------
+   template<typename T>
+   inline T log(const T& z, const T& base)
+   {
+      if( ::log(base)==0 ) return 1.0f;
+      return ::log(z) / ::log(base);
+   }
+   /*=======================================================*/
+   //double x = UbMath::getNegativeInfinity<double>();
+   template<typename T>
+   inline T getNegativeInfinity()
+   {
+      //assert(std::numeric_limits<T>::has_infinity);
+      UB_STATIC_ASSERT(std::numeric_limits<T>::has_infinity);
+      return -std::numeric_limits<T>::infinity();
+   }
+   /*=======================================================*/
+   //double x = UbMath::getPositiveInfinity<double>();
+   template<typename T>
+   inline T getPositiveInfinity()
+   {
+      //assert(std::numeric_limits<T>::has_infinity);
+      UB_STATIC_ASSERT(std::numeric_limits<T>::has_infinity);
+      return std::numeric_limits<T>::infinity();
+   }
+   /*=======================================================*/
+   //double x; bool b = UbMath::isInfinity(x);
+   template<typename T>
+   inline bool isInfinity(const T& value)
+   {
+      if(value==getNegativeInfinity<T>()) return true;
+      if(value==getPositiveInfinity<T>()) return true;
+      return false;
+   }
+   /*=======================================================*/
+   //double x = UbMath::getNaN<double>(x);
+   template<typename T>
+   inline T getNaN()
+   {
+      UB_STATIC_ASSERT(std::numeric_limits<T>::has_quiet_NaN);
+      return std::numeric_limits<T>::quiet_NaN();
+   }
+   /*=======================================================*/
+   //double x; bool b = UbMath::isNaN(x);
+   // x!=x liefert bei #QNAN "true"!
+   template<typename T>
+   inline bool isNaN(const T& x)
+   {
+      UB_STATIC_ASSERT(std::numeric_limits<T>::has_quiet_NaN);
+      return (x != x); 
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T getEqualityEpsilon()		  
+   { 
+      return  Epsilon<T>::val();  
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool zero(const T& value)		  
+   { 
+      return std::fabs( value ) < Epsilon<T>::val();
+      //return value >= -UbMath::EPSILON && value <= UbMath::EPSILON;	
+   }
+   /*=======================================================*/
+   //spezialisierung fuer ints
+   template<>
+   inline bool zero(const int& value)		  
+   { 
+      return value == 0;
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool zero(const T1& value1, const T2& value2)		  
+   { 
+      return !(!UbMath::zero(value1) || !UbMath::zero(value2));	
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline bool zero(const T1& value1, const T2& value2, const T3& value3)		  
+   { 
+      return !(!UbMath::zero(value1) || !UbMath::zero(value2,value3));	
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool negative(const T& value)    
+   { 
+      return value < -Epsilon<T>::val();  
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool nonPositive(const T& value) 
+   { 
+      return value <= Epsilon<T>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool positive(const T& value)    
+   { 
+      return value > +Epsilon<T>::val();   
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline bool nonNegative(const T& value) 
+   { 
+      return value >= -Epsilon<T>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool equal(const T1& value, const T2& reference) 
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return std::fabs(value-reference) < Epsilon<High>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline bool equal(const T1& val1, const T2& val2, const T3& val3) 
+   { 
+      return ( UbMath::equal(val1,val2) && UbMath::equal(val1,val3) ); 
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool less(const T1& value, const T2& reference)   
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return value < reference - Epsilon<High>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool lessEqual(const T1& value, const T2& reference) 
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return value <= reference + Epsilon<High>::val();
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool greater(const T1& value, const T2& reference)      
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return value > reference + Epsilon<High>::val();  
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2>
+   inline bool greaterEqual(const T1& value, const T2& reference) 
+   { 
+      typedef typename UbEqualTrait<T1,T2>::High High;
+      return value >= reference - Epsilon<High>::val(); 
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T round(const T& value, const int& decimalPlaces) 
+   { 
+      return static_cast<T>(floor(value * pow( 10.0, decimalPlaces) + 0.5 ) * pow(10.0, -decimalPlaces)); 
+   } 
+   /*=======================================================*/
+   template<typename T>
+   inline int integerRounding(const T& value) 
+   { 
+      return static_cast<int>( UbMath::zero(value) ?  0 : ( (value<0.0) ? (value-0.5) : (value+0.5) ) );
+   } 
+   /*=======================================================*/
+   template<typename T>
+   inline T getRad(const T& degrees) 
+   {
+      return degrees*static_cast<T>(UbMath::PI/180.0);
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T getDegrees(const T& rad) 
+   {
+      return rad*static_cast<T>(UbMath::PI/180.0);
+   }
+   /*=======================================================*/
+   //aus wildmagic
+   template<typename T>
+   inline T ACos (const T& fValue)
+   {
+      if ( -1.0 < fValue )
+      {
+         if ( fValue < 1.0 ) return static_cast<T>( acos(fValue) );
+         else                return static_cast<T>( 0.0          );
+      }
+      else return static_cast<T>( PI );
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T ASin(const T& fValue)
+   {
+      double HALF_PI = 0.5*UbMath::PI;
+      if ( -1.0 < fValue )
+      {
+         if ( fValue < 1.0 ) return static_cast<T>( asin(fValue) );
+         else                return static_cast<T>( HALF_PI      );
+      }
+      else return -static_cast<T>( HALF_PI );         
+   }
+   /*=======================================================*/
+   template<typename T>
+   inline T invSqrt(const T& fValue)   
+   { 
+      return static_cast<T>(1.0/sqrt(fValue));
+   }
+
+   /*=======================================================*/
+   /**
+   * Returns true, if specified values a and b are less both values c and d.
+   * @param a the first value to check
+   * @param b the second value to check
+   * @param c the first value to check against
+   * @param d the second value to check against
+   * @return true, if specified values a and b are less both values c and d
+   **/
+   template<typename T1, typename T2, typename T3, typename T4>
+   inline bool less2(const T1& value1, const T2& value2, T3 toBeLessAs1, T4 toBeLessAs2) 
+   {	
+      return (   less(value1,toBeLessAs1)
+              && less(value1,toBeLessAs2)
+              && less(value2,toBeLessAs1)
+              && less(value2,toBeLessAs2) );
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3, typename T4>
+   inline bool greater2(const T1& value1, const T2& value2, T3 toBeGreaterAs1, T4 toBeGreaterAs2)
+   { 
+      return (   greater(value1,toBeGreaterAs1)
+              && greater(value1,toBeGreaterAs2)
+              && greater(value2,toBeGreaterAs1)
+              && greater(value2,toBeGreaterAs2) );
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline bool inClosedInterval(const T1& value, const T2& threshold1, const T3& threshold2)
+   { 
+      if(threshold1 < threshold2)
+      {
+         return ( greaterEqual( value, threshold1) && lessEqual( value, threshold2) );
+      }
+
+      return ( greaterEqual( value, threshold2) && lessEqual( value, threshold1) );
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline bool inOpenInterval(const T1& value, const T2& threshold1, const T3& threshold2)
+   {	
+      if(threshold1 < threshold2) 
+      {
+         return (greater( value, threshold1) && less( value, threshold2));
+      }
+
+      return (greater( value, threshold2) && less( value, threshold1));
+   }
+   /*=======================================================*/
+   template<typename T1, typename T2, typename T3>
+   inline double adaptToClosedInterval(const T1& value, const T2& threshold1, const T3& threshold2)
+   { 
+      if(threshold1 < threshold2)
+      {
+         if     ( less(   value, threshold1) ) return threshold1;
+         else if( greater(value, threshold2) ) return threshold2;
+      }
+      else
+      {
+         if     ( less(   value, threshold2) ) return threshold2;
+         else if( greater(value, threshold1) ) return threshold1;
+      }
+      return value;
+   }
+   /*=======================================================*/
+   // -------------------------------------------------------------------------------------------------
+   // Funktion berechnet den groessten gemeinsamen Teiler zweier Zahlen (MK)
+   // -------------------------------------------------------------------------------------------------
+   /*=======================================================*/
+   inline int calcGgt(int val1, int val2)
+   {
+      if( val1 < val2 ) std::swap(val1,val2);
+      int ggt=val2;
+      while(ggt > 1)
+      {
+         if( (val1%ggt)==0 && (val2%ggt)==0 ) break;
+
+         ggt -=1;
+      }
+      return ggt;
+   }
+   /*=======================================================*/
+   // -------------------------------------------------------------------------------------------------
+   // Funktion berechnet den groessten gemeinsamen Teiler von drei Zahlen (MK)
+   // -------------------------------------------------------------------------------------------------
+   inline int calcGgt(int val1, const int& val2, int val3)
+   {
+      return UbMath::calcGgt( UbMath::calcGgt(val1, val2), val3 );
+   }
+   /*=======================================================*/
+   //returns the max of two values
+   //to avoid errors at mixed argument-types use: double myMax = max<double>(2,2.3);
+   template< typename T >
+   inline const T& max(const T& a1, const T& a2) 
+   { 
+     return (a1<a2) ? a2 : a1;
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& max(const T& a1, const T& a2, const T& a3) 
+   { 
+      return max(max(a1,a2),a3);
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& max(const T& a1, const T& a2, const T& a3, const T& a4)
+   {
+      return max(max(max(a1,a2),a3),a4);
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& min(const T& a1,const T& a2) 
+   { 
+      return (a1<a2) ? a1 : a2;
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& min(const T& a1, const T& a2, const T& a3) 
+   { 
+      return min(min(a1,a2),a3);
+   }
+   /*=======================================================*/
+   template< typename T >
+   inline const T& min(const T& a1, const T& a2, const T& a3, const T& a4)
+   {
+      return min(min(min(a1,a2),a3),a4);
+      
+//       double tmp = a1;
+//       if(tmp>a2) tmp=a2;
+//       if(tmp>a3) tmp=a3;
+//       if(tmp>a4) tmp=a4;
+//       return tmp;
+   }
+   /*=======================================================*/
+
+   class Vector3D
+   {
+   public:
+      // construction
+      Vector3D(); 
+      Vector3D(const double& fX1, const double& fX2, const double& fX3);
+      Vector3D(const Vector3D& rkV);
+
+      std::string toString() const;
+
+      // coordinate access
+      operator const double*() const;
+      operator double*();
+      double   operator[](const int& i) const;
+      double&  operator[](const int& i);
+      double   X1() const;
+      double&  X1();
+      double   X2() const;
+      double&  X2();                                    
+      double   X3() const;
+      double&  X3();
+
+      // assignment
+      Vector3D& operator=(const Vector3D& rkV);
+
+      // comparison
+      bool operator==(const Vector3D& rkV) const;
+      bool operator!=(const Vector3D& rkV) const;
+      bool operator< (const Vector3D& rkV) const;
+      bool operator<=(const Vector3D& rkV) const;
+      bool operator> (const Vector3D& rkV) const;
+      bool operator>=(const Vector3D& rkV) const;
+
+      // arithmetic operations
+      Vector3D operator+(const Vector3D& rkV) const;
+      Vector3D operator-(const Vector3D& rkV) const;
+      Vector3D operator*(const double& fScalar) const;
+      Vector3D operator/(const double& fScalar) const;
+      Vector3D operator-() const;
+
+      // arithmetic updates
+      Vector3D& operator+= (const Vector3D& rkV);
+      Vector3D& operator-= (const Vector3D& rkV);
+      Vector3D& operator*= (const double& fScalar);
+      Vector3D& operator/= (const double& fScalar);
+
+      Vector3D Add(Vector3D& vector);
+      Vector3D Subtract(Vector3D& vector);
+      Vector3D Scale(const double& x);
+
+      // vector operations
+      double Length () const;
+      double SquaredLength () const;
+      double Dot (const Vector3D& rkV) const;
+      double Normalize ();
+
+      // The cross products are computed using the right-handed rule.  Be aware
+      // that some graphics APIs use a left-handed rule.  If you have to compute
+      // a cross product with these functions and send the result to the API
+      // that expects left-handed, you will need to change sign on the vector
+      // (replace each component value c by -c).
+      Vector3D Cross (const Vector3D& rkV) const;
+      Vector3D UnitCross (const Vector3D& rkV) const;
+
+      // Compute the barycentric coordinates of the point with respect to the
+      // tetrahedron <V0,V1,V2,V3>, P = b0*V0 + b1*V1 + b2*V2 + b3*V3, where
+      // b0 + b1 + b2 + b3 = 1.
+      void GetBarycentrics (const Vector3D& rkV0, const Vector3D& rkV1, const Vector3D& rkV2, const Vector3D& rkV3, double afBary[4]) const;
+
+      // Gram-Schmidt orthonormalization.  Take linearly independent vectors
+      // U, V, and W and compute an orthonormal set (unit length, mutually
+      // perpendicular).
+      static void Orthonormalize (Vector3D& rkU, Vector3D& rkV, Vector3D& rkW);
+      static void Orthonormalize (Vector3D* akV);
+
+      // Input W must be initialized to a nonzero vector, output is {U,V,W},
+      // an orthonormal basis.  A hint is provided about whether or not W
+      // is already unit length.
+      static void GenerateOrthonormalBasis (Vector3D& rkU, Vector3D& rkV, Vector3D& rkW, bool bUnitLengthW);
+
+      // special vectors
+      static const Vector3D ZERO;
+      static const Vector3D UNIT_X1;
+      static const Vector3D UNIT_X2;
+      static const Vector3D UNIT_X3;
+
+   #ifdef CAB_RCF
+         template<class Archive>
+         void serialize(Archive & ar, const unsigned int version)
+         {
+            ar & m_afTuple;
+         }
+   #endif //CAB_RCF
+
+   protected:
+      // support for comparisons
+      int CompareArrays (const Vector3D& rkV) const;
+
+      double m_afTuple[3];
+   };
+   
+   //globaler multiplaktor mit skalar
+   Vector3D operator*(const double& fScalar, const Vector3D& rkV);
+   std::ostream& operator<<(std::ostream& os, const Vector3D& rkV);
+
+   //////////////////////////////////////////////////////////////////////////
+   //
+   //constants
+   //
+   //////////////////////////////////////////////////////////////////////////
+   static const double c8o27=8./27.;
+   static const double c2o27=2./27.;
+   static const double c1o54=1./54.;
+   static const double c1o216=1./216.;
+   static const double c9o2=9./2.;
+   static const double c3o9=3./9.;
+   static const double c3o54=3./54.;
+   static const double c3o216=3./216.;
+
+   static const double c1o27=1./27.;
+
+   static const double c1o72  = 1./72.;          //0.01388888
+   static const double c1o36  = 1./36.;          //0.02777777
+   static const double c1o48  = 1./48.;          //0.02083333
+   static const double c1o32  = 1./32.;          //0.03125
+   static const double c1o24  = 1./24.;          //0.04166666
+   static const double c1o20  = 1./20.;          //0.05
+   static const double c1o18  = 1./18.;          //0.05555555
+   static const double c1o16  = 1./16.;          //0.0625
+   static const double c1o12  = 1./12.;          //0.08333333
+   static const double c1o9   = 1./9.;           //0.11111111
+   static const double c1o8   = 1./8.;           //0.125
+   static const double c1o6   = 1./6.;           //0.16666666
+   static const double c1o5   = 1./5.;           //0.2
+   static const double c1o4   = 1./4.;           //0.25
+   static const double c5o16  = 5./16.;          //0.3125
+   static const double c1o3   = 1./3.;           //0.33333333
+   static const double c3o8   = 3./8.;           //0.375
+   static const double c4o9   = 4./9.;           //0.44444444
+   static const double c1o2   = 1./2.;           //0.5
+   static const double c9o16  = 9./16.;          //0.5625
+   static const double c2o3   = 2./3.;           //0.66666666
+   static const double c3o4   = 3./4.;           //0.75
+   static const double c3o2   = 3./2.;           //1.5
+   static const double c4o3   = 4./3.;           //1.33333333
+   static const double c5o3   = 5./3.;           //1.66666666
+   static const double c9o5   = 9./5.;           //1.8
+   static const double c2o9   = 2./9.;           //0.22222222
+   static const double one_over_sqrt2 =  1.0/sqrt(2.0); //0.707106781
+   static const double one_over_sqrt3 =  1.0/sqrt(3.0); //0.577350269
+   static const double sqrt2  = sqrt(2.0); //1.4142135
+   static const double sqrt3  = sqrt(3.0); //1.7320508
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbNupsTimer.h b/source/VirtualFluidsCore/Basics/utilities/UbNupsTimer.h
new file mode 100644
index 0000000000000000000000000000000000000000..8320aa7de8c5e465edaa032a1816f016e6133bc7
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbNupsTimer.h
@@ -0,0 +1,93 @@
+#ifndef UBNUPSTIMER_H
+#define UBNUPSTIMER_H
+
+#include <basics/utilities/UbTiming.h>
+#include <sstream>
+#include <vector>
+
+
+/*=========================================================================*/
+/*  UbNupsTimer                                                             */
+/*                                                                         */
+/**
+This Class provides the base for ...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 01.11.04
+*/ 
+class UbNupsTimer : public UbTiming
+{
+public:
+   UbNupsTimer() : UbTiming()
+   {
+      mTempNodes = 0.0;
+      mNofNodes.resize(0);
+      mDurations.resize(0);
+   }
+   /*==========================================================*/
+   UbNupsTimer(std::string name) : UbTiming(name)
+   {
+      mNofNodes.resize(0);
+      mDurations.resize(0);
+      mTempNodes = 0.0;
+   }
+   /*==========================================================*/
+   void initTiming()
+   {
+      UbTiming::initTiming();
+      mNofNodes.resize(0);
+      mDurations.resize(0);
+      mTempNodes   = 0.0;
+   }
+   /*==========================================================*/
+   void startTiming(double nofNodes)
+   {
+      mTempNodes=nofNodes;
+      UbTiming::startTiming();
+   }
+   /*==========================================================*/
+   void endTiming()
+   {
+      UbTiming::endTiming();
+      //save #node and time informations
+      mNofNodes.push_back(mTempNodes);
+      mDurations.push_back(UbTiming::getDuration());
+      //reset internal timecounter
+      UbTiming::initTiming();
+   }
+   /*==========================================================*/
+   double getAverageNups()
+   { 
+      double averageNups = 0.0;
+      for(int i=0;i<(int)mNofNodes.size();i++)
+         averageNups+=mNofNodes.at(i)/mDurations.at(i);
+      
+      return averageNups/(double)mNofNodes.size(); 
+   }
+   /*==========================================================*/
+   double getSumOfDuration()
+   {
+      double duration = 0.0;
+      for(int i=0;i<(int)mDurations.size();i++) duration+=mDurations.at(i);
+      return duration;
+   }
+   /*==========================================================*/
+   std::string getNupsString()
+   {
+      std::stringstream ss;
+      ss<<"saved nups informations"<<std::endl;
+      for(int i=0;i<(int)mNofNodes.size();i++)
+         ss<<mNofNodes.at(i)<<"nodes/"<<mDurations.at(i)<<"sec="<<mNofNodes.at(i)/mDurations.at(i)<<"nups\n";
+      return ss.str();
+   }
+
+protected:
+
+private:
+   std::vector<double> mNofNodes;
+   std::vector<double> mDurations;
+   
+   double mTempNodes;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbObservable.h b/source/VirtualFluidsCore/Basics/utilities/UbObservable.h
new file mode 100644
index 0000000000000000000000000000000000000000..a1ab9cafbe4443680dc728d1f8907a1ba34c1462
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbObservable.h
@@ -0,0 +1,259 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBOBSERVABLE_H
+#define UBOBSERVABLE_H
+
+#include <list>               
+#include <iostream>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <basics/utilities/UbObserver.h>
+
+class UbObserver;
+
+/*=========================================================================*/
+/*  Beobachtbares Objekt                                                   */
+/*                                                                         */
+/**
+  This class provides Observables. The Observeres which observe this
+  Observable are stored in an observerlist.
+  IMPORTANT: objectWillBeDeleted is called at UbObserver::~UbObserver
+             this destructor is called AFTER the destructor of the
+             child classes. if you down_cast the pointer sent with the
+             objectWillBeDeleted(UbObserver* objpointer) then have to go this:
+               
+               if(dynamic_cast<UbObserver*>(observedObj)==objpointer) 
+                     (e.g.) observedObj=NULL;
+   example: see end of file
+
+   a copy of an UbservableObject will NOT copy the observerList
+  <UL>
+    <LI><B>Extending:</B> This UbObservable is the observable object itself. Extending should be used
+	where object types can be extended from UbObservable.
+    <LI><B>Associating:</B> Initialization is done via the constructor <tt>UbObservable(ObservableObject)</tt>.
+	Associating may be used, where object types to be observed could not be extended from UbObservable.
+  </UL>
+  <BR><BR><HR>        
+  @author <A HREF="mailto:geller@cab.bau.tu-bs.de">S. Geller</A>
+  @author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+  @version 1.2 - 13.07.05
+  @see UbObserver
+*/
+
+class UbObservable 
+{
+protected:
+   /*======================================================================*/
+   /*  Konstruktoren                                                       */
+   /*                                                                      */
+   /**
+     Creates a UbObservable itself to be the object to be observed.
+     Usually this constructor is used in extended classes.
+   */
+   UbObservable()
+   {
+   }
+   
+   UbObservable(const UbObservable& src)
+   {
+      //no copy of observers !!!
+   }
+   
+   //falls irgendein schlaumeier den =operator von UbObservable aufrufen sollte,
+   //dann macht diesr auch keine kopie! (Allg: zuweisungsoperatoren werden nie vererbt
+   UbObservable& operator=(const UbObservable& src)
+   {
+      return *this;
+   }
+   
+   //   /**
+   //     Creates a UbObservable for the specified Object to be observed.
+   //     Usually this constructor is used in associating UbObservable.
+   //     @param object Object to be observed
+   //   */
+public:
+   /*======================================================================*/
+   /*  Destruktor                                                          */
+   /*                                                                      */
+   /**
+   */
+   virtual ~UbObservable()
+   {
+      this->notifyObserversObjectWillBeDeleted();
+   } 
+
+   /*======================================================================*/
+   /*  methods                                                            */
+   /*                                                                      */
+   
+   /**
+   Adds an UbObserver to the observerlist.
+   @param observer the observer to add to this observable (note that an observer may observe one observable more than once)
+   */
+   virtual void addObserver(UbObserver* observer)
+   {
+      if(!observer) return;
+      for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();++pos)
+      {
+         if(*pos == observer) return;
+      }
+      this->mObserverList.push_back(observer);
+   }
+   /**
+   Deletes an UbObserver from the observerlist.
+   @param observer the observer to remove from this observable (note that all observers identical are deleted)
+   ( delete means delete Heap... but here we're only removing a pointer)
+   */
+   virtual void removeObserver(UbObserver* observer)
+   {
+      if(!observer) return;
+      this->mObserverList.remove(observer);
+
+   }
+   /**
+   Deletes all Observers from the observerlist.
+   ( delete means delete Heap... but here we're only removing a pointer)
+   */
+   virtual void removeAllObservers()
+   {
+      this->mObserverList.clear();
+   }
+   
+   /**
+     Checks whether the specified UbObserver observes this observable.
+     @param observer the observer to remove from this observable (note that all observers identical are deleted)
+     @return true if the specified observer observes this observable
+   */
+   virtual bool isObservedBy(UbObserver* observer)
+   {
+      if(!observer) return false;
+      for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();++pos)
+      {
+         if(*pos == observer) return true;
+      }
+      return false;
+   }
+   /**
+     Notifies all of its observers that something happened. Does nothing, if the observed object is null.
+     Calls the Method UbObserver.objectChanged(Object) with the object of this observable as parameter.
+     The Method UbObserver.objectChanged(Object) must be defined
+     by each class implementing the interface TiObserver
+   */
+   virtual void notifyObserversObjectChanged()
+   {
+      std::list<UbObserver*>::iterator tmp_pos; //es kann sein, dass der aktuelle observer waehrend
+                                           //objectChanged() removed wird...
+      for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();)
+      {
+        //cout<<"in notifyObserversObjectChanged\n";
+        //cout<<this->mObserverList.size()<<endl;
+
+         tmp_pos = pos++; // erst tmp_pos=pos und dann pos++
+         (*tmp_pos)->objectChanged(this);
+      }
+   }
+
+   std::list<UbObserver*>* getObserverList() { return &mObserverList;}
+
+   virtual std::string toString() { return "UbObservable - toString()"; }
+
+#ifdef CAB_RCF
+   template<typename Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      //do nothing!
+   }
+#endif //CAB_RCF
+
+private:
+   /**
+     Notifies all of its observers that something happened. Does nothing, if the observed object is null.
+     Calls the Method UbObserver.objectChanged(Object) with the object of this observable as parameter.
+     The Method UbObserver.objectChanged(Object) must be defined
+     by each class implementing the interface TiObserver
+   */
+   virtual void notifyObserversObjectWillBeDeleted()
+   {
+      std::list<UbObserver*>::iterator tmp_pos; //es kann sein, dass der aktuelle observer waehrend
+                                          //objectWillBeDeleted() removed wird...
+      for(std::list<UbObserver*>::iterator pos=mObserverList.begin();pos!=mObserverList.end();)
+      {
+         //cout<<"in notifyObserversObjectWillBeDeleted\n";
+         //cout<<this->mObserverList.size()<<endl;
+
+         tmp_pos = pos++;
+         (*tmp_pos)->objectWillBeDeleted(this);
+      }
+   }
+
+   std::list<UbObserver*> mObserverList;
+};
+/*=========================================================================*/
+
+
+#ifdef RCF_USE_SF_SERIALIZATION
+   SF_NO_CTOR(UbObservable);
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
+
+////  E X A M P L E 
+////===================
+//class Point : public UbObservable
+//{
+//public:
+//   Point(){x=y=0;}
+//   ~Point(){}
+//   void setXCorrdinates(int x,int y)
+//   {
+//     this->x = x; this->y = y;
+//     this->notifyObserverObjectChanged();
+//   }
+//private:
+//   int x,y;
+//};
+//class VisPoint : public UbObserver
+//{
+//public:
+//   VisPoint(Point* point)
+//   { 
+//      this->point = point;
+//      this->point->addObserver(this);
+//   }
+//   ~VisPoint()
+//   {
+//      if(this->point) point->removeObserver(this);
+//   }
+//   void update() { /* do some actualisation stuff */ }
+//   void objectChanged(UbObservable* changedObject)
+//   {
+//      Point* point = dynamic_cast<Point*>(changedObject);
+//      if( !this->point || this->point != point ) return;
+//      this->repaint();
+//   }
+//   void objectWillBeDeleted(UbObservable* objectForDeletion)
+//   {
+//      if(!this->point) return;
+//      UbObservable* obsobjet = dynamic_cast<UbObservable*>(this->point);
+//      if(obsobjet == objectForDeletion) this->point = NULL;
+//      ///////////////////////////////////////////////////////////////////
+//      //*********************************************************************//
+//      //INGEGEN erster annahmen nicht verwenden, da es nicht immer funktioniert
+//      //z.B. bei mehrfachvererbung haut es nicht hin!
+//      ////      Point* point = reinterpret_cast<point*>(objectForDeletion);
+//      ////if(!this->point || objectForDeletion != this->point) return;
+//      ////this->point = NULL;
+//      //*********************************************************************//
+//      //was hingegen immer moeglich sein sollte:
+//      //if(dynamic_cast<void*>(objectForDeletion)==dynamic_cast<void*>(this->point))
+//   }
+//private:
+//   Point* point;
+//};
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbObserver.h b/source/VirtualFluidsCore/Basics/utilities/UbObserver.h
new file mode 100644
index 0000000000000000000000000000000000000000..6008481f65fffca2853ab6409d492ac7f9183050
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbObserver.h
@@ -0,0 +1,55 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBOBSERVER_H
+#define UBOBSERVER_H
+
+class UbObservable;
+/*=========================================================================*/
+/*  Observer                                                               */
+/*                                                                         */
+/**
+This interface must be implemented by classes which want to
+observe other objects.
+IMPORTANT: if you delete an observer, ensure to remove Observer from
+           all his oberved observable objects before!!!
+example: see end of UbObservable.h-file
+<BR><BR><HR>
+@author <A HREF="mailto:geller@cab.bau.tu-bs.de">S. Geller</A>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.1 - 20.11.04
+*/
+
+class UbObserver 
+{
+protected:
+
+   UbObserver(){}
+
+public:
+
+   virtual ~UbObserver(){}
+
+   /*======================================================================*/
+   /*  Methoden                                                            */
+   /*                                                                      */
+   /**
+   This function is called when the observable indicated that an object
+   has changed.
+   @param changedObject Object which has changed
+   */
+   virtual void objectChanged(UbObservable* changedObject)=0;
+   /**
+   This function is called when the observable indicated that an object
+   should be deleted.
+   @param objectForDeletion Object which should be deleted
+   */
+   virtual void objectWillBeDeleted(UbObservable* objectForDeletion)=0;
+};
+
+#endif
+
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbPointerWrapper.h b/source/VirtualFluidsCore/Basics/utilities/UbPointerWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..3fcf0b599c3f87971bbd9f4ee316cb26a9a55275
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbPointerWrapper.h
@@ -0,0 +1,36 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBPOINTERWRAPPER_H
+#define UBPOINTERWRAPPER_H
+
+//kappselt dynamische Objekte zur remote uebetragung
+//bei RCF werden z.B. aufgrund GC alle lokalen Objekte und 
+//"nackte" Pointer die automatisch als shared_ptr initialisert 
+//werde nach Methoden-Aufruf zerstoert
+//hierfuer kann man dann den UbPointerWrapper verwenden
+
+template<typename T>
+class UbPointerWrapper
+{
+public:
+	UbPointerWrapper() : pointer(NULL) {}
+	
+	UbPointerWrapper(T* pointer) : pointer(pointer) {}
+
+   T* get() { return pointer; }
+
+   template<class Archive>
+	void serialize(Archive& ar, const unsigned int version) 
+   {
+		ar & pointer;
+	}
+
+private:
+   T* pointer;
+};
+
+#endif //UBPOINTERWRAPPER_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbRandom.h b/source/VirtualFluidsCore/Basics/utilities/UbRandom.h
new file mode 100644
index 0000000000000000000000000000000000000000..b4429579eeb94f7a0381bc0f0a19d24845bd3e36
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbRandom.h
@@ -0,0 +1,60 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBRANDOM_H 
+#define UBRANDOM_H 
+
+#include <cstdlib> 
+#include <ctime> 
+#include <cassert> 
+#include <cmath> 
+
+/*=========================================================================*/
+/*  UbRandom                                                             */
+/*                                                                         */
+/**
+generates a random number
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 04.10.2007
+*/ 
+/*
+usage: 
+   int main() 
+   { 
+      char* hand[] = {"Schere", "Stein", "Papier"}; 
+      for (unsigned u = 0; u < 20; u++) 
+      { 
+         cout << hand[UbRandom::rand(0, 2, 1)] << endl; 
+      } 
+
+      return 0; 
+   } 
+*/
+
+class UbRandom 
+{ 
+private: 
+   UbRandom() { std::srand(static_cast<int>(std::time(NULL)));  } 
+
+public: 
+   //returns arbitrary int value element of [min ; max]
+   static inline int rand(const int& min, const int& max) 
+   { 
+      static UbRandom dummy; 
+      assert(max - min < RAND_MAX); 
+      return ( min + std::rand() % (max - min + 1) ); 
+   } 
+   //returns arbitrary float value element of "( (max - min) / gran ) * [min ; max]"
+   //with other words: val = min+n*(max-min)/gran, n=0..gran-1
+   static inline double rand(const double& min, const double& max, const double& gran)
+   {
+      static UbRandom dummy; 
+      return (min + std::floor( std::rand() / (1.0 + RAND_MAX) * gran)* (max - min) / gran);
+   }
+}; 
+
+#endif //UBRANDOM_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbScheduler.h b/source/VirtualFluidsCore/Basics/utilities/UbScheduler.h
new file mode 100644
index 0000000000000000000000000000000000000000..493b567c8c7fbbdaeadda18711b1cc1a1ca14bab
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbScheduler.h
@@ -0,0 +1,414 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBSCHEDULER_H
+#define UBSCHEDULER_H
+
+#include <iostream>
+#include <string>
+#include <limits>
+#include <cassert> 
+#include <sstream>
+#include <iomanip>
+#include <algorithm>
+
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbInfinity.h>
+#include <basics/utilities/UbComparators.h>
+#include <basics/utilities/UbFileOutput.h>
+#include <basics/utilities/UbFileInput.h>
+
+#include <boost/serialization/serialization.hpp>
+
+
+/*=========================================================================*/
+/*  UbScheduler                                                            */
+/*                                                                         */
+/**
+namespace for global system-functions
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@author <A HREF="mailto:hegewald@cab.bau.tu-bs.de">J. Hegewald</A>
+@version 1.0 - 06.09.06
+@version 1.1 - 09.09.06
+@version 1.2 - 03.07.08 - nun auch isDue(t) mehrmals fuer dasselbe t moeglich
+                          isDue(t) auch fuer t < lastUsedT
+                          bug entfernt, der bei Schedule (5,0,500) auch 505 als Due zurückgibt!
+*/ 
+
+/*
+usage: ...
+*/
+
+// this class is not thread save
+//
+#include <boost/smart_ptr.hpp>
+class UbScheduler;
+typedef boost::shared_ptr<UbScheduler> UbSchedulerPtr;
+
+class UbScheduler
+{
+public:
+   class UbSchedule
+   {
+      friend class UbScheduler;
+   public:
+      UbSchedule() :  step(Ub::inf), begin(Ub::inf), end(Ub::inf) { }
+      UbSchedule(const double& step, const double& begin=0.0, const double& end=Ub::inf) 
+         : step(step), begin(begin), end(end) 
+      {  
+      }
+      double getStep()  const { return this->step;  }
+      double getBegin() const { return this->begin; }
+      double getEnd()   const { return this->end;   }
+      
+      /*==========================================================*/
+      std::string toString() { std::stringstream text; text<<*this; return text.str(); }
+      /*==========================================================*/
+      friend inline std::ostream& operator << (std::ostream& os, const UbSchedule& schedule) 
+      {
+         os<<"Schedule[start,end,step]=["<<schedule.begin<<", "<<schedule.end<<", "<<schedule.step<<"]";
+         return os;
+      }
+
+      //------------- implements CAB serialization ----- start
+      virtual void write(UbFileOutput* out)
+      {
+         out->writeDouble( begin );
+         out->writeDouble( end );
+         out->writeDouble( step );
+      }
+      virtual void read(UbFileInput* in)
+      {
+         begin = in->readDouble();
+         end   = in->readDouble();
+         step  = in->readDouble();
+      }
+      //------------- implements boost serialization ----- end
+
+   private:
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & begin; 
+         ar & end; 
+         ar & step;
+      }
+   
+
+   private:
+      double step, begin, end;
+   };
+
+public:
+   UbScheduler() 
+   {
+      this->initVals();
+   }
+   /*==========================================================*/                         
+   UbScheduler(const double& step,const double& begin=0, const double& end=Ub::inf ) 
+   {
+      this->initVals();
+      this->addSchedule(step,begin,end);
+   }
+   /*==========================================================*/
+   UbScheduler(const UbSchedule& schedule) 
+   {
+      this->initVals();
+      this->addSchedule(schedule);
+   }
+   /*==========================================================*/
+   virtual ~UbScheduler() {}
+   /*==========================================================*/
+   inline void addSchedule(const UbSchedule& schedule)
+   {
+      this->addSchedule(schedule.step, schedule.begin, schedule.end);
+   }
+   /*==========================================================*/
+   bool addSchedule(const double& step, const double& begin, double end)
+   {
+      if( UbMath::zero(step) || begin>end )
+      { 
+         std::cerr<<"UbScheduler::addSchedule - invalid Schedule:\n\t"<<UbSchedule(step, begin, end)<<std::endl;
+         return false; 
+      }
+      
+      if( UbMath::less( end, (double)Ub::inf )  )
+      {
+         //es kann vorkommen, dass man mit dem intervall nicht genau auf den letzten wert kommt
+         //(z.B. step=2; start=0; end=9; -> ende wird angepasst)
+         //also wenn end-begin>Ub::inf ist, dann geht es halt nicht.. ein cast in long double half hier nichts
+         double multiplier=0.0;
+         double fractpart =  modf( (end-begin)/step, &multiplier);
+         if( !UbMath::zero(fractpart) )
+         {
+            //tmp-speicherung (fuer cerr)
+            fractpart = end;
+            //neues ende
+            end = begin+multiplier*step;
+            
+            std::cerr<<"Warning: UbScheduler::addSchedule - "
+                      <<"end of schedule was adapted to intervall \n\t"
+                      <<"from "<< UbSchedule(step, begin, fractpart) <<" to "<< UbSchedule(step, begin, end) <<std::endl;
+         }
+      }
+
+      //nu aber:
+      schedules.push_back(UbSchedule(step, begin, end));
+
+      if( end>maxT ) maxT = end;
+
+      double potentialDueTime;
+      if(   calcNextDueTimeForSchedule(schedules.back(), lastUsedT, potentialDueTime)
+         && potentialDueTime < nextDueTime   )
+      {
+         nextDueTime = potentialDueTime;
+      }
+
+      return true;
+   }
+   /*==========================================================*/
+   //returns true if scheduler contains schedules
+   bool   hasSchedules() const { return !schedules.empty(); }
+   /*==========================================================*/
+   //time bei dem das letzte mal isDue(time) true war
+   double getLastDueTime() const { return lastDueTime; }
+   /*==========================================================*/
+   //time bei dem das naechste mal isDue(time) true ergibt
+   double getNextDueTime() const { return nextDueTime; }
+   /*==========================================================*/
+   //maxDueTime (maxTime der Schedules!
+   double getMaxDueTime()  const { return this->maxT; }
+   /*==========================================================*/
+   bool isDue(const double& t)
+   {
+      lastUsedT = t;
+      if( UbMath::greaterEqual(t,nextDueTime) ) 
+      {
+         //groesser maxT is nicht
+         if( UbMath::greater(t,maxT) )  return false;
+         
+         //temp var
+         double actDueTime = nextDueTime;
+
+         //um Suche nach nextDueTime bei "Zukunfts-t" zu optimieren, setzt man die "start"-suchzeit auf "t-1":
+         nextDueTime = t-1; //t-1 deshlab, damit falls z.B. while Schleife nicht durchlaufen wird
+                            //die folgende if Abfrage nicht faelschlicher Weise true ist!
+         while( UbMath::greaterEqual(t,nextDueTime) && !UbMath::equal(nextDueTime, maxT) )
+         {
+            double tmpNextDueTime = maxT, potentialDueTime=-1.0;
+            for(std::size_t i=0; i<schedules.size(); i++)
+            {
+               if(   calcNextDueTimeForSchedule(schedules[i], nextDueTime, potentialDueTime)
+                  && potentialDueTime < tmpNextDueTime                 )
+               {
+                  assert( nextDueTime < potentialDueTime );
+                  tmpNextDueTime = potentialDueTime;
+               }
+            }
+            actDueTime  = nextDueTime;
+            nextDueTime = tmpNextDueTime;
+         } 
+
+         //wenn t = der aktuuellen oder gar schon der nächstmöglichen ist (hierbei wurde
+         //zuvor actDueTime und nextDueTime ggf. angepasst)
+         //Bsp.: nextDuTime war 5, aber für t=400 gilt andere schedule -> Bsp actDue=350 und nextDue 405
+         if(    UbMath::equal(t,actDueTime)    
+             || UbMath::equal(t,nextDueTime) ) 
+         {
+            lastDueTime = t;
+            return true;
+         }
+      }
+      else if( UbMath::lessEqual(t, lastDueTime) ) 
+      {
+         if(UbMath::equal(t, lastDueTime) ) return true; //braucht man, wenn man für dasselbe t isDue(t) aufruft
+         else  
+         {
+            //Fall: Zeit liegt faktisch in der Vergangenheit -> neu initialsisieren
+            double tmpNextDueTime = maxT, potentialDueTime=-1.0;
+            for(size_t i=0; i<schedules.size(); i++)
+            {
+               if(   calcNextDueTimeForSchedule(schedules[i], t-1, potentialDueTime)
+                  && potentialDueTime < tmpNextDueTime                 )
+               {
+                  tmpNextDueTime = potentialDueTime;
+               }
+            }
+            nextDueTime = tmpNextDueTime;
+
+            return UbMath::equal(t, nextDueTime);
+         }
+      }
+
+      return false;
+   }
+   /*==========================================================*/
+   inline double getMinBegin( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getBegin) )->getBegin();
+   }
+   /*==========================================================*/
+   inline double getMaxBegin( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getBegin) )->getBegin();
+   }
+   /*==========================================================*/
+   inline double getMinEnd( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getEnd) )->getEnd();
+   }
+   /*==========================================================*/
+   inline double getMaxEnd( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getEnd) )->getEnd();
+   }
+   /*==========================================================*/
+   inline double getMinStep( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::min_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getStep) )->getStep();
+   }
+   /*==========================================================*/
+   inline double getMaxStep( ) const
+   {
+      if( schedules.empty() ) return Ub::inf;
+      return std::max_element(schedules.begin(), schedules.end(),UbComparators::membercomp(&UbSchedule::getStep) )->getStep();
+   }
+   /*==========================================================*/
+   inline std::string toString() const
+   {
+      std::stringstream text;
+      text<<*this;
+      return text.str();
+   }
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const UbScheduler& scheduler) 
+   {
+      os<<"UbScheduler\n";
+      os<<"Schedule |       start       |        end        |     intervall     "<<std::endl;
+      for(std::size_t i=0; i<scheduler.schedules.size(); i++)
+         os<<std::setw(9)<<i<<"|"
+           <<std::setw(19)<<scheduler.schedules[i].getBegin()<<"|"
+           <<std::setw(19)<<scheduler.schedules[i].getEnd()  <<"|"
+           <<std::setw(19)<<scheduler.schedules[i].getStep() <<std::endl;
+      return os;
+   }
+
+   //------------- implements CAB serialization ----- start
+   virtual void write(UbFileOutput* out)
+   {
+      out->writeSize_t( schedules.size() );
+      
+      for(std::size_t i=0; i<schedules.size(); i++)
+         schedules[i].write(out);
+   }
+   virtual void read(UbFileInput* in)
+   {
+      this->initVals();
+
+      std::size_t nofSchedules = in->readSize_t();
+      for(std::size_t i=0; i<nofSchedules; i++)
+      {
+         UbSchedule schedule;
+         schedule.read(in);
+         this->addSchedule(schedule);
+      }
+   }
+   //------------- implements boost serialization ----- end
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & lastUsedT;
+      ar & lastDueTime; 
+      ar & nextDueTime; 
+      ar & maxT; 
+      ar & schedules;
+   }
+
+protected:
+   /*==========================================================*/
+   void initVals()
+   {
+      lastUsedT   = -Ub::inf; 
+      lastDueTime = -Ub::inf;
+      nextDueTime =  Ub::inf;
+      maxT        = -Ub::inf;
+   }
+   /*==========================================================*/
+   // calculates next due time for a schedule 
+   // with  nextDueTime > searchStart
+   bool calcNextDueTimeForSchedule(const UbSchedule& schedule, const double& searchStart, double& nextDueTime )
+   {
+      if     ( UbMath::greater(searchStart, schedule.end  ) ) return false;
+      else if( UbMath::less(   searchStart, schedule.begin) ) nextDueTime = schedule.begin;
+      else                            
+      {
+         nextDueTime = schedule.begin + ((int)((searchStart-schedule.begin)/schedule.step)+1)*schedule.step;
+         if(   UbMath::less(   nextDueTime, searchStart )
+            || UbMath::greater(nextDueTime, schedule.end) ) 
+         {
+            return false;
+         }
+      }
+      return true;
+   }
+
+protected:
+   double lastUsedT;
+   double lastDueTime;
+   double nextDueTime;
+   double maxT;
+   
+   std::vector<UbSchedule> schedules;
+};
+
+typedef UbScheduler::UbSchedule UbSchedule;
+// inline std::ostream& operator<<( std::ostream& os, const UbScheduler& scheduler )
+// {
+//    os<<"UbScheduler\n";
+//    os<<"Schedule |       start       |        end        |     intervall     "<<std::endl;
+//    for(std::size_t i=0; i<scheduler.schedules.size(); i++)
+//       os<<std::setw(9)<<i<<"|"
+//         <<std::setw(19)<<scheduler.schedules[i].getBegin()<<"|"
+//         <<std::setw(19)<<scheduler.schedules[i].getEnd()  <<"|"
+//         <<std::setw(19)<<scheduler.schedules[i].getStep() <<std::endl;
+//    return os;
+// }
+
+#endif //UBSCHEDULER_H
+
+
+
+//int main(int argc, char** argv)            
+//{   
+//	UbScheduler writeSchedule;
+////	writeSchedule.addSchedule(0,2000,100);
+////	writeSchedule.addSchedule(3005,4500,300);
+////	writeSchedule.addSchedule(0,10,1);
+////	writeSchedule.addSchedule(0,100001,100);
+//	writeSchedule.addSchedule(0,2,1);
+//	writeSchedule.addSchedule(0,100001,200);
+//
+//	for(int t = 0; t < 1001; t++)
+//	{
+//		if(writeSchedule.isDue(t))
+//		{
+//			cout<<"due@ "<<t<<endl;
+//		}
+//	}
+//	return 0;
+//}
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbStaticPathMap.cpp b/source/VirtualFluidsCore/Basics/utilities/UbStaticPathMap.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7772fc5d822487033d53af7caeb49b956ba7a201
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbStaticPathMap.cpp
@@ -0,0 +1,4 @@
+#include <basics/utilities/UbStaticPathMap.h>
+
+UbStaticPathMap::PathMap UbStaticPathMap::pathMap;
+const std::string UbStaticPathMap::GLOBAL = "UbStaticPathMap::GLOBAL";
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbStaticPathMap.h b/source/VirtualFluidsCore/Basics/utilities/UbStaticPathMap.h
new file mode 100644
index 0000000000000000000000000000000000000000..20e5b7e8fb294ba8da532aac010d8f85a878fd1c
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbStaticPathMap.h
@@ -0,0 +1,71 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBSTATICPATHMAP_H
+#define UBSTATICPATHMAP_H
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <basics/utilities/UbSystem.h>
+
+/*=========================================================================*/
+/*  UbStaticPathMap                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 12.10.2007
+*/ 
+
+/*
+stores pathnames for pathIDs (e.g. on different processes different paths with same pathID)
+adding an path autom. changes "\" to "/" and removed last "/" if exists
+
+*/
+
+class UbStaticPathMap
+{
+   typedef std::map< std::string, std::string > PathMap;
+public:
+   static const std::string GLOBAL;
+public:
+
+   static std::string addAndMakePath(const std::string& id, const std::string& path)
+   {
+      std::string tmpPath = UbStaticPathMap::addPath(id,path);
+      if( !tmpPath.empty() ) UbSystem::makeDirectory(tmpPath,20);
+      return tmpPath;
+   }
+   static std::string addPath(const std::string& id, const std::string& path)
+   {
+      std::string tmpPath = UbSystem::replaceInString(path,"\\","/");
+      if(tmpPath.rfind("/") == tmpPath.size()-1) tmpPath.resize(tmpPath.size()-1);
+      pathMap[id] = tmpPath;   
+      return tmpPath;
+   }
+   static std::string getPath(const std::string& id)
+   {
+      PathMap::iterator it = pathMap.find(id);
+      if(it == pathMap.end()) return "";
+      return it->second;
+   }
+   static void removePath(const std::string& id)
+   {
+      pathMap.erase(id);
+   }
+
+protected:
+   static PathMap pathMap;
+
+private:
+   UbStaticPathMap() {}
+   UbStaticPathMap(const UbStaticPathMap&) {}
+};
+
+#endif //UBSTATICPATHMAP_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbString.h b/source/VirtualFluidsCore/Basics/utilities/UbString.h
new file mode 100644
index 0000000000000000000000000000000000000000..516ee76ea90d44d33983fa3a1a531f98211e3dd1
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbString.h
@@ -0,0 +1,24 @@
+//unnoetig: UbSystem::toString() verwenden,... andere Richtung: stringTo... oder am besten boost::lexical_cast
+
+
+//#ifndef UBSTRING_H
+//#define UBSTRING_H
+//#include <string>
+//#include <sstream>
+//
+//using namespace std;
+//
+//class UbString
+//{
+//public:
+//   static void IntToString(int i, string& res)
+//   {
+//      ostringstream temp;
+//      temp << i;
+//      res = temp.str();
+//   }
+//protected:
+//private:
+//};
+//
+//#endif //end UBSTRING_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbStringInputASCII.cpp b/source/VirtualFluidsCore/Basics/utilities/UbStringInputASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cf104b9fd8c182621b67975e9693f8cd78d91b84
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbStringInputASCII.cpp
@@ -0,0 +1,211 @@
+#include <basics/utilities/UbStringInputASCII.h>
+#include <cstring>
+
+using namespace std;
+
+
+UbStringInputASCII::UbStringInputASCII(string inputString) : UbFileInputASCII("")
+{
+	instream.str(inputString);
+	
+	
+//	this->filename         = filename;
+//   this->commentindicator = 'C'; 
+//   
+//   infile.open(filename.c_str());
+
+}
+/*==========================================================*/
+int UbStringInputASCII::readInteger()				
+{
+	int dummy;
+	instream>>dummy;
+	return dummy;
+}
+/*==========================================================*/
+std::size_t UbStringInputASCII::readSize_t()				
+{
+   std::size_t dummy;
+   instream>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+string UbStringInputASCII::getFileName()				
+{
+	return this->filename;
+}
+
+/*==========================================================*/
+void UbStringInputASCII::skipLine()				
+{
+	string dummy;
+	getline(instream, dummy);
+}
+/*==========================================================*/
+void UbStringInputASCII::readLine()				
+{
+	string dummy;
+	getline(instream, dummy);
+}
+/*==========================================================*/
+string UbStringInputASCII::readStringLine()				
+{
+   string dummy;
+   getline(instream, dummy);
+   return dummy;
+}
+/*==========================================================*/
+string UbStringInputASCII::readLineTill(char stop)				
+{
+	string dummy;
+	getline(instream, dummy, stop);
+	return dummy;
+}
+/*==========================================================*/
+string UbStringInputASCII::parseString()				
+{
+	string dummy;
+	getline(instream, dummy, ' ');
+	return dummy;
+}
+/*==========================================================*/
+double UbStringInputASCII::readDouble()	
+{
+   double dummy;
+   instream>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+float UbStringInputASCII::readFloat()	
+{
+   float dummy;
+   instream>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+char UbStringInputASCII::readChar()	
+{
+   char dummy;
+   instream>>dummy;
+   return dummy;
+}
+/*==========================================================*/
+string UbStringInputASCII::readString()	
+{
+	string dummy;
+	instream>>dummy;
+	return dummy;
+}
+/*==========================================================*/
+bool UbStringInputASCII::containsString(string var)
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+   char line[512];								
+   do
+   { 
+      instream.getline(line,512);
+      if(instream.eof()) return false;
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+   
+   return true;
+}
+/*==========================================================*/
+void UbStringInputASCII::setPosAfterLineWithString(string var)
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+   char line[512];								
+   do
+   { 
+      instream.getline(line,512);
+      if(instream.eof()) UB_THROW( UbException(UB_EXARGS,var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+}
+/*==========================================================*/
+int UbStringInputASCII::readIntegerAfterString(string var)
+// last change [10.3.2004] at [9:46] 
+//suchts in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. timesteps 9
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];								
+
+   do
+   { 
+      instream.getline(line,512);
+      if(instream.eof()) UB_THROW( UbException(UB_EXARGS,var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+
+   strcpy (line, (line+strlen(var.c_str())));	    // zeile um "varname" kuerzen 
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   return(atoi(line));						// Umwandlung in int 					
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46] 
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+double UbStringInputASCII::readDoubleAfterString(string var)	
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];								
+
+   do
+   { 
+      instream.getline(line,512);
+      if(instream.eof()) UB_THROW( UbException(UB_EXARGS,var+" wasn't found in "+this->filename) );
+   }while (/*!strncmp(varname,line,sizeof(varname))==0*/strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+
+
+   strcpy (line, (line+strlen(var.c_str())));	    // zeile um "varname" kuerzen 
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   return (atof(line));			// Umwandlung in double 					
+}
+/*==========================================================*/
+//  [9.9.2002]
+// liefert sring-Wert der hinter dem uebergebenen char feld in der datei instream steht
+// zudem wird der wert in die uebergebene variable value uebertragen (falls man das ergebniss als char benoetig)
+string UbStringInputASCII::readStringAfterString(string var)	
+{
+   instream.seekg(0L, ios::beg); //Positionszeiger der Datei auf den Anfang setzen
+
+   char line[512];								
+   //string line_copy[512];
+
+   do{ 
+      instream.getline(line,512);
+      if(instream.eof()) UB_THROW( UbException(UB_EXARGS,var+" wasn't found in "+this->filename) );
+   }while (strstr(line,var.c_str()) != line);		// Ende Schleife, wenn varname ganz in zeile vorkommt	
+
+   strcpy (line, (line+strlen(var.c_str())));										// zeile um "varname" kuerzen 
+   while ((line[0] == ' ') || (line[0] == '\t')) strcpy (line, (line+1));	// Whitespaces entfernen
+
+   char *p;
+   p=strtok(line," "); //schneidet alles "ab und inklusive space " nach namen ab
+   p=strtok(line,"\t");//schneidet alles "ab und inklusive tab   " nach namen ab
+
+   return (string)p;			// Umwandlung in string					
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46] 
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+bool UbStringInputASCII::readBoolAfterString(string var)	
+{
+   if(this->readStringAfterString(var.c_str())      == "true" ) return true;
+   else if(this->readStringAfterString(var.c_str()) == "false") return false;
+   else UB_THROW( UbException(UB_EXARGS,var+" is not equal to 'true' or 'false' in "+this->filename) );
+}
+/*==========================================================*/
+// last change [10.3.2004] at [9:46] 
+//sucht in einer Datei nach varname und gibt den dahinter stehenden int-Wert zurueck
+//z.B. nue 9.5
+bool UbStringInputASCII::readBool()	
+{
+   string tmp = this->readString();
+   if(     tmp == "true" ) return true;
+   else if(tmp == "false") return false;
+   else UB_THROW( UbException(UB_EXARGS,"expression is not equal to 'true' or 'false' in "+this->filename) );
+}
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbStringInputASCII.h b/source/VirtualFluidsCore/Basics/utilities/UbStringInputASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..787048e071daf501e988d2baf9ebd861f04bf6cf
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbStringInputASCII.h
@@ -0,0 +1,55 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBSTRINGINPUTASCII_H
+#define UBSTRINGINPUTASCII_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+
+#include <basics/utilities/UbFileInputASCII.h>
+
+class UbStringInputASCII : public UbFileInputASCII
+{                               
+public:
+	UbStringInputASCII(std::string inputString);
+	
+	std::string getFileName();				
+	void	      skipLine();					   // Springt zur naechsten Zeile
+
+   void        readLine();		 
+   std::string readStringLine();				
+   std::size_t readSize_t();				
+   int		   readInteger();				   // Liest einen Int-Wert ein
+   double	   readDouble();				   // Liest einen double-Wert ein
+	float 	   readFloat();				   // Liest einen float-Wert ein
+	bool  	   readBool();				      // Liest einen bool-Wert ein
+   char        readChar();                // Liest einen char-Wert ein
+   std::string	readString();				   // Liest ein Wort ein
+	std::string	readLineTill(char stop);	// Liest gesamte Zeile ein bis zu einem bestimmten Zeichen
+	std::string	parseString();	
+
+   bool        containsString(std::string var);
+   void        setPosAfterLineWithString(std::string var);
+   int		   readIntegerAfterString(std::string var);
+   double	   readDoubleAfterString(std::string var);
+   bool        readBoolAfterString(std::string var);
+   std::string readStringAfterString(std::string var);
+
+   FILETYPE getFileType() { return ASCII; }
+
+private:
+	std::istringstream instream;
+};
+
+
+#endif
+
+
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbSystem.h b/source/VirtualFluidsCore/Basics/utilities/UbSystem.h
new file mode 100644
index 0000000000000000000000000000000000000000..4178ff2c02342837c0638c8fdac4406caab30d7e
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbSystem.h
@@ -0,0 +1,534 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBSYSTEM_H
+#define UBSYSTEM_H
+
+#if defined(_WIN32) || defined(_WIN64)
+   #define UBSYSTEM_WINDOWS
+   #include <process.h>
+   #include <io.h>
+   #include <direct.h>
+   //#ifndef _WINSOCK2API_  //ansonsten gibt es mecker bei #include "Windows.h" und ::Sleep()
+   //   #define _WINSOCK2API_
+   //   #include<WinSock2.h> 
+   //#endif
+  #include <windows.h>
+  //#include <Windows.h>
+  //#include <tchar.h>
+#elif defined(__APPLE__)
+   #define UBSYSTEM_APPLE
+   #include "dirent.h"
+   #include "sys/stat.h"
+   #include <sys/syscall.h>
+   #include <sys/stat.h>
+#elif (defined(__amd64) || defined(__amd64__) || defined(__unix__) || defined(__CYGWIN__)) && !defined(__AIX__) 
+   #define UBSYSTEM_LINUX
+   #include "dirent.h"
+   #include "sys/stat.h"
+   #include <sys/syscall.h>
+   #include <sys/stat.h>
+   #include <unistd.h>
+#elif defined(__AIX__)
+   #define UBSYSTEM_AIX
+   #include "dirent.h"
+   #include <unistd.h>
+   #include <sys/stat.h>
+   #include <sys/types.h>
+#else
+   #error "UbSystem::UnknownMachine"
+#endif
+
+
+
+#if defined(min) || defined(max) //daruch kann man sich spaeter #undef min; #undef max erparen
+#   error add NOMINMAX to preprocessor defines
+#endif
+
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <algorithm>
+#include <typeinfo>
+#include <cctype> //for toupper
+#include <ctime>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbLogger.h>
+
+#if defined(CAB_BOOST)
+#include <boost/thread.hpp>
+#endif // CAB_BOOST
+
+//DEFINE TO STRING
+//e.g. #define FOO hallo
+//     -> QUOTEME(FOO) == "hallo"
+#define _QUOTEME(x) #x
+#define QUOTEME(x) _QUOTEME(x)
+
+//allg.:
+//const int * C1        -> C1 is variable pointer to a constant integer
+//int const * C2        -> C2 is variable pointer to a constant integer (same as above)
+//int * const C3        -> C3 is constant pointer to a variable integer
+//int const * const C4  -> C4 is constant pointer to a constant integer
+
+//////////////////////////////////////////////////////////////////////////
+//UbSystem
+//////////////////////////////////////////////////////////////////////////
+namespace UbSystem
+{
+   template<bool> struct ub_static_assert;     //deklaration (ub_xxx da static_assert in C++0x ein keyword werden wird)
+   template<> struct ub_static_assert<true>{}; //deklaration + definition der spezialisierung fuer "true"
+                                               //ub_static_assert<false> fuehrt zu compiler fehler, da dafuer
+                                               //keine implementierung vorhanden!  //UB_STATIC_ASSERT(false)
+
+   /*==========================================================*/
+   inline void sleepMs(const unsigned int& msec)
+   {
+      #if defined UBSYSTEM_WINDOWS
+         ::Sleep(  (msec==0) ? 1 : msec );  // +1 here causes a context switch if SleepMSec(0) is called
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         ::usleep(1000*msec);
+      #else
+         #error "UbSystem::sleepMSec - UnknownMachine"
+      #endif
+   }
+   /*==========================================================*/
+   inline void sleepS(const unsigned int& sec)
+   {
+      #if defined UBSYSTEM_WINDOWS
+         ::Sleep( (sec==0) ? 1 : sec*1000 );  // +1 here causes a context switch if sleepS(0) is called
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         ::sleep(sec);
+      #else
+         #error "UbSystem::sleepS - UnknownMachine"
+      #endif
+   }
+   /*==========================================================*/
+   //checks if the bits of bitmask are set in value
+   template<typename T>
+   inline bool bitCheck(const T& value, const T& bitmask)
+   {
+      return  ( (value & bitmask) == bitmask);
+   }
+   /*==========================================================*/
+   //checks if the bits of bitmask are set in value
+   template<typename T>
+   inline void setBit(T& value, const T& bitmask)
+   {
+      value |= bitmask;
+   }
+   /*==========================================================*/
+   template<typename T>
+   inline void unsetBit(T& value, const T& bitmask)
+   {
+      value &= ~bitmask;
+   }
+   /*==========================================================*/
+   //returns bitmask as string e.g. 0001 0100 1101
+   template<typename T>
+   inline std::string getBitString(const T& value)
+   {
+      std::stringstream text;
+      for(int i=sizeof(value)*8-1/*8 bits per byte*/; i>=0; i--)
+      {
+         text<<(char) ( ((value>>i) & 1) + '0');
+         if(i%4 == 0 && i>0) text<<' ';
+      }
+      return text.str();
+   }
+   /*==========================================================*/
+   //converts string to type T
+   // usage: int x = stringTo<int>("123");
+   template<typename T>
+   inline T stringTo(const std::string& s)
+   {
+     std::istringstream iss(s);
+     T x;
+     iss >> x;
+     if(!iss)
+        UB_THROW( UbException(UB_EXARGS," cannot convert \""+s+"\" to type <"+static_cast<std::string>(typeid(x).name())+">") );
+
+     return x;
+   }
+   /*==========================================================*/
+   // usage: string s = toString(x);
+   template<typename T>
+   inline std::string toString(const T& x, int precision=15)
+   {
+     std::ostringstream oss;
+     oss<<std::setprecision(precision);
+     oss<<x;
+     return oss.str();
+   }
+   /*==========================================================*/
+   //e.g. str="iHcsnW" -> "IHCSNW"
+   inline std::string toUpperString(const std::string& str)
+   {
+      std::string tmp(str);
+      std::transform(tmp.begin(),tmp.end(),tmp.begin(), static_cast<int (*)(int)>(std::toupper));
+
+      return tmp;
+   }
+   /*==========================================================*/
+   //e.g. str="iHcsnW" -> "ihcsnw"
+   inline std::string toLowerString(const std::string& str)
+   {
+      std::string tmp(str);
+      std::transform(tmp.begin(),tmp.end(),tmp.begin(), static_cast<int (*)(int)>(std::tolower));
+
+      return tmp;
+   }
+   /*==========================================================*/
+   // usage: std::string s = replaceInString(str,"\\","/");
+   //        std::string s = replaceInString(str,"ich","du");
+   static std::string replaceInString(std::string original, const std::string& replace, const std::string& replaceWith )
+   {
+      size_t pos=0;
+      while( (pos=original.find(replace,pos))!=std::string::npos )
+      {
+         original.replace(pos,replace.size(),replaceWith);
+         pos+=replaceWith.size();
+      }
+      return original;
+   }
+   /*==========================================================*/
+   //returns content of an enviroment variable
+   inline std::string getEnv(const std::string& var)
+   {
+      char* str = getenv( var.c_str());
+      if(  str == NULL  ) 
+      {
+         return std::string("");
+      }
+      
+      return static_cast<std::string>( str );
+   }
+   /*==========================================================*/
+   inline bool isDirectory(const std::string& dir, const unsigned& attemptions = 3)
+   {
+      if( dir.empty() ) 
+         UB_THROW( UbException(UB_EXARGS,"dir is empty") );
+      
+      std::string path = UbSystem::replaceInString(dir,"\\","/");
+
+      #if defined UBSYSTEM_WINDOWS
+         #ifndef _UNICODE 
+            if( _access(path.c_str(), 0  ) == -1 ) return false;
+         #else
+            if( _waccess(path.c_str(), 0 ) == -1 ) return false;
+         #endif
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         struct stat stFileInfo;
+         if( stat(path.c_str(),&stFileInfo) != 0) 
+         {
+            return false;
+         } 
+      #endif
+      
+      return true;
+   }
+   /*==========================================================*/
+   // usage:  makeDirectory("c:/temp");
+   //         makeDirectory("c:/temp/");
+   // return: true  -> successful
+   //         false -> failed
+   #if defined(CAB_BOOST) 
+      static boost::mutex mtx_makeDirectory;
+   #endif
+   inline bool makeDirectory(const std::string& dir, const unsigned& attemptions = 3)
+   {
+      UBLOG(logDEBUG5,"UbSystem::makeDirectory - start, dir="<<dir<<" #attemptions="<<attemptions);
+
+      if( dir.empty() ) UB_THROW( UbException(UB_EXARGS,"dir is empty") );
+      std::string path = UbSystem::replaceInString(dir,"\\","/");
+
+      bool dirCreated = true;
+      #if defined UBSYSTEM_WINDOWS
+         if(path[path.size()-1] != '/') path+="/";
+         size_t  pos = 0;
+         while( ( pos=path.find("/",pos+1) ) != std::string::npos )
+         {
+            std::string tmpdir = path.substr(0,pos);
+            #if defined(CAB_BOOST) 
+            boost::mutex::scoped_lock lock(mtx_makeDirectory);
+            #endif
+            if( 
+                #ifndef _UNICODE 
+                 _access(tmpdir.c_str(), 0 ) == -1 && _mkdir(tmpdir.c_str() ) == -1
+                #else
+                 _waccess(tmpdir.c_str(), 0) == -1 && _wmkdir(tmpdir.c_str()) == -1
+                #endif
+               )
+               {
+                  UBLOG(logDEBUG5,"UbSystem::makeDirectory-  dir=\""<<tmpdir<<"\" doesn't exit or makedir failed");
+                  dirCreated = false;
+                  break;
+               }
+         }
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         std::string command = "mkdir -p \""+path+"\"";
+         {
+            #if defined(CAB_BOOST) 
+               boost::mutex::scoped_lock lock(mtx_makeDirectory);
+            #endif
+            if(system(command.c_str())!=0)
+            {
+               UBLOG(logDEBUG5,"UbSystem::makeDirectory-  dir=\""<<path<<"\" doesn't exit or makedir failed");
+               dirCreated = false;
+            }
+         }
+      #else
+         #error "UbSystem::makeDirectory - UnknownMachine"
+      #endif
+
+      if(!dirCreated && attemptions > 1)
+      {
+         UBLOG(logDEBUG5,"UbSystem::makeDirectory - internal call of UbSystem::makeDirectory");
+         UbSystem::sleepMs(500);
+         dirCreated = UbSystem::makeDirectory(path, attemptions-1);
+      }
+      
+      UBLOG(logDEBUG5,"UbSystem::makeDirectory - end (success="<<dirCreated<<", attemptions = "<<attemptions<<")");
+      return dirCreated;
+   }
+   /*==========================================================*/
+#if defined(CAB_BOOST) 
+   static boost::mutex mtx_removeDirectory;
+#endif
+   inline int removeDirectory(const std::string& dir)
+   {
+      #if defined(CAB_BOOST) 
+         boost::mutex::scoped_lock lock(mtx_removeDirectory);
+      #endif
+      std::string command = "rmdir \""+dir+"\"";
+      return std::system(command.c_str());
+   }
+   /*==========================================================*/
+   // usage  : getPathFromString("c:/temp/foo.txt");
+   //returns: "c:/temp"
+   // usage  : getPathFromString("c:\\temp\\foo.txt");
+   //returns: "c:/temp"
+   // usage  : getPathFromString("foo.txt");
+   // returns: ""
+   inline std::string getPathFromString(const std::string& fileStringWithPath)
+   {
+      std::string tmp = UbSystem::replaceInString(fileStringWithPath,"\\","/");
+      std::size_t last = tmp.rfind("/");
+      if(last!=std::string::npos) tmp.resize(last);
+      else                        tmp = "";
+      return tmp;
+   }
+   /*==========================================================*/
+   // usage  : getFilenameFromString("c:/temp/foo.txt");
+   // returns: "foo.txt"
+   // usage  : getFilenameFromString("c:/temp/foo.txt",false);
+   // returns: "foo"
+   // usage  : getFilenameFromString("c:/temp/");
+   // returns: ""
+   inline std::string getFilenameFromString(const std::string& fileStringWithPath, bool withExtension = true)
+   {
+      std::string tmp = UbSystem::replaceInString(fileStringWithPath,"\\","/");
+      
+      //remove path
+      std::size_t last = tmp.rfind("/");
+      if(last!=std::string::npos && (last+1)<tmp.size()) tmp.erase(0,last+1);
+      
+      //remove extension
+      if(!withExtension)
+      {
+         last = tmp.rfind(".");
+         if(last!=std::string::npos) tmp.erase(last);
+      }
+
+      return tmp;
+   }
+   /*==========================================================*/
+   inline int getProcessID()
+   {
+      #if defined UBSYSTEM_WINDOWS
+         return _getpid();
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE) || defined(UBSYSTEM_AIX)
+         return getpid();
+      #else
+         #error "int UbSystem::getProcessID() - UnknownMachine"
+      #endif
+   }
+   /*==========================================================*/
+   inline unsigned long getCurrentThreadID()
+   {
+      #if defined UBSYSTEM_WINDOWS
+         return (unsigned long)GetCurrentThreadId();
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_APPLE)
+         return (unsigned long)syscall(SYS_gettid);
+      #elif defined(UBSYSTEM_AIX)
+         return (unsigned long) getpid(); //WORKAROUND for IBM (for get thread id is another function necessary) 
+      #else
+         #error "unsigned long UbSystem::getCurrentThreadID() - UnknownMachine"
+      #endif
+   }
+   /*==========================================================*/
+   inline bool isBigEndian()
+   {
+      short word = 0x4321;
+      if((*(char*)& word) != 0x21 ) return true;
+      else                           return false;
+   }
+   /*==========================================================*/
+   inline bool isLittleEndian()
+   {
+      return !isBigEndian();
+   }
+   /*==========================================================*/
+   inline std::string getTimeStamp()
+   {
+      time_t t = time(NULL);
+      tm* localTime = localtime(&t); 	
+      
+      std::stringstream tmp;
+      tmp.fill('0');
+      
+      tmp << localTime->tm_year+1900 
+          << "." << std::setw(2) <<localTime->tm_mon+1
+          << "." << std::setw(2) << localTime->tm_mday 
+          << "@" << std::setw(2) << localTime->tm_hour  
+          << "." << std::setw(2) << localTime->tm_min   
+          << "." << std::setw(2) << localTime->tm_sec  ;
+
+      return tmp.str();
+   }
+   /*==========================================================*/
+   //swap Byte Order
+   //usage: int test = 8;
+   //       swapByteOrder((unsigned char*)& test, sizeof(int))
+   //#define ByteSwap5(x) ByteSwap((unsigned char *) &x,sizeof(x))
+   inline void swapByteOrder(unsigned char* toSwap, int length)
+   {
+      register int i = 0;
+      register int j = length-1;
+      while(i<j)
+      {
+         std::swap(toSwap[i], toSwap[j]);
+         i++, j--;
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //get host name
+   inline std::string getMachineName()
+   {
+      char Name[150];
+      int i = 0;
+
+#ifdef UBSYSTEM_WINDOWS
+      TCHAR infoBuf[150];
+      DWORD bufCharCount = 150;
+      memset(Name, 0, 150);
+      if (GetComputerName(infoBuf, &bufCharCount))
+      {
+         for (i = 0; i<150; i++)
+         {
+            Name[i] = infoBuf[i];
+         }
+      }
+      else
+      {
+         strcpy(Name, "Unknown_Host_Name");
+      }
+#else
+      memset(Name, 0, 150);
+      gethostname(Name, 150);
+#endif
+      return std::string(Name);
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   // generic IfThenElse - start
+   //////////////////////////////////////////////////////////////////////////
+   // primary template: yield second or third argument depending on first argument
+   template<bool C, typename Ta, typename Tb>
+   class IfThenElse;
+
+   // partial specialization: true yields second argument
+   template<typename Ta, typename Tb>
+   class IfThenElse<true, Ta, Tb> {
+   public:
+      typedef Ta ResultT;
+   };
+
+   // partial specialization: false yields third argument
+   template<typename Ta, typename Tb>
+   class IfThenElse<false, Ta, Tb> {
+   public:
+      typedef Tb ResultT;
+   };
+   //////////////////////////////////////////////////////////////////////////
+   // generic IfThenElse - end
+   //////////////////////////////////////////////////////////////////////////
+
+   //////////////////////////////////////////////////////////////////////////
+   //help struct for overloading methods in template classes for specific types
+   //////////////////////////////////////////////////////////////////////////
+   template< typename T>
+   struct type2type
+   {
+      typedef T type;
+   };
+
+
+   //////////////////////////////////////////////////////////////////////////
+   // pair selector
+   //////////////////////////////////////////////////////////////////////////
+   template <typename Pair>
+   struct select1st
+   {
+      typedef Pair argument_type ;
+      typedef typename Pair::first_type result_type ;
+
+      const result_type&  operator()(const argument_type &p) const
+      {
+         return p.first ;
+      }
+   };
+
+   template <typename Pair>
+   struct select2nd
+   {
+      typedef Pair argument_type ;
+      typedef typename Pair::second_type result_type ;
+
+      const result_type& operator()(const argument_type &p) const
+      {
+         return p.second ;
+      }
+   };
+
+};
+
+#define UB_STATIC_ASSERT(expr) static_cast<void>(sizeof( UbSystem::ub_static_assert<expr> ));
+//zum ueberpruefen von STATISCHEN ausdruecken waehrend der compile-zeit
+//--> Ausdruecke muessen schon ZUR compilerzeit auswertbar sein !!!
+//Anwendung z.B. zur Ueberpruefung von Funktionalitaeten, wie z.B. bei UbMath::getNegativeInfinity<double>();
+//
+//Grund fuer macro ist einfach, dass es besser anzuwenden ist in der praxis!
+//ansonsten würde es so aussehen:
+//     UbSystem::ub_static_assert< aaa == 1 > test();
+//    da ist  UB_STATIC_ASSERT(aaa == 1); schoener
+//
+//um das zu vermeiden machtman hier diesen static_cast<void>(sizeof(...) )
+//Code-Snippet:
+// struct Test { const static bool m_const_bool = true; bool m_bool; };
+// int main() {
+//  UB_STATIC_ASSERT( Test::m_const_bool == true );
+//  --> okay, assert bestanden
+//  UB_STATIC_ASSERT( Test::m_const_bool == false); //:
+//  --> assert nicht bestanden z.B. error C2027: use of undefined type 'UbSystem::ub_static_assert<__formal> with __formal = false --> funzt nicht. fehler im code
+//  UB_STATIC_ASSERT( Test::m_bool == true );
+//  --> nicht erlaubt, da m_bool nicht statisch und nicht const ist.
+//}
+
+#endif //UBSYSTEM_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbTableModel.cpp b/source/VirtualFluidsCore/Basics/utilities/UbTableModel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eca533129a77a21e3515939b72f848e8f611c9d4
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbTableModel.cpp
@@ -0,0 +1,20 @@
+#include <basics/utilities/UbTableModel.h>
+
+UbTableModel::UbTableModel()
+{
+}
+
+UbTableModel::~UbTableModel()
+{
+	//this->notifyObserversObjectWillBeDeleted();
+}
+
+//void UbTableModel::objectChanged(UbObservable* changedObject)
+//{
+//	this->notifyObserversObjectChanged();	
+//}
+//
+//void UbTableModel::objectWillBeDeleted(UbObservable* objectForDeletion)
+//{
+//	objectForDeletion->removeObserver(this);
+//}
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbTableModel.h b/source/VirtualFluidsCore/Basics/utilities/UbTableModel.h
new file mode 100644
index 0000000000000000000000000000000000000000..4a12d63b3881238daeb261b35b599ccbb7b64890
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbTableModel.h
@@ -0,0 +1,37 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBTABLEMODEL_H
+#define UBTABLEMODEL_H
+
+#include <iostream>
+
+class UbTableModel 
+{
+public:
+   const static int COL_TYPE_STRING  = 1;
+   const static int COL_TYPE_BOOL    = 2;
+   const static int COL_TYPE_INTEGER = 3;
+   const static int COL_TYPE_DOUBLE  = 4;
+
+	UbTableModel();
+	virtual ~UbTableModel();
+
+	//////////////////////////////////////////////////////////////////////////
+	//void objectChanged(UbObservable*);
+	//void objectWillBeDeleted(UbObservable*);
+
+	virtual int getColumnNumber() = 0;
+	virtual int getRowNumber()    = 0;
+   virtual std::string getColumnLabel(int column) = 0;
+	virtual int getColumnType(int column) = 0;
+	virtual std::string getStringValue(int row, int col) = 0;
+   virtual void setStringValue(int row, int col, std::string str) = 0;
+	virtual int getSelectedRowIndex() = 0;
+	//virtual bool GetBoolValue(int row, int col) = 0;
+};
+
+#endif //UBTABLEMODEL_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbTiming.h b/source/VirtualFluidsCore/Basics/utilities/UbTiming.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f768fea3d98129f7359f1576c46032ea42cf763
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbTiming.h
@@ -0,0 +1,429 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBTIMING_H
+#define UBTIMING_H
+
+#include <string>
+#include <limits>
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <ctime>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#ifdef VF_MPI
+   #include <mpi.h>
+   #include <basics/parallel/PbMpi.h>
+#endif //VF_MPI
+
+/*=========================================================================*/
+//  UbTiming - Time Measuring                                              
+//                                                                         
+//
+//
+//This Class provides the base for ...
+//<BR><BR>
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@author <A HREF="mailto:geller@cab.bau.tu-bs.de">S. Geller</A>
+//@version 1.1 - 14.02.06
+// 
+
+class UbTiming
+{
+public:
+	UbTiming()
+   {
+      this->duration		= 0.0;
+      this->deltaT		= 0.0;
+      this->startTime	= 0;
+      this->name        = "noname";
+   }
+   /*==========================================================*/
+   UbTiming(const std::string& name)
+   {
+      this->duration		= 0.0;
+      this->deltaT		= 0.0;
+      this->startTime	= 0;
+      this->name        = name;
+   }
+   /*==========================================================*/
+   virtual ~UbTiming() {}  
+   /*==========================================================*/
+   virtual void initTiming()
+   {
+      this->duration = 0.0;	
+   }
+   /*==========================================================*/
+   virtual void startTiming()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->startTime = PbMpi::Wtime();
+      #else
+         this->startTime = (double)clock();	
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   virtual void initAndStartTiming()
+   {
+      this->initTiming();
+      this->startTiming();
+   }
+   /*==========================================================*/
+   virtual void endTiming()
+   {
+      this->stopTiming();
+   }
+   /*==========================================================*/
+   virtual void stopTiming()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+            this->deltaT   = PbMpi::Wtime()-this->startTime;
+      #else
+         this->deltaT   = ((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+
+      this->duration += this->deltaT;
+   }
+   /*==========================================================*/
+   virtual double getDuration() const
+   {
+      return this->duration;
+   }
+   /*==========================================================*/
+   virtual void setName(const std::string& name)
+   {
+      this->name = name;
+   }
+   /*==========================================================*/
+   virtual std::string getName() const
+   { 
+      return this->name; 
+   }
+   /*==========================================================*/
+   void start()
+   {
+      this->duration = 0.0;
+
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->startTime = PbMpi::Wtime();
+      #else
+         this->startTime = (double)clock();
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   void pause()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->duration += PbMpi::Wtime()-this->startTime;
+      #else
+         this->duration +=((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   void unpause()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->startTime   = PbMpi::Wtime();
+      #else
+         this->startTime = (double)clock();
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   void stop()
+   {
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         this->duration += PbMpi::Wtime()-this->startTime;
+      #else
+         this->duration +=((double)clock()-this->startTime)/(double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+   }
+   /*==========================================================*/
+   double getTicks() const            
+   { 
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         return PbMpi::Wtick();
+      #else
+         return double(1.0)/double(CLOCKS_PER_SEC);
+      #endif  //VF_MPI 
+   }
+
+protected:
+   std::string name;
+
+   double startTime;
+   double duration;
+	double deltaT;
+};
+
+/*=========================================================================*/
+//  UbTimer - Time Measuring                                              
+//                                                                         
+//
+//
+//This Class provides the base for ...
+//<BR><BR>
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@version 1.0 - 16.08.2007
+// 
+#include <basics/utilities/UbSystem.h> //for definitons of system/OS type
+
+#ifdef UBSYSTEM_APPLE   //Apple hack
+   #include <mach/mach_time.h>  
+   #include <time.h>  
+   #include <stdio.h> 
+   inline void mach_absolute_difference(const uint64_t& end, const uint64_t& start, struct timespec *tp) 
+   {  
+         uint64_t difference = end - start;  
+         static mach_timebase_info_data_t info = {0,0};  
+   
+         if (info.denom == 0)  
+                 mach_timebase_info(&info);  
+   
+         uint64_t elapsednano = difference * (info.numer / info.denom);  
+   
+         tp->tv_sec = elapsednano * 1e-9;  
+         tp->tv_nsec = elapsednano - (tp->tv_sec * 1e9);  
+   } 
+#elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
+   #include <ctime>
+   #include <unistd.h> // for sysconf
+   #include <pthread.h>
+#endif
+
+//example:
+//t=0  start 
+//t=1 
+//t=2  stop  -> return 2; getLapTime=2; getTotalTime 2; getLapTimes:  2
+//t=3 
+//t=4 
+//t=5  stop  -> return 3; getLapTime=3; getTotalTime 5; getLapTimes:  2,3
+//t=6  stop  -> return 1; getLapTime=1; getTotalTime 6; getLapTimes:  2,3,1
+//t=7  
+//t=8  start ->no consideration of time 7 and 8 
+//t=9  
+//t=10 stop  -> return 2; getLapTime=2; getTotalTime 8; getLapTimes:  2,3,1,2
+//t=11 resetAndStart timer wird zurueckgestellt und neu gestaret
+//t=12
+//t=13 
+//t=14 stop  -> return 3; getLapTime=3; getTotalTime 3; getLapTimes:  3
+
+class UbTimer
+{
+public:
+   UbTimer(const bool& storeLapTimes = false) 
+      :  name("unamed"), isMeasuring(false), storeLapTimes(storeLapTimes)
+       , startTime(0.0), totalTime(0.0), lapTime(0.0)
+   {
+
+   }
+   /*==========================================================*/
+   UbTimer(const std::string& name, const bool& storeLapTimes = false) 
+      :  name(name), isMeasuring(false), storeLapTimes(storeLapTimes)
+       , startTime(0.0), totalTime(0.0), lapTime(0.0)
+   {
+
+   }
+   /*==========================================================*/
+   virtual ~UbTimer() {}  
+   /*==========================================================*/
+   double              getLapTime() const               { return this->lapTime;  }
+   std::vector<double> getLapTimes() const              { return this->lapTimes; }
+   void                setName(const std::string& name) { this->name = name;     }
+   std::string         getName() const                  { return this->name;     }
+   bool                isRunning() const                { return isMeasuring;    }
+   bool                isStoringLapTimes() const        { return storeLapTimes;  }
+   /*==========================================================*/
+   void setStoreLapTimes(const bool& storeLapTimes) { this->storeLapTimes = storeLapTimes; }
+   /*==========================================================*/
+   void start()
+   {
+      this->isMeasuring = true;
+
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+          this->startTime = PbMpi::Wtime();
+      #elif defined(UBSYSTEM_APPLE)
+    	 this->startTime = mach_absolute_time();  
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
+         timespec tp;
+         clock_gettime(CLOCK_REALTIME,&tp);
+         this->startTime = (double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec);
+      #else
+         this->startTime = (double)clock();
+      #endif //VF_MPI
+   }
+   /*==========================================================*/
+   void resetAndStart() { this->reset(); this->start(); }
+   /*==========================================================*/
+   //stop: - stops the calculation and returns the time elapsed since last start/stop
+   //      - timing continues
+   double stop()
+   {
+      //if start() was never activated before:
+      if(!isMeasuring) return 0.0; 
+      
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         double actTime = PbMpi::Wtime();
+         this->lapTime  = actTime-this->startTime;
+      #elif defined(UBSYSTEM_APPLE)
+    	 double actTime = mach_absolute_time();  
+         timespec tp;  
+         mach_absolute_difference(actTime, this->startTime, &tp);
+         this->lapTime  =  tp.tv_sec + tp.tv_nsec*1e-9;
+	  #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
+         timespec tp;
+         clock_gettime(CLOCK_REALTIME,&tp);
+         double actTime = (double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec);
+         this->lapTime  = (actTime-this->startTime)*1.0e-9;
+      #else
+         double actTime = (double)clock();
+         this->lapTime  = (actTime-this->startTime)/(double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+      
+      this->startTime  = actTime;
+      this->totalTime += this->lapTime;
+      if(storeLapTimes) lapTimes.push_back(this->lapTime);
+
+      return lapTime;
+   }
+   /*==========================================================*/
+   void reset()
+   {
+      this->isMeasuring = false;
+      
+      this->startTime   = 0.0;
+      this->totalTime   = 0.0;
+      this->lapTime     = 0.0;
+
+      lapTimes.resize(0);
+   }
+   /*==========================================================*/
+   double getCurrentLapTime() const
+   {
+     //if start() was never activated before:
+      if(!isMeasuring) return 0.0; 
+      
+      #if defined(VF_MPI) && !defined(CAB_RUBY)
+         return PbMpi::Wtime() - this->startTime;
+      #elif defined(UBSYSTEM_APPLE)
+         timespec tp;  
+         mach_absolute_difference(mach_absolute_time(), this->startTime, &tp);
+         return tp.tv_sec + tp.tv_nsec*1e-9;
+      #elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
+         timespec tp;
+         clock_gettime(CLOCK_REALTIME,&tp);
+         return ((double)(tp.tv_sec)*1.0e9 + (double)(tp.tv_nsec) - this->startTime)*1.0e-9;
+      #else
+         return ( (double)clock() - this->startTime ) / (double)CLOCKS_PER_SEC;
+      #endif //VF_MPI 
+      
+   }
+   /*==========================================================*/
+   double getTotalTime() const
+   {
+      return this->totalTime;
+   }
+   /*==========================================================*/
+   std::string toString()
+   {
+      std::stringstream text;
+      text<<*this;
+      return text.str();
+   }
+
+   //ueberladene Operatoren
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const UbTimer& timer) 
+   {
+       os<<"UbTimer[totalTime="<<timer.totalTime<<"sec, lapTimes(";
+       for(std::size_t i=0; i<timer.lapTimes.size(); i++) os<<timer.lapTimes[i]<<",";
+       os<<")]";
+       return os;
+   }
+
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      ar & name;
+      ar & isMeasuring;
+      ar & startTime;
+      ar & totalTime;
+      ar & lapTime;
+      ar & lapTimes;
+      ar & storeLapTimes;
+   }
+#endif //CAB_RCF
+
+protected:
+   std::string name;
+   bool        isMeasuring;
+   bool        storeLapTimes;
+
+   double      startTime;
+   double      totalTime;
+   double      lapTime;
+   
+   std::vector<double> lapTimes;
+};
+
+
+/*=========================================================================*/
+//  UbProgressTimer - Time Measuring                                              
+//                                                                         
+//
+//
+//UbProressTimer misst die Zeit von seiner Instantiierung bis zur Zerstörung
+//und gib die verstrichene Zeit auf "os" in [s] aus
+//example:
+// {
+//    UbProgressTimer timer;
+//    UbSystem::sleepS(10);
+// } //--> 10s
+//<BR><BR>
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@version 1.0 - 10.03.2008
+// 
+class UbProgressTimer : public UbTimer
+{
+private:
+	UbProgressTimer(const UbProgressTimer& rhs);
+public:
+  explicit UbProgressTimer( std::ostream & os = std::cout )
+     : UbTimer(),os(os) 
+  {
+  	  this->start();
+  }
+  /*==========================================================*/
+  ~UbProgressTimer()
+  {
+  //  A) Throwing an exception from a destructor is a Bad Thing.
+  //  B) The progress_timer destructor does output which may throw.
+  //  C) A progress_timer is usually not critical to the application.
+  //  Therefore, wrap the I/O in a try block, catch and ignore all exceptions.
+    try
+    {
+      // use istream instead of ios_base to workaround GNU problem (Greg Chicares)
+      std::istream::fmtflags old_flags = os.setf( std::istream::fixed,
+                                                  std::istream::floatfield );
+      std::streamsize old_prec = os.precision( 2 );
+      os << stop() << " s" << std::endl;
+      os.flags( old_flags );
+      os.precision( old_prec );
+    }
+    catch (...) {} // eat any exceptions
+  } 
+
+private:
+  std::ostream & os;
+};
+
+
+#endif //UBTIMING_H
diff --git a/source/VirtualFluidsCore/Basics/utilities/UbTuple.h b/source/VirtualFluidsCore/Basics/utilities/UbTuple.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb711c9dc9c3b91922a1252f78b1f00208d5ccc7
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/utilities/UbTuple.h
@@ -0,0 +1,1138 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef UBTUPLE_H
+#define UBTUPLE_H
+
+#include <iostream>
+#include <string>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+/*=========================================================================*/
+/*  UbTuple                                                             */
+/*                                                                         */
+/**
+...
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 23.10.06
+*/ 
+
+/*
+usage: ...
+////Advanced UbTuple
+//Bsp:
+//// create and use tuple with only one field
+//UbTuple<int,int,int,int,int> t1;
+//val<1>(t1) += 42;
+//std::cout << t1.v1() << std::endl;
+
+//// create and use duo
+//UbTuple<bool,int> t2;
+//std::cout << val<1>(t2) << ", ";
+//std::cout << t2.v1() << std::endl;
+
+//// create and use triple
+//UbTuple<bool,int,double> t3;
+//val<1>(t3) = true;  // new values via: val< pos >(triple) = ...
+//val<2>(t3) = 42;
+//val<3>(t3) = 0.2;
+//t3 = makeUbTuple(false, 23, 13.13);
+
+//std::cout << val<1>(t3) << ", ";
+//std::cout << val<2>(t3) << ", ";
+//std::cout << val<3>(t3) << std::endl;
+
+//// create and use quadruple
+//UbType<bool,int,float,double> t4(true,42,13,1.95583);
+//std::cout << val<4>(t4) << std::endl;        //<- option 2 (std)
+//std::cout << t4.v2().v2().v2() << std::endl; //<- option 2
+*/
+
+//typeop.h
+// primary template
+/**********************************
+* typeop1.hpp:
+**********************************/
+template <typename T>
+class UbTypeOp    // primary template
+{           
+public:
+   typedef T         ArgT;
+   typedef T         BareT;
+   typedef T const   ConstT;
+   typedef T &       RefT;
+   typedef T &       RefBareT;
+   typedef T const & RefConstT;
+};
+/**** end of typeop1.hpp ****/
+
+// partial specialization for const
+/**********************************
+* typeop2.hpp:
+**********************************/
+template <typename T>
+class UbTypeOp <T const>  // partial specialization for const types
+{
+ public:
+   typedef T const   ArgT;
+   typedef T         BareT;
+   typedef T const   ConstT;
+   typedef T const & RefT;
+   typedef T &       RefBareT;
+   typedef T const & RefConstT;
+};
+/**** end of typeop2.hpp ****/
+
+// partial specialization for references
+/**********************************
+* typeop3.hpp:
+**********************************/
+template <typename T>
+class UbTypeOp <T&>        // partial specialization for references
+{
+public:
+   typedef T &                           ArgT;
+   typedef typename UbTypeOp<T>::BareT   BareT;
+   typedef T const                       ConstT;
+   typedef T &                           RefT;
+   typedef typename UbTypeOp<T>::BareT & RefBareT;
+   typedef T const &                     RefConstT;
+};
+/**** end of typeop3.hpp ****/
+
+// full specialization for void
+/**********************************
+* typeop4.hpp:
+**********************************/
+template<>
+class UbTypeOp <void>      // full specialization for void
+{
+public:
+   typedef void       ArgT;
+   typedef void       BareT;
+   typedef void const ConstT;
+   typedef void       RefT;
+   typedef void       RefBareT;
+   typedef void       RefConstT;
+};
+/**** end of typeop4.hpp ****/
+
+//duo1.hpp
+template <typename T1, typename T2>
+class UbDuo 
+{
+public:
+   typedef T1 Type1;  // type of first field
+   typedef T2 Type2;  // type of second field
+   enum { N = 2 };    // number of fields
+
+public:
+   // constructors
+   UbDuo() : value1(), value2() {  }
+   UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b)  {  }
+
+   // for implicit type conversion during construction
+   template <typename U1, typename U2>
+   UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) {  }
+
+   // for implicit type conversion during assignments
+   template <typename U1, typename U2>
+   UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d) 
+   {
+      value1 = d.v1();//value1;
+      value2 = d.v2();//value2;
+      return *this;
+   }
+
+   // field access
+   T1& v1()             { return value1; }
+   T1 const& v1() const { return value1; }
+
+   T2& v2()             { return value2; }
+   T2 const& v2() const { return value2; }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive& ar, const unsigned int version)
+   {
+      ar & value1;
+      ar & value2;
+   }
+#endif //CAB_RCF
+
+private:
+   T1 value1;         // value of first field
+   T2 value2;         // value of second field
+};
+
+// comparison operators (allow mixed types):
+template <typename T1, typename T2,typename U1, typename U2>
+inline bool operator == (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+{
+   return d1.v1()==d2.v1() && d1.v2()==d2.v2();
+}
+
+template <typename T1, typename T2,typename U1, typename U2>
+inline bool operator != (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+{
+   return !(d1==d2);
+}
+
+template <typename T1, typename T2,typename U1, typename U2>
+inline bool operator < (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+{
+   if     (d1.v1() <  d2.v1() ) return true;
+   else if(d1.v1() == d2.v1() ) return d1.v2() < d2.v2();
+
+   return false;
+}
+
+// convenience function for creation and initialization
+template <typename T1, typename T2> 
+inline UbDuo<T1,T2> makeUbDuo(T1 const & a, T2 const & b)
+{
+   return UbDuo<T1,T2>(a,b);
+}
+
+//duo2.hpp
+template <typename A, typename B, typename C>
+class UbDuo<A, UbDuo<B,C> > 
+{
+public:
+   typedef A          T1;           // type of first field
+   typedef UbDuo<B,C> T2;           // type of second field
+   enum { N = UbDuo<B,C>::N + 1 };  // number of fields
+ 
+public:
+   // constructors
+   UbDuo() : value1(), value2() { }
+   UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b) { }
+
+   // for implicit type conversion during construction
+   template <typename U1, typename U2>
+   UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) { }
+
+   // for implicit type conversion during assignments
+   template <typename U1, typename U2>
+   UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d) 
+   { 
+      value1 = d.v1();//value1;     
+      value2 = d.v2();//value2;
+      return *this;
+   }
+
+   // field access
+   T1& v1()             { return value1; }
+   T1 const& v1() const { return value1; }
+
+   T2& v2()             { return value2; }
+   T2 const& v2() const { return value2; }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & value1;
+      ar & value2;
+   }
+#endif //CAB_RCF
+
+private:
+   T1 value1;         // value of first field
+   T2 value2;         // value of second field
+};
+
+//duo3.hpp
+// primary template for type of Nth field of (duo) T
+template <int N, typename T>
+class UbDuoT 
+{
+public:
+   typedef void ResultT;    // in general, the result type is void
+};
+
+// specialization for 1st field of a plain duo
+template <typename A, typename B>
+class UbDuoT<1, UbDuo<A,B> > 
+{
+public:
+   typedef A ResultT;
+};
+
+// specialization for 2nd field of a plain duo
+template <typename A, typename B>
+class UbDuoT<2, UbDuo<A,B> > 
+{
+public:
+   typedef B ResultT;
+};
+
+// specialization for Nth field of a recursive duo
+template <int N, typename A, typename B, typename C>
+class UbDuoT<N, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   typedef typename UbDuoT<N-1, UbDuo<B,C> >::ResultT ResultT;
+};
+
+// specialization for 1st field of a recursive duo
+template <typename A, typename B, typename C>
+class UbDuoT<1, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   typedef A ResultT;
+};
+
+// specialization for 2nd field of a recursive duo
+template <typename A, typename B, typename C>
+class UbDuoT<2, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   typedef B ResultT;
+};
+
+//duo4.hpp
+// primary template for value of Nth field of (duo) T
+template <int N, typename T>
+class DuoValue 
+{
+public:
+   static void get(T&) {  }      // in general, we have no value
+   static void get(T const&) { }
+};
+
+// specialization for 1st field of a plain duo
+template <typename A, typename B>
+class DuoValue<1, UbDuo<A, B> > 
+{
+public:
+   static A& get(UbDuo<A, B> &d)             { return d.v1(); }
+   static A const& get(UbDuo<A, B> const &d) { return d.v1(); }
+};
+
+// specialization for 2nd field of a plain duo
+template <typename A, typename B>
+class DuoValue<2, UbDuo<A, B> > 
+{
+public:
+   static B& get(UbDuo<A, B> &d)             { return d.v2(); }
+   static B const& get(UbDuo<A, B> const &d) { return d.v2(); }
+};
+
+// specialization for Nth field of recursive duo
+template <int N, typename A, typename B, typename C>
+struct DuoValue<N, UbDuo<A, UbDuo<B,C> > >
+{
+   static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefT  get(UbDuo<A, UbDuo<B,C> > &d)
+   { 
+      return DuoValue<N-1, UbDuo<B,C> >::get(d.v2()); 
+   }
+   static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefConstT  get(UbDuo<A, UbDuo<B,C> > const &d)
+   { 
+      return DuoValue<N-1, UbDuo<B,C> >::get(d.v2()); 
+   }
+};
+
+// specialization for 1st field of recursive duo
+template <typename A, typename B, typename C>
+class DuoValue<1, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   static A& get(UbDuo<A, UbDuo<B,C> > &d)             { return d.v1(); }
+   static A const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v1(); }
+};
+
+// specialization for 2nd field of recursive duo
+template <typename A, typename B, typename C>
+class DuoValue<2, UbDuo<A, UbDuo<B,C> > > 
+{
+public:
+   static B& get(UbDuo<A, UbDuo<B,C> > &d)             { return d.v2().v1(); }
+   static B const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v2().v1(); }
+};
+
+//duo5.hpp
+// return Nth value of variable duo
+template <int N, typename A, typename B> 
+inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefT val(UbDuo<A, B>& d)
+{
+   return DuoValue<N, UbDuo<A, B> >::get(d);
+}
+
+// return Nth value of constant duo
+template <int N, typename A, typename B> 
+inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefConstT val(UbDuo<A, B> const& d)
+{
+   return DuoValue<N, UbDuo<A, B> >::get(d);
+}
+
+//duo6.hpp
+// partial specialization for UbDuo<> with only one field
+template <typename A>
+struct UbDuo<A,void> 
+{
+public:
+   typedef A    T1;  // type of first field
+   typedef void T2;  // type of second field
+   enum { N = 1 };   // number of fields
+
+private:
+   T1 value1;        // value of first field
+
+public:
+   // constructors
+   UbDuo() : value1() { }
+   UbDuo (T1 const & a) : value1(a) { }
+
+   // field access
+   T1& v1()             { return value1; }
+   T1 const& v1() const { return value1; }
+
+   void v2() { }
+   void v2() const { }
+
+   #ifdef CAB_RCF
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & value1;
+      }
+   #endif
+};
+
+//tupel1.hpp
+// type that represents unused type parameters
+class UbNullT 
+{
+};
+
+// UbTuple<> in general derives from UbTuple<> with one more UbNullT
+template <typename P1,
+          typename P2 = UbNullT,
+          typename P3 = UbNullT,
+          typename P4 = UbNullT,
+          typename P5 = UbNullT,
+          typename P6 = UbNullT,
+          typename P7 = UbNullT,
+          typename P8 = UbNullT >
+class UbTuple : public UbDuo<P1, typename UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>::BaseT> 
+{
+public:
+   typedef UbDuo<P1, typename UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>::BaseT>  BaseT;
+
+   // constructor:
+   UbTuple() {}
+   UbTuple( typename UbTypeOp<P1>::RefConstT a1,
+            typename UbTypeOp<P2>::RefConstT a2,
+            typename UbTypeOp<P3>::RefConstT a3 = UbNullT(),
+            typename UbTypeOp<P4>::RefConstT a4 = UbNullT(),
+            typename UbTypeOp<P5>::RefConstT a5 = UbNullT(),
+            typename UbTypeOp<P6>::RefConstT a6 = UbNullT(),
+            typename UbTypeOp<P7>::RefConstT a7 = UbNullT(),
+            typename UbTypeOp<P8>::RefConstT a8 = UbNullT() )
+      : BaseT(a1, UbTuple<P2,P3,P4,P5,P6,P7,P8,UbNullT>(a2,a3,a4,a5,a6,a7,a8))
+   {
+   }
+
+   // for implicit type conversion during assignments
+   template <typename U1,typename U2, typename U3, typename U4, typename U5, typename U6, typename U7, typename U8 >
+   UbTuple<P1,P2,P3,P4,P5,P6,P7,P8>& operator = ( const UbTuple<U1,U2,U3,U4,U5,U6,U7,U8>& rhs)
+   {
+      this->BaseT::operator=( typename UbTuple<U1,U2,U3,U4,U5,U6,U7,U8>::BaseT(rhs) );
+      return *this;
+   }
+
+};
+
+// specialization to end deriving recursion
+template <typename P1, typename P2>
+class UbTuple<P1,P2,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,P2> {
+public:
+   typedef UbDuo<P1,P2> BaseT;
+   
+   // constructor:
+   UbTuple() {}
+   UbTuple( typename UbTypeOp<P1>::RefConstT a1,
+            typename UbTypeOp<P2>::RefConstT a2,
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT() )
+      : BaseT(a1, a2) 
+   {
+   }
+
+   // for implicit type conversion during assignments
+   template <typename U1,typename U2 >
+   UbTuple<P1,P2>& operator = ( const UbTuple<U1,U2>& rhs)
+   {
+      this->BaseT::operator=( typename UbTuple<U1,U2>::BaseT(rhs) );
+      return *this;
+   }
+
+};
+
+// specialization for singletons
+template <typename P1>
+class UbTuple<P1,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,void>
+{
+public:
+   typedef UbDuo<P1,void> BaseT;
+
+   // constructor:
+   UbTuple() {}
+   UbTuple( typename UbTypeOp<P1>::RefConstT a1,
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+            typename UbTypeOp<UbNullT>::RefConstT = UbNullT() )
+      : BaseT(a1) 
+   {
+   }
+
+   // for implicit type conversion during assignments
+   template <typename U1 >
+   UbTuple<P1>& operator = ( const UbTuple<U1>& rhs)
+   {
+      this->v1() = rhs.v1();
+      return *this;
+   }
+
+};
+
+// convenience function for 1 argument
+template <typename T1> 
+inline UbTuple<T1> makeUbTuple(T1 const &a1)
+{
+   return UbTuple<T1>(a1);
+}
+
+// convenience function for 2 arguments
+template <typename T1, typename T2>
+inline UbTuple<T1,T2> makeUbTuple(T1 const &a1, T2 const &a2)
+{
+   return UbTuple<T1,T2>(a1,a2);
+}
+
+// convenience function for 3 arguments
+template <typename T1, typename T2, typename T3>
+inline UbTuple<T1,T2,T3> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3)
+{
+   return UbTuple<T1,T2,T3>(a1,a2,a3);
+}
+
+// convenience function for 4 arguments
+template <typename T1, typename T2, typename T3, typename T4>
+inline UbTuple<T1,T2,T3,T4> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4)
+{
+   return UbTuple<T1,T2,T3,T4>(a1,a2,a3,a4);
+}
+
+// convenience function for 5 arguments
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline UbTuple<T1,T2,T3,T4,T5> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4,T5 const &a5)
+{
+   return UbTuple<T1,T2,T3,T4,T5>(a1,a2,a3,a4,a5);
+}
+
+// convenience function for 6 arguments
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+inline UbTuple<T1,T2,T3,T4,T5,T6> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6)
+{
+   return UbTuple<T1,T2,T3,T4,T5,T6>(a1,a2,a3,a4,a5,a6);
+}
+
+// convenience function for 7 arguments
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+inline UbTuple<T1,T2,T3,T4,T5,T6,T7> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4, T5 const &a5, T6 const &a6, T7 const &a7)
+{
+   return UbTuple<T1,T2,T3,T4,T5,T6,T7>(a1,a2,a3,a4,a5,a6,a7);
+}
+
+// convenience function for 8 arguments
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
+inline UbTuple<T1,T2,T3,T4,T5,T6,T7,T8> makeUbTuple(T1 const &a1, T2 const &a2,T3 const &a3, T4 const &a4,T5 const &a5, T6 const &a6,T7 const &a7, T8 const &a8 )
+{
+   return UbTuple<T1,T2,T3,T4,T5,T6,T7,T8>(a1,a2,a3,a4,a5,a6,a7,a8);
+}
+
+//some typedefs
+typedef UbTuple<float,float>                               UbTupleFloat2;
+typedef UbTuple<float,float,float>                         UbTupleFloat3;
+typedef UbTuple<int,int>                                   UbTupleInt2;
+typedef UbTuple<int,int,int>                               UbTupleInt3;
+typedef UbTuple<int,int,int,int>                           UbTupleInt4;
+typedef UbTuple<int,int,int,int,int>                       UbTupleInt5;
+typedef UbTuple<int,int,int,int,int,int>                   UbTupleInt6;
+typedef UbTuple<int,int,int,int,int,int,int,int>           UbTupleInt8;
+typedef UbTuple<double,double>                             UbTupleDouble2;
+typedef UbTuple<double,double,double>                      UbTupleDouble3;
+typedef UbTuple<double,double,double,double>               UbTupleDouble4;
+typedef UbTuple<double,double,double,double,double,double> UbTupleDouble6;
+typedef UbTuple<std::string,double,double>                 UbTupleStringDouble2;
+typedef UbTuple<std::string,double,double,double>          UbTupleStringDouble3;
+typedef UbTuple<std::string,int,int,int>                   UbTupleStringInt3;
+typedef UbTuple<short,short,short,short>                   UbTupleShort4;
+typedef UbTuple<bool,bool,bool>                            UbTupleBool3;
+typedef UbTuple<int,double,double>                         UbTupleIntDouble2;
+typedef UbTuple<int, bool>                                 UbTupleIntBool;
+
+
+// class UbTupleWrapper
+// {
+// public:
+//    UbTuple<int, int> a;
+// 
+// #ifdef CAB_RCF
+//    template<class Archive>
+//    void serialize(Archive & ar, const unsigned int version)
+//    {
+//       ar & a;
+//    }
+//    void tuWas()
+//    {
+//       std::cout<<val<1>(a)<<std::endl;
+// 
+//       std::cout<<val<2>(a)<<std::endl;
+//    }
+// 
+// #endif
+// 
+// };
+
+
+#endif //UBTUPLE_H
+
+
+//#ifndef AAAAAAAAAAAAAAAAAAAAAAAAAAAAA //UBTUPLE_H
+//#define AAAAAAAAAAAAAAAAAAAAAAAAAAAAA //UBTUPLE_H
+//class UbTuble;
+//#include <iostream>
+//#include <string>
+//#include <algorithm> 
+//
+//
+//// a helper traits to make the make_tuple functions shorter (Vesa Karvonen's suggestion)
+//struct UbNullType{};
+//
+//template < class T0 = UbNullType, class T1 = UbNullType, class T2 = UbNullType,
+//class T3 = UbNullType, class T4 = UbNullType, class T5 = UbNullType,
+//class T6 = UbNullType, class T7 = UbNullType, class T8 = UbNullType >
+//class UbSimpleTuple
+//{
+//public:  
+//   UbSimpleTuple() {}
+//   UbSimpleTuple(T0 t0) {}
+//   UbSimpleTuple( const T0& t0) 
+//      : t0(t0) {}
+//   UbSimpleTuple( const T0& t0,  const T1& t1)
+//      : t0(t0), t1(t1){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2) 
+//      : t0(t0), t1(t1), t2(t2) {}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3)
+//      : t0(t0), t1(t1), t2(t2), t3(t3){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4,  const T5& t5) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), t5(t5){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4,  const T5& t5,  const T6& t6) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), t5(t5), t6(t6){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4,  const T5& t5,  const T6& t6,  const T7& t7) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), t5(t5), t6(t6), t7(t7){}
+//   UbSimpleTuple( const T0& t0,  const T1& t1,  const T2& t2,  const T3& t3,  const T4& t4,  const T5& t5,  const T6& t6,  const T7& t7, const T8& t8) 
+//      : t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), t5(t5), t6(t6), t7(t7), t8(t8){}
+//
+//   T0 t0;
+//   T1 t1;
+//   T2 t2;
+//   T3 t3;
+//   T4 t4;
+//   T5 t5;
+//   T6 t6;
+//   T7 t7;
+//   T8 t8;
+//};
+// 
+//
+//UbSimpleTuple<> 
+//inline makeUbSimpleTuple() { return UbSimpleTuple<>(); }
+//
+//template<class T0>
+//inline UbSimpleTuple<T0> makeUbSimpleTuple(const T0& t0) { return UbSimpleTuple<T0>(t0); }
+//
+//template<class T0, class T1>
+//inline UbSimpleTuple<T0,T1> makeUbSimpleTuple(const T0& t0, const T1& t1)  { return UbSimpleTuple<T0,T1>(t0,t1); }
+//
+//template<class T0, class T1, class T2>
+//inline UbSimpleTuple<T0,T1,T2> makeUbSimpleTuple(const T0& t0, const T1& t1, const T2& t2)  { return UbSimpleTuple<T0,T1,T2>(t0,t1,t2); }
+//
+//template<class T0, class T1, class T2, class T3>
+//inline UbSimpleTuple<T0,T1,T2,T3> makeUbSimpleTuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3)  { return UbSimpleTuple<T0,T1,T2,T3>(t0,t1,t2,t2); }
+//
+////////////////////////////////////////////////////////////////////////////
+////Advanced UbTuple
+////Bsp:
+// //// create and use tuple with only one field
+// //UbTuple<int,int,int,int,int> t1;
+// //val<1>(t1) += 42;
+// //std::cout << t1.v1() << std::endl;
+//
+// //UbTuple<int,double,double> ttt3;
+// //val<3>(t3);
+// //
+// //// create and use duo
+// //UbType<bool,int> t2;
+// //std::cout << val<1>(t2) << ", ";
+// //std::cout << t2.v1() << std::endl;
+//
+// //// create and use triple
+// //UbType<bool,int,double> t3;
+// //val<1>(t3) = true;
+// //val<2>(t3) = 42;
+// //val<3>(t3) = 0.2;
+//
+// //std::cout << val<1>(t3) << ", ";
+// //std::cout << val<2>(t3) << ", ";
+// //std::cout << val<3>(t3) << std::endl;
+//
+// //t3 = make_tuple(false, 23, 13.13);
+//
+// //std::cout << val<1>(t3) << ", ";
+// //std::cout << val<2>(t3) << ", ";
+// //std::cout << val<3>(t3) << std::endl;
+//
+// //// create and use quadruple
+// //UbType<bool,int,float,double> t4(true,42,13,1.95583);
+// //std::cout << val<4>(t4) << std::endl;
+// //std::cout << t4.v2().v2().v2() << std::endl;
+//
+////typeop.hpp
+//// primary template
+///**********************************
+//* typeop1.hpp:
+//**********************************/
+//template <typename T>
+//class UbTypeOp             // primary template
+//{
+//public:
+//   typedef T         ArgT;
+//   typedef T         BareT;
+//   typedef T const   ConstT;
+//   typedef T &       RefT;
+//   typedef T &       RefBareT;
+//   typedef T const & RefConstT;
+//};
+///**** end of typeop1.hpp ****/
+//
+//// partial specialization for const
+///**********************************
+//* typeop2.hpp:
+//**********************************/
+//template <typename T>
+//class UbTypeOp <T const>   // partial specialization for const types
+//{
+//   public:
+//   typedef T const   ArgT;
+//   typedef T         BareT;
+//   typedef T const   ConstT;
+//   typedef T const & RefT;
+//   typedef T &       RefBareT;
+//   typedef T const & RefConstT;
+//};
+///**** end of typeop2.hpp ****/
+//
+//// partial specialization for references
+///**********************************
+//* typeop3.hpp:
+//**********************************/
+//template <typename T>
+//class UbTypeOp <T&>        // partial specialization for references
+//{
+//public:
+//   typedef T &                         ArgT;
+//   typedef typename UbTypeOp<T>::BareT   BareT;
+//   typedef T const                     ConstT;
+//   typedef T &                         RefT;
+//   typedef typename UbTypeOp<T>::BareT & RefBareT;
+//   typedef T const &                   RefConstT;
+//};
+///**** end of typeop3.hpp ****/
+//
+//// full specialization for void
+///**********************************
+//* typeop4.hpp:
+//**********************************/
+//template<>
+//class UbTypeOp <void>      // full specialization for void
+//{
+//public:
+//   typedef void       ArgT;
+//   typedef void       BareT;
+//   typedef void const ConstT;
+//   typedef void       RefT;
+//   typedef void       RefBareT;
+//   typedef void       RefConstT;
+//};
+///**** end of typeop4.hpp ****/
+//
+////duo1.hpp
+//template <typename T1, typename T2>
+//class UbDuo 
+//{
+//public:
+//   typedef T1 Type1;  // type of first field
+//   typedef T2 Type2;  // type of second field
+//   enum { N = 2 };    // number of fields
+//
+//private:
+//   T1 value1;         // value of first field
+//   T2 value2;         // value of second field
+//
+//public:
+//   // constructors
+//   UbDuo() : value1(), value2() { }
+//   UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b) { }
+//
+//   // for implicit type conversion during construction
+//   template <typename U1, typename U2>
+//   UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) { }
+//
+//   // for implicit type conversion during assignments
+//   template <typename U1, typename U2>
+//   UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d)
+//   {
+//      value1 = d.value1;
+//      value2 = d.value2;
+//      return *this;
+//   }
+//
+//   // field access
+//   T1& v1() { return value1; }
+//   T1 const& v1() const { return value1; }
+//
+//   T2& v2() { return value2; }
+//   T2 const& v2() const { return value2; }
+//};
+//
+//// comparison operators (allow mixed types):
+//template <typename T1, typename T2,
+//typename U1, typename U2>
+//inline bool operator == (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+//{
+//   return d1.v1()==d2.v1() && d1.v2()==d2.v2();
+//}
+//
+//template <typename T1, typename T2,
+//typename U1, typename U2>
+//inline bool operator != (UbDuo<T1,T2> const& d1, UbDuo<U1,U2> const& d2)
+//{
+//   return !(d1==d2);
+//}
+//
+//// convenience function for creation and initialization
+//template <typename T1, typename T2> 
+//inline UbDuo<T1,T2> makeUbDuo(T1 const & a, T2 const & b)
+//{
+//   return UbDuo<T1,T2>(a,b);
+//}
+//
+////duo2.hpp
+//template <typename A, typename B, typename C>
+//class UbDuo<A, UbDuo<B,C> >
+//{
+//public:
+//   typedef A          T1;           // type of first field
+//   typedef UbDuo<B,C> T2;           // type of second field
+//   enum { N = UbDuo<B,C>::N + 1 };  // number of fields
+//
+//private:
+//   T1 value1;         // value of first field
+//   T2 value2;         // value of second field
+//
+//public:
+//   // constructors
+//   UbDuo() : value1(), value2() {}
+//   UbDuo (T1 const & a, T2 const & b) : value1(a), value2(b) { }
+//
+//   // for implicit type conversion during construction
+//   template <typename U1, typename U2>
+//   UbDuo (UbDuo<U1,U2> const & d) : value1(d.v1()), value2(d.v2()) { }
+//
+//   // for implicit type conversion during assignments
+//   template <typename U1, typename U2>
+//   UbDuo<T1, T2>& operator = (UbDuo<U1,U2> const & d) 
+//   {
+//      value1 = d.value1;
+//      value2 = d.value2;
+//      return *this;
+//   }
+//
+//   // field access
+//   T1& v1() { return value1; }
+//   T1 const& v1() const { return value1; }
+//
+//   T2& v2() { return value2; }
+//   T2 const& v2() const { return value2; }
+//};
+//
+////duo3.hpp
+//// primary template for type of Nth field of (duo) T
+//template <int N, typename T>
+//class UbDuoT 
+//{
+//public:
+//   typedef void ResultT;    // in general, the result type is void
+//};
+//
+//// specialization for 1st field of a plain duo
+//template <typename A, typename B>
+//class UbDuoT<1, UbDuo<A,B> > 
+//{
+//public:
+//   typedef A ResultT;
+//};
+//
+//// specialization for 2nd field of a plain duo
+//template <typename A, typename B>
+//class UbDuoT<2, UbDuo<A,B> > 
+//{
+//public:
+//   typedef B ResultT;
+//};
+//
+//// specialization for Nth field of a recursive duo
+//template <int N, typename A, typename B, typename C>
+//class UbDuoT<N, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   typedef typename UbDuoT<N-1, UbDuo<B,C> >::ResultT ResultT;
+//};
+//
+//// specialization for 1st field of a recursive duo
+//template <typename A, typename B, typename C>
+//class UbDuoT<1, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   typedef A ResultT;
+//};
+//
+//// specialization for 2nd field of a recursive duo
+//template <typename A, typename B, typename C>
+//class UbDuoT<2, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   typedef B ResultT;
+//};
+//
+////duo4.hpp
+//// primary template for value of Nth field of (duo) T
+//template <int N, typename T>
+//class UbDuoValue 
+//{
+//public:
+//   static void get(T&) { }       // in general, we have no value
+//   static void get(T const&) { }
+//};
+//
+//// specialization for 1st field of a plain duo
+//template <typename A, typename B>
+//class UbDuoValue<1, UbDuo<A, B> > 
+//{
+//public:
+//   static A& get(UbDuo<A, B> &d) { return d.v1(); }
+//   static A const& get(UbDuo<A, B> const &d) { return d.v1();}
+//};
+//
+//// specialization for 2nd field of a plain duo
+//template <typename A, typename B>
+//class UbDuoValue<2, UbDuo<A, B> > 
+//{
+//public:
+//   static B& get(UbDuo<A, B> &d) 
+//   { 
+//      return d.v2(); 
+//   }
+//   static B const& get(UbDuo<A, B> const &d) { return d.v2(); }
+//};
+//
+//// specialization for Nth field of recursive duo
+//template <int N, typename A, typename B, typename C>
+//struct UbDuoValue<N, UbDuo<A, UbDuo<B,C> > > 
+//{
+//   static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefT
+//   get(UbDuo<A, UbDuo<B,C> > &d) { return UbDuoValue<N-1, UbDuo<B,C> >::get(d.v2()); }
+//
+//   static typename UbTypeOp<typename UbDuoT<N-1, UbDuo<B,C> >::ResultT>::RefConstT
+//   get(UbDuo<A, UbDuo<B,C> > const &d) { return UbDuoValue<N-1, UbDuo<B,C> >::get(d.v2()); }
+//};
+//
+//// specialization for 1st field of recursive duo
+//template <typename A, typename B, typename C>
+//class UbDuoValue<1, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   static A& get(UbDuo<A, UbDuo<B,C> > &d) { return d.v1(); }
+//   static A const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v1(); }
+//};
+//
+//// specialization for 2nd field of recursive duo
+//template <typename A, typename B, typename C>
+//class UbDuoValue<2, UbDuo<A, UbDuo<B,C> > > 
+//{
+//public:
+//   static B& get(UbDuo<A, UbDuo<B,C> > &d) { return d.v2().v1(); }
+//   static B const& get(UbDuo<A, UbDuo<B,C> > const &d) { return d.v2().v1(); }
+//};
+//
+////duo5.hpp
+//// return Nth value of variable duo
+//template <int N, typename A, typename B> 
+//inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefT
+//val(UbDuo<A, B>& d)
+//{
+//   return UbDuoValue<N, UbDuo<A, B> >::get(d);
+//}
+//
+//// return Nth value of constant duo
+//template <int N, typename A, typename B> 
+//inline typename UbTypeOp<typename UbDuoT<N, UbDuo<A, B> >::ResultT>::RefConstT
+//val(UbDuo<A, B> const& d)
+//{
+//   return UbDuoValue<N, UbDuo<A, B> >::get(d);
+//}
+//
+////duo6.hpp
+//// partial specialization for UbDuo<> with only one field
+//template <typename A>
+//struct UbDuo<A,void> 
+//{
+//public:
+//   typedef A    T1;  // type of first field
+//   typedef void T2;  // type of second field
+//   enum { N = 1 };   // number of fields
+//
+//private:
+//   T1 value1;        // value of first field
+//
+//public:
+//   // constructors
+//   UbDuo() : value1() { }
+//   UbDuo (T1 const & a) : value1(a) { }
+//
+//   // field access
+//   T1& v1() { return value1; }
+//   T1 const& v1() const { return value1; }
+//
+//   void v2() { }
+//   void v2() const { }
+//   //...
+//};
+//
+////tuple1.hpp
+//// a helper traits to make the make_tuple functions shorter (Vesa Karvonen's suggestion)
+//struct UbNullT{};
+//
+//// UbType<> in general derives from UbType<> with one more UbNullT
+//template <typename P1,
+//          typename P2 = UbNullT,
+//          typename P3 = UbNullT,
+//          typename P4 = UbNullT,
+//          typename P5 = UbNullT>
+//class UbType : public UbDuo<P1, typename UbType<P2,P3,P4,P5,UbNullT>::BaseT> 
+//{
+//public:
+//   typedef UbDuo<P1, typename UbType<P2,P3,P4,P5,UbNullT>::BaseT> BaseT;
+//
+//   // constructors:
+//   UbType() {}
+//   UbType(typename UbTypeOp<P1>::RefConstT a1,
+//          typename UbTypeOp<P2>::RefConstT a2,
+//          typename UbTypeOp<P3>::RefConstT a3 = UbNullT(),
+//          typename UbTypeOp<P4>::RefConstT a4 = UbNullT(),
+//          typename UbTypeOp<P5>::RefConstT a5 = UbNullT() ) : BaseT(a1, UbType<P2,P3,P4,P5,UbNullT>(a2,a3,a4,a5)) 
+//   {
+//   }
+//};
+//
+//// specialization to end deriving recursion
+//template <typename P1, typename P2>
+//class UbType<P1,P2,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,P2> 
+//{
+//public:
+//   typedef UbDuo<P1,P2> BaseT;
+//   UbType() {}
+//   UbType(typename UbTypeOp<P1>::RefConstT a1,
+//          typename UbTypeOp<P2>::RefConstT a2,
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT() ) : BaseT(a1, a2) 
+//   {
+//   }
+//};
+//
+//// specialization for singletons
+//template <typename P1>
+//class UbType<P1,UbNullT,UbNullT,UbNullT,UbNullT> : public UbDuo<P1,void> 
+//{
+//public:
+//   typedef UbDuo<P1,void> BaseT;
+//   UbType() {}
+//   UbType(typename UbTypeOp<P1>::RefConstT a1,
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT(),
+//          typename UbTypeOp<UbNullT>::RefConstT = UbNullT() ) : BaseT(a1) 
+//   {
+//   }
+//};
+//
+//// convenience function for 1 argument
+//template <typename T1>
+//inline UbType<T1> makeUbTuple(T1 const &a1)
+//{
+//   return UbType<T1>(a1);
+//}
+//
+//// convenience function for 2 arguments
+//template <typename T1, typename T2>
+//inline UbType<T1,T2> makeUbTuple(T1 const &a1, T2 const &a2)
+//{
+//   return UbType<T1,T2>(a1,a2);
+//}
+//
+//// convenience function for 3 arguments
+//template <typename T1, typename T2, typename T3>
+//inline UbType<T1,T2,T3> makeUbTuple(T1 const &a1, T2 const &a2, T3 const &a3)
+//{
+//   return UbType<T1,T2,T3>(a1,a2,a3);
+//}
+//
+//// convenience function for 4 arguments
+//template <typename T1, typename T2, typename T3, typename T4>
+//inline UbType<T1,T2,T3,T4> make_tuple(T1 const &a1, T2 const &a2, T3 const &a3, T4 const &a4)
+//{
+//   return UbType<T1,T2,T3,T4>(a1,a2,a3,a4);
+//}
+//
+//// convenience function for 5 arguments
+//template <typename T1, typename T2, typename T3,
+//typename T4, typename T5>
+//inline UbType<T1,T2,T3,T4,T5> make_tuple(T1 const &a1, T2 const &a2,T3 const &a3, T4 const &a4,T5 const &a5)
+//{
+//   return UbType<T1,T2,T3,T4,T5>(a1,a2,a3,a4,a5);
+//}
+//
+//#endif
+
diff --git a/source/VirtualFluidsCore/Basics/writer/CMakePackage.txt b/source/VirtualFluidsCore/Basics/writer/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1222f87f3fb0a45838379cdf4345e3d11a06e575
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/CMakePackage.txt
@@ -0,0 +1,3 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
+
diff --git a/source/VirtualFluidsCore/Basics/writer/WbCWriterVtkXmlASCII.cpp.bugy b/source/VirtualFluidsCore/Basics/writer/WbCWriterVtkXmlASCII.cpp.bugy
new file mode 100644
index 0000000000000000000000000000000000000000..2edbeeebb81ed1609ac84b6d34f40dc709e567e4
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbCWriterVtkXmlASCII.cpp.bugy
@@ -0,0 +1,896 @@
+#include <basics/writer/WbCWriterVtkXmlASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::pvdEndTag ="   </Collection>\n</VTKFile>";
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   std::string vtkfilename=filename+".pvd";
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+
+   if(vtkfile == NULL)
+   { 
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");	}
+      if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   std::string endian;
+   if(UbSystem::isLittleEndian()) endian = "LittleEndian";
+   else                           endian = "BigEndian";
+   fprintf(vtkfile,"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"%s\" >\n",endian);
+   fputs("   <Collection>\n",vtkfile);
+   
+   int group = 0, part=0;
+   for(std::size_t i=0; i<filenames.size(); i++)
+   {
+	  fprintf(vtkfile,"       <DataSet timestep=\"%g\" group=\"%d\" part=\"%d\" file=\"%s\"/>\n",timeStep,group,part,filenames[i]);
+      if(sepGroups) group++;
+      else          part++;
+   }
+   fprintf(vtkfile,"%s",pvdEndTag.c_str());
+   fclose(vtkfile);
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   std::string vtkfilename=filename;
+   FILE * test;
+   test = fopen(vtkfilename.c_str(), "r");
+
+   if(test == NULL)
+   {
+      vtkfilename += ".pvd";
+      test = fopen(vtkfilename.c_str(), "r");
+      if(test == NULL) return this->writeCollection(filename,filenames,timeStep,sepGroups);
+   }
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "r+");
+   fseek(vtkfile,-(int)pvdEndTag.size()-1,SEEK_END);								
+
+   int group = 0;
+   for(std::size_t i=0; i<filenames.size(); i++)
+   {
+	  fprintf(vtkfile,"       <DataSet timestep=\"%g\" group=\"%d\" part=\"%d\" file=\"%s\"/>\n",timeStep,group,i,filenames[i]);
+      if(sepGroups) group++;
+   }
+   fprintf(vtkfile,"%s",pvdEndTag.c_str());
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeParallelFile(const string& filename,vector<string>& pieceSources, vector<string>& pointDataNames, vector<string>& cellDataNames)
+{
+   string vtkfilename=filename+".pvtu";
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeParallelFile to "<<vtkfilename<<" - start");
+   
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");	}
+      if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //VTK FILE
+   fputs("<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n  <PUnstructuredGrid GhostLevel=\"0\">\n    <PPoints>\n      <PDataArray type=\"Float32\" NumberOfComponents=\"3\"/>\n    </PPoints>\n    <PPointData>\n",vtkfile);
+   for(size_t s=0; s<pointDataNames.size(); s++)
+	   fprintf(vtkfile, "      <PDataArray type=\"Float32\" Name=\"%s\"/>\n", pointDataNames[s]);
+   fputs("    </PPointData>\n",vtkfile);
+   if (cellDataNames.size() > 0)
+   {
+	  fputs("    <PCellData>\n",vtkfile);
+      for(size_t s=0; s<cellDataNames.size(); s++)
+         fprintf(vtkfile, "      <PDataArray type=\"Float32\" Name=\"%s\"/>\n", cellDataNames[s]);
+	  fputs("    </PCellData>\n",vtkfile);
+   }
+
+   for(size_t s=0; s<pieceSources.size(); s++)
+	  fprintf(vtkfile, "    <Piece Source=\"%s\"/>\n", pieceSources[s]);
+   fputs("  </PUnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeParallelFile to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuads to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+      if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n", nofNodes, nofCells);
+
+   //POINTS SECTION
+   fputs("      <Points>\n         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile, "%g %g %g   ", val<1>(nodes[n]),val<2>(nodes[n]), val<3>(nodes[n]));
+   fputs("\n         </DataArray>\n      </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("      <Cells>\n         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fprintf(vtkfile,"%d %d %d %d   ",val<1>(cells[c]),val<2>(cells[c]),val<4>(cells[c]),val<3>(cells[c]));
+   fputs("\n      </DataArray>\n         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n",vtkfile);
+   for(int c=1; c<nofCells+1; c++)
+	   fprintf(vtkfile,"%d ",c*4);
+
+   fputs("\n         </DataArray>\n      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fputs("8 ",vtkfile);
+
+   fputs("\n      </DataArray>\n      </Cells>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuads to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+      if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofCells);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile, "%g %g %g   ", val<1>(nodes[n]),val<2>(nodes[n]), val<3>(nodes[n]));		 
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fprintf(vtkfile,"%d %d %d %d   ",val<1>(cells[c]),val<2>(cells[c]),val<4>(cells[c]),val<3>(cells[c]));
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+   for(int c=1; c<nofCells+1; c++)
+	   fprintf(vtkfile,"%d ",c*4);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fputs("8 ",vtkfile);
+   fputs("\n            </DataArray>\n         </Cells>\n",vtkfile);
+
+   //write data section
+   fputs("         <PointData Scalars=\"Scalars\"> \n",vtkfile);
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\"> \n",datanames[s]);
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+		  fprintf(vtkfile,"%g ",nodedata[s][d]);
+	  fputs("\n          </DataArray>\n",vtkfile);
+    }
+   fputs("         </PointData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+      if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofCells);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fprintf(vtkfile,"%d %d %d %d   ",val<1>(cells[c]),val<2>(cells[c]),val<4>(cells[c]),val<3>(cells[c]));
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+   for(int c=1; c<nofCells+1; c++)
+	   fprintf(vtkfile,"%d ",c*4);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fputs("8 ",vtkfile);
+   fputs("\n            </DataArray>\n         </Cells>\n",vtkfile);
+
+   //write data section
+   fputs("         <CellData Scalars=\"Scalars\"> \n",vtkfile);
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\"> \n",datanames[s]);
+
+      for(int d=0; d<(int)celldata[s].size(); d++)
+		  fprintf(vtkfile,"%g ",celldata[s][d]);
+
+	  fputs("\n          </DataArray>\n",vtkfile);
+   }
+   fputs("         </CellData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbCWriterVtkXmlASCII::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                          vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                          vector< vector< double > >& celldata                                                                       )
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofCells);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fprintf(vtkfile,"%d %d %d %d   ",val<1>(cells[c]),val<2>(cells[c]),val<4>(cells[c]),val<3>(cells[c]));
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+   for(int c=1; c<nofCells+1; c++)
+	   fprintf(vtkfile,"%d ",c*4);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fputs("8 ",vtkfile);
+   fputs("\n            </DataArray>\n         </Cells>\n",vtkfile);
+
+   //write PointData section
+   fputs("         <PointData Scalars=\"PScalars\"> \n",vtkfile);
+   for(int s=0; s<(int)nodedatanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\">\n",nodedatanames[s]);
+
+	   for(int d=0; d<(int)nodedata[s].size(); d++)
+		   fprintf(vtkfile,"%g ",nodedata[s][d]);
+	   
+	   fputs("\n          </DataArray>\n",vtkfile);
+   }
+   fputs("         </PointData>\n",vtkfile);
+
+   //write celldata section
+   fputs("         <CellData Scalars=\"CScalars\"> \n",vtkfile);
+   for(int s=0; s<(int)celldatanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\">\n",celldatanames[s]);
+
+	   for(int d=0; d<(int)celldata[s].size(); d++)
+		   fprintf(vtkfile,"%g ",celldata[s][d]);
+
+	   fputs("\n          </DataArray>\n",vtkfile);
+   }
+   fputs("         </CellData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines) 
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofLines);
+
+   //POINTS SECTION
+   fputs("         <Points>\n         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+
+   fputs("\n         </DataArray>\n      </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("      <Cells>\n         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n",vtkfile);
+
+   for(int c=0; c<nofLines; c++)
+	   fprintf(vtkfile,"%d %d  ",val<1>(lines[c]),val<2>(lines[c]));
+   fputs("\n      </DataArray>\n         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n",vtkfile);
+   for(int c=1; c<=nofLines; c++)
+	   fprintf(vtkfile,"%d ",c*2);
+
+   fputs("\n         </DataArray>\n      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n",vtkfile);
+
+   for(int c=0; c<nofLines; c++)
+	   fputs("3 ",vtkfile);
+   fputs("\n      </DataArray>\n      </Cells>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeLinesWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLinesWithNodeData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofLines);
+
+   //POINTS SECTION
+   fputs("      <Points>\n         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+
+   fputs("\n         </DataArray>\n      </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("      <Cells>\n         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n",vtkfile);
+
+   for(int c=0; c<nofLines; c++)
+	   fprintf(vtkfile,"%d %d  ",val<1>(lines[c]),val<2>(lines[c]));
+   fputs("\n      </DataArray>\n         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n",vtkfile);
+   for(int c=1; c<=nofLines; c++)
+	   fprintf(vtkfile,"%d ",c*2);
+
+   fputs("\n         </DataArray>\n      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n",vtkfile);
+
+   for(int c=0; c<nofLines; c++)
+	   fputs("3 ",vtkfile);
+   fputs("\n      </DataArray>\n      </Cells>\n",vtkfile);
+
+   //write data section
+   fputs("         <PointData Scalars=\"Scalars\"> \n",vtkfile);
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\"> \n",datanames[s]);
+
+	   for(int d=0; d<(int)nodedata[s].size(); d++)
+		   fprintf(vtkfile,"%g ",nodedata[s][d]);
+
+	   fputs("\n          </DataArray>\n",vtkfile);
+   }
+   fputs("         </PointData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLinesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTriangles to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofTriangles= (int)triangles.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofTriangles);
+
+   //POINTS SECTION
+   fputs("      <Points>\n         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+
+   fputs("\n         </DataArray>\n      </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("      <Cells>\n         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n",vtkfile);
+
+   for(int c=0; c<nofTriangles; c++)
+	   fprintf(vtkfile,"%d %d %d  ",val<1>(triangles[c]),val<2>(triangles[c]),val<3>(triangles[c]));
+   fputs("\n      </DataArray>\n         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n",vtkfile);
+   for(int c=1; c<nofTriangles+1; c++)
+	   fprintf(vtkfile,"%d ",c*3);
+
+   fputs("\n         </DataArray>\n      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n",vtkfile);
+
+   for(int c=0; c<nofTriangles; c++)
+	   fputs("5 ",vtkfile);
+   fputs("\n      </DataArray>\n      </Cells>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTriangles to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofCells);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fprintf(vtkfile,"%d %d %d   ",val<1>(cells[c]),val<2>(cells[c]),val<3>(cells[c]));
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+   for(int c=1; c<nofCells+1; c++)
+	   fprintf(vtkfile,"%d ",c*3);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fputs("5 ",vtkfile);
+   fputs("\n            </DataArray>\n         </Cells>\n",vtkfile);
+
+   //write data section
+   fputs("         <PointData Scalars=\"Scalars\"> \n",vtkfile);
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\"> \n",datanames[s]);
+
+	   for(int d=0; d<(int)nodedata[s].size(); d++)
+		   fprintf(vtkfile,"%g ",nodedata[s][d]);
+
+	   fputs("\n          </DataArray>\n",vtkfile);
+   }
+   fputs("         </PointData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeOctsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithCellData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofCells);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fprintf(vtkfile,"%d %d %d %d %d %d %d %d  ",val<1>(cells[c]),val<2>(cells[c]),val<4>(cells[c]),val<3>(cells[c]),val<5>(cells[c]),val<6>(cells[c]),val<8>(cells[c]),val<7>(cells[c]));
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+   for(int c=1; c<nofCells+1; c++)
+	   fprintf(vtkfile,"%d ",c*8);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fputs("11 ",vtkfile);
+   fputs("\n            </DataArray>\n         </Cells>\n",vtkfile);
+
+   //write data section
+   fputs("         <CellData Scalars=\"Scalars\"> \n",vtkfile);
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\"> \n",datanames[s]);
+
+	   for(int d=0; d<(int)celldata[s].size(); d++)
+		   fprintf(vtkfile,"%g ",celldata[s][d]);
+
+	   fputs("\n          </DataArray>\n",vtkfile);
+   }
+   fputs("         </CellData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeOctsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+      if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofCells);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+		fprintf(vtkfile,"%g %g %g ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fprintf(vtkfile,"%d %d %d %d %d %d %d %d  ",val<1>(cells[c]),val<2>(cells[c]),val<4>(cells[c]),val<3>(cells[c]),val<5>(cells[c]),val<6>(cells[c]),val<8>(cells[c]),val<7>(cells[c]));
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+   for(int c=1; c<nofCells+1; c++)
+	   fprintf(vtkfile,"%d ",c*8);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fputs("11 ",vtkfile);
+
+   fputs("\n            </DataArray>\n         </Cells>\n",vtkfile);
+
+   //write PointData section
+   fputs("         <PointData Scalars=\"PScalars\"> \n",vtkfile);
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+       fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\">",datanames[s]);
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      {
+         //out<<base64_encode((unsigned char*)(&nodedata[s][d]),sizeof(float));
+         //out.write((char*)&nodedata[s][d],sizeof(float));
+		  fprintf(vtkfile,"%g ",nodedata[s][d]);
+      }
+	  fputs("</DataArray>\n",vtkfile);
+   }
+   fputs("         </PointData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbCWriterVtkXmlASCII::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOcts to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofCells);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fprintf(vtkfile,"%d %d %d %d %d %d %d %d   ",val<1>(cells[c]),val<2>(cells[c]),val<4>(cells[c]),val<3>(cells[c]),val<5>(cells[c]),val<6>(cells[c]),val<8>(cells[c]),val<7>(cells[c]));
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+   for(int c=1; c<nofCells+1; c++)
+	   fprintf(vtkfile,"%d ",c*8);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofCells; c++)
+	   fputs("11 ",vtkfile);
+
+   fputs("\n            </DataArray>\n         </Cells>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOcts to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbCWriterVtkXmlASCII::writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofNodes);
+
+   //POINTS SECTION
+   fputs("      <Points>\n         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+   fputs("\n         </DataArray>\n      </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("      <Cells>\n         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n",vtkfile);
+
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%d  ",n);
+   fputs("\n      </DataArray>\n         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n",vtkfile);
+
+   for(int n=1; n<=nofNodes; n++)
+	   fprintf(vtkfile,"%d ",n);
+
+   fputs("\n         </DataArray>\n      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n",vtkfile);
+
+   for(int n=0; n<nofNodes; n++)
+	   fputs("1 ",vtkfile);
+
+   fputs("\n      </DataArray>\n      </Cells>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbCWriterVtkXmlASCII::writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofNodes);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofNodes; c++)
+	   fprintf(vtkfile,"%d   ",c);
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=1; c<nofNodes+1; c++)
+	   fprintf(vtkfile,"%d ",c);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int n=0; n<nofNodes; n++)
+	   fputs("1 ",vtkfile);
+
+   fputs("\n            </DataArray>\n         </Cells>\n",vtkfile);
+
+   //write data section
+   fputs("         <PointData Scalars=\"Scalars\"> \n",vtkfile);
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float32\" Name=\"%s\" format=\"ascii\"> \n",datanames[s]);
+
+	   for(int d=0; d<(int)nodedata[s].size(); d++)
+		   fprintf(vtkfile,"%g ",nodedata[s][d]);
+
+	   fputs("\n          </DataArray>\n",vtkfile);
+   }
+   fputs("         </PointData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+
+//////////////////////////////////////////////////////////////////////////
+std::string WbCWriterVtkXmlASCII::writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - start");
+
+   FILE * vtkfile;
+   vtkfile = fopen(vtkfilename.c_str(), "w");
+   if(vtkfile == NULL)
+   { 
+	   string path = UbSystem::getPathFromString(vtkfilename);
+	   if(path.size()>0){UbSystem::makeDirectory(path);vtkfile = fopen(vtkfilename.c_str(), "w");}
+	   if(vtkfile == NULL) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   fprintf(vtkfile,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >\n   <UnstructuredGrid>\n      <Piece NumberOfPoints=\"%d\"	NumberOfCells=\"%d\">   \n",nofNodes,nofNodes);
+
+   //POINTS SECTION
+   fputs("         <Points>\n            <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">\n               ",vtkfile);
+   for(int n=0; n<nofNodes; n++)
+	   fprintf(vtkfile,"%g %g %g   ",val<1>(nodes[n]),val<2>(nodes[n]),val<3>(nodes[n]));
+   fputs("\n            </DataArray>\n         </Points>\n",vtkfile);
+
+   //CELLS SECTION
+   fputs("         <Cells>\n            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofNodes; c++)
+	   fprintf(vtkfile,"%d   ",c);
+   fputs("\n            </DataArray>\n            <DataArray type=\"Int64\" Name=\"offsets\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=1; c<nofNodes+1; c++)
+	   fprintf(vtkfile,"%d ",c);
+
+   fputs("\n            </DataArray>\n            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ",vtkfile);
+
+   for(int c=0; c<nofNodes; c++)
+	   fputs("1 ",vtkfile);
+
+   fputs("\n            </DataArray>\n         </Cells>\n",vtkfile);
+
+   //write data section
+   fputs("         <PointData Scalars=\"Scalars\"> \n",vtkfile);
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+	   fprintf(vtkfile,"           <DataArray type=\"Float64\" Name=\"%s\" format=\"ascii\"> \n",datanames[s]);
+
+	   for(int d=0; d<(int)nodedata[s].size(); d++)
+		   fprintf(vtkfile,"%g ",nodedata[s][d]);
+
+	   fputs("\n          </DataArray>\n",vtkfile);
+   }
+   fputs("         </PointData>\n      </Piece>\n   </UnstructuredGrid>\n</VTKFile>\n",vtkfile);
+   fclose(vtkfile);
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
diff --git a/source/VirtualFluidsCore/Basics/writer/WbCWriterVtkXmlASCII.h.bugy b/source/VirtualFluidsCore/Basics/writer/WbCWriterVtkXmlASCII.h.bugy
new file mode 100644
index 0000000000000000000000000000000000000000..5e413892366d219098dbcfd2620d669c56a356c7
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbCWriterVtkXmlASCII.h.bugy
@@ -0,0 +1,101 @@
+#ifndef WBCWRITERVTKXMLASCII_H
+#define WBWCRITERVTKXMLASCII_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+//#include <boost/serialization/base_object.hpp>
+
+class WbCWriterVtkXmlASCII  : public WbWriter
+{
+public:
+	OBCREATOR_EXT( WbCWriterVtkXmlASCII )
+
+		static WbCWriterVtkXmlASCII* getInstance()
+	{
+		static WbCWriterVtkXmlASCII instance;
+		return &instance;
+	}
+private:
+	WbCWriterVtkXmlASCII() : WbWriter() 
+	{
+		if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+		if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+		if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+	}
+	WbCWriterVtkXmlASCII( const WbCWriterVtkXmlASCII& );                  //no copy allowed 
+	const WbCWriterVtkXmlASCII& operator=( const WbCWriterVtkXmlASCII& ); //no copy allowed
+
+	static std::string  pvdEndTag;
+
+public:
+	std::string getFileExtension()  { return ".ascii.vtu"; }
+
+	//write a metafile 
+	std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timesteps, const bool& sepGroups);//std::vector<double>& groups, std::vector<double>& parts);
+	std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+	std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames);
+
+	//////////////////////////////////////////////////////////////////////////
+	//nodes
+	std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes);
+	std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+	std::string writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+	//////////////////////////////////////////////////////////////////////////
+	//lines
+	//     0 ---- 1
+	//nodenumbering must start with 0!
+	std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+	std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+	//////////////////////////////////////////////////////////////////////////
+	//triangles
+	//                    2
+	//                     
+	//                  0---1
+	//nodenumbering must start with 0!
+	std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+	std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+	//////////////////////////////////////////////////////////////////////////
+	//2D
+	//cell numbering:
+	//                  3---2
+	//                  |   |
+	//                  0---1
+	//nodenumbering must start with 0!
+
+	std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+	std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+	std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+	std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+		std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+		std::vector< std::vector< double > >& celldata                                                                       );
+
+	//////////////////////////////////////////////////////////////////////////
+	//octs
+	//     7 ---- 6
+	//    /|     /|
+	//   4 +--- 5 |
+	//   | |    | |
+	//   | 3 ---+ 2
+	//   |/     |/
+	//   0 ---- 1
+	std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+	std::string writeOctsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+	std::string writeOctsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+	//private:
+	//   friend class boost::serialization::access;
+	//   template<class Archive>
+	//   void serialize(Archive & ar, const unsigned int version)
+	//   {
+	//      ar & boost::serialization::base_object<WbWriter>(*this);
+	//   }
+};
+
+//UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbCWriterVtkXmlASCII ,WbWriter>::getInstance()), CAB_WbWriterVtkXmlASCII);
+
+#endif //WBWRITERVTKXMLASCII_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriter.h b/source/VirtualFluidsCore/Basics/writer/WbWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..77869d11876747e42811a0c0659233804353a5a0
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriter.h
@@ -0,0 +1,183 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITER_H
+#define WBWRITER_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+
+#include <vector>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <map>
+
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbPointerWrapper.h>
+#include <basics/utilities/UbAutoRun.hpp>
+#include <basics/objects/ObFactory.h>
+
+#include <boost/serialization/serialization.hpp>
+
+class WbWriter
+{
+public:
+   OBCREATOR_EXT(WbWriter)
+
+   //////////////////////////////////////////////////////////////////////////
+   virtual ~WbWriter() 
+   {
+
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //rein virtuelle Methoden
+   virtual std::string getFileExtension() = 0;
+
+   //////////////////////////////////////////////////////////////////////////
+   //nodes
+   virtual std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   virtual std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                     2
+   //                      
+   //                  0 === 1
+   //nodenumbering must start with 0!
+   virtual std::string writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+   //////////////////////////////////////////////////////////////////////////
+   //quads
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   virtual std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                                     std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                                     std::vector< std::vector< double > >& celldata                                                                                       ){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   virtual std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+   virtual std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata){ throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() );  }
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+
+   }
+};
+
+
+#ifdef CAB_RCF
+//serialize von singletons muss hier etwas anders erfolgen ;-)
+template<class Archive>
+inline bool serializeWbWriter(Archive &ar, WbWriter*& writer)
+{
+   std::string writerID;
+
+   if( ArchiveTools::isReading(ar) )
+   {                                                                  
+      ar & writerID;
+      if(writerID!="no_WbWriter") writer = ObFactory<WbWriter>::getInstance()->createObject(writerID);
+      else                        writer = NULL;
+   }                                                                  
+   else /* if (ar.isWrite())) if(Archive::is_saving())*/                                      
+   {                                                                   
+      if(writer) writerID = writer->getClassObjectTypeID(); 
+      else       writerID = "no_WbWriter";
+      ar & writerID;
+   } 
+   return true;
+}
+//////////////////
+template<class Archive, class STL_container>
+inline bool serializeWbWriter(Archive &ar, STL_container& writers)
+{
+   int       nofCounter;
+   std::string    writerID;
+   WbWriter* dummy;
+
+   if( ArchiveTools::isReading(ar) )
+   {                                                                  
+      ar & nofCounter;
+      for(int i=0; i<nofCounter; i++)
+      {
+         serializeWbWriter(ar, dummy);
+         writers.push_back(dummy);
+      }
+   }                                                                  
+   else                                 
+   {                                                                   
+      nofCounter = (int)writers.size();
+      ar & nofCounter;
+      typename STL_container::iterator pos;
+      for(pos=writers.begin(); pos!=writers.end(); ++pos)
+         serializeWbWriter(ar, *pos);
+   }                                                                   
+
+   return true;
+}
+//////////////////////////////////////////////////////////////////////////
+// Spezialisierung des UbPointerWrappers fuer WbWriter... 
+// da man bei singletons keine serializemethode einbauen kann...
+template< >
+class UbPointerWrapper< WbWriter > 
+{
+public:
+   UbPointerWrapper() : pointer(NULL) {}
+
+   UbPointerWrapper(WbWriter* pointer) : pointer(pointer) {}
+
+   WbWriter* get() { return pointer; }
+
+   template<class Archive>
+   void serialize(Archive& ar, const unsigned int version) 
+   {
+      serializeWbWriter(ar, pointer);
+   }
+
+private:
+   WbWriter* pointer;
+};
+
+
+#endif //CAB_RCF
+
+
+#endif //WBWRITER_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterAvsASCII.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterAvsASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a9616fd73b6ee250b1e11ac266d8bea77e478b2
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterAvsASCII.cpp
@@ -0,0 +1,896 @@
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+std::string WbWriterAvsASCII::writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuads to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+avsfilename);
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuads to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOcts to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden "+avsfilename);
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 7; //=hex
+   int nofNodesPerCell = 8; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOcts to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithNodeData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write UCD File "+avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)datanames.size();
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) 
+      { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithNodeData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithCellData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File  "+avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = (int)datanames.size();
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   fdummy=0.0;
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //CELL DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofCellData-1; ++d) { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofCellData-1].c_str()); 
+
+   for(int d=0; d<nofCellData-1; ++d) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofCellData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofCellData; ++d)
+      for(int n=0; n<(int)celldata[d].size(); n++)
+         { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithCellData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames, vector< vector< double > >& celldata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithNodeAndCellData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File  "+avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)nodedatanames.size();
+   int nofCellData     = (int)celldatanames.size();
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char nodelabels[1024];
+   char nodeunits[1024];
+   strcpy(nodelabels, "");
+   strcpy(nodeunits, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) { strcat(nodelabels, nodedatanames[d].c_str() ); strcat(nodelabels,"."); }
+   strcat(nodelabels, nodedatanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(nodeunits, "no_unit.");
+   strcat(nodeunits, "no_unit");
+
+   out.write((char*)&nodelabels,sizeof(nodelabels));
+   out.write((char*)&nodeunits,sizeof(nodeunits));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //CELL DATA
+   char celllabels[1024];
+   char cellunits[1024];
+   strcpy(celllabels, "");
+   strcpy(cellunits, "");
+
+   for(int d=0; d<nofCellData-1; ++d) { strcat(celllabels, celldatanames[d].c_str() ); strcat(celllabels,"."); }
+   strcat(celllabels, celldatanames[nofCellData-1].c_str()); 
+
+   for(int d=0; d<nofCellData-1; ++d) strcat(cellunits, "no_unit.");
+   strcat(cellunits, "no_unit");
+
+   out.write((char*)&celllabels,sizeof(celllabels));
+   out.write((char*)&cellunits,sizeof(cellunits));
+
+   //nof and type of data
+   idummy = nofCellData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofCellData; ++d)
+      for(int n=0; n<(int)celldata[d].size(); n++)
+      { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeQuadsWithNodeAndCellData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeLines to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+   
+   out<<"# UCD-File created by WbWriterAvsASCII\n";
+   out<<nofNodes<<" "<<nofLines<<" 0 0 0 "<<endl;
+
+   for(int n=0; n<nofNodes; n++)
+      out<<n+1<<" "<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n])<<" \n";
+
+   for(int l=0; l<nofLines; l++)
+       out<<l+1<<" 2 line "<< val<1>(lines[l])+1 <<" "<< val<2>(lines[l])+1 <<" "<<endl;
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeLines to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeTriangles to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out);}
+      if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden "+avsfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofTrian = (int)triangles.size(); 
+
+   out<<"# UCD-File created by WbWriterAvsASCII\n";
+   out<<nofNodes<<" "<<nofTrian<<" 0 0 0 "<<endl;
+
+   for(int n=0; n<nofNodes; n++)
+   out<<n+1<<" "<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n])<<" \n";
+
+   for(int l=0; l<nofTrian; l++)
+   out<<l+1<<" 2 tri "<< val<1>(triangles[l])+1 <<" "<< val<2>(triangles[l])+1 <<" "<< val<3>(triangles[l])+1 <<" "<<endl;
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeTriangles to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeTrianglesWithNodeData to "<<avsfilename<<" - end");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File "+avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)datanames.size();
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 2; //triangle
+   int nofNodesPerCell = 3; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) 
+   { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+      fdummy = 1.;
+      for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsASCII::writeTrianglesWithNodeData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata)
+{
+    string avsfilename = filename+getFileExtension();
+    UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOctsWithCellData to "<<avsfilename<<" - start");
+
+    ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+    if(!out)
+    { 
+       out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+       string path = UbSystem::getPathFromString(avsfilename);
+       if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+       if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden "+avsfilename);
+    }
+
+    char magic = (char)7;
+    int   idummy;
+    float fdummy;
+
+    int nofNodes = (int)nodes.size();
+    int nofCells = (int)cells.size();
+
+    int nofNodeData     = 0;
+    int nofCellData     = (int)datanames.size();
+    int nofModelData    = 0;
+    int cellType        = 7; //=hex
+    int nofNodesPerCell = 8; 
+
+    out.write((char*)&magic,sizeof(char));      
+    out.write((char*)&nofNodes,sizeof(int));    
+    out.write((char*)&nofCells,sizeof(int));    
+    out.write((char*)&nofNodeData,sizeof(int)); 
+    out.write((char*)&nofCellData,sizeof(int)); 
+    out.write((char*)&nofModelData,sizeof(int));
+
+    idummy = (int)nofCells*nofNodesPerCell;
+    out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+       idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+       idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+       idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+    }
+    //knotennummern der einzelnen zellen
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+    }
+
+    //coords
+    //x1-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x2-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x3-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //out<<"\n";
+
+    //CELL DATA
+    char labels[1024];
+    char units[1024];
+    strcpy(labels, "");
+    strcpy(units, "");
+
+    for(int d=0; d<nofCellData-1; ++d) { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+    strcat(labels, datanames[nofCellData-1].c_str()); 
+
+    for(int d=0; d<nofCellData-1; ++d) strcat(units, "no_unit.");
+    strcat(units, "no_unit");
+
+    out.write((char*)&labels,sizeof(labels));
+    out.write((char*)&units,sizeof(units));
+
+    //nof and type of data
+    idummy = nofCellData;
+    out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+    idummy = 1;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+    //min and max of data
+    fdummy = 0.0;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+    fdummy = 1.0;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    //daten ins file schreiben
+    for(int d=0; d<nofCellData; ++d)
+    for(int n=0; n<(int)celldata[d].size(); n++)
+    { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+    fdummy = 1.;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    out.close(); 
+    UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOctsWithCellData to "<<avsfilename<<" - end");
+
+    return avsfilename;
+ }
+/*===============================================================================*/
+std::string WbWriterAvsASCII::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+    string avsfilename = filename+getFileExtension();
+    UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOctsWithNodeData to "<<avsfilename<<" - start");
+
+    ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+    if(!out)
+    { 
+       out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+       string path = UbSystem::getPathFromString(avsfilename);
+       if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+       if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden "+avsfilename);
+    }
+
+    if((int)nodedata.size()==0) throw UbException(UB_EXARGS,"no nodedata!!!");
+    if(nodes.size()!=nodedata[0].size()) throw UbException(UB_EXARGS,"nodedata != nofNodes!!!");
+
+    char magic = (char)7;
+    int   idummy;
+    float fdummy;
+
+    int nofNodes = (int)nodes.size();
+    int nofCells = (int)cells.size();
+
+    int nofNodeData     = (int)datanames.size();
+    int nofCellData     = 0;
+    int nofModelData    = 0;
+    int cellType        = 7; //=hex
+    int nofNodesPerCell = 8; 
+
+    out.write((char*)&magic,sizeof(char));      
+    out.write((char*)&nofNodes,sizeof(int));    
+    out.write((char*)&nofCells,sizeof(int));    
+    out.write((char*)&nofNodeData,sizeof(int)); 
+    out.write((char*)&nofCellData,sizeof(int)); 
+    out.write((char*)&nofModelData,sizeof(int));
+
+    idummy = (int)nofCells*nofNodesPerCell;
+    out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+       idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+       idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+       idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+    }
+    //knotennummern der einzelnen zellen
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+    }
+
+    //coords
+    //x1-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x2-coords
+    for(int n=0; n<nofNodes; n++)
+       { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x3-coords
+    for(int n=0; n<nofNodes; n++)
+       { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+
+    //NODE DATA
+    char labels[1024];
+    char units[1024];
+    strcpy(labels, "");
+    strcpy(units, "");
+
+    for(int d=0; d<nofNodeData-1; ++d) 
+    { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+    strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+    for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+    strcat(units, "no_unit");
+
+    out.write((char*)&labels,sizeof(labels));
+    out.write((char*)&units,sizeof(units));
+
+    //nof and type of data
+    idummy = nofNodeData;
+    out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+    idummy = 1;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+    //min and max of data
+    fdummy = 0.0;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+    fdummy = 1.0;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    //daten ins file schreiben
+    for(int d=0; d<nofNodeData; ++d)
+       for(int n=0; n<(int)nodedata[d].size(); n++)
+       { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+    fdummy = 1.;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    out.close(); 
+    UBLOG(logDEBUG1,"WbWriterAvsASCII::writeOctsWithNodeData to "<<avsfilename<<" - end");
+
+    return avsfilename;
+ }
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterAvsASCII.h b/source/VirtualFluidsCore/Basics/writer/WbWriterAvsASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c65e1683d3de61a6322be303be76bdfd7f5a677
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterAvsASCII.h
@@ -0,0 +1,76 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITERAVSASCII_H
+#define WBWRITERAVSASCII_H
+
+#include <basics/writer/WbWriter.h>
+      
+class WbWriterAvsASCII : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterAvsASCII )
+
+   static WbWriterAvsASCII* getInstance()
+   {
+      static WbWriterAvsASCII instance;
+      return &instance;
+   }
+
+private:
+   WbWriterAvsASCII() : WbWriter() {}                            
+   WbWriterAvsASCII( const WbWriterAvsASCII& );                  //no copy allowed 
+   const WbWriterAvsASCII& operator=( const WbWriterAvsASCII& ); //no copy allowed
+
+public:
+   std::string getFileExtension() { return ".ascii.inp"; }
+   
+   ///////////////////virtual std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells) = 0;
+   ///////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                    2
+   //                       
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTuple<int,int,int> >& triangles);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //quads
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames, std::vector< std::vector< double > >& celldata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector< std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector< std::vector<double > >& nodedata);
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterAvsASCII ,WbWriter>::getInstance()), CAB_WbWriterAvsASCII);
+
+#endif //WBWRITERAVSASCII_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterAvsBinary.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterAvsBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..34d1d3415cf6ca738b0343b334a9d158d783012a
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterAvsBinary.cpp
@@ -0,0 +1,975 @@
+#include <basics/writer/WbWriterAvsBinary.h>
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+std::string WbWriterAvsBinary::writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeLines to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary); }
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)lines.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 1; //line
+   int nofNodesPerCell = 2; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(lines[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(lines[c])+1; out.write((char*)&idummy,sizeof(int)); 
+     
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   fdummy=0.0;
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeLines to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTuple<int,int,int> >& triangles)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeTriangles to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)triangles.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 2; //triangle
+   int nofNodesPerCell = 3; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(triangles[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(triangles[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(triangles[c])+1; out.write((char*)&idummy,sizeof(int)); 
+
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   fdummy=0.0;
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeTriangles to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuads to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+  
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuads to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOcts to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 7; //=hex
+   int nofNodesPerCell = 8; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+   { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOcts to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeTrianglesWithNodeData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File "+avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)datanames.size();
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 2; //triangle
+   int nofNodesPerCell = 3; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) 
+      { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeTrianglesWithNodeData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithNodeData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"write_OutputFile-UCD File "+avsfilename+" konnte nicht geschrieben werden");
+   }
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)datanames.size();
+   int nofCellData     = 0;
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) 
+      { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithNodeData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithCellData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = 0;
+   int nofCellData     = (int)datanames.size();
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   fdummy=0.0;
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //CELL DATA
+   char labels[1024];
+   char units[1024];
+   strcpy(labels, "");
+   strcpy(units, "");
+
+   for(int d=0; d<nofCellData-1; ++d) { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+   strcat(labels, datanames[nofCellData-1].c_str()); 
+
+   for(int d=0; d<nofCellData-1; ++d) strcat(units, "no_unit.");
+   strcat(units, "no_unit");
+
+   out.write((char*)&labels,sizeof(labels));
+   out.write((char*)&units,sizeof(units));
+
+   //nof and type of data
+   idummy = nofCellData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofCellData; ++d)
+      for(int n=0; n<(int)celldata[d].size(); n++)
+         { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithCellData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames, vector< vector< double > >& celldata)
+{
+   string avsfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithNodeAndCellData to "<<avsfilename<<" - start");
+
+   ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+      string path = UbSystem::getPathFromString(avsfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,avsfilename+" konnte nicht geschrieben werden");
+   }
+
+   char magic = (char)7;
+   int   idummy;
+   float fdummy;
+
+   int nofNodes = (int)nodes.size();
+   int nofCells = (int)cells.size();
+
+   int nofNodeData     = (int)nodedatanames.size();
+   int nofCellData     = (int)celldatanames.size();
+   int nofModelData    = 0;
+   int cellType        = 3; //=quad
+   int nofNodesPerCell = 4; 
+
+   out.write((char*)&magic,sizeof(char));      
+   out.write((char*)&nofNodes,sizeof(int));    
+   out.write((char*)&nofCells,sizeof(int));    
+   out.write((char*)&nofNodeData,sizeof(int)); 
+   out.write((char*)&nofCellData,sizeof(int)); 
+   out.write((char*)&nofModelData,sizeof(int));
+
+   idummy = (int)nofCells*nofNodesPerCell;
+   out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+      idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+      idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+      idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+   }
+   //knotennummern der einzelnen zellen
+   for(int c=0; c<nofCells; c++)
+   {
+      idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+      idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+   }
+
+   //coords
+   //x1-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x2-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //x3-coords
+   for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+   //out<<"\n";
+
+   //NODE DATA
+   char nodelabels[1024];
+   char nodeunits[1024];
+   strcpy(nodelabels, "");
+   strcpy(nodeunits, "");
+
+   for(int d=0; d<nofNodeData-1; ++d) { strcat(nodelabels, nodedatanames[d].c_str() ); strcat(nodelabels,"."); }
+   strcat(nodelabels, nodedatanames[nofNodeData-1].c_str()); 
+
+   for(int i=0;i<(nofNodeData-1);i++) strcat(nodeunits, "no_unit.");
+   strcat(nodeunits, "no_unit");
+
+   out.write((char*)&nodelabels,sizeof(nodelabels));
+   out.write((char*)&nodeunits,sizeof(nodeunits));
+
+   //nof and type of data
+   idummy = nofNodeData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofNodeData; ++d)
+      for(int n=0; n<(int)nodedata[d].size(); n++)
+      { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //CELL DATA
+   char celllabels[1024];
+   char cellunits[1024];
+   strcpy(celllabels, "");
+   strcpy(cellunits, "");
+
+   for(int d=0; d<nofCellData-1; ++d) { strcat(celllabels, celldatanames[d].c_str() ); strcat(celllabels,"."); }
+   strcat(celllabels, celldatanames[nofCellData-1].c_str()); 
+
+   for(int d=0; d<nofCellData-1; ++d) strcat(cellunits, "no_unit.");
+   strcat(cellunits, "no_unit");
+
+   out.write((char*)&celllabels,sizeof(celllabels));
+   out.write((char*)&cellunits,sizeof(cellunits));
+
+   //nof and type of data
+   idummy = nofCellData;
+   out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+   idummy = 1;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+   //min and max of data
+   fdummy = 0.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+   fdummy = 1.0;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   //daten ins file schreiben
+   for(int d=0; d<nofCellData; ++d)
+      for(int n=0; n<(int)celldata[d].size(); n++)
+      { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+   fdummy = 1.;
+   for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+   out.close(); 
+   UBLOG(logDEBUG1,"WbWriterAvsBinary::writeQuadsWithNodeAndCellData to "<<avsfilename<<" - end");
+
+   return avsfilename;
+}
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata)
+{
+    string avsfilename = filename+getFileExtension();
+    UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOctsWithCellData to "<<avsfilename<<" - start");
+
+    ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+    if(!out)
+    { 
+       out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+       string path = UbSystem::getPathFromString(avsfilename);
+       if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+       if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden");
+    }
+
+    char magic = (char)7;
+    int   idummy;
+    float fdummy;
+
+    int nofNodes = (int)nodes.size();
+    int nofCells = (int)cells.size();
+
+    int nofNodeData     = 0;
+    int nofCellData     = (int)datanames.size();
+    int nofModelData    = 0;
+    int cellType        = 7; //=hex
+    int nofNodesPerCell = 8; 
+
+    out.write((char*)&magic,sizeof(char));      
+    out.write((char*)&nofNodes,sizeof(int));    
+    out.write((char*)&nofCells,sizeof(int));    
+    out.write((char*)&nofNodeData,sizeof(int)); 
+    out.write((char*)&nofCellData,sizeof(int)); 
+    out.write((char*)&nofModelData,sizeof(int));
+
+    idummy = (int)nofCells*nofNodesPerCell;
+    out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+       idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+       idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+       idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+    }
+    //knotennummern der einzelnen zellen
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+    }
+
+    //coords
+    //x1-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x2-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x3-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //out<<"\n";
+
+    //CELL DATA
+    char labels[1024];
+    char units[1024];
+    strcpy(labels, "");
+    strcpy(units, "");
+
+    for(int d=0; d<nofCellData-1; ++d) { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+    strcat(labels, datanames[nofCellData-1].c_str()); 
+
+    for(int d=0; d<nofCellData-1; ++d) strcat(units, "no_unit.");
+    strcat(units, "no_unit");
+
+    out.write((char*)&labels,sizeof(labels));
+    out.write((char*)&units,sizeof(units));
+
+    //nof and type of data
+    idummy = nofCellData;
+    out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+    idummy = 1;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+    //min and max of data
+    fdummy = 0.0;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+    fdummy = 1.0;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    //daten ins file schreiben
+    for(int d=0; d<nofCellData; ++d)
+    for(int n=0; n<(int)celldata[d].size(); n++)
+    { fdummy=(float)celldata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+    fdummy = 1.;
+    for(int i=0;i<nofCellData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    out.close(); 
+    UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOctsWithCellData to "<<avsfilename<<" - end");
+
+    return avsfilename;
+ }
+/*===============================================================================*/
+std::string WbWriterAvsBinary::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+    string avsfilename = filename+getFileExtension();
+    UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOctsWithNodeData to "<<avsfilename<<" - start");
+
+    ofstream out(avsfilename.c_str(),ios::out|ios::binary);
+    if(!out)
+    { 
+       out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!outfile) weiterhin true!!!
+       string path = UbSystem::getPathFromString(avsfilename);
+       if(path.size()>0){UbSystem::makeDirectory(path);out.open(avsfilename.c_str(),ios::out|ios::binary);}
+       if(!out) throw UbException(UB_EXARGS,"file konnte nicht geschrieben werden");
+    }
+
+    if((int)nodedata.size()==0) throw UbException(UB_EXARGS,"no nodedata!!!");
+    if(nodes.size()!=nodedata[0].size()) throw UbException(UB_EXARGS,"nodedata != nofNodes!!!");
+
+    char magic = (char)7;
+    int   idummy;
+    float fdummy;
+
+    int nofNodes = (int)nodes.size();
+    int nofCells = (int)cells.size();
+
+    int nofNodeData     = (int)datanames.size();
+    int nofCellData     = 0;
+    int nofModelData    = 0;
+    int cellType        = 7; //=hex
+    int nofNodesPerCell = 8; 
+
+    out.write((char*)&magic,sizeof(char));      
+    out.write((char*)&nofNodes,sizeof(int));    
+    out.write((char*)&nofCells,sizeof(int));    
+    out.write((char*)&nofNodeData,sizeof(int)); 
+    out.write((char*)&nofCellData,sizeof(int)); 
+    out.write((char*)&nofModelData,sizeof(int));
+
+    idummy = (int)nofCells*nofNodesPerCell;
+    out.write((char*)&idummy,sizeof(int)); //(nof nodes) * (nodes per cell)
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy=c+1;             out.write((char*)&idummy,sizeof(int)); //cell id
+       idummy=1;               out.write((char*)&idummy,sizeof(int)); //mat
+       idummy=nofNodesPerCell; out.write((char*)&idummy,sizeof(int)); //nodes per cell
+       idummy=cellType;        out.write((char*)&idummy,sizeof(int)); //cell type 
+    }
+    //knotennummern der einzelnen zellen
+    for(int c=0; c<nofCells; c++)
+    {
+       idummy = val<1>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<2>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<3>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<4>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<5>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<6>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<7>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+       idummy = val<8>(cells[c])+1; out.write((char*)&idummy,sizeof(int)); 
+    }
+
+    //coords
+    //x1-coords
+    for(int n=0; n<nofNodes; n++)
+      { fdummy = (float)( val<1>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x2-coords
+    for(int n=0; n<nofNodes; n++)
+       { fdummy = (float)( val<2>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+    //x3-coords
+    for(int n=0; n<nofNodes; n++)
+       { fdummy = (float)( val<3>(nodes[n]) ); out.write((char*)&fdummy ,sizeof(float)); }
+
+    //NODE DATA
+    char labels[1024];
+    char units[1024];
+    strcpy(labels, "");
+    strcpy(units, "");
+
+    for(int d=0; d<nofNodeData-1; ++d) 
+    { strcat(labels, datanames[d].c_str() ); strcat(labels,"."); }
+    strcat(labels, datanames[nofNodeData-1].c_str()); 
+
+    for(int i=0;i<(nofNodeData-1);i++) strcat(units, "no_unit.");
+    strcat(units, "no_unit");
+
+    out.write((char*)&labels,sizeof(labels));
+    out.write((char*)&units,sizeof(units));
+
+    //nof and type of data
+    idummy = nofNodeData;
+    out.write((char*)&idummy,sizeof(int)); //Datentypen pro knoten (hier = nof_node_data, da NUR skalare)
+
+    idummy = 1;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&idummy,sizeof(int)); //jeder Datentyp ist ein skalarer Wert
+
+    //min and max of data
+    fdummy = 0.0;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //min Wert pro Datentyp
+    fdummy = 1.0;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    //daten ins file schreiben
+    for(int d=0; d<nofNodeData; ++d)
+       for(int n=0; n<(int)nodedata[d].size(); n++)
+       { fdummy=(float)nodedata[d][n]; out.write((char*)&fdummy,sizeof(float)); }
+
+    fdummy = 1.;
+    for(int i=0;i<nofNodeData;i++) out.write((char*)&fdummy,sizeof(float)); //max Wert pro Datentyp
+
+    out.close(); 
+    UBLOG(logDEBUG1,"WbWriterAvsBinary::writeOctsWithNodeData to "<<avsfilename<<" - end");
+
+    return avsfilename;
+ }
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterAvsBinary.h b/source/VirtualFluidsCore/Basics/writer/WbWriterAvsBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..39a5019e92568ea529aacb257253fc5274a4ae2e
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterAvsBinary.h
@@ -0,0 +1,74 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITERAVSBINARY_H
+#define WBWRITERAVSBINARY_H
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterAvsBinary : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterAvsBinary )
+
+   static WbWriterAvsBinary* getInstance()
+   {
+      static WbWriterAvsBinary instance;
+      return &instance;
+   }
+private:
+   WbWriterAvsBinary() : WbWriter() {}                             
+   WbWriterAvsBinary( const WbWriterAvsBinary& );                  //no copy allowed 
+   const WbWriterAvsBinary& operator=( const WbWriterAvsBinary& ); //no copy allowed
+
+public:
+   std::string getFileExtension() { return ".bin.inp"; }
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                    2
+   //                      
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTuple<int,int,int> >& triangles);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   
+   //////////////////////////////////////////////////////////////////////////
+   //quads
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename, std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames, std::vector< std::vector< double > >& celldata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector< std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector< std::vector<double > >& nodedata);
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterAvsBinary ,WbWriter>::getInstance()), CAB_WbWriterAvsBinary);
+
+#endif //WBWRITERAVSBINARY_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterBOBJ.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterBOBJ.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..20b1774de592e73bd0bb95d52cffeeacd1431345
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterBOBJ.cpp
@@ -0,0 +1,79 @@
+#ifdef CAB_ZLIB
+   #include <basics/writer/WbWriterBOBJ.h>
+   #include <basics/utilities/UbLogger.h>
+   #include <cstring>
+
+   #include <zlib.h>
+
+
+   using namespace std;
+   /*===============================================================================*/
+   std::string WbWriterBOBJ::writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles)
+   {
+      string bobjFilename=filename+getFileExtension();
+      UBLOG(logDEBUG1,"WbWriterBOBJ::writeTriangles to "<<bobjFilename<<" - start");
+
+      gzFile gzf = gzopen( bobjFilename.c_str(), "wb1" );
+      
+      size_t nofNodes     = nodes.size(); 
+      size_t nofTriangles = triangles.size(); 
+
+      //write to file
+      size_t numVerts;
+      //double v[3];
+      if(sizeof(numVerts)!=4) { throw UbException(UB_EXARGS,"danger..."); }
+      numVerts = nofNodes;
+      gzwrite(gzf, &numVerts, sizeof(numVerts));
+
+      for(size_t k=0; k<nofNodes; k++) {
+         float vertp = val<1>(nodes[k]);
+         gzwrite(gzf, &vertp, sizeof(vertp));
+         vertp       = val<2>(nodes[k]);
+         gzwrite(gzf, &vertp, sizeof(vertp));
+         vertp       = val<3>(nodes[k]);
+         gzwrite(gzf, &vertp, sizeof(vertp));
+      }
+
+      //NORMAL VECTOR
+      //double n[3];
+      gzwrite(gzf, &numVerts, sizeof(numVerts));
+      for(size_t k=0; k<nofNodes; k++) {
+         //poly->GetPointData()->GetNormals()->GetTuple(k, n);
+         float normp = 0.0;//n[0];
+         gzwrite(gzf, &normp, sizeof(normp));
+         normp = 0.0;//n[1];
+         gzwrite(gzf, &normp, sizeof(normp));
+         normp = 0.0;//n[2];
+         gzwrite(gzf, &normp, sizeof(normp));
+      }
+
+      //vtkIdType npts = 3;
+      //vtkIdType* pts;
+      size_t numTris = nofTriangles;
+      gzwrite(gzf, &numTris, sizeof(numTris));
+      for(size_t k=0; k<nofTriangles/*(size_t)poly->GetNumberOfPolys()*/; k++) {
+         //poly->GetPolys()->GetNextCell(npts, pts);
+         //int triIndex = *pts;
+         //gzwrite(gzf, &triIndex, sizeof(triIndex)); 
+         //triIndex = *(pts+1);
+         //gzwrite(gzf, &triIndex, sizeof(triIndex)); 
+         //triIndex = *(pts+2);
+         //gzwrite(gzf, &triIndex, sizeof(triIndex));
+         //poly->GetPolys()->GetNextCell(npts, pts);
+         int triIndex = val<1>(triangles[k]);//*pts;
+         gzwrite(gzf, &triIndex, sizeof(triIndex)); 
+         triIndex     = val<2>(triangles[k]);//*(pts+1);
+         gzwrite(gzf, &triIndex, sizeof(triIndex)); 
+         triIndex     = val<3>(triangles[k]);//*(pts+2);
+         gzwrite(gzf, &triIndex, sizeof(triIndex));
+      }
+
+      gzclose( gzf );
+
+      UBLOG(logDEBUG1,"WbWriterBOBJ::writeTriangles to "<<bobjFilename<<" - end");
+
+      return bobjFilename;
+   }
+   /*===============================================================================*/
+
+#endif //CAB_ZLIB
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterBOBJ.h b/source/VirtualFluidsCore/Basics/writer/WbWriterBOBJ.h
new file mode 100644
index 0000000000000000000000000000000000000000..fec3454c3d4cbafb5d360c37f99a3a847f052dec
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterBOBJ.h
@@ -0,0 +1,40 @@
+#ifdef CAB_ZLIB
+   #ifndef WBWRITERBOBJ_H
+   #define WBWRITERBOBJ_H
+
+   #include <string>
+   #include <basics/writer/WbWriter.h>
+
+   class WbWriterBOBJ  : public WbWriter
+   {
+   public:
+      OBCREATOR_EXT( WbWriterBOBJ )
+
+         static WbWriterBOBJ* getInstance()
+      {
+         static WbWriterBOBJ instance;
+         return &instance;
+      }
+   private:
+      WbWriterBOBJ() : WbWriter() 
+      {
+         if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+         if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+         if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+      }
+      WbWriterBOBJ( const WbWriterBOBJ& );                  //no copy allowed 
+      const WbWriterBOBJ& operator=( const WbWriterBOBJ& ); //no copy allowed
+
+      static std::string  pvdEndTag;
+
+   public:
+      std::string getFileExtension()  { return "BOBJ.gz"; }
+
+      std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+   };
+
+   UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterBOBJ ,WbWriter>::getInstance()), CAB_WbWriterVtkXmlASCII);
+
+   #endif //WBWRITERBOBJ_H
+
+#endif //CAB_ZLIB
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterSunflow.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterSunflow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4fa1a6381babc0837a2f3c65c576cfe76b75431c
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterSunflow.cpp
@@ -0,0 +1,112 @@
+#include <basics/writer/WbWriterSunflow.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+/*===============================================================================*/
+std::string WbWriterSunflow::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string sunflowFilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterSunflow::writeTriangles to "<<sunflowFilename<<" - start");
+
+   std::ofstream out(sunflowFilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(sunflowFilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(sunflowFilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+sunflowFilename);
+   }
+
+   // General part
+
+   // Image details
+   out<<"image {"              <<endl;
+   out<<"   resolution 640 480"<<endl;
+   out<<"   aa 0 1"            <<endl;
+   out<<"   filter mitchell"   <<endl;
+   out<<"}"                    <<endl<<endl;
+
+   // Camera position
+   out<<"camera {"                 <<endl;
+   out<<"   type pinhole"          <<endl;
+   out<<"   eye    -0.25 -0.3 0.13"<<endl;
+   out<<"   target -0.1 0.1 0.13"  <<endl;
+   out<<"   up     0 0 1"          <<endl;
+   out<<"   fov    60"             <<endl;
+   out<<"   aspect 1.333333"       <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   // Light
+   out<<"light {"                  <<endl;
+   out<<"   type ibl"              <<endl;
+   out<<"   image sky_small.hdr"   <<endl;
+   out<<"   center 0 -1 0"         <<endl;
+   out<<"   up 0 0 1"              <<endl;
+   out<<"   lock true"             <<endl;
+   out<<"   samples 200"           <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   // Shaders
+   out<<"shader {"                 <<endl;
+   out<<"   name default-shader"   <<endl;
+   out<<"   type diffuse"          <<endl;
+   out<<"   diff 0.25 0.25 0.25"   <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   out<<"shader {"                 <<endl;
+   out<<"   name Glass"            <<endl;
+   out<<"   type glass"            <<endl;
+   out<<"   eta 1.333"             <<endl;
+   out<<"   color 0.1 0.3 0.8"     <<endl;
+   out<<"}"                        <<endl<<endl;
+                                   
+   out<<"shader {"                 <<endl;
+   out<<"   name Mirror"           <<endl;
+   out<<"   type mirror"           <<endl;
+   out<<"   refl 0.7 0.7 0.7"      <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   // Objects
+   // a) Ground plane
+   out<<"object {"                 <<endl;
+   out<<"   shader default-shader" <<endl;
+   out<<"   type plane"            <<endl;
+   out<<"   p 0 0 0"               <<endl;
+   out<<"   n 0 0 1"               <<endl;
+   out<<"}"                        <<endl<<endl;
+
+   // b) Mesh
+   out<<"object {"                 <<endl;
+   out<<"   shader Glass"          <<endl;
+   out<<"   transform {"           <<endl;
+   out<<"      rotatey 270.0"      <<endl;
+   out<<"   }"                     <<endl;
+   out<<"   type generic-mesh"     <<endl;
+   out<<"      name polySurfac"    <<endl<<endl;
+
+
+   // POINTS SECTION
+   int nofNodes = (int)nodes.size(); 
+   out<<"   points "<<nofNodes<<endl;
+   for(int n=0; n<nofNodes; n++)
+      out<<"      "<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<endl;
+
+   // TRIANGLES SECTION
+   int nofTriangles= (int)triangles.size(); 
+   out<<"   triangles "<<nofTriangles<<endl;
+   for(int c=0; c<nofTriangles; c++)
+      out<<"      "<<val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<endl;
+
+   // FOOTER
+   out<<"   normals none" << endl;
+   out<<"   uvs none"     << endl;
+   out<<"}"               << endl;
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterSunflow::writeTriangles to "<<sunflowFilename<<" - end");
+
+   return sunflowFilename;
+}
+/*===============================================================================*/
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterSunflow.h b/source/VirtualFluidsCore/Basics/writer/WbWriterSunflow.h
new file mode 100644
index 0000000000000000000000000000000000000000..5681eac73dc63a24c703120bb58821312aab2090
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterSunflow.h
@@ -0,0 +1,38 @@
+#ifndef WbWriterSunflow_H
+#define WbWriterSunflow_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterSunflow  : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterSunflow )
+
+   static WbWriterSunflow* getInstance()
+   {
+      static WbWriterSunflow instance;
+      return &instance;
+   }
+private:
+   WbWriterSunflow() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+   }
+   WbWriterSunflow( const WbWriterSunflow& );                  //no copy allowed 
+   const WbWriterSunflow& operator=( const WbWriterSunflow& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+
+public:
+   std::string getFileExtension()  { return "ascii.sunflow"; }
+
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterSunflow ,WbWriter>::getInstance()), CAB_WbWriterSunflow);
+
+#endif //WbWriterSunflow_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterTecPlotASCII.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterTecPlotASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b2f83ef59c09e5d9b00b15b90c3d166042444f6a
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterTecPlotASCII.cpp
@@ -0,0 +1,68 @@
+#include <basics/writer/WbWriterTecPlotASCII.h>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+
+/*===============================================================================*/
+string WbWriterTecPlotASCII::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+   string tecplotfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterTecPlotASCII::writeOctsWithNodeData to "<<tecplotfilename<<" - start");
+
+   ofstream out(tecplotfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(tecplotfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(tecplotfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+tecplotfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"TITLE = VirtualFluids OctGrid from "<<UbSystem::getTimeStamp()<<endl;
+
+   out<<"VARIABLES = \"X\", \"Y\", \"Z\"";
+   for(size_t d=0; d<datanames.size(); d++)   
+      out<<", \""<<datanames[d]<<"\"";
+   out<<endl;
+
+   out<<"ZONE NODES="<<nofNodes<<", ELEMENTS="<<nofCells<<", DATAPACKING=POINT, ZONETYPE=FEBRICK"<<endl;
+   for(size_t n=0; n<nodes.size(); n++)   
+   {
+      UbTupleFloat3& coords = nodes[n];
+      out<<val<1>(coords)<<" "
+         <<val<2>(coords)<<" "
+         <<val<3>(coords);
+      for(size_t d=0; d<datanames.size(); d++)   
+         out<<" "<<nodedata[d][n];
+      out<<endl;
+   }
+
+   for(size_t c=0; c<cells.size(); c++)   
+   {
+      UbTupleInt8& cell = cells[c];
+      out<<val<1>(cell)<<" "
+         <<val<2>(cell)<<" "
+         <<val<3>(cell)<<" "
+         <<val<4>(cell)<<" "
+         <<val<5>(cell)<<" "
+         <<val<6>(cell)<<" "
+         <<val<7>(cell)<<" "
+         <<val<8>(cell)<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterTecPlotASCII::writeOctsWithNodeData to "<<tecplotfilename<<" - end");
+
+   return tecplotfilename;
+}
+/*===============================================================================*/
+string WbWriterTecPlotASCII::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   vector<string > datanames;
+   vector<vector<double > > nodedata;
+   return writeOctsWithNodeData(filename,nodes,cells,datanames,nodedata);
+}
+/*===============================================================================*/
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterTecPlotASCII.h b/source/VirtualFluidsCore/Basics/writer/WbWriterTecPlotASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff50c9c928d3636c0a894a77c5e2d523fb88be86
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterTecPlotASCII.h
@@ -0,0 +1,95 @@
+#ifndef WBWRITERTECPLOTASCII_H
+#define WBWRITERTECPLOTASCII_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterTecPlotASCII  : public WbWriter
+{
+public:
+   #ifndef SWIG
+   OBCREATOR_EXT( WbWriterTecPlotASCII )
+   #endif
+
+   static WbWriterTecPlotASCII* getInstance()
+   {
+      static WbWriterTecPlotASCII instance;
+      return &instance;
+   }
+private:
+   WbWriterTecPlotASCII() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"machine error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"machine error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"machine error float type mismatch");
+   }
+
+   WbWriterTecPlotASCII( const WbWriterTecPlotASCII& );                  //no copy allowed 
+   const WbWriterTecPlotASCII& operator=( const WbWriterTecPlotASCII& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+public:
+   std::string getFileExtension() { return ".ascii.dat";   }
+
+   //write a metafile 
+//    std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+//    std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+//    std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames);
+
+   //////////////////////////////////////////////////////////////////////////
+   //nodes
+//    std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes);
+//    std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+//    std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+//    std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+// 
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+//    std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+//    std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+
+//    std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+//    std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+//    std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+//    std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+//                                              std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+//                                              std::vector< std::vector< double > >& celldata                                                                    );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   //std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+   
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterTecPlotASCII ,WbWriter>::getInstance()), CAB_WbWriterTecPlotASCII);
+#endif
+
+#endif //WBWRITERTECPLOTASCII_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterVtkASCII.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0356f38fa155525ac929c81a7117acba2ffbd0bc
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkASCII.cpp
@@ -0,0 +1,601 @@
+#include <basics/writer/WbWriterVtkASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+std::string WbWriterVtkASCII::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuads to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+   
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<5*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"4 "
+         << val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"8"<<endl;
+   out<<endl;
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuads to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+ 
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<5*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"4 "
+      << val<1>(cells[c]) <<" "
+      << val<2>(cells[c]) <<" "
+      << val<4>(cells[c]) <<" "
+      << val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"8"<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<"\n";
+      
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<5*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"4 "
+      << val<1>(cells[c]) <<" "
+      << val<2>(cells[c]) <<" "
+      << val<4>(cells[c]) <<" "
+      << val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"8"<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                            vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                            vector< vector< double > >& celldata                                                                       )
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<5*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"4 "
+         << val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"8"<<endl;
+   out<<endl;
+
+   //write node data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)nodedatanames.size(); ++s)
+   {
+      out<<"SCALARS "<<nodedatanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   //write cell data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)celldatanames.size(); ++s)
+   {
+      out<<"SCALARS "<<celldatanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines) 
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeLines to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+   
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n])<<" \n";
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofLines<<" "<<3*nofLines<<"\n";
+   int nr = 0;
+   for(int l=0; l<nofLines; l++)
+   {
+      int el = nr+1;	
+      out<<"2 "<< val<1>(lines[l]) <<" "<< val<2>(lines[l]) <<" "<<endl;
+      nr=el+1;
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofLines<<"\n";
+   for(int l=0; l<nofLines; l++) out<<"3"<<endl;
+   out<<endl;
+
+   out.close();
+   
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeLines to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeTriangles to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes     = (int)nodes.size(); 
+   int nofTriangles = (int)triangles.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n])<<" \n";
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofTriangles<<" "<<4*nofTriangles<<"\n";
+   int nr = 0;
+   for(int t=0; t<nofTriangles; t++)
+   {
+      int el = nr+1;	
+      out<<"3 "<< val<1>(triangles[t]) <<" "<< val<2>(triangles[t]) <<" "<< val<3>(triangles[t]) <<" "<<endl;
+      nr=el+1;
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofTriangles<<"\n";
+   for(int l=0; l<nofTriangles; l++) out<<"5"<<endl;
+   out<<endl;
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeTriangles to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeTrianglesWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt3 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<4*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"3 "<< val<1>(cells[c]) <<" "<< val<2>(cells[c]) <<" "<< val<3>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"5"<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeOctsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOctsWithCellData to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<9*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+   {   out<<"8 "
+         << val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<" \n";
+   }
+
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"11 "<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOctsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeOctsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //write geo
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<9*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+   {   out<<"8 "
+         << val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<" \n";
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"11"<<endl;
+   out<<endl;
+
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<"\n";
+
+      out<<endl;
+   }
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkASCII::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOcts to "<<vtkfilename<<" - start");
+   
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VtkASCII FILE
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"GeoFile"<<"\n";
+   out<<"ASCII"<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<" \n";
+
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<9*nofCells<<"\n";
+   for(int c=0; c<(int)cells.size(); c++)
+      out<<"8 "
+      << val<1>(cells[c]) <<" "
+      << val<2>(cells[c]) <<" "
+      << val<4>(cells[c]) <<" "
+      << val<3>(cells[c]) <<" "
+      << val<5>(cells[c]) <<" "
+      << val<6>(cells[c]) <<" "
+      << val<8>(cells[c]) <<" "
+      << val<7>(cells[c]) <<" \n";
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<nofCells<<"\n";
+   for(int i=0; i<nofCells; i++) out<<"11"<<endl;
+   out<<endl;
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkASCII::writeOcts to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterVtkASCII.h b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..914ab2cab9a37ace767e9fd389c79401d12c5a8a
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkASCII.h
@@ -0,0 +1,78 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITERVTKASCII_H
+#define WBWRITERVTKASCII_H
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterVtkASCII : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterVtkASCII )
+
+   static WbWriterVtkASCII* getInstance()
+   {
+      static WbWriterVtkASCII instance;
+      return &instance;
+   }
+private:
+   WbWriterVtkASCII() : WbWriter() {}                            
+   WbWriterVtkASCII( const WbWriterVtkASCII& );                  //no copy allowed 
+   const WbWriterVtkASCII& operator=( const WbWriterVtkASCII& ); //no copy allowed
+
+public:
+   std::string getFileExtension()  { return ".ascii.vtk"; }
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                             std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                             std::vector< std::vector< double > >& celldata                                                                       );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsBinary(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterVtkASCII,WbWriter>::getInstance()), CAB_WbWriterVtkASCII);
+
+#endif //WBWRITERVTKASCII_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterVtkBinary.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f766fa402236f3fa47a218a54e3187fb3b3a9fb0
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkBinary.cpp
@@ -0,0 +1,747 @@
+#include <basics/writer/WbWriterVtkBinary.h>
+#include <basics/writer/WbWriterVtkASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+std::string WbWriterVtkBinary::writeLines(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines)
+{
+   return WbWriterVtkASCII::getInstance()->writeLines(filename,nodes,lines);
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells)
+{
+   return WbWriterVtkASCII::getInstance()->writeTriangles(filename,nodes,cells);
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   return WbWriterVtkASCII::getInstance()->writeTrianglesWithNodeData(filename,nodes,cells,datanames,nodedata);
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuads to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //HEADER-SECTION
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*5<<"\n";
+
+   int nodesPerCellDummy = 4;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int SW = val<1>(cells[c]); 
+      int SE = val<2>(cells[c]); 
+      int NE = val<3>(cells[c]);
+      int NW = val<4>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&SW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&SE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&SW,sizeof(int));
+      out.write((char*)&SE,sizeof(int));
+      out.write((char*)&NW,sizeof(int));
+      out.write((char*)&NE,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 8;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuads to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*5<<"\n";
+
+   int nodesPerCellDummy = 4;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int SW = val<1>(cells[c]); 
+      int SE = val<2>(cells[c]); 
+      int NE = val<3>(cells[c]);
+      int NW = val<4>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&SW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&SE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&SW,sizeof(int));
+      out.write((char*)&SE,sizeof(int));
+      out.write((char*)&NW,sizeof(int));
+      out.write((char*)&NE,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 8;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //DATA SECTION
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      if((int)nodedata[s].size() != nofNodes) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      { 
+         float dummy = (float)nodedata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   //HEADER-SECTION
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*5<<"\n";
+
+   int nodesPerCellDummy = 4;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int SW = val<1>(cells[c]); 
+      int SE = val<2>(cells[c]); 
+      int NE = val<3>(cells[c]);
+      int NW = val<4>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&SW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&SE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&SW,sizeof(int));
+      out.write((char*)&SE,sizeof(int));
+      out.write((char*)&NW,sizeof(int));
+      out.write((char*)&NE,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 8;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //DATA SECTION
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      if((int)celldata[s].size() != nofCells) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+      { 
+         float dummy = (float)celldata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                             vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                             vector< vector< double > >& celldata                                                                    )
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //HEADER-SECTION
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]);  
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*5<<"\n";
+
+   int nodesPerCellDummy = 4;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int SW = val<1>(cells[c]); 
+      int SE = val<2>(cells[c]); 
+      int NE = val<3>(cells[c]);
+      int NW = val<4>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&SW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&SE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&NE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&SW,sizeof(int));
+      out.write((char*)&SE,sizeof(int));
+      out.write((char*)&NW,sizeof(int));
+      out.write((char*)&NE,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 8;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //NODE DATA SECTION
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)nodedatanames.size(); ++s)
+   {
+      if((int)nodedata[s].size() != nofNodes) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<nodedatanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      { 
+         float dummy = (float)nodedata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+   
+   //CELL DATA SECTION
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)celldatanames.size(); ++s)
+   {
+      if((int)celldata[s].size() != nofCells) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<celldatanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+      { 
+         float dummy = (float)celldata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata)
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOctsWithCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //HEADER-SECTION
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = (float)val<1>(nodes[n]); 
+      float x2 = (float)val<2>(nodes[n]); 
+      float x3 = (float)val<3>(nodes[n]);
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*9<<"\n";
+
+   int nodesPerCellDummy = 8;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int BSW = val<1>(cells[c]);  int TSW = val<5>(cells[c]);
+      int BSE = val<2>(cells[c]);  int TSE = val<6>(cells[c]);
+      int BNW = val<3>(cells[c]);  int TNW = val<7>(cells[c]);
+      int BNE = val<4>(cells[c]);  int TNE = val<8>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&BSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&BSW,sizeof(int));
+      out.write((char*)&BSE,sizeof(int));
+      out.write((char*)&BNE,sizeof(int));
+      out.write((char*)&BNW,sizeof(int));
+      out.write((char*)&TSW,sizeof(int));
+      out.write((char*)&TSE,sizeof(int));
+      out.write((char*)&TNE,sizeof(int));
+      out.write((char*)&TNW,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 11;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //CELL DATA SECTION
+   //write data section
+   out<<"CELL_DATA "<<nofCells<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      if((int)celldata[s].size() != nofCells) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)celldata[s].size(); d++)
+      { 
+         float dummy = (float)celldata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOctsWithCellData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+   //HEADER-SECTION
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = val<1>(nodes[n]); 
+      float x2 = val<2>(nodes[n]); 
+      float x3 = val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*9<<"\n";
+
+   int nodesPerCellDummy = 8;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int BSW = val<1>(cells[c]);  int TSW = val<5>(cells[c]);
+      int BSE = val<2>(cells[c]);  int TSE = val<6>(cells[c]);
+      int BNW = val<3>(cells[c]);  int TNW = val<7>(cells[c]);
+      int BNE = val<4>(cells[c]);  int TNE = val<8>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&BSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNE,sizeof(int));
+      }
+
+      out.write((char*)&nodesPerCellDummy,sizeof(int));
+      out.write((char*)&BSW,sizeof(int));
+      out.write((char*)&BSE,sizeof(int));
+      out.write((char*)&BNE,sizeof(int));
+      out.write((char*)&BNW,sizeof(int));
+      out.write((char*)&TSW,sizeof(int));
+      out.write((char*)&TSE,sizeof(int));
+      out.write((char*)&TNE,sizeof(int));
+      out.write((char*)&TNW,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 11;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+
+   //NODE DATA SECTION
+   //write data section
+   out<<"POINT_DATA "<<nofNodes<<"\n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      if((int)nodedata[s].size() != nofNodes) throw UbException(UB_EXARGS,"datasetsize must be equal to nofNodes");
+      out<<"SCALARS "<<datanames[s]<<" float 1 \n LOOKUP_TABLE default \n";
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      { 
+         float dummy = (float)nodedata[s][d]; 
+         if(swapByte) UbSystem::swapByteOrder((unsigned char*)&dummy,sizeof(float)); 
+         out.write((const char*)&dummy,sizeof(float));
+      }
+      out<<endl;
+   }
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkBinary::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename = filename + getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOcts to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ofstream::out | ofstream::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //HEADER-SECTION
+   //WRITE BIGENDIAN VtkBinary FILE
+   bool swapByte = UbSystem::isLittleEndian();
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   out<<"# vtk DataFile Version 4.0"<<"\n";
+   out<<"D3Q19MasterNodeGrid"<<"\n";
+   out<<""<<"\n";
+
+   //POINTS SECTION
+   out<<"DATASET UNSTRUCTURED_GRID"<<"\n";
+   out<<"POINTS "<<nofNodes<<" float"<<"\n";
+   for(int n=0; n<nofNodes; n++)
+   {
+      float x1 = val<1>(nodes[n]); 
+      float x2 = val<2>(nodes[n]); 
+      float x3 = val<3>(nodes[n]); 
+
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&x1,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x2,sizeof(float));
+         UbSystem::swapByteOrder((unsigned char*)&x3,sizeof(float));
+      }
+
+      out.write((char*)&x1,sizeof(float));
+      out.write((char*)&x2,sizeof(float));
+      out.write((char*)&x3,sizeof(float));
+   }
+   out<<"\n";
+
+   //CELLS SECTION
+   out<<"CELLS "<<nofCells<<" "<<nofCells*9<<"\n";
+
+   int nodesPerCellDummy = 8;  //nofNodesPerCell         
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&nodesPerCellDummy,sizeof(int));
+   for(int c=0; c<(int)cells.size(); c++)
+   {
+      int BSW = val<1>(cells[c]);  int TSW = val<5>(cells[c]);
+      int BSE = val<2>(cells[c]);  int TSE = val<6>(cells[c]);
+      int BNW = val<3>(cells[c]);  int TNW = val<7>(cells[c]);
+      int BNE = val<4>(cells[c]);  int TNE = val<8>(cells[c]);
+      if(swapByte)
+      {
+         UbSystem::swapByteOrder((unsigned char*)&BSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&BNE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TSE,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNW,sizeof(int));
+         UbSystem::swapByteOrder((unsigned char*)&TNE,sizeof(int));
+      }
+
+       out.write((char*)&nodesPerCellDummy,sizeof(int));
+       out.write((char*)&BSW,sizeof(int));
+       out.write((char*)&BSE,sizeof(int));
+       out.write((char*)&BNE,sizeof(int));
+       out.write((char*)&BNW,sizeof(int));
+       out.write((char*)&TSW,sizeof(int));
+       out.write((char*)&TSE,sizeof(int));
+       out.write((char*)&TNE,sizeof(int));
+       out.write((char*)&TNW,sizeof(int));
+   }
+   out<<"\n";
+
+   out<<"CELL_TYPES "<<(int)cells.size()<<"\n";
+   int celltype = 11;
+   if(swapByte) UbSystem::swapByteOrder((unsigned char*)&celltype,sizeof(int));
+   for(int c=0; c<nofCells; c++)
+      out.write((char*)&celltype,sizeof(int));
+
+   out<<endl;
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkBinary::writeOcts to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterVtkBinary.h b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..dca3567d3505e0bea3c549ab601cb478c0bb17ed
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkBinary.h
@@ -0,0 +1,77 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef WBWRITERVTKBINARY_H
+#define WBWRITERVTKBINARY_H
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterVtkBinary : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterVtkBinary )
+
+   static WbWriterVtkBinary* getInstance()
+   {
+      static WbWriterVtkBinary instance;
+      return &instance;
+   }
+private:
+   WbWriterVtkBinary() : WbWriter() {}                             
+   WbWriterVtkBinary( const WbWriterVtkBinary& );                  //no copy allowed 
+   const WbWriterVtkBinary& operator=( const WbWriterVtkBinary& ); //no copy allowed
+
+public:
+   std::string getFileExtension() { return ".bin.vtk"; }
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename, std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //cell numbering:
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                             std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                             std::vector< std::vector< double > >& celldata                                                                    );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterVtkBinary ,WbWriter>::getInstance()), CAB_WbWriterVtkBinary);
+
+#endif //WBWRITERVTKBINARY_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlASCII.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlASCII.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a5e5fdf7cf9d5550046fb66dfc0250de23a797d0
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlASCII.cpp
@@ -0,0 +1,1188 @@
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::pvdEndTag ="   </Collection>\n</VTKFile>";
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   std::string vtkfilename=filename+".pvd";
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   std::string endian;
+   if(UbSystem::isLittleEndian()) endian = "LittleEndian";
+   else                           endian = "BigEndian";
+   out<<"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\""<<endian<<"\" >\n";
+   out<<"   <Collection>"<<endl;
+   
+   int group = 0, part=0;
+   for(std::size_t i=0; i<filenames.size(); i++)
+   {
+      out<<"       <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<part<<"\" file=\""<<filenames[i]<<"\"/>\n";
+      if(sepGroups) group++;
+      else          part++;
+   }
+   out<<pvdEndTag;
+   out.close();
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   std::string vtkfilename=filename;
+   std::fstream test(vtkfilename.c_str(), ios::in);
+   if(!test)
+   {
+      test.clear();
+      vtkfilename += ".pvd";
+      test.open(vtkfilename.c_str(), ios::in);
+      if(!test) return this->writeCollection(filename,filenames,timeStep,sepGroups);
+   }
+
+   std::fstream out(vtkfilename.c_str(), ios::in | ios::out);
+   out.seekp(-(int)pvdEndTag.size()-1, ios_base::end);
+
+   int group = 0;
+   for(std::size_t i=0; i<filenames.size(); i++)
+   {
+      out<<"       <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<i<<"\" file=\""<<filenames[i]<<"\"/>\n";
+      if(sepGroups) group++;
+   }
+   out<<pvdEndTag;
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeParallelFile(const string& filename,vector<string>& pieceSources, vector<string>& pointDataNames, vector<string>& cellDataNames)
+{
+   string vtkfilename=filename+".pvtu";
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeParallelFile to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //VTK FILE
+   out<<"<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
+   out<<"  <PUnstructuredGrid GhostLevel=\"0\">\n";
+   out<<"    <PPoints>\n"; 
+   out<<"      <PDataArray type=\"Float32\" NumberOfComponents=\"3\"/>\n";
+   out<<"    </PPoints>\n";
+   out<<"    <PPointData>\n";
+   for(size_t s=0; s<pointDataNames.size(); s++)
+      out<< "      <PDataArray type=\"Float32\" Name=\""<< pointDataNames[s] <<"\"/>\n";
+   out<<"    </PPointData>\n";
+   if (cellDataNames.size() > 0)
+   {
+      out<<"    <PCellData>\n";
+      for(size_t s=0; s<cellDataNames.size(); s++)
+         out<< "      <PDataArray type=\"Float32\" Name=\""<< cellDataNames[s] <<"\"/>\n";
+      out<<"    </PCellData>\n";
+   }
+
+   for(size_t s=0; s<pieceSources.size(); s++)
+      out<<"    <Piece Source=\""<<pieceSources[s]<<"\"/>\n";
+   out<<"  </PUnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeParallelFile to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuads to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*4<<" " ;
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"8 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuads to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*4<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"8 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+    }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*4<<" " ;
+
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"8 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <CellData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </CellData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+
+   out.close();
+
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                          vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                          vector< vector< double > >& celldata                                                                       )
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*4<<" " ;
+
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"8 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+   
+   //write PointData section
+   out<<"         <PointData Scalars=\"PScalars\"> \n";
+   for(int s=0; s<(int)nodedatanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< nodedatanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+
+   //write celldata section
+   out<<"         <CellData Scalars=\"CScalars\"> \n";
+   for(int s=0; s<(int)celldatanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< celldatanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </CellData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines) 
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofLines<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofLines; c++)
+      out<< val<1>(lines[c]) <<" "<< val<2>(lines[c])<<"  ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int c=1; c<=nofLines; c++)
+      out<<c*2<<" " ;
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofLines; c++)
+      out<<"3 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeLinesWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLinesWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofLines = (int)lines.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofLines<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofLines; c++)
+      out<< val<1>(lines[c]) <<" "<< val<2>(lines[c])<<"  ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int c=1; c<=nofLines; c++)
+      out<<c*2<<" " ;
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofLines; c++)
+      out<<"3 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLinesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTriangles to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofTriangles= (int)triangles.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofTriangles<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofTriangles; c++)
+      out<< val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<"  ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int c=1; c<nofTriangles+1; c++)
+      out<<c*3<<" " ;
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int c=0; c<nofTriangles; c++)
+      out<<"5 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTriangles to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "<< val<2>(cells[c]) <<" "<< val<3>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*3<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"5 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeTrianglesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeOctsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithCellData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<"  ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*8<<" " ;
+
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"11 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+   
+
+   //write data section
+   out<<"         <CellData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)celldata[s].size(); d++)
+         out<<celldata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </CellData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeOctsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<<val<1>(nodes[n])<<" "<<val<2>(nodes[n])<<" "<<val<3>(nodes[n])<<" ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<"  ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*8<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"11 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write PointData section
+   out<<"         <PointData Scalars=\"PScalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\">";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+      {
+         //out<<base64_encode((unsigned char*)(&nodedata[s][d]),sizeof(float));
+         //out.write((char*)&nodedata[s][d],sizeof(float));
+         out<<nodedata[s][d]<<" ";
+      }
+      out<<"</DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlASCII::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOcts to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofCells<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<< val<1>(cells[c]) <<" "
+         << val<2>(cells[c]) <<" "
+         << val<4>(cells[c]) <<" "
+         << val<3>(cells[c]) <<" "
+         << val<5>(cells[c]) <<" "
+         << val<6>(cells[c]) <<" "
+         << val<8>(cells[c]) <<" "
+         << val<7>(cells[c]) <<"   ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofCells+1; c++)
+      out<<c*8<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofCells; c++)
+      out<<"11 ";
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeOcts to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbWriterVtkXmlASCII::writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofNodes<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"      <Points>\n"; 
+   out<<"         <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+   out<<"      </Points>\n";
+
+   //CELLS SECTION
+   out<<"      <Cells>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
+   for(int n=0; n<nofNodes; n++)
+      out<< n << "  ";
+   out<<"\n";
+
+   out<<"      </DataArray>\n";
+   out<<"         <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
+   for(int n=1; n<=nofNodes; n++)
+      out << n << " ";
+
+   out<<"\n";
+   out<<"         </DataArray>\n";
+
+   out<<"      <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
+
+   for(int n=0; n<nofNodes; n++)
+      out<<"1 ";
+   out<<"\n";
+   out<<"      </DataArray>\n";
+   out<<"      </Cells>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeLines to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbWriterVtkXmlASCII::writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofNodes<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofNodes; c++)
+      out << c <<"   ";
+   out<<"\n";
+
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofNodes+1; c++)
+      out<<c<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+   for(int c=0; c<nofNodes; c++)
+      out<<"1 ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+
+//////////////////////////////////////////////////////////////////////////
+std::string WbWriterVtkXmlASCII::writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata)
+{
+   string vtkfilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - start");
+
+   std::ofstream out(vtkfilename.c_str());
+   out.precision (std::numeric_limits<double>::digits10 + 1);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   //VTK FILE
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\"	NumberOfCells=\""<<nofNodes<<"\">   \n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">\n               ";
+   for(int n=0; n<nofNodes; n++)
+      out<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<"   ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+   out<<"         </Points>\n";
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n              ";
+
+   for(int c=0; c<nofNodes; c++)
+      out << c <<"   ";
+   out<<"\n";
+
+   out<<"            </DataArray>\n";
+   out<<"            <DataArray type=\"Int64\" Name=\"offsets\" format=\"ascii\">\n              ";
+   for(int c=1; c<nofNodes+1; c++)
+      out<<c<<" " ;
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n              ";
+   for(int c=0; c<nofNodes; c++)
+      out<<"1 ";
+
+   out<<"\n";
+   out<<"            </DataArray>\n";
+
+   out<<"         </Cells>\n";
+
+   //write data section
+   out<<"         <PointData Scalars=\"Scalars\"> \n";
+   for(int s=0; s<(int)datanames.size(); ++s)
+   {
+      out<< "           <DataArray type=\"Float64\" Name=\""<< datanames[s] <<"\" format=\"ascii\"> \n";
+
+      for(int d=0; d<(int)nodedata[s].size(); d++)
+         out<<nodedata[s][d]<<" ";
+
+      out<<"\n          </DataArray>\n";
+   }
+   out<<"         </PointData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlASCII::writeNodesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlASCII.h b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlASCII.h
new file mode 100644
index 0000000000000000000000000000000000000000..84212bd509f14768427a5792717b907e4e90601c
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlASCII.h
@@ -0,0 +1,101 @@
+#ifndef WBWRITERVTKXMLASCII_H
+#define WBWRITERVTKXMLASCII_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+#include <boost/serialization/base_object.hpp>
+
+class WbWriterVtkXmlASCII  : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterVtkXmlASCII )
+
+   static WbWriterVtkXmlASCII* getInstance()
+   {
+      static WbWriterVtkXmlASCII instance;
+      return &instance;
+   }
+private:
+   WbWriterVtkXmlASCII() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+   }
+   WbWriterVtkXmlASCII( const WbWriterVtkXmlASCII& );                  //no copy allowed 
+   const WbWriterVtkXmlASCII& operator=( const WbWriterVtkXmlASCII& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+
+public:
+   std::string getFileExtension()  { return ".ascii.vtu"; }
+
+   //write a metafile 
+   std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timesteps, const bool& sepGroups);//std::vector<double>& groups, std::vector<double>& parts);
+   std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+   std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames);
+
+   //////////////////////////////////////////////////////////////////////////
+   //nodes
+   std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes);
+   std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+   std::string writeNodesWithNodeDataDouble(const std::string& filename,std::vector< UbTupleDouble3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+   std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                             std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                             std::vector< std::vector< double > >& celldata                                                                       );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<WbWriter>(*this);
+   }
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterVtkXmlASCII ,WbWriter>::getInstance()), CAB_WbWriterVtkXmlASCII);
+
+#endif //WBWRITERVTKXMLASCII_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlBinary.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlBinary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d3d9dbf790dee6b6eca2eeb78135fcf877961f3
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlBinary.cpp
@@ -0,0 +1,1582 @@
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+#include <basics/utilities/UbLogger.h>
+#include <cstring>
+
+using namespace std;
+
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::pvdEndTag ="   </Collection>\n</VTKFile>";
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeCollection(const string& filename, const vector<string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   string vtkfilename=filename+".pvd";
+   ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   string endian;
+   if(UbSystem::isLittleEndian()) endian = "LittleEndian";
+   else                           endian = "BigEndian";
+   out<<"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\""<<endian<<"\" >"<<endl;
+   out<<"   <Collection>"<<endl;
+   
+   int group = 0, part=0;
+   for(size_t i=0; i<filenames.size(); i++)
+   {
+      out<<"       <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<part<<"\" file=\""<<filenames[i]<<"\"/>"<<endl;
+      if(sepGroups) group++;
+      else          part++;
+   }
+   out<<pvdEndTag;
+   out.close();
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::addFilesToCollection(const string& filename, const vector<string>& filenames, const double& timeStep, const bool& sepGroups)
+{
+   string vtkfilename=filename;
+   fstream test(vtkfilename.c_str(), ios::in);
+   if(!test)
+   {
+      test.clear();
+      vtkfilename += ".pvd";
+      test.open(vtkfilename.c_str(), ios::in);
+      if(!test) return this->writeCollection(filename,filenames,timeStep,sepGroups);
+   }
+ 
+   fstream out(vtkfilename.c_str(), ios::in | ios::out);
+   out.seekp(-(int)pvdEndTag.size()-1, ios_base::end);
+
+   int group = 0;
+   for(size_t i=0; i<filenames.size(); i++)
+   {
+      out<<"       <DataSet timestep=\""<<timeStep<<"\" group=\""<<group<<"\" part=\""<<i<<"\" file=\""<<filenames[i]<<"\"/>"<<endl;
+      if(sepGroups) group++;
+   }
+   out<<pvdEndTag;
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeParallelFile(const string& filename,vector<string>& pieceSources, vector<string>& pointDataNames, vector<string>& cellDataNames)
+{
+   string vtkfilename=filename+".pvtu";
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeParallelFile to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   //VTK FILE
+   out<<"<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">"<<"\n";
+   out<<"  <PUnstructuredGrid GhostLevel=\"0\">"<<"\n";
+   out<<"    <PPoints>\n"; 
+   out<<"      <PDataArray type=\"Float32\" NumberOfComponents=\"3\"/>\n";
+   out<<"    </PPoints>\n";
+   out<<"    <PPointData>\n";
+   for(size_t s=0; s<pointDataNames.size(); s++)
+      out<< "      <PDataArray type=\"Float32\" Name=\""<< pointDataNames[s] <<"\"/>\n";
+   out<<"    </PPointData>\n";
+   if (cellDataNames.size() > 0)
+   {
+      out<<"    <PCellData>\n";
+      for(size_t s=0; s<cellDataNames.size(); s++)
+         out<< "      <PDataArray type=\"Float32\" Name=\""<< cellDataNames[s] <<"\"/>\n";
+      out<<"    </PCellData>\n";
+   }
+
+   for(size_t s=0; s<pieceSources.size(); s++)
+      out<<"    <Piece Source=\""<<pieceSources[s]<<"\"/>\n";
+   out<<"  </PUnstructuredGrid>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeParallelFile to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeLines(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLines to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)lines.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 2 /*nodes per line */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per line */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of line */ * nofCells * sizeof(unsigned char);
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(lines[c]), sizeof(int) );
+      out.write( (char*)&val<2>(lines[c]), sizeof(int) );
+      
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 2 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 3;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLines to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+std::string WbWriterVtkXmlBinary::writeLinesWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLinesWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)lines.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 2 /*nodes per line  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per line */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of line    */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(lines[c]), sizeof(int) );
+      out.write( (char*)&val<2>(lines[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 3 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 5;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeLinesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTriangles to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)triangles.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3 - coord    */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 3 /*nodes per triangle  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per triangle */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of triangle    */ * nofCells * sizeof(unsigned char);
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(triangles[c]), sizeof(int) );
+      out.write( (char*)&val<2>(triangles[c]), sizeof(int) );
+      out.write( (char*)&val<3>(triangles[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 3 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 5;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out<<flush;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTriangles to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeTrianglesWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt3 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTrianglesWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 3 /*nodes per tri   */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per tri  */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of tri     */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float); 
+   
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 3 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 5;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeTrianglesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeQuads(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuads to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 4 /*nodes per quad  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
+  
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 4 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 8;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out<<flush;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuads to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeQuadsWithNodeData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 4 /*nodes per quad  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar          */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 4 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 8;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeQuadsWithCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, vector< string >& datanames, vector< vector< double > >& celldata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 4 /*nodes per quad  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar          */ * nofCells * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <CellData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </CellData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 4 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 8;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<celldata[s].size(); ++d)
+      {
+         //loake kopie machen, da in celldata "doubles" sind
+         float tmp = (float)celldata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+
+   out<<"\n</AppendedData>\n";
+
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt4 >& cells, 
+                                                                vector< string >& nodedatanames, vector< vector< double > >& nodedata, vector< string >& celldatanames,
+                                                                vector< vector< double > >& celldata                                                                    )
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 4 /*nodes per quad  */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per quad */ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of quad    */ * nofCells * sizeof(unsigned char);
+   int bytesScalarDataPoint = 1 /*scalar          */ * nofNodes * sizeof(float); 
+   int bytesScalarDataCell  = 1 /*scalar          */ * nofCells * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   // Point DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<nodedatanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< nodedatanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarDataPoint);
+   }
+   out<<"         </PointData>\n";
+
+
+   // Cell DATA SECTION
+   out<<"         <CellData>\n";
+   for(size_t s=0; s<celldatanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< celldatanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarDataCell);
+   }
+   out<<"         </CellData>\n";
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 4 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 8;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //Point DATA SECTION
+   //scalarData
+   for(size_t s=0; s<nodedatanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarDataPoint,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   //Cell DATA SECTION
+   //scalarData
+   for(size_t s=0; s<celldatanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarDataCell,bytesPerByteVal);
+      for(size_t d=0; d<celldata[s].size(); ++d)
+      {
+         //loake kopie machen, da in celldata "doubles" sind
+         float tmp = (float)celldata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeOctsWithCellData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& celldata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithCellData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3      */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per oct*/ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of oct   */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar        */ * nofCells * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <CellData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </CellData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<5>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<6>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<8>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<7>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 8 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 11;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<celldata[s].size(); ++d)
+      {
+         //loake kopie machen, da in celldata "doubles" sind
+         float tmp = (float)celldata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithCellData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeOctsWithNodeData(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt8 >& cells, vector<string >& datanames, vector<vector<double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3      */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per oct*/ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of oct   */ * nofCells * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar        */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<5>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<6>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<8>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<7>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 8 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 11;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOctsWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+/*===============================================================================*/
+string WbWriterVtkXmlBinary::writeOcts(const string& filename,vector< UbTupleFloat3 >& nodes, vector< UbTupleInt8 >& cells)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOcts to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+   int nofCells = (int)cells.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3      */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 8 /*nodes per oct */ * nofCells * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per oct*/ * nofCells * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of oct   */ * nofCells * sizeof(unsigned char);
+   //int bytesScalarData      = 1 /*scalar        */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofCells<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofCells; c++) 
+   {
+      out.write( (char*)&val<1>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<2>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<4>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<3>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<5>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<6>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<8>(cells[c]), sizeof(int) );
+      out.write( (char*)&val<7>(cells[c]), sizeof(int) );
+   }
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   int itmp;
+   for(int c=1; c<=nofCells; c++)
+   {
+      itmp = 8 * c;    
+      out.write( (char*)&itmp, sizeof(int) );
+   }
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 11;
+   for(int c=0; c<nofCells; c++)
+   {
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeOcts to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbWriterVtkXmlBinary::writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodes to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3        */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 1 /*nodes per cell  */ * nofNodes * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per cell */ * nofNodes * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of line    */ * nofNodes * sizeof(unsigned char);
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofNodes; c++) 
+      out.write( (char*)&c, sizeof(int) );
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   for(int c=1; c<=nofNodes; c++)
+      out.write( (char*)&c, sizeof(int) );
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 1;
+   for(int c=0; c<nofNodes; c++)
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodes to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+}
+std::string WbWriterVtkXmlBinary::writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata)
+{
+   string vtkfilename = filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodesWithNodeData to "<<vtkfilename<<" - start");
+
+   ofstream out(vtkfilename.c_str(),ios::out | ios::binary);
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(vtkfilename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); out.open(vtkfilename.c_str(),ios::out | ios::binary);}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+vtkfilename);
+   }
+
+   int nofNodes = (int)nodes.size(); 
+
+   int bytesPerByteVal      = 4; //==sizeof(int)
+   int bytesPoints          = 3 /*x1/x2/x3       */ * nofNodes * sizeof(float);
+   int bytesCellConnectivty = 1 /*nodes per cell */ * nofNodes * sizeof(int  );
+   int bytesCellOffsets     = 1 /*offset per cell*/ * nofNodes * sizeof(int  );
+   int bytesCellTypes       = 1 /*type of oct    */ * nofNodes * sizeof(unsigned char);
+   int bytesScalarData      = 1 /*scalar         */ * nofNodes * sizeof(float); 
+
+   int offset = 0;
+   //VTK FILE
+   out<<"<?xml version=\"1.0\"?>\n";
+   out<<"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" >"<<"\n";
+   out<<"   <UnstructuredGrid>"<<"\n";
+   out<<"      <Piece NumberOfPoints=\""<<nofNodes<<"\" NumberOfCells=\""<<nofNodes<<"\">\n";
+
+   //POINTS SECTION
+   out<<"         <Points>\n"; 
+   out<<"            <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"appended\" offset=\""<< offset <<"\"  />\n";
+   out<<"         </Points>\n";
+   offset += (bytesPerByteVal + bytesPoints);
+
+   //CELLS SECTION
+   out<<"         <Cells>\n";
+   out<<"            <DataArray type=\"Int32\" Name=\"connectivity\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellConnectivty); 
+   out<<"            <DataArray type=\"Int32\" Name=\"offsets\" format=\"appended\" offset=\""<< offset <<"\" />\n";
+   offset += (bytesPerByteVal + bytesCellOffsets);
+   out<<"            <DataArray type=\"UInt8\" Name=\"types\" format=\"appended\" offset=\""<< offset <<"\" />\n ";
+   offset += (bytesPerByteVal + bytesCellTypes);
+   out<<"         </Cells>\n";
+
+   //DATA SECTION
+   out<<"         <PointData>\n";
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out<< "            <DataArray type=\"Float32\" Name=\""<< datanames[s] <<"\" format=\"appended\" offset=\""<< offset <<"\" /> \n";
+      offset += (bytesPerByteVal + bytesScalarData);
+   }
+   out<<"         </PointData>\n";
+
+   out<<"      </Piece>\n";
+   out<<"   </UnstructuredGrid>\n";
+
+   // AppendedData SECTION
+   out<<"   <AppendedData encoding=\"raw\">\n";
+   out<<"_";
+
+   //POINTS SECTION
+   out.write((char*)&bytesPoints,bytesPerByteVal);
+   for(int n=0; n<nofNodes; n++)
+   {
+      out.write((char*)&val<1>(nodes[n]),sizeof(float));
+      out.write((char*)&val<2>(nodes[n]),sizeof(float));
+      out.write((char*)&val<3>(nodes[n]),sizeof(float));
+   }
+
+   //CELLS SECTION
+   //cellConnectivity
+   out.write( (char*)&bytesCellConnectivty, bytesPerByteVal );  
+   for(int c=0; c<nofNodes; c++) 
+      out.write( (char*)&c, sizeof(int) );
+
+   //cellOffsets
+   out.write( (char*)&bytesCellOffsets, bytesPerByteVal );
+   for(int c=1; c<=nofNodes; c++)
+      out.write( (char*)&c, sizeof(int) );
+
+   //cellTypes
+   out.write( (char*)&bytesCellTypes, bytesPerByteVal );
+   unsigned char vtkCellType = 1;
+   for(int c=0; c<nofNodes; c++)
+      out.write( (char*)&vtkCellType, sizeof(unsigned char) );
+   
+   //DATA SECTION
+   //scalarData
+   for(size_t s=0; s<datanames.size(); ++s)
+   {
+      out.write((char*)&bytesScalarData,bytesPerByteVal);
+      for(size_t d=0; d<nodedata[s].size(); ++d)
+      {
+         //loake kopie machen, da in nodedata "doubles" sind
+         float tmp = (float)nodedata[s][d];
+         out.write((char*)&tmp,sizeof(float));
+      }
+   }
+   out<<"\n</AppendedData>\n";
+   out<<"</VTKFile>";
+   out<<endl;
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterVtkXmlBinary::writeNodesWithNodeData to "<<vtkfilename<<" - end");
+
+   return vtkfilename;
+
+}
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlBinary.h b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlBinary.h
new file mode 100644
index 0000000000000000000000000000000000000000..b00157fed2b38826b31375e6ffa459eda1b1483b
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterVtkXmlBinary.h
@@ -0,0 +1,104 @@
+#ifndef WBWRITERVTKXMLBINARY_H
+#define WBWRITERVTKXMLBINARY_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+#include <boost/serialization/base_object.hpp>
+
+class WbWriterVtkXmlBinary  : public WbWriter
+{
+public:
+#ifndef SWIG
+   OBCREATOR_EXT( WbWriterVtkXmlBinary )
+#endif
+
+   static WbWriterVtkXmlBinary* getInstance()
+   {
+      static WbWriterVtkXmlBinary instance;
+      return &instance;
+   }
+private:
+   WbWriterVtkXmlBinary() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"machine error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"machine error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"machine error float type mismatch");
+   }
+
+   WbWriterVtkXmlBinary( const WbWriterVtkXmlBinary& );                  //no copy allowed 
+   const WbWriterVtkXmlBinary& operator=( const WbWriterVtkXmlBinary& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+public:
+   std::string getFileExtension() { return ".bin.vtu";   }
+
+   //write a metafile 
+   std::string writeCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+   std::string addFilesToCollection(const std::string& filename, const std::vector<std::string>& filenames, const double& timestep, const bool& sepGroups);
+   std::string writeParallelFile(const std::string& filename,std::vector<std::string>& pieceSources, std::vector<std::string>& pointDataNames, std::vector<std::string>& cellDataNames);
+
+   //////////////////////////////////////////////////////////////////////////
+   //nodes
+   std::string writeNodes(const std::string& filename,std::vector< UbTupleFloat3 >& nodes);
+   std::string writeNodesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //lines
+   //     0 ---- 1
+   //nodenumbering must start with 0!
+   std::string writeLines(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+   std::string writeLinesWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //triangles
+   //                    2
+   //                     
+   //                  0---1
+   //nodenumbering must start with 0!
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+   std::string writeTrianglesWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt3 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+
+   //////////////////////////////////////////////////////////////////////////
+   //2D
+   //cell numbering:
+   //                  3---2
+   //                  |   |
+   //                  0---1
+   //nodenumbering must start with 0!
+
+   std::string writeQuads(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells);
+   std::string writeQuadsWithNodeData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& nodedata);
+   std::string writeQuadsWithCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, std::vector< std::string >& datanames, std::vector< std::vector< double > >& celldata);
+   std::string writeQuadsWithNodeAndCellData(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt4 >& cells, 
+                                             std::vector< std::string >& nodedatanames, std::vector< std::vector< double > >& nodedata, std::vector< std::string >& celldatanames,
+                                             std::vector< std::vector< double > >& celldata                                                                    );
+   
+   //////////////////////////////////////////////////////////////////////////
+   //octs
+   //     7 ---- 6
+   //    /|     /|
+   //   4 +--- 5 |
+   //   | |    | |
+   //   | 3 ---+ 2
+   //   |/     |/
+   //   0 ---- 1
+   std::string writeOcts(const std::string& filename,std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells);
+   std::string writeOctsWithCellData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata);
+   std::string writeOctsWithNodeData(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& nodedata);
+   
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<WbWriter>(*this);
+   }
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterVtkXmlBinary ,WbWriter>::getInstance()), CAB_WbWriterVtkXmlBinary);
+#endif
+
+#endif //WBWRITERVTKXMLBINARY_H
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterX3D.cpp b/source/VirtualFluidsCore/Basics/writer/WbWriterX3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..68eee613779233c44dbb0cf6c501c564a0bfdab2
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterX3D.cpp
@@ -0,0 +1,152 @@
+#include <basics/writer/WbWriterX3D.h>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+
+/*===============================================================================*/
+std::string WbWriterX3D::writeTriangles(const string& filename,vector<UbTupleFloat3 >& nodes, vector<UbTupleInt3 >& triangles)
+{
+   string X3DFilename=filename+getFileExtension();
+   UBLOG(logDEBUG1,"WbWriterX3D::writeTriangles to "<<X3DFilename<<" - start");
+
+   std::ofstream out(X3DFilename.c_str());
+   if(!out)
+   { 
+      out.clear(); //flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
+      string path = UbSystem::getPathFromString(X3DFilename);
+      if(path.size()>0){UbSystem::makeDirectory(path);out.open(X3DFilename.c_str());}
+      if(!out) throw UbException(UB_EXARGS,"couldn't open file "+X3DFilename);
+   }
+
+   // General part
+
+   //Root Element
+   out<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"																																 	   <<endl;
+   out<<"<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.1//EN\"   \"http://www.web3d.org/specifications/x3d-3.1.dtd\">"																	   <<endl;
+   out<<"<X3D profile='Interchange' version='3.1' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation=' http://www.web3d.org/specifications/x3d-3.1.xsd '>"<<endl<<endl;
+
+   //Head
+   out<<"<head>"										 <<endl;
+   out<<"<meta content='Simple X3D Writer for blender'/>"<<endl;
+   out<<"</head>"										 <<endl<<endl;
+
+	//Scene, Shape beginn 
+   out<<"<Scene>"            <<endl;
+   out<<"<Shape>"            <<endl;
+
+	//IndexedFaceSet => Polylinien der Dreiecke
+	out<<"<IndexedFaceSet  coordIndex=\""<<endl;
+
+	// TRIANGLES Ponits SECTION
+	int nofTriangles= (int)triangles.size(); 
+	//out<<"   triangles "<<nofTriangles<<endl;
+	for(int c=0; c<nofTriangles; c++)
+		out<<"      "<<val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<" -1"<<endl;
+	out<<"\">"            <<endl;
+    
+	//Coordinates
+	out<<"<Coordinate  point=\""    <<endl;
+
+	// Coordinates SECTION
+	int nofNodes = (int)nodes.size(); 
+	//out<<"   points "<<nofNodes<<endl;
+	for(int n=0; n<nofNodes; n++)
+		out<<"      "<< val<1>(nodes[n]) <<", "<< val<2>(nodes[n]) <<", "<< val<3>(nodes[n])<<", "<<endl;
+   out<<"\"/>"            <<endl;
+
+	//Footer
+	out<<"</IndexedFaceSet>"<< endl;
+	out<<"</Shape>"			<< endl;
+	out<<"</Scene>"         << endl;
+	out<<"</X3D>"           << endl;
+   
+
+   //// Image details
+   //out<<"image {"              <<endl;
+   //out<<"   resolution 640 480"<<endl;
+   //out<<"   aa 0 1"            <<endl;
+   //out<<"   filter mitchell"   <<endl;
+   //out<<"}"                    <<endl<<endl;
+
+   //// Camera position
+   //out<<"camera {"                 <<endl;
+   //out<<"   type pinhole"          <<endl;
+   //out<<"   eye    -0.25 -0.3 0.13"<<endl;
+   //out<<"   target -0.1 0.1 0.13"  <<endl;
+   //out<<"   up     0 0 1"          <<endl;
+   //out<<"   fov    60"             <<endl;
+   //out<<"   aspect 1.333333"       <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //// Light
+   //out<<"light {"                  <<endl;
+   //out<<"   type ibl"              <<endl;
+   //out<<"   image sky_small.hdr"   <<endl;
+   //out<<"   center 0 -1 0"         <<endl;
+   //out<<"   up 0 0 1"              <<endl;
+   //out<<"   lock true"             <<endl;
+   //out<<"   samples 200"           <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //// Shaders
+   //out<<"shader {"                 <<endl;
+   //out<<"   name default-shader"   <<endl;
+   //out<<"   type diffuse"          <<endl;
+   //out<<"   diff 0.25 0.25 0.25"   <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //out<<"shader {"                 <<endl;
+   //out<<"   name Glass"            <<endl;
+   //out<<"   type glass"            <<endl;
+   //out<<"   eta 1.333"             <<endl;
+   //out<<"   color 0.1 0.3 0.8"     <<endl;
+   //out<<"}"                        <<endl<<endl;
+   //                                
+   //out<<"shader {"                 <<endl;
+   //out<<"   name Mirror"           <<endl;
+   //out<<"   type mirror"           <<endl;
+   //out<<"   refl 0.7 0.7 0.7"      <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //// Objects
+   //// a) Ground plane
+   //out<<"object {"                 <<endl;
+   //out<<"   shader default-shader" <<endl;
+   //out<<"   type plane"            <<endl;
+   //out<<"   p 0 0 0"               <<endl;
+   //out<<"   n 0 0 1"               <<endl;
+   //out<<"}"                        <<endl<<endl;
+
+   //// b) Mesh
+   //out<<"object {"                 <<endl;
+   //out<<"   shader Glass"          <<endl;
+   //out<<"   transform {"           <<endl;
+   //out<<"      rotatey 270.0"      <<endl;
+   //out<<"   }"                     <<endl;
+   //out<<"   type generic-mesh"     <<endl;
+   //out<<"      name polySurfac"    <<endl<<endl;
+
+
+   //// POINTS SECTION
+   //int nofNodes = (int)nodes.size(); 
+   //out<<"   points "<<nofNodes<<endl;
+   //for(int n=0; n<nofNodes; n++)
+   //   out<<"      "<< val<1>(nodes[n]) <<" "<< val<2>(nodes[n]) <<" "<< val<3>(nodes[n]) <<endl;
+
+   //// TRIANGLES SECTION
+   //int nofTriangles= (int)triangles.size(); 
+   //out<<"   triangles "<<nofTriangles<<endl;
+   //for(int c=0; c<nofTriangles; c++)
+   //   out<<"      "<<val<1>(triangles[c]) <<" "<< val<2>(triangles[c])<<" "<< val<3>(triangles[c])<<endl;
+
+   //// FOOTER
+   //out<<"   normals none" << endl;
+   //out<<"   uvs none"     << endl;
+   //out<<"}"               << endl;
+
+   out.close();
+   UBLOG(logDEBUG1,"WbWriterX3D::writeTriangles to "<<X3DFilename<<" - end");
+
+   return X3DFilename;
+}
+/*===============================================================================*/
diff --git a/source/VirtualFluidsCore/Basics/writer/WbWriterX3D.h b/source/VirtualFluidsCore/Basics/writer/WbWriterX3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9c708c1215bb897d6ff58e5e30367b4b54505ae
--- /dev/null
+++ b/source/VirtualFluidsCore/Basics/writer/WbWriterX3D.h
@@ -0,0 +1,38 @@
+#ifndef WBWRITERX3D_H
+#define WBWRITERX3D_H
+
+#include <string>
+
+#include <basics/writer/WbWriter.h>
+
+class WbWriterX3D  : public WbWriter
+{
+public:
+   OBCREATOR_EXT( WbWriterX3D )
+
+   static WbWriterX3D* getInstance()
+   {
+      static WbWriterX3D instance;
+      return &instance;
+   }
+private:
+   WbWriterX3D() : WbWriter() 
+   {
+      if(sizeof(unsigned char)!=1) throw UbException(UB_EXARGS,"error char  type mismatch");
+      if(sizeof(int)          !=4) throw UbException(UB_EXARGS,"error int   type mismatch");
+      if(sizeof(float)        !=4) throw UbException(UB_EXARGS,"error float type mismatch");
+   }
+   WbWriterX3D( const WbWriterX3D& );                  //no copy allowed 
+   const WbWriterX3D& operator=( const WbWriterX3D& ); //no copy allowed
+
+   static std::string  pvdEndTag;
+
+public:
+   std::string getFileExtension()  { return "ascii.X3D"; }
+
+   std::string writeTriangles(const std::string& filename,std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt3 >& triangles);
+};
+
+UB_AUTO_RUN_NAMED(ObFactory<WbWriter>::getInstance()->addObCreator(ObSingletonCreatorImpl<WbWriterX3D ,WbWriter>::getInstance()), CAB_WbWriterX3D);
+
+#endif //WBWRITERX3D_H
diff --git a/source/VirtualFluidsCore/BoundaryCondition/BCArray.h b/source/VirtualFluidsCore/BoundaryCondition/BCArray.h
new file mode 100644
index 0000000000000000000000000000000000000000..704d0df69c86b9bfef0ef229a9704460bec95b40
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/BCArray.h
@@ -0,0 +1,289 @@
+#ifndef BCArray_H
+#define BCArray_H
+
+#include <typeinfo>
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/shared_ptr.hpp>
+
+class BCArray
+{
+public:
+   typedef typename boost::shared_ptr<BCArray> BCArrayPtr;
+   typedef std::size_t size_type;
+   typedef int IndexType;
+
+public:
+   //////////////////////////////////////////////////////////////////////////
+   BCArray() {}
+   //////////////////////////////////////////////////////////////////////////
+   virtual ~BCArray();
+   //////////////////////////////////////////////////////////////////////////
+   virtual inline size_type getNX1() const = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual inline size_type getNX2() const = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual inline size_type getNX3() const = 0;
+   //////////////////////////////////////////////////////////////////////////
+   void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3, const IndexType& val) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   bool validIndices(const size_type& x1, const size_type& x2, const size_type& x3)  const = 0;
+   //////////////////////////////////////////////////////////////////////////
+   inline bool hasBC(const size_type& x1, const size_type& x2, const size_type& x3)  const = 0;
+   //////////////////////////////////////////////////////////////////////////
+   void setBC(const size_type& x1, const size_type& x2, const size_type& x3, BCClassPtr const& bc)
+   {
+      if( this->hasBC(x1,x2,x3) )
+      {
+         if( this->getBC(x1,x2,x3)==bc ) return;
+         else                            this->deleteBC(x1,x2,x3);
+      }
+
+      //wenn keine frei gewordene BCs vorhanden
+      if( indexContainer.empty() )
+      {
+         bcvector.push_back(bc);
+         bcindexmatrix(x1,x2,x3) = (IndexType)bcvector.size()-1;
+      }
+      else
+      {
+         IndexType index = indexContainer.back();
+         bcindexmatrix(x1,x2,x3) = index;
+         bcvector[index] = bc;
+         indexContainer.pop_back();
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline IndexType getBCVectorIndex(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline const BCClassPtr getBC(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      IndexType index = bcindexmatrix(x1,x2,x3);
+      if(index<0) return BCClassPtr(); //=> NULL Pointer
+
+      return bcvector[index];
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline BCClassPtr getBC(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      IndexType index = bcindexmatrix(x1,x2,x3);
+      if(index<0) return BCClassPtr(); //=> NULL Pointer
+
+      return bcvector[index];
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setSolid(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      if( this->hasBC(x1,x2,x3) ) this->deleteBC(x1,x2,x3);
+      bcindexmatrix(x1,x2,x3)=SOLID;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool isSolid(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3)==SOLID;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setFluid(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      if( this->hasBC(x1,x2,x3) ) this->deleteBC(x1,x2,x3);
+      bcindexmatrix(x1,x2,x3)=FLUID;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //true : FLUID or BC
+   //false: UNDEFINED or SOLID
+   inline bool isFluid(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      int tmp = bcindexmatrix(x1,x2,x3);
+      return (tmp==FLUID || tmp>=0);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool isFluidWithoutBC(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3)==FLUID;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool isUndefined(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3)==UNDEFINED;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setUndefined(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      if( this->hasBC(x1,x2,x3) ) this->deleteBC(x1,x2,x3);
+      bcindexmatrix(x1,x2,x3)=UNDEFINED;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool isInterface(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3)==INTERFACE;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setInterface(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      if( this->hasBC(x1,x2,x3) ) this->deleteBC(x1,x2,x3);
+      bcindexmatrix(x1,x2,x3)=INTERFACE;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfSolidEntries() const 
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+         if(data[i]==SOLID) counter++;
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfFluidEntries() const 
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+      {
+         const IndexType& tmp = data[i];
+         if(tmp==FLUID || tmp>=0) counter++;
+      }
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfFluidWithoutBCEntries() const
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+         if(data[i]==FLUID) counter++;
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfBCEntries() const
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+         if(data[i]>=0) counter++;
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfUndefinedEntries() const
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+         if(data[i]==UNDEFINED) counter++;
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getBCVectorSize() const
+   {
+      return this->bcvector.size();
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::string toString() const
+   {
+      std::size_t solidCounter = 0;
+      std::size_t fluidCounter = 0;
+      std::size_t bcCounter    = 0;
+      std::size_t undefCounter = 0;
+
+      for(int x1=0; x1<bcindexmatrix.getNX1(); x1++)
+      {
+         for(int x2=0; x2<bcindexmatrix.getNX2(); x2++)
+         {
+            for(int x3=0; x3<bcindexmatrix.getNX3(); x3++)
+            {
+               if(bcindexmatrix(x1,x2,x3)>=0             ) bcCounter++;
+               else if(bcindexmatrix(x1,x2,x3)==FLUID    ) fluidCounter++;
+               else if(bcindexmatrix(x1,x2,x3)==SOLID    ) solidCounter++;
+               else if(bcindexmatrix(x1,x2,x3)==UNDEFINED) undefCounter++;
+               else throw UbException(UB_EXARGS,"invalid matrixEntry");
+            }
+         }
+      }
+
+      std::size_t unrefEntriesInBcVector=0;
+      for(std::size_t i=0; i<bcvector.size(); i++) if(!bcvector[i]) unrefEntriesInBcVector++;
+
+      std::stringstream text;
+      text<<"BCArray<"<<typeid(BCClass).name()<<","<<typeid(IndexType).name()<<">";
+      text<<"[ entries: "<<bcindexmatrix.getNX1()<<"x"<<bcindexmatrix.getNX2();
+      text<<"x"<<bcindexmatrix.getNX3()<<"=";
+      text<<bcindexmatrix.getNX1()*bcindexmatrix.getNX2()*bcindexmatrix.getNX3()<<" ]:\n";
+      text<<" - #fluid entries : "<<fluidCounter<<std::endl;
+      text<<" - #bc    entries : "<<bcCounter<<std::endl;
+      text<<" - #solid entries : "<<solidCounter<<std::endl;
+      text<<" - #undef entries : "<<undefCounter<<std::endl;
+      text<<" - bcvector-entries      : "<<bcvector.size()<<" (empty ones: "<<unrefEntriesInBcVector<<")\n";
+      text<<" - indexContainer-entries: "<<indexContainer.size()<<std::endl;
+
+      return text.str();
+   }
+   //////////////////////////////////////////////////////////////////////////
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      ar & bcindexmatrix;
+      ar & bcvector;
+      ar & indexContainer;
+   }
+#endif //CAB_RCF
+
+   static const IndexType SOLID;     //definiton erfolgt ausserhalb!!!
+   static const IndexType FLUID;     //definiton erfolgt ausserhalb!!!
+   static const IndexType INTERFACE; //definiton erfolgt ausserhalb!!!
+   static const IndexType UNDEFINED; //definiton erfolgt ausserhalb!!!
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   void deleteBCAndSetType(const size_type& x1, const size_type& x2, const size_type& x3, const IndexType& type)
+   {
+      this->deleteBC(x1,x2,x3);
+
+      //matrix neuen Typ zuweisen
+      bcindexmatrix(x1,x2,x3) = type;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void deleteBC(const size_type& x1,const size_type& x2, const size_type& x3)
+   {
+      //ueberpruefen, ob ueberhaupt BC vorhanden
+      IndexType index = bcindexmatrix(x1,x2,x3);
+      if(index<0) return;
+
+      //frei gewordenen Index in den Indexcontainer schieben
+      indexContainer.push_back(index);
+
+      //element "loeschen"
+      bcvector[index] = BCClassPtr();
+   }
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & bcindexmatrix;
+      ar & bcvector;
+      ar & indexContainer;
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   //CbArray3D<IndexType,IndexerX1X2X3> bcindexmatrix;  //-1 solid // -2 fluid -...
+   CbArray3D<IndexType,IndexerX3X2X1> bcindexmatrix;
+   std::vector<BCClassPtr> bcvector;
+   std::vector<IndexType> indexContainer;
+};
+
+template< typename BCClass , class IndexType>
+const IndexType BCArray<BCClass,IndexType>::SOLID  = -1;
+template< typename BCClass , class IndexType>
+const IndexType BCArray<BCClass,IndexType>::FLUID  = -2;
+template< typename BCClass , class IndexType> 
+const IndexType BCArray<BCClass,IndexType>::INTERFACE = -3;
+template< typename BCClass , class IndexType>
+const IndexType BCArray<BCClass,IndexType>::UNDEFINED = -4;
+
+#endif //D3Q19BCMATRIX_H
diff --git a/source/VirtualFluidsCore/BoundaryCondition/BCArray3D.h b/source/VirtualFluidsCore/BoundaryCondition/BCArray3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..f345f63600b7759214fac44b3b9c4f12fa2f0252
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/BCArray3D.h
@@ -0,0 +1,338 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef BCARRAY_H
+#define BCARRAY_H
+
+#include <basics/container/CbArray3D.h>
+#include <typeinfo>
+
+#include <boost/serialization/serialization.hpp>
+
+//IndexType must be int or long or short!!!
+//no unsiged!
+
+template< typename BCClass , class IndexType = int >
+class BCArray3D
+{
+public:
+   typedef typename boost::shared_ptr<BCClass> BCClassPtr;
+   typedef std::size_t size_type;
+
+public:
+   //////////////////////////////////////////////////////////////////////////
+   BCArray3D() {}
+   //////////////////////////////////////////////////////////////////////////
+   BCArray3D(const size_type& nx1, const size_type& nx2, const size_type& nx3)
+   {
+      bcindexmatrix.resize(nx1,nx2,nx3,UNDEFINED);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   BCArray3D(const size_type& nx1, const size_type& nx2, const size_type& nx3, const IndexType& val)
+   {
+      bcindexmatrix.resize(nx1,nx2,nx3,val);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   virtual ~BCArray3D() {}
+   //////////////////////////////////////////////////////////////////////////
+   inline size_type getNX1() const { return bcindexmatrix.getNX1(); }
+   //////////////////////////////////////////////////////////////////////////
+   inline size_type getNX2() const { return bcindexmatrix.getNX2(); }
+   //////////////////////////////////////////////////////////////////////////
+   inline size_type getNX3() const { return bcindexmatrix.getNX3(); }
+   //////////////////////////////////////////////////////////////////////////
+   void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3)
+   {
+      bcindexmatrix.resize(nx1,nx2,nx3);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void resize(const size_type& nx1, const size_type& nx2, const size_type& nx3, const IndexType& val)
+   {
+      bcindexmatrix.resize(nx1,nx2,nx3,val);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   bool validIndices(const size_type& x1, const size_type& x2, const size_type& x3)  const
+   {
+      if( x1 < 0 || x1 >= this->bcindexmatrix.getNX1()) return false;
+      if( x2 < 0 || x2 >= this->bcindexmatrix.getNX2()) return false;
+      if( x3 < 0 || x3 >= this->bcindexmatrix.getNX3()) return false;
+      return true;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool hasBC(const size_type& x1, const size_type& x2, const size_type& x3)  const
+   {
+      return bcindexmatrix(x1,x2,x3)>=0;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setBC(const size_type& x1, const size_type& x2, const size_type& x3, BCClassPtr const& bc)
+   {
+      if( this->hasBC(x1,x2,x3) )
+      {
+         if( this->getBC(x1,x2,x3)==bc ) return;
+         else                            this->deleteBC(x1,x2,x3);
+      }
+
+      //wenn keine frei gewordene BCs vorhanden
+      if( indexContainer.empty() )
+      {
+         bcvector.push_back(bc);
+         bcindexmatrix(x1,x2,x3) = (IndexType)bcvector.size()-1;
+      }
+      else
+      {
+         IndexType index = indexContainer.back();
+         bcindexmatrix(x1,x2,x3) = index;
+         bcvector[index] = bc;
+         indexContainer.pop_back();
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline IndexType getBCVectorIndex(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline const BCClassPtr getBC(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      IndexType index = bcindexmatrix(x1,x2,x3);
+      if(index<0) return BCClassPtr(); //=> NULL Pointer
+
+      return bcvector[index];
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline BCClassPtr getBC(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      IndexType index = bcindexmatrix(x1,x2,x3);
+      if(index<0) return BCClassPtr(); //=> NULL Pointer
+
+      return bcvector[index];
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setSolid(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      if( this->hasBC(x1,x2,x3) ) this->deleteBC(x1,x2,x3);
+      bcindexmatrix(x1,x2,x3)=SOLID;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool isSolid(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3)==SOLID;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setFluid(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      if( this->hasBC(x1,x2,x3) ) this->deleteBC(x1,x2,x3);
+      bcindexmatrix(x1,x2,x3)=FLUID;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //true : FLUID or BC
+   //false: UNDEFINED or SOLID
+   inline bool isFluid(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      int tmp = bcindexmatrix(x1,x2,x3);
+      return (tmp==FLUID || tmp>=0);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool isFluidWithoutBC(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3)==FLUID;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool isUndefined(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1,x2,x3)==UNDEFINED;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setUndefined(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      if( this->hasBC(x1,x2,x3) ) this->deleteBC(x1,x2,x3);
+      bcindexmatrix(x1,x2,x3)=UNDEFINED;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //inline bool isInterface(const size_type& x1, const size_type& x2, const size_type& x3) const
+   //{
+   //   return bcindexmatrix(x1,x2,x3)==INTERFACE;
+   //}
+   ////////////////////////////////////////////////////////////////////////////
+   //void setInterface(const size_type& x1, const size_type& x2, const size_type& x3)
+   //{
+   //   if( this->hasBC(x1,x2,x3) ) this->deleteBC(x1,x2,x3);
+   //   bcindexmatrix(x1,x2,x3)=INTERFACE;
+   //}
+   inline bool isInterfaceCF(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1, x2, x3)==INTERFACECF;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setInterfaceCF(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      //if (this->hasBC(x1, x2, x3)) this->deleteBC(x1, x2, x3);
+      bcindexmatrix(x1, x2, x3) = INTERFACECF;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline bool isInterfaceFC(const size_type& x1, const size_type& x2, const size_type& x3) const
+   {
+      return bcindexmatrix(x1, x2, x3)==INTERFACEFC;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void setInterfaceFC(const size_type& x1, const size_type& x2, const size_type& x3)
+   {
+      //if (this->hasBC(x1, x2, x3)) this->deleteBC(x1, x2, x3);
+      bcindexmatrix(x1, x2, x3) = INTERFACEFC;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfSolidEntries() const 
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+         if(data[i]==SOLID) counter++;
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfFluidEntries() const 
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+      {
+         const IndexType& tmp = data[i];
+         if(tmp==FLUID || tmp>=0) counter++;
+      }
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfFluidWithoutBCEntries() const
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+         if(data[i]==FLUID) counter++;
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfBCEntries() const
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+         if(data[i]>=0) counter++;
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getNumberOfUndefinedEntries() const
+   {
+      const std::vector<IndexType>& data = bcindexmatrix.getDataVector();
+      std::size_t counter = 0;
+      for(std::size_t i=0; i<data.size(); i++)
+         if(data[i]==UNDEFINED) counter++;
+      return counter;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::size_t getBCVectorSize() const
+   {
+      return this->bcvector.size();
+   }
+   //////////////////////////////////////////////////////////////////////////
+   std::string toString() const
+   {
+      std::size_t solidCounter = 0;
+      std::size_t fluidCounter = 0;
+      std::size_t bcCounter    = 0;
+      std::size_t undefCounter = 0;
+
+      for(int x1=0; x1<bcindexmatrix.getNX1(); x1++)
+      {
+         for(int x2=0; x2<bcindexmatrix.getNX2(); x2++)
+         {
+            for(int x3=0; x3<bcindexmatrix.getNX3(); x3++)
+            {
+               if(bcindexmatrix(x1,x2,x3)>=0             ) bcCounter++;
+               else if(bcindexmatrix(x1,x2,x3)==FLUID    ) fluidCounter++;
+               else if(bcindexmatrix(x1,x2,x3)==SOLID    ) solidCounter++;
+               else if(bcindexmatrix(x1,x2,x3)==UNDEFINED) undefCounter++;
+               else throw UbException(UB_EXARGS,"invalid matrixEntry");
+            }
+         }
+      }
+
+      std::size_t unrefEntriesInBcVector=0;
+      for(std::size_t i=0; i<bcvector.size(); i++) if(!bcvector[i]) unrefEntriesInBcVector++;
+
+      std::stringstream text;
+      text<<"BCArray3D<"<<typeid(BCClass).name()<<","<<typeid(IndexType).name()<<">";
+      text<<"[ entries: "<<bcindexmatrix.getNX1()<<"x"<<bcindexmatrix.getNX2();
+      text<<"x"<<bcindexmatrix.getNX3()<<"=";
+      text<<bcindexmatrix.getNX1()*bcindexmatrix.getNX2()*bcindexmatrix.getNX3()<<" ]:\n";
+      text<<" - #fluid entries : "<<fluidCounter<<std::endl;
+      text<<" - #bc    entries : "<<bcCounter<<std::endl;
+      text<<" - #solid entries : "<<solidCounter<<std::endl;
+      text<<" - #undef entries : "<<undefCounter<<std::endl;
+      text<<" - bcvector-entries      : "<<bcvector.size()<<" (empty ones: "<<unrefEntriesInBcVector<<")\n";
+      text<<" - indexContainer-entries: "<<indexContainer.size()<<std::endl;
+
+      return text.str();
+   }
+//////////////////////////////////////////////////////////////////////////
+
+   static const IndexType SOLID;     //definiton erfolgt ausserhalb!!!
+   static const IndexType FLUID;     //definiton erfolgt ausserhalb!!!
+   //static const IndexType INTERFACE; //definiton erfolgt ausserhalb!!!
+   static const IndexType INTERFACECF; //definiton erfolgt ausserhalb!!!
+   static const IndexType INTERFACEFC; //definiton erfolgt ausserhalb!!!
+   static const IndexType UNDEFINED; //definiton erfolgt ausserhalb!!!
+
+private:
+   //////////////////////////////////////////////////////////////////////////
+   void deleteBCAndSetType(const size_type& x1, const size_type& x2, const size_type& x3, const IndexType& type)
+   {
+      this->deleteBC(x1,x2,x3);
+
+      //matrix neuen Typ zuweisen
+      bcindexmatrix(x1,x2,x3) = type;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   void deleteBC(const size_type& x1,const size_type& x2, const size_type& x3)
+   {
+      //ueberpruefen, ob ueberhaupt BC vorhanden
+      IndexType index = bcindexmatrix(x1,x2,x3);
+      if(index<0) return;
+
+      //frei gewordenen Index in den Indexcontainer schieben
+      indexContainer.push_back(index);
+
+      //element "loeschen"
+      bcvector[index] = BCClassPtr();
+   }
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & bcindexmatrix;
+      ar & bcvector;
+      ar & indexContainer;
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   //CbArray3D<IndexType,IndexerX1X2X3> bcindexmatrix;  //-1 solid // -2 fluid -...
+   CbArray3D<IndexType,IndexerX3X2X1> bcindexmatrix;
+   std::vector<BCClassPtr> bcvector;
+   std::vector<IndexType> indexContainer;
+};
+
+template< typename BCClass , class IndexType>
+const IndexType BCArray3D<BCClass,IndexType>::SOLID  = -1;
+template< typename BCClass , class IndexType>
+const IndexType BCArray3D<BCClass,IndexType>::FLUID  = -2;
+template< typename BCClass , class IndexType> 
+const IndexType BCArray3D<BCClass,IndexType>::INTERFACECF = -3;
+template< typename BCClass, class IndexType>
+const IndexType BCArray3D<BCClass, IndexType>::INTERFACEFC = -4;
+template< typename BCClass , class IndexType>
+const IndexType BCArray3D<BCClass,IndexType>::UNDEFINED = -5;
+
+#endif //D3Q19BCMATRIX_H
diff --git a/source/VirtualFluidsCore/BoundaryCondition/BCProcessor.cpp b/source/VirtualFluidsCore/BoundaryCondition/BCProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6e2f2589e364812052f21e34da8fb790d0271bd2
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/BCProcessor.cpp
@@ -0,0 +1,9 @@
+#include "BCProcessor.h"
+
+BCProcessor::BCProcessor()
+{}
+//////////////////////////////////////////////////////////////////////////
+BCProcessor::~BCProcessor()
+{}
+//////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/BCProcessor.h b/source/VirtualFluidsCore/BoundaryCondition/BCProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7711926889fd321e52456a2b047d93260c8abf0
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/BCProcessor.h
@@ -0,0 +1,36 @@
+#ifndef BCPROCESSOR_H
+#define BCPROCESSOR_H
+
+#include "EsoTwist3D.h"
+
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/shared_ptr.hpp>
+
+class BCProcessor;
+typedef boost::shared_ptr<BCProcessor> BCProcessorPtr;
+
+#include "LBMKernel3D.h"
+#include "BoundaryCondition.h"
+
+class BCProcessor
+{
+public:
+   BCProcessor();
+   virtual ~BCProcessor();
+   virtual void applyBC() = 0;
+   virtual void applyPreCollisionBC() = 0;
+   virtual void applyPostCollisionBC() = 0;
+   virtual void addBC(BoundaryConditionPtr bc) = 0;
+   virtual BoundaryConditionPtr getBC(BoundaryCondition::Type type) = 0;
+   virtual BCProcessorPtr clone(LBMKernel3DPtr kernel) = 0;
+protected:
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+   }
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/BoundaryCondition/BoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/BoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..caba2663dbb775a386982d2e4df91ebc27cd1275
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/BoundaryCondition.cpp
@@ -0,0 +1,101 @@
+#include "BoundaryCondition.h"
+
+BoundaryCondition::BoundaryCondition() : compressible(false)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryCondition::apply()
+{
+   if (this->compressible)
+   {
+      //rho0 = REAL_CAST(0.0);
+      calcFeqsForDirFct = &D3Q27System::getCompFeqForDirection;
+      calcMacrosFct = &D3Q27System::calcCompMacroscopicValues;
+      calcFeqFct = &D3Q27System::calcCompFeq;
+   }
+   else
+   {
+      //rho0 = REAL_CAST(1.0);
+      calcFeqsForDirFct = &D3Q27System::getIncompFeqForDirection;
+      calcMacrosFct = &D3Q27System::calcIncompMacroscopicValues;
+      calcFeqFct = &D3Q27System::calcIncompFeq;
+   }
+
+   int cbc = 0;
+   int cn = 0;
+   int j;
+   //int dsize = (int)distVector.size();
+
+   //for (int i = 0; i < dsize; i++)
+   //{
+   //   distributions = distVector[i];
+      //int nsize = (int)sizeVector[i] * 3 + cn;
+   int nsize = (int)nodeVector.size();
+
+      for (j = cn; j < nsize;)
+      {
+         x1 = nodeVector[j++];
+         x2 = nodeVector[j++];
+         x3 = nodeVector[j++];
+
+         bcPtr = bcVector[cbc];
+         cbc++;
+
+         applyBC();
+      }
+      cn = j;
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+//void BoundaryCondition::apply()
+//{
+//}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryCondition::addDistributions(EsoTwist3DPtr distributions)
+{
+   //distVector.push_back(distribution);
+   this->distributions = distributions;
+}
+//////////////////////////////////////////////////////////////////////////
+//void BoundaryCondition::addNnode(int nnode)
+//{
+//   sizeVector.push_back(nnode);
+//}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryCondition::addNode(int x1, int x2, int x3)
+{
+   nodeVector.push_back(x1);
+   nodeVector.push_back(x2);
+   nodeVector.push_back(x3);
+}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryCondition::addBcPointer(D3Q27BoundaryConditionPtr bcPtr)
+{
+   bcVector.push_back(bcPtr);
+}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryCondition::setCompressible(bool c)
+{
+   compressible = c;
+}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryCondition::setCollFactor(LBMReal cf)
+{
+   collFactor = cf;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BoundaryCondition::Type BoundaryCondition::getType()
+{
+   return type;
+}
+//////////////////////////////////////////////////////////////////////////
+bool BoundaryCondition::isPreCollision()
+{
+   return preCollision;
+}
+
+
+
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/BoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/BoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f88d4a05208bf79367dc0c1dadd1e989be715fe
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/BoundaryCondition.h
@@ -0,0 +1,86 @@
+
+#ifndef BOUNDARYCONDITION_H
+#define BOUNDARYCONDITION_H
+
+#include <vector>
+#include <string>
+
+#include "D3Q27BoundaryCondition.h"
+#include "D3Q27System.h"
+#include "EsoTwist3D.h"
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/export.hpp>
+
+#include <boost/shared_ptr.hpp>
+
+class BoundaryCondition;
+typedef boost::shared_ptr<BoundaryCondition> BoundaryConditionPtr;
+
+class BoundaryCondition
+{
+public:
+   enum Type
+   {
+      Velocity, Density, NoSlip, Slip 
+   };
+public:
+   BoundaryCondition();
+   virtual ~BoundaryCondition() {}
+   
+   //void apply(int level);
+
+   //void addDistribution(int level, EsoTwist3DPtr distribution);
+   //void addNnode(int level, int nnode);
+   //void addNode(int level, int x1, int x2, int x3);
+   //void addBcPointer(int level, D3Q27BoundaryConditionPtr bcPtr);
+   //void setCompressible(bool c);
+   //void setCollFactor(int level, double cf);
+   void apply();
+
+   void addDistributions(EsoTwist3DPtr distributions);
+   //void addNnode(int nnode);
+   void addNode(int x1, int x2, int x3);
+   void addBcPointer(D3Q27BoundaryConditionPtr bcPtr);
+   void setCompressible(bool c);
+   void setCollFactor(LBMReal cf);
+   BoundaryCondition::Type getType();
+   bool isPreCollision();
+   virtual BoundaryConditionPtr clone()=0;
+protected:
+   virtual void applyBC() = 0;
+   
+   //std::vector <EsoTwist3DPtr> distVector;
+   //std::vector <int> sizeVector;
+   std::vector <int> nodeVector;
+   std::vector <D3Q27BoundaryConditionPtr> bcVector;
+
+   bool compressible;
+   Type type;
+   bool preCollision;
+
+   D3Q27BoundaryConditionPtr bcPtr;
+   EsoTwist3DPtr distributions;
+   EsoTwist3DPtr distributionsTemp;
+   LBMReal collFactor;
+   int x1, x2, x3;
+
+   typedef void(*CalcMacrosFct)(const LBMReal* const& /*f[27]*/, LBMReal& /*rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   typedef LBMReal(*CalcFeqForDirFct)(const int& /*direction*/, const LBMReal& /*(d)rho*/, const LBMReal& /*vx1*/, const LBMReal& /*vx2*/, const LBMReal& /*vx3*/);
+   typedef  void(*CalcFeqFct)(LBMReal* const& /*feq/*[27]*/, const LBMReal& /*rho*/, const LBMReal& /*vx1*/, const LBMReal& /*vx2*/, const LBMReal& /*vx3*/);
+   
+   CalcFeqForDirFct calcFeqsForDirFct ;
+   CalcMacrosFct    calcMacrosFct;
+   CalcFeqFct       calcFeqFct;
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+   }
+};
+
+
+#endif 
diff --git a/source/VirtualFluidsCore/BoundaryCondition/BoundaryConditionProcessor.cpp b/source/VirtualFluidsCore/BoundaryCondition/BoundaryConditionProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5234a86aa0f3fde616c50a0f82942aa90de04069
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/BoundaryConditionProcessor.cpp
@@ -0,0 +1,58 @@
+#include "BoundaryConditionProcessor.h"
+#include <boost/foreach.hpp>
+
+BoundaryConditionProcessor::BoundaryConditionProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryConditionProcessor::addBC(BoundaryConditionPtr bc)
+{
+   BoundaryCondition::Type type = bc->getType();
+   if (bc->isPreCollision())
+   {
+      preBC.push_back(bc);
+   }
+   else
+   {
+      postBC.push_back(bc);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr BoundaryConditionProcessor::getBC(BoundaryCondition::Type type)
+{
+   BOOST_FOREACH(BoundaryConditionPtr bc, preBC)
+   {
+     if (bc->getType() == type)
+     {
+        return bc;
+     }
+   }
+
+   BOOST_FOREACH(BoundaryConditionPtr bc, postBC)
+   {
+      if (bc->getType() == type)
+      {
+         return bc;
+      }
+   }
+
+   return BoundaryConditionPtr();
+}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryConditionProcessor::applyPreCollisionBC()
+{
+   BOOST_FOREACH(BoundaryConditionPtr bc, preBC)
+   {
+      bc->apply();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryConditionProcessor::applyPostCollisionBC()
+{
+   BOOST_FOREACH(BoundaryConditionPtr bc, postBC)
+   {
+      bc->apply();
+   }
+}
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/BoundaryConditionProcessor.h b/source/VirtualFluidsCore/BoundaryCondition/BoundaryConditionProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f8bb152279d193d767b37790df4abe2f14bc635
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/BoundaryConditionProcessor.h
@@ -0,0 +1,26 @@
+#ifndef BoundaryConditionProcessor_h__
+#define BoundaryConditionProcessor_h__
+
+#include "BoundaryCondition.h"
+#include <vector>
+
+class BoundaryConditionProcessor;
+typedef boost::shared_ptr<BoundaryConditionProcessor> BoundaryConditionProcessorPtr;
+
+class BoundaryConditionProcessor
+{
+public:
+   BoundaryConditionProcessor();
+   virtual ~BoundaryConditionProcessor() {}
+
+   void addBC(BoundaryConditionPtr bc);
+   BoundaryConditionPtr getBC(BoundaryCondition::Type type);
+   void applyPreCollisionBC();
+   void applyPostCollisionBC();
+protected:
+private:
+   std::vector<BoundaryConditionPtr> preBC;
+   std::vector<BoundaryConditionPtr> postBC;
+};
+
+#endif // BoundaryConditionProcessor_h__
diff --git a/source/VirtualFluidsCore/BoundaryCondition/CMakePackage.txt b/source/VirtualFluidsCore/BoundaryCondition/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de1dc5a88225180b8e40c6cf46f4a6fbb102778f
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
\ No newline at end of file
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27BCFunction.cpp b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BCFunction.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d4489cee079ca7f2ab422634ac2e495a257aa4e
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BCFunction.cpp
@@ -0,0 +1,5 @@
+#include "D3Q27BCFunction.h"
+
+const double D3Q27BCFunction::INFTIMEDEPENDENT = -1.0;
+const double D3Q27BCFunction::INFCONST         = -10.0;
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27BCFunction.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BCFunction.h
new file mode 100644
index 0000000000000000000000000000000000000000..7090afd4c17dde17a5eec219c89def1272b5494d
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BCFunction.h
@@ -0,0 +1,117 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef D3Q27BCFUNCTION_H
+#define D3Q27BCFUNCTION_H
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/split_member.hpp>
+
+#include <basics/utilities/UbInfinity.h>
+
+#include <MuParser/include/muParser.h>
+
+
+class D3Q27BCFunction
+{
+public:
+   static const double INFTIMEDEPENDENT;
+   static const double INFCONST;
+
+public:
+   D3Q27BCFunction() 
+      : starttime(-Ub::inf ), endtime(-Ub::inf ) 
+   {
+
+   }
+   D3Q27BCFunction( const mu::Parser& function, const double& starttime, const double& endtime )
+      : function(function), starttime(starttime), endtime(endtime)
+   {
+
+   }
+   D3Q27BCFunction( const std::string& functionstring, const double& starttime, const double& endtime )
+      : starttime(starttime), endtime(endtime)
+   {
+      this->setFunction(functionstring); 
+   }
+   D3Q27BCFunction( const double& velocity, const double& starttime, const double& endtime )
+      : starttime(starttime), endtime(endtime)
+   {
+      this->setFunction(velocity); 
+   }
+
+   void setFunction(const mu::Parser& function) { this->function = function; }
+   void setFunction(const std::string& functionstring) { this->function.SetExpr(functionstring); }
+   void setFunction(const double& constVelocity) { std::stringstream dummy; dummy<<constVelocity; function.SetExpr(dummy.str());  }
+   void setStartTime(const double& starttime) {this->starttime = starttime; }
+   void setEndTime(const double& starttime) {this->endtime = endtime; }
+
+   mu::Parser&        getFunction()        { return function;  }
+   const mu::Parser&  getFunction()  const { return function;  }
+   const double&      getStartTime() const { return starttime; }
+   const double&      getEndTime()   const { return endtime;   }
+
+   std::string toString() const
+   {
+      std::stringstream info;
+      if     (starttime==INFTIMEDEPENDENT) info<<"start=inf. timedep., ";
+      else if(starttime==INFCONST        ) info<<"start=inf. const., ";
+      else                                 info<<"start="<<starttime<<", ";
+      if     (endtime==INFTIMEDEPENDENT) info<<"end=inf. timedep."<<std::endl;
+      else if(endtime==INFCONST        ) info<<"end=inf. const."<<std::endl;
+      else                               info<<"end="<<endtime<<std::endl;
+      info<<"expr="<<function.GetExpr()<<std::endl;
+      info<<"with constants: ";
+      mu::valmap_type cmap = function.GetConst();
+      for(mu::valmap_type::const_iterator item = cmap.begin(); item!=cmap.end(); ++item)
+         info<<item->first<<"="<<item->second<<", ";
+      return info.str();
+   }
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, const D3Q27BCFunction& bc) 
+   {
+      os<<bc.toString();
+      return os;
+   }
+
+protected:
+   mu::Parser function;
+   double starttime;
+   double endtime;
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void save(Archive & ar, const unsigned int version) const
+   {
+      mu::string_type expr = function.GetExpr();
+      mu::valmap_type constants = function.GetConst();
+      ar & expr;
+      ar & constants;
+
+      ar & starttime;
+      ar & endtime;
+   }
+   template<class Archive>
+   void load(Archive & ar, const unsigned int version)
+   {
+      mu::string_type expr;
+      mu::valmap_type constants;
+      ar & expr;
+      ar & constants;
+      function.SetExpr(expr);
+      for (mu::valmap_type::iterator pos = constants.begin(); pos!=constants.end(); ++pos)
+         function.DefineConst(pos->first, pos->second);
+
+      function.InitConst();
+
+      ar & starttime;
+      ar & endtime;
+   }
+   BOOST_SERIALIZATION_SPLIT_MEMBER()
+};
+
+#endif //D3Q27BCFUNCTION_H
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ac1e0b1dceaf04c7fe9c4a12aa671cea7e85b29c
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryCondition.cpp
@@ -0,0 +1,4 @@
+#include "D3Q27BoundaryCondition.h"
+
+const long long D3Q27BoundaryCondition::maxOptionVal = ( 1<<optionDigits ) - 1; //2^3-1 -> 7 
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..99d8e63c533a3fa1b57ff4a76c8bc9b72ba13b5f
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryCondition.h
@@ -0,0 +1,282 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef D3Q27BOUNDARYCONDITION_H
+#define D3Q27BOUNDARYCONDITION_H
+
+#include <vector>
+#include <string>
+
+#include <basics/utilities/UbException.h>                  
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbTuple.h>
+#include "D3Q27System.h"
+
+#include <boost/serialization/serialization.hpp>
+
+class D3Q27BoundaryCondition;
+typedef boost::shared_ptr<D3Q27BoundaryCondition> D3Q27BoundaryConditionPtr;
+
+class D3Q27BoundaryCondition 
+{
+public:
+   D3Q27BoundaryCondition() 
+      : noslipBoundaryFlags(0)		
+      , slipBoundaryFlags(0)		
+      , velocityBoundaryFlags(0)		
+      , densityBoundaryFlags(0)		
+      , wallModelBoundaryFlags(0)
+      , bcVelocityX1(0.0f)
+      , bcVelocityX2(0.0f)
+      , bcVelocityX3(0.0f)
+      , bcDensity(0.0f)
+      , bcLodiDensity(0.0f)
+      , bcLodiVelocityX1(0.0f)
+      , bcLodiVelocityX2(0.0f)
+      , bcLodiVelocityX3(0.0f)
+      , bcLodiLentgh(0.0f)
+      , nx1(0.0f)
+      , nx2(0.0f)
+      , nx3(0.0f)
+   {
+      //wenn folgendes nicht geht, dann hat man weiter unten bei der bit-geschichte ein ernstes problem!!!
+      UB_STATIC_ASSERT( sizeof(long long) >= 8);
+      //UB_STATIC_ASSERT( sizeof(double) >= 16);
+      //UB_STATIC_ASSERT( sizeof(long long) == 32);
+      UB_STATIC_ASSERT( (sizeof(long long)*8) >= (D3Q27System::FENDDIR+1)*D3Q27BoundaryCondition::optionDigits );
+
+      for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++) 
+         q[fdir] = -999.; 
+   }
+   virtual ~D3Q27BoundaryCondition() {}
+
+   virtual bool isEmpty() { return (noslipBoundaryFlags&slipBoundaryFlags&velocityBoundaryFlags&densityBoundaryFlags)==0;}
+   virtual bool hasBoundaryCondition()
+   {
+      return (  hasNoSlipBoundary() || hasSlipBoundary() 
+             || hasDensityBoundary() || hasVelocityBoundary() || hasWallModelBoundary() );
+   }
+
+   virtual bool hasBoundaryConditionFlag(const int& direction)
+   {
+      assert( direction >= D3Q27System::FSTARTDIR && direction <= D3Q27System::FENDDIR );
+
+      return (   hasNoSlipBoundaryFlag(direction) || hasSlipBoundaryFlag(direction) 
+              || hasDensityBoundaryFlag(direction) || hasVelocityBoundaryFlag(direction)  || hasWallModelBoundaryFlag(direction));
+   }
+protected:
+   void setFlagBits(long long& flag, const int& direction, const short& secOpt)
+   {
+      if( (secOpt+1)>maxOptionVal ) 
+         throw UbException(UB_EXARGS,"error: option > "+UbSystem::toString(maxOptionVal-1));
+      
+      //alle digits an den betreffenden postionen auf "0"
+      flag &= ~( maxOptionVal<<(direction*optionDigits) );
+      //alle digitsan den betreffenden postionen entsprechend der marke setzen
+      flag |= ((long long)(secOpt+1)<<(direction*optionDigits));
+   }
+public:
+   /*===================== NoSlip Boundary ==================================================*/	
+   void       setNoSlipBoundaryFlag(const int& direction, const short& secOpt=0)    { this->setFlagBits(noslipBoundaryFlags,direction,secOpt);                                     }  
+   void       unsetNoSlipBoundaryFlag(const int& direction)                         { this->noslipBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) );                    }
+   void       unsetNoSlipBoundary()                                                 { this->noslipBoundaryFlags = 0;                                                               }
+   long long  getNoSlipBoundary()	                                                { return this->noslipBoundaryFlags;                                                            }
+   bool       hasNoSlipBoundary()					                                    { return (noslipBoundaryFlags!=0);                                                             }
+   bool       hasNoSlipBoundaryFlag(const int& direction)                           { return ( ( ( noslipBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0);         }
+   short      getNoSlipSecondaryOption(const int& direction)                        { return (short)( (  ( noslipBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); }
+   /*===================== WallModel Boundary ==================================================*/	
+   void       setWallModelBoundaryFlag(const int& direction, const short& secOpt=0) { this->setFlagBits(wallModelBoundaryFlags,direction,secOpt);                                     }  
+   void       unsetWallModelBoundaryFlag(const int& direction)                      { this->wallModelBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) );                    }
+   void       unsetWallModelBoundary()                                              { this->wallModelBoundaryFlags = 0;                                                               }
+   long long  getWallModelBoundary()	                                             { return this->wallModelBoundaryFlags;                                                            }
+   bool       hasWallModelBoundary()					                                 { return (wallModelBoundaryFlags!=0);                                                             }
+   bool       hasWallModelBoundaryFlag(const int& direction)                        { return ( ( ( wallModelBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0);         }
+   short      getWallModelSecondaryOption(const int& direction)                     { return (short)( (  ( wallModelBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); }
+   /*===================== Slip-Solid Boundary ==================================================*/	
+   void       setSlipBoundaryFlag(const int& direction, const short& secOpt=0)      { this->setFlagBits(slipBoundaryFlags,direction,secOpt);                                     }  
+   void       unsetSlipBoundaryFlag(const int& direction)                           { this->slipBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) );                    }
+   void       unsetSlipBoundary()                                                   { this->slipBoundaryFlags = 0;                                                               }
+   long long  getSlipBoundary()	                                                   { return this->slipBoundaryFlags;                                                            }
+   bool       hasSlipBoundary()					                                       { return (slipBoundaryFlags!=0);                                                             }
+   bool       hasSlipBoundaryFlag(const int& direction)	                           { return ( ( ( slipBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0);         }
+   short      getSlipSecondaryOption(const int& direction)                          { return (short)( (  ( slipBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); }
+   void       setNormalVector(const float& nx1,const float& nx2,const float& nx3)   { this->nx1 = nx1; this->nx2 = nx2;  this->nx3 = nx3;}
+   UbTupleFloat3 getNormalVector()                                                  { return makeUbTuple(nx1,nx2,nx3); }
+
+   /*============== Velocity Boundary ========================*/
+   void       setVelocityBoundaryFlag(const int& direction, const short& secOpt=0)  { this->setFlagBits(velocityBoundaryFlags,direction,secOpt);                                     }  
+   void       unsetVelocityBoundaryFlag(const int& direction)                       { this->velocityBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) );                    }
+   void       unsetVelocityBoundary()                 		                        { this->velocityBoundaryFlags = 0;                                                               }
+   long long  getVelocityBoundary()	               		                           { return this->velocityBoundaryFlags;                                                            }
+   bool       hasVelocityBoundary()   					 		                           { return this->velocityBoundaryFlags!=0;                                                         }
+   bool       hasVelocityBoundaryFlag(const int& direction)                         { return ( ( ( velocityBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0);         }
+   short      getVelocitySecondaryOption(const int& direction)                      { return (short)( (  ( velocityBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); }
+
+   void  setBoundaryVelocityX1(const float& vx1) { this->bcVelocityX1 = vx1;  } 
+   void  setBoundaryVelocityX2(const float& vx2) { this->bcVelocityX2 = vx2;  } 
+   void  setBoundaryVelocityX3(const float& vx3) { this->bcVelocityX3 = vx3;  } 
+   float getBoundaryVelocityX1()                 { return this->bcVelocityX1; }
+   float getBoundaryVelocityX2()                 { return this->bcVelocityX2; }
+   float getBoundaryVelocityX3()                 { return this->bcVelocityX3; }
+   float getBoundaryVelocity(const int& direction) 
+   {                   
+      switch(direction)
+      {
+      case D3Q27System::E : return (float)( UbMath::c4o9*(+bcVelocityX1) );      //(2/cs^2)(=6)*rho_0(=1 bei imkompr)*wi*u*ei mit cs=1/sqrt(3)
+      case D3Q27System::W : return (float)( UbMath::c4o9*(-bcVelocityX1) );      //z.B. aus paper manfred MRT LB models in three dimensions (2002)   
+      case D3Q27System::N : return (float)( UbMath::c4o9*(+bcVelocityX2) );   
+      case D3Q27System::S : return (float)( UbMath::c4o9*(-bcVelocityX2) );
+      case D3Q27System::T : return (float)( UbMath::c4o9*(+bcVelocityX3) );
+      case D3Q27System::B : return (float)( UbMath::c4o9*(-bcVelocityX3) );
+      case D3Q27System::NE: return (float)( UbMath::c1o9*(+bcVelocityX1+bcVelocityX2             ) );
+      case D3Q27System::SW: return (float)( UbMath::c1o9*(-bcVelocityX1-bcVelocityX2             ) );
+      case D3Q27System::SE: return (float)( UbMath::c1o9*(+bcVelocityX1-bcVelocityX2             ) );
+      case D3Q27System::NW: return (float)( UbMath::c1o9*(-bcVelocityX1+bcVelocityX2             ) );
+      case D3Q27System::TE: return (float)( UbMath::c1o9*(+bcVelocityX1             +bcVelocityX3) );
+      case D3Q27System::BW: return (float)( UbMath::c1o9*(-bcVelocityX1             -bcVelocityX3) );
+      case D3Q27System::BE: return (float)( UbMath::c1o9*(+bcVelocityX1             -bcVelocityX3) );
+      case D3Q27System::TW: return (float)( UbMath::c1o9*(-bcVelocityX1             +bcVelocityX3) );
+      case D3Q27System::TN: return (float)( UbMath::c1o9*(             +bcVelocityX2+bcVelocityX3) );
+      case D3Q27System::BS: return (float)( UbMath::c1o9*(             -bcVelocityX2-bcVelocityX3) );
+      case D3Q27System::BN: return (float)( UbMath::c1o9*(             +bcVelocityX2-bcVelocityX3) );
+      case D3Q27System::TS: return (float)( UbMath::c1o9*(             -bcVelocityX2+bcVelocityX3) );
+      case D3Q27System::TNE: return (float)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2+bcVelocityX3) );
+      case D3Q27System::BSW: return (float)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2-bcVelocityX3) );
+      case D3Q27System::BNE: return (float)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2-bcVelocityX3) );
+      case D3Q27System::TSW: return (float)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2+bcVelocityX3) );
+      case D3Q27System::TSE: return (float)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2+bcVelocityX3) );
+      case D3Q27System::BNW: return (float)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2-bcVelocityX3) );
+      case D3Q27System::BSE: return (float)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2-bcVelocityX3) );
+      case D3Q27System::TNW: return (float)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2+bcVelocityX3) ); 
+      default: throw UbException(UB_EXARGS,"unknown error");
+      }
+   }
+
+   /*============== Density Boundary ========================*/
+   void       setDensityBoundaryFlag(const int& direction, const short& secOpt=0) { this->setFlagBits(densityBoundaryFlags,direction,secOpt);                                     }  
+   void       unsetDensityBoundaryFlag(const int& direction)                      { this->densityBoundaryFlags &= ~( maxOptionVal<<(direction*optionDigits) );                    }
+   void       unsetDensityBoundary()                                              { this->densityBoundaryFlags = 0;                                                               }
+   long long  getDensityBoundary()	                                              { return this->densityBoundaryFlags;                                                            }
+   bool       hasDensityBoundary()					                                  { return (this->densityBoundaryFlags!=0);                                                       }
+   bool       hasDensityBoundaryFlag(const int& direction)	                      { return ( ( ( densityBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) != 0);         }
+   short      getDensitySecondaryOption(const int& direction)                     { return (short)( (  ( densityBoundaryFlags>>(optionDigits*direction) ) & maxOptionVal ) - 1 ); }
+
+   void  setBoundaryDensity(float density) { this->bcDensity = density; } 
+   float getBoundaryDensity()              { return this->bcDensity;    }
+
+   //Lodi extension
+   void  setDensityLodiDensity(const float& bcLodiDensity)       { this->bcLodiDensity    = bcLodiDensity;    } 
+   void  setDensityLodiVelocityX1(const float& bcLodiVelocityX1) { this->bcLodiVelocityX1 = bcLodiVelocityX1; } 
+   void  setDensityLodiVelocityX2(const float& bcLodiVelocityX2) { this->bcLodiVelocityX2 = bcLodiVelocityX2; } 
+   void  setDensityLodiVelocityX3(const float& bcLodiVelocityX3) { this->bcLodiVelocityX3 = bcLodiVelocityX3; } 
+   void  setDensityLodiLength(const float& bcLodiLentgh)         { this->bcLodiLentgh     = bcLodiLentgh;     } 
+   float getDensityLodiDensity() const                           { return this->bcLodiDensity;    } 
+   float getDensityLodiVelocityX1() const                        { return this->bcLodiVelocityX1; }
+   float getDensityLodiVelocityX2() const                        { return this->bcLodiVelocityX2; }
+   float getDensityLodiVelocityX3() const                        { return this->bcLodiVelocityX3; }
+   float getDensityLodiLength() const                            { return this->bcLodiLentgh;     }
+
+   float& densityLodiDensity()                                   { return this->bcLodiDensity;    } 
+   float& densityLodiVelocityX1()                                { return this->bcLodiVelocityX1; }
+   float& densityLodiVelocityX2()                                { return this->bcLodiVelocityX2; }
+   float& densityLodiVelocityX3()                                { return this->bcLodiVelocityX3; }
+   float& densityLodiLentgh()                                    { return this->bcLodiLentgh;     }
+
+   const float& densityLodiDensity()  const                      { return this->bcLodiDensity;    } 
+   const float& densityLodiVelocityX1() const                    { return this->bcLodiVelocityX1; }
+   const float& densityLodiVelocityX2() const                    { return this->bcLodiVelocityX2; }
+   const float& densityLodiVelocityX3() const                    { return this->bcLodiVelocityX3; }
+   const float& densityLodiLentgh()  const                       { return this->bcLodiLentgh;     }
+
+
+   /*======================= Qs =============================*/
+   void  setQ(const float& val, const int& direction) { q[direction] = val; }
+   float getQ(const int& direction)                   { return q[direction]; }
+   
+   virtual std::vector< std::string > getBCNames()
+   {
+      std::vector< std::string > tmp;
+      tmp.push_back( "NoSlipBC"   );
+      tmp.push_back( "SlipBC"     );
+      tmp.push_back( "VelocityBC" );
+      tmp.push_back( "DensityBC"  );
+      return tmp;
+   }
+   virtual std::vector< long long > getBCFlags()
+   {
+      std::vector< long long > tmp;
+      tmp.push_back( noslipBoundaryFlags   );
+      tmp.push_back( slipBoundaryFlags     );
+      tmp.push_back( velocityBoundaryFlags );
+      tmp.push_back( densityBoundaryFlags  );
+      return tmp;
+   }
+
+   static bool hasFlagForDirection(const long long& flag, const int& direction)
+   {
+      return ( ( ( flag>>(optionDigits*direction) ) & maxOptionVal ) != 0);
+   }
+
+public:
+   static const int       optionDigits = 2;  //--> 3 bits für secondary Option --> maxOptionVal = 7, da man mit drei Digits max die 7 darstellen kann
+   static const long long maxOptionVal;// = ( 1<<optionDigits ) - 1; //2^3-1 -> 7
+
+protected:
+   float q[D3Q27System::FENDDIR+1];
+   //float q[D3Q27System::STARTF+1];
+
+   long long noslipBoundaryFlags;		
+   long long slipBoundaryFlags;		
+   long long velocityBoundaryFlags;		
+   long long densityBoundaryFlags;		
+   long long wallModelBoundaryFlags;
+
+   float  bcVelocityX1;
+   float  bcVelocityX2;
+   float  bcVelocityX3;
+   float  bcDensity;
+
+   float  bcLodiDensity;
+   float  bcLodiVelocityX1;
+   float  bcLodiVelocityX2;
+   float  bcLodiVelocityX3;
+   float  bcLodiLentgh;
+
+   float  nx1,nx2,nx3;
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & q; 
+
+      ar & noslipBoundaryFlags;		
+      ar & slipBoundaryFlags;		
+      ar & velocityBoundaryFlags;		
+      ar & densityBoundaryFlags;		
+
+      ar & bcVelocityX1;
+      ar & bcVelocityX2;
+      ar & bcVelocityX3;
+      ar & bcDensity;
+
+      ar & bcLodiDensity;
+      ar & bcLodiVelocityX1;
+      ar & bcLodiVelocityX2;
+      ar & bcLodiVelocityX3;
+      ar & bcLodiLentgh;
+
+      ar & wallModelBoundaryFlags;
+
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+   }
+
+};
+
+#endif //D3Q27BOUNDARYCONDITION_H
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryConditionAdapter.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryConditionAdapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..668e3c0bfab781f6df7e97f9d385ad29c21c8cfb
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27BoundaryConditionAdapter.h
@@ -0,0 +1,90 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef D3Q27BOUNDARYCONDITIONADAPTER_H
+#define D3Q27BOUNDARYCONDITIONADAPTER_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/export.hpp>
+#include <boost/shared_ptr.hpp>
+
+class D3Q27BoundaryConditionAdapter;
+typedef boost::shared_ptr<D3Q27BoundaryConditionAdapter> D3Q27BoundaryConditionAdapterPtr;
+
+#include "D3Q27BoundaryCondition.h"
+#include "basics/objects/ObObject.h"
+#include "basics/objects/ObObjectCreator.h"
+#include "basics/utilities/UbFileOutput.h"
+#include "basics/utilities/UbFileInput.h"
+#include "basics/utilities/UbAutoRun.hpp"
+
+
+/*=========================================================================*/
+/*  D3Q27BoundaryConditionAdapter                                          */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 06.09.06
+*/ 
+
+/*
+usage: ...
+*/
+
+class D3Q27Interactor;
+
+class D3Q27BoundaryConditionAdapter
+{
+public:
+   D3Q27BoundaryConditionAdapter() 
+      :  secondaryBcOption(0)
+       , type(0)
+   {
+   }
+   D3Q27BoundaryConditionAdapter(const short& secondaryBcOption) 
+      :  secondaryBcOption(secondaryBcOption) 
+       , type(0)
+   {
+   }
+   virtual ~D3Q27BoundaryConditionAdapter() {}
+
+   //methods
+   bool isTimeDependent() { return((this->type & TIMEDEPENDENT) ==  TIMEDEPENDENT); }
+
+   virtual short getSecondaryBcOption() { return this->secondaryBcOption; }
+   virtual void  setSecondaryBcOption(const short& val) { this->secondaryBcOption=val; }
+
+   virtual void init(const D3Q27Interactor* const& interactor, const double& time=0) = 0;
+   virtual void update(const D3Q27Interactor* const& interactor, const double& time=0) = 0;
+
+   virtual void adaptBC( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time=0 ) = 0;
+   virtual void adaptBCForDirection( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time=0 ) = 0;
+
+protected:
+   short secondaryBcOption;
+
+   char  type;
+
+   static const char   TIMEDEPENDENT = 1<<0;//'1';
+   static const char   TIMEPERIODIC  = 1<<1;//'2';
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & secondaryBcOption;
+   }
+};
+
+
+#endif //D3Q27BOUNDARYCONDITIONADAPTER_H
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27DensityBCAdapter.cpp b/source/VirtualFluidsCore/BoundaryCondition/D3Q27DensityBCAdapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..13dfa0488183e3156ab0ce295b869e40ba20eac4
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27DensityBCAdapter.cpp
@@ -0,0 +1,156 @@
+#include "D3Q27DensityBCAdapter.h"
+#include "basics/utilities/UbLogger.h"
+#include "basics/utilities/UbInfinity.h"
+
+using namespace std;
+/*==========================================================*/
+D3Q27DensityBCAdapter::D3Q27DensityBCAdapter(const double& dens, const double& startTime, const double& endTime )
+{
+   this->densBCs.push_back( D3Q27BCFunction(dens,startTime,endTime) );
+   this->init();
+}
+/*==========================================================*/
+D3Q27DensityBCAdapter::D3Q27DensityBCAdapter(const D3Q27BCFunction& densBC )
+{
+   this->densBCs.push_back(densBC);
+   this->init();
+}
+/*==========================================================*/
+D3Q27DensityBCAdapter::D3Q27DensityBCAdapter(const std::vector< D3Q27BCFunction >& densBCs)
+{
+   this->densBCs = densBCs;
+   this->init();
+}
+/*==========================================================*/
+D3Q27DensityBCAdapter::D3Q27DensityBCAdapter(const mu::Parser& function, const double& startTime, const double& endTime )
+{
+   this->densBCs.push_back(D3Q27BCFunction(function,startTime,endTime));
+   this->init();
+}
+/*==========================================================*/
+void D3Q27DensityBCAdapter::init()
+{
+   this->timeStep = 0.0;
+
+   this->x1 = 0.0;
+   this->x2 = 0.0;
+   this->x3 = 0.0;
+
+   this->tmpDensityFunction = NULL;
+
+   try //initilialization and validation of functions
+   {
+      for(size_t pos=0; pos<densBCs.size(); ++pos)
+      {
+         if( !(    UbMath::equal( D3Q27BCFunction::INFCONST, densBCs[pos].getEndTime() )
+                && UbMath::greaterEqual( this->timeStep,  densBCs[pos].getStartTime()  ) ) )
+         { 
+            this->setTimeDependent();
+         }
+
+         densBCs[pos].getFunction().DefineVar("t" , &this->timeStep);
+         densBCs[pos].getFunction().DefineVar("x1", &this->x1      );
+         densBCs[pos].getFunction().DefineVar("x2", &this->x2      );
+         densBCs[pos].getFunction().DefineVar("x3", &this->x3      );
+
+         densBCs[pos].getFunction().Eval(); //<-- validation
+      }
+   }
+   catch(mu::Parser::exception_type& e){ stringstream error; error<<"mu::parser exception occurs, message("<<e.GetMsg()<<"), formula("<<e.GetExpr()+"), token("+e.GetToken()<<")"
+                                         <<", pos("<<e.GetPos()<<"), error code("<<e.GetCode(); throw UbException(error.str()); }
+   catch(...)                          { throw UbException(UB_EXARGS,"unknown exception" );                       }
+}
+/*==========================================================*/
+void D3Q27DensityBCAdapter::init(const D3Q27Interactor* const& interactor, const double& time)
+{
+   this->timeStep           = time;
+   this->tmpDensityFunction = NULL;
+   double maxEndtime        = -Ub::inf;
+
+   //aktuelle Densityfunction bestimmen
+   for(size_t pos=0; pos<densBCs.size(); ++pos)
+   {
+      if( UbMath::equal(densBCs[pos].getEndTime(),D3Q27BCFunction::INFTIMEDEPENDENT)) maxEndtime=Ub::inf;
+      maxEndtime = UbMath::max(maxEndtime,densBCs[pos].getStartTime(),densBCs[pos].getEndTime()); //startTime abfragen, da  INFCONST=-10
+
+      if( UbMath::greaterEqual(this->timeStep,densBCs[pos].getStartTime()) ) 
+      {
+         if(   UbMath::lessEqual(this->timeStep,densBCs[pos].getEndTime())
+            || UbMath::equal(densBCs[pos].getEndTime(),(double)D3Q27BCFunction::INFCONST)
+            || UbMath::equal(densBCs[pos].getEndTime(),(double)D3Q27BCFunction::INFTIMEDEPENDENT) )
+         {
+            tmpDensityFunction = &densBCs[pos].getFunction();
+            break;
+         }
+      }
+   }
+
+   //wenn funktionen zweitlich konstant sind und bis t=unendlich gelten
+   //kann man zeitabhaengigkeit deaktivieren
+   if( UbMath::greaterEqual(time,maxEndtime) ) this->unsetTimeDependent();
+
+   UBLOG(logDEBUG4,"D3Q27DensityBCAdapter::init(time="<<time<<") "
+                    <<", rho= \""<<(tmpDensityFunction ? tmpDensityFunction->GetExpr() : "-")
+                    <<"\", timedependant="<<(this->isTimeDependent() ? "true" : "false") );
+}
+/*==========================================================*/
+void D3Q27DensityBCAdapter::update( const D3Q27Interactor* const& interactor, const double& time ) 
+{
+   this->init(interactor,time);
+}
+/*==========================================================*/
+void D3Q27DensityBCAdapter::adaptBCForDirection( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time )
+{
+   bc->setDensityBoundaryFlag(D3Q27System::INVDIR[fdirection],secondaryBcOption);
+   bc->setQ((float)q,fdirection);
+}
+/*==========================================================*/
+void D3Q27DensityBCAdapter::adaptBC( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time )
+{
+   this->setNodeDensity(interactor,bc,worldX1,worldX2,worldX3,time);
+}
+/*==========================================================*/
+void D3Q27DensityBCAdapter::setNodeDensity( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& timestep) 
+{
+   //Geschwindigkeiten setzen
+   try
+   {
+      //PunktKoordinaten bestimmen
+      this->x1 = worldX1;
+      this->x2 = worldX2;
+      this->x3 = worldX3;
+      this->timeStep = timestep;
+
+      if(tmpDensityFunction) bc->setBoundaryDensity((float)tmpDensityFunction->Eval());  
+   }
+   catch(mu::Parser::exception_type& e){ stringstream error; error<<"mu::parser exception occurs, message("<<e.GetMsg()<<"), formula("<<e.GetExpr()+"), token("+e.GetToken()<<")"
+                                          <<", pos("<<e.GetPos()<<"), error code("<<e.GetCode(); throw UbException(error.str()); }
+   catch(...)                          { throw UbException(UB_EXARGS,"unknown exception" ); }
+}
+/*==========================================================*/
+double D3Q27DensityBCAdapter::getDensity(const double& x1, const double& x2, const double& x3, const double& timeStep)
+{
+   this->x1 = x1;
+   this->x2 = x2;
+   this->x3 = x3;
+   this->timeStep = timeStep;
+
+   if(!tmpDensityFunction) return 0.0;
+
+   return tmpDensityFunction->Eval();  
+}
+/*==========================================================*/
+string D3Q27DensityBCAdapter::toString()
+{
+   stringstream info;
+   info<<"D3Q27DensityBCAdapter:\n";
+   info<<" #dens-functions = "<<(int)densBCs.size()<<endl;
+   info<<" protected variables: x1, x2, x3, t"<<endl;
+
+   for(size_t i=0; i<densBCs.size(); ++i)
+   {
+      info<<"\n   dens-function nr."<<i<<":"<<endl;
+      info<<densBCs[i].toString()<<endl;
+   }
+   return info.str();
+}
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27DensityBCAdapter.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27DensityBCAdapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..f93088ecd7194e3d9bb7cb41125d22b2fa1ed931
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27DensityBCAdapter.h
@@ -0,0 +1,81 @@
+#ifndef D3Q27DensityBCAdapter_H
+#define D3Q27DensityBCAdapter_H
+        
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include "basics/utilities/UbMath.h"
+#include "basics/utilities/UbTuple.h"
+
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "D3Q27BCFunction.h"
+
+//*  D3Q27DensityBCAdapter                                                            */
+//*                                                                         */
+//**
+//<BR><BR>
+//@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+//@version 1.0 - 06.09.06
+//*/ 
+//
+//*
+//usage: ...
+//*/
+
+
+class D3Q27DensityBCAdapter : public D3Q27BoundaryConditionAdapter
+{
+public:
+   //constructors
+   D3Q27DensityBCAdapter() { this->init(); }
+   D3Q27DensityBCAdapter(const double& dens, const double& startTime=0.0, const double& endTime = D3Q27BCFunction::INFCONST );
+   D3Q27DensityBCAdapter(const D3Q27BCFunction& densBC );
+   D3Q27DensityBCAdapter(const std::vector< D3Q27BCFunction >& densBCs);
+   D3Q27DensityBCAdapter(const mu::Parser& function, const double& startTime=0.0, const double& endTime = D3Q27BCFunction::INFCONST  );
+
+   //------------- implements D3Q27BoundaryConditionAdapter ----- start
+   std::string toString();
+   ObObjectCreator* getCreator();
+
+   void init(const D3Q27Interactor* const& interactor, const double& time=0);
+   void update(const D3Q27Interactor* const& interactor, const double& time=0);
+
+   void adaptBCForDirection( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time=0 );
+   void adaptBC( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time=0 );
+
+   double getDensity(const double& x1, const double& x2, const double& x3, const double& timeStep);
+
+   //------------- implements D3Q27BoundaryConditionAdapter ----- end
+
+
+protected:
+   void init();
+   
+   //time dependency wird automatisch ueber D3Q27BCFunction Intervalle ermittelt!
+   void setTimeDependent()   { (this->type |=   TIMEDEPENDENT);}
+   void unsetTimeDependent() { (this->type &=  ~TIMEDEPENDENT);}
+   
+   void clear() { densBCs.clear(); }
+   void setNodeDensity(const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& timestep);
+
+private:
+   mu::value_type x1, x2, x3; //brauch man nicht serialisieren!
+   mu::value_type timeStep;   //brauch man nicht serialisieren!
+
+   mu::Parser* tmpDensityFunction; //brauch man nicht serialisieren!
+   
+   std::vector<D3Q27BCFunction> densBCs;
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<D3Q27BoundaryConditionAdapter>(*this);
+      ar & densBCs;
+   }
+};
+
+#endif 
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETBCProcessor.cpp b/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETBCProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff567490cb377b26f0ac9c98ff72422f8c649a1d
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETBCProcessor.cpp
@@ -0,0 +1,610 @@
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+
+D3Q27ETBCProcessor::D3Q27ETBCProcessor()
+{
+   
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27ETBCProcessor::D3Q27ETBCProcessor(LBMKernel3DPtr kernel)
+{
+   distributions = boost::dynamic_pointer_cast<EsoTwist3D>(kernel->getDataSet()->getFdistributions());
+   ghostLayerWitdh = kernel->getGhostLayerWidth();
+   collFactor = kernel->getCollisionFactor();
+   bcArray.resize( distributions->getNX1(), distributions->getNX2(), distributions->getNX3(), BCArray3D<D3Q27BoundaryCondition>::FLUID);
+   this->compressible = kernel->getCompressible();
+
+   minX1 = 0;
+   minX2 = 0;
+   minX3 = 0;
+   maxX1 = (int)bcArray.getNX1();
+   maxX2 = (int)bcArray.getNX2();
+   maxX3 = (int)bcArray.getNX3();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27ETBCProcessor::~D3Q27ETBCProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27ETBCProcessor::init(LBMKernel3DPtr kernel)
+//{
+//   distributions = boost::dynamic_pointer_cast<EsoTwist3D>(kernel->getDataSet()->getFdistributions());
+//   ghostLayerWitdh = kernel->getGhostLayerWidth();
+//   collFactor = kernel->getCollisionFactor();
+//   bcArray.resize( distributions->getNX1(), distributions->getNX2(), distributions->getNX3(), BCArray3D<D3Q27BoundaryCondition>::FLUID);
+//   this->compressible = kernel->getCompressible();
+//   CalcFeqForDirFct calcFeqsForDirFct = NULL;
+//   CalcMacrosFct    calcMacrosFct     = NULL;
+//   CalcFeqFct       calcFeqFct        = NULL;
+//
+//   if(this->compressible)
+//   {
+//      rho0 = REAL_CAST(0.0);
+//      calcFeqsForDirFct = &D3Q27System::getCompFeqForDirection; 
+//      calcMacrosFct     = &D3Q27System::calcCompMacroscopicValues;
+//      calcFeqFct        = &D3Q27System::calcCompFeq; 
+//   }
+//   else
+//   {
+//      rho0 = REAL_CAST(1.0);
+//      calcFeqsForDirFct = &D3Q27System::getIncompFeqForDirection; 
+//      calcMacrosFct     = &D3Q27System::calcIncompMacroscopicValues;
+//      calcFeqFct        = &D3Q27System::calcIncompFeq; 
+//   }
+//
+//   minX1 = 0;
+//   minX2 = 0;
+//   minX3 = 0;
+//   maxX1 = (int)bcArray.getNX1();
+//   maxX2 = (int)bcArray.getNX2();
+//   maxX3 = (int)bcArray.getNX3();
+//}
+//////////////////////////////////////////////////////////////////////////
+BCProcessorPtr D3Q27ETBCProcessor::clone(LBMKernel3DPtr kernel)
+{
+   BCProcessorPtr bcProcessor(new D3Q27ETBCProcessor(kernel));
+   //boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(bcProcessor)->init(kernel);
+   BoundaryConditionPtr velocity = this->getBC(BoundaryCondition::Velocity);
+   BoundaryConditionPtr density  = this->getBC(BoundaryCondition::Density);
+   BoundaryConditionPtr noSlip   = this->getBC(BoundaryCondition::NoSlip);
+   BoundaryConditionPtr slip     = this->getBC(BoundaryCondition::Slip);
+   if (velocity)bcProcessor->addBC(velocity->clone());
+   if (density) bcProcessor->addBC(density->clone());
+   if (noSlip)  bcProcessor->addBC(noSlip->clone());
+   if (slip)    bcProcessor->addBC(slip->clone());
+   return bcProcessor;
+}
+//////////////////////////////////////////////////////////////////////////
+BCArray3D<D3Q27BoundaryCondition>& D3Q27ETBCProcessor::getBCArray()
+{ 
+   return this->bcArray; 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETBCProcessor::applyBC()
+{
+   typedef void      (*CalcMacrosFct)(const LBMReal* const& /*f[27]*/, LBMReal& /*rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   typedef LBMReal (*CalcFeqForDirFct)(const int& /*direction*/,const LBMReal& /*(d)rho*/,const LBMReal& /*vx1*/,const LBMReal& /*vx2*/,const LBMReal& /*vx3*/);
+   typedef  void     (*CalcFeqFct)(LBMReal* const& /*feq/*[27]*/,const LBMReal& /*rho*/,const LBMReal& /*vx1*/,const LBMReal& /*vx2*/,const LBMReal& /*vx3*/);
+
+   CalcFeqForDirFct calcFeqsForDirFct = NULL;
+   CalcMacrosFct    calcMacrosFct     = NULL;
+   CalcFeqFct       calcFeqFct        = NULL;
+
+   if(this->compressible)
+   {
+      rho0 = REAL_CAST(0.0);
+      calcFeqsForDirFct = &D3Q27System::getCompFeqForDirection; 
+      calcMacrosFct     = &D3Q27System::calcCompMacroscopicValues;
+      calcFeqFct        = &D3Q27System::calcCompFeq; 
+   }
+   else
+   {
+      rho0 = REAL_CAST(1.0);
+      calcFeqsForDirFct = &D3Q27System::getIncompFeqForDirection; 
+      calcMacrosFct     = &D3Q27System::calcIncompMacroscopicValues;
+      calcFeqFct        = &D3Q27System::calcIncompFeq; 
+   }
+
+
+
+   //////////////////////////////////////////////////////////////////////////
+   //EsoTwist3DPtr distributionsTemp(new D3Q27EsoTwist3DSplittedVector(maxX1, maxX2, maxX2, -999.0));
+   //printf("create new distributionsTemp\n");
+   //////////////////////////////////////////////////////////////////////////
+
+   for(int x3 = minX3; x3 < maxX3; x3++)      
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)      
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)  
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3)) 
+            {
+               if( (bcPtr=bcArray.getBC(x1,x2,x3)) != NULL)
+               {
+                  //velocity boundary condition
+                  if(bcPtr->hasVelocityBoundary())
+                  {
+                     //distributions->getDistributionInv(f,x1,x2,x3);
+                     //int nx1 = x1;
+                     //int nx2 = x2;
+                     //int nx3 = x3;
+
+                     //rho = rho0;
+                     //if(compressible) rho += D3Q27System::getDensity(f); 
+
+                     //for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                     //{
+                     //   if(bcPtr->hasVelocityBoundaryFlag(fdir))
+                     //   {
+                     //      int invDir = D3Q27System::INVDIR[fdir];
+                     //      LBMReal ftemp = distributions->getDistributionInvForDirection(x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                     //      ftemp += rho * bcPtr->getBoundaryVelocity(fdir);
+                     //      distributions->setDistributionForDirection(ftemp, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                     //   }
+                     //}
+                     distributions->getDistributionInv(ftemp,x1,x2,x3);
+                     calcMacrosFct(ftemp,rho,vx1,vx2,vx3);
+                     calcFeqFct(feq,rho,vx1,vx2,vx3);
+
+                     for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                     {
+                        if(bcPtr->hasVelocityBoundaryFlag(fdir))
+                        {
+                           const int invDir = D3Q27System::INVDIR[fdir];
+                           LBMReal q = 1.0;//bcPtr->getQ(invDir);// m+m q=0 stabiler
+                           LBMReal velocity = bcPtr->getBoundaryVelocity(invDir);
+                           //LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir]*collFactor)/(1.0-collFactor))+((q*(ftemp[invDir]+ftemp[fdir])-velocity)/(1.0+q));
+                           LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir])/(1.0-collFactor)+feq[invDir])+((q*(ftemp[invDir]+ftemp[fdir])-velocity)/(1.0+q));
+                           distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                        }
+                     }
+                  }
+///////////////////velocity bc for non reflecting pressure bc
+                  //if (bcPtr->hasVelocityBoundary())
+                  //{
+                  //   distributions->getDistributionInv(ftemp, x1, x2, x3);
+                  //   calcMacrosFct(ftemp, rho, vx1, vx2, vx3);
+                  //   calcFeqFct(feq, rho, vx1, vx2, vx3);
+
+                  //   for (int fdir = D3Q27System::FSTARTDIR; fdir <= D3Q27System::FENDDIR; fdir++)
+                  //   {
+                  //      if (bcPtr->hasVelocityBoundaryFlag(fdir))
+                  //      {
+                  //         const int invDir = D3Q27System::INVDIR[fdir];
+                  //         LBMReal q = 1.0;//bcPtr->getQ(invDir);// m+m q=0 stabiler
+                  //         LBMReal velocity = bcPtr->getBoundaryVelocity(invDir);
+                  //         //LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir]*collFactor)/(1.0-collFactor))+((q*(ftemp[invDir]+ftemp[fdir])-velocity)/(1.0+q));
+                  //         LBMReal fReturn = ((1.0 - q) / (1.0 + q))*((ftemp[invDir] - feq[invDir]) / (1.0 - collFactor) + feq[invDir]) + ((q*(ftemp[invDir] + ftemp[fdir]) - velocity) / (1.0 + q))-rho*D3Q27System::WEIGTH[invDir];
+                  //         distributions->setDistributionForDirection(fReturn, x1 + D3Q27System::DX1[invDir], x2 + D3Q27System::DX2[invDir], x3 + D3Q27System::DX3[invDir], fdir);
+                  //      }
+                  //   }
+                  //}
+                  //density boundary condition
+                  else if(bcPtr->hasDensityBoundary())
+                  {
+                     distributions->getDistributionInv(f,x1,x2,x3);
+                     int nx1 = x1;
+                     int nx2 = x2;
+                     int nx3 = x3;
+                     int direction = -1;
+
+                     //flag points in direction of fluid
+                     if     ( bcPtr->hasDensityBoundaryFlag(D3Q27System::E) ) {nx1 -= 1; direction=D3Q27System::E; }
+                     else if( bcPtr->hasDensityBoundaryFlag(D3Q27System::W) ) {nx1 += 1; direction=D3Q27System::W; }
+                     else if( bcPtr->hasDensityBoundaryFlag(D3Q27System::N) ) {nx2 -= 1; direction=D3Q27System::N; }
+                     else if( bcPtr->hasDensityBoundaryFlag(D3Q27System::S) ) {nx2 += 1; direction=D3Q27System::S; }
+                     else if( bcPtr->hasDensityBoundaryFlag(D3Q27System::T) ) {nx3 -= 1; direction=D3Q27System::T; }
+                     else if( bcPtr->hasDensityBoundaryFlag(D3Q27System::B) ) {nx3 += 1; direction=D3Q27System::B; }
+                     else UB_THROW( UbException(UB_EXARGS,"Danger...no orthogonal BC-Flag on density boundary...") );
+                        
+                     #ifdef _DEBUG
+                     if( nx1<0 || nx1>maxX1 ) UB_THROW( UbException(UB_EXARGS,"nx1<0 || nx1>=lengthX1") );
+                     if( nx2<0 || nx2>maxX2 ) UB_THROW( UbException(UB_EXARGS,"nx2<0 || nx2>=lengthX2") );
+                     if( nx3<0 || nx3>maxX3 ) UB_THROW( UbException(UB_EXARGS,"nx3<0 || nx3>=lengthX3") );
+                     #endif
+
+                     //if(bcPtr->getDensitySecondaryOption(direction)!=0) 
+                     //   UB_THROW( UbException(UB_EXARGS,"invalid bc->getDensitySecondaryOption()="+UbSystem::toString(bcPtr->getDensitySecondaryOption(direction))) );
+
+                     calcMacrosFct(f,rho,vx1,vx2,vx3);
+                     LBMReal rhoBC = bcPtr->getBoundaryDensity();
+                     for(int fdir=D3Q27System::STARTF; fdir<=D3Q27System::ENDF; fdir++)
+                      {
+                         if(bcPtr->hasDensityBoundaryFlag(fdir))
+                         {
+                            short densitySO = bcPtr->getDensitySecondaryOption(fdir);
+                            if ( densitySO == 0)
+                            {
+                               // Martins NEQ ADDON
+                               ////original: 15.2.2013:
+                               LBMReal ftemp = calcFeqsForDirFct(fdir,rho,vx1,vx2,vx3);             
+                               ftemp = calcFeqsForDirFct(fdir,rhoBC,vx1,vx2,vx3)+f[fdir]-ftemp;
+                               distributions->setDistributionForDirection(ftemp, nx1, nx2, nx3, fdir);
+                            }
+                            else if(densitySO == 1)
+                            {
+                               //Ehsan: 15.2.2013:
+                               LBMReal ftemp = calcFeqsForDirFct(fdir,rhoBC,vx1,vx2,vx3);
+                               distributions->setDistributionForDirection(ftemp, nx1, nx2, nx3, fdir);
+                            }
+                         }
+                     }
+                  }
+///////////////non reflecting pressure baundary condition             
+               //else if(bcPtr->hasDensityBoundary())
+               //   {
+//                     distributions->swap();
+//                     distributions->getDistribution(f, x1, x2, x3);
+//                     int nx1 = x1;
+//                     int nx2 = x2;
+//                     int nx3 = x3;
+//                     int direction = -1;
+//
+//                     //flag points in direction of fluid
+//                     if (bcPtr->hasDensityBoundaryFlag(D3Q27System::E))      { nx1 += 1; direction = D3Q27System::E; }
+//                     else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::W)) { nx1 -= 1; direction = D3Q27System::W; }
+//                     else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::N)) { nx2 += 1; direction = D3Q27System::N; }
+//                     else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::S)) { nx2 -= 1; direction = D3Q27System::S; }
+//                     else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::T)) { nx3 += 1; direction = D3Q27System::T; }
+//                     else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::B)) { nx3 -= 1; direction = D3Q27System::B; }
+//                     else UB_THROW(UbException(UB_EXARGS, "Danger...no orthogonal BC-Flag on density boundary..."));
+//
+//#ifdef _DEBUG
+//                     if (nx1<0 || nx1>maxX1) UB_THROW(UbException(UB_EXARGS, "nx1<0 || nx1>=lengthX1"));
+//                     if (nx2<0 || nx2>maxX2) UB_THROW(UbException(UB_EXARGS, "nx2<0 || nx2>=lengthX2"));
+//                     if (nx3<0 || nx3>maxX3) UB_THROW(UbException(UB_EXARGS, "nx3<0 || nx3>=lengthX3"));
+//#endif
+//                     distributions->getDistribution(ftemp, nx1, nx2, nx3);
+//                     calcMacrosFct(f, rho, vx1, vx2, vx3);
+//
+//                     distributions->swap();
+//
+//                     double dim = 0.01;
+//
+//                     f[D3Q27System::W] = ftemp[D3Q27System::W] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::W] - rho*dim*D3Q27System::WEIGTH[D3Q27System::W];
+//                     f[D3Q27System::NW] = ftemp[D3Q27System::NW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::NW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::NW];
+//                     f[D3Q27System::SW] = ftemp[D3Q27System::SW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::SW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::SW];
+//                     f[D3Q27System::TW] = ftemp[D3Q27System::TW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TW];
+//                     f[D3Q27System::BW] = ftemp[D3Q27System::BW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BW];
+//                     f[D3Q27System::TNW] = ftemp[D3Q27System::TNW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TNW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TNW];
+//                     f[D3Q27System::TSW] = ftemp[D3Q27System::TSW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TSW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TSW];
+//                     f[D3Q27System::BNW] = ftemp[D3Q27System::BNW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BNW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BNW];
+//                     f[D3Q27System::BSW] = ftemp[D3Q27System::BSW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BSW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BSW];
+//                                                                                                                                             
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::W], x1, x2, x3, D3Q27System::W);
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::NW], x1, x2, x3, D3Q27System::NW);
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::SW], x1, x2, x3, D3Q27System::SW);
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::TW], x1, x2, x3, D3Q27System::TW);
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::BW], x1, x2, x3, D3Q27System::BW);
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::TNW], x1, x2, x3, D3Q27System::TNW);
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::TSW], x1, x2, x3, D3Q27System::TSW);
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::BNW], x1, x2, x3, D3Q27System::BNW);
+//                     distributions->setDistributionInvForDirection(f[D3Q27System::BSW], x1, x2, x3, D3Q27System::BSW);
+                   
+                  //}
+               else if(bcPtr->hasNoSlipBoundary())
+               {
+                  distributions->getDistributionInv(ftemp,x1,x2,x3);
+                  calcMacrosFct(ftemp,rho,vx1,vx2,vx3);
+                  calcFeqFct(feq,rho,vx1,vx2,vx3);
+
+                  for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                  {
+                     if(bcPtr->hasNoSlipBoundaryFlag(fdir))
+                     {
+                        switch(bcPtr->getNoSlipSecondaryOption(fdir))
+                        {
+                        case 0:
+                           //simple bounce back - do nothing
+                           break;
+                        case 1:
+                           {
+                              //quadratic bounce back
+                              const int invDir = D3Q27System::INVDIR[fdir];
+                              LBMReal q = bcPtr->getQ(invDir);
+                              //LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir]*collFactor)/(1.0-collFactor))+((q/(1.0+q))*(ftemp[invDir]+ftemp[fdir]));
+                              LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir])/(1.0-collFactor)+feq[invDir])+((q/(1.0+q))*(ftemp[invDir]+ftemp[fdir]));
+                              distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                           }
+                           break;
+                           //////////////////////////////////////////////////////////////////////////
+                        ////HighViscosityNoSlipBoundaryCondition
+                        //case 1:
+                        //{
+                        //   //quadratic bounce back
+                        //   const int invDir = D3Q27System::INVDIR[fdir];
+                        //   LBMReal q = bcPtr->getQ(invDir);
+                        //   LBMReal fReturn = ((1.0-q)*ftemp[invDir]+q*((ftemp[invDir]+ftemp[fdir])*(1-collFactor)+collFactor*(feq[invDir]+feq[fdir])))/(1.0+q);
+                        //   distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                        //}
+                        //break;
+                        //////////////////////////////////////////////////////////////////////////
+                        //case 2:
+                        //   {
+                        //      //quadratic bounce back 2nd choice
+                        //      const int invDir = D3Q27System::INVDIR[fdir];
+                        //      LBMReal q = bcPtr->getQ(invDir);
+                        //      LBMReal fReturn = ((1.0-q)/(1.0+q))*0.5*(ftemp[invDir]-ftemp[fdir]+(ftemp[invDir]+ftemp[fdir]-collFactor*(feq[fdir]+feq[invDir]))/(1.0-collFactor)); 
+                        //      distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                        //   }
+                        //   break;
+                        case 2:
+                           {
+                              //quadratic bounce back with for thin walls
+                              const int invDir = D3Q27System::INVDIR[fdir];
+                              LBMReal q = bcPtr->getQ(invDir);
+                              //LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir])/(1.0-collFactor)+feq[invDir])+((q/(1.0+q))*(ftemp[invDir]+ftemp[fdir]));
+                              LBMReal fReturn = ((1.0-q)/(1.0+q))*0.5*(ftemp[invDir]-ftemp[fdir]+(ftemp[invDir]+ftemp[fdir]-collFactor*(feq[fdir]+feq[invDir]))/(1.0-collFactor)); 
+                              //printf("set distributionsTemp - start\n");
+                              distributionsTemp->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                              //printf("set distributionsTemp - end\n");
+                           }
+                           break;
+                        }
+                     }
+                  }
+               }
+               else if(bcPtr->hasSlipBoundary()) 
+               {
+                  distributions->getDistributionInv(ftemp,x1,x2,x3);
+                  calcMacrosFct(ftemp,rho,vx1,vx2,vx3);
+                  calcFeqFct(feq,rho,vx1,vx2,vx3);
+
+                  UbTupleFloat3 normale = bcPtr->getNormalVector();
+                  LBMReal amp = vx1*val<1>(normale)+vx2*val<2>(normale)+vx3*val<3>(normale);
+
+                  vx1 = vx1 - amp * val<1>(normale); //normale zeigt von struktur weg!
+                  vx2 = vx2 - amp * val<2>(normale); //normale zeigt von struktur weg!
+                  vx3 = vx3 - amp * val<3>(normale); //normale zeigt von struktur weg!
+
+                  for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                  {
+                     if(bcPtr->hasSlipBoundaryFlag(fdir))
+                     {
+
+
+                        switch( bcPtr->getSlipSecondaryOption(fdir) )
+                        {
+                        case 0:
+                           //doesn't work
+                           //simple bounce back - do nothing
+                           break;
+                        case 1:
+                           {
+                              //quadratic bounce back
+                              const int invDir = D3Q27System::INVDIR[fdir];
+                              LBMReal q = 1.0;//bcPtr->getQ(invDir);// m+m q=0 stabiler
+                              //vx3=0;
+                              LBMReal velocity = 0.0;
+                              switch(invDir)
+                              {
+                              case D3Q27System::E : velocity = ( UbMath::c4o9*(+vx1) ); break;      //(2/cs^2)(=6)*rho_0(=1 bei imkompr)*wi*u*ei mit cs=1/sqrt(3)
+                              case D3Q27System::W : velocity = ( UbMath::c4o9*(-vx1) ); break;      //z.B. aus paper manfred MRT LB models in three dimensions (2002)   
+                              case D3Q27System::N : velocity = ( UbMath::c4o9*(+vx2) ); break;   
+                              case D3Q27System::S : velocity = ( UbMath::c4o9*(-vx2) ); break;
+                              case D3Q27System::T : velocity = ( UbMath::c4o9*(+vx3) ); break;
+                              case D3Q27System::B : velocity = ( UbMath::c4o9*(-vx3) ); break;
+                              case D3Q27System::NE: velocity = ( UbMath::c1o9*(+vx1+vx2             ) ); break;
+                              case D3Q27System::SW: velocity = ( UbMath::c1o9*(-vx1-vx2             ) ); break;
+                              case D3Q27System::SE: velocity = ( UbMath::c1o9*(+vx1-vx2             ) ); break;
+                              case D3Q27System::NW: velocity = ( UbMath::c1o9*(-vx1+vx2             ) ); break;
+                              case D3Q27System::TE: velocity = ( UbMath::c1o9*(+vx1             +vx3) ); break;
+                              case D3Q27System::BW: velocity = ( UbMath::c1o9*(-vx1             -vx3) ); break;
+                              case D3Q27System::BE: velocity = ( UbMath::c1o9*(+vx1             -vx3) ); break;
+                              case D3Q27System::TW: velocity = ( UbMath::c1o9*(-vx1             +vx3) ); break;
+                              case D3Q27System::TN: velocity = ( UbMath::c1o9*(             +vx2+vx3) ); break;
+                              case D3Q27System::BS: velocity = ( UbMath::c1o9*(             -vx2-vx3) ); break;
+                              case D3Q27System::BN: velocity = ( UbMath::c1o9*(             +vx2-vx3) ); break;
+                              case D3Q27System::TS: velocity = ( UbMath::c1o9*(             -vx2+vx3) ); break;
+                              case D3Q27System::TNE: velocity = ( UbMath::c1o36*(+vx1+vx2+vx3) ); break;
+                              case D3Q27System::BSW: velocity = ( UbMath::c1o36*(-vx1-vx2-vx3) ); break;
+                              case D3Q27System::BNE: velocity = ( UbMath::c1o36*(+vx1+vx2-vx3) ); break;
+                              case D3Q27System::TSW: velocity = ( UbMath::c1o36*(-vx1-vx2+vx3) ); break;
+                              case D3Q27System::TSE: velocity = ( UbMath::c1o36*(+vx1-vx2+vx3) ); break;
+                              case D3Q27System::BNW: velocity = ( UbMath::c1o36*(-vx1+vx2-vx3) ); break;
+                              case D3Q27System::BSE: velocity = ( UbMath::c1o36*(+vx1-vx2-vx3) ); break;
+                              case D3Q27System::TNW: velocity = ( UbMath::c1o36*(-vx1+vx2+vx3) ); break; 
+                              default: throw UbException(UB_EXARGS,"unknown error");
+                              }
+                              //LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir]*collFactor)/(1.0-collFactor))+((q*(ftemp[invDir]+ftemp[fdir])-velocity)/(1.0+q));
+                              LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir])/(1.0-collFactor)+feq[invDir])+((q*(ftemp[invDir]+ftemp[fdir])-velocity)/(1.0+q));
+                              distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                           }
+                           break;
+                        default:  
+                           UB_THROW( UbException(UB_EXARGS,"unknown secondary option for SlipBC") );
+                        }
+                     }
+                  }
+               }
+               }
+            }
+         }   
+      }
+   }
+
+
+//   for(int x3 = minX3; x3 < maxX3; x3++)      
+//   {
+//      for(int x2 = minX2; x2 < maxX2; x2++)      
+//      {
+//         for(int x1 = minX1; x1 < maxX1; x1++)  
+//         {
+//            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3)) 
+//            {
+//               if( (bcPtr=bcArray.getBC(x1,x2,x3)) != NULL)
+//               {
+//                  if(bcPtr->hasNoSlipBoundary())
+//                  {
+//                     //distributions->getDistributionInv(ftemp,x1,x2,x3);
+//                     //calcMacrosFct(ftemp,rho,vx1,vx2,vx3);
+//                     //calcFeqFct(feq,rho,vx1,vx2,vx3);
+//
+//                     for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+//                     {
+//                        if(bcPtr->hasNoSlipBoundaryFlag(fdir))
+//                        {
+//                           switch(bcPtr->getNoSlipSecondaryOption(fdir))
+//                           {
+//                           case 2:
+//                              {
+//                                 //quadratic bounce back with for thin walls
+//                                const int invDir = D3Q27System::INVDIR[fdir];
+///*                                 LBMReal q = bcPtr->getQ(invDir);
+//                                 LBMReal fReturn = ((1.0-q)/(1.0+q))*0.5*(ftemp[invDir]-ftemp[fdir]+(ftemp[invDir]+ftemp[fdir]-collFactor*(feq[fdir]+feq[invDir]))/(1.0-collFactor));*/ 
+//                                //printf("get distributionsTemp - start\n");
+//                                //printf("x1=%d,x2=%d,x3=%d,D3Q27System::DX1[invDir]=%d,D3Q27System::DX2[invDir]=%d,D3Q27System::DX3[invDir]%d\n",x1,x2,x3,D3Q27System::DX1[invDir],D3Q27System::DX2[invDir],D3Q27System::DX3[invDir]);
+//                                ftemp[fdir] = distributionsTemp->getDistributionInvForDirection(x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+//                                //printf("get distributionsTemp - end\n"); 
+//                                distributions->setDistributionForDirection(ftemp[fdir], x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+//                              }
+//                              break;
+//                           }
+//                        }
+//                     }
+//                  }
+//               }
+//            }
+//         }
+//      }
+//   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27ETBCProcessor::init()
+//{
+//   BoundaryConditionPtr velocity = getBC(BoundaryCondition::Velocity);
+//   BoundaryConditionPtr density  = getBC(BoundaryCondition::Density);
+//   BoundaryConditionPtr noSlip   = getBC(BoundaryCondition::NoSlip);
+//   BoundaryConditionPtr slip     = getBC(BoundaryCondition::Slip);
+//
+//   if (velocity) velocity->setCompressible(compressible);
+//   if (density) density->setCompressible(compressible);
+//   if (noSlip) noSlip->setCompressible(compressible);
+//   if (slip) slip->setCompressible(compressible);
+//
+//   int vCount = 0;
+//   int dCount = 0;
+//   int nsCount = 0;
+//   int sCount = 0;
+//
+//   for (int x3 = minX3; x3 < maxX3; x3++)
+//   {
+//      for (int x2 = minX2; x2 < maxX2; x2++)
+//      {
+//         for (int x1 = minX1; x1 < maxX1; x1++)
+//         {
+//            if (!bcArray.isSolid(x1, x2, x3) && !bcArray.isUndefined(x1, x2, x3))
+//            {
+//               if ((bcPtr = bcArray.getBC(x1, x2, x3)) != NULL)
+//               {
+//                  //velocity boundary condition
+//                  if (bcPtr->hasVelocityBoundary() && velocity)
+//                  {
+//                     velocity->addNode(x1, x2, x3);
+//                     velocity->addBcPointer(bcPtr);
+//                     vCount++;
+//                  }
+//                  //density boundary condition
+//                  else if (bcPtr->hasDensityBoundary() && density)
+//                  {
+//                     density->addNode(x1, x2, x3);
+//                     density->addBcPointer(bcPtr);
+//                     dCount++;
+//                  }
+//                  //no slip boundary condition
+//                  else if (bcPtr->hasNoSlipBoundary() && noSlip)
+//                  {
+//                     noSlip->addNode(x1, x2, x3);
+//                     noSlip->addBcPointer(bcPtr);
+//                     nsCount++;
+//                  }
+//                  //slip boundary condition
+//                  else if (bcPtr->hasSlipBoundary() && slip)
+//                  {
+//                     slip->addNode(x1, x2, x3);
+//                     slip->addBcPointer(bcPtr);
+//                     sCount++;
+//                  }
+//               }
+//            }
+//         }
+//      }
+//   }
+//   if (vCount > 0)
+//   {
+//      velocity->addNnode(vCount);
+//      velocity->addDistributions(distributions);
+//      velocity->setCollFactor(collFactor);
+//   }
+//   if (dCount > 0)
+//   {
+//      density->addNnode(dCount);
+//      density->addDistributions(distributions);
+//      density->setCollFactor(collFactor);
+//   }
+//   if (nsCount > 0)
+//   {
+//      noSlip->addNnode(nsCount);
+//      noSlip->addDistributions(distributions);
+//      noSlip->setCollFactor(collFactor);
+//   }
+//   if (sCount > 0)
+//   {
+//      slip->addNnode(sCount);
+//      slip->addDistributions(distributions);
+//      slip->setCollFactor(collFactor);
+//   }
+//}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETBCProcessor::addBC(BoundaryConditionPtr bc)
+{
+   BoundaryCondition::Type type = bc->getType();
+   if (bc->isPreCollision())
+   {
+      preBC.push_back(bc);
+   }
+   else
+   {
+      postBC.push_back(bc);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr D3Q27ETBCProcessor::getBC(BoundaryCondition::Type type)
+{
+   BOOST_FOREACH(BoundaryConditionPtr bc, preBC)
+   {
+      if (bc->getType() == type)
+      {
+         return bc;
+      }
+   }
+
+   BOOST_FOREACH(BoundaryConditionPtr bc, postBC)
+   {
+      if (bc->getType() == type)
+      {
+         return bc;
+      }
+   }
+
+   return BoundaryConditionPtr();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETBCProcessor::applyPreCollisionBC()
+{
+   BOOST_FOREACH(BoundaryConditionPtr bc, preBC)
+   {
+      bc->apply();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETBCProcessor::applyPostCollisionBC()
+{
+   BOOST_FOREACH(BoundaryConditionPtr bc, postBC)
+   {
+      bc->apply();
+   }
+}
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETBCProcessor.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETBCProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..75e34f5922cb7311475fb4297b5a0a2e2c55634d
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETBCProcessor.h
@@ -0,0 +1,85 @@
+#ifndef D3Q27ETBCPROCESSSOR_H
+#define D3Q27ETBCPROCESSSOR_H
+
+#include "BCProcessor.h"
+#include "D3Q27BoundaryCondition.h"
+#include "EsoTwist3D.h"
+#include "BCArray3D.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+//#include "BoundaryCondition.h"
+#include <vector>
+
+#include <boost/serialization/base_object.hpp>
+
+class D3Q27ETBCProcessor;
+typedef boost::shared_ptr<D3Q27ETBCProcessor> D3Q27ETBCProcessorPtr;
+
+class D3Q27ETBCProcessor : public BCProcessor
+{
+public:
+   D3Q27ETBCProcessor();
+   D3Q27ETBCProcessor(LBMKernel3DPtr kernel);
+   virtual ~D3Q27ETBCProcessor();
+   virtual void applyBC();
+   virtual BCArray3D<D3Q27BoundaryCondition>& getBCArray();
+   virtual BCProcessorPtr clone(LBMKernel3DPtr kernel);
+
+   void addBC(BoundaryConditionPtr bc);
+   BoundaryConditionPtr getBC(BoundaryCondition::Type type);
+   void applyPreCollisionBC();
+   void applyPostCollisionBC();
+   //void init();
+protected:
+   std::vector<BoundaryConditionPtr> preBC;
+   std::vector<BoundaryConditionPtr> postBC;
+
+   int minX1, minX2, minX3, maxX1, maxX2, maxX3;
+   D3Q27BoundaryConditionPtr bcPtr;
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal ftemp[D3Q27System::ENDF+1];
+   LBMReal feq[D3Q27System::ENDF+1];
+   LBMReal rho, vx1, vx2, vx3, rho0;
+
+   //void init(LBMKernel3DPtr kernel);
+   BCArray3D<D3Q27BoundaryCondition> bcArray;
+   EsoTwist3DPtr distributions;
+   int ghostLayerWitdh;
+   LBMReal collFactor;
+   bool compressible;
+   EsoTwist3DPtr distributionsTemp;
+
+   //std::vector <int> sizeVector;
+   //std::vector <int> nodeVector;
+   //std::vector <D3Q27BoundaryConditionPtr> bcVector;
+
+   //typedef void(*CalcMacrosFct)(const LBMReal* const& /*f[27]*/, LBMReal& /*rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   //typedef LBMReal(*CalcFeqForDirFct)(const int& /*direction*/, const LBMReal& /*(d)rho*/, const LBMReal& /*vx1*/, const LBMReal& /*vx2*/, const LBMReal& /*vx3*/);
+   //typedef  void(*CalcFeqFct)(LBMReal* const& /*feq/*[27]*/, const LBMReal& /*rho*/, const LBMReal& /*vx1*/, const LBMReal& /*vx2*/, const LBMReal& /*vx3*/);
+   //CalcFeqForDirFct calcFeqsForDirFct;
+   //CalcMacrosFct    calcMacrosFct;
+   //CalcFeqFct       calcFeqFct;
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BCProcessor>(*this);
+      ar & bcArray;
+      ar & distributions;
+      ar & ghostLayerWitdh;
+      ar & collFactor;
+      ar & compressible;
+      ar & minX1;
+      ar & minX2;
+      ar & minX3;
+      ar & maxX1;
+      ar & maxX2;
+      ar & maxX3;
+      ar & distributionsTemp;
+      ar & preBC;
+      ar & postBC;
+   }
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETForThinWallBCProcessor.cpp b/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETForThinWallBCProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f12da636602ea97410354f3c0d7cd78ce0c6cb35
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETForThinWallBCProcessor.cpp
@@ -0,0 +1,82 @@
+#include "D3Q27ETForThinWallBCProcessor.h"
+
+#include "D3Q27EsoTwist3DSplittedVector.h"
+
+D3Q27ETForThinWallBCProcessor::D3Q27ETForThinWallBCProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27ETForThinWallBCProcessor::D3Q27ETForThinWallBCProcessor(LBMKernel3DPtr kernel) : D3Q27ETBCProcessor(kernel)
+{
+   //distributionsTemp = EsoTwist3DPtr(new D3Q27EsoTwist3DSplittedVector(maxX1, maxX2, maxX2, -999.0));
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27ETForThinWallBCProcessor::~D3Q27ETForThinWallBCProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+BCProcessorPtr D3Q27ETForThinWallBCProcessor::clone(LBMKernel3DPtr kernel)
+{
+   BCProcessorPtr bcProcessor(new D3Q27ETForThinWallBCProcessor(kernel));
+   return bcProcessor;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETForThinWallBCProcessor::applyBC()
+{
+   D3Q27ETBCProcessor::applyBC();
+
+   LBMReal fReturn;
+
+   for (int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for (int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for (int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if (!bcArray.isSolid(x1, x2, x3) && !bcArray.isUndefined(x1, x2, x3))
+            {
+               if ((bcPtr=bcArray.getBC(x1, x2, x3)) != NULL)
+               {
+                  if (bcPtr->hasNoSlipBoundary())
+                  {
+                     for (int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                     {
+                        if (bcPtr->hasNoSlipBoundaryFlag(fdir))
+                        {
+                           switch (bcPtr->getNoSlipSecondaryOption(fdir))
+                           {
+                           case 2:
+                           {
+                              //quadratic bounce back with for thin walls
+                              const int invDir = D3Q27System::INVDIR[fdir];
+                              fReturn = distributionsTemp->getDistributionInvForDirection(x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                              distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+                           }
+                           break;
+                           }
+                        }
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETForThinWallBCProcessor::applyPostCollisionBC()
+{
+   D3Q27ETBCProcessor::applyPostCollisionBC();
+
+   BOOST_FOREACH(BoundaryConditionPtr bc, postBC)
+   {
+      if (bc->getType() == BoundaryCondition::NoSlip)
+      {
+         bc->apply();
+      }
+   }
+}
+
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETForThinWallBCProcessor.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETForThinWallBCProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..7acafa538d88a64acb57bfb88b37fb646674af64
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27ETForThinWallBCProcessor.h
@@ -0,0 +1,37 @@
+#ifndef D3Q27ETFORTHINWALLBCPROCESSSOR_H
+#define D3Q27ETFORTHINWALLBCPROCESSSOR_H
+
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27BoundaryCondition.h"
+#include "EsoTwist3D.h"
+#include "BCArray3D.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+
+#include <boost/serialization/base_object.hpp>
+
+class D3Q27ETForThinWallBCProcessor;
+typedef boost::shared_ptr<D3Q27ETForThinWallBCProcessor> D3Q27ETForThinWallBCProcessorPtr;
+
+class D3Q27ETForThinWallBCProcessor : public D3Q27ETBCProcessor
+{
+public:
+   D3Q27ETForThinWallBCProcessor();
+   D3Q27ETForThinWallBCProcessor(LBMKernel3DPtr kernel);
+   virtual ~D3Q27ETForThinWallBCProcessor();
+   virtual void applyBC();
+   virtual BCProcessorPtr clone(LBMKernel3DPtr kernel);
+   void applyPostCollisionBC();
+protected:
+   //EsoTwist3DPtr distributionsTemp;
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<D3Q27ETBCProcessor>(*this);
+      //ar & distributionsTemp;
+   }
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27NoSlipBCAdapter.cpp b/source/VirtualFluidsCore/BoundaryCondition/D3Q27NoSlipBCAdapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b6433969d456386f4334d50dbe0e084fde915425
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27NoSlipBCAdapter.cpp
@@ -0,0 +1 @@
+#include "D3Q27NoSlipBCAdapter.h"
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27NoSlipBCAdapter.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27NoSlipBCAdapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..927ae9ee89d2b450995b5082611e7da24182b786
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27NoSlipBCAdapter.h
@@ -0,0 +1,52 @@
+#ifndef D3Q27NOSLIPBCADAPTER_H
+#define D3Q27NOSLIPBCADAPTER_H
+
+#include "D3Q27BoundaryConditionAdapter.h"
+
+/*=========================================================================*/
+/*  D3Q27NoSlipBCAdapter                                                   */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 06.09.06
+*/ 
+
+/*
+usage: ...
+*/
+
+class D3Q27NoSlipBCAdapter : public D3Q27BoundaryConditionAdapter
+{
+public:
+   D3Q27NoSlipBCAdapter()
+    : D3Q27BoundaryConditionAdapter()
+   {
+   }
+   D3Q27NoSlipBCAdapter(const short& secondaryBcOption)
+      : D3Q27BoundaryConditionAdapter(secondaryBcOption)
+   {
+   }
+
+   void init(const D3Q27Interactor* const& interactor, const double& time=0) {}
+   void update(const D3Q27Interactor* const& interactor, const double& time=0) {}
+
+   void adaptBCForDirection( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time=0 )
+   {
+      bc->setNoSlipBoundaryFlag(D3Q27System::INVDIR[fdirection],secondaryBcOption);
+      bc->setQ((float)q,fdirection);
+   }
+   void adaptBC( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time=0 ) 
+   {
+
+   }
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<D3Q27BoundaryConditionAdapter>(*this);
+   }
+};
+#endif //D3Q27NOSLIPBCADAPTER_H
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27SlipBCAdapter.cpp b/source/VirtualFluidsCore/BoundaryCondition/D3Q27SlipBCAdapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..349e24bf41d20cbbd583ee5cfa09ac1638ee5657
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27SlipBCAdapter.cpp
@@ -0,0 +1,33 @@
+#include "D3Q27SlipBCAdapter.h"
+#include "D3Q27System.h"
+#include "D3Q27Interactor.h"
+#include "numerics/geometry3d/GbCuboid3D.h"
+#include <boost/pointer_cast.hpp>
+
+//*==========================================================*/
+//ObObject* D3Q27SlipBCAdapterCreator::createObObject()
+//{
+//   return new D3Q27SlipBCAdapter; 
+//}
+//*==========================================================*/
+//ObObjectCreator* D3Q27SlipBCAdapter::getCreator()
+//{
+//   return D3Q27SlipBCAdapterCreator::getInstance();
+//}
+//*==========================================================*/
+void D3Q27SlipBCAdapter::adaptBC(const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time)
+{
+   //////////////////////////////////////////////////////////////////////////
+   //>>> nur workaround! -> Hendrick nach normalen berechnung aus qs fragen
+   
+   GbCuboid3DPtr geo = boost::dynamic_pointer_cast<GbCuboid3D>(interactor.getGbObject3D());
+   if(!geo) throw UbException(UB_EXARGS,"derzeit nur fuer Cubes valide");
+
+   if     ( bc->hasSlipBoundaryFlag(D3Q27System::E) ) bc->setNormalVector( 1.0, 0.0, 0.0);  
+   else if( bc->hasSlipBoundaryFlag(D3Q27System::W) ) bc->setNormalVector(-1.0, 0.0, 0.0);  
+   else if( bc->hasSlipBoundaryFlag(D3Q27System::N) ) bc->setNormalVector( 0.0, 1.0, 0.0);  
+   else if( bc->hasSlipBoundaryFlag(D3Q27System::S) ) bc->setNormalVector( 0.0,-1.0, 0.0);  
+   else if( bc->hasSlipBoundaryFlag(D3Q27System::T) ) bc->setNormalVector( 0.0, 0.0, 1.0);  
+   else if( bc->hasSlipBoundaryFlag(D3Q27System::B) ) bc->setNormalVector( 0.0, 0.0,-1.0);  
+}
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27SlipBCAdapter.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27SlipBCAdapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a2ff7ee5b4ecb8f2c0436af15d4f30de914683a
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27SlipBCAdapter.h
@@ -0,0 +1,94 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef D3Q27SLIPBCADAPTER_H
+#define D3Q27SLIPBCADAPTER_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+#include "D3Q27BoundaryConditionAdapter.h"
+
+
+/*=======================================================*/
+//D3Q27SlipBCAdapterCreator
+//class D3Q27SlipBCAdapterCreator : public ObObjectCreator
+//{
+//public: 
+//   static D3Q27SlipBCAdapterCreator* getInstance()
+//   {
+//      static D3Q27SlipBCAdapterCreator instance;
+//      return &instance;
+//   }
+//   
+//   ObObject* createObObject();  
+//
+//   std::string getTypeID() { return "D3Q27SlipBCAdapter";}        
+//   std::string toString()  { return "D3Q27SlipBCAdapterCreator"; }
+//
+//private:
+//   D3Q27SlipBCAdapterCreator( const D3Q27SlipBCAdapterCreator& );                  //no copy allowed 
+//   const D3Q27SlipBCAdapterCreator& operator=( const D3Q27SlipBCAdapterCreator& ); //no copy allowed
+//   D3Q27SlipBCAdapterCreator() : ObObjectCreator() {}
+//};
+//
+//#ifndef SWIG
+//UB_AUTO_RUN_NAMED( D3Q27BCAdapterFactory::getInstance()->addObObjectCreator(D3Q27SlipBCAdapterCreator::getInstance()), CAB_D3Q27SlipBCAdapterCreator);
+//#endif
+
+/*=========================================================================*/
+/*  D3Q27SlipBCAdapter                                                     */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 06.09.06
+*/ 
+
+/*
+usage: ...
+*/
+
+class D3Q27SlipBCAdapter : public D3Q27BoundaryConditionAdapter
+{
+public:
+   D3Q27SlipBCAdapter() 
+      : D3Q27BoundaryConditionAdapter()
+   {
+   }
+   D3Q27SlipBCAdapter(const short& secondaryBcOption)
+      : D3Q27BoundaryConditionAdapter(secondaryBcOption)
+   {
+   }
+
+   //------------- implements D3Q27BoundaryConditionAdapter ----- start
+   ObObjectCreator* getCreator();
+
+   void init(const D3Q27Interactor* const& interactor, const double& timestep=0) {}
+   void update(const D3Q27Interactor* const& interactor, const double& timestep=0) {}
+
+   void adaptBCForDirection( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time=0 )
+   {
+      bc->setSlipBoundaryFlag(D3Q27System::INVDIR[fdirection],secondaryBcOption);
+      bc->setQ((float)q,fdirection);
+   }
+   void adaptBC(const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time=0);
+   
+   //------------- implements D3Q27BoundaryConditionAdapter ----- end
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<D3Q27BoundaryConditionAdapter>(*this);
+}
+
+};
+
+#endif
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27VelocityBCAdapter.cpp b/source/VirtualFluidsCore/BoundaryCondition/D3Q27VelocityBCAdapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e63e080d62f2688bfaadc175402b347fe9771280
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27VelocityBCAdapter.cpp
@@ -0,0 +1,305 @@
+#include "D3Q27VelocityBCAdapter.h"
+#include "basics/utilities/UbLogger.h"
+#include "basics/utilities/UbMath.h"
+#include "basics/utilities/UbTuple.h"
+
+using namespace std;
+
+
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const D3Q27BCFunction& velVxBC)
+{
+   if(vx1) this->vx1BCs.push_back(velVxBC);
+   if(vx2) this->vx2BCs.push_back(velVxBC);
+   if(vx3) this->vx3BCs.push_back(velVxBC);
+   this->init();
+}
+/*==========================================================*/
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const mu::Parser& function, const double& startTime, const double& endTime )
+{
+   if(vx1) this->vx1BCs.push_back(D3Q27BCFunction(function,startTime,endTime));
+   if(vx2) this->vx2BCs.push_back(D3Q27BCFunction(function,startTime,endTime));
+   if(vx3) this->vx3BCs.push_back(D3Q27BCFunction(function,startTime,endTime));
+   this->init();
+}
+/*==========================================================*/
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const mu::Parser& function1, const mu::Parser& function2, const mu::Parser& function3, const double& startTime, const double& endTime )
+{
+   if(vx1) this->vx1BCs.push_back(D3Q27BCFunction(function1,startTime,endTime));
+   if(vx2) this->vx2BCs.push_back(D3Q27BCFunction(function2,startTime,endTime));
+   if(vx3) this->vx3BCs.push_back(D3Q27BCFunction(function3,startTime,endTime));
+   this->init();
+}
+/*==========================================================*/
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const string& functionstring, const double& startTime, const double& endTime )
+{
+   if(vx1) this->vx1BCs.push_back(D3Q27BCFunction(functionstring,startTime,endTime));
+   if(vx2) this->vx2BCs.push_back(D3Q27BCFunction(functionstring,startTime,endTime));
+   if(vx3) this->vx3BCs.push_back(D3Q27BCFunction(functionstring,startTime,endTime));
+   this->init();
+}
+/*==========================================================*/
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const D3Q27BCFunction& velBC, bool x1Dir, bool x2Dir, bool x3Dir)
+{
+   if(x1Dir) this->vx1BCs.push_back(velBC);
+   if(x2Dir) this->vx2BCs.push_back(velBC);
+   if(x3Dir) this->vx3BCs.push_back(velBC);
+   this->init();
+}
+/*==========================================================*/
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const D3Q27BCFunction& velVx1BC, const D3Q27BCFunction& velVx2BC, const D3Q27BCFunction& velVx3BC)
+{
+   if( velVx1BC.getEndTime()!=-Ub::inf ) this->vx1BCs.push_back(velVx1BC);
+   if( velVx2BC.getEndTime()!=-Ub::inf ) this->vx2BCs.push_back(velVx2BC);
+   if( velVx3BC.getEndTime()!=-Ub::inf ) this->vx3BCs.push_back(velVx3BC);
+   this->init();
+}
+/*==========================================================*/
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const vector< D3Q27BCFunction >& velVx1BCs, const vector< D3Q27BCFunction >& velVx2BCs, const vector< D3Q27BCFunction >& velVx3BCs)
+{
+   this->vx1BCs = velVx1BCs;
+   this->vx2BCs = velVx2BCs;
+   this->vx3BCs = velVx3BCs;
+   this->init();
+}
+/*==========================================================*/
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const double& vx1, const double& vx1StartTime, const double& vx1EndTime,
+                                               const double& vx2, const double& vx2StartTime, const double& vx2EndTime,
+                                               const double& vx3, const double& vx3StartTime, const double& vx3EndTime )
+{
+   this->vx1BCs.push_back(D3Q27BCFunction(vx1,vx1StartTime,vx1EndTime));
+   this->vx2BCs.push_back(D3Q27BCFunction(vx2,vx2StartTime,vx2EndTime));
+   this->vx3BCs.push_back(D3Q27BCFunction(vx3,vx3StartTime,vx3EndTime));
+   this->init();
+}
+/*==========================================================*/
+D3Q27VelocityBCAdapter::D3Q27VelocityBCAdapter(const string& vx1Function, const double& vx1StartTime, const double& vx1EndTime,
+                                               const string& vx2Function, const double& vx2StartTime, const double& vx2EndTime,
+                                               const string& vx3Function, const double& vx3StartTime, const double& vx3EndTime ) 
+{
+   if(vx1Function.size()) this->vx1BCs.push_back(D3Q27BCFunction(vx1Function,vx1StartTime,vx1EndTime));
+   if(vx2Function.size()) this->vx2BCs.push_back(D3Q27BCFunction(vx2Function,vx2StartTime,vx2EndTime));
+   if(vx3Function.size()) this->vx3BCs.push_back(D3Q27BCFunction(vx3Function,vx3StartTime,vx3EndTime));
+   this->init();
+}
+/*==========================================================*/
+void D3Q27VelocityBCAdapter::setNewVelocities(const double& vx1, const double& vx1StartTime, const double& vx1EndTime,
+                                              const double& vx2, const double& vx2StartTime, const double& vx2EndTime,
+                                              const double& vx3, const double& vx3StartTime, const double& vx3EndTime )
+{
+   this->clear();
+   this->vx1BCs.push_back(D3Q27BCFunction(vx1,vx1StartTime,vx1EndTime));
+   this->vx2BCs.push_back(D3Q27BCFunction(vx2,vx2StartTime,vx2EndTime));
+   this->vx3BCs.push_back(D3Q27BCFunction(vx3,vx3StartTime,vx3EndTime));
+   this->init();
+}
+/*==========================================================*/
+void D3Q27VelocityBCAdapter::init()
+{
+   this->unsetTimeDependent();
+   
+   this->timeStep = 0.0;
+
+   this->x1 = 0.0;
+   this->x2 = 0.0;
+   this->x3 = 0.0;
+
+   this->tmpVx1Function = NULL;
+   this->tmpVx2Function = NULL;
+   this->tmpVx3Function = NULL;
+
+   try //initilialization and validation of functions
+   {
+      this->init(vx1BCs);
+      this->init(vx2BCs);
+      this->init(vx3BCs);
+   }
+   catch(mu::Parser::exception_type& e){ stringstream error; error<<"mu::parser exception occurs, message("<<e.GetMsg()<<"), formula("<<e.GetExpr()+"), token("+e.GetToken()<<")"
+                                          <<", pos("<<e.GetPos()<<"), error code("<<e.GetCode(); throw UbException(error.str()); }
+   catch(...)                          { throw UbException(UB_EXARGS,"unknown exception" ); }
+}
+/*==========================================================*/
+void D3Q27VelocityBCAdapter::init(std::vector<D3Q27BCFunction>& vxBCs)
+{
+   for(size_t pos=0; pos<vxBCs.size(); ++pos)
+   {
+      if( !(    UbMath::equal( D3Q27BCFunction::INFCONST, vxBCs[pos].getEndTime() )
+             && UbMath::greaterEqual( this->timeStep,  vxBCs[pos].getStartTime()  ) ) )
+      {
+         this->setTimeDependent();
+      }
+
+      vxBCs[pos].getFunction().DefineVar("t" , &this->timeStep);
+      vxBCs[pos].getFunction().DefineVar("x1", &this->x1      );
+      vxBCs[pos].getFunction().DefineVar("x2", &this->x2      );
+      vxBCs[pos].getFunction().DefineVar("x3", &this->x3      );
+
+      vxBCs[pos].getFunction().Eval(); //<-- validation
+   }
+}
+/*==========================================================*/
+void D3Q27VelocityBCAdapter::init(const D3Q27Interactor* const& interactor, const double& time)
+{
+   this->timeStep       = time;
+   this->tmpVx1Function = this->tmpVx2Function = this->tmpVx3Function = NULL;
+
+   //aktuelle velocityfunction bestimmen
+   double maxEndtime = -Ub::inf;
+   
+   for(size_t pos=0; pos<vx1BCs.size(); ++pos)
+   {
+      if( UbMath::equal(vx1BCs[pos].getEndTime(),D3Q27BCFunction::INFTIMEDEPENDENT) ) maxEndtime=Ub::inf;
+      maxEndtime = UbMath::max(maxEndtime,vx1BCs[pos].getStartTime(),vx1BCs[pos].getEndTime()); //startTime abfragen, da  INFCONST=-10
+      
+      if( UbMath::greaterEqual(this->timeStep,vx1BCs[pos].getStartTime()) ) 
+      {
+          if(   UbMath::lessEqual( this->timeStep     , vx1BCs[pos].getEndTime()     )
+             || UbMath::equal(     vx1BCs[pos].getEndTime(), (double)D3Q27BCFunction::INFCONST        )
+             || UbMath::equal(     vx1BCs[pos].getEndTime(), (double)D3Q27BCFunction::INFTIMEDEPENDENT)  )
+         {
+            tmpVx1Function = &vx1BCs[pos].getFunction();
+            break;
+         }
+      }
+   }
+   for(size_t pos=0; pos<vx2BCs.size(); ++pos)
+   {
+      if( UbMath::equal(vx2BCs[pos].getEndTime(),D3Q27BCFunction::INFTIMEDEPENDENT)) maxEndtime=Ub::inf;
+      maxEndtime = UbMath::max(maxEndtime,vx2BCs[pos].getStartTime(),vx2BCs[pos].getEndTime()); //startTime abfragen, da  INFCONST=-10
+
+      if( UbMath::greaterEqual(this->timeStep,vx2BCs[pos].getStartTime()) ) 
+      {
+         if(   UbMath::lessEqual( this->timeStep     , vx2BCs[pos].getEndTime()      )
+            || UbMath::equal(     vx2BCs[pos].getEndTime(), (double)D3Q27BCFunction::INFCONST         )
+            || UbMath::equal(     vx2BCs[pos].getEndTime(), (double)D3Q27BCFunction::INFTIMEDEPENDENT )  )
+         {
+            tmpVx2Function = &vx2BCs[pos].getFunction();
+            break;
+         }
+      }
+   }
+   for(size_t pos=0; pos<vx3BCs.size(); ++pos)
+   {
+      if( UbMath::equal(vx3BCs[pos].getEndTime(),D3Q27BCFunction::INFTIMEDEPENDENT)) maxEndtime=Ub::inf;
+      maxEndtime = UbMath::max(maxEndtime,vx3BCs[pos].getStartTime(),vx3BCs[pos].getEndTime()); //startTime abfragen, da  INFCONST=-10
+
+      if( UbMath::greaterEqual(this->timeStep,vx3BCs[pos].getStartTime()) ) 
+      {
+         if(   UbMath::lessEqual( this->timeStep     , vx3BCs[pos].getEndTime()      )
+            || UbMath::equal(     vx3BCs[pos].getEndTime(), (double)D3Q27BCFunction::INFCONST         )
+            || UbMath::equal(     vx3BCs[pos].getEndTime(), (double)D3Q27BCFunction::INFTIMEDEPENDENT )  )
+         {
+            tmpVx3Function = &vx3BCs[pos].getFunction();
+            break;
+         }
+      }
+   }
+
+   if( UbMath::greaterEqual(time,maxEndtime) ) 
+   {
+      if( !this->isTimePeriodic() ) this->unsetTimeDependent();
+      else //bei peridoic die interavalle neu setzen:
+      {
+         if( UbMath::equal(maxEndtime,D3Q27BCFunction::INFCONST) )
+            for(size_t pos=0; pos<vx1BCs.size(); ++pos)
+            {
+               vx1BCs[pos].setStartTime( vx1BCs[pos].getStartTime() + timeStep );
+               vx1BCs[pos].setEndTime( vx1BCs[pos].getEndTime() + timeStep );
+            }
+            if( UbMath::equal(maxEndtime,D3Q27BCFunction::INFCONST) )
+            for(size_t pos=0; pos<vx2BCs.size(); ++pos)
+            {
+               vx2BCs[pos].setStartTime( vx2BCs[pos].getStartTime() + timeStep );
+               vx2BCs[pos].setEndTime( vx2BCs[pos].getEndTime() + timeStep );
+            }
+         if( UbMath::equal(maxEndtime,D3Q27BCFunction::INFCONST) )
+            for(size_t pos=0; pos<vx3BCs.size(); ++pos)
+            {
+               vx3BCs[pos].setStartTime( vx3BCs[pos].getStartTime() + timeStep );
+               vx3BCs[pos].setEndTime( vx3BCs[pos].getEndTime() + timeStep );
+            }
+        this->init(interactor,time);
+      }
+   }
+
+   UBLOG(logDEBUG4,"D3Q27VelocityBCAdapter::init(time="<<time<<") "
+                   <<", vx1= \""<<(tmpVx1Function ? tmpVx1Function->GetExpr() : "-")<<"\""
+                   <<", vx2= \""<<(tmpVx2Function ? tmpVx2Function->GetExpr() : "-")<<"\""
+                   <<", vx3= \""<<(tmpVx3Function ? tmpVx3Function->GetExpr() : "-")<<"\""
+                   <<", timedependent="<<boolalpha<<this->isTimeDependent()   );
+}
+/*==========================================================*/
+void D3Q27VelocityBCAdapter::update( const D3Q27Interactor* const& interactor, const double& time ) 
+{
+   this->init(interactor,time);
+}
+/*==========================================================*/
+void D3Q27VelocityBCAdapter::adaptBCForDirection( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time )
+{
+   bc->setVelocityBoundaryFlag(D3Q27System::INVDIR[fdirection],secondaryBcOption);
+   bc->setQ((float)q,fdirection);
+}
+/*==========================================================*/
+void D3Q27VelocityBCAdapter::adaptBC( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time ) 
+{
+   this->setNodeVelocity(interactor,bc,worldX1,worldX2,worldX3,time);
+}
+/*==========================================================*/
+void D3Q27VelocityBCAdapter::setNodeVelocity( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& timestep) 
+{
+   //Geschwindigkeiten setzen
+   try
+   {
+      //PunktKoordinaten bestimmen
+      this->x1 = worldX1;
+      this->x2 = worldX2;
+      this->x3 = worldX3;
+      this->timeStep = timestep;
+
+      if(tmpVx1Function) bc->setBoundaryVelocityX1((float)tmpVx1Function->Eval());  
+      if(tmpVx2Function) bc->setBoundaryVelocityX2((float)tmpVx2Function->Eval());
+      if(tmpVx3Function) bc->setBoundaryVelocityX3((float)tmpVx3Function->Eval());
+   }
+   catch(mu::Parser::exception_type& e){ stringstream error; error<<"mu::parser exception occurs, message("<<e.GetMsg()<<"), formula("<<e.GetExpr()+"), token("+e.GetToken()<<")"
+                                         <<", pos("<<e.GetPos()<<"), error code("<<e.GetCode(); throw UbException(error.str()); }
+   catch(...)                          { throw UbException(UB_EXARGS,"unknown exception" ); }
+}
+/*==========================================================*/
+UbTupleDouble3 D3Q27VelocityBCAdapter::getVelocity(const double& x1, const double& x2, const double& x3, const double& timeStep) const
+{
+	double vx1 = 0.0;
+	double vx2 = 0.0;
+	double vx3 = 0.0;
+   this->x1 = x1;
+   this->x2 = x2;
+   this->x3 = x3;
+   this->timeStep = timeStep;
+	
+	if(tmpVx1Function) vx1 = tmpVx1Function->Eval();  
+   if(tmpVx2Function) vx2 = tmpVx2Function->Eval();
+   if(tmpVx3Function) vx3 = tmpVx3Function->Eval();
+    
+   return UbTupleDouble3(vx1,vx2,vx3);
+}
+/*==========================================================*/
+string D3Q27VelocityBCAdapter::toString()
+{
+   stringstream info;
+   info<<"D3Q27VelocityBCAdapter:\n";
+   info<<" #vx1-functions = "<<(int)vx1BCs.size()<<endl;
+   info<<" #vx2-functions = "<<(int)vx2BCs.size()<<endl;
+   info<<" #vx3-functions = "<<(int)vx3BCs.size()<<endl;
+   info<<" protected variables: x1, x2, x3, t"<<endl;
+   
+   const vector<D3Q27BCFunction>* bcvecs[3] = { &vx1BCs, &vx2BCs, &vx3BCs };
+   for(int i=0; i<3; i++)
+   {
+      for(size_t pos=0; pos<bcvecs[i]->size(); ++pos)
+      {
+         info<<"\n   vx"<<(i+1)<<"-function nr."<<pos<<":"<<endl;
+         info<<(*bcvecs[i])[pos]<<endl;
+      }
+   }
+   return info.str();
+}
+
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/D3Q27VelocityBCAdapter.h b/source/VirtualFluidsCore/BoundaryCondition/D3Q27VelocityBCAdapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..679cd455e9b7f0194cee847f24dcb279fabb346b
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/D3Q27VelocityBCAdapter.h
@@ -0,0 +1,156 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef D3Q27VELOCITYADAPTER_H
+#define D3Q27VELOCITYADAPTER_H
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif
+
+#include <basics/utilities/UbInfinity.h>
+#include <basics/utilities/UbFileOutput.h>
+#include <basics/utilities/UbFileInput.h>
+
+class UbFileOutput;
+class UbFileInput;
+
+#include <D3Q27BoundaryConditionAdapter.h>
+#include <D3Q27BCFunction.h>
+
+//example:
+//        vector<D3Q27BCFunction> vx1BCs,vx2BCs,vx3BCs;
+//        vx1BCs.push_back(D3Q27BCFunction(0.01 , 0  , 100) );   //t=[0  ..100[ -> vx1 = 0.01
+//        vx1BCs.push_back(D3Q27BCFunction(0.004, 100, 200) );   //t=[100..200[ -> vx1 = 0.004
+//        vx1BCs.push_back(D3Q27BCFunction(0.03 , 200, 400) );   //t=[200..400] -> vx1 = 0.03
+// 
+//        vx2BCs.push_back(D3Q27BCFunction(0.02 , 0  , 200) );   //t=[0  ..200[ -> vx2 = 0.02
+//        vx2BCs.push_back(D3Q27BCFunction(0.002, 200, 300) );   //t=[200..300[ -> vx2 = 0.002
+//        vx2BCs.push_back(D3Q27BCFunction(0.043, 300, 600) );   //t=[300..600] -> vx2 = 0.043
+//        
+//        D3Q27VelocityBCAdapter bcAdapter(vx1BCs,vx2BCs,vx3BCs);
+//        bcAdapter.setTimePeriodic(); //->  t=[0  ..100[ -> vx1 = 0.01
+//                                     //    t=[100..200[ -> vx1 = 0.004
+//                                     //    t=[200..400[ -> vx1 = 0.03
+//                                     //    t=[400..500[ -> vx1 = 0.01
+//                                     //    t=[500..600[ -> vx1 = 0.004
+//                                     //    t=[600..800[ -> vx1 = 0.03  ...
+//                                     //    t=[0  ..200[ -> vx2 = 0.02
+//                                     //    t=[200..300[ -> vx2 = 0.002
+//                                     //    t=[300..600] -> vx2 = 0.043
+//                                     //    t=[600..800[ -> vx2 = 0.02
+//                                     //    t=[800..900[ -> vx2 = 0.002
+//                                     //    t=[900..1200]-> vx2 = 0.043  ...
+//
+// example parabolic inflow:
+//    mu::Parser fct;
+//    fct.SetExpr("max(vmax*(1.0-4.0*((x2-x2_vmax)^2+(x3-x3_vmax)^2)/H^2),0.0)"); //paraboloid (mit vmax bei (0/x2_vmax/x3_vmax) 
+//    fct.DefineConst("x2Vmax", 0.0            ); //x2-Pos für vmax
+//    fct.DefineConst("x3Vmax", 0.0            ); //x3-Pos für vmax
+//    fct.DefineConst("H"     , rohrDurchmesser);
+//    fct.DefineConst("vmax"  , vmax           );
+//    D3Q27VelocityBCAdapter velBC(true, false ,false ,fct, 0, D3Q27BCFunction::INFCONST);
+
+/*=========================================================================*/
+/*  D3Q27VelocityBCAdapter                                                 */
+/*                                                                         */
+/**
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 06.09.06
+*/ 
+
+class D3Q27VelocityBCAdapter : public D3Q27BoundaryConditionAdapter
+{
+public:
+   //constructors
+   D3Q27VelocityBCAdapter() { this->init(); }
+   
+   D3Q27VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const D3Q27BCFunction& velVxBC );
+
+   D3Q27VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const mu::Parser& function, const double& startTime, const double& endTime  );
+
+   D3Q27VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const mu::Parser& function1, const mu::Parser& function2, const mu::Parser& function3, const double& startTime, const double& endTime );
+   
+   D3Q27VelocityBCAdapter(const bool& vx1, const bool& vx2, const bool& vx3, const std::string& functionstring, const double& startTime, const double& endTime );
+
+   D3Q27VelocityBCAdapter(const D3Q27BCFunction& velBC, bool x1Dir, bool x2Dir, bool x3Dir);
+
+   D3Q27VelocityBCAdapter(const D3Q27BCFunction& velVx1BC, const D3Q27BCFunction& velVx2BC, const D3Q27BCFunction& velVx3BC);
+
+   D3Q27VelocityBCAdapter(const std::vector< D3Q27BCFunction >& velVx1BCs, const std::vector< D3Q27BCFunction >& velVx2BCs, const std::vector< D3Q27BCFunction >& velVx3BCs);
+
+   D3Q27VelocityBCAdapter(const double& vx1, const double& vx1StartTime, const double& vx1EndTime,
+                          const double& vx2, const double& vx2StartTime, const double& vx2EndTime,
+                          const double& vx3, const double& vx3StartTime, const double& vx3EndTime);
+
+   D3Q27VelocityBCAdapter(const std::string& vx1Function, const double& vx1StartTime, const double& vx1EndTime,
+                          const std::string& vx2Function, const double& vx2StartTime, const double& vx2EndTime,
+                          const std::string& vx3Function, const double& vx3StartTime, const double& vx3EndTime ); 
+
+   //methods
+   void setTimePeriodic()    { (this->type |=   TIMEPERIODIC); }
+   void unsetTimePeriodic()  { (this->type &=  ~TIMEPERIODIC); }
+   bool isTimePeriodic()     { return ((this->type & TIMEPERIODIC) ==  TIMEPERIODIC); }
+
+   //folgendes ist fuer moving objects gedadacht... 
+   void setNewVelocities(const double& vx1, const double& vx1StartTime, const double& vx1EndTime,
+                         const double& vx2, const double& vx2StartTime, const double& vx2EndTime,
+                         const double& vx3, const double& vx3StartTime, const double& vx3EndTime);
+
+      
+   //------------- implements D3Q27BoundaryConditionAdapter ----- start
+   std::string toString();
+   
+   void init(const D3Q27Interactor* const& interactor, const double& time=0);
+   void update(const D3Q27Interactor* const& interactor, const double& time=0);
+
+   void adaptBCForDirection( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& q, const int& fdirection, const double& time=0 );
+   void adaptBC( const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& time=0 );
+
+   //------------- implements D3Q27BoundaryConditionAdapter ----- end
+
+   UbTupleDouble3 getVelocity(const double& x1, const double& x2, const double& x3, const double& timeStep) const;
+
+
+protected:
+   void init();
+   void init(std::vector<D3Q27BCFunction>& vxBCs);
+
+   //time dependency wird automatisch ueber D3Q27BCFunction Intervalle ermittelt!
+   void setTimeDependent()   { (this->type |=   TIMEDEPENDENT); }
+   void unsetTimeDependent() { (this->type &=  ~TIMEDEPENDENT); }
+
+   void clear() { vx1BCs.clear(); vx2BCs.clear();  vx3BCs.clear(); this->init(); }
+   void setNodeVelocity(const D3Q27Interactor& interactor, D3Q27BoundaryConditionPtr bc, const double& worldX1, const double& worldX2, const double& worldX3, const double& timestep);
+
+private:
+   mutable mu::value_type x1, x2, x3;
+   mutable mu::value_type timeStep;
+
+   mu::Parser* tmpVx1Function;
+   mu::Parser* tmpVx2Function;
+   mu::Parser* tmpVx3Function;
+
+   std::vector<D3Q27BCFunction> vx1BCs;
+   std::vector<D3Q27BCFunction> vx2BCs;
+   std::vector<D3Q27BCFunction> vx3BCs;
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<D3Q27BoundaryConditionAdapter>(*this);
+   }
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/BoundaryCondition/EqDensityBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/EqDensityBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d50f776c027f78a83a5109e74ced559e94c363f8
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/EqDensityBoundaryCondition.cpp
@@ -0,0 +1,53 @@
+#include "EqDensityBoundaryCondition.h"
+#include <boost/pointer_cast.hpp>
+
+EqDensityBoundaryCondition::EqDensityBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::Density;
+   BoundaryCondition::preCollision = false;
+}
+//////////////////////////////////////////////////////////////////////////
+EqDensityBoundaryCondition::~EqDensityBoundaryCondition()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr EqDensityBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new EqDensityBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void EqDensityBoundaryCondition::applyBC()
+{
+   LBMReal f[D3Q27System::ENDF+1];
+
+   distributions->getDistributionInv(f, x1, x2, x3);
+   int nx1 = x1;
+   int nx2 = x2;
+   int nx3 = x3;
+   int direction = -1;
+
+   //flag points in direction of fluid
+   if (bcPtr->hasDensityBoundaryFlag(D3Q27System::E)) { nx1 -= 1; direction = D3Q27System::E; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::W)) { nx1 += 1; direction = D3Q27System::W; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::N)) { nx2 -= 1; direction = D3Q27System::N; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::S)) { nx2 += 1; direction = D3Q27System::S; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::T)) { nx3 -= 1; direction = D3Q27System::T; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::B)) { nx3 += 1; direction = D3Q27System::B; }
+   else UB_THROW(UbException(UB_EXARGS, "Danger...no orthogonal BC-Flag on density boundary..."));
+
+   LBMReal rho, vx1, vx2, vx3;
+   calcMacrosFct(f, rho, vx1, vx2, vx3);
+   LBMReal rhoBC = bcPtr->getBoundaryDensity();
+   for (int fdir = D3Q27System::STARTF; fdir<=D3Q27System::ENDF; fdir++)
+   {
+      if (bcPtr->hasDensityBoundaryFlag(fdir))
+      {
+         //Ehsan: 15.2.2013:
+         LBMReal ftemp = calcFeqsForDirFct(fdir, rhoBC, vx1, vx2, vx3);
+         distributions->setDistributionForDirection(ftemp, nx1, nx2, nx3, fdir);
+      }
+   }
+
+}
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/EqDensityBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/EqDensityBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..65aaf8a08db7bcc6782c6b7cc3d7276718abbafd
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/EqDensityBoundaryCondition.h
@@ -0,0 +1,25 @@
+#ifndef SimpleDensityBoundaryCondition_h__
+#define SimpleDensityBoundaryCondition_h__
+
+#include "BoundaryCondition.h"
+
+class EqDensityBoundaryCondition;
+typedef boost::shared_ptr<EqDensityBoundaryCondition> SimpleDensityBoundaryConditionPtr;
+
+class EqDensityBoundaryCondition : public BoundaryCondition
+{
+public:
+   EqDensityBoundaryCondition();
+   ~EqDensityBoundaryCondition();
+   BoundaryConditionPtr clone();
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+#endif // SimpleDensityBoundaryCondition_h__
diff --git a/source/VirtualFluidsCore/BoundaryCondition/HighViscosityNoSlipBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/HighViscosityNoSlipBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad0b265d2909abf43ab1ee16299a2798007ed607
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/HighViscosityNoSlipBoundaryCondition.cpp
@@ -0,0 +1,40 @@
+#include "HighViscosityNoSlipBoundaryCondition.h"
+
+HighViscosityNoSlipBoundaryCondition::HighViscosityNoSlipBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::NoSlip;
+   BoundaryCondition::preCollision = true;
+}
+//////////////////////////////////////////////////////////////////////////
+HighViscosityNoSlipBoundaryCondition::~HighViscosityNoSlipBoundaryCondition()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr HighViscosityNoSlipBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new HighViscosityNoSlipBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void HighViscosityNoSlipBoundaryCondition::applyBC()
+{
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal feq[D3Q27System::ENDF+1];
+   distributions->getDistribution(f, x1, x2, x3);
+   LBMReal rho, vx1, vx2, vx3;
+   calcMacrosFct(f, rho, vx1, vx2, vx3);
+   calcFeqFct(feq, rho, vx1, vx2, vx3);
+
+   for (int fDir = D3Q27System::FSTARTDIR; fDir<=D3Q27System::FENDDIR; fDir++)
+   {
+      if (bcPtr->hasNoSlipBoundaryFlag(fDir))
+      {
+         //quadratic bounce back
+         const int invDir = D3Q27System::INVDIR[fDir];
+         LBMReal q = bcPtr->getQ(invDir);
+         LBMReal fReturn = (f[invDir]+q*f[fDir]+q*collFactor*(feq[invDir]-f[invDir]+feq[fDir]-f[fDir]))/(1.0+q);
+         distributions->setDistributionInvForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], invDir);
+      }
+   }
+}
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/HighViscosityNoSlipBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/HighViscosityNoSlipBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..4df602a09bcec3bd5a65a0dd58cf49c90d55e248
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/HighViscosityNoSlipBoundaryCondition.h
@@ -0,0 +1,26 @@
+#ifndef HighViscosityNoSlipBoundaryCondition_h__
+#define HighViscosityNoSlipBoundaryCondition_h__
+
+#include "BoundaryCondition.h"
+
+class NoSlipBoundaryCondition;
+typedef boost::shared_ptr<NoSlipBoundaryCondition> NoSlipBoundaryConditionPtr;
+
+class HighViscosityNoSlipBoundaryCondition : public BoundaryCondition
+{
+public:
+   HighViscosityNoSlipBoundaryCondition();
+   ~HighViscosityNoSlipBoundaryCondition();
+   BoundaryConditionPtr clone();
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+#endif // HighViscosityNoSlipBoundaryCondition_h__
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/NoSlipBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/NoSlipBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5634cfad2909c15a06a661c1657b9ea27f4af782
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/NoSlipBoundaryCondition.cpp
@@ -0,0 +1,40 @@
+#include "NoSlipBoundaryCondition.h"
+
+NoSlipBoundaryCondition::NoSlipBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::NoSlip;
+   BoundaryCondition::preCollision = false;
+}
+//////////////////////////////////////////////////////////////////////////
+NoSlipBoundaryCondition::~NoSlipBoundaryCondition()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr NoSlipBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new NoSlipBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void NoSlipBoundaryCondition::applyBC()
+{
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal feq[D3Q27System::ENDF+1];
+   distributions->getDistributionInv(f, x1, x2, x3);
+   LBMReal rho, vx1, vx2, vx3;
+   calcMacrosFct(f, rho, vx1, vx2, vx3);
+   calcFeqFct(feq, rho, vx1, vx2, vx3);
+
+   for (int fdir = D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+   {
+      if (bcPtr->hasNoSlipBoundaryFlag(fdir))
+      {
+         //quadratic bounce back
+         const int invDir = D3Q27System::INVDIR[fdir];
+         LBMReal q = bcPtr->getQ(invDir);
+         LBMReal fReturn = ((1.0-q)/(1.0+q))*((f[invDir]-feq[invDir])/(1.0-collFactor)+feq[invDir])+((q/(1.0+q))*(f[invDir]+f[fdir]));
+         distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/BoundaryCondition/NoSlipBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/NoSlipBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..299e6807e5bf84a3fb30c57fa94e9504a66affa8
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/NoSlipBoundaryCondition.h
@@ -0,0 +1,25 @@
+#ifndef NoSlipBoundaryCondition_h__
+#define NoSlipBoundaryCondition_h__
+
+#include "BoundaryCondition.h"
+
+class NoSlipBoundaryCondition;
+typedef boost::shared_ptr<NoSlipBoundaryCondition> NoSlipBoundaryConditionPtr;
+
+class NoSlipBoundaryCondition : public BoundaryCondition
+{
+public:
+   NoSlipBoundaryCondition();
+   virtual ~NoSlipBoundaryCondition();
+   BoundaryConditionPtr clone();
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+#endif // NoSlipBoundaryCondition_h__
diff --git a/source/VirtualFluidsCore/BoundaryCondition/NonEqDensityBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/NonEqDensityBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..529c2b9bc2a83d8e58474201e0091c9644d81a57
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/NonEqDensityBoundaryCondition.cpp
@@ -0,0 +1,54 @@
+#include "NonEqDensityBoundaryCondition.h"
+#include <boost/pointer_cast.hpp>
+
+NonEqDensityBoundaryCondition::NonEqDensityBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::Density;
+   BoundaryCondition::preCollision = false;
+}
+//////////////////////////////////////////////////////////////////////////
+NonEqDensityBoundaryCondition::~NonEqDensityBoundaryCondition()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr NonEqDensityBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new NonEqDensityBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void NonEqDensityBoundaryCondition::applyBC()
+{
+   LBMReal f[D3Q27System::ENDF+1];
+   distributions->getDistributionInv(f, x1, x2, x3);
+   int nx1 = x1;
+   int nx2 = x2;
+   int nx3 = x3;
+   int direction = -1;
+
+   //flag points in direction of fluid
+   if      (bcPtr->hasDensityBoundaryFlag(D3Q27System::E)) { nx1 -= 1; direction = D3Q27System::E; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::W)) { nx1 += 1; direction = D3Q27System::W; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::N)) { nx2 -= 1; direction = D3Q27System::N; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::S)) { nx2 += 1; direction = D3Q27System::S; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::T)) { nx3 -= 1; direction = D3Q27System::T; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::B)) { nx3 += 1; direction = D3Q27System::B; }
+   else UB_THROW(UbException(UB_EXARGS, "Danger...no orthogonal BC-Flag on density boundary..."));
+
+   LBMReal rho, vx1, vx2, vx3;
+   calcMacrosFct(f, rho, vx1, vx2, vx3);
+   LBMReal rhoBC = bcPtr->getBoundaryDensity();
+   for (int fdir = D3Q27System::STARTF; fdir<=D3Q27System::ENDF; fdir++)
+   {
+      if (bcPtr->hasDensityBoundaryFlag(fdir))
+      {
+         // Martins NEQ ADDON
+         ////original: 15.2.2013:
+         LBMReal ftemp = calcFeqsForDirFct(fdir, rho, vx1, vx2, vx3);
+         ftemp = calcFeqsForDirFct(fdir, rhoBC, vx1, vx2, vx3)+f[fdir]-ftemp;
+         distributions->setDistributionForDirection(ftemp, nx1, nx2, nx3, fdir);
+      }
+   }
+
+}
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/NonEqDensityBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/NonEqDensityBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..59c42480da0837fcdd2b20c89685b26b912b6a7b
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/NonEqDensityBoundaryCondition.h
@@ -0,0 +1,25 @@
+#ifndef DensityNEQBoundaryCondition_h__
+#define DensityNEQBoundaryCondition_h__
+
+#include "BoundaryCondition.h"
+
+class NonEqDensityBoundaryCondition;
+typedef boost::shared_ptr<NonEqDensityBoundaryCondition> DensityBoundaryConditionStrategyPtr;
+
+class NonEqDensityBoundaryCondition : public BoundaryCondition
+{
+public:
+   NonEqDensityBoundaryCondition();
+   ~NonEqDensityBoundaryCondition();
+   BoundaryConditionPtr clone();
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+#endif // DensityNEQBoundaryCondition_h__
diff --git a/source/VirtualFluidsCore/BoundaryCondition/NonReflectingDensityBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/NonReflectingDensityBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff39c53208c36bded85944d30f54f98f08f1ab74
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/NonReflectingDensityBoundaryCondition.cpp
@@ -0,0 +1,187 @@
+#include "NonReflectingDensityBoundaryCondition.h"
+#include <boost/pointer_cast.hpp>
+#include "D3Q27System.h"
+
+NonReflectingDensityBoundaryCondition::NonReflectingDensityBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::Density;
+   BoundaryCondition::preCollision = false;
+}
+//////////////////////////////////////////////////////////////////////////
+NonReflectingDensityBoundaryCondition::~NonReflectingDensityBoundaryCondition()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr NonReflectingDensityBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new NonReflectingDensityBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void NonReflectingDensityBoundaryCondition::applyBC()
+{
+   distributions->swap();
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal ftemp[D3Q27System::ENDF+1];
+   distributions->getDistribution(f, x1, x2, x3);
+   int nx1 = x1;
+   int nx2 = x2;
+   int nx3 = x3;
+   int direction = -1;
+
+   //flag points in direction of fluid
+   if      (bcPtr->hasDensityBoundaryFlag(D3Q27System::E)) { nx1 += 1; direction = D3Q27System::E; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::W)) { nx1 -= 1; direction = D3Q27System::W; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::N)) { nx2 += 1; direction = D3Q27System::N; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::S)) { nx2 -= 1; direction = D3Q27System::S; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::T)) { nx3 += 1; direction = D3Q27System::T; }
+   else if (bcPtr->hasDensityBoundaryFlag(D3Q27System::B)) { nx3 -= 1; direction = D3Q27System::B; }
+   else UB_THROW(UbException(UB_EXARGS, "Danger...no orthogonal BC-Flag on density boundary..."));
+
+   //#ifdef _DEBUG
+   //   if (nx1<0 || nx1>maxX1) UB_THROW(UbException(UB_EXARGS, "nx1<0 || nx1>=lengthX1"));
+   //   if (nx2<0 || nx2>maxX2) UB_THROW(UbException(UB_EXARGS, "nx2<0 || nx2>=lengthX2"));
+   //   if (nx3<0 || nx3>maxX3) UB_THROW(UbException(UB_EXARGS, "nx3<0 || nx3>=lengthX3"));
+   //#endif
+
+   distributions->getDistribution(ftemp, nx1, nx2, nx3);
+   LBMReal rho, vx1, vx2, vx3;
+   calcMacrosFct(f, rho, vx1, vx2, vx3);
+
+   distributions->swap();
+
+   double dim = 0.01;
+
+   switch (direction)
+   {
+   case D3Q27System::E:
+      f[D3Q27System::E] = ftemp[D3Q27System::E] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::E] - rho*dim*D3Q27System::WEIGTH[D3Q27System::E];
+      f[D3Q27System::NE] = ftemp[D3Q27System::NE] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::NE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::NE];
+      f[D3Q27System::SE] = ftemp[D3Q27System::SE] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::SE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::SE];
+      f[D3Q27System::TE] = ftemp[D3Q27System::TE] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TE];
+      f[D3Q27System::BE] = ftemp[D3Q27System::BE] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BE];
+      f[D3Q27System::TNE] = ftemp[D3Q27System::TNE] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TNE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TNE];
+      f[D3Q27System::TSE] = ftemp[D3Q27System::TSE] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TSE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TSE];
+      f[D3Q27System::BNE] = ftemp[D3Q27System::BNE] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BNE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BNE];
+      f[D3Q27System::BSE] = ftemp[D3Q27System::BSE] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BSE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BSE];
+
+      distributions->setDistributionInvForDirection(f[D3Q27System::E], x1, x2, x3, D3Q27System::E);
+      distributions->setDistributionInvForDirection(f[D3Q27System::NE], x1, x2, x3, D3Q27System::NE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::SE], x1, x2, x3, D3Q27System::SE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TE], x1, x2, x3, D3Q27System::TE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BE], x1, x2, x3, D3Q27System::BE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TNE], x1, x2, x3, D3Q27System::TNE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TSE], x1, x2, x3, D3Q27System::TSE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BNE], x1, x2, x3, D3Q27System::BNE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BSE], x1, x2, x3, D3Q27System::BSE);
+      break;
+   case D3Q27System::W:
+      f[D3Q27System::W] = ftemp[D3Q27System::W] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::W] - rho*dim*D3Q27System::WEIGTH[D3Q27System::W];
+      f[D3Q27System::NW] = ftemp[D3Q27System::NW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::NW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::NW];
+      f[D3Q27System::SW] = ftemp[D3Q27System::SW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::SW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::SW];
+      f[D3Q27System::TW] = ftemp[D3Q27System::TW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TW];
+      f[D3Q27System::BW] = ftemp[D3Q27System::BW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BW];
+      f[D3Q27System::TNW] = ftemp[D3Q27System::TNW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TNW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TNW];
+      f[D3Q27System::TSW] = ftemp[D3Q27System::TSW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::TSW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TSW];
+      f[D3Q27System::BNW] = ftemp[D3Q27System::BNW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BNW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BNW];
+      f[D3Q27System::BSW] = ftemp[D3Q27System::BSW] * (one_over_sqrt3 - vx1) + (1.0 - one_over_sqrt3 + vx1)*f[D3Q27System::BSW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BSW];
+
+      distributions->setDistributionInvForDirection(f[D3Q27System::W], x1, x2, x3, D3Q27System::W);
+      distributions->setDistributionInvForDirection(f[D3Q27System::NW], x1, x2, x3, D3Q27System::NW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::SW], x1, x2, x3, D3Q27System::SW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TW], x1, x2, x3, D3Q27System::TW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BW], x1, x2, x3, D3Q27System::BW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TNW], x1, x2, x3, D3Q27System::TNW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TSW], x1, x2, x3, D3Q27System::TSW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BNW], x1, x2, x3, D3Q27System::BNW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BSW], x1, x2, x3, D3Q27System::BSW);
+      break;
+   case D3Q27System::N:
+      f[D3Q27System::N] = ftemp[D3Q27System::N] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::N] - rho*dim*D3Q27System::WEIGTH[D3Q27System::N];
+      f[D3Q27System::NE] = ftemp[D3Q27System::NE] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::NE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::NE];
+      f[D3Q27System::NW] = ftemp[D3Q27System::NW] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::NW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::NW];
+      f[D3Q27System::TN] = ftemp[D3Q27System::TN] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::TN] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TN];
+      f[D3Q27System::BN] = ftemp[D3Q27System::BN] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::BN] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BN];
+      f[D3Q27System::TNE] = ftemp[D3Q27System::TNE] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::TNE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TNE];
+      f[D3Q27System::TNW] = ftemp[D3Q27System::TNW] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::TNW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TNW];
+      f[D3Q27System::BNE] = ftemp[D3Q27System::BNE] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::BNE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BNE];
+      f[D3Q27System::BNW] = ftemp[D3Q27System::BNW] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::BNW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BNW];
+
+      distributions->setDistributionInvForDirection(f[D3Q27System::N], x1, x2, x3, D3Q27System::N);
+      distributions->setDistributionInvForDirection(f[D3Q27System::NE], x1, x2, x3, D3Q27System::NE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::NW], x1, x2, x3, D3Q27System::NW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TN], x1, x2, x3, D3Q27System::TN);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BN], x1, x2, x3, D3Q27System::BN);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TNE], x1, x2, x3, D3Q27System::TNE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TNW], x1, x2, x3, D3Q27System::TNW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BNE], x1, x2, x3, D3Q27System::BNE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BNW], x1, x2, x3, D3Q27System::BNW);
+      break;
+   case D3Q27System::S:
+      f[D3Q27System::S] = ftemp[D3Q27System::S] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::S] - rho*dim*D3Q27System::WEIGTH[D3Q27System::S];
+      f[D3Q27System::SE] = ftemp[D3Q27System::SE] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::SE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::SE];
+      f[D3Q27System::SW] = ftemp[D3Q27System::SW] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::SW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::SW];
+      f[D3Q27System::TS] = ftemp[D3Q27System::TS] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::TS] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TS];
+      f[D3Q27System::BS] = ftemp[D3Q27System::BS] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::BS] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BS];
+      f[D3Q27System::TSE] = ftemp[D3Q27System::TSE] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::TSE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TSE];
+      f[D3Q27System::TSW] = ftemp[D3Q27System::TSW] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::TSW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TSW];
+      f[D3Q27System::BSE] = ftemp[D3Q27System::BSE] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::BSE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BSE];
+      f[D3Q27System::BSW] = ftemp[D3Q27System::BSW] * (one_over_sqrt3 - vx2) + (1.0 - one_over_sqrt3 + vx2)*f[D3Q27System::BSW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BSW];
+
+      distributions->setDistributionInvForDirection(f[D3Q27System::S], x1, x2, x3, D3Q27System::S);
+      distributions->setDistributionInvForDirection(f[D3Q27System::SE], x1, x2, x3, D3Q27System::SE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::SW], x1, x2, x3, D3Q27System::SW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TS], x1, x2, x3, D3Q27System::TS);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BS], x1, x2, x3, D3Q27System::BS);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TSE], x1, x2, x3, D3Q27System::TSE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TSW], x1, x2, x3, D3Q27System::TSW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BSE], x1, x2, x3, D3Q27System::BSE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BSW], x1, x2, x3, D3Q27System::BSW);
+      break;
+   case D3Q27System::T:
+      f[D3Q27System::T] = ftemp[D3Q27System::T] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::T] - rho*dim*D3Q27System::WEIGTH[D3Q27System::T];
+      f[D3Q27System::TE] = ftemp[D3Q27System::TE] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::TE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TE];
+      f[D3Q27System::TW] = ftemp[D3Q27System::TW] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::TW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TW];
+      f[D3Q27System::TN] = ftemp[D3Q27System::TN] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::TN] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TN];
+      f[D3Q27System::TS] = ftemp[D3Q27System::TS] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::TS] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TS];
+      f[D3Q27System::TNE] = ftemp[D3Q27System::TNE] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::TNE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TNE];
+      f[D3Q27System::TNW] = ftemp[D3Q27System::TNW] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::TNW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TNW];
+      f[D3Q27System::TSE] = ftemp[D3Q27System::TSE] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::TSE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TSE];
+      f[D3Q27System::TSW] = ftemp[D3Q27System::TSW] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::TSW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::TSW];
+
+      distributions->setDistributionInvForDirection(f[D3Q27System::T], x1, x2, x3, D3Q27System::T);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TE], x1, x2, x3, D3Q27System::TE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TW], x1, x2, x3, D3Q27System::TW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TN], x1, x2, x3, D3Q27System::TN);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TS], x1, x2, x3, D3Q27System::TS);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TNE], x1, x2, x3, D3Q27System::TNE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TNW], x1, x2, x3, D3Q27System::TNW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TSE], x1, x2, x3, D3Q27System::TSE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::TSW], x1, x2, x3, D3Q27System::TSW);
+      break;
+   case D3Q27System::B:
+      f[D3Q27System::B] = ftemp[D3Q27System::B] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::B] - rho*dim*D3Q27System::WEIGTH[D3Q27System::B];
+      f[D3Q27System::BE] = ftemp[D3Q27System::BE] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::BE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BE];
+      f[D3Q27System::BW] = ftemp[D3Q27System::BW] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::BW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BW];
+      f[D3Q27System::BN] = ftemp[D3Q27System::BN] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::BN] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BN];
+      f[D3Q27System::BS] = ftemp[D3Q27System::BS] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::BS] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BS];
+      f[D3Q27System::BNE] = ftemp[D3Q27System::BNE] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::BNE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BNE];
+      f[D3Q27System::BNW] = ftemp[D3Q27System::BNW] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::BNW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BNW];
+      f[D3Q27System::BSE] = ftemp[D3Q27System::BSE] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::BSE] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BSE];
+      f[D3Q27System::BSW] = ftemp[D3Q27System::BSW] * (one_over_sqrt3 - vx3) + (1.0 - one_over_sqrt3 + vx3)*f[D3Q27System::BSW] - rho*dim*D3Q27System::WEIGTH[D3Q27System::BSW];
+
+      distributions->setDistributionInvForDirection(f[D3Q27System::B], x1, x2, x3, D3Q27System::B);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BE], x1, x2, x3, D3Q27System::BE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BW], x1, x2, x3, D3Q27System::BW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BN], x1, x2, x3, D3Q27System::BN);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BS], x1, x2, x3, D3Q27System::BS);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BNE], x1, x2, x3, D3Q27System::BNE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BNW], x1, x2, x3, D3Q27System::BNW);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BSE], x1, x2, x3, D3Q27System::BSE);
+      distributions->setDistributionInvForDirection(f[D3Q27System::BSW], x1, x2, x3, D3Q27System::BSW);
+      break;
+   default:
+      UB_THROW(UbException(UB_EXARGS, "It isn't implemented non reflecting density boundary for this direction!"));
+   }
+}
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/NonReflectingDensityBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/NonReflectingDensityBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..5fcf412d500b22f1d95477d3588278694024dec1
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/NonReflectingDensityBoundaryCondition.h
@@ -0,0 +1,25 @@
+#ifndef NonReflectingDensityBoundaryCondition_h__
+#define NonReflectingDensityBoundaryCondition_h__
+
+#include "BoundaryCondition.h"
+
+class NonReflectingDensityBoundaryCondition;
+typedef boost::shared_ptr<NonReflectingDensityBoundaryCondition> NonReflectingDensityBoundaryConditionPtr;
+
+class NonReflectingDensityBoundaryCondition : public BoundaryCondition
+{
+public:
+   NonReflectingDensityBoundaryCondition();
+   ~NonReflectingDensityBoundaryCondition();
+   BoundaryConditionPtr clone();
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+#endif // NonReflectingDensityBoundaryCondition_h__
diff --git a/source/VirtualFluidsCore/BoundaryCondition/NonReflectingVelocityBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/NonReflectingVelocityBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..734545f6f7563d43b068fdd20fe794829b46d3d4
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/NonReflectingVelocityBoundaryCondition.cpp
@@ -0,0 +1,42 @@
+#include "NonReflectingVelocityBoundaryCondition.h"
+
+NonReflectingVelocityBoundaryCondition::NonReflectingVelocityBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::Velocity;
+   BoundaryCondition::preCollision = false;
+}
+//////////////////////////////////////////////////////////////////////////
+NonReflectingVelocityBoundaryCondition::~NonReflectingVelocityBoundaryCondition()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr NonReflectingVelocityBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new NonReflectingVelocityBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void NonReflectingVelocityBoundaryCondition::applyBC()
+{
+   //velocity bc for non reflecting pressure bc
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal feq[D3Q27System::ENDF+1];
+   distributions->getDistributionInv(f, x1, x2, x3);
+   LBMReal rho, vx1, vx2, vx3;
+   calcMacrosFct(f, rho, vx1, vx2, vx3);
+   calcFeqFct(feq, rho, vx1, vx2, vx3);
+
+   for (int fdir = D3Q27System::FSTARTDIR; fdir <= D3Q27System::FENDDIR; fdir++)
+   {
+      if (bcPtr->hasVelocityBoundaryFlag(fdir))
+      {
+         const int invDir = D3Q27System::INVDIR[fdir];
+         LBMReal q = 1.0;//bcPtr->getQ(invDir);// m+m q=0 stabiler
+         LBMReal velocity = bcPtr->getBoundaryVelocity(invDir);
+         //LBMReal fReturn = ((1.0-q)/(1.0+q))*((ftemp[invDir]-feq[invDir]*collFactor)/(1.0-collFactor))+((q*(ftemp[invDir]+ftemp[fdir])-velocity)/(1.0+q));
+         LBMReal fReturn = ((1.0 - q) / (1.0 + q))*((f[invDir] - feq[invDir]) / (1.0 - collFactor) + feq[invDir]) + ((q*(f[invDir] + f[fdir]) - velocity) / (1.0 + q))-rho*D3Q27System::WEIGTH[invDir];
+         distributions->setDistributionForDirection(fReturn, x1 + D3Q27System::DX1[invDir], x2 + D3Q27System::DX2[invDir], x3 + D3Q27System::DX3[invDir], fdir);
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/BoundaryCondition/NonReflectingVelocityBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/NonReflectingVelocityBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..cfb00fa20de8f1fecb318f66983cfd3f146319e0
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/NonReflectingVelocityBoundaryCondition.h
@@ -0,0 +1,31 @@
+//!  \file NonReflectingVelocityBoundaryCondition.h
+//!  \brief Class implements velocity bc for non reflecting pressure bc.
+//!  \author Konstantin Kutscher
+
+#ifndef NonReflectingVelocityBoundaryCondition_h__
+#define NonReflectingVelocityBoundaryCondition_h__
+
+#include "BoundaryCondition.h"
+
+class NonReflectingVelocityBoundaryCondition;
+typedef boost::shared_ptr<NonReflectingVelocityBoundaryCondition> NonReflectingVelocityBoundaryConditionPtr;
+
+//!  \brief Class implements velocity boundary condition for non reflecting pressure boundary condition
+
+class NonReflectingVelocityBoundaryCondition : public BoundaryCondition
+{
+public:
+   NonReflectingVelocityBoundaryCondition();
+   ~NonReflectingVelocityBoundaryCondition();
+   BoundaryConditionPtr clone();
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+#endif // NonReflectingVelocityBoundaryCondition_h__
diff --git a/source/VirtualFluidsCore/BoundaryCondition/SlipBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/SlipBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb96544cc9a52ed435903a6302e583e9bdd299f9
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/SlipBoundaryCondition.cpp
@@ -0,0 +1,79 @@
+#include "SlipBoundaryCondition.h"
+
+SlipBoundaryCondition::SlipBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::Slip;
+   BoundaryCondition::preCollision = false;
+}
+//////////////////////////////////////////////////////////////////////////
+SlipBoundaryCondition::~SlipBoundaryCondition()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr SlipBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new SlipBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void SlipBoundaryCondition::applyBC()
+{
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal feq[D3Q27System::ENDF+1];
+   distributions->getDistributionInv(f, x1, x2, x3);
+   LBMReal rho, vx1, vx2, vx3;
+   calcMacrosFct(f, rho, vx1, vx2, vx3);
+   calcFeqFct(feq, rho, vx1, vx2, vx3);
+
+   UbTupleFloat3 normale = bcPtr->getNormalVector();
+   LBMReal amp = vx1*val<1>(normale)+vx2*val<2>(normale)+vx3*val<3>(normale);
+
+   vx1 = vx1 - amp * val<1>(normale); //normale zeigt von struktur weg!
+   vx2 = vx2 - amp * val<2>(normale); //normale zeigt von struktur weg!
+   vx3 = vx3 - amp * val<3>(normale); //normale zeigt von struktur weg!
+
+   for (int fdir = D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+   {
+      if (bcPtr->hasSlipBoundaryFlag(fdir))
+      {
+         //quadratic bounce back
+         const int invDir = D3Q27System::INVDIR[fdir];
+         LBMReal q = 1.0;//bcPtr->getQ(invDir);// m+m q=0 stabiler
+         //vx3=0;
+         LBMReal velocity = 0.0;
+         switch (invDir)
+         {
+         case D3Q27System::E: velocity = (UbMath::c4o9*(+vx1)); break;      //(2/cs^2)(=6)*rho_0(=1 bei imkompr)*wi*u*ei mit cs=1/sqrt(3)
+         case D3Q27System::W: velocity = (UbMath::c4o9*(-vx1)); break;      //z.B. aus paper manfred MRT LB models in three dimensions (2002)   
+         case D3Q27System::N: velocity = (UbMath::c4o9*(+vx2)); break;
+         case D3Q27System::S: velocity = (UbMath::c4o9*(-vx2)); break;
+         case D3Q27System::T: velocity = (UbMath::c4o9*(+vx3)); break;
+         case D3Q27System::B: velocity = (UbMath::c4o9*(-vx3)); break;
+         case D3Q27System::NE: velocity = (UbMath::c1o9*(+vx1+vx2)); break;
+         case D3Q27System::SW: velocity = (UbMath::c1o9*(-vx1-vx2)); break;
+         case D3Q27System::SE: velocity = (UbMath::c1o9*(+vx1-vx2)); break;
+         case D3Q27System::NW: velocity = (UbMath::c1o9*(-vx1+vx2)); break;
+         case D3Q27System::TE: velocity = (UbMath::c1o9*(+vx1             +vx3)); break;
+         case D3Q27System::BW: velocity = (UbMath::c1o9*(-vx1             -vx3)); break;
+         case D3Q27System::BE: velocity = (UbMath::c1o9*(+vx1             -vx3)); break;
+         case D3Q27System::TW: velocity = (UbMath::c1o9*(-vx1             +vx3)); break;
+         case D3Q27System::TN: velocity = (UbMath::c1o9*(+vx2+vx3)); break;
+         case D3Q27System::BS: velocity = (UbMath::c1o9*(-vx2-vx3)); break;
+         case D3Q27System::BN: velocity = (UbMath::c1o9*(+vx2-vx3)); break;
+         case D3Q27System::TS: velocity = (UbMath::c1o9*(-vx2+vx3)); break;
+         case D3Q27System::TNE: velocity = (UbMath::c1o36*(+vx1+vx2+vx3)); break;
+         case D3Q27System::BSW: velocity = (UbMath::c1o36*(-vx1-vx2-vx3)); break;
+         case D3Q27System::BNE: velocity = (UbMath::c1o36*(+vx1+vx2-vx3)); break;
+         case D3Q27System::TSW: velocity = (UbMath::c1o36*(-vx1-vx2+vx3)); break;
+         case D3Q27System::TSE: velocity = (UbMath::c1o36*(+vx1-vx2+vx3)); break;
+         case D3Q27System::BNW: velocity = (UbMath::c1o36*(-vx1+vx2-vx3)); break;
+         case D3Q27System::BSE: velocity = (UbMath::c1o36*(+vx1-vx2-vx3)); break;
+         case D3Q27System::TNW: velocity = (UbMath::c1o36*(-vx1+vx2+vx3)); break;
+         default: throw UbException(UB_EXARGS, "unknown error");
+         }
+         LBMReal fReturn = ((1.0-q)/(1.0+q))*((f[invDir]-feq[invDir])/(1.0-collFactor)+feq[invDir])+((q*(f[invDir]+f[fdir])-velocity)/(1.0+q));
+         distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+      }
+   }
+}
\ No newline at end of file
diff --git a/source/VirtualFluidsCore/BoundaryCondition/SlipBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/SlipBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2a5b333bf2a2d7cbf87aeb10b9166ed43601d64
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/SlipBoundaryCondition.h
@@ -0,0 +1,25 @@
+#ifndef SlipBoundaryCondition_h__
+#define SlipBoundaryCondition_h__
+
+#include "BoundaryCondition.h"
+
+class SlipBoundaryCondition;
+typedef boost::shared_ptr<SlipBoundaryCondition> SlipBoundaryConditionPtr;
+
+class SlipBoundaryCondition : public BoundaryCondition
+{
+public:
+   SlipBoundaryCondition();
+   virtual ~SlipBoundaryCondition();
+   BoundaryConditionPtr clone();
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+#endif // SlipBoundaryCondition_h__
diff --git a/source/VirtualFluidsCore/BoundaryCondition/ThinWallNoSlipBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/ThinWallNoSlipBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..21e07bf8a2ff59b1422c7871055b63267a62609d
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/ThinWallNoSlipBoundaryCondition.cpp
@@ -0,0 +1,44 @@
+#include "ThinWallNoSlipBoundaryCondition.h"
+
+#include "D3Q27EsoTwist3DSplittedVector.h"
+
+
+ThinWallNoSlipBoundaryCondition::ThinWallNoSlipBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::NoSlip;
+   BoundaryCondition::preCollision = false;
+}
+//////////////////////////////////////////////////////////////////////////
+ThinWallNoSlipBoundaryCondition::~ThinWallNoSlipBoundaryCondition()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr ThinWallNoSlipBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new ThinWallNoSlipBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void ThinWallNoSlipBoundaryCondition::applyBC()
+{
+   LBMReal fReturn;
+
+   for (int fdir = D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+   {
+      if (bcPtr->hasNoSlipBoundaryFlag(fdir))
+      {
+         //quadratic bounce back with for thin walls
+         const int invDir = D3Q27System::INVDIR[fdir];
+         fReturn = distributionsTemp->getDistributionInvForDirection(x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+         distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void ThinWallNoSlipBoundaryCondition::addDistributions(EsoTwist3DPtr distributions)
+{
+   this->distributions = distributions;
+   distributionsTemp = EsoTwist3DPtr(new D3Q27EsoTwist3DSplittedVector(distributions->getNX1(), distributions->getNX2(), distributions->getNX3(), -999.0));
+}
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/ThinWallNoSlipBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/ThinWallNoSlipBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4d49b751db941871c69d4531e1ac44898c5f168
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/ThinWallNoSlipBoundaryCondition.h
@@ -0,0 +1,26 @@
+#ifndef ThinWallNoSlipBoundaryCondition_h__
+#define ThinWallNoSlipBoundaryCondition_h__
+
+#include "NoSlipBoundaryCondition.h"
+
+class ThinWallNoSlipBoundaryCondition;
+typedef boost::shared_ptr<ThinWallNoSlipBoundaryCondition> ThinWallNoSlipBoundaryConditionPtr;
+
+class ThinWallNoSlipBoundaryCondition : public NoSlipBoundaryCondition
+{
+public:
+   ThinWallNoSlipBoundaryCondition();
+   virtual ~ThinWallNoSlipBoundaryCondition();
+   BoundaryConditionPtr clone();
+   void addDistributions(EsoTwist3DPtr distributions);
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+#endif // ThinWallNoSlipBoundaryCondition_h__
diff --git a/source/VirtualFluidsCore/BoundaryCondition/VelocityBoundaryCondition.cpp b/source/VirtualFluidsCore/BoundaryCondition/VelocityBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb04d2f3effdd009df00efbfa03174bb2c80c29d
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/VelocityBoundaryCondition.cpp
@@ -0,0 +1,42 @@
+#include "VelocityBoundaryCondition.h"
+#include <boost/pointer_cast.hpp>
+
+VelocityBoundaryCondition::VelocityBoundaryCondition()
+{
+   BoundaryCondition::type = BoundaryCondition::Velocity;
+   BoundaryCondition::preCollision = false;
+}
+//////////////////////////////////////////////////////////////////////////
+VelocityBoundaryCondition::~VelocityBoundaryCondition()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionPtr VelocityBoundaryCondition::clone()
+{
+   BoundaryConditionPtr bc(new VelocityBoundaryCondition());
+   return bc;
+}
+//////////////////////////////////////////////////////////////////////////
+void VelocityBoundaryCondition::applyBC()
+{
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal feq[D3Q27System::ENDF+1];
+   distributions->getDistributionInv(f, x1, x2, x3);
+   LBMReal rho, vx1, vx2, vx3;
+   calcMacrosFct(f, rho, vx1, vx2, vx3);
+   calcFeqFct(feq, rho, vx1, vx2, vx3);
+
+   for (int fdir = D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+   {
+      if (bcPtr->hasVelocityBoundaryFlag(fdir))
+      {
+         const int invDir = D3Q27System::INVDIR[fdir];
+         LBMReal q = bcPtr->getQ(invDir);// m+m q=0 stabiler
+         LBMReal velocity = bcPtr->getBoundaryVelocity(invDir);
+         LBMReal fReturn = ((1.0-q)/(1.0+q))*((f[invDir]-feq[invDir])/(1.0-collFactor)+feq[invDir])+((q*(f[invDir]+f[fdir])-velocity)/(1.0+q));
+         distributions->setDistributionForDirection(fReturn, x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+      }
+   }
+
+}
+
diff --git a/source/VirtualFluidsCore/BoundaryCondition/VelocityBoundaryCondition.h b/source/VirtualFluidsCore/BoundaryCondition/VelocityBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..84517254808c7e870275fc1599bdbbec3d8b345f
--- /dev/null
+++ b/source/VirtualFluidsCore/BoundaryCondition/VelocityBoundaryCondition.h
@@ -0,0 +1,27 @@
+#ifndef VelocityBoundaryCondition_h__
+#define VelocityBoundaryCondition_h__
+
+#include "BoundaryCondition.h"
+
+class VelocityBoundaryCondition;
+typedef boost::shared_ptr<VelocityBoundaryCondition> VelocityBoundaryConditionPtr;
+
+class VelocityBoundaryCondition : public BoundaryCondition
+{
+public:
+   VelocityBoundaryCondition();
+   ~VelocityBoundaryCondition();
+   BoundaryConditionPtr clone();
+protected:
+   void applyBC();
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<BoundaryCondition>(*this);
+   }
+};
+
+#endif // VelocityBoundaryCondition_h__
+
diff --git a/source/VirtualFluidsCore/CMakeLists.txt b/source/VirtualFluidsCore/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a2afff40eabbb65ac17573c33925a87f3f51ff87
--- /dev/null
+++ b/source/VirtualFluidsCore/CMakeLists.txt
@@ -0,0 +1,108 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+########################################################
+## C++ PROJECT                                       ###
+########################################################
+PROJECT(VirtualFluids)
+  
+#################################################################
+###   PACKAGES						                        ###
+#################################################################
+SET(WITH_SUBFOLDERS_FOR_SG TRUE)
+#old VirtualFluids
+INCLUDE(${SOURCE_ROOT}/ThirdParty/MuParser/CMakePackage.txt)
+#INCLUDE(${SOURCE_ROOT}/ThirdParty/MarchingCubes/CMakePackage.txt)
+#INCLUDE(${SOURCE_ROOT}/ThirdParty/Basics/objects/CMakePackage.txt)
+# INCLUDE(${SOURCE_ROOT}/ThirdParty/Basics/utilities/CMakePackage.txt)
+# #INCLUDE(${SOURCE_ROOT}/ThirdParty/Basics/memory/CMakePackage.txt)
+# INCLUDE(${SOURCE_ROOT}/ThirdParty/Basics/container/CMakePackage.txt)
+# INCLUDE(${SOURCE_ROOT}/ThirdParty/Basics/writer/CMakePackage.txt)
+# #INCLUDE(${SOURCE_ROOT}/ThirdParty/Basics/parallel/CMakePackage.txt)
+# INCLUDE(${SOURCE_ROOT}/ThirdParty/Basics/transmitter/CMakePackage.txt)
+
+#new VirtualFluids
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/BoundaryCondition/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Connectors/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Data/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Interactors/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/LBM/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Parallel/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Grid/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Visitors/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/CoProcessors/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/Utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/numerics/geometry3d/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/numerics/geometry3d/creator/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/numerics/geometry3d/KdTree/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/basics/objects/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/basics/memory/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/basics/container/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/basics/writer/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/ThirdParty/Library/basics/transmitter/CMakePackage.txt)
+
+#FETOL
+IF(${USE_FETOL})
+INCLUDE(${SOURCE_ROOT}/VirtualFluidsCore/FETOL/CMakePackage.txt)
+ENDIF()
+
+INCLUDE(${SOURCE_ROOT}/IncludsList.cmake)
+
+SET(CAB_ADDITIONAL_LINK_LIBRARIES muParserLib ${Boost_LIBRARIES} ${MPI_LIBRARY})
+
+IF(${USE_GCC})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} rt)
+ENDIF()
+
+IF(${USE_INTEL})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} irc)
+ENDIF()
+
+IF(${USE_ZOLTAN})
+   INCLUDE_DIRECTORIES(${ZOLTAN_INCLUDEDIR})
+   SET(LINK_LIBRARY optimized ${ZOLTAN_RELEASE_LIBRARY} debug ${ZOLTAN_DEBUG_LIBRARY})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+ENDIF()
+
+IF(${USE_METIS})
+   SET(LINK_LIBRARY optimized ${METIS_RELEASE_LIBRARY} debug ${METIS_DEBUG_LIBRARY})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+ENDIF()
+
+IF(${USE_VTK})
+   SET(LINK_LIBRARY optimized ${VTK_LIBRARIES} debug ${VTK_LIBRARIES})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+ENDIF()
+
+IF(${USE_CATALYST})
+   SET(LINK_LIBRARY optimized vtkPVPythonCatalyst debug vtkPVPythonCatalyst )
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+   SET(LINK_LIBRARY optimized vtkParallelMPI debug vtkParallelMPI )
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+ENDIF()
+
+
+IF(${USE_PYTHON})
+   SET(LINK_LIBRARY optimized ${PYTHON_LIBRARY} debug ${PYTHON_LIBRARY})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+ENDIF()
+
+IF(${USE_FETOL})
+   SET(LINK_LIBRARY optimized ${BOND_RELEASE_LIBRARY} debug ${BOND_DEBUG_LIBRARY})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+
+   SET(LINK_LIBRARY optimized ${JAVA_JVM_LIBRARY} debug ${JAVA_JVM_LIBRARY})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+   
+   SET(LINK_LIBRARY optimized ${YAML_RELEASE_LIBRARY} debug ${YAML_DEBUG_LIBRARY})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+   
+   SET(LINK_LIBRARY optimized ${FETOL_RELEASE_LIBRARY} debug ${FETOL_DEBUG_LIBRARY})
+   SET(CAB_ADDITIONAL_LINK_LIBRARIES ${CAB_ADDITIONAL_LINK_LIBRARIES} ${LINK_LIBRARY})
+ENDIF()
+
+message("CAB_ADDITIONAL_LINK_LIBRARIES: " ${CAB_ADDITIONAL_LINK_LIBRARIES})
+#################################################################
+###   CREATE PROJECT                                          ###
+#################################################################
+CREATE_CAB_PROJECT(VirtualFluids STATIC)
diff --git a/source/VirtualFluidsCore/CoProcessors/AverageValuesPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/AverageValuesPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ebbbc484c052fda099675edae7d58efd6881646
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/AverageValuesPostprocessor.cpp
@@ -0,0 +1,570 @@
+#include "AverageValuesPostprocessor.h"
+#include "LBMKernel3D.h"
+#include "SimulationParameters.h"
+#include "D3Q27ETBCProcessor.h"
+#include <vector>
+#include <sstream>
+#include <string>
+#include <iostream>
+#include <boost/foreach.hpp>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/utilities/UbMath.h"
+
+using namespace std;
+
+AverageValuesPostprocessor::AverageValuesPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+AverageValuesPostprocessor::AverageValuesPostprocessor(Grid3DPtr grid, const std::string& path,	WbWriter* const writer, 
+   UbSchedulerPtr s, UbSchedulerPtr Avs, UbSchedulerPtr rsMeans, UbSchedulerPtr rsRMS, bool restart)
+	                                                   : Postprocessor(grid, s),
+	                                                   averageScheduler(Avs),
+	                                                   resetSchedulerMeans(rsMeans),
+	                                                   resetSchedulerRMS(rsRMS),
+	                                                   path(path),
+	                                                   writer(writer)
+{
+   resetStepMeans = (int)rsMeans->getMinBegin();
+   resetStepRMS = (int)rsRMS->getMinBegin();
+   averageInterval = (double)Avs->getMinStep();
+
+   gridRank  = grid->getRank();
+   minInitLevel = this->grid->getCoarsestInitializedLevel();
+   maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   blockVector.resize(maxInitLevel+1);
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+      
+      if (blockVector[level].size() > 0)
+         compressible = blockVector[level][0]->getKernel()->getCompressible();
+
+      if (!restart)
+      {
+         BOOST_FOREACH(Block3DPtr block, blockVector[level])
+         {
+            UbTupleInt3 nx = grid->getBlockNX();
+            AverageValuesArray3DPtr averageValues = AverageValuesArray3DPtr(new AverageValuesArray3D(11, val<1>(nx)+1, val<2>(nx)+1, val<3>(nx)+1, 0.0));
+            block->getKernel()->getDataSet()->setAverageValues(averageValues);
+         }
+      }
+   }
+
+   // for musis special use
+	//initPlotDataZ(0.0);
+	//restartStep = 0.0;
+}
+//////////////////////////////////////////////////////////////////////////
+void AverageValuesPostprocessor::update(double step)
+{
+	//resetRMS(step);
+	if(resetSchedulerRMS->isDue(step) )
+		resetPostprocessDataRMS(step);
+
+	//reset(step);
+	if(resetSchedulerMeans->isDue(step) )
+		resetPostprocessDataMeans(step);
+
+	if(averageScheduler->isDue(step) ){
+		calculateAverageValues(step);
+			// for musis special use
+			//collectPlotDataZ(step);
+	}
+	if(scheduler->isDue(step) ){
+			collectPostprocessData(step);
+
+		}
+
+		UBLOG(logDEBUG3, "AverageValuesPostprocessor::update:" << step);
+}
+
+void AverageValuesPostprocessor::resetPostprocessDataRMS(double step)
+{
+	resetStepRMS=(int)step;
+
+	for(int level = minInitLevel; level<=maxInitLevel;level++)
+	{
+		BOOST_FOREACH(Block3DPtr block, blockVector[level])
+		{
+			if (block)
+			{
+				LBMKernel3DPtr kernel = block->getKernel();
+				BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+				DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+				AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageValues();
+
+				int minX1 = 0;
+				int minX2 = 0;
+				int minX3 = 0;
+
+				int maxX1 = int(distributions->getNX1());
+				int maxX2 = int(distributions->getNX2());
+				int maxX3 = int(distributions->getNX3());
+
+				for(int ix3=minX3; ix3<maxX3-1; ix3++)
+				{
+					for(int ix2=minX2; ix2<maxX2-1; ix2++)
+					{
+						for(int ix1=minX1; ix1<maxX1-1; ix1++)
+						{
+							if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+							{
+								//////////////////////////////////////////////////////////////////////////
+								//compute average values
+								//////////////////////////////////////////////////////////////////////////
+								(*av)(AvVxx,ix1,ix2,ix3) = 0.0;
+								(*av)(AvVyy,ix1,ix2,ix3) = 0.0;
+								(*av)(AvVzz,ix1,ix2,ix3) = 0.0;
+                        (*av)(AvVxy,ix1,ix2,ix3) = 0.0;
+                        (*av)(AvVxz,ix1,ix2,ix3) = 0.0;
+                        (*av)(AvVyz,ix1,ix2,ix3) = 0.0;
+                        (*av)(AvPrms,ix1,ix2,ix3) = 0.0;
+								//////////////////////////////////////////////////////////////////////////
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+void AverageValuesPostprocessor::resetPostprocessDataMeans(double step)
+{
+	resetStepMeans=(int)step;
+
+	for(int level = minInitLevel; level<=maxInitLevel;level++)
+	{
+		BOOST_FOREACH(Block3DPtr block, blockVector[level])
+		{
+			if (block)
+			{
+				LBMKernel3DPtr kernel = block->getKernel();
+				BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+				DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+				AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageValues();
+
+				int minX1 = 0;
+				int minX2 = 0;
+				int minX3 = 0;
+
+				int maxX1 = int(distributions->getNX1());
+				int maxX2 = int(distributions->getNX2());
+				int maxX3 = int(distributions->getNX3());
+
+				for(int ix3=minX3; ix3<maxX3-1; ix3++)
+				{
+					for(int ix2=minX2; ix2<maxX2-1; ix2++)
+					{
+						for(int ix1=minX1; ix1<maxX1-1; ix1++)
+						{
+							if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+							{
+								//////////////////////////////////////////////////////////////////////////
+								//compute average values
+								//////////////////////////////////////////////////////////////////////////
+								(*av)(AvVx,ix1,ix2,ix3) = 0.0;
+								(*av)(AvVy,ix1,ix2,ix3) = 0.0;
+								(*av)(AvVz,ix1,ix2,ix3) = 0.0;
+                        (*av)(AvP,ix1,ix2,ix3) = 0.0;
+								//////////////////////////////////////////////////////////////////////////
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+void AverageValuesPostprocessor::collectPostprocessData(double step)
+{
+	int istep = int(step);
+
+	for(int level = minInitLevel; level<=maxInitLevel;level++)
+	{
+		BOOST_FOREACH(Block3DPtr block, blockVector[level])
+		{
+			if (block)
+			{
+				addPostprocessData(block);
+			}
+		}
+	}
+
+   string pfilePath, partPath, subfolder, cfilePath;
+   subfolder = "av"+UbSystem::toString(istep);
+   pfilePath =  path+"/av/"+subfolder;
+   cfilePath =  path+"/av/av_collection";
+   partPath = pfilePath+"/av"+UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep);
+
+   string partName = writer->writeOctsWithNodeData(partPath,nodes,cells,datanames,data);
+   size_t found=partName.find_last_of("/");
+   string piece = partName.substr(found+1);
+   piece = subfolder + "/" + piece;
+
+   vector<string> cellDataNames;
+   CommunicatorPtr comm = Communicator::getInstance();
+   vector<string> pieces = comm->gather(piece);
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(pfilePath,pieces,datanames,cellDataNames);
+      found=pname.find_last_of("/");
+      piece = pname.substr(found+1);
+
+      vector<string> filenames;
+      filenames.push_back(piece);
+      if (step == Postprocessor::scheduler->getMinBegin())
+      {
+         WbWriterVtkXmlASCII::getInstance()->writeCollection(cfilePath,filenames,istep,false);
+      } 
+      else
+      {
+         WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(cfilePath,filenames,istep,false);
+      }
+      UBLOG(logINFO,"AverageValuesPostprocessor step: " << istep);
+   }
+
+	clearData();
+}
+//////////////////////////////////////////////////////////////////////////
+void AverageValuesPostprocessor::clearData()
+{
+	nodes.clear();
+	cells.clear();
+	datanames.clear();
+	data.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+void AverageValuesPostprocessor::addPostprocessData(const Block3DPtr block)
+{
+	UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+	UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+	UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+	double         dx           = grid->getDeltaX(block);
+
+	//Diese Daten werden geschrieben:
+	datanames.resize(0);
+	datanames.push_back("AvVx");
+   datanames.push_back("AvVy");
+   datanames.push_back("AvVz");
+	datanames.push_back("AvVxx");
+	datanames.push_back("AvVyy");
+	datanames.push_back("AvVzz");
+   datanames.push_back("AvVxy");
+   datanames.push_back("AvVxz");
+   datanames.push_back("AvVyz");
+   datanames.push_back("AvP");
+   datanames.push_back("AvPrms");
+
+
+	data.resize(datanames.size());
+
+	LBMKernel3DPtr kernel = block->getKernel();
+	BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+	DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+	AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageValues();
+	//int ghostLayerWidth = kernel->getGhostLayerWidth();
+
+	//knotennummerierung faengt immer bei 0 an!
+	int SWB,SEB,NEB,NWB,SWT,SET,NET,NWT;
+
+	int minX1 = 0;
+	int minX2 = 0;
+	int minX3 = 0;
+
+	int maxX1 = int(distributions->getNX1());
+	int maxX2 = int(distributions->getNX2());
+	int maxX3 = int(distributions->getNX3());
+
+	//nummern vergeben und node vector erstellen + daten sammeln
+	CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3,-1);
+
+	maxX1 -= 2;
+	maxX2 -= 2;
+	maxX3 -= 2;
+
+	//D3Q27BoundaryConditionPtr bcPtr;
+
+	int nr = (int)nodes.size();
+
+	for(int ix3=minX3; ix3<=maxX3; ix3++)
+	{
+		for(int ix2=minX2; ix2<=maxX2; ix2++)
+		{
+			for(int ix1=minX1; ix1<=maxX1; ix1++)
+			{
+				if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+				{
+					int index = 0;
+					nodeNumbers(ix1,ix2,ix3) = nr++;
+					nodes.push_back( makeUbTuple(float(val<1>(org) - val<1>(nodeOffset) + ix1*dx),
+						float(val<2>(org) - val<2>(nodeOffset) + ix2*dx),
+						float(val<3>(org) - val<3>(nodeOffset) + ix3*dx)) );
+
+					LBMReal vx=(*av)(AvVx,ix1,ix2,ix3);
+					LBMReal vy=(*av)(AvVy,ix1,ix2,ix3);
+					LBMReal vz=(*av)(AvVz,ix1,ix2,ix3);
+               
+               LBMReal vxx=(*av)(AvVxx,ix1,ix2,ix3);
+               LBMReal vyy=(*av)(AvVyy,ix1,ix2,ix3);
+               LBMReal vzz=(*av)(AvVzz,ix1,ix2,ix3);
+               
+               LBMReal vxy=(*av)(AvVxy,ix1,ix2,ix3);
+               LBMReal vxz=(*av)(AvVxz,ix1,ix2,ix3);
+               LBMReal vyz=(*av)(AvVyz,ix1,ix2,ix3);
+
+               LBMReal vp=(*av)(AvP,ix1,ix2,ix3);
+               LBMReal vprms=(*av)(AvPrms,ix1,ix2,ix3);
+ 
+					
+					data[index++].push_back(vx);
+               data[index++].push_back(vy);
+               data[index++].push_back(vz);
+
+					data[index++].push_back(vxx);
+					data[index++].push_back(vyy);
+					data[index++].push_back(vzz);
+
+               data[index++].push_back(vxy);
+               data[index++].push_back(vxz);
+               data[index++].push_back(vyz);
+
+               data[index++].push_back(vp);
+               data[index++].push_back(vprms);
+				}
+			}
+		}
+	}
+
+	maxX1 -= 1;
+	maxX2 -= 1;
+	maxX3 -= 1;
+
+	//cell vector erstellen
+	for(int ix3=minX3; ix3<=maxX3; ix3++)
+	{
+		for(int ix2=minX2; ix2<=maxX2; ix2++)
+		{
+			for(int ix1=minX1; ix1<=maxX1; ix1++)
+			{
+				if(   (SWB=nodeNumbers( ix1  , ix2,   ix3   )) >= 0
+					&& (SEB=nodeNumbers( ix1+1, ix2,   ix3   )) >= 0
+					&& (NEB=nodeNumbers( ix1+1, ix2+1, ix3   )) >= 0
+					&& (NWB=nodeNumbers( ix1  , ix2+1, ix3   )) >= 0 
+					&& (SWT=nodeNumbers( ix1  , ix2,   ix3+1 )) >= 0
+					&& (SET=nodeNumbers( ix1+1, ix2,   ix3+1 )) >= 0
+					&& (NET=nodeNumbers( ix1+1, ix2+1, ix3+1 )) >= 0
+					&& (NWT=nodeNumbers( ix1  , ix2+1, ix3+1 )) >= 0                )
+				{
+					cells.push_back( makeUbTuple(SWB,SEB,NEB,NWB,SWT,SET,NET,NWT) );
+				}
+			}
+		}
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+void AverageValuesPostprocessor::calculateAverageValues(double timeStep)
+{
+	using namespace D3Q27System;
+
+   //Funktionszeiger
+   calcMacros = NULL;
+   if (compressible)
+   {
+      calcMacros = &calcCompMacroscopicValues;
+   }
+   else
+   {
+      calcMacros = &calcIncompMacroscopicValues;
+   }
+
+	LBMReal f[27];
+
+	for(int level = minInitLevel; level<=maxInitLevel;level++)
+	{
+		BOOST_FOREACH(Block3DPtr block, blockVector[level])
+		{
+			if (block)
+			{
+				LBMKernel3DPtr kernel = block->getKernel();
+				BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+				DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+				AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageValues();
+
+				int minX1 = 0;
+				int minX2 = 0;
+				int minX3 = 0;
+
+				int maxX1 = int(distributions->getNX1());
+				int maxX2 = int(distributions->getNX2());
+				int maxX3 = int(distributions->getNX3());
+
+				maxX1 -= 2;
+				maxX2 -= 2;
+				maxX3 -= 2;
+
+				for(int ix3=minX3; ix3<=maxX3; ix3++)
+				{
+					for(int ix2=minX2; ix2<=maxX2; ix2++)
+					{
+						for(int ix1=minX1; ix1<=maxX1; ix1++)
+						{
+							if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+							{
+								//////////////////////////////////////////////////////////////////////////
+								//read distribution
+								////////////////////////////////////////////////////////////////////////////
+								distributions->getDistribution(f, ix1, ix2, ix3);
+								//////////////////////////////////////////////////////////////////////////
+								//compute velocity
+								//////////////////////////////////////////////////////////////////////////
+                        LBMReal vx,vy,vz,rho;
+                        calcMacros(f,rho,vx,vy,vz);
+                        double press = D3Q27System::calcPress(f,rho,vx,vy,vz);
+
+								//////////////////////////////////////////////////////////////////////////
+								//compute average values
+								//////////////////////////////////////////////////////////////////////////
+
+								LBMReal timeStepAfterResetRMS=(double)(timeStep-resetStepRMS)/((double)averageInterval);
+								LBMReal timeStepAfterResetMeans=(double)(timeStep-resetStepMeans)/((double)averageInterval);
+
+                        //mean velocity
+                        (*av)(AvVx,ix1,ix2,ix3) = ((*av)(AvVx,ix1,ix2,ix3)*timeStepAfterResetMeans + vx)/(timeStepAfterResetMeans+1.0);
+                        (*av)(AvVy,ix1,ix2,ix3) = ((*av)(AvVy,ix1,ix2,ix3)*timeStepAfterResetMeans + vy)/(timeStepAfterResetMeans+1.0);
+                        (*av)(AvVz,ix1,ix2,ix3) = ((*av)(AvVz,ix1,ix2,ix3)*timeStepAfterResetMeans + vz)/(timeStepAfterResetMeans+1.0);
+
+                        //rms
+								(*av)(AvVxx,ix1,ix2,ix3) = ((vx-(*av)(AvVx,ix1,ix2,ix3))*(vx-(*av)(AvVx,ix1,ix2,ix3)) +
+									(*av)(AvVxx,ix1,ix2,ix3)*timeStepAfterResetRMS)/(timeStepAfterResetRMS+1.0);
+								(*av)(AvVyy,ix1,ix2,ix3) = ((vy-(*av)(AvVy,ix1,ix2,ix3))*(vy-(*av)(AvVy,ix1,ix2,ix3)) +
+									(*av)(AvVyy,ix1,ix2,ix3)*timeStepAfterResetRMS)/(timeStepAfterResetRMS+1.0);
+								(*av)(AvVzz,ix1,ix2,ix3) = ((vz-(*av)(AvVz,ix1,ix2,ix3))*(vz-(*av)(AvVz,ix1,ix2,ix3)) +
+									(*av)(AvVzz,ix1,ix2,ix3)*timeStepAfterResetRMS)/(timeStepAfterResetRMS+1.0);
+
+                        //cross-correlations
+                        (*av)(AvVxy,ix1,ix2,ix3) = ((vx-(*av)(AvVx,ix1,ix2,ix3))*(vy-(*av)(AvVy,ix1,ix2,ix3)) +
+                           (*av)(AvVxy,ix1,ix2,ix3)*timeStepAfterResetRMS)/(timeStepAfterResetRMS+1.0);
+                        (*av)(AvVxz,ix1,ix2,ix3) = ((vx-(*av)(AvVx,ix1,ix2,ix3))*(vz-(*av)(AvVz,ix1,ix2,ix3)) +
+                           (*av)(AvVxz,ix1,ix2,ix3)*timeStepAfterResetRMS)/(timeStepAfterResetRMS+1.0);
+                        (*av)(AvVyz,ix1,ix2,ix3) = ((vy-(*av)(AvVy,ix1,ix2,ix3))*(vz-(*av)(AvVz,ix1,ix2,ix3)) +
+                           (*av)(AvVyz,ix1,ix2,ix3)*timeStepAfterResetRMS)/(timeStepAfterResetRMS+1.0);
+
+                        //mean and rms press
+                        (*av)(AvP,ix1,ix2,ix3) = ((*av)(AvP,ix1,ix2,ix3)*timeStepAfterResetMeans + press)/(timeStepAfterResetMeans+1.0);
+                        (*av)(AvPrms,ix1,ix2,ix3) = ((press-(*av)(AvP,ix1,ix2,ix3))*(press-(*av)(AvP,ix1,ix2,ix3)) +
+                           (*av)(AvPrms,ix1,ix2,ix3)*timeStepAfterResetRMS)/(timeStepAfterResetRMS+1.0);
+
+								//////////////////////////////////////////////////////////////////////////
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+////////////////////////////////////////////////////////////////////////////
+//void AverageValuesPostprocessor::initPlotData(double step)
+//{
+//   CommunicatorPtr comm = Communicator::getInstance();
+//	if (comm->getProcessID() == comm->getRoot())
+//	{
+//		std::ofstream ostr;
+//		string fname = path + "_PlotData_" + UbSystem::toString(step) + ".txt"; 
+//		ostr.open(fname.c_str(), std::ios_base::out);
+//		if(!ostr)
+//		{ 
+//			ostr.clear();
+//			string path = UbSystem::getPathFromString(fname);
+//			if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out);}
+//			if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+//		}
+//		ostr << "Time"<< "\t" <<"Ref.Time"<<"\t"<< "Z_Coor"<< "\t" << "Pore fraction" << "\t";
+//		ostr << "Vx"  << "\t" << "Vy" << "\t" << "Vz" << "\t";
+//		ostr << "TSx" << "\t" << "TSy"<< "\t" << "TSz"<< "TSxz";
+//		ostr << endl;
+//		ostr.close();
+//	}
+//}
+//////////////////////////////////////////////////////////////////////////////
+//void AverageValuesPostprocessor::collectPlotData(double step)
+//{
+//
+//	double hminX1 = 0.9;
+//	double hminX2 = 0.0;
+//	double hmaxX1 = 0.95;
+//	double hmaxX2 = 0.01; //systemabmessungen world units
+//
+//	// 3 level platte standard:
+//	double hX3_level[] = {0.305, 0.309,0.3365,0.35};
+//	//0.004, 0,0365,0.045
+//	//musis: 3 level refinement
+//	//double hX3_level[] = {0.42, 0.28, 0.105, 0.0}; //refinement coords
+//	                    //bsislevel von 0.42-0.28,... (level 0 bis 2 , 3 insgesamt)
+//	//musis: 4 level refinement
+//	//double hX3_level[] = {0.42, 0.3, 0.195, 0.078, 0.0};
+//	//musis: 5 level refinement
+//	//double hX3_level[] = {0.396, 0.28, 0.18, 0.08, 0.006, 0.0};
+//
+//	ostringstream Str;
+//	Str << step;
+//	string step2string(Str.str());
+//	string fname = path + "_PlotZ_" + step2string + ".txt"; 
+//
+//
+//	for(int level = minInitLevel; level<=maxInitLevel;level++)
+//	{
+//		double dx = grid->getDeltaX(level);
+//
+//		for (double hi =hX3_level[level]; hi >= hX3_level[level+1]; hi=hi-dx ){
+//			D3Q27IntegrateValuesHelper h1(grid, comm, 
+//				hminX1, hminX2, hi, 
+//				hmaxX1, hmaxX2, hi-dx);
+//
+//			h1.calculateAV();
+//			double nn1 = h1.getNumberOfNodes();
+//			double ns1 = h1.getNumberOfSolids();
+//			if (nn1 > 0.0){
+//				// get data and write into txt files
+//				if (comm->getProcessID() == comm->getRoot())
+//				{
+//					int istep = static_cast<int>(step);
+//					std::ofstream ostr;
+//
+//					double AvVx1 = h1.getAvVx1()/nn1;
+//					double AvVx2 = h1.getAvVx2()/nn1;
+//					double AvVx3 = h1.getAvVx3()/nn1;
+//
+//					double AvTSx1 = h1.getTSx1()/nn1;
+//					double AvTSx2 = h1.getTSx2()/nn1;
+//					double AvTSx3 = h1.getTSx3()/nn1;
+//
+//					double AvTSx1x3 = h1.getTSx1x3()/nn1;
+//
+//					ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);
+//					if(!ostr)
+//					{ 
+//						ostr.clear();
+//						string path = UbSystem::getPathFromString(fname);
+//						if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);}
+//						if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+//					}
+//					ostr << istep << "\t" << resetStep << "\t" << hi+0.5*dx << "\t" << nn1/(nn1+ns1)*100.0 << "%\t";
+//					ostr << AvVx1 << "\t" << AvVx2 << "\t" << AvVx3 << "\t";
+//					ostr << AvTSx1<< "\t" << AvTSx2<< "\t" << AvTSx3<< "\t" << AvTSx1x3;
+//					ostr << endl;
+//					ostr.close();
+//
+//				}
+//			}
+//		}
+//
+//	}
+//}
+
diff --git a/source/VirtualFluidsCore/CoProcessors/AverageValuesPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/AverageValuesPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..8e5b9461ca7e391b063756fa1b12d8be46e08de3
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/AverageValuesPostprocessor.h
@@ -0,0 +1,94 @@
+#ifndef AverageValuesPostprocessor_H
+#define AverageValuesPostprocessor_H
+
+#include "Postprocessor.h"
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+#include "D3Q27IntegrateValuesHelper.h"
+
+#include "WbWriter.h"
+
+#include <boost/shared_ptr.hpp>
+class AverageValuesPostprocessor;
+typedef boost::shared_ptr<AverageValuesPostprocessor> AverageValuesPostprocessorPtr;
+
+//! \brief  Computes the time averaged mean velocity and RMS values and writes to parallel .vtk
+//! \details writes at given time intervals specified in scheduler (s), does averaging according to scheduler (Avs) and resets according to scheduler (rs).  <br>
+//!  Computes  the time averaged mean velocity  \f$ u_{mean}=\frac{1}{N}\sum\limits_{i=1}^n u_{i} \f$  and RMS of fluctuations. You need to calculate a square root before plotting RMS. <br>
+//           
+//! \author  Sonja Uphoff, Kostyantyn Kucher 
+// \f$ u_{mean}=\frac{1}{N}\sum\limits_{i=1}^n u_{i} \f$
+class AverageValuesPostprocessor : public Postprocessor
+{
+public:
+   AverageValuesPostprocessor();
+   AverageValuesPostprocessor(Grid3DPtr grid, const std::string& path, WbWriter* const writer, 
+                              UbSchedulerPtr s, UbSchedulerPtr Avs, UbSchedulerPtr rsMeans, UbSchedulerPtr rsRMS, bool restart);
+	//! Make update
+	void update(double step); 
+	//! Resets averaged velocity and RMS-values according to ResetSceduler
+	void reset(double step); 
+protected:
+	//! Prepare data and write in .vtk file
+	void collectPostprocessData(double step);
+	//! Reset data
+	void resetPostprocessDataRMS(double step);
+	void resetPostprocessDataMeans(double step);
+	//! prepare data
+	void addPostprocessData(const Block3DPtr block);
+	void clearData();
+	//! Computes average and RMS values of macroscopic quantities 
+	void calculateAverageValues(double timeStep);
+	////! write .txt file spatial intergrated averaged value, fluctuation, porous features
+	//void collectPlotDataZ(double step);
+	////! create txt file and write head line 
+	//void initPlotDataZ(double step);
+
+private:
+	std::vector<UbTupleFloat3> nodes;
+	std::vector<UbTupleInt8> cells;
+	std::vector<std::string> datanames;
+	std::vector<std::vector<double> > data; 
+	std::vector<std::vector<Block3DPtr> > blockVector;
+	int minInitLevel; //min init level
+	int maxInitLevel;
+	int gridRank;
+	int resetStepRMS;
+	int resetStepMeans;
+	double averageInterval;
+	std::string path;
+	WbWriter* writer;
+   bool restart, compressible;
+	UbSchedulerPtr averageScheduler;  //additional scheduler to averaging after a given interval
+	UbSchedulerPtr resetSchedulerRMS;  //additional scheduler to restart averaging after a given interval
+	UbSchedulerPtr resetSchedulerMeans;  //additional scheduler to restart averaging after a given interval
+	//labels for the different components, e.g. AvVxx for time averaged RMS: 1/n SUM((U-Umean)^2)
+   //you need to calculate a square root before plotting RMS
+	enum Values{AvVx = 0, AvVy = 1, AvVz = 2, AvVxx = 3, AvVyy = 4, AvVzz = 5, AvVxy = 6, AvVxz = 7, AvVyz = 8, AvP = 9, AvPrms = 10}; 
+
+   typedef void (*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/,LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   CalcMacrosFct calcMacros;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<Postprocessor>(*this);
+      ar & path;
+      ar & blockVector;
+      ar & minInitLevel;
+      ar & maxInitLevel;
+      ar & gridRank;
+      ar & writer;
+      ar & resetStepRMS;
+      ar & resetStepMeans;
+      ar & averageInterval;
+      ar & averageScheduler;  
+      ar & resetSchedulerRMS; 
+      ar & resetSchedulerMeans;
+      ar & compressible;
+   }
+};
+#endif
diff --git a/source/VirtualFluidsCore/CoProcessors/BlocksPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/BlocksPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..48698c7424c06059aea6600a3f1ecbc870046a8c
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/BlocksPostprocessor.cpp
@@ -0,0 +1,149 @@
+#include "BlocksPostprocessor.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include <boost/foreach.hpp>
+#include "D3Q27System.h"
+
+BlocksPostprocessor::BlocksPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, 
+                                         const std::string& path, WbWriter* const writer, 
+                                         CommunicatorPtr comm) :
+                                         Postprocessor(grid, s),
+                                         path(path),
+                                         writer(writer),
+                                         comm(comm)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+BlocksPostprocessor::~BlocksPostprocessor() 
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void BlocksPostprocessor::update(double step)
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+}
+//////////////////////////////////////////////////////////////////////////
+void BlocksPostprocessor::collectPostprocessData(double step)
+{
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      int istep = int(step);
+      std::vector<std::string> filenames;
+      std::vector< UbTupleFloat3 > nodes;
+      std::vector< UbTupleInt8 > cells;
+      std::vector<std::string> celldatanames;
+
+      celldatanames.push_back("isActive");
+      celldatanames.push_back("rank");
+      celldatanames.push_back("interface");
+      celldatanames.push_back("ID");
+      celldatanames.push_back("part");
+      celldatanames.push_back("level");
+      //celldatanames.push_back("connectorCF");
+      //celldatanames.push_back("connectorFC");
+#if defined VF_FETOL
+      celldatanames.push_back("bundle");
+#endif
+
+      std::vector< std::vector< double > > celldata(celldatanames.size());
+
+      int nr=0;
+      int minInitLevel = this->grid->getCoarsestInitializedLevel();
+      int maxInitLevel = this->grid->getFinestInitializedLevel();
+
+      for(int level = minInitLevel; level<=maxInitLevel;level++)
+      {
+         std::vector<Block3DPtr> blockVector;
+         grid->getBlocks(level, blockVector);
+         BOOST_FOREACH(Block3DPtr block, blockVector)
+         {
+            UbTupleDouble3 org = grid->getBlockWorldCoordinates(block);
+            UbTupleDouble3 blockLength = grid->getBlockLengths(block);
+
+            nodes.push_back(makeUbTuple((float)(val<1>(org)), (float)(val<2>(org)), (float)(val<3>(org))));
+            nodes.push_back(makeUbTuple((float)(val<1>(org)+val<1>(blockLength)), (float)(val<2>(org)), (float)(val<3>(org))));
+            nodes.push_back(makeUbTuple((float)(val<1>(org)+val<1>(blockLength)), (float)(val<2>(org)+val<2>(blockLength)), (float)(val<3>(org))));
+            nodes.push_back(makeUbTuple((float)(val<1>(org)), (float)(val<2>(org)+val<2>(blockLength)), (float)(val<3>(org))));
+            nodes.push_back(makeUbTuple((float)(val<1>(org)), (float)(val<2>(org)), (float)(val<3>(org)+val<3>(blockLength))));
+            nodes.push_back(makeUbTuple((float)(val<1>(org)+val<1>(blockLength)), (float)(val<2>(org)), (float)(val<3>(org)+val<3>(blockLength))));
+            nodes.push_back(makeUbTuple((float)(val<1>(org)+val<1>(blockLength)), (float)(val<2>(org)+val<2>(blockLength)), (float)(val<3>(org)+val<3>(blockLength))));
+            nodes.push_back(makeUbTuple((float)(val<1>(org)), (float)(val<2>(org)+val<2>(blockLength)), (float)(val<3>(org)+val<3>(blockLength))));
+            cells.push_back(makeUbTuple(nr, nr+1, nr+2, nr+3, nr+4, nr+5, nr+6, nr+7));
+            nr += 8;
+
+            //data
+            celldata[0].push_back((double)block->isActive());
+            celldata[1].push_back((double)block->getRank());
+            celldata[2].push_back((double)block->hasInterpolationFlag());
+            celldata[3].push_back((double)block->getGlobalID());
+            celldata[4].push_back((double)block->getPart());
+            celldata[5].push_back((double)block->getLevel());
+
+            //bool flag = false;
+            //std::vector<Block3DConnectorPtr> connectors;
+
+            //block->pushBackLocalInterpolationConnectorsCF(connectors);
+            //for (std::size_t i = 0; i<connectors.size(); i++)
+            //   if (connectors[i])
+            //   {
+            //      if (connectors[i]->getSendDir() == D3Q27System::BS)
+            //      {
+
+            //         flag = true;
+            //      }
+            //   }
+
+            //if (flag)
+            //{
+            //   celldata[6].push_back(1);
+            //   UBLOG(logINFO, "CF: "+block->toString());
+            //}
+            //else
+            //{
+            //   celldata[6].push_back(0);
+            //}
+
+            //flag = false;
+            //connectors.resize(0);
+            //block->pushBackLocalInterpolationConnectorsFC(connectors);
+            //for (std::size_t i = 0; i<connectors.size(); i++)
+            //   if (connectors[i])
+            //   {
+            //      if (connectors[i]->getSendDir() == D3Q27System::BS)
+            //      {
+
+            //         flag = true;
+            //      }
+            //   }
+
+            //if (flag)
+            //{
+            //   celldata[7].push_back(1);
+            //   UBLOG(logINFO, "FC: "+block->toString());
+            //}
+            //else
+            //{
+            //   celldata[7].push_back(0);
+            //}
+
+#ifdef VF_FETOL            
+            celldata[6].push_back( (double)block->getBundle());
+#endif
+         }
+      }
+
+      filenames.push_back(writer->writeOctsWithCellData(path+"/blocks/blocks_" + UbSystem::toString(grid->getRank()) + "_" + UbSystem::toString(istep),nodes,cells,celldatanames,celldata));
+
+      if (istep == Postprocessor::scheduler->getMinBegin())
+      {
+         WbWriterVtkXmlASCII::getInstance()->writeCollection(path+"/blocks/blocks_collection",filenames,istep,false);
+      } 
+      else
+      {
+         WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(path + "/blocks/blocks_collection", filenames, istep, false);
+      }
+
+      UBLOG(logINFO,"BlocksPostprocessor step: " << istep);
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/BlocksPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/BlocksPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..458deefbacdfc422ef09ab0bc41e387bcdffde52
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/BlocksPostprocessor.h
@@ -0,0 +1,32 @@
+/*
+*  BlocksPostprocessor.h
+*
+*  Created on: 24.09.2012
+*  Author: K. Kucher
+*/
+
+#ifndef BlocksPostprocessor_H_
+#define BlocksPostprocessor_H_
+
+#include "Postprocessor.h"
+#include "Communicator.h"
+#include "WbWriter.h"
+
+#include <boost/shared_ptr.hpp>
+class BlocksPostprocessor;
+typedef boost::shared_ptr<BlocksPostprocessor> BlocksPostprocessorPtr;
+
+class BlocksPostprocessor: public Postprocessor {
+public:
+   BlocksPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, const std::string& path, WbWriter* const writer, CommunicatorPtr comm);
+   virtual ~BlocksPostprocessor();
+   void update(double step);
+protected:
+   void collectPostprocessData(double step);
+   std::string path;
+   WbWriter* writer;
+   CommunicatorPtr comm;
+};
+
+
+#endif 
diff --git a/source/VirtualFluidsCore/CoProcessors/CMakePackage.txt b/source/VirtualFluidsCore/CoProcessors/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27AdjustForcingPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/D3Q27AdjustForcingPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..324df1556ec7e145c0e1faef80ce642585ba89e4
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27AdjustForcingPostprocessor.cpp
@@ -0,0 +1,128 @@
+/*
+* D3Q27AdjustForcingPostprocessor.cpp
+*
+*  
+*  Author: Sonja Uphoff
+*/
+
+#include "D3Q27AdjustForcingPostprocessor.h"
+
+#include <SetForcingBlockVisitor.h>
+
+#include <iostream>
+#include <fstream>
+
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+D3Q27AdjustForcingPostprocessor::D3Q27AdjustForcingPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+                                                                 const std::string& path,
+                                                                 D3Q27IntegrateValuesHelperPtr integrateValues, 
+                                                                 LBMReal vTarged,
+                                                                 LBMReal forcing,
+                                                                 CommunicatorPtr comm)
+
+                                                                 : Postprocessor(grid, s),
+                                                                 path(path),
+                                                                 integrateValues(integrateValues),
+                                                                 comm(comm),
+                                                                 vTarged(vTarged),
+                                                                 vPreviousStep(0.0),
+                                                                 forcing(forcing)
+{
+   cnodes = integrateValues->getCNodes();
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      std::string fname = path+"/forcing/forcing.csv";
+      std::ofstream ostr;
+      ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);
+      if (!ostr)
+      {
+         ostr.clear();
+         string path = UbSystem::getPathFromString(fname);
+         if (path.size()>0) { UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app); }
+         if (!ostr) throw UbException(UB_EXARGS, "couldn't open file "+fname);
+      }
+      ostr << "step;volume;vx1average;factor;forcing\n";
+      ostr.close();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27AdjustForcingPostprocessor::~D3Q27AdjustForcingPostprocessor() 
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27AdjustForcingPostprocessor::update(double step)
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27AdjustForcingPostprocessor::collectPostprocessData(double step)
+{
+   integrateValues->calculateMQ();
+
+   UBLOG(logDEBUG3, "D3Q27AdjustForcingPostprocessor::update:" << step);
+   int gridRank = grid->getRank();
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   double cellsVolume = integrateValues->getCellsVolume();
+
+   double vx1 = integrateValues->getVx1();
+   double vx1average = (vx1/cellsVolume);
+
+
+   double newForcing = forcing;
+
+   if (!((vPreviousStep>(vx1average) && (vx1average)>vTarged)  || (vPreviousStep<(vx1average) && ((vx1average)<vTarged))))
+   {
+      double C = 1.0; //0.7 //P; //free parameter [0.1, 1]
+      newForcing = forcing*((1-((vx1average-vTarged)/vTarged)*C));
+      newForcing=UbMath::max(newForcing,0.0);
+      newForcing=UbMath::min(newForcing,5e-3);
+   }
+
+   vPreviousStep=vx1average;
+
+   forcing = newForcing;
+
+   mu::Parser fctForcingX1, fctForcingX2, fctForcingX3;
+   fctForcingX1.SetExpr("Fx1");
+   fctForcingX1.DefineConst("Fx1", newForcing);
+   fctForcingX2.SetExpr("0.0");
+   fctForcingX3.SetExpr("0.0");
+   //SetForcingBlockVisitor forcingVisitor(fctForcingX1, fctForcingX2, fctForcingX3);
+   //grid->accept(forcingVisitor);
+
+   BOOST_FOREACH(CalcNodes cn, cnodes)
+   {
+      LBMKernel3DPtr kernel = cn.block->getKernel();
+      if (kernel)
+      {
+         kernel->setForcingX1(fctForcingX1);
+         kernel->setWithForcing(true);
+      }
+         
+   }
+
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      //UBLOG(logINFO, "D3Q27AdjustForcingPostprocessor step: " << static_cast<int>(step));
+      //UBLOG(logINFO, "new forcing is: " << forcing);
+      std::string fname = path+"/forcing/forcing.csv";
+      std::ofstream ostr;
+      ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);
+      if (!ostr)
+      {
+         ostr.clear();
+         string path = UbSystem::getPathFromString(fname);
+         if (path.size()>0) { UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app); }
+         if (!ostr) throw UbException(UB_EXARGS, "couldn't open file "+fname);
+      }
+      int istep = static_cast<int>(step);
+      ostr << istep << ";" << cellsVolume << ";" << vx1average << "; " << 1-((vx1average-vTarged)/vTarged) << "; " << forcing << "\n";
+      ostr.close();
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27AdjustForcingPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/D3Q27AdjustForcingPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..45f53d3bc6008674f96938880ec33a51881de8c5
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27AdjustForcingPostprocessor.h
@@ -0,0 +1,41 @@
+#ifndef D3Q27ADJUSTFORCINGPOSTPROCESSOR_H
+#define D3Q27ADJUSTFORCINGPOSTPROCESSOR_H
+
+#include "Postprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+
+#include <boost/shared_ptr.hpp>
+class D3Q27AdjustForcingPostprocessor;
+typedef boost::shared_ptr<D3Q27AdjustForcingPostprocessor> D3Q27AdjustForcingPostprocessorPtr;
+
+//! \brief   Computes Forcing such that a given velocity (vxZiel) is reached inside an averaging domain (h1). 
+//! \details Integrate values helper, scheduler must be set in test case. Example usage: bKanal.cpp
+//! \author: Konstantin Kutscher
+
+class D3Q27AdjustForcingPostprocessor: public Postprocessor {
+public:
+	D3Q27AdjustForcingPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+                                   const std::string& path,
+                                   D3Q27IntegrateValuesHelperPtr integrateValues,
+                                   LBMReal vTarged, LBMReal forcing, CommunicatorPtr comm);
+	virtual ~D3Q27AdjustForcingPostprocessor();
+	 //!< calls collect PostprocessData
+   void update(double step);
+protected:
+   //!< object that can compute spacial average values in 3D-subdomain.
+   D3Q27IntegrateValuesHelperPtr integrateValues;
+   //!< compares velocity in integrateValues with target velocity and adjusts forcing accordingly.
+	void collectPostprocessData(double step);  
+   CommunicatorPtr comm;
+private:
+   double vPreviousStep; //!< velocity at previous update step.
+   double vTarged; //!< target velocity.
+   double forcing; //!< forcing at previous update step. 
+   std::vector<CalcNodes> cnodes;
+   std::string path;
+};
+
+
+#endif /* D3Q27RHODIFFERENCEPOSTPROCESSOR_H_ */
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27ForcesPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/D3Q27ForcesPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..89c1c9d6586315e5f8028c71a6aa39580c8a52e8
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27ForcesPostprocessor.cpp
@@ -0,0 +1,223 @@
+#include "D3Q27ForcesPostprocessor.h"
+#include "D3Q27ETBCProcessor.h"
+#include <boost/foreach.hpp>
+
+D3Q27ForcesPostprocessor::D3Q27ForcesPostprocessor( Grid3DPtr grid, UbSchedulerPtr s, 
+                                                    const std::string &path,
+                                                    CommunicatorPtr comm ,
+                                                    double v, double a) : 
+                                                    Postprocessor(grid, s),
+                                                    path(path), comm(comm),
+                                                    v(v), a(a),
+                                                    forceX1global(0), forceX2global(0), forceX3global(0)
+{
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      std::ofstream ostr;
+      std::string fname = path;
+      ostr.open(fname.c_str(), std::ios_base::out);
+      if(!ostr)
+      { 
+         ostr.clear();
+         std::string path = UbSystem::getPathFromString(fname);
+         if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out);}
+         if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+      }
+      ostr.width(12);
+      ostr << "step" << "\t";
+      ostr.width(12);
+      ostr << "Cx" << "\t";
+      ostr.width(12);
+      ostr << "Cy"  << "\t"; 
+      ostr.width(12);   
+      ostr << "Cz" << std::endl;
+      ostr.close();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27ForcesPostprocessor::~D3Q27ForcesPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ForcesPostprocessor::update( double step )
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+
+   UBLOG(logDEBUG3, "D3Q27ForcesPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ForcesPostprocessor::collectPostprocessData( double step )
+{
+   calculateForces();
+
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      int istep = static_cast<int>(step);
+      std::ofstream ostr;
+      std::string fname = path;
+      ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);
+      if(!ostr)
+      { 
+         ostr.clear();
+         std::string path = UbSystem::getPathFromString(fname);
+         if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);}
+         if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+      }
+
+      calculateCoefficients();
+
+      ostr.width(12); 
+      ostr.setf(std::ios::fixed); 
+      ostr << istep << "\t";
+      write(&ostr, C1, (char*)"\t");
+      write(&ostr, C2, (char*)"\t");
+      write(&ostr, C3, (char*)"\t");
+      ostr << std::endl;
+      ostr.close();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ForcesPostprocessor::calculateForces()
+{
+   forceX1global = 0.0;
+   forceX2global = 0.0;
+   forceX3global = 0.0;
+
+   BOOST_FOREACH(D3Q27InteractorPtr interactor, interactors)
+   {
+      typedef std::map<Block3DPtr, std::set< std::vector<int> > > TransNodeIndicesMap;
+      BOOST_FOREACH(TransNodeIndicesMap::value_type t, interactor->getTransNodeIndicesMap())
+      {
+         double forceX1 = 0.0;
+         double forceX2 = 0.0;
+         double forceX3 = 0.0;
+
+         Block3DPtr block = t.first;
+         std::set< std::vector<int> >& transNodeIndicesSet = t.second;
+
+         LBMKernel3DPtr kernel = block->getKernel();
+         BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+         DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+         distributions->swap();
+
+         int minX1 = kernel->getGhostLayerWidth();
+         int maxX1 = (int)bcArray.getNX1() - 1 - kernel->getGhostLayerWidth();
+         int minX2 = kernel->getGhostLayerWidth();
+         int maxX2 = (int)bcArray.getNX2() - 1 - kernel->getGhostLayerWidth();
+         int minX3 = kernel->getGhostLayerWidth();
+         int maxX3 = (int)bcArray.getNX3() - 1 - kernel->getGhostLayerWidth();
+
+         BOOST_FOREACH(std::vector<int> node, transNodeIndicesSet)
+         {
+            int x1 = node[0];
+            int x2 = node[1];
+            int x3 = node[2];
+
+            //without ghost nodes
+            if (x1 < minX1 || x1 > maxX1 || x2 < minX2 || x2 > maxX2 ||x3 < minX3 || x3 > maxX3 ) continue;
+
+            if(bcArray.isFluid(x1,x2,x3)) //es kann sein, dass der node von einem anderen interactor z.B. als solid gemarkt wurde!!!
+            {
+               D3Q27BoundaryConditionPtr bc = bcArray.getBC(x1,x2,x3);
+               UbTupleDouble3 forceVec = getForces(x1,x2,x3,distributions,bc);
+               forceX1 += val<1>(forceVec);
+               forceX2 += val<2>(forceVec);
+               forceX3 += val<3>(forceVec);
+            }
+         }
+         //if we have got discretization with more level
+         // deltaX is LBM deltaX and equal LBM deltaT 
+         double deltaX = LBMSystem::getDeltaT(block->getLevel()); //grid->getDeltaT(block);
+         double deltaXquadrat = deltaX*deltaX;
+         forceX1 *= deltaXquadrat;
+         forceX2 *= deltaXquadrat;
+         forceX3 *= deltaXquadrat;
+
+         distributions->swap();
+
+         forceX1global += forceX1;
+         forceX2global += forceX2;
+         forceX3global += forceX3;
+      }
+   }
+   std::vector<double> values;
+   std::vector<double> rvalues;
+   values.push_back(forceX1global);
+   values.push_back(forceX2global);
+   values.push_back(forceX3global);
+
+   rvalues = comm->gather(values);
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      forceX1global = 0.0;
+      forceX2global = 0.0;
+      forceX3global = 0.0;
+      
+      for (int i = 0; i < (int)rvalues.size(); i+=3)
+      {
+         forceX1global += rvalues[i];
+         forceX2global += rvalues[i+1];
+         forceX3global += rvalues[i+2];
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleDouble3 D3Q27ForcesPostprocessor::getForces(int x1, int x2, int x3, DistributionArray3DPtr distributions, D3Q27BoundaryConditionPtr bc)
+{
+   UbTupleDouble3 force(0.0,0.0,0.0);
+   
+   if(bc)
+   {
+      //references to tuple "force"
+      double& forceX1 = val<1>(force);
+      double& forceX2 = val<2>(force);
+      double& forceX3 = val<3>(force);
+      double f,  fnbr;
+
+      for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+      {
+         if(bc->hasNoSlipBoundaryFlag(fdir))
+         {
+            const int invDir = D3Q27System::INVDIR[fdir];
+            f = boost::dynamic_pointer_cast<EsoTwist3D>(distributions)->getDistributionInvForDirection(x1, x2, x3, invDir);
+            fnbr = boost::dynamic_pointer_cast<EsoTwist3D>(distributions)->getDistributionInvForDirection(x1+D3Q27System::DX1[invDir], x2+D3Q27System::DX2[invDir], x3+D3Q27System::DX3[invDir], fdir);
+
+            forceX1 += (f + fnbr)*D3Q27System::DX1[invDir];
+            forceX2 += (f + fnbr)*D3Q27System::DX2[invDir];
+            forceX3 += (f + fnbr)*D3Q27System::DX3[invDir];
+         }
+      }
+   }
+   
+   return force;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ForcesPostprocessor::calculateCoefficients()
+{
+   double F1 = forceX1global;
+   double F2 = forceX2global;
+   double F3 = forceX3global;
+   
+   //return 2*F/(rho*v*v*a); 
+   C1 = 2.0*F1/(v*v*a);
+   C2 = 2.0*F2/(v*v*a);
+   C3 = 2.0*F3/(v*v*a);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ForcesPostprocessor::addInteractor( D3Q27InteractorPtr interactor )
+{
+   interactors.push_back(interactor);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ForcesPostprocessor::write(std::ofstream *fileObject, double value, char *separator) 
+{ 
+   (*fileObject).width(12); 
+   //(*fileObject).precision(2); 
+   (*fileObject).setf(std::ios::fixed); 
+   (*fileObject) << value; 
+   (*fileObject) << separator; 
+} 
+
+
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27ForcesPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/D3Q27ForcesPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b2dc97f6f8a7030acf9c3d041b497d9f89e254d
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27ForcesPostprocessor.h
@@ -0,0 +1,59 @@
+/*
+ *  D3Q27ForcesPostprocessor.h
+ *
+ *  Created on: 29.09.2012
+ *  Author: K. Kucher
+ */
+
+#ifndef D3Q27ForcesPostprocessor_H
+#define D3Q27ForcesPostprocessor_H
+
+#include "Postprocessor.h"
+#include "Communicator.h"
+#include "D3Q27Interactor.h"
+
+class D3Q27ForcesPostprocessor: public Postprocessor 
+{
+public:
+   //! Constructor
+   //! \param v - velocity of fluid in LB units
+   //! \param a - area of object in LB units
+   D3Q27ForcesPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+                            const std::string &path,
+                            CommunicatorPtr comm, double v, double a);
+	virtual ~D3Q27ForcesPostprocessor();             
+	void update(double step); 
+   void addInteractor(D3Q27InteractorPtr interactor);
+protected:
+	void collectPostprocessData(double step);
+   void calculateForces();
+   UbTupleDouble3 getForces(int x1, int x2, int x3, DistributionArray3DPtr distributions, D3Q27BoundaryConditionPtr bc);
+   void calculateCoefficients();
+   void write(std::ofstream *fileObject, double value, char *separator);
+private:
+   std::string path;
+   CommunicatorPtr comm;
+   std::vector<D3Q27InteractorPtr> interactors;
+   double forceX1global;
+   double forceX2global;
+   double forceX3global;
+   double v;     //!< is the speed of the object relative to the fluid
+   double a;     //!< is the reference area
+   double C1;
+   double C2;
+   double C3;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<Postprocessor>(*this);
+      ar & path;
+      ar & v;
+      ar & a;
+      ar & interactors;
+   }
+};
+
+
+#endif /* D3Q27ForcesPostprocessor_H */
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27MacroscopicQuantitiesPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/D3Q27MacroscopicQuantitiesPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d551a8ae831f04b0de68774b97d3a89b9de8ae23
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27MacroscopicQuantitiesPostprocessor.cpp
@@ -0,0 +1,404 @@
+#include "D3Q27MacroscopicQuantitiesPostprocessor.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include <vector>
+#include <string>
+#include <boost/foreach.hpp>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+
+using namespace std;
+
+D3Q27MacroscopicQuantitiesPostprocessor::D3Q27MacroscopicQuantitiesPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27MacroscopicQuantitiesPostprocessor::D3Q27MacroscopicQuantitiesPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+                                                                                 const std::string& path, WbWriter* const writer, 
+                                                                                 LBMUnitConverterPtr conv, 
+                                                                                 bool bcInformation)
+                                                                                 : Postprocessor(grid, s),
+                                                                                 path(path),
+                                                                                 writer(writer),
+                                                                                 conv(conv),
+                                                                                 bcInformation(bcInformation)
+//D3Q27MacroscopicQuantitiesPostprocessor::D3Q27MacroscopicQuantitiesPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+//                                                                                 const std::string& path, WbWriter* const writer, 
+//                                                                                 const LBMUnitConverterPtr conv, CommunicatorPtr comm, 
+//                                                                                 bool bcInformation)
+//                                                                                 : ScheduledGridObserver(grid, s),
+//                                                                                 path(path),
+//                                                                                 comm(comm),
+//                                                                                 writer(writer),
+//                                                                                 conv(conv),
+//                                                                                 bcInformation(bcInformation)
+{
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27MacroscopicQuantitiesPostprocessor::init()
+{
+   gridRank  = Communicator::getInstance()->getProcessID(); 
+   minInitLevel = this->grid->getCoarsestInitializedLevel();
+   maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   blockVector.resize(maxInitLevel+1);
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27MacroscopicQuantitiesPostprocessor::update(double step)
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+
+   UBLOG(logDEBUG3, "D3Q27MacroscopicQuantitiesPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27MacroscopicQuantitiesPostprocessor::collectPostprocessData(double step)
+{
+   int istep = static_cast<int>(step);
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         if (block)
+         {
+               if(!bcInformation)
+               {
+                  addPostprocessData1(block);
+               }
+               else
+               {
+                  addPostprocessData2(block);
+               }
+         }
+      }
+   }
+
+   string pfilePath, partPath, subfolder, cfilePath;
+
+   if(!bcInformation)
+   {
+      subfolder = "mq"+UbSystem::toString(istep);
+      pfilePath =  path+"/mq/"+subfolder;
+      cfilePath =  path+"/mq/mq_collection";
+      partPath = pfilePath+"/mq"+UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep);
+   }
+   else
+   {
+      subfolder = "nodes"+UbSystem::toString(istep);
+      pfilePath =  path+"/nodes/"+subfolder;
+      cfilePath =  path+"/nodes/nodes_collection";
+      partPath = pfilePath+"/nodes"+UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep);
+   }
+
+   string partName = writer->writeOctsWithNodeData(partPath,nodes,cells,datanames,data);
+   size_t found=partName.find_last_of("/");
+   string piece = partName.substr(found+1);
+   piece = subfolder + "/" + piece;
+
+   vector<string> cellDataNames;
+   CommunicatorPtr comm = Communicator::getInstance();
+   vector<string> pieces = comm->gather(piece);
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(pfilePath,pieces,datanames,cellDataNames);
+      found=pname.find_last_of("/");
+      piece = pname.substr(found+1);
+
+      vector<string> filenames;
+      filenames.push_back(piece);
+      if (step == Postprocessor::scheduler->getMinBegin())
+      {
+         WbWriterVtkXmlASCII::getInstance()->writeCollection(cfilePath,filenames,istep,false);
+      } 
+      else
+      {
+         WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(cfilePath,filenames,istep,false);
+      }
+      UBLOG(logINFO,"D3Q27MacroscopicQuantitiesPostprocessor step: " << istep);
+   }
+
+   clearData();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27MacroscopicQuantitiesPostprocessor::clearData()
+{
+   nodes.clear();
+   cells.clear();
+   datanames.clear();
+   data.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27MacroscopicQuantitiesPostprocessor::addPostprocessData1(Block3DPtr block)
+{
+   UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+   UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+   double         dx           = grid->getDeltaX(block);
+
+   double level = (double)block->getLevel();
+   double blockID = (double)block->getGlobalID();
+
+   //Diese Daten werden geschrieben:
+   datanames.resize(0);
+   datanames.push_back("Rho");
+   datanames.push_back("Vx");
+   datanames.push_back("Vy");
+   datanames.push_back("Vz");
+   //datanames.push_back("Press");
+   //datanames.push_back("Level");
+   //datanames.push_back("BlockID");
+
+     
+
+   data.resize(datanames.size());
+
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();     
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal vx1,vx2,vx3,rho;
+
+   //knotennummerierung faengt immer bei 0 an!
+   int SWB,SEB,NEB,NWB,SWT,SET,NET,NWT;
+
+   //Funktionszeiger
+   typedef void (*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/,LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+
+   CalcMacrosFct calcMacros = NULL;
+
+   if(block->getKernel()->getCompressible())
+   {
+      calcMacros = &D3Q27System::calcCompMacroscopicValues;
+   }
+   else
+   {
+      calcMacros = &D3Q27System::calcIncompMacroscopicValues;
+   }
+
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int maxX1 = (int)(distributions->getNX1());
+   int maxX2 = (int)(distributions->getNX2());
+   int maxX3 = (int)(distributions->getNX3());
+
+   //int minX1 = 1;
+   //int minX2 = 1;
+   //int minX3 = 1;
+
+   //int maxX1 = (int)(distributions->getNX1());
+   //int maxX2 = (int)(distributions->getNX2());
+   //int maxX3 = (int)(distributions->getNX3());
+
+   //nummern vergeben und node vector erstellen + daten sammeln
+   CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3,-1);
+   maxX1 -= 2;
+   maxX2 -= 2;
+   maxX3 -= 2;
+
+   //D3Q27BoundaryConditionPtr bcPtr;
+   int nr = (int)nodes.size();
+ 
+   for(size_t ix3=minX3; ix3<=maxX3; ix3++)
+   {
+      for(size_t ix2=minX2; ix2<=maxX2; ix2++)
+      {
+         for(size_t ix1=minX1; ix1<=maxX1; ix1++)
+         {
+            if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+            {
+               int index = 0;
+               nodeNumbers(ix1,ix2,ix3) = nr++;
+               nodes.push_back( makeUbTuple(float(val<1>(org) - val<1>(nodeOffset) + ix1*dx),
+                                            float(val<2>(org) - val<2>(nodeOffset) + ix2*dx),
+                                            float(val<3>(org) - val<3>(nodeOffset) + ix3*dx)) );
+
+               distributions->getDistribution(f, ix1, ix2, ix3);
+               calcMacros(f,rho,vx1,vx2,vx3);
+               //double press = D3Q27System::calcPress(f,rho,vx1,vx2,vx3);
+
+               if (UbMath::isNaN(rho) || UbMath::isInfinity(rho)) 
+                  UB_THROW( UbException(UB_EXARGS,"rho is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                   ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+                     //rho=999.0;
+               //if (UbMath::isNaN(press) || UbMath::isInfinity(press)) 
+               //   UB_THROW( UbException(UB_EXARGS,"press is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+               //   ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+                  //press=999.0;
+               if (UbMath::isNaN(vx1) || UbMath::isInfinity(vx1)) 
+                  UB_THROW( UbException(UB_EXARGS,"vx1 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                  ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+                     //vx1=999.0;
+               if (UbMath::isNaN(vx2) || UbMath::isInfinity(vx2)) 
+                  UB_THROW( UbException(UB_EXARGS,"vx2 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                  ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+                     //vx2=999.0;
+               if (UbMath::isNaN(vx3) || UbMath::isInfinity(vx3)) 
+                  UB_THROW( UbException(UB_EXARGS,"vx3 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                  ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+
+               data[index++].push_back(rho);
+               data[index++].push_back(vx1);
+               data[index++].push_back(vx2);
+               data[index++].push_back(vx3);
+               
+               //data[index++].push_back(rho * conv->getFactorDensityLbToW2() );
+               //data[index++].push_back(vx1 * conv->getFactorVelocityLbToW2());
+               //data[index++].push_back(vx2 * conv->getFactorVelocityLbToW2());
+               //data[index++].push_back(vx3 * conv->getFactorVelocityLbToW2());
+               //data[index++].push_back(press * conv->getFactorPressureLbToW2());
+               //data[index++].push_back(level);
+               //data[index++].push_back(blockID);
+            }
+         }
+      }
+   }
+   maxX1 -= 1;
+   maxX2 -= 1;
+   maxX3 -= 1;
+   //cell vector erstellen
+   for(int ix3=minX3; ix3<=maxX3; ix3++)
+   {
+      for(int ix2=minX2; ix2<=maxX2; ix2++)
+      {
+         for(int ix1=minX1; ix1<=maxX1; ix1++)
+         {
+            if(   (SWB=nodeNumbers( ix1  , ix2,   ix3   )) >= 0
+               && (SEB=nodeNumbers( ix1+1, ix2,   ix3   )) >= 0
+               && (NEB=nodeNumbers( ix1+1, ix2+1, ix3   )) >= 0
+               && (NWB=nodeNumbers( ix1  , ix2+1, ix3   )) >= 0 
+               && (SWT=nodeNumbers( ix1  , ix2,   ix3+1 )) >= 0
+               && (SET=nodeNumbers( ix1+1, ix2,   ix3+1 )) >= 0
+               && (NET=nodeNumbers( ix1+1, ix2+1, ix3+1 )) >= 0
+               && (NWT=nodeNumbers( ix1  , ix2+1, ix3+1 )) >= 0                )
+            {
+               cells.push_back( makeUbTuple(SWB,SEB,NEB,NWB,SWT,SET,NET,NWT) );
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27MacroscopicQuantitiesPostprocessor::addPostprocessData2(Block3DPtr block)
+{
+   UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+   UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+   double         dx           = grid->getDeltaX(block);
+   
+   double level = (double)block->getLevel();
+
+   //Diese Daten werden geschrieben:
+   datanames.resize(0);
+   datanames.push_back("Boundary Conditions");
+   datanames.push_back("Geometry");
+   datanames.push_back("Level");
+   //datanames.push_back("Interface CF");
+
+   data.resize(datanames.size());
+
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+
+   //knotennummerierung faengt immer bei 0 an!
+   int SWB,SEB,NEB,NWB,SWT,SET,NET,NWT;
+
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int maxX1 = (int)bcArray.getNX1();
+   int maxX2 = (int)bcArray.getNX2();
+   int maxX3 = (int)bcArray.getNX3();
+
+   //nummern vergeben und node vector erstellen + daten sammeln
+   CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3,-1);
+   //D3Q27BoundaryConditionPtr bcPtr;
+   int nr = (int)nodes.size();
+
+   maxX1 -= 1;
+   maxX2 -= 1;
+   maxX3 -= 1;
+
+   for(size_t ix3=minX3; ix3<=maxX3; ix3++)
+   {
+      for(size_t ix2=minX2; ix2<=maxX2; ix2++)
+      {
+         for(size_t ix1=minX1; ix1<=maxX1; ix1++)
+         {
+               if(!bcArray.isUndefined(ix1,ix2,ix3) )
+               {
+                  //int index = 0;
+                  nodeNumbers(ix1,ix2,ix3) = nr++;
+                  nodes.push_back(makeUbTuple(float(val<1>(org) - val<1>(nodeOffset) + ix1*dx), 
+                                              float(val<2>(org) - val<2>(nodeOffset) + ix2*dx),
+                                              float(val<3>(org) - val<3>(nodeOffset) + ix3*dx)));
+
+                  if ( !bcArray.hasBC(ix1,ix2,ix3)) 
+                     data[0].push_back( 0.0);
+                  else if(bcArray.getBC(ix1,ix2,ix3)->hasNoSlipBoundary()) 
+                     data[0].push_back( 1.0);
+                  else if(bcArray.getBC(ix1,ix2,ix3)->hasVelocityBoundary()) 
+                     data[0].push_back( 2.0);
+                  else if(bcArray.getBC(ix1,ix2,ix3)->hasDensityBoundary()) 
+                     data[0].push_back( 3.0);
+                  else if(bcArray.getBC(ix1,ix2,ix3)->hasSlipBoundary()) 
+                     data[0].push_back( 4.0);
+                  else  
+                     data[0].push_back( 5.0);
+
+                  if( bcArray.isSolid(ix1,ix2,ix3))
+                     data[1].push_back(1.0);
+                  else
+                     data[1].push_back(0.0);
+
+                  data[2].push_back(level);
+                  
+                  //if (bcArray.isInterfaceCF(ix1, ix2, ix3))
+                  //{
+                  //   data[3].push_back(1.0);
+                  //} 
+                  //else
+                  //{
+                  //   data[3].push_back(0.0);
+                  //}
+                  
+               }
+         }
+      }
+   }
+   
+   maxX1 -= 1;
+   maxX2 -= 1;
+   maxX3 -= 1;
+
+   //cell vector erstellen
+   for(int ix3=minX3; ix3<=maxX3; ix3++)
+   {
+      for(int ix2=minX2; ix2<=maxX2; ix2++)
+      {
+         for(int ix1=minX1; ix1<=maxX1; ix1++)
+         {
+            if(   (SWB=nodeNumbers( ix1  , ix2,   ix3   )) >= 0
+               && (SEB=nodeNumbers( ix1+1, ix2,   ix3   )) >= 0
+               && (NEB=nodeNumbers( ix1+1, ix2+1, ix3   )) >= 0
+               && (NWB=nodeNumbers( ix1  , ix2+1, ix3   )) >= 0 
+               && (SWT=nodeNumbers( ix1  , ix2,   ix3+1 )) >= 0
+               && (SET=nodeNumbers( ix1+1, ix2,   ix3+1 )) >= 0
+               && (NET=nodeNumbers( ix1+1, ix2+1, ix3+1 )) >= 0
+               && (NWT=nodeNumbers( ix1  , ix2+1, ix3+1 )) >= 0                )
+            {
+               cells.push_back( makeUbTuple(SWB,SEB,NEB,NWB,SWT,SET,NET,NWT) );
+            }
+         }
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27MacroscopicQuantitiesPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/D3Q27MacroscopicQuantitiesPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5a26a929099059ed1bc013636e5cb27f723cce3
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27MacroscopicQuantitiesPostprocessor.h
@@ -0,0 +1,59 @@
+#ifndef D3Q27MACROSCOPICQUANTITIESPOSTPROCESSOR_H
+#define D3Q27MACROSCOPICQUANTITIESPOSTPROCESSOR_H
+
+#include "Postprocessor.h"
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+#include "WbWriter.h"
+
+#include <boost/shared_ptr.hpp>
+class D3Q27MacroscopicQuantitiesPostprocessor;
+typedef boost::shared_ptr<D3Q27MacroscopicQuantitiesPostprocessor> D3Q27MacroscopicQuantitiesPostprocessorPtr;
+
+class D3Q27MacroscopicQuantitiesPostprocessor : public  Postprocessor 
+{
+public:
+   D3Q27MacroscopicQuantitiesPostprocessor();
+   D3Q27MacroscopicQuantitiesPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, 
+                                           const std::string& path, WbWriter* const writer, 
+                                           LBMUnitConverterPtr conv,  
+                                           bool nodesInformation = false);
+   void update(double step);
+protected:
+   void collectPostprocessData(double step);
+   void addPostprocessData1(Block3DPtr block);
+   void addPostprocessData2(Block3DPtr block);
+   void clearData();
+private:
+   void init();
+   std::vector<UbTupleFloat3> nodes;
+   std::vector<UbTupleInt8> cells;
+   std::vector<std::string> datanames;
+   std::vector<std::vector<double> > data; 
+   std::string path;
+   WbWriter* writer;
+   LBMUnitConverterPtr conv;
+   bool bcInformation;
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   int minInitLevel;
+   int maxInitLevel;
+   int gridRank;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<Postprocessor>(*this);
+      ar & path;
+      ar & conv;
+      ar & bcInformation;
+      ar & blockVector;
+      ar & minInitLevel;
+      ar & maxInitLevel;
+      ar & gridRank;
+      ar & writer;
+   }
+};
+#endif
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27MeanValuesPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/D3Q27MeanValuesPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..791a59602f8580ffa5a7b5d04cdab8dc16a194e1
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27MeanValuesPostprocessor.cpp
@@ -0,0 +1,67 @@
+#include "D3Q27MeanValuesPostprocessor.h"
+
+D3Q27MeanValuesPostprocessor::D3Q27MeanValuesPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, const std::string &path,
+                                                           CommunicatorPtr comm, D3Q27IntegrateValuesHelperPtr ih, double factorPressure, double factorVelocity) :
+                                                            Postprocessor(grid, s),
+                                                            filename(path),
+                                                            comm(comm),
+                                                            ih(ih),
+                                                            factorPressure(factorPressure),
+                                                            factorVelocity(factorVelocity)
+{
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      FILE *output;
+      output = fopen(filename.c_str(), "w");
+      if (output == NULL)
+      {
+         std::string pathf = UbSystem::getPathFromString(filename);
+         if (filename.size()>0) { UbSystem::makeDirectory(pathf); output = fopen(filename.c_str(), "w"); }
+         if (output == NULL) throw UbException(UB_EXARGS, "can not open " + filename);
+      }
+         
+      //fprintf(output, "%-18s %-18s %-18s %-18s %-18s %-18s %-18s\n", "time step", "area", "pressure [Pa*m^2]", "velocity [m^3/s]", "velocityX [m^3/s]", "velocityY [m^3/s]", "velocityZ [m^3/s]");
+      fprintf(output, "%-18s;%-18s;%-18s;%-18s;%-18s\n", "time step", "area", "velocityX [m^3/s]", "velocityY [m^3/s]", "velocityZ [m^3/s]");
+      fclose(output);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27MeanValuesPostprocessor::~D3Q27MeanValuesPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27MeanValuesPostprocessor::update(double step)
+{
+   if (scheduler->isDue(step))
+      collectPostprocessData(step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27MeanValuesPostprocessor::collectPostprocessData(double step)
+{
+   ih->calculateMQ();
+   
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      int istep = static_cast<int>(step);
+      std::ofstream ostr;
+      double nn = ih->getNumberOfFluidsNodes();
+      //double p = (ih->getPress())*factorPressure;
+      double vx1 = (ih->getVx1())*factorVelocity;
+      double vx2 = (ih->getVx2())*factorVelocity;
+      double vx3 = (ih->getVx3())*factorVelocity;
+      //double vm = (ih->getVm())*factorVelocity;
+
+      FILE *output;
+      output = fopen(filename.c_str(), "a");
+      if (output == NULL)
+         throw UbException(UB_EXARGS, "can not open " + filename);
+
+      //fprintf(output, "%-18d %-18d %-18.3f %-18.3f %-18.3f %-18.3f %-18.3f\n", istep, (int)nn, p, vm, vx1, vx2, vx3);
+      fprintf(output, "%-18d %-18d %-18.3f %-18.3f %-18.3f\n", istep, (int)nn, vx1, vx2, vx3);
+
+      fclose(output);
+
+      UBLOG(logINFO, "D3Q27MeanValuesPostprocessor step: " << istep);
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27MeanValuesPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/D3Q27MeanValuesPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ab1f2278c690f7111cf26983897b80f7f013ce9
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27MeanValuesPostprocessor.h
@@ -0,0 +1,26 @@
+#ifndef D3Q27MEANVALUESPOSTPROCESSOR_H
+#define D3Q27MEANVALUESPOSTPROCESSOR_H
+
+#include <Postprocessor.h>
+#include <D3Q27IntegrateValuesHelper.h>
+#include <LBMUnitConverter.h>
+
+class D3Q27MeanValuesPostprocessor : public Postprocessor
+{
+public:
+   D3Q27MeanValuesPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, const std::string &path,
+      CommunicatorPtr comm, D3Q27IntegrateValuesHelperPtr ih, double factorPressure, double factorVelocity);
+                                
+   virtual ~D3Q27MeanValuesPostprocessor();
+   void update(double step);
+   
+private:
+   D3Q27IntegrateValuesHelperPtr ih;
+   CommunicatorPtr comm;
+   std::string filename;
+   double factorPressure, factorVelocity;
+   void collectPostprocessData(double step);
+};
+
+#endif
+   
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6e8ca7ea9729974b86e2955674fee27089dbccf5
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessor.cpp
@@ -0,0 +1,1505 @@
+#include "D3Q27PathLinePostprocessor.h"
+#include "LBMKernelETD3Q27.h"
+#include "SimulationParameters.h"
+#include "D3Q27ETBCProcessor.h"
+#include <vector>
+#include <string>
+#include <boost/foreach.hpp>
+#include "WbWriter.h"
+
+using namespace std;
+
+
+D3Q27PathLinePostprocessor::D3Q27PathLinePostprocessor(Grid3DPtr grid, const std::string& path,
+                                                       WbWriter* const writer, LBMUnitConverterPtr conv,
+                                                       UbSchedulerPtr s, CommunicatorPtr comm, 
+                                                       double x1, double x2, double x3, LBMReal nue, D3Q27InterpolationProcessorPtr iProcessor)
+                                                       : Postprocessor(grid, s),
+                                                       path(path),
+                                                       comm(comm),
+                                                       writer(writer),
+                                                       conv(conv),
+                                                       x1(x1),
+                                                       x2(x2),
+                                                       x3(x3),
+                                                       nue(nue),
+                                                       iProcessor(iProcessor),
+                                                       vx1old(0.0),
+                                                       vx2old(0.0),
+                                                       vx3old(0.0),
+                                                       vx1oldf(0.1),
+                                                       vx2oldf(0.1),
+                                                       vx3oldf(0.1),
+                                                       isExtrapolation(0),
+                                                       istep(0),
+                                                       maxtag(-1),
+                                                       particleHasMass(true),
+                                                       rank(comm->getProcessID())
+{
+   iHelper = D3Q27InterpolationHelperPtr(new D3Q27InterpolationHelper(iProcessor));
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27PathLinePostprocessor::~D3Q27PathLinePostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::update(double step)
+{
+   this->stepcheck=(int)step;
+   double aa=scheduler->getMinEnd();
+   if (step >= scheduler->getMaxBegin() && step <= scheduler->getMinEnd())
+   {
+      collectPostprocessData();
+   }
+
+   UBLOG(logDEBUG3, "PathLinePostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::collectPostprocessData()
+{
+   //for (int n=0;n<Positions[][0].size();n++)
+   //{
+   //}
+
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+   bool goinside=true;
+
+   LBMKernelETD3Q27Ptr kernel;
+   DistributionArray3DPtr distributions;
+   BCArray3D<D3Q27BoundaryCondition> bcArray;
+   Block3DPtr block;
+   Block3DPtr block2;
+   int isPointSuitable=0;//0 means false
+   ///////send tau for printing to proccess 0
+   double tau[6];//={tauxx,tauyy,tauzz,tauxy,tauxz,tauyz};
+   for(int level = minInitLevel; level<=maxInitLevel; level++)
+   {	      
+      UbTupleInt3 blockIndexes = grid->getBlockIndexes(x1, x2, x3,level);
+      block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+      if(!block) continue; 
+      if(block->isActive()) 
+      {
+         this->root=block->getRank();
+         if(rank == block->getRank())
+         { 
+            if(!checkNodes(block))
+            {		   
+               isPointSuitable=0;//0 meas false
+               if(comm->getNumberOfProcesses() > 1)   {  sendtoOtherIsOk(isPointSuitable);}
+               continue;
+            }  
+            initialMovement(block, kernel, distributions,  bcArray);
+            isPointSuitable=1;//0 meas false
+            if(comm->getNumberOfProcesses() > 1)   {  sendtoOtherIsOk(isPointSuitable);}
+            break;
+         }	
+         else
+         {
+            if(comm->getNumberOfProcesses() > 1)  
+            { 
+               MPI_Status status; 
+               MPI_Recv(&isPointSuitable,1, MPI_INT,this->root,this->rank,MPI_COMM_WORLD,&status);
+               if (isPointSuitable)
+               {
+                  break;
+               }
+            }
+         } 
+      }
+   } 
+   if (isPointSuitable)
+   {
+      if(comm->getNumberOfProcesses() > 1) updateDistributedValues();
+      bool isPointSuitable2;
+      checkLevel(block, kernel, distributions,  bcArray,isPointSuitable2);
+      if (isPointSuitable2)
+      {  
+         if(block->isActive())
+         { 
+            if (rank == block->getRank())
+            {
+               interpolMovement(block, kernel, distributions,  bcArray,isExtrapolation,tau);
+               if (isExtrapolation)
+               {	
+                  extrapolMovement(block, kernel, distributions,  bcArray,tau);
+               }
+            }
+            else
+            {
+               if(comm->getNumberOfProcesses() > 1)  
+               {  
+                  //recive isExtrapolation
+                  if (this->rank!=this->root)
+                  {
+                     MPI_Status status; 
+                     MPI_Recv(&isExtrapolation,1, MPI_INT,this->root,this->rank,MPI_COMM_WORLD,&status);
+                  }
+               }
+            }
+         }   
+         if(comm->getNumberOfProcesses() > 1) 
+         {
+            if (isExtrapolation)
+            {	
+               if (this->rank!=this->root)
+               {
+                  MPI_Status status;   
+                  MPI_Recv(&maxtag,1, MPI_INT,this->root,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+               }	   
+            }
+            if (isExtrapolation)
+            {	
+               if (this->rank!=this->root)
+               {
+                  MPI_Status status; 
+                  double input [7][25];
+                  double AllCell[7][8*27];
+                  int sizeinput=25;
+                  for (int i=0;i<maxtag;i++)
+                  {  
+                     double vectforTrans[25]; 
+                     double *Cell=(double*)malloc(8*27*sizeof(double));
+                     MPI_Recv(vectforTrans,25, MPI_DOUBLE_PRECISION,this->root,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+                     getAllInfoForCompare(vectforTrans,Cell);
+
+                     for (int j=0;j<sizeinput;j++)  {  input[i][j]=vectforTrans[j]; }
+                     for (int k=0;k<8*27;k++)       {  AllCell[i][k]=Cell[k];   	  }
+                     free (Cell);
+                  }
+                  for (int i=0;i<maxtag;i++)
+                  { 
+                     double vectforTrans[25];
+                     double *Cell=(double*)malloc(8*27*sizeof(double));
+                     for (int j=0;j<sizeinput;j++)   {	  vectforTrans[j]=input[i][j]; 	  }
+                     for (int k=0;k<8*27;k++)       {    Cell[k]=AllCell[i][k];   	  }
+
+                     MPI_Send(vectforTrans,25, MPI_DOUBLE_PRECISION,this->root,i,MPI_COMM_WORLD);
+                     MPI_Send(Cell,8*27, MPI_DOUBLE_PRECISION,this->root,i,MPI_COMM_WORLD);
+                     free (Cell);
+                  }
+               }
+            }
+            updateDistributedValues();
+         }
+
+         if(comm->getNumberOfProcesses() > 1)  MPI_Bcast(tau,6, MPI_DOUBLE, this->root, MPI_COMM_WORLD);	   
+         if (rank==0)
+         {
+            MPI_Status status;   
+            printPoint(tau);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::printPoint(double tau[])
+{
+   double tauxx=tau[0];
+   double tauyy=tau[1];
+   double tauzz=tau[2];
+   double tauxy=tau[3];
+   double tauxz=tau[4];
+   double tauyz=tau[5];
+   datanames.resize(0);
+   datanames.push_back("TimeStep");
+   datanames.push_back("Vx");
+   datanames.push_back("Vy");
+   datanames.push_back("Vz");
+   datanames.push_back("tauxx");
+   datanames.push_back("tauyy");
+   datanames.push_back("tauzz");
+   datanames.push_back("tauxy");
+   datanames.push_back("tauxz");
+   datanames.push_back("tauyz");
+   /*datanames.push_back("xoff");
+   datanames.push_back("yoff");
+   datanames.push_back("zoff");
+   */
+   data.resize(datanames.size());
+
+   int index = 0;
+   data[index++].push_back(istep++);
+   data[index++].push_back(vx1old);
+   data[index++].push_back(vx2old);
+   data[index++].push_back(vx3old);
+   data[index++].push_back(tauxx);
+   data[index++].push_back(tauyy);
+   data[index++].push_back(tauzz);
+   data[index++].push_back(tauxy);
+   data[index++].push_back(tauxz);
+   data[index++].push_back(tauyz);
+   //data[index++].push_back(xoff);
+   //data[index++].push_back(yoff);
+   //data[index++].push_back(zoff);
+
+   nodes.push_back( makeUbTuple(  double(x1), double(x2), double(x3)) );
+
+   //if(scheduler->isDue((double)istep) )
+   if (istep%1 ==0)
+   {
+      string test = writer->writeNodesWithNodeDataDouble(path,nodes,datanames,data);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::clearData()
+{
+   nodes.clear();
+   datanames.clear();
+   data.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::initialMovement(Block3DPtr block, LBMKernelETD3Q27Ptr& kernel, DistributionArray3DPtr& distributions,  BCArray3D<D3Q27BoundaryCondition>& bcArray)
+{
+   //UBLOG(logINFO, "addPostprocessData1");
+   //root = rank;
+
+   double dx = grid->getDeltaX(block);
+   kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   distributions = kernel->getDataSet()->getFdistributions();
+   bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+   x1old=x1;
+   x2old=x2;
+   x3old=x3;
+
+   x1=x1old+vx1old*conv->getFactorTimeLbToW(grid->getDeltaX(block));
+   x2=x2old+vx2old*conv->getFactorTimeLbToW(grid->getDeltaX(block));
+   x3=x3old+vx3old*conv->getFactorTimeLbToW(grid->getDeltaX(block));
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::checkLevel(Block3DPtr& block, LBMKernelETD3Q27Ptr& kernel, DistributionArray3DPtr& distributions,  BCArray3D<D3Q27BoundaryCondition>& bcArray,bool &isPointSuitable2)
+{
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel(); 
+   bool goinside=true;
+   int isPointSuitable=0;//0 means false
+   for(int level = minInitLevel; level<=maxInitLevel; level++)
+   {	      
+      UbTupleInt3 blockIndexes = grid->getBlockIndexes(x1, x2, x3,level);
+      block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+      if(!block) continue; 
+      if(block->isActive()) 
+      {
+         this->root=block->getRank();
+         if(rank == block->getRank())
+         { 
+            if(!checkNodes(block))
+            {		   
+               isPointSuitable=0;//0 meas false
+               if(comm->getNumberOfProcesses() > 1)   {  sendtoOtherIsOk(isPointSuitable);}
+               continue;
+            }  
+            kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+            distributions = kernel->getDataSet()->getFdistributions();
+            bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+            isPointSuitable=1;//0 meas false
+            if(comm->getNumberOfProcesses() > 1)   {  sendtoOtherIsOk(isPointSuitable);}
+            break;
+         }	
+         else
+         {
+            if(comm->getNumberOfProcesses() > 1)  
+            { 
+               MPI_Status status; 
+               MPI_Recv(&isPointSuitable,1, MPI_INT,this->root,this->rank,MPI_COMM_WORLD,&status);
+               if (isPointSuitable)
+               {
+                  break;
+               }
+            }
+         } 
+      }
+   }
+   if (isPointSuitable){isPointSuitable2=true;	} 
+   else isPointSuitable2=false;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::interpolMovement(Block3DPtr block, LBMKernelETD3Q27Ptr& kernel, DistributionArray3DPtr& distributions,  BCArray3D<D3Q27BoundaryCondition>& bcArray, int &isExtrapolation,double tau[])
+{
+   LBMReal tauxx,	   tauyy,	   tauzz,	   tauxy,	   tauxz,	   tauyz;
+   LBMReal vx1,vx2,vx3,rho;
+   UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block, x1, x2, x3);
+   LBMReal dx = grid->getDeltaX(block); 
+   D3Q27ICell iCell;
+   LBMReal f[D3Q27System::ENDF+1];
+   int ix1 = val<1>(nodeIndexes);
+   int ix2 = val<2>(nodeIndexes);
+   int ix3 = val<3>(nodeIndexes);
+   double xoff=0.0; 
+   double yoff=0.0;
+   double zoff=0.0;
+   //typedef void (*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/,LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   /*
+   CalcMacrosFct calcMacros = NULL;
+
+   if(block->getKernel()->getCompressible())
+   {
+   calcMacros = &D3Q27System::calcCompMacroscopicValues;
+   }
+   else
+   {
+   calcMacros = &D3Q27System::calcIncompMacroscopicValues;
+   }*/
+
+   double Ucor=0,Vcor=0,Wcor=0;
+   double tauxxC=00,tauyyC=0,tauzzC=0,tauxyC=0,tauxzC=0,tauyzC=0;
+   double X_Wcor,Y_Wcor,Z_Wcor;
+   double X_Pcor,Y_Pcor,Z_Pcor;
+   double xp000,yp000,zp000;
+   double Xw;
+   double Yw;
+   double Zw;
+
+   UbTupleDouble3 orgNodeRW =  grid->getNodeCoordinates(block,  ix1, ix2, ix3);
+   double ix1p= ( val<1>(orgNodeRW));
+   double ix2p= ( val<2>(orgNodeRW));
+   double ix3p= ( val<3>(orgNodeRW));
+   if(!iProcessor->iCellHasSolid(bcArray, ix1, ix2, ix3))
+   {
+      iProcessor->readICell(distributions, iCell, ix1, ix2, ix3);
+      double x1LB, x2LB, x3LB;
+      UbTupleDouble3 orgNodeRW =  grid->getNodeCoordinates(block,  ix1, ix2, ix3);
+      double offsetX1RW = abs(x1 - val<1>(orgNodeRW));
+      double offsetX2RW = abs(x2 - val<2>(orgNodeRW));
+      double offsetX3RW = abs(x3 - val<3>(orgNodeRW));
+      x1LB = offsetX1RW / dx;
+      x2LB = offsetX2RW / dx;
+      x3LB = offsetX3RW / dx;
+      x1LB -= 0.5-xoff;
+      x2LB -= 0.5-yoff;
+      x3LB -= 0.5-zoff;
+      LBMReal omega = LBMSystem::calcCollisionFactor(nue, block->getLevel());
+      /*iProcessor->interpolate8to1(iCell, f, x1LB, x2LB, x3LB, omega);
+      calcMacros(f,rho,vx1,vx2,vx3);*/
+      //iProcessor->interpolate8to1WithVelocity(iCell, f, x1LB, x2LB, x3LB, omega,vx1,vx2,vx3);
+      iHelper->interpolate8to1WithVelocityWithShearStress(iCell, x1LB, x2LB, x3LB, omega,vx1,vx2,vx3,tauxx,tauyy,tauzz,tauxy,tauxz,tauyz);
+      vx1 = vx1 *  conv->getFactorVelocityLbToW();
+      vx2 = vx2 *  conv->getFactorVelocityLbToW();
+      vx3 = vx3 *  conv->getFactorVelocityLbToW();
+      tau[0]=tauxx/grid->getDeltaX(block);
+      tau[1]=tauyy/grid->getDeltaX(block);
+      tau[2]=tauzz/grid->getDeltaX(block);
+      tau[3]=tauxy/grid->getDeltaX(block);
+      tau[4]=tauxz/grid->getDeltaX(block);
+      tau[5]=tauyz/grid->getDeltaX(block);  
+
+      //if (particleHasMass) {   CalcVelParticle(dx,vx1,vx2,vx3,vx1old,vx2old,vx3old,vx1oldf,vx2oldf,vx3oldf);}
+      if (particleHasMass) {   CalcVelParticle2(dx,vx1,vx2,vx3,vx1old,vx2old,vx3old,vx1oldf,vx2oldf,vx3oldf);}
+      //heuns method
+      x1 = (x1old) + 1.0/2.0*(vx1 + vx1old)*conv->getFactorTimeLbToW(dx);
+      x2 = (x2old) + 1.0/2.0*(vx2 + vx2old)*conv->getFactorTimeLbToW(dx);
+      x3 = (x3old) + 1.0/2.0*(vx3 + vx3old)*conv->getFactorTimeLbToW(dx);
+
+      vx1old = vx1;
+      vx2old = vx2;
+      vx3old = vx3;
+
+      //send isExtrapolation false
+      isExtrapolation=0;//1 means true
+      if(comm->getNumberOfProcesses() > 1)  
+      { 
+         int size=comm->getNumberOfProcesses();
+         for (int i=0;i<size;i++)
+         {
+            if (i!=rank)
+            {
+               MPI_Send(&isExtrapolation,1, MPI_INT,i,i,MPI_COMM_WORLD); 
+            }	
+         }
+      }
+   }
+   else
+   {
+      //send isExtrapolation true
+      isExtrapolation=1;//1 means true
+      if(comm->getNumberOfProcesses() > 1)  
+      { 
+         int size=comm->getNumberOfProcesses();
+         for (int i=0;i<size;i++)
+         {
+            if (i!=rank)
+            {
+               MPI_Send(&isExtrapolation,1, MPI_INT,i,i,MPI_COMM_WORLD); 
+            }	
+         }
+      }
+
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::extrapolMovement(Block3DPtr block, LBMKernelETD3Q27Ptr& kernel, DistributionArray3DPtr& distributions,  BCArray3D<D3Q27BoundaryCondition>& bcArray,double tau[])
+{
+   LBMReal tauxx,	   tauyy,	   tauzz,	   tauxy,	   tauxz,	   tauyz;
+   LBMReal vx1,vx2,vx3,rho;
+   UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block, x1, x2, x3);
+   LBMReal dx = grid->getDeltaX(block);
+   int    level = block->getLevel();
+   double deltaT= 1.0/(double)(1<<level);	 
+   LBMReal omega = LBMSystem::calcCollisionFactor(nue,level);
+   D3Q27ICell iCell;
+   LBMReal f[D3Q27System::ENDF+1];
+   int ix1 = val<1>(nodeIndexes);
+   int ix2 = val<2>(nodeIndexes);
+   int ix3 = val<3>(nodeIndexes);
+   double xoff=0.0; 
+   double yoff=0.0;
+   double zoff=0.0;
+   double Ucor=0,Vcor=0,Wcor=0;
+   double tauxxC=00,tauyyC=0,tauzzC=0,tauxyC=0,tauxzC=0,tauyzC=0;
+   double X_Wcor,Y_Wcor,Z_Wcor;
+   double X_Pcor,Y_Pcor,Z_Pcor;
+   double xp000,yp000,zp000;
+   double Xw=999.0;
+   double Yw=999.0;
+   double Zw=999.0;
+
+   UbTupleDouble3 orgNodeRW =  grid->getNodeCoordinates(block,  ix1, ix2, ix3);
+   double ix1p= ( val<1>(orgNodeRW));
+   double ix2p= ( val<2>(orgNodeRW));
+   double ix3p= ( val<3>(orgNodeRW));
+   {
+      UbTupleDouble3 orgNodeRW =  grid->getNodeCoordinates(block,  ix1, ix2, ix3);
+      double ix1ph = ( val<1>(orgNodeRW));
+      double ix2ph = ( val<2>(orgNodeRW));
+      double ix3ph = ( val<3>(orgNodeRW)); 
+      double cofWeightx=999.0,cofWeighty=999.0,cofWeightz=999.0;
+      double A,B,C,D,ii=0.0;
+      findPlane(ix1,ix2,ix3,grid,block,A,B,C,D,ii);
+      double s = A*x1 + B*x2 + C*x3 + D;//The sign of s = Ax + By + Cz + D determines which side the point (x,y,z) lies with respect to the plane. If s > 0 then the point lies on the same side as the normal (A,B,C). If s < 0 then it lies on the opposite side, if s = 0 then the point (x,y,z) lies on the plane.
+      if (s>0){s=1;} else if (s<0){s=-1;}else {s=0;}
+      double normalDis=((A*x1 + B*x2 + C*x3 + D)/sqrt(A*A+B*B+C*C));///distance point to plane xp-Xw=distance
+      double di=A/sqrt(A*A+B*B+C*C);      double dj=B/sqrt(A*A+B*B+C*C);       double dk=C/sqrt(A*A+B*B+C*C);
+      double XXw=x1-di*normalDis;    double YYw=x2-dj*normalDis;    double ZZw=x3-dk*normalDis;
+      findInitialCell(s,di,dj,dk,dx,ix1ph,ix2ph,ix3ph,xp000,yp000,zp000);//find initial cell with xp000,yp000,zp000
+      /////////////////////////////////////////////////////////////////////////
+      int level=block->getLevel();
+      int Rankx,Ranky,Rankz,Rankxy,Rankxz,Rankyz,Rankxyz;
+      double disx=9990,disy=9990,disz=9990,disxy=9990,disxz=9990,disyz=9990,disxyz=9990; 
+      getAllRankWithAllPositions(ix1ph,ix2ph,ix3ph,xp000,yp000,zp000,Rankx,Ranky,Rankz,Rankxy,Rankxz,Rankyz,Rankxyz,level);
+      //getAllRankWithAllPositions2(ix1ph,ix2ph,ix3ph,xp000,yp000,zp000,Rankx,Ranky,Rankz,Rankxy,Rankxz,Rankyz,Rankxyz);
+
+      int allRank[7]={ Rankx,Ranky,Rankz,Rankxy,Rankxz,Rankyz,Rankxyz};
+      int allTag[7];
+      getAllTag(allRank,allTag);
+      int numberproccessused=0;
+      int numberpro=comm->getNumberOfProcesses();
+      int *mainproccess=new int[numberpro] ; 
+      sendMaxtagToAllProccess(allRank,allTag,numberpro,numberproccessused,mainproccess);
+
+      //{0=xp000, 1=ix2ph,  2=ix3ph,3=x1,4=x2,5=x3,6=Xw,7=Yw,8=Zw,9=A,10=B,11=C,12=D,
+      //13=normalDis,14=di,15=dj,16=dk,17=cofWeightx,18=cofWeighty,19=cofWeightz,,20=dx,21=omega,22=level,23=disx,24=dir  };
+      const int sizeinput=25;
+      double input [7][sizeinput]=
+      {{xp000, ix2ph,  ix3ph,x1,x2,x3,Xw,Yw,Zw,A,B,C,D,normalDis,di,dj,dk,cofWeightx,cofWeighty,cofWeightz,dx,omega,level,disx  ,dirx  }
+      ,{ix1ph, yp000,  ix3ph,x1,x2,x3,Xw,Yw,Zw,A,B,C,D,normalDis,di,dj,dk,cofWeightx,cofWeighty,cofWeightz,dx,omega,level,disy  ,diry  }
+      ,{ix1ph, ix2ph,  zp000,x1,x2,x3,Xw,Yw,Zw,A,B,C,D,normalDis,di,dj,dk,cofWeightx,cofWeighty,cofWeightz,dx,omega,level,disz  ,dirz  }
+      ,{xp000, yp000,  ix3ph,x1,x2,x3,Xw,Yw,Zw,A,B,C,D,normalDis,di,dj,dk,cofWeightx,cofWeighty,cofWeightz,dx,omega,level,disxy ,dirxy }
+      ,{xp000, ix2ph,  zp000,x1,x2,x3,Xw,Yw,Zw,A,B,C,D,normalDis,di,dj,dk,cofWeightx,cofWeighty,cofWeightz,dx,omega,level,disxz ,dirxz }
+      ,{ix1ph, yp000,  zp000,x1,x2,x3,Xw,Yw,Zw,A,B,C,D,normalDis,di,dj,dk,cofWeightx,cofWeighty,cofWeightz,dx,omega,level,disyz ,diryz }
+      ,{xp000, yp000,  zp000,x1,x2,x3,Xw,Yw,Zw,A,B,C,D,normalDis,di,dj,dk,cofWeightx,cofWeighty,cofWeightz,dx,omega,level,disxyz,dirxyz}};
+
+      double AllCell[7][8*27];
+      int index;
+      SendAndReceiveData(input,AllCell,allRank,allTag);
+
+      double dis[7]={input[0][23],input[1][23],input[2][23],input[3][23],input[4][23],input[5][23],input[6][23]};                                                                  
+      rearangedDouble(dis);
+      UbTupleInt3 blockIndexes;
+
+      getAfterCompare(dis,input,AllCell,xp000, yp000,zp000,Xw,Yw,Zw,cofWeightx,cofWeighty,cofWeightz,dx,omega,iCell);
+
+      double x1LB, x2LB, x3LB;
+      double offsetX1RW000 = (x1 - xp000);
+      double offsetX2RW000 = (x2 - yp000);
+      double offsetX3RW000 = (x3 - zp000);
+
+      x1LB = offsetX1RW000 / dx;
+      x2LB = offsetX2RW000 / dx;
+      x3LB = offsetX3RW000 / dx;
+      x1LB -= 0.5;
+      x2LB -= 0.5;
+      x3LB -= 0.5;
+      // outICell(iCell);
+      //iProcessor->interpolate8to1WithVelocity(iCell, f, x1LB, x2LB, x3LB, omega,vx1,vx2,vx3);
+      iHelper->interpolate8to1WithVelocityWithShearStress(iCell, x1LB, x2LB, x3LB, omega,vx1,vx2,vx3,tauxx,tauyy,tauzz,tauxy,tauxz,tauyz);	    
+      addCorrection(vx1,vx2,vx3,tauxx,tauyy,tauzz,tauxy,tauxz,tauyz,dx,iCell,Xw, Yw, Zw, omega,cofWeightx,cofWeighty,cofWeightz,ii, x1LB, x2LB, x3LB,di,dj,dk);
+      tau[0]=tauxx;
+      tau[1]=tauyy;
+      tau[2]=tauzz;
+      tau[3]=tauxy;
+      tau[4]=tauxz;
+      tau[5]=tauyz;
+      // if (particleHasMass) {   CalcVelParticle(dx,vx1,vx2,vx3,vx1old,vx2old,vx3old,vx1oldf,vx2oldf,vx3oldf);}
+      if (particleHasMass) {   CalcVelParticle2(dx,vx1,vx2,vx3,vx1old,vx2old,vx3old,vx1oldf,vx2oldf,vx3oldf);}
+      //heuns method
+      x1 = (x1old) + 1.0/2.0*(vx1 + vx1old)*conv->getFactorTimeLbToW(dx);
+      x2 = (x2old) + 1.0/2.0*(vx2 + vx2old)*conv->getFactorTimeLbToW(dx);
+      x3 = (x3old) + 1.0/2.0*(vx3 + vx3old)*conv->getFactorTimeLbToW(dx);
+      collWall(A,B,C,D,x1,x2,x3,x1old,x2old,x3old,dx,vx1,vx2,vx3,ii);
+      vx1old = vx1;
+      vx2old = vx2;
+      vx3old = vx3;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+bool D3Q27PathLinePostprocessor::checkNodes( Block3DPtr block)
+{
+   bool result = true;
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+   D3Q27BoundaryConditionPtr bcPtr;
+
+   double x1_ch = x1;// + vx1old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+   double x2_ch = x2;// + vx2old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+   double x3_ch = x3;// + vx3old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+
+   int nx1 = static_cast<int>(bcArray.getNX1());
+   int nx2 = static_cast<int>(bcArray.getNX2());
+   int nx3 = static_cast<int>(bcArray.getNX3());
+
+   UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block, x1_ch, x2_ch, x3_ch);
+
+   int ix1 = val<1>(nodeIndexes);
+   int ix2 = val<2>(nodeIndexes);
+   int ix3 = val<3>(nodeIndexes);
+   bool outlet=false;
+
+   for (int xx3 = ix3; xx3 <= ix3 + 1 && ix3 + 1 < nx3; xx3++)
+      for(int xx2 = ix2; xx2 <= ix2 + 1 && ix2 + 1 < nx2; xx2++)
+         for(int xx1 = ix1; xx1 <= ix1 + 1 && ix1 + 1 < nx1; xx1++)
+         {
+            bcPtr=bcArray.getBC(xx1,xx2,xx3);
+            for(int fdir=D3Q27System::STARTF; fdir<=D3Q27System::ENDF; fdir++)
+            {
+               if ( bcPtr != NULL)
+               {
+                  if (bcPtr->hasDensityBoundaryFlag(fdir))
+                  {	
+                     if(outlet)break; 
+                     outlet=true;
+                     break;
+                  }
+               }
+            }
+            result = result && !bcArray.isUndefined(xx1, xx2, xx3) &&  !outlet;
+         }
+
+         return result;
+
+}
+//////////////////////////////////////////////////////////////////////////
+bool D3Q27PathLinePostprocessor::checkNodes2( Block3DPtr block,double x11,double x22,double x33)
+{
+   bool result = true;
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+   D3Q27BoundaryConditionPtr bcPtr;
+
+   double x1_ch = x11;// + vx1old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+   double x2_ch = x22;// + vx2old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+   double x3_ch = x33;// + vx3old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+
+   int nx1 = static_cast<int>(bcArray.getNX1());
+   int nx2 = static_cast<int>(bcArray.getNX2());
+   int nx3 = static_cast<int>(bcArray.getNX3());
+
+   UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block, x1_ch, x2_ch, x3_ch);
+
+   int ix1 = val<1>(nodeIndexes);
+   int ix2 = val<2>(nodeIndexes);
+   int ix3 = val<3>(nodeIndexes);
+   bool outlet=false;
+
+   for (int xx3 = ix3; xx3 <= ix3 + 1 && ix3 + 1 < nx3; xx3++)
+      for(int xx2 = ix2; xx2 <= ix2 + 1 && ix2 + 1 < nx2; xx2++)
+         for(int xx1 = ix1; xx1 <= ix1 + 1 && ix1 + 1 < nx1; xx1++)
+         {
+            bcPtr=bcArray.getBC(xx1,xx2,xx3);
+            for(int fdir=D3Q27System::STARTF; fdir<=D3Q27System::ENDF; fdir++)
+            {
+               if ( bcPtr != NULL)
+               {
+                  if (bcPtr->hasDensityBoundaryFlag(fdir))
+                  {	
+                     if(outlet)break; 
+                     outlet=true;
+                     break;
+                  }
+               }
+            }
+            result = result && !bcArray.isUndefined(xx1, xx2, xx3) &&  !outlet;
+         }
+
+         return result;
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::outICell(D3Q27ICell& iCell)
+{
+   std::ofstream ostr;
+   string fname = path+"_iCell";
+   ostr.open(fname.c_str(), std::ios_base::out);
+   if(!ostr)
+   { 
+      ostr.clear();
+      string path = UbSystem::getPathFromString(fname);
+      if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out);}
+      if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+   }
+   ostr << "step = "<< stepcheck << endl;
+   for (int i = 0; i < 27; i++)
+   {
+      ostr << "iCell.BNE[" << i <<"] = "<< iCell.BNE[i] << "\t"<<"iCell.BNW[" << i <<"] = "<< iCell.BNW[i] << "\t"<<"iCell.BSE[" << i <<"] = "<< iCell.BSE[i]<<"\t"<<"iCell.BSW[" << i <<"] = "<< iCell.BSW[i]<<"\t"<<"iCell.TNE[" << i <<"] = "<< iCell.TNE[i] << "\t"<<"iCell.TNW[" << i <<"] = "<< iCell.TNW[i] << "\t"<<"iCell.TSE[" << i <<"] = "<< iCell.TSE[i]<<"\t"<<"iCell.TSW[" << i <<"] = "<< iCell.TSW[i]<<"\t"<< endl;
+
+   }
+   ostr.close();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::updateDistributedValues()
+{
+   int size;	
+   MPI_Status status; 
+   MPI_Comm_size(MPI_COMM_WORLD,&size);	
+   const int row=12;
+   double values[row];//
+   if (this->root == this->rank)
+   {
+      values[0]=x1;
+      values[1]=x2;
+      values[2]=x3;
+      values[3]=x1old;
+      values[4]=x2old;
+      values[5]=x3old;
+      values[6]=vx1old;
+      values[7]=vx2old;
+      values[8]=vx3old;
+      values[9]=vx1oldf;
+      values[10]=vx2oldf;
+      values[11]=vx3oldf;
+      for (int i=0;i<size;i++)
+      {
+         if (i!=this->root)
+         {
+            MPI_Send(&values,row, MPI_DOUBLE_PRECISION,i,i,MPI_COMM_WORLD);
+         }	
+      }
+   }
+   else{ 
+      MPI_Recv(&values,row, MPI_DOUBLE_PRECISION,this->root,this->rank,MPI_COMM_WORLD,&status);
+      x1     = values[0];
+      x2     = values[1];
+      x3     = values[2];
+      x1old  = values[3];
+      x2old  = values[4];
+      x3old  = values[5];
+      vx1old = values[6];
+      vx2old = values[7];
+      vx3old = values[8];
+      vx1oldf =values[9];
+      vx2oldf=values[10];
+      vx3oldf=values[11];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::findPlane(int ix1,int ix2,int ix3,Grid3DPtr grid,Block3DPtr block,double &A,double &B,double &C,double &D,double &ii)
+{
+   double x1plane=0.0,y1plane=0.0,z1plane=0.0;
+   double x2plane=0.0,y2plane=0.0,z2plane=0.0;
+   double x3plane=0.0,y3plane=0.0,z3plane=0.0;
+   D3Q27BoundaryConditionPtr bcPtr;
+   double dx = grid->getDeltaX(block);
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+   BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+   for (int k = ix3; k <= ix3 + 1; k++){
+      for(int j = ix2; j <= ix2 + 1; j++){
+         for(int i = ix1; i <= ix1 + 1; i++)
+         {
+            UbTupleDouble3 pointplane1 =  grid->getNodeCoordinates(block,  i,	  j,	 k);
+
+            double   iph=val<1>(pointplane1);
+            double   jph=val<2>(pointplane1);
+            double   kph=val<3>(pointplane1);
+
+            if(!bcArray.isSolid(i, j, k))
+            {
+               bcPtr=bcArray.getBC(i,j,k);
+               if(bcPtr)
+               {	 
+                  for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                  {
+                     if( ii<=2)
+                     {
+                        LBMReal q = bcPtr->getQ(fdir);
+                        if (q!=999.00000)
+                        {
+
+                           if     ( fdir==D3Q27System::E ) 
+                           {
+                              if (i+q<=ix1+1)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph+q*dx;	  y1plane=jph;	 z1plane=kph;    	ii++;	} 
+                                 else if (ii==1) 	{	x2plane=iph+q*dx;     y2plane=jph;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if(ii==2) 	    {   x3plane=iph+q*dx;     y3plane=jph;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+                           if     ( fdir==D3Q27System::W ) 
+                           {
+                              if (i-q>=ix1)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph-q*dx;	  y1plane=jph;	 z1plane=kph;    	ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph-q*dx;    y2plane=jph;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if(ii==2) 	    {   x3plane=iph-q*dx;    y3plane=jph;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+                           if     ( fdir==D3Q27System::N ) 
+                           {
+                              if(j+q<=ix2+1)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph;	y1plane=jph+q*dx;	 z1plane=kph; 	    ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph;    y2plane=jph+q*dx;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if (ii==2) 	    {   x3plane=iph;    y3plane=jph+q*dx;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+                           if     ( fdir==D3Q27System::S ) 
+                           {
+                              if (j-q>=ix2)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph;	y1plane=jph-q*dx;	 z1plane=kph; 	ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph;    y2plane=jph-q*dx;	 z2plane=kph;	if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if (ii==2) 	    {   x3plane=iph;    y3plane=jph-q*dx;	 z3plane=kph;   if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+
+                           if     ( fdir==D3Q27System::T ) 
+                           {
+                              if(k+q<=ix3+1)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph;	y1plane=jph;	 z1plane=kph+q*dx; 	    ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph;    y2plane=jph;	 z2plane=kph+q*dx;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if (ii==2) 	    {   x3plane=iph;    y3plane=jph;	 z3plane=kph+q*dx;      if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+                           if     ( fdir==D3Q27System::B ) 
+                           {
+                              if (k-q>=ix3)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph;	y1plane=jph;	 z1plane=kph-q*dx; 	ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph;    y2plane=jph;	 z2plane=kph-q*dx;	  if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if (ii==2) 	    {   x3plane=iph;    y3plane=jph;	 z3plane=kph-q*dx;     if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+
+                        }
+                     }
+                  }
+
+               }
+
+            }
+         }
+      }
+   }
+
+   A =   y1plane* (z2plane - z3plane) + y2plane*(z3plane - z1plane) + y3plane* (z1plane - z2plane);   
+   B =   z1plane* (x2plane - x3plane) + z2plane*(x3plane - x1plane) + z3plane* (x1plane - x2plane) ;      
+   C =   x1plane* (y2plane - y3plane) + x2plane*(y3plane - y1plane) + x3plane* (y1plane - y2plane) ;       
+   D =-( x1plane*(y2plane*z3plane - y3plane*z2plane)+x2plane*(y3plane*z1plane - y1plane*z3plane) + x3plane* (y1plane* z2plane - y2plane* z1plane));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::finddisPointToCentercell(double x1,double x2,double x3,double xp000, double yp000, double zp000,double &dis,double &dx,
+                                                          double &deltaT,Block3DPtr &block,int level)
+{	
+   UbTupleInt3 blockIndexes = grid->getBlockIndexes(xp000, yp000,  zp000,level);
+   block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   if (!kernel)	  cout<<__FILE__<<" "<<__LINE__<<endl;
+   else
+   {
+      DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+      BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+      if(block && block->isActive())
+      {	     		     
+         deltaT= 1.0/(double)(1<<level);
+         dx = grid->getDeltaX(block);
+         UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block,  xp000, yp000,  zp000);
+         int ix1Se = val<1>(nodeIndexes);
+         int ix2Se = val<2>(nodeIndexes);
+         int ix3Se = val<3>(nodeIndexes);  
+         if     (!iProcessor->iCellHasSolid(bcArray, ix1Se, ix2Se,  ix3Se  ))        
+         {				 
+            UbTupleDouble3 pointCell =  grid->getNodeCoordinates(block,  ix1Se,	  ix2Se,	 ix3Se);	 double   iph=val<1>(pointCell)+dx/2.0;	 double   jph=val<2>(pointCell)+dx/2.0;	 double   kph=val<3>(pointCell)+dx/2.0;
+            dis=sqrt((iph-x1)*(iph-x1)+(jph-x2)*(jph-x2)+(kph-x3)*(kph-x3));
+         }
+      }	 	 	
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27PathLinePostprocessor::finddisPointToCentercell(double x1,double x2,double x3,double xp000, double yp000, double zp000,double &dis,double &dx,
+// double &deltaT,Block3DPtr &block)
+//{
+
+// int minInitLevel = this->grid->getCoarsestInitializedLevel();
+// int maxInitLevel = this->grid->getFinestInitializedLevel();
+// bool goinside=true;
+// Block3DPtr block2;
+// for(int level = minInitLevel; level<=maxInitLevel; level++)
+// {	   
+//	 if (goinside )
+//	 {
+//		 UbTupleInt3 blockIndexes = grid->getBlockIndexes(xp000, yp000,  zp000,level);
+//		 block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+//		 LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+//		 if (kernel)
+//		 {
+//			 DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+//			 BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+//			 if(block && block->isActive())
+//			 {	     		     
+//				 if(!checkNodes(block))continue;
+//				 goinside=false;
+//				 deltaT= 1.0/(double)(1<<level);
+//				 dx = grid->getDeltaX(block);
+//				 UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block,  xp000, yp000,  zp000);
+//				 int ix1Se = val<1>(nodeIndexes);
+//				 int ix2Se = val<2>(nodeIndexes);
+//				 int ix3Se = val<3>(nodeIndexes);  
+//				 if     (!iProcessor->iCellHasSolid(bcArray, ix1Se, ix2Se,  ix3Se  ))        
+//				 {				 
+//					 UbTupleDouble3 pointCell =  grid->getNodeCoordinates(block,  ix1Se,	  ix2Se,	 ix3Se);	 double   iph=val<1>(pointCell)+dx/2.0;	 double   jph=val<2>(pointCell)+dx/2.0;	 double   kph=val<3>(pointCell)+dx/2.0;
+//					 dis=sqrt((iph-x1)*(iph-x1)+(jph-x2)*(jph-x2)+(kph-x3)*(kph-x3));
+//					 block2=block;
+//				 }
+//			 }	 	 
+//		 }
+//	 }
+// }
+
+//}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getWallPosition(double input[])
+{ 
+
+   //{0=xp000, 1=ix2ph,  2=ix3ph,3=x1,4=x2,5=x3,6=Xw,7=Yw,8=Zw,9=A,10=B,11=C,12=D,13=normalDis,14=di,15=dj,16=dk,
+   //17=cofWeightx,18=cofWeighty,19=cofWeightz,,20=dx,21=omega,22=nue,23=disx,24=dir  };
+   double dx=input[20];double xp000=input[0];double yp000=input[1];double zp000=input[2];double Xw=input[6];double Yw=input[7];double Zw=input[8];
+   double x1=input[3] ;double x2=input[4] ;double x3=input[5]; double A=input[9];double B=input[10];double C=input[11];double D=input[12];
+   double normalDis=input[13]; double di=input[14];double dj=input[15];double dk=input[16]; double cofWeightx=input[17];double cofWeighty=input[18];
+   double cofWeightz=input[19];int dir=(int)input[24];
+
+   //char dirx,diry,dirz,dirxy,dirxz,diryz,dirxyz;
+   if      (dir==dirx  )  {  Xw=(B*x2+C*x3+D)/(-A); Yw=x2;                 Zw=x3;	         	      cofWeightx=1;  cofWeighty=0;cofWeightz=0;}     
+   else if (dir==diry  )  {  Xw=x1;                 Yw=(A*x1+C*x3+D)/(-B); Zw=x3;		              cofWeightx=0;  cofWeighty=1;cofWeightz=0;}
+   else if (dir==dirz  )  {  Xw=x1;                 Yw=x3;	             Zw=(B*x2+A*x1+D)/(-C);   cofWeightx=0;  cofWeighty=0;cofWeightz=1;    }
+   else if (dir==dirxy )  {  Xw=x1-di*normalDis;    Yw=x2-dj*normalDis;    Zw=x3;        		      cofWeightx=1;  cofWeighty=1;cofWeightz=0;}
+   else if (dir==dirxz )  {  Xw=x1-di*normalDis;    Yw=x2;                 Zw=x3-dk*normalDis;	  cofWeightx=1;  cofWeighty=0;cofWeightz=1;    }
+   else if (dir==diryz )  {  Xw=x1;                 Yw=x2-dj*normalDis;    Zw=x3-dk*normalDis;	  cofWeightx=0;  cofWeighty=1;cofWeightz=1;    }
+   else if (dir==dirxyz)  {  Xw=x1-di*normalDis;    Yw=x2-dj*normalDis;    Zw=x3-dk*normalDis;	  cofWeightx=1;  cofWeighty=1;cofWeightz=1;    }  
+
+   Xw=(Xw-xp000)/dx-0.5;       
+   Yw=(Yw-yp000)/dx-0.5;       
+   Zw=(Zw-zp000)/dx-0.5; 
+
+   input[6]=Xw;
+   input[7]=Yw;
+   input[8]=Zw;
+   input[17]=cofWeightx;
+   input[18]=cofWeighty;
+   input[19]=cofWeightz;
+
+}
+////////////////////////////////////////////////////////////////////////////
+// void D3Q27PathLinePostprocessor::getWallPosition(double dixmax,double disx,double disy,double disz,double disxy,double disxz,double disyz,double disxyz
+//  ,double &Xw,double &Yw,double &Zw,double x1,double x2,double x3,double A,double B,double C,double D,double normalDis,double di,double dj,double dk,
+//  double &cofWeightx,double &cofWeighty,double &cofWeightz)
+// {
+//  if      (dixmax==disx)  {  Xw=(B*x2+C*x3+D)/(-A); Yw=x2;                 Zw=x3;	         	  cofWeightx=1;  cofWeighty=0;cofWeightz=0;}     
+//  else if (dixmax==disy)  {  Xw=x1;                 Yw=(A*x1+C*x3+D)/(-B); Zw=x3;		          cofWeightx=0;  cofWeighty=1;cofWeightz=0;}
+//  else if (dixmax==disz)  {  Xw=x1;                 Yw=x3;	               Zw=(B*x2+A*x1+D)/(-C); cofWeightx=0;  cofWeighty=0;cofWeightz=1;}
+//  else if (dixmax==disxy) {  Xw=x1-di*normalDis;    Yw=x2-dj*normalDis;    Zw=x3;        		  cofWeightx=1;  cofWeighty=1;cofWeightz=0;}
+//  else if (dixmax==disxz) {  Xw=x1-di*normalDis;    Yw=x2;                 Zw=x3-dk*normalDis;	  cofWeightx=1;  cofWeighty=0;cofWeightz=1;}
+//  else if (dixmax==disyz) {  Xw=x1;                 Yw=x2-dj*normalDis;    Zw=x3-dk*normalDis;	  cofWeightx=0;  cofWeighty=1;cofWeightz=1;}
+//  else if (dixmax==disxyz){  Xw=x1-di*normalDis;    Yw=x2-dj*normalDis;    Zw=x3-dk*normalDis;	  cofWeightx=1;  cofWeighty=1;cofWeightz=1;}
+// }
+////////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::findInitialCell(double s,double di,double dj,double dk,double dx,double ix1ph,double ix2ph,double ix3ph,double &xp000,double &yp000,double &zp000)
+{
+   if (s*di>0)         {            xp000=ix1ph+dx;    }
+   else if(s*di<0)     {            xp000=ix1ph-dx;    }
+   else                {            xp000=ix1ph;      }
+   if (s*dj>0)         {            yp000=ix2ph+dx;    }
+   else if(s*dj<0)     {            yp000=ix2ph-dx;    }
+   else                {            yp000=ix2ph;      }
+   if (s*dk>0)         {            zp000=ix3ph+dx;    }
+   else if(s*dk<0)     {            zp000=ix3ph-dx;    }
+   else                {            zp000=ix3ph;      }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::rearangedDouble( double dis[7])
+{
+   double item;
+   for (int i=6;i>0;i--){   
+      for(int j=0;j<i;j++){ 
+         if (dis[j]>dis[j+1])
+         {	  
+            item=dis[j];  
+            dis[j]=dis[j+1]; 
+            dis[j+1]=item;					   
+         }
+      }
+   } 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::rearangeInt( int dis[7])
+{
+   double item;
+   for (int i=6;i>0;i--){   
+      for(int j=0;j<i;j++){ 
+         if (dis[j]>dis[j+1])
+         {	  
+            item=dis[j];  
+            dis[j]=dis[j+1]; 
+            dis[j+1]=(int)item;					   
+         }
+      }
+   } 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::addCorrection(double &vx1,double &vx2,double &vx3,double &tauxx,double &tauyy,double &tauzz,double &tauxy,double &tauxz,double &tauyz,
+                                               double dx,D3Q27ICell iCell,double Xw, double Yw, double Zw,double  omega,double cofWeightx,double cofWeighty,double cofWeightz,double ii,double x1LB,double x2LB,double x3LB,double di,double dj,double dk)
+{
+   LBMReal f[D3Q27System::ENDF+1];
+   double  Udif,Vdif,Wdif;	  
+   iHelper->interpolate8to1WithVelocity(iCell, Xw, Yw, Zw, omega,Udif,Vdif,Wdif);
+   double Ucx,Ucy,Ucz;
+   double Vcx,Vcy,Vcz;
+   double Wcx,Wcy,Wcz;
+
+   double dxUcx,dyUcy,dzUcz;
+   double dxVcx,dyVcy,dzVcz;
+   double dxWcx,dyWcy,dzWcz;
+   //double di,dj,dk;
+
+   if (cofWeightx==0){di=0;}
+   if (cofWeighty==0){dj=0;}
+   if (cofWeightz==0){dk=0;}
+
+   double weightx=(di*di)/(di*di+dj*dj+dk*dk);
+   double weighty=(dj*dj)/(di*di+dj*dj+dk*dk);
+   double weightz=(dk*dk)/(di*di+dj*dj+dk*dk);
+   // /* if (Xw<0.5||Xw>-0.5){weightx=0;}
+   //  if (Yw<0.5||Yw>-0.5){weighty=0;}
+   //  if (Zw<0.5||Zw>-0.5){weightz=0;}
+   //*/
+   if (weightx==0){Ucx=0;Vcx=0;Wcx=0;dxUcx=0;dxVcx=0;dxWcx=0;}else{
+      Ucx=-Udif*weightx/(Xw*Xw*Xw-Xw/4.0)*(x1LB*x1LB*x1LB-x1LB/4.0);Vcx=-Vdif*weightx/(Xw*Xw*Xw-Xw/4.0)*(x1LB*x1LB*x1LB-x1LB/4.0);Wcx=-Wdif*weightx/(Xw*Xw*Xw-Xw/4.0)*(x1LB*x1LB*x1LB-x1LB/4.0);
+      dxUcx=-Udif*weightx/(Xw*Xw*Xw-Xw/4.0)*(3.0*x1LB*x1LB-1.0/4.0);dxVcx=-Vdif*weightx/(Xw*Xw*Xw-Xw/4.0)*(3.0*x1LB*x1LB-1.0/4.0);dxWcx=-Wdif*weightx/(Xw*Xw*Xw-Xw/4.0)*(3.0*x1LB*x1LB-1.0/4.0);
+   }
+   if (weighty==0){Ucy=0;Vcy=0;Wcy=0;dyUcy=0;dyVcy=0;dyWcy=0;}else{
+      Ucy=-Udif*weighty/(Yw*Yw*Yw-Yw/4.0)*(x2LB*x2LB*x2LB-x2LB/4.0);Vcy=-Vdif*weighty/(Yw*Yw*Yw-Yw/4.0)*(x2LB*x2LB*x2LB-x2LB/4.0);Wcy=-Wdif*weighty/(Yw*Yw*Yw-Yw/4.0)*(x2LB*x2LB*x2LB-x2LB/4.0);
+      dyUcy=-Udif*weighty/(Yw*Yw*Yw-Yw/4.0)*(3.0*x2LB*x2LB-1.0/4.0);dyVcy=-Vdif*weighty/(Yw*Yw*Yw-Yw/4.0)*(3.0*x2LB*x2LB-1.0/4.0);dyWcy=-Wdif*weighty/(Yw*Yw*Yw-Yw/4.0)*(3.0*x2LB*x2LB-1.0/4.0);
+   }
+   if (weightz==0){Ucz=0;Vcz=0;Wcz=0;dzUcz=0;dzVcz=0;dzWcz=0;}else{
+      Ucz=-Udif*weightz/(Zw*Zw*Zw-Zw/4.0)*(x3LB*x3LB*x3LB-x3LB/4.0);Vcz=-Vdif*weightz/(Zw*Zw*Zw-Zw/4.0)*(x3LB*x3LB*x3LB-x3LB/4.0);Wcz=-Wdif*weightz/(Zw*Zw*Zw-Zw/4.0)*(x3LB*x3LB*x3LB-x3LB/4.0);
+      dzUcz=-Udif*weightz/(Zw*Zw*Zw-Zw/4.0)*(3.0*x3LB*x3LB-1.0/4.0);dzVcz=-Vdif*weightz/(Zw*Zw*Zw-Zw/4.0)*(3.0*x3LB*x3LB-1.0/4.0);dzWcz=-Wdif*weightz/(Zw*Zw*Zw-Zw/4.0)*(3.0*x3LB*x3LB-1.0/4.0);
+   }
+
+   double Ucor=Ucx+Ucy+Ucz;
+   double Vcor=Vcx+Vcy+Vcz;
+   double Wcor=Wcx+Wcy+Wcz;
+
+   double tauxxC=dxUcx;
+   double tauyyC=dyVcy;
+   double tauzzC=dzWcz;
+   double tauxyC=0.5*(dyUcy+dxVcx);
+   double tauxzC=0.5*(dzUcz+dxWcx);
+   double tauyzC=0.5*(dzVcz+dyWcy);
+
+   if (ii!=3) 
+   {
+      //std::cout<<"there are not 3point for making plane"<<endl<<"Ucor="<<Ucor<<endl<<"vx1="<<vx1;
+      Ucor  =0.0;
+      Vcor  =0.0;
+      Wcor  =0.0;
+      tauxxC=0.0;
+      tauyyC=0.0;
+      tauzzC=0.0;
+      tauxyC=0.0;
+      tauxzC=0.0;
+      tauyzC=0.0;
+   }
+
+   vx1+=Ucor;
+   vx2+=Vcor;
+   vx3+=Wcor;
+   tauxx+=tauxxC;
+   tauyy+=tauyyC;
+   tauzz+=tauzzC;
+   tauxy+=tauxyC;
+   tauxz+=tauxzC;
+   tauyz+=tauyzC;
+
+   vx1 = vx1 *  conv->getFactorVelocityLbToW();
+   vx2 = vx2 *  conv->getFactorVelocityLbToW();
+   vx3 = vx3 *  conv->getFactorVelocityLbToW();
+   tauxx=tauxx/dx;
+   tauyy=tauyy/dx;
+   tauzz=tauzz/dx;
+   tauxy=tauxy/dx;
+   tauxz=tauxz/dx;
+   tauyz=tauyz/dx;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::collWall(double A,double B,double C,double D,double &x1,double &x2,double &x3,double x1old,double x2old,double x3old,double dx,double &vx1,double &vx2,double &vx3,double ii)
+{
+   if (particleHasMass)
+   {
+      double s = A*x1 + B*x2 + C*x3 + D;//The sign of s = Ax + By + Cz + D determines which side the point (x,y,z) lies with respect to the plane. If s > 0 then the point lies on the same side as the normal (A,B,C). If s < 0 then it lies on the opposite side, if s = 0 then the point (x,y,z) lies on the plane.
+      if (s>0){s=1;} else if (s<0){s=-1;}else {s=0;}
+      double normalDis=((A*x1 + B*x2 + C*x3 + D)/sqrt(A*A+B*B+C*C));///distance point to plane xp-Xw=distance
+      double di=A/sqrt(A*A+B*B+C*C);      double dj=B/sqrt(A*A+B*B+C*C);       double dk=C/sqrt(A*A+B*B+C*C);
+      A*=s;B*=s;C*=s;
+      if (abs(normalDis)<0.05*dx)
+      {
+         if (ii==3)
+         {
+            ///reflection without e factor
+            /*  double vn=(A*vx1 + B*vx2 + C*vx3)/(A*A+B*B+C*C);
+            double  vx1L=vx1-2*vn*A;
+            double  vx2L=vx2-2*vn*B;
+            double  vx3L=vx3-2*vn*C;*/
+            double vnx=A*(A*vx1 + B*vx2 + C*vx3)/(A*A+B*B+C*C);
+            double vny=B*(A*vx1 + B*vx2 + C*vx3)/(A*A+B*B+C*C);
+            double vnz=C*(A*vx1 + B*vx2 + C*vx3)/(A*A+B*B+C*C);
+            ////do collision  
+            double CollitionFactor_n=0.01;
+            double CollitionFactor_bt=0.01;
+            vnx=-1*CollitionFactor_n*vnx;
+            vny=-1*CollitionFactor_n*vny;
+            vnz=-1*CollitionFactor_n*vnz;
+            double vbtx=(B*B*vx1 + C*C*vx1 - A*B*vx2 - A*C*vx3)/(A*A+B*B+C*C);
+            double vbty=(-(A*B*vx1) + A*A*vx2 + C*C*vx2 - B*C*vx3)/(A*A+B*B+C*C);
+            double vbtz=(-(A*C*vx1) - B*C*vx2 + A*A*vx3 + B*B*vx3)/(A*A+B*B+C*C);
+            vbtx=vbtx*CollitionFactor_bt;
+            vbty=vbty*CollitionFactor_bt;
+            vbtz=vbtz*CollitionFactor_bt;
+            vx1=vnx+vbtx;
+            vx2=vny+vbty;
+            vx3=vnz+vbtz;
+
+            x1 = (x1old);
+            x2 = (x2old);
+            x3 = (x3old);
+         } 
+         else   std::cout<<"there is no plane to reflect";
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::CalcVelParticle(double dx,double &vx1,double &vx2,double &vx3,double vx1old,double vx2old,
+                                                 double vx3old,double &vx1oldf,double &vx2oldf,double &vx3oldf)
+{
+   double signDragx,signDragy,signDragz;
+   double dragCoff=1.0;
+   if     (vx1old>=vx1oldf)    {  signDragx=-1.0;   } 
+   else if(vx1old<vx1oldf)     {  signDragx= 1.0;    }
+   if     (vx2old>=vx2oldf)    {  signDragy=-1.0;   } 
+   else if(vx2old< vx2oldf)    {  signDragy= 1.0;    }
+   if     (vx3old>=vx3oldf)    {  signDragz=-1.0;   } 
+   else if(vx3old< vx3oldf)    {  signDragz= 1.0;    }
+   double vx1p=vx1old+signDragx*(vx1old-vx1oldf)*(vx1old-vx1oldf)*conv->getFactorTimeLbToW(dx);
+   double vx2p=vx2old+signDragy*(vx2old-vx2oldf)*(vx2old-vx2oldf)*conv->getFactorTimeLbToW(dx);
+   double vx3p=vx3old+signDragz*(vx3old-vx3oldf)*(vx3old-vx3oldf)*conv->getFactorTimeLbToW(dx);   
+
+   double signDragNextx,signDragNexty,signDragNextz;
+   if     (vx1p>=vx1)    {  signDragNextx=-1.0;   } 
+   else if(vx1p< vx1)    {  signDragNextx= 1.0;    }
+   if     (vx2p>=vx2)    {  signDragNexty=-1.0;   } 
+   else if(vx2p< vx2)    {  signDragNexty= 1.0;    }
+   if     (vx3p>=vx3)    {  signDragNextz=-1.0;   } 
+   else if(vx3p< vx3)    {  signDragNextz= 1.0;    }
+   ////////////////////velocity of particle////////////////////////////////////////////////////// 
+   double velx1oldf=vx1;
+   double velx2oldf=vx2;
+   double velx3oldf=vx3;
+
+   vx1=vx1old+1.0/2.0*( signDragNextx*(vx1p-vx1)*(vx1p-vx1)+signDragx*(vx1old-vx1oldf)*(vx1old-vx1oldf) )*conv->getFactorTimeLbToW(dx);
+   vx2=vx2old+1.0/2.0*( signDragNexty*(vx2p-vx2)*(vx2p-vx2)+signDragy*(vx2old-vx2oldf)*(vx2old-vx2oldf) )*conv->getFactorTimeLbToW(dx);
+   vx3=vx3old+1.0/2.0*( signDragNextz*(vx3p-vx3)*(vx3p-vx3)+signDragz*(vx3old-vx3oldf)*(vx3old-vx3oldf) )*conv->getFactorTimeLbToW(dx);
+
+   vx1oldf=velx1oldf;
+   vx2oldf=velx2oldf;
+   vx3oldf=velx3oldf;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::CalcVelParticle2(double dx,double &vx1,double &vx2,double &vx3,double vx1old,double vx2old,
+                                                  double vx3old,double &vx1oldf,double &vx2oldf,double &vx3oldf)
+{
+   double signDragx,signDragy,signDragz;
+
+   LBMReal muRE = 1.002*1e-3;//m2/s
+   double mass=2.3*1e-17;// kg
+   double Diameter=600*1e-9;//m
+   double deltatime=conv->getFactorTimeLbToW(dx)*0.001;
+   double Coff=3*PI*Diameter*muRE*deltatime/mass;
+   double exCoff=exp(-Coff);
+
+
+   //////////////////////velocity of particle////////////////////////////////////////////////////// 
+   double velx1oldf=vx1;
+   double velx2oldf=vx2;
+   double velx3oldf=vx3;
+
+   //air
+
+   vx1=vx1old*exCoff+(velx1oldf-(velx1oldf)*exCoff);
+   vx2=vx2old*exCoff+(velx2oldf-(velx2oldf)*exCoff);
+   vx3=vx3old*exCoff+(velx3oldf-(velx3oldf)*exCoff);
+
+
+   vx1oldf=velx1oldf;
+   vx2oldf=velx2oldf;
+   vx3oldf=velx3oldf;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getRankWithPosition(Grid3DPtr grid,double xp000, double yp000, double zp000,int &RankNeigber,int level)
+{
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+   bool goinside=true;
+
+   LBMKernelETD3Q27Ptr kernel;
+   DistributionArray3DPtr distributions;
+   BCArray3D<D3Q27BoundaryCondition> bcArray;
+   Block3DPtr block;
+
+   //for(int level = minInitLevel; level<=maxInitLevel; level++)
+   {	   
+      UbTupleInt3 blockIndexes = grid->getBlockIndexes(xp000,yp000, zp000,level);
+      block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+      //LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+      // if(block )
+      {
+         if(block->isActive())
+         {	     		     
+            // if(!checkNodes2(block,xp000,yp000,zp000))continue;
+            RankNeigber= block->getRank();   
+            //break;
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getRankWithPosition2(Grid3DPtr grid,double xp000, double yp000, double zp000,int &RankNeigber)
+{
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+   bool goinside=true;
+
+   LBMKernelETD3Q27Ptr kernel;
+   DistributionArray3DPtr distributions;
+   BCArray3D<D3Q27BoundaryCondition> bcArray;
+   Block3DPtr block;
+
+   for(int level = minInitLevel; level<=maxInitLevel; level++)
+   {	   
+      UbTupleInt3 blockIndexes = grid->getBlockIndexes(xp000,yp000, zp000,level);
+      block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+      LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+      // if(kernel )
+      {
+         if(block->isActive())
+         {	     		     
+            // if(!checkNodes2(block,xp000,yp000,zp000))continue;
+            RankNeigber= block->getRank();   
+            break;
+         }
+      }
+   }
+}
+
+
+////////////////////////////////////////////////////////////////////////// 
+void D3Q27PathLinePostprocessor::getAllTag(int allRank[7],int allTag[7])
+{
+
+   for (int i=0;i<7;i++)
+   {
+      int tagme=0;
+      for (int j=0;j<=i;j++)
+      {
+         if(allRank[j]==allRank[i])
+         {
+            tagme++;
+         }
+         allTag[i]=tagme;
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getAllInfoForCompare(double input[],double *Vect)
+{
+   //{0=xp000, 1=ix2ph,  2=ix3ph,3=x1,4=x2,5=x3,6=Xw,7=Yw,8=Zw,9=A,10=B,11=C,12=D,13=normalDis,14=di,15=dj,16=dk,
+   //17=cofWeightx,18=cofWeighty,19=cofWeightz,,20=dx,21=omega,22=level,23=disx,24=dir  };
+
+   double deltaT;
+   Block3DPtr block;
+   finddisPointToCentercell(input[3],input[4],input[5],input[0],input[1],input[2],input[23],input[20],deltaT,block,(int)input[22]);//get double &dis,double &dx,double &deltaT
+   getWallPosition(input);	 //get wall position,Xw,Yw,Zw and cofWeightx,cofWeighty,cofWeightz	   
+
+   double xp000=input[0];
+   double yp000=input[1];
+   double zp000=input[2]; 
+   // double nue=input[22];
+   LBMReal omega = LBMSystem::calcCollisionFactor(nue,block->getLevel());
+   input[21]=omega;
+   UbTupleInt3 nodeIndexes000 = grid->getNodeIndexes(block,  xp000, yp000,  zp000);
+   double xp000id = val<1>(nodeIndexes000);
+   double yp000id = val<2>(nodeIndexes000);
+   double zp000id = val<3>(nodeIndexes000);
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   if (kernel)
+   {
+      DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+      D3Q27ICell iCell;
+      iProcessor->readICell(distributions, iCell, (int)xp000id, (int)yp000id, (int)zp000id);
+      getVectfromiCell(iCell,Vect);
+   } 
+   else
+   {
+      cout<<__FILE__<<" "<<__LINE__<<endl;
+      for (int k=0;k<8*27;k++)       {  Vect[k]=999.0;   	  }
+   }
+
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::sendMaxtagToAllProccess(int allRank[],int allTag[],int numberpro,int &numberproccessused,int *mainproccess)
+{
+
+   int allRank_[7];
+   for (int i=0;i<7;i++)
+   {
+      allRank_[i]=allRank[i];
+   }
+   rearangeInt(allRank_);
+
+   for (int i=0;i<7;i++)
+   {
+      int maxtag_=0;
+      if (i==6)
+      {
+         if (allRank_[i]!=this->root)
+         {			   
+            for (int k=0;k<=i;k++)
+            {
+               if (allRank_[i]==allRank_[k])
+               {
+                  maxtag_++;
+               }
+            }
+            MPI_Send(&maxtag_,1, MPI_INT,allRank_[i],i,MPI_COMM_WORLD);
+         }
+         numberproccessused++;
+         mainproccess[numberproccessused-1]=allRank_[i];
+      } 
+      else 
+      {		
+         if(allRank_[i]!=allRank_[i+1])			   
+         {				   
+            if (allRank_[i]!=this->root)
+            { 
+               for (int k=0;k<=i;k++)
+               {
+                  if (allRank_[i]==allRank_[k])
+                  {
+                     maxtag_++;
+                  }
+               }
+               MPI_Send(&maxtag_,1, MPI_INT,allRank_[i],i,MPI_COMM_WORLD);  
+            }
+            numberproccessused++;
+            mainproccess[numberproccessused-1]=allRank_[i];
+         }   
+      }
+   }
+   for (int i=0;i<numberpro;i++)
+   {
+      bool goinside=true;
+      for (int j=0;j<numberproccessused;j++)
+      {
+         if (i==mainproccess[j]){goinside=false;break;}
+      }
+      if(goinside)
+      {
+         int maxtag_=0;
+         if (i!=this->root)
+         {
+            MPI_Send(&maxtag_,1, MPI_INT,i,i,MPI_COMM_WORLD);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getAllRankWithAllPositions(double ix1ph,double ix2ph,double ix3ph,double xp000,double yp000,double zp000,
+                                                            int &Rankx,int &Ranky,int &Rankz,int &Rankxy,int &Rankxz,int &Rankyz,int &Rankxyz,int level)
+{
+
+   getRankWithPosition(grid,xp000, ix2ph,  ix3ph,Rankx  ,level);
+   getRankWithPosition(grid,ix1ph, yp000,  ix3ph,Ranky  ,level);
+   getRankWithPosition(grid,ix1ph, ix2ph,  zp000,Rankz  ,level);
+   getRankWithPosition(grid,xp000, yp000,  ix3ph,Rankxy ,level);
+   getRankWithPosition(grid,xp000, ix2ph,  zp000,Rankxz ,level);
+   getRankWithPosition(grid,ix1ph, yp000,  zp000,Rankyz ,level);
+   getRankWithPosition(grid,xp000, yp000,  zp000,Rankxyz,level);  	
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getAllRankWithAllPositions2(double ix1ph,double ix2ph,double ix3ph,double xp000,double yp000,double zp000,
+                                                             int &Rankx,int &Ranky,int &Rankz,int &Rankxy,int &Rankxz,int &Rankyz,int &Rankxyz)
+{
+
+   getRankWithPosition2(grid,xp000, ix2ph,  ix3ph,Rankx  );
+   getRankWithPosition2(grid,ix1ph, yp000,  ix3ph,Ranky  );
+   getRankWithPosition2(grid,ix1ph, ix2ph,  zp000,Rankz  );
+   getRankWithPosition2(grid,xp000, yp000,  ix3ph,Rankxy );
+   getRankWithPosition2(grid,xp000, ix2ph,  zp000,Rankxz );
+   getRankWithPosition2(grid,ix1ph, yp000,  zp000,Rankyz );
+   getRankWithPosition2(grid,xp000, yp000,  zp000,Rankxyz);  	
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getVectfromiCell(D3Q27ICell iCell,double *Vect)
+{
+
+   for (int i=0*27;i<1*27;i++)         {   Vect[i]=iCell.TSW[i-0*27];   }
+   for (int i=1*27;i<2*27;i++)		   {   Vect[i]=iCell.TNW[i-1*27];   }
+   for (int i=2*27;i<3*27;i++)		   {   Vect[i]=iCell.TNE[i-2*27];   }
+   for (int i=3*27;i<4*27;i++)         {   Vect[i]=iCell.TSE[i-3*27];   }
+   for (int i=4*27;i<5*27;i++)		   {   Vect[i]=iCell.BSW[i-4*27];   }
+   for (int i=5*27;i<6*27;i++)		   {   Vect[i]=iCell.BNW[i-5*27];   }
+   for (int i=6*27;i<7*27;i++)		   {   Vect[i]=iCell.BNE[i-6*27];   }
+   for (int i=7*27;i<8*27;i++)		   {   Vect[i]=iCell.BSE[i-7*27];   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getiCellfromVect(D3Q27ICell &iCell,double *Vect)
+{
+
+   for (int i=0*27;i<1*27;i++)         {   iCell.TSW[i-0*27]=Vect[i];   }
+   for (int i=1*27;i<2*27;i++)		   {   iCell.TNW[i-1*27]=Vect[i];   }
+   for (int i=2*27;i<3*27;i++)		   {   iCell.TNE[i-2*27]=Vect[i];   }
+   for (int i=3*27;i<4*27;i++)         {   iCell.TSE[i-3*27]=Vect[i];   }
+   for (int i=4*27;i<5*27;i++)		   {   iCell.BSW[i-4*27]=Vect[i];   }
+   for (int i=5*27;i<6*27;i++)		   {   iCell.BNW[i-5*27]=Vect[i];   }
+   for (int i=6*27;i<7*27;i++)		   {   iCell.BNE[i-6*27]=Vect[i];   }
+   for (int i=7*27;i<8*27;i++)		   {   iCell.BSE[i-7*27]=Vect[i];   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::getAfterCompare(double dis[],double input [7][25],double AllCell[7][8*27],double &xp000,double &yp000,double &zp000,
+                                                 double &Xw,double &Yw,double &Zw,double &cofWeightx,double &cofWeighty,double &cofWeightz,double &dx,double &omega,D3Q27ICell &iCell)
+{
+
+   double *Cell=(double*)malloc(8*27*sizeof(double));   	   
+   bool goinside=true;
+
+   for (int i=0;i<7;i++)
+   {	
+      double dist=dis[i];
+      if(goinside )
+      {  //17=cofWeightx,18=cofWeighty,19=cofWeightz,,20=dx,21=omega
+         if      (dist==input[0][23]){  Xw=input[0][6];	Yw=input[0][7]; Zw=input[0][8]; xp000=input[0][0];	yp000=input[0][1]; zp000=input[0][2];  cofWeightx=input[0][17];	cofWeighty=input[0][18]; cofWeightz=input[0][19]; dx=input[0][20];	omega=input[0][21]; for (int i=0;i<8*27;i++){Cell[i]=AllCell[0][i];} } //get suitable block from suitable cell
+         else if (dist==input[1][23]){  Xw=input[1][6];	Yw=input[1][7]; Zw=input[1][8]; xp000=input[1][0];	yp000=input[1][1]; zp000=input[1][2];  cofWeightx=input[1][17];	cofWeighty=input[1][18]; cofWeightz=input[1][19]; dx=input[1][20];	omega=input[1][21]; for (int i=0;i<8*27;i++){Cell[i]=AllCell[1][i];} }
+         else if (dist==input[2][23]){  Xw=input[2][6];	Yw=input[2][7]; Zw=input[2][8]; xp000=input[2][0];	yp000=input[2][1]; zp000=input[2][2];  cofWeightx=input[2][17];	cofWeighty=input[2][18]; cofWeightz=input[2][19]; dx=input[2][20];	omega=input[2][21]; for (int i=0;i<8*27;i++){Cell[i]=AllCell[2][i];} }
+         else if (dist==input[3][23]){  Xw=input[3][6];   Yw=input[3][7]; Zw=input[3][8]; xp000=input[3][0];  yp000=input[3][1]; zp000=input[3][2];  cofWeightx=input[3][17]; cofWeighty=input[3][18]; cofWeightz=input[3][19]; dx=input[3][20];  omega=input[3][21]; for (int i=0;i<8*27;i++){Cell[i]=AllCell[3][i];} }
+         else if (dist==input[4][23]){  Xw=input[4][6];	Yw=input[4][7]; Zw=input[4][8]; xp000=input[4][0];	yp000=input[4][1]; zp000=input[4][2];  cofWeightx=input[4][17];	cofWeighty=input[4][18]; cofWeightz=input[4][19]; dx=input[4][20];	omega=input[4][21]; for (int i=0;i<8*27;i++){Cell[i]=AllCell[4][i];} }
+         else if (dist==input[5][23]){  Xw=input[5][6];	Yw=input[5][7]; Zw=input[5][8]; xp000=input[5][0];	yp000=input[5][1]; zp000=input[5][2];  cofWeightx=input[5][17];	cofWeighty=input[5][18]; cofWeightz=input[5][19]; dx=input[5][20];	omega=input[5][21]; for (int i=0;i<8*27;i++){Cell[i]=AllCell[5][i];} }
+         else if (dist==input[6][23]){  Xw=input[6][6];	Yw=input[6][7]; Zw=input[6][8]; xp000=input[6][0];	yp000=input[6][1]; zp000=input[6][2];  cofWeightx=input[6][17];	cofWeighty=input[6][18]; cofWeightz=input[6][19]; dx=input[6][20];	omega=input[6][21]; for (int i=0;i<8*27;i++){Cell[i]=AllCell[6][i];} }
+         if (Xw<2.5&&Xw>-2.5&&Yw<2.50&&Yw>-2.50&&Zw<2.50&&Zw>-2.50){goinside=false;}      
+      }
+   }
+
+   getiCellfromVect(iCell,Cell);
+   free (Cell);
+}
+
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::SendAndReceiveData(double input[7][25],double AllCell[7][8*27],int allRank[7],int allTag[7])
+{
+
+   int sizeinput =25;
+   double *Cell=(double*)malloc(8*27*sizeof(double));	
+
+
+   for (int i=0;i<7;i++)
+   {
+      if (allRank[i]==this->root)
+      {
+         double vectforTrans[25];
+         for (int j=0;j<sizeinput;j++)
+         {
+            vectforTrans[j]=input[i][j];
+         }
+         getAllInfoForCompare(vectforTrans,Cell);
+         int index=(int)vectforTrans[24];
+         for (int k=0;k<8*27;k++)
+         {
+            AllCell[index][k]=Cell[k];
+         }
+         for (int j=0;j<sizeinput;j++)
+         {
+            input[index][j]=vectforTrans[j];
+         }
+      }
+      else
+      {
+         double vectforTrans[25];
+         for (int j=0;j<sizeinput;j++)
+         {
+            vectforTrans[j]=input[i][j];
+         }
+         MPI_Send(vectforTrans,sizeinput, MPI_DOUBLE_PRECISION,allRank[i],allTag[i],MPI_COMM_WORLD);
+      }
+   }
+   for (int i=0;i<7;i++)
+   {
+      if (allRank[i]!=this->root)
+      {
+         MPI_Status status; 
+         double receiveVector[25];
+         double *receiceCell=(double*)malloc(8*27*sizeof(double));
+         MPI_Recv(receiveVector,25, MPI_DOUBLE_PRECISION,allRank[i],MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+         MPI_Recv(receiceCell,8*27, MPI_DOUBLE_PRECISION,allRank[i],MPI_ANY_TAG,MPI_COMM_WORLD,&status);				  
+         int index=(int)receiveVector[24];
+         for (int j=0;j<sizeinput;j++)
+         {
+            input[index][j]=receiveVector[j];
+         }
+         for (int k=0;k<8*27;k++)
+         {
+            AllCell[index][k]=receiceCell[k];
+         }
+         free (receiceCell);
+      }
+   }
+   free (Cell);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessor::sendtoOtherIsOk(int isPointSuitable)
+{
+   if(comm->getNumberOfProcesses() > 1)  
+   { 
+      int size=comm->getNumberOfProcesses();
+      for (int i=0;i<size;i++)
+      {
+         if (i!=rank)
+         {
+            MPI_Send(&isPointSuitable,1, MPI_INT,i,i,MPI_COMM_WORLD); 
+         }	
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessor.h b/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..dcc4c85a9c3543e47bb5fad5cc0187434d8a4e96
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessor.h
@@ -0,0 +1,115 @@
+/*
+*  PathLinePostprocessor.h
+*
+*  Created on: 04.24.2012
+*  Author: Fard
+*/
+
+
+#ifndef PATHLINEPOSTPROCESSOR_H
+#define PATHLINEPOSTPROCESSOR_H
+
+# define dirx 0
+# define diry 1
+# define dirz 2
+# define dirxy 3 
+# define dirxz 4 
+# define diryz 5
+# define dirxyz 6
+#include <mpi.h>
+#include "Postprocessor.h"
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include <boost/shared_ptr.hpp>
+#include "WbWriter.h"
+
+class D3Q27PathLinePostprocessor;
+typedef boost::shared_ptr<D3Q27PathLinePostprocessor> D3Q27PathLinePostprocessorPtr;
+
+class D3Q27PathLinePostprocessor : public Postprocessor
+{
+public:
+   D3Q27PathLinePostprocessor(Grid3DPtr grid, const std::string& path, WbWriter* const writer,
+      LBMUnitConverterPtr conv, UbSchedulerPtr s, CommunicatorPtr comm, 
+      double x1, double x2, double x3,  LBMReal nue, D3Q27InterpolationProcessorPtr iProcessor);
+   ~D3Q27PathLinePostprocessor();
+   void update(double step);
+
+protected:
+   void collectPostprocessData();
+   void initialMovement(Block3DPtr block, LBMKernelETD3Q27Ptr& kernel, DistributionArray3DPtr& distributions,  BCArray3D<D3Q27BoundaryCondition>& bcArray);
+   void interpolMovement(Block3DPtr block, LBMKernelETD3Q27Ptr& kernel, DistributionArray3DPtr& distributions,  BCArray3D<D3Q27BoundaryCondition>& bcArray,int &isExtrapolation,double tau[]);
+   void extrapolMovement(Block3DPtr block, LBMKernelETD3Q27Ptr& kernel, DistributionArray3DPtr& distributions,  BCArray3D<D3Q27BoundaryCondition>& bcArray,double tau[]);
+   void clearData();
+   void outICell(D3Q27ICell& iCell);
+   void updateDistributedValues();
+   void printPoint(double tau[]);
+   void findPlane(int ix1,int ix2,int ix3,Grid3DPtr grid,Block3DPtr block,double &A,double &B,double &C,double &D,double &ii);
+   void finddisPointToCentercell(double x1,double x2,double x3,double xp000, double yp000, double zp000,double &dis,double &dx,double &deltaT,Block3DPtr &block,int level);
+
+   //void getWallPosition(Grid3DPtr grid,Block3DPtr &block,double xp000,double yp000,double zp000,double &Xw,double &Yw,double &Zw,double x1,double x2,double x3,
+   //  double &xp000T,double &yp000T,double &zp000T,double A,double B,double C,double D,double normalDis,double di,double dj,double dk,double &cofWeightx
+   //,double &cofWeighty,double &cofWeightz,double dismax,double dis,int level);
+   void getWallPosition(double input[]);
+   void findInitialCell(double s,double di,double dj,double dk,double dx,double ix1ph,double ix2ph,double ix3ph,double &xp000,double &yp000,double &zp000);
+   void rearangeInt( int dis[7]);
+   void rearangedDouble( double dis[7]);
+   void addCorrection(double &vx1,double &vx2,double &vx3,double &tauxx,double &tauyy,double &tauzz,double &tauxy,double &tauxz,double &tauyz,
+      double dx,D3Q27ICell iCell,double Xw, double Yw, double Zw,double  omega,double cofWeightx,double cofWeighty,double cofWeightz,double ii,double x1LB,double x2LB,double x3LB,double di,double dj,double dk);
+   void collWall(double A,double B,double C,double D,double &x1,double &x2,double &x3,double x1old,double x2old,double x3old,double dx,double &vx1,double &vx2,double &vx3,double ii);
+   void CalcVelParticle(double dx,double &vx1,double &vx2,double &vx3,double vx1old,double vx2old,double vx3old,double &vx1oldf,double &vx2oldf,double &vx3oldf);
+   void CalcVelParticle2(double dx,double &vx1,double &vx2,double &vx3,double vx1old,double vx2old,double vx3old,double &vx1oldf,double &vx2oldf,double &vx3oldf);
+
+   // void getWallPosition(double dixmax,double disx,double disy,double disz,double disxy,double disxz,double disyz,double disxyz,double &Xw,double &Yw,double &Zw,double x1,double x2,double x3,double A,double B,double C,double D,double normalDis,double di,double dj,double dk,
+   //   double &cofWeightx,double &cofWeighty,double &cofWeightz);
+   void getRankWithPosition(Grid3DPtr grid,double xp000, double yp000, double zp000,int &RankNeigber,int level);
+   void getRankWithPosition(Grid3DPtr grid,double xp000, double yp000, double zp000,int &RankNeigber);
+   void getRankWithPosition2(Grid3DPtr grid,double xp000, double yp000, double zp000,int &RankNeigber);
+   void getAllTag(int allRank[7],int allTag[7]);
+   void getAllInfoForCompare(double input[],double *Vect);
+   void sendMaxtagToAllProccess(int allRank[],int allTag[],int numberpro,int &numberproccessused,int *mainproccess);
+   void getAllRankWithAllPositions(double ix1ph,double ix2ph,double ix3ph,double xp000,double yp000,double zp000,int &Rankx,int &Ranky,int &Rankz,int &Rankxy,int &Rankxz,int &Rankyz,int &Rankxyz,int level);
+   void getAllRankWithAllPositions2(double ix1ph,double ix2ph,double ix3ph,double xp000,double yp000,double zp000,int &Rankx,int &Ranky,int &Rankz,int &Rankxy,int &Rankxz,int &Rankyz,int &Rankxyz);
+   void getVectfromiCell(D3Q27ICell iCell,double *Vect);
+   void getiCellfromVect(D3Q27ICell &iCell,double *Vect);
+
+   void getAfterCompare(double dis[],double input [7][25],double AllCell[7][8*27],double &xp000,double &yp000,double &zp000,
+      double &Xw,double &Yw,double &Zw,double &cofWeightx,double &cofWeighty,double &cofWeightz,double &dx,double &omega,D3Q27ICell &iCell);
+   void SendAndReceiveData(double input [7][25],double AllCell[7][8*27],int allRank[7],int allTag[7]);	
+   void sendtoOtherIsOk(int isPointSuitable);
+private:
+   bool checkNodes(Block3DPtr block);
+   bool checkNodes2( Block3DPtr block,double x11,double x22,double x33);
+   void checkLevel(Block3DPtr& block, LBMKernelETD3Q27Ptr& kernel, DistributionArray3DPtr& distributions,  BCArray3D<D3Q27BoundaryCondition>& bcArray,bool &isPointSuitable2);
+
+   std::vector<UbTupleDouble3> nodes;
+   std::vector<std::string> datanames;
+   std::vector<std::vector<double> > data;
+   std::string path;
+   WbWriter* writer;
+   LBMUnitConverterPtr conv;
+   CommunicatorPtr comm;
+   D3Q27InterpolationProcessorPtr interpolation;
+   double x1, x2, x3;
+   double x1old, x2old, x3old;
+   LBMReal vx1old,vx2old,vx3old;
+   LBMReal vx1oldf,vx2oldf,vx3oldf;
+   bool particleHasMass;
+   int isExtrapolation;
+   int istep;
+   int stepcheck;
+   LBMReal nue;
+   D3Q27InterpolationProcessorPtr iProcessor;
+   D3Q27InterpolationHelperPtr iHelper;
+   int rank;
+   int root;
+   int maxtag;
+   std::vector<std::vector<double> > Positions;
+};
+#endif
+
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessorMcpart.cpp b/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessorMcpart.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..74d87180b9b6c27850e5610de0525c6fed910531
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessorMcpart.cpp
@@ -0,0 +1,1301 @@
+#include "D3Q27PathLinePostprocessorMcpart.h"
+#include "LBMKernelETD3Q27.h"
+#include "SimulationParameters.h"
+#include "D3Q27ETBCProcessor.h"
+#include <vector>
+#include <string>
+#include <boost/foreach.hpp>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+//#include "D3Q27ETFCoffVectorConnector.h"
+using namespace std;
+
+
+D3Q27PathLinePostprocessorMcpart::D3Q27PathLinePostprocessorMcpart(Grid3DPtr grid, const std::string& path, WbWriter* const writer,
+                                                                   LBMUnitConverterPtr conv, UbSchedulerPtr s, CommunicatorPtr comm, 
+                                                                   std::vector<UbTupleDouble3 > _Positions, LBMReal nue, D3Q27InterpolationProcessorPtr iProcessor)
+                                                                   : Postprocessor(grid, s),
+                                                                   path(path),
+                                                                   comm(comm),
+                                                                   writer(writer),
+                                                                   conv(conv),
+                                                                   nue(nue),
+                                                                   iProcessor(iProcessor),
+                                                                   istep(0),
+                                                                   particleHasMass(true),
+                                                                   rank(comm->getProcessID())
+{
+   iHelper = D3Q27InterpolationHelperPtr(new D3Q27InterpolationHelper(iProcessor));
+   getParticlePerProccess(_Positions);
+   getNeighborsRank();
+   initializeForPrinting((int)_Positions.size());
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27PathLinePostprocessorMcpart::~D3Q27PathLinePostprocessorMcpart()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::update(double step)
+{
+   this->stepcheck=(int)step;
+   double aa=scheduler->getMinEnd();
+   if (step >= scheduler->getMaxBegin() && step <= scheduler->getMinEnd())
+   {
+      collectPostprocessData();
+   }
+
+   UBLOG(logDEBUG3, "PathLinePostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::collectPostprocessData()
+{
+
+   int ran=rank;
+   updateParticles();
+   checkParticles();
+   initialMovement();
+   updateParticles();
+   checkParticles();
+   BOOST_FOREACH(ParticlesPtr particle, particles)
+   { 
+      double tau[6];//={tauxx,tauyy,tauzz,tauxy,tauxz,tauyz};
+      finalMovement(particle,tau);	
+      //printParticle(particle);
+      gatherData(particle);
+   }		
+
+   if(scheduler->isDue((double)istep) )
+   {
+      string partName = writer->writeNodesWithNodeDataDouble(path+ UbSystem::toString(rank),nodes,datanames,data);
+      size_t found=partName.find_last_of("//");
+      string piece = partName.substr(found+1);
+
+      vector<string> cellDataNames;
+
+      vector<string> pieces = comm->gather(piece);
+      if (comm->getProcessID() == comm->getRoot())
+      {
+         string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(path,pieces,datanames,cellDataNames);
+
+         //vector<string> filenames;
+         //filenames.push_back(pname);
+         //if (istep == Postprocessor::scheduler->getMinBegin())
+         //{
+         //   WbWriterVtkXmlASCII::getInstance()->writeCollection(path+"_collection",filenames,0,false);
+         //} 
+         //else
+         //{
+         //   WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(path+"_collection",filenames,0,false);
+         //}
+         UBLOG(logINFO,"D3Q27MacroscopicQuantitiesPostprocessor step: " << istep);
+      }
+   }
+
+   istep++;
+}
+////////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::initializeForPrinting(int _number)
+{
+   for (int i=0;i<_number;i++)
+   {
+      string fileName=path + UbSystem::toString(i)+ ".txt";
+      files.push_back(boost::shared_ptr<std::ofstream>(new std::ofstream(fileName.c_str())));	
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::getParticlePerProccess(std::vector<UbTupleDouble3 >particlesVec)
+{
+   for (int i=0;i<particlesVec.size();i++)
+   {
+      int minInitLevel = this->grid->getCoarsestInitializedLevel();
+      int maxInitLevel = this->grid->getFinestInitializedLevel();
+      LBMKernelETD3Q27Ptr kernel;
+      DistributionArray3DPtr distributions;
+      BCArray3D<D3Q27BoundaryCondition> bcArray;
+      Block3DPtr block;
+
+      for(int level = minInitLevel; level<=maxInitLevel; level++)
+      {	      
+         UbTupleInt3 blockIndexes = grid->getBlockIndexes(val<1>(particlesVec[i]), val<2>(particlesVec[i]), val<3>(particlesVec[i]),level);
+         block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+         if(!block) continue; 
+         if(block->isActive()) 
+         {
+            if (block->hasInterpolationFlagCF() || block->hasInterpolationFlagFC())
+            {
+               if(rank == block->getRank())
+               { 					
+                  if(!checkNodes(block,val<1>(particlesVec[i]), val<2>(particlesVec[i]), val<3>(particlesVec[i])))
+                  {	
+                     sendStatusOfPoint(false,val<1>(particlesVec[i]), val<2>(particlesVec[i]), val<3>(particlesVec[i]),level,i);
+                     continue;
+                  }
+                  initializeParticle ( val<1>(particlesVec[i]), val<2>(particlesVec[i]), val<3>(particlesVec[i]),i ,level);
+                  //getParticle(particle,grid->getDeltaX(block),particle.x,particle.y,particle.z,level,i);
+                  sendStatusOfPoint(true,val<1>(particlesVec[i]), val<2>(particlesVec[i]), val<3>(particlesVec[i]),level,i);
+                  break;
+               }
+               else							
+               {								
+                  bool isPointSuitable=true;
+                  receiveStatusOfPoint(isPointSuitable,block->getRank(),val<1>(particlesVec[i]), val<2>(particlesVec[i]), val<3>(particlesVec[i]),level)	;	
+                  if (isPointSuitable){break;}							
+               }		
+            }
+            else
+            {
+               if(rank == block->getRank())
+               { 
+                  if(!checkNodes(block,val<1>(particlesVec[i]), val<2>(particlesVec[i]), val<3>(particlesVec[i])))
+                  {		   
+                     continue;
+                  }  
+                  initializeParticle ( val<1>(particlesVec[i]), val<2>(particlesVec[i]), val<3>(particlesVec[i]),i,level );
+                  Particles particle;
+                  //getParticle(particle,grid->getDeltaX(block),particle.x,particle.y,particle.z,level,i);
+                  //particlesVec.push_back(particle);
+                  //particles.erase(t.first);
+                  break;	
+               }
+
+            }
+         }		
+      }
+   } 			
+}
+////////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::initializeParticle(double x, double y,double z,int i,int level)
+{
+   ParticlesPtr particle = ParticlesPtr(new Particles() );
+
+   particle->xold=x;	                    particle->yold=y;  	                particle->zold=z;
+   particle->x   =x;	                    particle->y   =y;	                particle->z   =z;			 	  
+   particle->vxold =0.1;		            particle->vyold =0.1;	            particle->vzold=0.1;	 
+   particle->vxoldf=0.0;		            particle->vyoldf=0.0;	            particle->vzoldf=0.0;
+   particle->rankOfParticle=rank;          particle->ID=i;                     particle->level=level;
+   particles.push_back(particle);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::getNeighborsRank()
+{
+   int gridRank = grid->getRank();
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      vector<Block3DPtr> blockVector;
+      grid->getBlocks(level, gridRank, blockVector);
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         int blockRank = block->getRank();
+         if (gridRank == blockRank && block->isActive())
+         {				
+            //std::vector<Block3DPtr> neighbors; 
+            int ix1 = block->getX1();
+            int ix2 = block->getX2();
+            int ix3 = block->getX3();
+            int level = block->getLevel();
+            //grid->getAllNeighbors(ix1, ix2, ix3, level, level, neighbors);
+            int dirs=26;//number of directions
+            for( int dir = 0; dir < dirs; dir++)
+            {
+               Block3DPtr neighBlock = grid->getNeighborBlock(dir, ix1, ix2, ix3, level);
+               if(neighBlock)
+               {
+                  int neighBlockRank = neighBlock->getRank();			
+                  if(blockRank != neighBlockRank && neighBlock->isActive())
+                  {
+                     if (neighbors.size()==0)
+                     {
+                        neighbors.insert((std::make_pair(neighBlockRank,0)));
+                     } 
+                     else
+                     {
+                        for ( std::map< int, int >::const_iterator iter = neighbors.begin();iter != neighbors.end(); ++iter )
+                        {
+                           if (iter->first!=neighBlockRank)
+                           {
+                              neighbors.insert((std::make_pair(neighBlockRank,0)));
+                           }
+                        }	
+                     }	
+                  }	
+               }	
+            }
+         }		
+      }	
+   }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27PathLinePostprocessorMcpart::getParticle(Particles &particle, double dx,double x, double y,double z,int level,int i)
+//{
+//	particle.particleNumber=i;
+//	particle.xold=val<1>(xold[i]);	        particle.yold=val<2>(xold[i]);  	particle.zold=val<3>(xold[i]);
+//	particle.x   =x;	                    particle.y   =y;	                particle.z   =z;			 
+//	particle.level=level;
+//	particle.dx=dx;		 
+//	particle.vxold=val<1>(vxold[i]);		particle.vyold=val<2>(vxold[i]);	particle.vzold=val<3>(vxold[i]);	 
+//	particle.vxoldf=val<1>(vxoldf[i]);		particle.vyoldf=val<2>(vxoldf[i]);	particle.vzoldf=val<3>(vxoldf[i]);
+//
+//}
+//////////////////////////////////////////////////////////////////////////
+bool D3Q27PathLinePostprocessorMcpart::checkNodes( Block3DPtr block,double _x1,double _x2,double _x3)
+{
+   bool result = true;
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+   D3Q27BoundaryConditionPtr bcPtr;
+
+   double x1_ch = _x1;// + vx1old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+   double x2_ch = _x2;// + vx2old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+   double x3_ch = _x3;// + vx3old*conv->getfactorTimeShouldMultiplebyDx()*grid->getDeltaX(block);
+
+   int nx1 = static_cast<int>(bcArray.getNX1());
+   int nx2 = static_cast<int>(bcArray.getNX2());
+   int nx3 = static_cast<int>(bcArray.getNX3());
+
+   UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block, x1_ch, x2_ch, x3_ch);
+
+   int ix1 = val<1>(nodeIndexes);
+   int ix2 = val<2>(nodeIndexes);
+   int ix3 = val<3>(nodeIndexes);
+   bool outlet=false;
+
+   for (int xx3 = ix3; xx3 <= ix3 + 1 && ix3 + 1 < nx3; xx3++)
+      for(int xx2 = ix2; xx2 <= ix2 + 1 && ix2 + 1 < nx2; xx2++)
+         for(int xx1 = ix1; xx1 <= ix1 + 1 && ix1 + 1 < nx1; xx1++)
+         {
+            bcPtr=bcArray.getBC(xx1,xx2,xx3);
+            for(int fdir=D3Q27System::STARTF; fdir<=D3Q27System::ENDF; fdir++)
+            {
+               if ( bcPtr != NULL)
+               {
+                  if (bcPtr->hasDensityBoundaryFlag(fdir))
+                  {	
+                     if(outlet)break; 
+                     outlet=true;
+                     break;
+                  }
+               }
+            }
+            result = result && !bcArray.isUndefined(xx1, xx2, xx3) &&  !outlet;
+         }
+
+         return result;
+
+}
+//	//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::initialMovement()
+{
+   BOOST_FOREACH(ParticlesPtr particle, particles)
+   {
+      double dx=grid->getDeltaX(particle->level);
+      particle->xold=particle->x;
+      particle->yold=particle->y;
+      particle->zold=particle->z;
+      particle->x   =particle->xold+particle->vxold*dx*conv->getFactorTimeLbToW(dx);
+      particle->y   =particle->yold+particle->vyold*dx*conv->getFactorTimeLbToW(dx);
+      particle->z   =particle->zold+particle->vzold*dx*conv->getFactorTimeLbToW(dx);	
+   }
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//void D3Q27PathLinePostprocessorMcpart::updateDistributedValues(std::vector<Particles> *particlesVec,std::vector<UbTupleDouble3> &x)
+//{
+//	
+//	int numberOFVariable=18;
+//	std::vector<double> sendParticlesInfomation;	
+//	std::vector<double> receiveParticlesInfomation;	
+//	getVectorFromParticles(sendParticlesInfomation,particlesVec,numberOFVariable);
+//	allGatherDoubles(sendParticlesInfomation, receiveParticlesInfomation);
+//	fillOutPositions(receiveParticlesInfomation,x);
+//	//getParticlesFromVector(receiveParticlesInfomation,particlesVec,numberOFVariable);
+//	//std::vector<Particles> *particlesVec;
+//}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::sendBool(bool _bool,int distinationRank ,int i)
+{
+   int variable;
+   if (_bool==false)
+   {
+      variable=0;
+   }
+   else variable=1;
+   if(comm->getNumberOfProcesses() > 1)  
+   { 		
+      MPI_Send(&variable,1, MPI_INT,distinationRank,i,MPI_COMM_WORLD); 
+      //std::cout<<"\n"<<variable<<"send from rank "<<rank<<" to rank "<< distinationRank;
+   }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::sendInt(int svalue,int distinationRank ,int tag)
+{
+   if(comm->getNumberOfProcesses() > 1)  
+   { 		
+      MPI_Send(&svalue,1, MPI_INT,distinationRank,tag,MPI_COMM_WORLD); 
+   }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::receiveBool(bool &variable,int rankBlock)
+{
+   if(comm->getNumberOfProcesses() > 1)  
+   { 	
+      int _bool;
+      MPI_Status status; 
+      MPI_Recv(&_bool,1, MPI_INT,rankBlock,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+      //std::cout<<"\n"<<_bool<<"received in rank "<<rank<<" from rank "<< rankBlock;
+      if (_bool==false)
+      {
+         variable=false;
+      }
+      else variable=true;
+   }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::receiveInt(int &rvalue,int root)
+{
+   if(comm->getNumberOfProcesses() > 1)  
+   { 	
+      MPI_Status status; 
+      MPI_Recv(&rvalue,1, MPI_INT,root,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+   }
+}
+////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::sendStatusOfPoint(bool status,double x1,double x2,double x3,double level,int i)
+{
+   for(int lev = (int)level-1; lev<=(int)level+1; lev++)
+   {	      	
+      UbTupleInt3 blockIndexesDistination = grid->getBlockIndexes(x1,x2,x3,lev);
+      Block3DPtr blockDistination= grid->getBlock(val<1>(blockIndexesDistination), val<2>(blockIndexesDistination), val<3>(blockIndexesDistination), lev);
+      if(!blockDistination) continue; 
+      if(blockDistination->isActive()) 	
+      {
+         if(rank!=blockDistination->getRank())
+         {
+            sendBool(status,blockDistination->getRank(),i );  
+         }
+
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::receiveStatusOfPoint(bool &status,int rankRoot,double x1,double x2,double x3,double level)
+{
+   for(int lev = (int)level-1; lev<=(int)level+1; lev++)
+   {	      
+      UbTupleInt3 blockIndexes = grid->getBlockIndexes(x1,x2,x3,lev);
+      Block3DPtr block= grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), lev);
+      if (block)
+      {
+         if(rankRoot!=block->getRank())
+         {
+            LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+            if(kernel) 
+            {
+               if(checkNodes(block,x1,x2,x3))
+               {	
+                  receiveBool(status,rankRoot);	
+               }
+            }
+
+         }
+
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::getVectorFromParticles(std::vector<double> &particlesInfomation,ParticlesPtr particle)
+{
+   particlesInfomation.push_back(particle->x     ); 
+   particlesInfomation.push_back(particle->y     );	
+   particlesInfomation.push_back(particle->z     );
+   particlesInfomation.push_back(particle->xold  ); 
+   particlesInfomation.push_back(particle->yold  );	
+   particlesInfomation.push_back(particle->zold  );
+   particlesInfomation.push_back(particle->vxold ); 
+   particlesInfomation.push_back(particle->vyold );	
+   particlesInfomation.push_back(particle->vzold );
+   particlesInfomation.push_back(particle->vxoldf); 
+   particlesInfomation.push_back(particle->vyoldf);	
+   particlesInfomation.push_back(particle->vzoldf);
+   particlesInfomation.push_back(particle->rankOfParticle); 
+   particlesInfomation.push_back(particle->ID);
+   particlesInfomation.push_back(particle->level);
+
+}
+////////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::getParticlesFromVector(std::vector<double> particlesInfomation,int numberOFVariable)
+{
+   int numParticles= (int)particlesInfomation.size()/numberOFVariable;
+   for (int i=0;i<numParticles;i++)
+   {
+      ParticlesPtr particle = ParticlesPtr(new Particles() );
+
+      particle->x                 =particlesInfomation[i*numberOFVariable+0]; 
+      particle->y     			=particlesInfomation[i*numberOFVariable+1];
+      particle->z     			=particlesInfomation[i*numberOFVariable+2];
+      particle->xold   		    =particlesInfomation[i*numberOFVariable+3];
+      particle->yold  			=particlesInfomation[i*numberOFVariable+4];
+      particle->zold  			=particlesInfomation[i*numberOFVariable+5];
+      particle->vxold  		    =particlesInfomation[i*numberOFVariable+6];
+      particle->vyold 			=particlesInfomation[i*numberOFVariable+7];
+      particle->vzold 			=particlesInfomation[i*numberOFVariable+8];
+      particle->vxoldf 		    =particlesInfomation[i*numberOFVariable+9];
+      particle->vyoldf			=particlesInfomation[i*numberOFVariable+10];
+      particle->vzoldf			=particlesInfomation[i*numberOFVariable+11];
+      particle->rankOfParticle    =(int)particlesInfomation[i*numberOFVariable+12];
+      particle->ID	            =(int)particlesInfomation[i*numberOFVariable+13];
+      particle->level	            =(int)particlesInfomation[i*numberOFVariable+14];
+      particles.push_back(particle);
+   }
+}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27PathLinePostprocessorMcpart::updateinfo(std::vector<Particles> *particlesVec,std::vector<UbTupleDouble3> &x)
+//{
+//	std::vector<Particles>&particles=*particlesVec;
+//	for (int i=0;i<particlesVec->size();i++)
+//	{
+//		Particles &particle=particles[i];
+//		int index=particle.particleNumber;
+//		val<1>(x[index])=particle.xold;	        
+//		val<2>(x[index])=particle.yold; 
+//		val<3>(x[index])=particle.zold;
+//	}
+//}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27PathLinePostprocessorMcpart::allGatherDoubles(std::vector<double>& svalues, std::vector<double>& rvalues)
+//{
+//	int scount;
+//	vector<int> displs, rcounts;
+//
+//	scount = (int)(svalues.size());
+//	rcounts.resize(comm->getNumberOfProcesses());
+//	MPI_Allgather(&scount, 1, MPI_INT, &rcounts[0], 1, MPI_INT, MPI_COMM_WORLD);
+//	displs.resize(comm->getNumberOfProcesses());
+//
+//	displs[0] = 0; 
+//	for (int i=1; i<comm->getNumberOfProcesses(); ++i) { 
+//		displs[i] = displs[i-1]+rcounts[i-1]; 
+//	}
+//
+//	rvalues.resize(displs[comm->getNumberOfProcesses()-1]+rcounts[comm->getNumberOfProcesses()-1]); 
+//
+//	if(rvalues.size() == 0)
+//	{
+//		rvalues.resize(1);
+//		rvalues[0] = -999;
+//	}
+//	if(scount == 0)
+//	{
+//		svalues.resize(1);
+//		svalues[0] = -999;
+//	}
+//
+//	MPI_Allgatherv(&svalues[0], scount, MPI_DOUBLE, &rvalues[0], &rcounts[0], &displs[0], MPI_DOUBLE, MPI_COMM_WORLD); 
+//}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27PathLinePostprocessorMcpart::fillOutPositions(std::vector<double> particlesInfomation,std::vector<UbTupleDouble3> &x,double numberOFVariable)
+//{
+//	if (particlesInfomation.size()!=x.size()*numberOFVariable)
+//	{
+//		std::cout<<"number of particle is wrong";
+//	}
+//	for (int i=0;i<x.size();i++)
+//	{
+//		Particles particle;
+//		particle.x              =particlesInfomation[i*numberOFVariable+0]; 
+//		particle.y     			=particlesInfomation[i*numberOFVariable+1];
+//		particle.z     			=particlesInfomation[i*numberOFVariable+2];
+//		particle.xold   		=particlesInfomation[i*numberOFVariable+3];
+//		particle.yold  			=particlesInfomation[i*numberOFVariable+4];
+//		particle.zold  			=particlesInfomation[i*numberOFVariable+5];
+//		particle.vx     		=particlesInfomation[i*numberOFVariable+6];
+//		particle.vy    			=particlesInfomation[i*numberOFVariable+7];
+//		particle.vz    			=particlesInfomation[i*numberOFVariable+8];
+//		particle.vxold  		=particlesInfomation[i*numberOFVariable+9];
+//		particle.vyold 			=particlesInfomation[i*numberOFVariable+10];
+//		particle.vzold 			=particlesInfomation[i*numberOFVariable+11];
+//		particle.vxoldf 		=particlesInfomation[i*numberOFVariable+12];
+//		particle.vyoldf			=particlesInfomation[i*numberOFVariable+13];
+//		particle.vzoldf			=particlesInfomation[i*numberOFVariable+14];
+//		particle.dx     		=particlesInfomation[i*numberOFVariable+15];
+//		particle.level 			=particlesInfomation[i*numberOFVariable+16];
+//		particle.particleNumber	=particlesInfomation[i*numberOFVariable+17];
+//
+//		int index=particle.particleNumber;
+//		val<1>(x[index])=particle.x;	        val<2>(x[index])=particle.y;        	val<3>(x[index])=particle.z;
+//		val<1>(xold[index])=particle.xold;	    val<2>(xold[index])=particle.yold;  	val<3>(xold[index])=particle.zold;
+//		val<1>(vxold[index])=particle.vxold;	val<2>(vxold[index])=particle.vyold;  	val<3>(vxold[index])=particle.vzold;
+//		val<1>(vxoldf[index])=particle.vxoldf;	val<2>(vxoldf[index])=particle.vyoldf;  	val<3>(vxoldf[index])=particle.vzoldf;
+//	}
+//
+//}
+//
+//
+//
+
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::updateParticles()
+{
+   //find particles which want to go to another process
+   BOOST_FOREACH(ParticlesPtr particle, particles)
+   {
+      int minInitLevel = this->grid->getCoarsestInitializedLevel();
+      int maxInitLevel = this->grid->getFinestInitializedLevel();
+      LBMKernelETD3Q27Ptr kernel;
+      DistributionArray3DPtr distributions;
+      BCArray3D<D3Q27BoundaryCondition> bcArray;
+      Block3DPtr block;
+
+      for(int level = minInitLevel; level<=maxInitLevel; level++)
+      {	      
+         UbTupleInt3 blockIndexes = grid->getBlockIndexes(particle->x,particle->y,particle->z,level);
+         block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+         if(!block) continue; 
+         if(block->isActive()) 
+         {
+            if(rank != block->getRank())
+            { 					
+               std::map<int,int>::iterator p;
+               p=neighbors.find(block->getRank());
+               p->second++;
+               particle->rankOfParticle=block->getRank();
+               particle->level=level;
+               break;//break should be here
+            }
+            //break;//break should be here
+         }			
+      }
+   }
+   //send number of particle moving to another process 
+   for ( std::map< int, int >::const_iterator iter = neighbors.begin();iter != neighbors.end(); ++iter )
+   {					
+      int svalue=iter->second;
+      if(comm->getNumberOfProcesses() > 1)  
+      { 		
+         MPI_Send(&svalue,1, MPI_INT,iter->first,iter->first,MPI_COMM_WORLD); 
+         //std::cout<<"\n"<<svalue<<" send from rank "<<rank<<" to rank "<< iter->first;
+      }
+   }	
+   std::map<int,int> receiveNeighbors;
+   //receive number of particle coming form another process
+   for ( std::map< int, int >::const_iterator iter = neighbors.begin();iter != neighbors.end(); ++iter )
+   {
+      int rvalue;	
+      if(comm->getNumberOfProcesses() > 1)  
+      { 	
+         MPI_Status status; 
+         MPI_Recv(&rvalue,1, MPI_INT,iter->first,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+         //std::cout<<"\n"<<"rank "<< rank<<" receive "<<rvalue<<" from rank "<<iter->first;
+         receiveNeighbors.insert((std::make_pair(iter->first,rvalue)));
+      }
+   }
+   //int numOfvarClass=18;
+
+   ///send data
+   for ( std::map< int, int >::const_iterator iter = neighbors.begin();iter != neighbors.end(); ++iter )
+   {					
+      if (iter->second!=0)
+      {
+         std::vector<double> sendParticlesInfomation;
+         int lengthSending=numOfvarClass*iter->second;
+
+         BOOST_FOREACH(ParticlesPtr particle, particles)
+         {
+            if (particle->rankOfParticle==iter->first)
+            {
+               getVectorFromParticles(sendParticlesInfomation,particle);
+            }
+         }
+         MPI_Send(&sendParticlesInfomation[0],lengthSending, MPI_DOUBLE,iter->first,iter->first,MPI_COMM_WORLD); 
+         std::cout<<"\n send from rank "<<rank<<" to rank "<< iter->first;
+      }
+   }	
+   //delete particle
+   std::list<ParticlesPtr> newparticles;
+   BOOST_FOREACH(ParticlesPtr particle, particles)
+   {
+      if (particle->rankOfParticle==rank)
+      {
+         newparticles.push_back(particle);
+      }
+      else
+      {
+         //	int idNumber =particle->ID;
+         //	printParticle(idNumber);
+         //delete data
+      }
+   }
+   particles=newparticles;
+   ///receive data
+   for ( std::map< int, int >::const_iterator iter = receiveNeighbors.begin();iter != receiveNeighbors.end(); ++iter )
+   {					
+      if (iter->second!=0)
+      {
+         int lengthReceiving=numOfvarClass*iter->second;	
+         std::vector<double> rvalue(lengthReceiving);	
+         MPI_Status status; 
+         MPI_Recv(&rvalue[0],lengthReceiving, MPI_DOUBLE,iter->first,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
+         std::cout<<"\n"<<"rank "<< rank<<" receive  from rank "<<iter->first;
+         getParticlesFromVector(rvalue,numOfvarClass);
+      }
+   }
+   //reset neighbors
+   std::map<int,int> Neighbors2;
+   Neighbors2=neighbors;
+   neighbors.clear();
+   for ( std::map< int, int >::const_iterator iter = Neighbors2.begin();iter != Neighbors2.end(); ++iter )
+   {
+      neighbors.insert((std::make_pair(iter->first,0)));	
+   }	
+
+
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::checkParticles()
+{
+   std::list<ParticlesPtr> newparticles;
+   BOOST_FOREACH(ParticlesPtr particle, particles)
+   { 
+      int minInitLevel = this->grid->getCoarsestInitializedLevel();
+      int maxInitLevel = this->grid->getFinestInitializedLevel();
+      Block3DPtr block;
+
+      for(int level = minInitLevel; level<=maxInitLevel; level++)
+      {	      
+         UbTupleInt3 blockIndexes = grid->getBlockIndexes(particle->x,particle->y,particle->z,level);
+         block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+         if(!block) continue; 
+         if(block->isActive()) 
+         {
+            LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+            if(!kernel) continue; 
+            if(rank == block->getRank())
+            { 					
+               if(!checkNodes(block,particle->x,particle->y,particle->z))
+               {	
+                  std::cout<<"particle number "<<particle->ID <<"is gone";
+                  continue;
+               }
+               newparticles.push_back(particle);
+               break;
+            }
+         }
+      }
+   }
+   particles=newparticles;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::finalMovement(ParticlesPtr particle,double tau[])
+{
+   Block3DPtr block;
+   UbTupleInt3 blockIndexes = grid->getBlockIndexes(particle->x, particle->y, particle->z,particle->level);
+   block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), particle->level);
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+   BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+   UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block, particle->x, particle->y, particle->z);
+   int ix1 = val<1>(nodeIndexes);
+   int ix2 = val<2>(nodeIndexes);
+   int ix3 = val<3>(nodeIndexes);
+
+   if(!iProcessor->iCellHasSolid(bcArray, ix1, ix2, ix3))
+   {
+      interpolMovement(block,distributions,particle,tau,ix1, ix2, ix3);
+   }
+   else
+   {
+      extrapolMovement( block, particle, tau, ix1,  ix2,  ix3);
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::interpolMovement(Block3DPtr block,DistributionArray3DPtr& distributions,ParticlesPtr particle,double tau[],int ix1, int ix2, int ix3)
+{
+   D3Q27ICell iCell;
+   //LBMReal f[D3Q27System::ENDF+1];
+   LBMReal dx =grid->getDeltaX(particle->level);
+   LBMReal vx1,vx2,vx3;
+   iProcessor->readICell(distributions, iCell, ix1, ix2, ix3);
+   double x1LB, x2LB, x3LB;
+   UbTupleDouble3 orgNodeRW =  grid->getNodeCoordinates(block,  ix1, ix2, ix3);
+   double offsetX1RW = abs(particle->x - val<1>(orgNodeRW));
+   double offsetX2RW = abs(particle->y - val<2>(orgNodeRW));
+   double offsetX3RW = abs(particle->z - val<3>(orgNodeRW));
+   x1LB = offsetX1RW / dx;
+   x2LB = offsetX2RW / dx;
+   x3LB = offsetX3RW / dx;
+
+   x1LB -= 0.5;
+   x2LB -= 0.5;
+   x3LB -= 0.5;
+   LBMReal omega = LBMSystem::calcCollisionFactor(nue, block->getLevel());
+   LBMReal tauxx,	   tauyy,	   tauzz,	   tauxy,	   tauxz,	   tauyz;
+   iHelper->interpolate8to1WithVelocityWithShearStress(iCell, x1LB, x2LB, x3LB, omega,vx1,vx2,vx3,tauxx,tauyy,tauzz,tauxy,tauxz,tauyz);
+   vx1 = vx1 *  conv->getFactorVelocityLbToW();
+   vx2 = vx2 *  conv->getFactorVelocityLbToW();
+   vx3 = vx3 *  conv->getFactorVelocityLbToW();
+   tau[0]=tauxx/dx;
+   tau[1]=tauyy/dx;
+   tau[2]=tauzz/dx;
+   tau[3]=tauxy/dx;
+   tau[4]=tauxz/dx;
+   tau[5]=tauyz/dx;  
+
+   if (particleHasMass) {   CalcVelParticle(dx,vx1,vx2,vx3,particle->vxold,particle->vyold,particle->vzold,particle->vxoldf,particle->vyoldf,particle->vzoldf);}
+   //if (particleHasMass) {   CalcVelParticle2(dx,vx1,vx2,vx3,particle->vxold,particle->vyold,particle->vzold,particle->vxoldf,particle->vyoldf,particle->vzoldf);}
+   //heuns method
+   particle->x= (particle->xold) + 1.0/2.0*(vx1 + particle->vxold)*conv->getFactorTimeLbToW(dx);
+   particle->y= (particle->yold) + 1.0/2.0*(vx2 + particle->vyold)*conv->getFactorTimeLbToW(dx);
+   particle->z= (particle->zold) + 1.0/2.0*(vx3 + particle->vzold)*conv->getFactorTimeLbToW(dx);
+
+   particle->vxold = vx1;
+   particle->vyold = vx2;
+   particle->vzold = vx3;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::extrapolMovement(Block3DPtr block,ParticlesPtr particle,double tau[],int ix1, int ix2, int ix3)
+{
+
+   LBMReal vx1,vx2,vx3;
+   LBMReal dx =grid->getDeltaX(particle->level);
+   int level =particle->level;
+   LBMReal omega = LBMSystem::calcCollisionFactor(nue,level);
+   D3Q27ICell iCell;
+   //LBMReal f[D3Q27System::ENDF+1];
+   double xp000,yp000,zp000;
+   double Xw=999.0,Yw=999.0,Zw=999.0;
+   double cofWeightx=999.0,cofWeighty=999.0,cofWeightz=999.0;
+   double A,B,C,D,ii=0.0;
+   double disx=9990,disy=9990,disz=9990,disxy=9990,disxz=9990,disyz=9990,disxyz=9990;
+
+   UbTupleDouble3 orgNodeRW =  grid->getNodeCoordinates(block,  ix1, ix2, ix3);
+   double ix1ph = ( val<1>(orgNodeRW));
+   double ix2ph = ( val<2>(orgNodeRW));
+   double ix3ph = ( val<3>(orgNodeRW)); 
+   findPlane(ix1,ix2,ix3,grid,block,A,B,C,D,ii);
+   double s = A*particle->x + B*particle->y + C*particle->z + D;//The sign of s = Ax + By + Cz + D determines which side the point (x,y,z) lies with respect to the plane. If s > 0 then the point lies on the same side as the normal (A,B,C). If s < 0 then it lies on the opposite side, if s = 0 then the point (x,y,z) lies on the plane.
+   if (s>0){s=1;} else if (s<0){s=-1;}else {s=0;}
+   double normalDis=((A*particle->x + B*particle->y + C*particle->z + D)/sqrt(A*A+B*B+C*C));///distance point to plane xp-Xw=distance
+   double di=A/sqrt(A*A+B*B+C*C);      double dj=B/sqrt(A*A+B*B+C*C);       double dk=C/sqrt(A*A+B*B+C*C);
+   double XXw=particle->x-di*normalDis;    double YYw=particle->y-dj*normalDis;    double ZZw=particle->z-dk*normalDis;
+   findInitialCell(s,di,dj,dk,dx,ix1ph,ix2ph,ix3ph,xp000,yp000,zp000);//find initial cell with xp000,yp000,zp000
+
+   double dis[7]={disx,disy,disz,disxy,disxz,disyz,disxyz};   
+   getAllDis(dis,particle->x,particle->y,particle->z,ix1ph,ix2ph,ix3ph,xp000,yp000,zp000,level);
+   rearangedDouble(dis);
+   getAfterCompare(dis,dx,ix1ph,ix2ph,ix3ph,xp000,yp000,zp000,Xw,Yw,Zw,particle->x,particle->y,particle->z,A,B,C, D, normalDis,di,dj,dk,cofWeightx,cofWeighty,cofWeightz,iCell,level);
+
+   double x1LB, x2LB, x3LB;
+   double offsetX1RW000 = (particle->x - xp000);
+   double offsetX2RW000 = (particle->y - yp000);
+   double offsetX3RW000 = (particle->z - zp000);
+
+   x1LB = offsetX1RW000 / dx;
+   x2LB = offsetX2RW000 / dx;
+   x3LB = offsetX3RW000 / dx;
+   x1LB -= 0.5;
+   x2LB -= 0.5;
+   x3LB -= 0.5;
+   // outICell(iCell);
+   //iProcessor->interpolate8to1WithVelocity(iCell, f, x1LB, x2LB, x3LB, omega,vx1,vx2,vx3);
+   LBMReal tauxx,	   tauyy,	   tauzz,	   tauxy,	   tauxz,	   tauyz;
+   iHelper->interpolate8to1WithVelocityWithShearStress(iCell, x1LB, x2LB, x3LB, omega,vx1,vx2,vx3,tauxx,tauyy,tauzz,tauxy,tauxz,tauyz);	
+   addCorrection(vx1,vx2,vx3,tauxx,tauyy,tauzz,tauxy,tauxz,tauyz,dx,iCell,Xw, Yw, Zw, omega,cofWeightx,cofWeighty,cofWeightz,ii, x1LB, x2LB, x3LB,di,dj,dk);
+   tau[0]=tauxx;
+   tau[1]=tauyy;
+   tau[2]=tauzz;
+   tau[3]=tauxy;
+   tau[4]=tauxz;
+   tau[5]=tauyz;
+   // if (particleHasMass) {   CalcVelParticle(dx,vx1,vx2,vx3,vx1old,vx2old,vx3old,vx1oldf,vx2oldf,vx3oldf);}
+   if (particleHasMass) {   CalcVelParticle2(dx,vx1,vx2,vx3,particle->vxold,particle->vyold,particle->vzold,particle->vxoldf,particle->vyoldf,particle->vzoldf);}
+   //heuns method
+   particle->x= (particle->xold) + 1.0/2.0*(vx1 + particle->vxold)*conv->getFactorTimeLbToW(dx);
+   particle->y= (particle->yold) + 1.0/2.0*(vx2 + particle->vyold)*conv->getFactorTimeLbToW(dx);
+   particle->z= (particle->zold) + 1.0/2.0*(vx3 + particle->vzold)*conv->getFactorTimeLbToW(dx);
+   collWall(A,B,C,D,particle->x,particle->y,particle->z,particle->xold,particle->yold,particle->zold,dx,vx1,vx2,vx3,ii);
+   particle->vxold = vx1;
+   particle->vyold = vx2;
+   particle->vzold = vx3;
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::CalcVelParticle(double dx,double &vx1,double &vx2,double &vx3,double vx1old,double vx2old,
+                                                       double vx3old,double &vx1oldf,double &vx2oldf,double &vx3oldf)
+{
+   double signDragx,signDragy,signDragz;
+   double dragCoff=1.0;
+   if     (vx1old>=vx1oldf)    {  signDragx=-1.0;   } 
+   else if(vx1old<vx1oldf)     {  signDragx= 1.0;    }
+   if     (vx2old>=vx2oldf)    {  signDragy=-1.0;   } 
+   else if(vx2old< vx2oldf)    {  signDragy= 1.0;    }
+   if     (vx3old>=vx3oldf)    {  signDragz=-1.0;   } 
+   else if(vx3old< vx3oldf)    {  signDragz= 1.0;    }
+   double vx1p=vx1old+signDragx*(vx1old-vx1oldf)*(vx1old-vx1oldf)*conv->getFactorTimeLbToW(dx);
+   double vx2p=vx2old+signDragy*(vx2old-vx2oldf)*(vx2old-vx2oldf)*conv->getFactorTimeLbToW(dx);
+   double vx3p=vx3old+signDragz*(vx3old-vx3oldf)*(vx3old-vx3oldf)*conv->getFactorTimeLbToW(dx);   
+
+   double signDragNextx,signDragNexty,signDragNextz;
+   if     (vx1p>=vx1)    {  signDragNextx=-1.0;   } 
+   else if(vx1p< vx1)    {  signDragNextx= 1.0;    }
+   if     (vx2p>=vx2)    {  signDragNexty=-1.0;   } 
+   else if(vx2p< vx2)    {  signDragNexty= 1.0;    }
+   if     (vx3p>=vx3)    {  signDragNextz=-1.0;   } 
+   else if(vx3p< vx3)    {  signDragNextz= 1.0;    }
+   ////////////////////velocity of particle////////////////////////////////////////////////////// 
+   double velx1oldf=vx1;
+   double velx2oldf=vx2;
+   double velx3oldf=vx3;
+
+   vx1=vx1old+1.0/2.0*( signDragNextx*(vx1p-vx1)*(vx1p-vx1)+signDragx*(vx1old-vx1oldf)*(vx1old-vx1oldf) )*conv->getFactorTimeLbToW(dx);
+   vx2=vx2old+1.0/2.0*( signDragNexty*(vx2p-vx2)*(vx2p-vx2)+signDragy*(vx2old-vx2oldf)*(vx2old-vx2oldf) )*conv->getFactorTimeLbToW(dx);
+   vx3=vx3old+1.0/2.0*( signDragNextz*(vx3p-vx3)*(vx3p-vx3)+signDragz*(vx3old-vx3oldf)*(vx3old-vx3oldf) )*conv->getFactorTimeLbToW(dx);
+
+   vx1oldf=velx1oldf;
+   vx2oldf=velx2oldf;
+   vx3oldf=velx3oldf;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::CalcVelParticle2(double dx,double &vx1,double &vx2,double &vx3,double vx1old,double vx2old,
+                                                        double vx3old,double &vx1oldf,double &vx2oldf,double &vx3oldf)
+{
+   LBMReal muRE = 1.002*1e-3;//m2/s
+   double mass=2.3*1e-17;// kg
+   double Diameter=600*1e-9;//m
+   double deltatime=conv->getFactorTimeLbToW(dx)*0.001;
+   double Coff=3*PI*Diameter*muRE*deltatime/mass;
+   double exCoff=exp(-Coff);
+   //velocity of particle/// 
+   double velx1oldf=vx1;
+   double velx2oldf=vx2;
+   double velx3oldf=vx3;
+   //air
+   vx1=vx1old*exCoff+(velx1oldf-(velx1oldf)*exCoff);
+   vx2=vx2old*exCoff+(velx2oldf-(velx2oldf)*exCoff);
+   vx3=vx3old*exCoff+(velx3oldf-(velx3oldf)*exCoff);
+
+   vx1oldf=velx1oldf;
+   vx2oldf=velx2oldf;
+   vx3oldf=velx3oldf;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::findPlane(int ix1,int ix2,int ix3,Grid3DPtr grid,Block3DPtr block,double &A,double &B,double &C,double &D,double &ii)
+{
+   double x1plane=0.0,y1plane=0.0,z1plane=0.0;
+   double x2plane=0.0,y2plane=0.0,z2plane=0.0;
+   double x3plane=0.0,y3plane=0.0,z3plane=0.0;
+   D3Q27BoundaryConditionPtr bcPtr;
+   double dx = grid->getDeltaX(block);
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+   BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+   for (int k = ix3; k <= ix3 + 1; k++){
+      for(int j = ix2; j <= ix2 + 1; j++){
+         for(int i = ix1; i <= ix1 + 1; i++)
+         {
+            UbTupleDouble3 pointplane1 =  grid->getNodeCoordinates(block,  i,	  j,	 k);
+
+            double   iph=val<1>(pointplane1);
+            double   jph=val<2>(pointplane1);
+            double   kph=val<3>(pointplane1);
+
+            if(!bcArray.isSolid(i, j, k))
+            {
+               bcPtr=bcArray.getBC(i,j,k);
+               if(bcPtr)
+               {	 
+                  for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                  {
+                     if( ii<=2)
+                     {
+                        LBMReal q = bcPtr->getQ(fdir);
+                        if (q!=999.00000)
+                        {
+
+                           if     ( fdir==D3Q27System::E ) 
+                           {
+                              if (i+q<=ix1+1)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph+q*dx;	  y1plane=jph;	 z1plane=kph;    	ii++;	} 
+                                 else if (ii==1) 	{	x2plane=iph+q*dx;     y2plane=jph;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if(ii==2) 	    {   x3plane=iph+q*dx;     y3plane=jph;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+                           if     ( fdir==D3Q27System::W ) 
+                           {
+                              if (i-q>=ix1)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph-q*dx;	  y1plane=jph;	 z1plane=kph;    	ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph-q*dx;    y2plane=jph;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if(ii==2) 	    {   x3plane=iph-q*dx;    y3plane=jph;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+                           if     ( fdir==D3Q27System::N ) 
+                           {
+                              if(j+q<=ix2+1)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph;	y1plane=jph+q*dx;	 z1plane=kph; 	    ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph;    y2plane=jph+q*dx;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if (ii==2) 	    {   x3plane=iph;    y3plane=jph+q*dx;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+                           if     ( fdir==D3Q27System::S ) 
+                           {
+                              if (j-q>=ix2)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph;	y1plane=jph-q*dx;	 z1plane=kph; 	ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph;    y2plane=jph-q*dx;	 z2plane=kph;	if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if (ii==2) 	    {   x3plane=iph;    y3plane=jph-q*dx;	 z3plane=kph;   if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+
+                           if     ( fdir==D3Q27System::T ) 
+                           {
+                              if(k+q<=ix3+1)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph;	y1plane=jph;	 z1plane=kph+q*dx; 	    ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph;    y2plane=jph;	 z2plane=kph+q*dx;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if (ii==2) 	    {   x3plane=iph;    y3plane=jph;	 z3plane=kph+q*dx;      if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+                           if     ( fdir==D3Q27System::B ) 
+                           {
+                              if (k-q>=ix3)
+                              {
+                                 if      (ii==0)	    {	x1plane=iph;	y1plane=jph;	 z1plane=kph-q*dx; 	ii++;	} 
+                                 else if (ii==1) 	    {	x2plane=iph;    y2plane=jph;	 z2plane=kph-q*dx;	  if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                 else if (ii==2) 	    {   x3plane=iph;    y3plane=jph;	 z3plane=kph-q*dx;     if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                              }
+                           }
+
+                        }
+                     }
+                  }
+
+               }
+
+            }
+         }
+      }
+   }
+
+   A =   y1plane* (z2plane - z3plane) + y2plane*(z3plane - z1plane) + y3plane* (z1plane - z2plane);   
+   B =   z1plane* (x2plane - x3plane) + z2plane*(x3plane - x1plane) + z3plane* (x1plane - x2plane) ;      
+   C =   x1plane* (y2plane - y3plane) + x2plane*(y3plane - y1plane) + x3plane* (y1plane - y2plane) ;       
+   D =-( x1plane*(y2plane*z3plane - y3plane*z2plane)+x2plane*(y3plane*z1plane - y1plane*z3plane) + x3plane* (y1plane* z2plane - y2plane* z1plane));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::findInitialCell(double s,double di,double dj,double dk,double dx,double ix1ph,double ix2ph,double ix3ph,double &xp000,double &yp000,double &zp000)
+{
+   if (s*di>0)         {            xp000=ix1ph+dx;    }
+   else if(s*di<0)     {            xp000=ix1ph-dx;    }
+   else                {            xp000=ix1ph;      }
+   if (s*dj>0)         {            yp000=ix2ph+dx;    }
+   else if(s*dj<0)     {            yp000=ix2ph-dx;    }
+   else                {            yp000=ix2ph;      }
+   if (s*dk>0)         {            zp000=ix3ph+dx;    }
+   else if(s*dk<0)     {            zp000=ix3ph-dx;    }
+   else                {            zp000=ix3ph;      }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::finddisPointToCentercell(double x1,double x2,double x3,double xp000, double yp000, double zp000,double &dis,int level)
+{	
+   UbTupleInt3 blockIndexes = grid->getBlockIndexes(xp000, yp000,  zp000,level);
+   Block3DPtr block = grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+   if(block&& block->isActive())
+   {
+      LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+      if (kernel)
+      {
+         {
+            DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+            BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+            if(block && block->isActive())
+            {	
+               double dx = grid->getDeltaX(block);
+               UbTupleInt3 nodeIndexes = grid->getNodeIndexes(block,  xp000, yp000,  zp000);
+               int ix1Se = val<1>(nodeIndexes);
+               int ix2Se = val<2>(nodeIndexes);
+               int ix3Se = val<3>(nodeIndexes);  
+               if     (!iProcessor->iCellHasSolid(bcArray, ix1Se, ix2Se,  ix3Se  ))        
+               {				 
+                  UbTupleDouble3 pointCell =  grid->getNodeCoordinates(block,  ix1Se,	  ix2Se,	 ix3Se);	 double   iph=val<1>(pointCell)+dx/2.0;	 double   jph=val<2>(pointCell)+dx/2.0;	 double   kph=val<3>(pointCell)+dx/2.0;
+                  dis=sqrt((iph-x1)*(iph-x1)+(jph-x2)*(jph-x2)+(kph-x3)*(kph-x3));
+               }
+            }	 	 	
+         }
+      }
+
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::collWall(double A,double B,double C,double D,double &x1,double &x2,double &x3,double x1old,double x2old,double x3old,double dx,double &vx1,double &vx2,double &vx3,double ii)
+{
+   if (particleHasMass)
+   {
+      double s = A*x1 + B*x2 + C*x3 + D;//The sign of s = Ax + By + Cz + D determines which side the point (x,y,z) lies with respect to the plane. If s > 0 then the point lies on the same side as the normal (A,B,C). If s < 0 then it lies on the opposite side, if s = 0 then the point (x,y,z) lies on the plane.
+      if (s>0){s=1;} else if (s<0){s=-1;}else {s=0;}
+      double normalDis=((A*x1 + B*x2 + C*x3 + D)/sqrt(A*A+B*B+C*C));///distance point to plane xp-Xw=distance
+      double di=A/sqrt(A*A+B*B+C*C);      double dj=B/sqrt(A*A+B*B+C*C);       double dk=C/sqrt(A*A+B*B+C*C);
+      A*=s;B*=s;C*=s;
+      if (abs(normalDis)<0.05*dx)
+      {
+         if (ii==3)
+         {
+            ///reflection without e factor
+            /*  double vn=(A*vx1 + B*vx2 + C*vx3)/(A*A+B*B+C*C);
+            double  vx1L=vx1-2*vn*A;
+            double  vx2L=vx2-2*vn*B;
+            double  vx3L=vx3-2*vn*C;*/
+            double vnx=A*(A*vx1 + B*vx2 + C*vx3)/(A*A+B*B+C*C);
+            double vny=B*(A*vx1 + B*vx2 + C*vx3)/(A*A+B*B+C*C);
+            double vnz=C*(A*vx1 + B*vx2 + C*vx3)/(A*A+B*B+C*C);
+            ////do collision  
+            double CollitionFactor_n=0.01;
+            double CollitionFactor_bt=0.01;
+            vnx=-1*CollitionFactor_n*vnx;
+            vny=-1*CollitionFactor_n*vny;
+            vnz=-1*CollitionFactor_n*vnz;
+            double vbtx=(B*B*vx1 + C*C*vx1 - A*B*vx2 - A*C*vx3)/(A*A+B*B+C*C);
+            double vbty=(-(A*B*vx1) + A*A*vx2 + C*C*vx2 - B*C*vx3)/(A*A+B*B+C*C);
+            double vbtz=(-(A*C*vx1) - B*C*vx2 + A*A*vx3 + B*B*vx3)/(A*A+B*B+C*C);
+            vbtx=vbtx*CollitionFactor_bt;
+            vbty=vbty*CollitionFactor_bt;
+            vbtz=vbtz*CollitionFactor_bt;
+            vx1=vnx+vbtx;
+            vx2=vny+vbty;
+            vx3=vnz+vbtz;
+
+            x1 = (x1old);
+            x2 = (x2old);
+            x3 = (x3old);
+         } 
+         else   std::cout<<"there is no plane to reflect";
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::addCorrection(double &vx1,double &vx2,double &vx3,double &tauxx,double &tauyy,double &tauzz,double &tauxy,double &tauxz,double &tauyz,
+                                                     double dx,D3Q27ICell iCell,double Xw, double Yw, double Zw,double  omega,double cofWeightx,double cofWeighty,double cofWeightz,double ii,double x1LB,double x2LB,double x3LB,double di,double dj,double dk)
+{
+   //LBMReal f[D3Q27System::ENDF+1];
+   double  Udif,Vdif,Wdif;	  
+   iHelper->interpolate8to1WithVelocity(iCell, Xw, Yw, Zw, omega,Udif,Vdif,Wdif);
+
+   double Ucx,Ucy,Ucz;
+   double Vcx,Vcy,Vcz;
+   double Wcx,Wcy,Wcz;
+
+   double dxUcx,dyUcy,dzUcz;
+   double dxVcx,dyVcy,dzVcz;
+   double dxWcx,dyWcy,dzWcz;
+   //double di,dj,dk;
+
+   if (cofWeightx==0){di=0;}
+   if (cofWeighty==0){dj=0;}
+   if (cofWeightz==0){dk=0;}
+
+   double weightx=(di*di)/(di*di+dj*dj+dk*dk);
+   double weighty=(dj*dj)/(di*di+dj*dj+dk*dk);
+   double weightz=(dk*dk)/(di*di+dj*dj+dk*dk);
+   // /* if (Xw<0.5||Xw>-0.5){weightx=0;}
+   //  if (Yw<0.5||Yw>-0.5){weighty=0;}
+   //  if (Zw<0.5||Zw>-0.5){weightz=0;}
+   //*/
+   if (weightx==0){Ucx=0;Vcx=0;Wcx=0;dxUcx=0;dxVcx=0;dxWcx=0;}else{
+      Ucx=-Udif*weightx/(Xw*Xw*Xw-Xw/4.0)*(x1LB*x1LB*x1LB-x1LB/4.0);Vcx=-Vdif*weightx/(Xw*Xw*Xw-Xw/4.0)*(x1LB*x1LB*x1LB-x1LB/4.0);Wcx=-Wdif*weightx/(Xw*Xw*Xw-Xw/4.0)*(x1LB*x1LB*x1LB-x1LB/4.0);
+      dxUcx=-Udif*weightx/(Xw*Xw*Xw-Xw/4.0)*(3.0*x1LB*x1LB-1.0/4.0);dxVcx=-Vdif*weightx/(Xw*Xw*Xw-Xw/4.0)*(3.0*x1LB*x1LB-1.0/4.0);dxWcx=-Wdif*weightx/(Xw*Xw*Xw-Xw/4.0)*(3.0*x1LB*x1LB-1.0/4.0);
+   }
+   if (weighty==0){Ucy=0;Vcy=0;Wcy=0;dyUcy=0;dyVcy=0;dyWcy=0;}else{
+      Ucy=-Udif*weighty/(Yw*Yw*Yw-Yw/4.0)*(x2LB*x2LB*x2LB-x2LB/4.0);Vcy=-Vdif*weighty/(Yw*Yw*Yw-Yw/4.0)*(x2LB*x2LB*x2LB-x2LB/4.0);Wcy=-Wdif*weighty/(Yw*Yw*Yw-Yw/4.0)*(x2LB*x2LB*x2LB-x2LB/4.0);
+      dyUcy=-Udif*weighty/(Yw*Yw*Yw-Yw/4.0)*(3.0*x2LB*x2LB-1.0/4.0);dyVcy=-Vdif*weighty/(Yw*Yw*Yw-Yw/4.0)*(3.0*x2LB*x2LB-1.0/4.0);dyWcy=-Wdif*weighty/(Yw*Yw*Yw-Yw/4.0)*(3.0*x2LB*x2LB-1.0/4.0);
+   }
+   if (weightz==0){Ucz=0;Vcz=0;Wcz=0;dzUcz=0;dzVcz=0;dzWcz=0;}else{
+      Ucz=-Udif*weightz/(Zw*Zw*Zw-Zw/4.0)*(x3LB*x3LB*x3LB-x3LB/4.0);Vcz=-Vdif*weightz/(Zw*Zw*Zw-Zw/4.0)*(x3LB*x3LB*x3LB-x3LB/4.0);Wcz=-Wdif*weightz/(Zw*Zw*Zw-Zw/4.0)*(x3LB*x3LB*x3LB-x3LB/4.0);
+      dzUcz=-Udif*weightz/(Zw*Zw*Zw-Zw/4.0)*(3.0*x3LB*x3LB-1.0/4.0);dzVcz=-Vdif*weightz/(Zw*Zw*Zw-Zw/4.0)*(3.0*x3LB*x3LB-1.0/4.0);dzWcz=-Wdif*weightz/(Zw*Zw*Zw-Zw/4.0)*(3.0*x3LB*x3LB-1.0/4.0);
+   }
+
+   double Ucor=Ucx+Ucy+Ucz;
+   double Vcor=Vcx+Vcy+Vcz;
+   double Wcor=Wcx+Wcy+Wcz;
+
+   double tauxxC=dxUcx;
+   double tauyyC=dyVcy;
+   double tauzzC=dzWcz;
+   double tauxyC=0.5*(dyUcy+dxVcx);
+   double tauxzC=0.5*(dzUcz+dxWcx);
+   double tauyzC=0.5*(dzVcz+dyWcy);
+
+   if (ii!=3) 
+   {
+      //std::cout<<"there are not 3point for making plane"<<endl<<"Ucor="<<Ucor<<endl<<"vx1="<<vx1;
+      Ucor  =0.0;
+      Vcor  =0.0;
+      Wcor  =0.0;
+      tauxxC=0.0;
+      tauyyC=0.0;
+      tauzzC=0.0;
+      tauxyC=0.0;
+      tauxzC=0.0;
+      tauyzC=0.0;
+   }
+
+   vx1+=Ucor;
+   vx2+=Vcor;
+   vx3+=Wcor;
+   tauxx+=tauxxC;
+   tauyy+=tauyyC;
+   tauzz+=tauzzC;
+   tauxy+=tauxyC;
+   tauxz+=tauxzC;
+   tauyz+=tauyzC;
+
+   vx1 = vx1 *  conv->getFactorVelocityLbToW();
+   vx2 = vx2 *  conv->getFactorVelocityLbToW();
+   vx3 = vx3 *  conv->getFactorVelocityLbToW();
+   tauxx=tauxx/dx;
+   tauyy=tauyy/dx;
+   tauzz=tauzz/dx;
+   tauxy=tauxy/dx;
+   tauxz=tauxz/dx;
+   tauyz=tauyz/dx;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::getAllDis(double dis[],double x,double y,double z,double ix1ph,double ix2ph,double ix3ph,double xp000,double yp000,double zp000,int level)
+{
+   finddisPointToCentercell(x,y,z,xp000, ix2ph,  ix3ph,dis[0],level);//disx  
+   finddisPointToCentercell(x,y,z,ix1ph, yp000,  ix3ph,dis[1],level);//disy  
+   finddisPointToCentercell(x,y,z,ix1ph, ix2ph,  zp000,dis[2],level);//disz  
+   finddisPointToCentercell(x,y,z,xp000, yp000,  ix3ph,dis[3],level);//disxy 
+   finddisPointToCentercell(x,y,z,xp000, ix2ph,  zp000,dis[4],level);//disxz 
+   finddisPointToCentercell(x,y,z,ix1ph, yp000,  zp000,dis[5],level);//disyz 
+   finddisPointToCentercell(x,y,z,xp000, yp000,  zp000,dis[6],level);//disxyz  	   
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::getAfterCompare(double dis[],double dx,double ix1ph,double ix2ph,double ix3ph,double &xp000,double &yp000,double &zp000,double &Xw,
+                                                       double &Yw,double &Zw,double x1,double x2,double x3,double A,double B,double C,double D,double normalDis, double di,double dj,double dk, double &cofWeightx
+                                                       ,double &cofWeighty,double &cofWeightz,D3Q27ICell &iCell,int level)
+{
+   for (int i=0;i<7;i++)
+   {	
+      double dist=dis[i];
+      if      (dist==dirx  ){ Xw=(B*x2+C*x3+D)/(-A); Yw=x2;                 Zw=x3;	         	cofWeightx=1; cofWeighty=0; cofWeightz=0;  xp000=xp000;	yp000=ix2ph; zp000=ix3ph; getIcell(iCell,xp000, ix2ph, ix3ph,level); } //get suitable block from suitable cell
+      else if (dist==diry  ){ Xw=x1;                 Yw=(A*x1+C*x3+D)/(-B); Zw=x3;		        cofWeightx=0; cofWeighty=1; cofWeightz=0;  xp000=ix1ph;	yp000=yp000; zp000=ix3ph; getIcell(iCell,ix1ph, yp000, ix3ph,level); } 
+      else if (dist==dirz  ){ Xw=x1;                 Yw=x3;	              Zw=(B*x2+A*x1+D)/(-C);cofWeightx=0; cofWeighty=0; cofWeightz=1;  xp000=ix1ph;	yp000=ix2ph; zp000=zp000; getIcell(iCell,ix1ph, ix2ph, zp000,level); } 
+      else if (dist==dirxy ){ Xw=x1-di*normalDis;    Yw=x2-dj*normalDis;    Zw=x3;        		cofWeightx=1; cofWeighty=1; cofWeightz=0;  xp000=xp000; yp000=yp000; zp000=ix3ph; getIcell(iCell,xp000, yp000, ix3ph,level); } 
+      else if (dist==dirxz ){ Xw=x1-di*normalDis;    Yw=x2;                 Zw=x3-dk*normalDis;	cofWeightx=1; cofWeighty=0; cofWeightz=1;  xp000=xp000;	yp000=ix2ph; zp000=zp000; getIcell(iCell,xp000, ix2ph, zp000,level); } 
+      else if (dist==diryz ){ Xw=x1;                 Yw=x2-dj*normalDis;    Zw=x3-dk*normalDis;	cofWeightx=0; cofWeighty=1; cofWeightz=1;  xp000=ix1ph;	yp000=yp000; zp000=zp000; getIcell(iCell,ix1ph, yp000, zp000,level); } 
+      else if (dist==dirxyz){ Xw=x1-di*normalDis;    Yw=x2-dj*normalDis;    Zw=x3-dk*normalDis;	cofWeightx=1; cofWeighty=1; cofWeightz=1;  xp000=xp000;	yp000=yp000; zp000=zp000; getIcell(iCell,xp000, yp000, zp000,level); } 
+
+      Xw=(Xw-xp000)/dx-0.5;       
+      Yw=(Yw-yp000)/dx-0.5;       
+      Zw=(Zw-zp000)/dx-0.5;
+      if (Xw<2.5&&Xw>-2.5&&Yw<2.50&&Yw>-2.50&&Zw<2.50&&Zw>-2.50){break;}      
+   }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::rearangedDouble( double dis[7])
+{
+   double item;
+   for (int i=6;i>0;i--){   
+      for(int j=0;j<i;j++){ 
+         if (dis[j]>dis[j+1])
+         {	  
+            item=dis[j];  
+            dis[j]=dis[j+1]; 
+            dis[j+1]=item;					   
+         }
+      }
+   } 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::getIcell(D3Q27ICell &iCell,double xp000, double yp000, double zp000,int level)
+{ 
+   UbTupleInt3 blockIndexes = grid->getBlockIndexes(xp000, yp000, zp000,level);
+   Block3DPtr block= grid->getBlock(val<1>(blockIndexes), val<2>(blockIndexes), val<3>(blockIndexes), level);
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+   iProcessor->readICell(distributions, iCell, (int)xp000, (int)yp000, (int)zp000);
+}
+////////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::printParticle(ParticlesPtr particle)
+
+{
+   /*BOOST_FOREACH(ParticlesPtr particle, particles)
+   {*/
+   int index=particle->ID;
+   (*files[index]).precision (std::numeric_limits<double>::digits10 + 1);
+   (*files[index])<<index<<" "<<istep<<" "<<particle->x<<"  "<< particle->y<<"  "<<particle->z<<" "<<particle->vxold<<"  "<<particle->vyold<<"  "<<particle->vzold<< std::endl;
+   //}
+}
+
+///////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::printParticle(int index)
+
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PathLinePostprocessorMcpart::gatherData(ParticlesPtr particle)
+{
+   //int index=particle->ID;
+   //std::vector<std::vector<double> > tempData;
+   //tempData.resize(7);
+   //if (!data.count(index ))	
+   //{	
+   //	data.insert((std::make_pair(index,tempData)));	
+   //}
+   //tempData=data.at(index);
+   //int t=0;
+   //tempData[t++].push_back(istep);
+   //tempData[t++].push_back(particle->x);
+   //tempData[t++].push_back(particle->y);
+   //tempData[t++].push_back(particle->z);
+   //tempData[t++].push_back(particle->vxold);
+   //tempData[t++].push_back(particle->vyold);
+   //tempData[t++].push_back(particle->vzold);
+
+   //  data.at(index)=tempData;
+
+   datanames.resize(0);
+   datanames.push_back("ID");
+   datanames.push_back("TimeStep");
+   datanames.push_back("Vx");
+   datanames.push_back("Vy");
+   datanames.push_back("Vz");
+   //datanames.push_back("tauxx");
+   //datanames.push_back("tauyy");
+   //datanames.push_back("tauzz");
+   //datanames.push_back("tauxy");
+   //datanames.push_back("tauxz");
+   //datanames.push_back("tauyz");
+   //datanames.push_back("xoff");
+   //datanames.push_back("yoff");
+   //datanames.push_back("zoff");
+
+   data.resize(datanames.size());
+
+   int index = 0;
+   data[index++].push_back(particle->ID);
+   data[index++].push_back(istep);
+   data[index++].push_back(particle->vxold);
+   data[index++].push_back(particle->vyold);
+   data[index++].push_back(particle->vzold);
+   //data[index++].push_back(tauxx);
+   //data[index++].push_back(tauyy);
+   //data[index++].push_back(tauzz);
+   //data[index++].push_back(tauxy);
+   //data[index++].push_back(tauxz);
+   //data[index++].push_back(tauyz);
+   //data[index++].push_back(xoff);
+   //data[index++].push_back(yoff);
+   //data[index++].push_back(zoff);
+
+   nodes.push_back( makeUbTuple(  double(particle->x), double(particle->y), double(particle->z)) );
+
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessorMcpart.h b/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessorMcpart.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d84fb4376a705e5e460a5b89286bf4962043021
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27PathLinePostprocessorMcpart.h
@@ -0,0 +1,133 @@
+/*
+*  PathLinePostprocessor.h
+*
+*  Created on: 3.6.2012
+*  Author: Fard
+*/
+
+
+#ifndef PATHLINEPOSTPROCESSORMCPART_H
+#define PATHLINEPOSTPROCESSORMCPART_H
+
+# define dirx 0
+# define diry 1
+# define dirz 2
+# define dirxy 3 
+# define dirxz 4 
+# define diryz 5
+# define dirxyz 6
+#include <mpi.h>
+#include "Postprocessor.h"
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include <boost/shared_ptr.hpp>
+//#include <boost/tr1/memory.hpp>
+#include "Particles.h"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+
+class D3Q27PathLinePostprocessorMcpart;
+typedef boost::shared_ptr<D3Q27PathLinePostprocessorMcpart> D3Q27PathLinePostprocessorMcpartPtr;
+
+class D3Q27PathLinePostprocessorMcpart : public Postprocessor  
+{
+public:
+   //typedef std::map<int,ParticlesPtr> ParticlesMap;
+   std::map<int,int> neighbors;
+   //std::map<ofstream,std::vector<int> > pathOfstream;
+   D3Q27PathLinePostprocessorMcpart(Grid3DPtr grid, const std::string& path, WbWriter* const writer,
+      LBMUnitConverterPtr conv, UbSchedulerPtr s, CommunicatorPtr comm, 
+      std::vector<UbTupleDouble3 > Positions, LBMReal nue, D3Q27InterpolationProcessorPtr iProcessor);
+   ~D3Q27PathLinePostprocessorMcpart();
+   void update(double step);
+   void getNeighborsRank();
+
+protected:
+   void collectPostprocessData();
+   //void getParticles(std::vector<Particles> *particles,std::vector<UbTupleDouble3> x);
+   void initializeParticle(double x, double y,double z,int i,int level);
+   void getParticlePerProccess(std::vector<UbTupleDouble3 >);
+   void getParticle(Particles &particle, double dx,double x, double y,double z,int level,int i);
+   void initialMovement();
+   void updateDistributedValues(std::vector<Particles> *particles,std::vector<UbTupleDouble3> &x);
+   void receiveStatusOfPoint(bool &status,int rankRoot,double x1,double x2,double x3,double level);
+   void sendStatusOfPoint(bool status,double x1,double x2,double x3,double level,int i);
+   void receiveBool(bool &variable,int rankBlock);
+   void receiveInt(int &rvalue,int root);
+   void sendBool(bool _bool,int distinationRank,int i );
+   void sendInt(int svalue,int distinationRank ,int tag);
+   void getVectorFromParticles(std::vector<double> &particlesInfomation,ParticlesPtr particles);
+   void getParticlesFromVector(std::vector<double> particlesInfomation,int numberOFVariable);
+   void updateinfo(std::vector<Particles> *particlesVec,std::vector<UbTupleDouble3> &x);
+   void allGatherDoubles(std::vector<double>& svalues, std::vector<double>& rvalues);
+   void fillOutPositions(std::vector<double> particlesInfomation,std::vector<UbTupleDouble3> &x,double numberOFVariable);
+   void updateParticles();
+   void checkParticles();
+   void finalMovement(ParticlesPtr particle,double tau[]);
+   void interpolMovement(Block3DPtr block,DistributionArray3DPtr& distributions,ParticlesPtr particle,double tau[],int ix1, int ix2, int ix3);
+   void extrapolMovement(Block3DPtr block, ParticlesPtr particle,double tau[],int ix1, int ix2, int ix3);
+   void findPlane(int ix1,int ix2,int ix3,Grid3DPtr grid,Block3DPtr block,double &A,double &B,double &C,double &D,double &ii);
+   void CalcVelParticle2(double dx,double &vx1,double &vx2,double &vx3,double vx1old,double vx2old,double vx3old,double &vx1oldf,double &vx2oldf,double &vx3oldf);
+   void CalcVelParticle(double dx,double &vx1,double &vx2,double &vx3,double vx1old,double vx2old,double vx3old,double &vx1oldf,double &vx2oldf,double &vx3oldf);
+   void findInitialCell(double s,double di,double dj,double dk,double dx,double ix1ph,double ix2ph,double ix3ph,double &xp000,double &yp000,double &zp000);
+   void finddisPointToCentercell(double x1,double x2,double x3,double xp000, double yp000, double zp000,double &dis,int level);
+   void collWall(double A,double B,double C,double D,double &x1,double &x2,double &x3,double x1old,double x2old,double x3old,double dx,double &vx1,double &vx2,double &vx3,double ii);
+   void addCorrection(double &vx1,double &vx2,double &vx3,double &tauxx,double &tauyy,double &tauzz,double &tauxy,double &tauxz,double &tauyz,
+      double dx,D3Q27ICell iCell,double Xw, double Yw, double Zw,double  omega,double cofWeightx,double cofWeighty,double cofWeightz,double ii,double x1LB,double x2LB,double x3LB,double di,double dj,double dk);
+   void getAllDis(double dis[],double x,double y,double z,double ix1ph,double ix2ph,double ix3ph,double xp000,double yp000,double zp000,int level);
+   void rearangedDouble( double dis[7]);
+   void getWallPosition(double dx,double xp000,double yp000,double zp000,double &Xw,double &Yw,double &Zw,double x1,double x2,double x3,double A
+      ,double B,double C,double D,double normalDis, double di,double dj,double dk, double &cofWeightx,double &cofWeighty,double &cofWeightz,int dir);
+   void getIcell(D3Q27ICell &iCell,double xp000, double yp000, double zp000,int level);
+   void getAfterCompare(double dis[],double dx,double ix1ph,double ix2ph,double ix3ph,double &xp000,double &yp000,double &zp000,double &Xw,
+      double &Yw,double &Zw,double x1,double x2,double x3,double A,double B,double C,double D,double normalDis, double di,double dj,double dk, double &cofWeightx
+      ,double &cofWeighty,double &cofWeightz,D3Q27ICell &iCell,int level);
+   void printParticle(ParticlesPtr particle);
+   void printParticle(int index);
+   void initializeForPrinting(int number);
+   void gatherData(ParticlesPtr particle);
+private:
+   bool checkNodes(Block3DPtr block,double _x1,double _x2,double _x3);
+   CommunicatorPtr comm;
+   //std::map<int ,std::vector<UbTupleDouble3> > nodes;
+   //std::map<int ,std::vector<std::string> >datanames;
+   //std::map<int ,std::vector<std::vector<double> > >data;
+
+   std::vector<UbTupleDouble3> nodes;
+   std::vector<std::string> datanames;
+   std::vector<std::vector<double> > data;
+
+   std::vector<boost::shared_ptr<std::ofstream> > files;
+   std::string path;
+   WbWriter* writer;
+   LBMUnitConverterPtr conv;
+
+   D3Q27InterpolationProcessorPtr interpolation;
+   //std::vector<UbTupleDouble3> x;
+   //std::vector<UbTupleDouble3> xold;
+   //std::vector<UbTupleDouble3 >vxold;
+   //std::vector<UbTupleDouble3 > vxoldf;
+   bool particleHasMass;
+   int isExtrapolation;
+   int istep;
+   int stepcheck;
+   LBMReal nue;
+   D3Q27InterpolationProcessorPtr iProcessor;
+   D3Q27InterpolationHelperPtr iHelper;
+   //Particles particles;
+   int rank;
+   int root;
+   int maxtag;
+   std::list<ParticlesPtr> particles;
+   //std::vector<std::vector<UbTupleDouble3> > Positions;
+   //Particles particles;
+
+   //ParticlesMap particles;
+
+};
+#endif
+
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27PressureDifferencePostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/D3Q27PressureDifferencePostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9dee7e1c42de85ed92d13f2e6f357f8819ce80d7
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27PressureDifferencePostprocessor.cpp
@@ -0,0 +1,99 @@
+/*
+ * D3Q27RhoPostprocessor.cpp
+ *
+ *  Created on: 28.12.2010
+ *      Author: kucher
+ */
+
+#include "D3Q27PressureDifferencePostprocessor.h"
+
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+D3Q27PressureDifferencePostprocessor::D3Q27PressureDifferencePostprocessor(Grid3DPtr grid, UbSchedulerPtr s, const std::string& path,
+                                                                 D3Q27IntegrateValuesHelperPtr h1, D3Q27IntegrateValuesHelperPtr h2, 
+                                                                 LBMReal rhoReal, LBMReal uReal, LBMReal uLB,
+                                                                 CommunicatorPtr comm)
+
+                                                : Postprocessor(grid, s)
+                                                , path(path)
+																, h1(h1)
+																, h2(h2)
+                                                ,comm(comm)
+{
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      std::ofstream ostr;
+      string fname = path;
+      ostr.open(fname.c_str(), std::ios_base::out);
+      if(!ostr)
+      { 
+         ostr.clear();
+         string path = UbSystem::getPathFromString(fname);
+         if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out);}
+         if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+      }
+      ostr << "step" << "\t" << "nodes1" << "\t" << "nodes2" << "\t";
+      ostr << "sRho1" << "\t" << "p1_1"  << "\t" << "sRho2" << "\t" << "p1_2" << "\t" << "deltaP1"<< "\t";
+      ostr << "sPress1" << "\t" << "p2_1" << "\t" << "sPress2" << "\t" << "p2_2" << "\t" << "deltaP2";
+      ostr << endl;
+      ostr.close();
+
+      factor1 = (1.0/3.0)*rhoReal*(uReal/uLB)*(uReal/uLB);
+      factor2 = rhoReal*(uReal/uLB)*(uReal/uLB);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27PressureDifferencePostprocessor::~D3Q27PressureDifferencePostprocessor() 
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PressureDifferencePostprocessor::update(double step)
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27PressureDifferencePostprocessor::collectPostprocessData(double step)
+{
+   h1->calculateMQ();
+   h2->calculateMQ();
+   
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      int istep = static_cast<int>(step);
+      std::ofstream ostr;
+      double nn1 = h1->getNumberOfFluidsNodes();
+      double nn2 = h2->getNumberOfFluidsNodes();
+      double rho1 = h1->getRho();
+      double rho2 = h2->getRho();
+      double p1_1 = (rho1/nn1) * factor1;
+      double p1_2 = (rho2/nn2) * factor1;
+      double dp1 = p1_1 - p1_2;
+
+      //double press1 = h1->getPress();
+      //double press2 = h2->getPress();
+      //double p2_1 = (press1/nn1) * factor2;
+      //double p2_2 = (press2/nn2) * factor2;
+      //double dp2 = p2_1 - p2_2;
+
+      string fname = path;
+      ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);
+      if(!ostr)
+      { 
+         ostr.clear();
+         string path = UbSystem::getPathFromString(fname);
+         if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);}
+         if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+      }
+
+      ostr << istep << "\t" << nn1 << "\t"  << nn2 << "\t"; 
+      ostr << rho1 << "\t" << p1_1 << "\t" << rho2 << "\t" << p1_2 << "\t" << dp1 << "\t";
+      //ostr << press1 << "\t" << p2_1 << "\t" << press2 << "\t" << p2_2 << "\t" << dp2;
+      ostr << endl;
+      ostr.close();
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27PressureDifferencePostprocessor.h b/source/VirtualFluidsCore/CoProcessors/D3Q27PressureDifferencePostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..28b080bfb3910df180dda306fe155f492a8ee9c8
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27PressureDifferencePostprocessor.h
@@ -0,0 +1,35 @@
+/*
+ *  D3Q27PressureDifferencePostprocessor.h
+ *
+ *  Created on: 28.12.2010
+ *  Author: kucher
+ */
+
+#ifndef D3Q27PRESSUREDIFFERENCEPOSTPROCESSOR_H
+#define D3Q27PRESSUREDIFFERENCEPOSTPROCESSOR_H
+
+#include "Postprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+
+class D3Q27PressureDifferencePostprocessor: public Postprocessor {
+public:
+	D3Q27PressureDifferencePostprocessor(Grid3DPtr grid, UbSchedulerPtr s, const std::string& path, 
+                                   D3Q27IntegrateValuesHelperPtr h1, D3Q27IntegrateValuesHelperPtr h2, 
+                                   LBMReal rhoReal, LBMReal uReal, LBMReal uLB,
+                                   /*const LBMUnitConverterPtr conv,*/ CommunicatorPtr comm);
+	virtual ~D3Q27PressureDifferencePostprocessor();
+	void update(double step);
+protected:
+	D3Q27IntegrateValuesHelperPtr h1, h2;
+   std::string path;
+   LBMUnitConverterPtr conv;
+	void collectPostprocessData(double step);
+   CommunicatorPtr comm;
+   LBMReal factor1; //= (1/3)*rhoReal*(uReal/uLB)^2 for calculation pReal = rhoLB * (1/3)*rhoReal*(uReal/uLB)^2, rhoReal and uReal in SI
+   LBMReal factor2; //= rhoReal*(uReal/uLB)^2       for calculation pReal = press * rhoReal*(uReal/uLB)^2,       rhoReal and uReal in SI
+};
+
+
+#endif /* D3Q27RHODIFFERENCEPOSTPROCESSOR_H_ */
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27ShearStressPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/D3Q27ShearStressPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b57dab49772d35f1001ee3c20584aa5087baf728
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27ShearStressPostprocessor.cpp
@@ -0,0 +1,693 @@
+#include "D3Q27ShearStressPostprocessor.h"
+#include "D3Q27ETBCProcessor.h"
+#include "WbWriterVtkXmlASCII.h"
+
+
+D3Q27ShearStressPostprocessor::D3Q27ShearStressPostprocessor(Grid3DPtr grid, const std::string& path, 
+                                                             WbWriter* const writer,
+                                                             UbSchedulerPtr s,UbSchedulerPtr rs)
+                                                             : Postprocessor(grid, s),
+                                                             Resetscheduler(rs),
+                                                             path(path),
+                                                             writer(writer)
+{
+   CommunicatorPtr comm = Communicator::getInstance();
+   normals.push_back(0);
+   normals.push_back(0);
+   normals.push_back(1);
+   gridRank  = grid->getRank();
+   minInitLevel = this->grid->getCoarsestInitializedLevel();
+   maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   blockVector.resize(maxInitLevel+1);
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         UbTupleInt3 nx = grid->getBlockNX();
+         ShearStressValuesArray3DPtr shearStressValues = ShearStressValuesArray3DPtr(new ShearStressValuesArray3D(14, val<1>(nx)+1, val<2>(nx)+1, val<3>(nx)+1, 0.0));
+         block->getKernel()->getDataSet()->setShearStressValues(shearStressValues);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27ShearStressPostprocessor::~D3Q27ShearStressPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::update( double step )
+{
+   if (step==0)
+   {
+      initDistance();
+   }
+   calculateShearStress(step);
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+   UBLOG(logDEBUG3, "D3Q27ShearStressPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::collectPostprocessData(double step)
+{
+   using namespace std;
+
+   int istep = int(step);
+   addPostprocessData();
+
+   //string partName = writer->writeNodesWithNodeData(path+ UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep),nodes,datanames,data);
+   //size_t found=partName.find_last_of("//");
+   //string piece = partName.substr(found+1);
+
+   //vector<string> cellDataNames;
+
+   //CommunicatorPtr comm = Communicator::getInstance();
+   //vector<string> pieces = comm->gatherStrings(piece);
+   //if (comm->getProcessID() == comm->getRoot())
+   //{
+   //   string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(path+"_"+UbSystem::toString(istep),pieces,datanames,cellDataNames);
+
+   //   vector<string> filenames;
+   //   filenames.push_back(pname);
+   //   if (step == Postprocessor::scheduler->getMinBegin())
+   //   {
+   //      WbWriterVtkXmlASCII::getInstance()->writeCollection(path+"__Shear_collection",filenames,istep,false);
+   //   } 
+   //   else
+   //   {
+   //      WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(path+"__Shear_collection",filenames,istep,false);
+   //   }
+   //   UBLOG(logINFO,"D3Q27ShearStressPostprocessor step: " << istep);
+   //}
+
+   string pfilePath, partPath, subfolder, cfilePath;
+   subfolder = "shs"+UbSystem::toString(istep);
+   pfilePath =  path+"/shs/"+subfolder;
+   cfilePath =  path+"/shs/shs_collection";
+   partPath = pfilePath+"/shs"+UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep);
+
+   string partName = writer->writeNodesWithNodeData(partPath,nodes,datanames,data);
+   size_t found=partName.find_last_of("/");
+   string piece = partName.substr(found+1);
+   piece = subfolder + "/" + piece;
+
+   vector<string> cellDataNames;
+   CommunicatorPtr comm = Communicator::getInstance();
+   vector<string> pieces = comm->gather(piece);
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(pfilePath,pieces,datanames,cellDataNames);
+      found=pname.find_last_of("/");
+      piece = pname.substr(found+1);
+
+      vector<string> filenames;
+      filenames.push_back(piece);
+      if (step == Postprocessor::scheduler->getMinBegin())
+      {
+         WbWriterVtkXmlASCII::getInstance()->writeCollection(cfilePath,filenames,istep,false);
+      } 
+      else
+      {
+         WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(cfilePath,filenames,istep,false);
+      }
+      UBLOG(logINFO,"D3Q27ShearStressPostprocessor step: " << istep);
+   }
+
+   clearData();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::clearData()
+{
+   nodes.clear();
+   datanames.clear();
+   data.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::calculateShearStress(double timeStep)
+{
+   using namespace D3Q27System;
+
+   LBMReal f[27];
+   LBMReal vx, vy, vz, sxx, syy, szz, sxy, syz, sxz;
+
+   BOOST_FOREACH(D3Q27InteractorPtr interactor, interactors)
+   {
+      typedef std::map<Block3DPtr, std::set< std::vector<int> > > TransNodeIndicesMap;
+      BOOST_FOREACH(TransNodeIndicesMap::value_type t, interactor->getTransNodeIndicesMap())
+      {
+         Block3DPtr block = t.first;
+         std::set< std::vector<int> >& transNodeIndicesSet = t.second;
+
+         LBMKernel3DPtr kernel = block->getKernel();
+         BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+         DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+         ShearStressValuesArray3DPtr ssv = kernel->getDataSet()->getShearStressValues();
+
+         int ghostLayer = kernel->getGhostLayerWidth();
+         LBMReal collFactor = kernel->getCollisionFactor();
+
+         int minX1 = ghostLayer;
+         int maxX1 = (int)bcArray.getNX1() - 1 - ghostLayer;
+         int minX2 = ghostLayer;
+         int maxX2 = (int)bcArray.getNX2() - 1 - ghostLayer;
+         int minX3 = ghostLayer;
+         int maxX3 = (int)bcArray.getNX3() - 1 - ghostLayer;
+
+         BOOST_FOREACH(std::vector<int> node, transNodeIndicesSet)
+         {
+            int ix1 = node[0];
+            int ix2 = node[1];
+            int ix3 = node[2];
+
+            //without ghost nodes
+            if (ix1 < minX1 || ix1 > maxX1 || ix2 < minX2 || ix2 > maxX2 ||ix3 < minX3 || ix3 > maxX3 ) continue;
+
+            if(bcArray.isFluid(ix1,ix2,ix3)) 
+            {
+               double q=(*ssv)(normalq,ix1,ix2,ix3) ;
+               double numPoint=(*ssv)(numberOfPoint,ix1,ix2,ix3) ;
+               if (q==0||numPoint!=3)continue;
+               // if (q==0)continue;
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               distributions->getDistribution(f, ix1, ix2, ix3);
+               //////////////////////////////////////////////////////////////////////////
+               //compute velocity
+               //////////////////////////////////////////////////////////////////////////
+               vx = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) +
+                  (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) +
+                  (f[E]-f[W])); 
+
+               vy = ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) +
+                  (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) +
+                  (f[N]-f[S])); 
+
+               vz = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[TNW]-f[BSE]) + (f[TSW]-f[BNE]))) +
+                  (((f[TS]-f[BN]) + (f[TN]-f[BS])) + ((f[TW]-f[BE]) + (f[TE]-f[BW]))) +
+                  (f[T]-f[B]));
+
+
+               sxy = 3.0 * collFactor/(collFactor - 1.0)* ( ((f[TNE] + f[BSW])-(f[TSE]+f[BNW]))+(-(f[BSE]+f[TNW])+ (f[TSW]+f[BNE]))
+                  +(((f[NE] + f[SW]) - (f[SE] + f[NW])))  -vx*vy);
+
+               sxz = 3.0 * collFactor/(collFactor-1.0)*(((f[TNE] + f[BSW])+(f[TSE]+f[BNW]))+(-(f[BSE]+f[TNW])- (f[TSW]+f[BNE]))
+                  +((f[TE] + f[BW])-(f[BE]+ f[TW])) -vx*vz);
+
+               syz = 3.0 * collFactor/(collFactor-1.0)*(((f[TNE] + f[BSW])-(f[TSE]+f[BNW]))+((f[BSE]+f[TNW])- (f[TSW]+f[BNE]))
+                  +(-(f[BN] + f[TS]) + (f[TN] + f[BS])) -vy*vz);                 
+
+               LBMReal dxxMyy =3.0/2.0 * collFactor/(collFactor-1.0)* (((f[TE] + f[BW])+(f[BE]+ f[TW]))
+                  -((f[BN] + f[TS]) + (f[TN] + f[BS]))+((f[E] + f[W])-(f[N] + f[S]))-vx*vx+vy*vy);
+
+               LBMReal dxxMzz =3.0/2.0 * collFactor/(collFactor-1.0)*((((f[NE] + f[SW]) + (f[SE] + f[NW]))
+                  -((f[BN] + f[TS]) + (f[TN] + f[BS])))+((f[E] + f[W])-(f[T] + f[B])) -vx*vx +vz*vz);
+
+               // LBMReal dyyMzz =3.0/2.0 *collFactor/(collFactor-1.0)*((((f[NE] + f[SW]) + (f[SE] + f[NW]))-((f[TE] + f[BW])+(f[BE]+ f[TW])))
+               //    +((f[N] + f[S])-(f[T] + f[B])) -vy*vy +vz*vz);
+
+               sxx=(dxxMyy+dxxMzz)/3.0; // weil dxxPyyPzz=0
+
+               syy=(dxxMzz-2*dxxMyy)/3.0;
+
+               szz=(dxxMyy-2*dxxMzz)/3.0;
+
+               //////////////////////////////////////////////////////////////////////////
+               //compute average values
+               //////////////////////////////////////////////////////////////////////////
+               (*ssv)(AvVx,ix1,ix2,ix3) = ((*ssv)(AvVx,ix1,ix2,ix3)*timeStep + vx)/(timeStep+1.0);
+               (*ssv)(AvVy,ix1,ix2,ix3) = ((*ssv)(AvVy,ix1,ix2,ix3)*timeStep + vy)/(timeStep+1.0);
+               (*ssv)(AvVz,ix1,ix2,ix3) = ((*ssv)(AvVz,ix1,ix2,ix3)*timeStep + vz)/(timeStep+1.0);
+
+               (*ssv)(AvSxx,ix1,ix2,ix3) = ((*ssv)(AvSxx,ix1,ix2,ix3)*timeStep + sxx)/(timeStep+1.0);
+               (*ssv)(AvSyy,ix1,ix2,ix3) = ((*ssv)(AvSyy,ix1,ix2,ix3)*timeStep + syy)/(timeStep+1.0);
+               (*ssv)(AvSzz,ix1,ix2,ix3) = ((*ssv)(AvSzz,ix1,ix2,ix3)*timeStep + szz)/(timeStep+1.0);
+               (*ssv)(AvSxy,ix1,ix2,ix3) = ((*ssv)(AvSxy,ix1,ix2,ix3)*timeStep + sxy)/(timeStep+1.0);
+               (*ssv)(AvSyz,ix1,ix2,ix3) = ((*ssv)(AvSyz,ix1,ix2,ix3)*timeStep + syz)/(timeStep+1.0);
+               (*ssv)(AvSxz,ix1,ix2,ix3) = ((*ssv)(AvSxz,ix1,ix2,ix3)*timeStep + sxz)/(timeStep+1.0);
+            }
+         }
+
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::addPostprocessData()
+{
+   //Diese Daten werden geschrieben:
+   datanames.resize(0);
+   datanames.push_back("y^plus");
+   datanames.push_back("u_tau");
+   //datanames.push_back("yPlusFD");
+
+   data.resize(datanames.size());
+
+   BOOST_FOREACH(D3Q27InteractorPtr interactor, interactors)
+   {
+      typedef std::map<Block3DPtr, std::set< std::vector<int> > > TransNodeIndicesMap;
+      BOOST_FOREACH(TransNodeIndicesMap::value_type t, interactor->getTransNodeIndicesMap())
+      {
+         Block3DPtr block = t.first;
+         std::set< std::vector<int> >& transNodeIndicesSet = t.second;
+
+         UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+         UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+         UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+         double         dx           = grid->getDeltaX(block);
+
+         LBMKernel3DPtr kernel = block->getKernel();
+         BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+         DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+         ShearStressValuesArray3DPtr ssv = kernel->getDataSet()->getShearStressValues();
+
+         int ghostLayer = kernel->getGhostLayerWidth();
+         LBMReal collFactor = kernel->getCollisionFactor();
+
+         int minX1 = ghostLayer;
+         int maxX1 = (int)bcArray.getNX1() - 1 - ghostLayer;
+         int minX2 = ghostLayer;
+         int maxX2 = (int)bcArray.getNX2() - 1 - ghostLayer;
+         int minX3 = ghostLayer;
+         int maxX3 = (int)bcArray.getNX3() - 1 - ghostLayer;
+
+         int level=block->getLevel();
+         if(level==1)
+         {
+            int le=0;
+         }
+         BOOST_FOREACH(std::vector<int> node, transNodeIndicesSet)
+         {
+            int ix1 = node[0];
+            int ix2 = node[1];
+            int ix3 = node[2];
+
+            //without ghost nodes
+            if (ix1 < minX1 || ix1 > maxX1 || ix2 < minX2 || ix2 > maxX2 ||ix3 < minX3 || ix3 > maxX3 ) continue;
+
+            if(bcArray.isFluid(ix1,ix2,ix3)) 
+            {
+               double q=(*ssv)(normalq,ix1,ix2,ix3) ;
+               double numPoint=(*ssv)(numberOfPoint,ix1,ix2,ix3) ;
+               if (q==0||numPoint!=3)continue;
+               // if (q==0)continue;
+
+               int index = 0;
+               nodes.push_back( makeUbTuple(float(val<1>(org) - val<1>(nodeOffset) + ix1*dx),
+                  float(val<2>(org) - val<2>(nodeOffset) + ix2*dx),
+                  float(val<3>(org) - val<3>(nodeOffset) + ix3*dx)) );
+
+               //////get normal and distance//////
+               double A,B,C;
+               A=	(*ssv)(normalX1,ix1,ix2,ix3)	;
+               B=	(*ssv)(normalX2,ix1,ix2,ix3)	;
+               C=	(*ssv)(normalX3,ix1,ix2,ix3)	;
+
+               ///////////
+               //compute y plus
+               //double vtxSonja, vtySonja, vtzSonja; //tangent velocity
+               // double temp = (*av)(ix1,ix2,ix3,AvVx)*A+(*av)(ix1,ix2,ix3,AvVy)*B+(*av)(ix1,ix2,ix3,AvVz)*C;
+               // vtxSonja = (*av)(ix1,ix2,ix3,AvVx)-normals[0]*temp;
+               // vtySonja = (*av)(ix1,ix2,ix3,AvVy)-normals[1]*temp;
+               // vtzSonja = (*av)(ix1,ix2,ix3,AvVz)-normals[2]*temp;
+
+               double vtx=  (B*B*(*ssv)(AvVx,ix1,ix2,ix3) +  C*C*(*ssv)(AvVx,ix1,ix2,ix3) - A*B*(*ssv)(AvVy,ix1,ix2,ix3) - A*C*(*ssv)(AvVy,ix1,ix2,ix3))/(A*A+B*B+C*C);
+               double vty=(-(A*B*(*ssv)(AvVx,ix1,ix2,ix3)) + A*A*(*ssv)(AvVy,ix1,ix2,ix3) + C*C*(*ssv)(AvVy,ix1,ix2,ix3) - B*C*(*ssv)(AvVz,ix1,ix2,ix3))/(A*A+B*B+C*C);
+               double vtz=(-(A*C*(*ssv)(AvVx,ix1,ix2,ix3)) - B*C*(*ssv)(AvVy,ix1,ix2,ix3) + A*A*(*ssv)(AvVz,ix1,ix2,ix3) + B*B*(*ssv)(AvVz,ix1,ix2,ix3))/(A*A+B*B+C*C);
+
+               double normVt = sqrt(vtx*vtx+vty*vty+vtz*vtz)+1e-100;
+               double nvtx = vtx / normVt;
+               double nvty = vty / normVt;
+               double nvtz = vtz / normVt;
+
+               double sx=0.5*((*ssv)(AvSxx,ix1,ix2,ix3)*nvtx+(*ssv)(AvSxy,ix1,ix2,ix3)*nvty+(*ssv)(AvSxz,ix1,ix2,ix3)*nvtz);
+               double sy=0.5*((*ssv)(AvSxy,ix1,ix2,ix3)*nvtx+(*ssv)(AvSyy,ix1,ix2,ix3)*nvty+(*ssv)(AvSyz,ix1,ix2,ix3)*nvtz);
+               double sz=0.5*((*ssv)(AvSxz,ix1,ix2,ix3)*nvtx+(*ssv)(AvSyz,ix1,ix2,ix3)*nvty+(*ssv)(AvSzz,ix1,ix2,ix3)*nvtz);
+               double sabs=sqrt(sx*sx+sy*sy+sz*sz);
+
+               double viscosity = (1.0/3.0)*(1.0/collFactor-0.5);
+               double rho = 1.0;
+               double utau=sqrt(viscosity/rho*sabs);
+
+               // double q=(*av)(ix1,ix2,ix3,normalq) ;
+               double yPlus = (utau*q)/viscosity;
+
+               data[index++].push_back(yPlus);
+               data[index++].push_back(utau);
+            }
+         }
+      }
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::reset(double step)
+{
+   if(Resetscheduler->isDue(step) )
+      resetPostprocessData(step);
+
+   UBLOG(logDEBUG3, "resetPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::resetPostprocessData(double step)
+{
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         if (block)
+         {
+            UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+            UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+            UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+            double         dx           = grid->getDeltaX(block);
+
+            LBMKernel3DPtr kernel = block->getKernel();
+            BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+            DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+            ShearStressValuesArray3DPtr ssv = kernel->getDataSet()->getShearStressValues();
+
+            int minX1 = 0;
+            int minX2 = 0;
+            int minX3 = 0;
+
+            int maxX1 = int(distributions->getNX1());
+            int maxX2 = int(distributions->getNX2());
+            int maxX3 = int(distributions->getNX3());
+
+            for(int ix3=minX3; ix3<maxX3-1; ix3++)
+            {
+               for(int ix2=minX2; ix2<maxX2-1; ix2++)
+               {
+                  for(int ix1=minX1; ix1<maxX1-1; ix1++)
+                  {
+                     if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+                     {
+                        //////////////////////////////////////////////////////////////////////////
+                        //compute average values
+                        //////////////////////////////////////////////////////////////////////////
+                        (*ssv)(AvVx,ix1,ix2,ix3) = 0.0;
+                        (*ssv)(AvVy,ix1,ix2,ix3) = 0.0;
+                        (*ssv)(AvVz,ix1,ix2,ix3) = 0.0;
+
+                        (*ssv)(AvSxx,ix1,ix2,ix3) = 0.0;
+                        (*ssv)(AvSyy,ix1,ix2,ix3) = 0.0;
+                        (*ssv)(AvSzz,ix1,ix2,ix3) = 0.0;
+                        (*ssv)(AvSxy,ix1,ix2,ix3) = 0.0;
+                        (*ssv)(AvSyz,ix1,ix2,ix3) = 0.0;
+                        (*ssv)(AvSxz,ix1,ix2,ix3) = 0.0;
+                        //////////////////////////////////////////////////////////////////////////
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::addInteractor( D3Q27InteractorPtr interactor )
+{
+   interactors.push_back(interactor);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::findPlane(int ix1,int ix2,int ix3,Grid3DPtr grid,Block3DPtr block,double &A,double &B,double &C,double &D,double &ii)
+{
+   double x1plane=0.0,y1plane=0.0,z1plane=0.0;
+   double x2plane=0.0,y2plane=0.0,z2plane=0.0;
+   double x3plane=0.0,y3plane=0.0,z3plane=0.0;
+   D3Q27BoundaryConditionPtr bcPtr;
+   double dx = grid->getDeltaX(block);
+   LBMKernel3DPtr kernel = block->getKernel();
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+   BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+   bcPtr=bcArray.getBC(ix1,ix2,ix3);
+   int x,y,z;
+
+
+   if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1, ix2, ix3)) { x = ix1;y = ix2;z = ix3;}   
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1  , ix2-1, ix3  )) { x = ix1+0; y = ix2-1; z = ix3+0;}//S
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1  , ix2  , ix3-1)) { x = ix1+0; y = ix2+0; z = ix3-1;}//B		   
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2  , ix3  )) { x = ix1-1; y = ix2+0; z = ix3+0;}//w
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1  , ix2-1, ix3-1)) { x = ix1+0; y = ix2-1; z = ix3-1;}//BS
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2  , ix3-1)) { x = ix1-1; y = ix2+0; z = ix3-1;}//BW
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2-1, ix3  )) { x = ix1-1; y = ix2-1; z = ix3+0;}//SW
+
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2-1, ix3-1)) { x = ix1-1; y = ix2-1; z = ix3-1;}//BSW	  
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2  , ix3  )) { x = ix1+1; y = ix2+0; z = ix3+0;}//E
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1  , ix2+1, ix3  )) { x = ix1+0; y = ix2+1; z = ix3+0;}//N
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1  , ix2  , ix3+1)) { x = ix1+0; y = ix2+0; z = ix3+1;}//T	
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2+1, ix3  )) { x = ix1+1; y = ix2+1; z = ix3+0;}//NE
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2  , ix3+1)) { x = ix1+1; y = ix2+0; z = ix3+1;}//TE
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1  , ix2+1, ix3+1)) { x = ix1+0; y = ix2+1; z = ix3+1;}//TN
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2+1, ix3+1)) { x = ix1+1; y = ix2+1; z = ix3+1;}//TNE
+
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2-1, ix3  )) { x = ix1+1; y = ix2-1; z = ix3+0;}//SE
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2+1, ix3  )) { x = ix1-1; y = ix2+1; z = ix3+0;}//NW
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2  , ix3-1)) { x = ix1+1; y = ix2+0; z = ix3-1;}//BE
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2  , ix3+1)) { x = ix1-1; y = ix2+0; z = ix3+1;}//TW
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+0, ix2+1, ix3-1)) { x = ix1+0; y = ix2+1; z = ix3-1;}//BN
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+0, ix2-1, ix3+1)) { x = ix1+0; y = ix2-1; z = ix3+1;}//TS
+
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2+1, ix3+1)) { x = ix1-1; y = ix2+1; z = ix3+1;}//TNW 
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2-1, ix3+1)) { x = ix1+1; y = ix2-1; z = ix3+1;}//TSE 
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2-1, ix3+1)) { x = ix1-1; y = ix2-1; z = ix3+1;}//TSW 
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2+1, ix3-1)) { x = ix1+1; y = ix2+1; z = ix3-1;}//BNE 
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1-1, ix2+1, ix3-1)) { x = ix1-1; y = ix2+1; z = ix3-1;}//BNW 
+   else if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, ix1+1, ix2-1, ix3-1)) { x = ix1+1; y = ix2-1; z = ix3-1;}//BSE 
+
+
+   else   {{UB_THROW( UbException(UB_EXARGS,"there is no cell  ix1="+UbSystem::toString(ix1)+"ix2="+UbSystem::toString(ix2)+"ix3="+UbSystem::toString(ix3)+"GlobalID="+UbSystem::toString(block->getGlobalID())+"dx="+UbSystem::toString(dx)
+      +"T="+UbSystem::toString(bcPtr->getQ(D3Q27System::T))+"B="+UbSystem::toString(bcPtr->getQ(D3Q27System::B))
+      +"E="+UbSystem::toString(bcPtr->getQ(D3Q27System::E))+"W="+UbSystem::toString(bcPtr->getQ(D3Q27System::W))+"N="+UbSystem::toString(bcPtr->getQ(D3Q27System::N))	
+      +"S="+UbSystem::toString(bcPtr->getQ(D3Q27System::S))+"NE="+UbSystem::toString(bcPtr->getQ(D3Q27System::NE))+"SW="+UbSystem::toString(bcPtr->getQ(D3Q27System::SW))
+      +"SE="+UbSystem::toString(bcPtr->getQ(D3Q27System::SE))+"NW="+UbSystem::toString(bcPtr->getQ(D3Q27System::NW))    
+      +"TE="+
+      UbSystem::toString(bcPtr->getQ(D3Q27System::TE))+"BW="+UbSystem::toString(bcPtr->getQ(D3Q27System::BW))+"BE="+UbSystem::toString(bcPtr->getQ(D3Q27System::BE))+"TW="+
+      UbSystem::toString(bcPtr->getQ(D3Q27System::TW))+"TN="+UbSystem::toString(bcPtr->getQ(D3Q27System::TN))+"BS="+UbSystem::toString(bcPtr->getQ(D3Q27System::BS))+"BN="+
+      UbSystem::toString(bcPtr->getQ(D3Q27System::BN))+"TS="+UbSystem::toString(bcPtr->getQ(D3Q27System::TS))+"TNE="+UbSystem::toString(bcPtr->getQ(D3Q27System::TNE))+"TNW="+
+      UbSystem::toString(bcPtr->getQ(D3Q27System::TNW))+"TSE="+UbSystem::toString(bcPtr->getQ(D3Q27System::TSE))+"TSW="+UbSystem::toString(bcPtr->getQ(D3Q27System::TSW))+"BNE="+
+      UbSystem::toString(bcPtr->getQ(D3Q27System::BNE))+"BNW="+UbSystem::toString(bcPtr->getQ(D3Q27System::BNW))+"BSE="+UbSystem::toString(bcPtr->getQ(D3Q27System::BSE))+"BSW="+UbSystem::toString(bcPtr->getQ(D3Q27System::BSW)*dx)
+      ) ) ;}} 
+
+
+   if(D3Q27InterpolationProcessor::iCellHasSolid(bcArray, x, y, z))
+   {  
+      for(int i = x; i <= x + 1; i++){
+         for(int j = y; j <= y + 1; j++){
+            for (int k = z; k <= z + 1; k++)
+            {
+               UbTupleDouble3 pointplane1 =  grid->getNodeCoordinates(block,  i,	  j,	 k);
+
+               double   iph=val<1>(pointplane1);
+               double   jph=val<2>(pointplane1);
+               double   kph=val<3>(pointplane1);
+
+               if(!bcArray.isSolid(i, j, k))
+               {
+                  D3Q27BoundaryConditionPtr bcPtrIn=bcArray.getBC(i,j,k);
+                  if(bcPtrIn)
+                  {	 
+                     for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                     {
+                        if( ii<=2)
+                        {
+                           LBMReal q = bcPtrIn->getQ(fdir);
+                           if (q!=999.00000)
+                           {	  
+                              if     ( fdir==D3Q27System::E ) 
+                              {
+                                 //if(!bcArray.isSolid(i, j, k))continue;
+                                 if (i+q<=x+1)
+                                 {
+                                    if      (ii==0)	    {	x1plane=iph+q*dx;	  y1plane=jph;	 z1plane=kph;    	ii++;	} 
+                                    else if (ii==1) 	{	x2plane=iph+q*dx;     y2plane=jph;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                    else if(ii==2) 	    {   x3plane=iph+q*dx;     y3plane=jph;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                                 }
+                              }
+                              if     ( fdir==D3Q27System::W ) 
+                              {
+                                 //if(!bcArray.isSolid(i, j, k))continue;
+                                 if (i-q>=x)
+                                 {
+                                    if      (ii==0)	    {	x1plane=iph-q*dx;	  y1plane=jph;	 z1plane=kph;    	ii++;	} 
+                                    else if (ii==1) 	    {	x2plane=iph-q*dx;    y2plane=jph;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                    else if(ii==2) 	    {   x3plane=iph-q*dx;    y3plane=jph;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                                 }
+                              }
+                              if     ( fdir==D3Q27System::N ) 
+                              {
+                                 //if(!bcArray.isSolid(i, j, k))continue;
+                                 if(j+q<=y+1)
+                                 {
+                                    if      (ii==0)	    {	x1plane=iph;	y1plane=jph+q*dx;	 z1plane=kph; 	    ii++;	} 
+                                    else if (ii==1) 	    {	x2plane=iph;    y2plane=jph+q*dx;	 z2plane=kph;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                    else if (ii==2) 	    {   x3plane=iph;    y3plane=jph+q*dx;	 z3plane=kph;       if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                                 }
+                              }
+                              if     ( fdir==D3Q27System::S ) 
+                              {
+                                 //if(!bcArray.isSolid(i, j, k))continue;
+                                 if (j-q>=y)
+                                 {
+                                    if      (ii==0)	    {	x1plane=iph;	y1plane=jph-q*dx;	 z1plane=kph; 	ii++;	} 
+                                    else if (ii==1) 	    {	x2plane=iph;    y2plane=jph-q*dx;	 z2plane=kph;	if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                    else if (ii==2) 	    {   x3plane=iph;    y3plane=jph-q*dx;	 z3plane=kph;   if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                                 }
+                              }
+
+                              if     ( fdir==D3Q27System::T ) 
+                              {
+                                 //if(!bcArray.isSolid(i, j, k))continue;
+                                 if(k+q<=z+1)
+                                 {
+                                    if      (ii==0)	    {	x1plane=iph;	y1plane=jph;	 z1plane=kph+q*dx; 	    ii++;	} 
+                                    else if (ii==1) 	    {	x2plane=iph;    y2plane=jph;	 z2plane=kph+q*dx;	    if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                    else if (ii==2) 	    {   x3plane=iph;    y3plane=jph;	 z3plane=kph+q*dx;      if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                                 }
+                              }
+                              if     ( fdir==D3Q27System::B ) 
+                              {
+                                 //if(!bcArray.isSolid(i, j, k))continue;
+                                 if (k-q>=z)
+                                 {
+                                    if      (ii==0)	    {	x1plane=iph;	y1plane=jph;	 z1plane=kph-q*dx; 	ii++;	} 
+                                    else if (ii==1) 	    {	x2plane=iph;    y2plane=jph;	 z2plane=kph-q*dx;	  if  (x1plane!=x2plane||y1plane!=y2plane||z1plane!=z2plane) 	ii++;	}
+                                    else if (ii==2) 	    {   x3plane=iph;    y3plane=jph;	 z3plane=kph-q*dx;     if ((x3plane!=x1plane||y3plane!=y1plane||z3plane!=z1plane)&&(x2plane!=x3plane||y2plane!=y3plane||z2plane!=z3plane)) ii++;} 
+                                 }
+                              }
+
+                           }
+                        }
+                     }
+                  }
+               }
+            }
+         }
+      }
+
+      A =   y1plane* (z2plane - z3plane) + y2plane*(z3plane - z1plane) + y3plane* (z1plane - z2plane);   
+      B =   z1plane* (x2plane - x3plane) + z2plane*(x3plane - x1plane) + z3plane* (x1plane - x2plane) ;      
+      C =   x1plane* (y2plane - y3plane) + x2plane*(y3plane - y1plane) + x3plane* (y1plane - y2plane) ;       
+      D =-( x1plane*(y2plane*z3plane - y3plane*z2plane)+x2plane*(y3plane*z1plane - y1plane*z3plane) + x3plane* (y1plane* z2plane - y2plane* z1plane));	
+   }
+   if(ii!=3){
+
+      {{UB_THROW( UbException(UB_EXARGS,"ii is="+UbSystem::toString(ii)+"  ix1="+UbSystem::toString(ix1)+" ix2="+UbSystem::toString(ix2)+" ix3="+UbSystem::toString(ix3)+" Block3D::GlobalID="+UbSystem::toString(block->getGlobalID())+" dx="+UbSystem::toString(dx)
+         +" T="+UbSystem::toString(bcPtr->getQ(D3Q27System::T))+" B="+UbSystem::toString(bcPtr->getQ(D3Q27System::B))
+         +" E="+UbSystem::toString(bcPtr->getQ(D3Q27System::E))+" W="+UbSystem::toString(bcPtr->getQ(D3Q27System::W))+" N="+UbSystem::toString(bcPtr->getQ(D3Q27System::N))	
+         +" S="+UbSystem::toString(bcPtr->getQ(D3Q27System::S))+" NE="+UbSystem::toString(bcPtr->getQ(D3Q27System::NE))+" SW="+UbSystem::toString(bcPtr->getQ(D3Q27System::SW))
+         +" SE="+UbSystem::toString(bcPtr->getQ(D3Q27System::SE))+" NW="+UbSystem::toString(bcPtr->getQ(D3Q27System::NW))    
+         +" TE="+
+         UbSystem::toString(bcPtr->getQ(D3Q27System::TE))+" BW="+UbSystem::toString(bcPtr->getQ(D3Q27System::BW))+" BE="+UbSystem::toString(bcPtr->getQ(D3Q27System::BE))+" TW="+
+         UbSystem::toString(bcPtr->getQ(D3Q27System::TW))+" TN="+UbSystem::toString(bcPtr->getQ(D3Q27System::TN))+" BS="+UbSystem::toString(bcPtr->getQ(D3Q27System::BS))+" BN="+
+         UbSystem::toString(bcPtr->getQ(D3Q27System::BN))+" TS="+UbSystem::toString(bcPtr->getQ(D3Q27System::TS))+" TNE="+UbSystem::toString(bcPtr->getQ(D3Q27System::TNE))+" TNW="+
+         UbSystem::toString(bcPtr->getQ(D3Q27System::TNW))+" TSE="+UbSystem::toString(bcPtr->getQ(D3Q27System::TSE))+" TSW="+UbSystem::toString(bcPtr->getQ(D3Q27System::TSW))+" BNE="+
+         UbSystem::toString(bcPtr->getQ(D3Q27System::BNE))+" BNW="+UbSystem::toString(bcPtr->getQ(D3Q27System::BNW))+" BSE="+UbSystem::toString(bcPtr->getQ(D3Q27System::BSE))+" BSW="+UbSystem::toString(bcPtr->getQ(D3Q27System::BSW))
+         ) ) ;}}
+
+   }	
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool D3Q27ShearStressPostprocessor::checkUndefindedNodes( BCArray3D<D3Q27BoundaryCondition>& bcArray,int ix1,int ix2,int ix3)
+{
+   for(int i = ix1; i <= ix1 + 1; i++){
+      for(int j = ix2; j <= ix2 + 1; j++){
+         for (int k = ix3; k <= ix3 + 1; k++)
+         {	
+            if(bcArray.isUndefined(i, j, k)) return true;
+         }  
+      }
+   }
+   return false;
+}
+//////////////////////////////////////////////////////////////////////////////////////
+void D3Q27ShearStressPostprocessor::initDistance()
+{
+   BOOST_FOREACH(D3Q27InteractorPtr interactor, interactors)
+   {
+      typedef std::map<Block3DPtr, std::set< std::vector<int> > > TransNodeIndicesMap;
+      BOOST_FOREACH(TransNodeIndicesMap::value_type t, interactor->getTransNodeIndicesMap())
+      {
+         Block3DPtr block = t.first;
+         std::set< std::vector<int> >& transNodeIndicesSet = t.second;
+
+         UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+         UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+         UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+         double         dx           = grid->getDeltaX(block);
+
+         LBMKernel3DPtr kernel = block->getKernel();
+         BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+         DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+         ShearStressValuesArray3DPtr ssv = kernel->getDataSet()->getShearStressValues();
+
+         int ghostLayer = kernel->getGhostLayerWidth();
+         LBMReal collFactor = kernel->getCollisionFactor();
+
+         int minX1 = ghostLayer;
+         int maxX1 = (int)bcArray.getNX1() - 1 - ghostLayer;
+         int minX2 = ghostLayer;
+         int maxX2 = (int)bcArray.getNX2() - 1 - ghostLayer;
+         int minX3 = ghostLayer;
+         int maxX3 = (int)bcArray.getNX3() - 1 - ghostLayer;
+
+         BOOST_FOREACH(std::vector<int> node, transNodeIndicesSet)
+         {
+            int ix1 = node[0];
+            int ix2 = node[1];
+            int ix3 = node[2];
+
+            //without ghost nodes
+            if (ix1 < minX1 || ix1 > maxX1 || ix2 < minX2 || ix2 > maxX2 ||ix3 < minX3 || ix3 > maxX3 ) continue;
+
+            if(bcArray.isFluid(ix1,ix2,ix3) )
+            {
+               D3Q27BoundaryConditionPtr bc = bcArray.getBC(ix1,ix2,ix3);
+               if((bc->hasDensityBoundary()||bc->hasVelocityBoundary()))continue;
+               int numberOfCorner=0;
+
+               if(bc->getQ(D3Q27System::T)  !=999.000){ numberOfCorner++;}
+               if(bc->getQ(D3Q27System::B)  !=999.000){ numberOfCorner++;}
+               if(bc->getQ(D3Q27System::E)  !=999.000){ numberOfCorner++;}
+               if(bc->getQ(D3Q27System::W)  !=999.000){ numberOfCorner++;}
+               if(bc->getQ(D3Q27System::N)  !=999.000){ numberOfCorner++;}
+               if(bc->getQ(D3Q27System::S)  !=999.000){ numberOfCorner++;}
+               // if(bc->hasVelocityBoundary()||bc->hasDensityBoundary())continue;
+               if(numberOfCorner>1)continue;
+               if(checkUndefindedNodes( bcArray, ix1,ix2,ix3))continue;
+
+
+               //////get normal and distance//////
+               double A,B,C,D,ii=0.0;
+               findPlane(ix1,ix2,ix3,grid,block,A,B,C,D,ii);
+               UbTupleDouble3 pointplane1 =  grid->getNodeCoordinates(block, ix1,ix2,ix3);
+               double   ix1ph=val<1>(pointplane1);
+               double   ix2ph=val<2>(pointplane1);
+               double   ix3ph=val<3>(pointplane1);
+               double normalDis;
+               if(ii!=3)
+               {
+                  UB_THROW( UbException(UB_EXARGS,"not enough points to create plane"+UbSystem::toString(ii)));
+               }
+               else
+               {    
+                  double s = A*ix1ph + B*ix2ph + C*ix3ph + D;//The sign of s = Ax + By + Cz + D determines which side the point (x,y,z) lies with respect to the plane. If s > 0 then the point lies on the same side as the normal (A,B,C). If s < 0 then it lies on the opposite side, if s = 0 then the point (x,y,z) lies on the plane.
+                  if (s>0){s=1;} else if (s<0){s=-1;}else {s=0;}
+
+                  normalDis=((A*ix1ph + B*ix2ph + C*ix3ph + D)/sqrt(A*A+B*B+C*C));///distance point to plane xp-Xw=distance
+                  normalDis*=s;
+
+                  (*ssv)(normalX1,ix1,ix2,ix3) = A;
+                  (*ssv)(normalX2,ix1,ix2,ix3) = B;
+                  (*ssv)(normalX3,ix1,ix2,ix3) = C;
+                  (*ssv)(normalq,ix1,ix2,ix3) = normalDis;
+                  (*ssv)(numberOfPoint,ix1,ix2,ix3) = ii;
+
+               }
+            }
+         }
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/D3Q27ShearStressPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/D3Q27ShearStressPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..78c82cbe145a6f7b9066d6866cbcd847b5bfa49c
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/D3Q27ShearStressPostprocessor.h
@@ -0,0 +1,76 @@
+#ifndef D3Q27ShearStressPostprocessor_H
+#define D3Q27ShearStressPostprocessor_H
+
+#include "Postprocessor.h"
+#include "Communicator.h"
+#include "D3Q27Interactor.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "WbWriter.h"
+
+#include <boost/shared_ptr.hpp>
+class D3Q27ShearStressPostprocessor;
+typedef boost::shared_ptr<D3Q27ShearStressPostprocessor> D3Q27ShearStressPostprocessorPtr;
+
+//! \brief  Computes the shear stress and y plus values and writes to parallel .vtk
+//! \details writes at given time intervals specified in scheduler (s) and resets according to scheduler (rs).  
+//!          Take root to obtain  during post processing (paraview).   
+//! \author  K. Kucher, S. Uphoff, M. Geier, E. Goraki Fard  
+
+class D3Q27ShearStressPostprocessor: public Postprocessor 
+{
+public:
+   //! Defoult constructor
+   D3Q27ShearStressPostprocessor(){}
+   //! Constructor
+   D3Q27ShearStressPostprocessor(Grid3DPtr grid, const std::string& path, WbWriter* const writer, 
+      UbSchedulerPtr s, UbSchedulerPtr rs);
+   virtual ~D3Q27ShearStressPostprocessor();             
+   void update(double step); 
+   void addInteractor(D3Q27InteractorPtr interactor);
+protected:
+   //! Computes average and shear stress values of macroscopic quantities 
+   void calculateShearStress(double timeStep);
+   //! Prepare data and write in .vtk file
+   void collectPostprocessData(double step);
+   //! Reset data
+   void resetPostprocessData(double step);
+   //! prepare data
+   void addPostprocessData();
+   void clearData();
+   void reset(double step);
+   void findPlane(int ix1,int ix2,int ix3,Grid3DPtr grid,Block3DPtr block,double &A,double &B,double &C,double &D,double &ii);
+   bool checkUndefindedNodes( BCArray3D<D3Q27BoundaryCondition>& bcArray,int ix1,int ix2,int ix3);
+   void initDistance();
+private:
+   std::vector<UbTupleFloat3> nodes;
+   std::vector<std::string> datanames;
+   std::vector<std::vector<double> > data;
+   std::string path;
+   std::vector<D3Q27InteractorPtr> interactors;
+   std::vector<double> normals;
+   int gridRank;
+   WbWriter* writer;
+   UbSchedulerPtr Resetscheduler;  //additional scheduler to restart averaging after a given interval
+   int minInitLevel; //min init level
+   int maxInitLevel;
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   enum Values{AvVx = 0, AvVy = 1, AvVz = 2, AvSxx = 3, AvSyy = 4, AvSzz = 5, AvSxy = 6, AvSyz = 7, AvSxz = 8, normalX1 = 9, normalX2 = 10, normalX3 = 11, normalq = 12,numberOfPoint=13}; 
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<Postprocessor>(*this);
+      ar & path;
+      ar & normals;
+      ar & interactors;
+      ar & blockVector;
+      ar & minInitLevel;
+      ar & maxInitLevel;
+      ar & gridRank;
+      ar & writer;
+   }
+};
+
+
+#endif /* D3Q27ShearStressPostprocessor_H */
diff --git a/source/VirtualFluidsCore/CoProcessors/DecreaseViscosityPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/DecreaseViscosityPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..851f66e90cb8858966c5b45cbd7240d6f8090063
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/DecreaseViscosityPostprocessor.cpp
@@ -0,0 +1,81 @@
+/*
+*  DecreaseViscosityPostprocessor
+*
+*  Created on: 10.05.2013
+*  Author: uphoff
+*/
+
+#include "DecreaseViscosityPostprocessor.h"
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+DecreaseViscosityPostprocessor::DecreaseViscosityPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+                                                               mu::Parser* nueFunc, CommunicatorPtr comm)
+
+                                                               : Postprocessor(grid, s)
+                                                               ,nueFunc(nueFunc)
+                                                               ,comm(comm)
+{
+   if (comm->getProcessID() == comm->getRoot())
+   {
+
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+DecreaseViscosityPostprocessor::~DecreaseViscosityPostprocessor() 
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void DecreaseViscosityPostprocessor::update(double step)
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+}
+//////////////////////////////////////////////////////////////////////////
+void DecreaseViscosityPostprocessor::collectPostprocessData(double step)
+{
+
+   UBLOG(logDEBUG3, "DecreaseViscosityPostprocessor::update:" << step);
+   int gridRank = grid->getRank();
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   if (comm->getProcessID() == comm->getRoot())
+   {
+
+      for(int level = minInitLevel; level<=maxInitLevel;level++)
+      {
+         vector<Block3DPtr> blockVector;
+         grid->getBlocks(level, gridRank, blockVector);
+         BOOST_FOREACH(Block3DPtr block, blockVector)
+         {
+            LBMKernel3DPtr kernel =block->getKernel();
+         }
+      }
+
+      int istep = static_cast<int>(step);
+      this->timeStep       = istep;
+      nueFunc->DefineVar("t" , &this->timeStep);
+      double nue=nueFunc->Eval();
+
+      for(int level = minInitLevel; level<=maxInitLevel;level++)
+      {
+         vector<Block3DPtr> blockVector;
+         grid->getBlocks(level, gridRank, blockVector);
+         BOOST_FOREACH(Block3DPtr block, blockVector)
+         {
+            LBMKernel3DPtr kernel =block->getKernel();
+            if(kernel)      
+            {
+               LBMReal collFactor = LBMSystem::calcCollisionFactor(nue, block->getLevel());
+               kernel->setCollisionFactor(collFactor);
+            }
+         }
+      }
+
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/DecreaseViscosityPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/DecreaseViscosityPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..041a858a3ad0f7069ad32a9c0354e38f900dc108
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/DecreaseViscosityPostprocessor.h
@@ -0,0 +1,44 @@
+#ifndef DecreaseViscosityPOSTPROCESSOR_H
+#define DecreaseViscosityPOSTPROCESSOR_H
+
+#include "Postprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+
+#include <boost/shared_ptr.hpp>
+class DecreaseViscosityPostprocessor;
+typedef boost::shared_ptr<DecreaseViscosityPostprocessor> DecreaseViscosityPostprocessorPtr;
+
+//! \brief The class sets viscosity/collision factor according to a previously defined function in time. 
+//! \details initialization in test case (example): 
+//! \code{.cpp}
+//! mu::Parser decrViscFunc;                       //define a mu-parser function 
+//! decrViscFunc.SetExpr("nue0+c0/(t+1)/(t+1)");   //this function is time-dependent, the viscosity decreases a 1/t^2 
+//! decrViscFunc.DefineConst("nue0", nueLB);       
+//! decrViscFunc.DefineConst("c0", 0.1);           //constants such as c0 controll how fast the viscosity decreasis 
+//! UbSchedulerPtr DecrViscSch(new UbScheduler()); //the postprocessor is called according to a Scheduler
+//! DecrViscSch->addSchedule(10,10,1000);          //in this case the viscosity is reset every 10 timesteps for the first 1000 timesteps 
+//! DecreaseViscosityPostprocessor decrViscPPPtr(grid, DecrViscSch,&decrViscFunc, comm); 
+//! \endcode
+//! \author Sonja Uphoff
+
+class DecreaseViscosityPostprocessor: public Postprocessor 
+{ 
+public:
+   DecreaseViscosityPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+      mu::Parser* nueFunc, CommunicatorPtr comm);
+   virtual ~DecreaseViscosityPostprocessor();
+   //! calls collect PostprocessData.
+   void update(double step); 
+protected:
+   //! resets the collision factor depending on the current timestep.
+   void collectPostprocessData(double step);  
+   CommunicatorPtr comm;
+private:
+   mutable mu::value_type timeStep;
+   mu::Parser* nueFunc;
+};
+
+
+#endif /* DecreaseViscosityPOSTPROCESSOR_H_ */
diff --git a/source/VirtualFluidsCore/CoProcessors/EmergencyExitPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/EmergencyExitPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..163120e91002381543fba935474c625b7ac9b493
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/EmergencyExitPostprocessor.cpp
@@ -0,0 +1,70 @@
+#include "EmergencyExitPostprocessor.h"
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+EmergencyExitPostprocessor::EmergencyExitPostprocessor( Grid3DPtr grid, UbSchedulerPtr s, 
+                                                        const std::string& path, 
+                                                        RestartPostprocessorPtr rp, CommunicatorPtr comm ) :
+                                                        Postprocessor(grid, s),
+                                                        path(path),
+                                                        rp(rp),
+                                                        comm(comm)
+{
+   this->path = path + "/exit";
+   metafile = this->path + "/stop.txt";
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      //checkMetafile();
+      writeMetafile(false);
+   }
+   comm->barrier();
+}
+//////////////////////////////////////////////////////////////////////////
+EmergencyExitPostprocessor::~EmergencyExitPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void EmergencyExitPostprocessor::update( double step )
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+
+   UBLOG(logDEBUG3, "EmergencyExitPostprocessor::update:" << step);
+}
+
+void EmergencyExitPostprocessor::collectPostprocessData( double step )
+{
+   if(readMetafile())
+   {
+      rp->doCheckPoint((int)step);
+      if(comm->getProcessID() == comm->getRoot()) UBLOG(logINFO,"EmergencyExitPostprocessor save step: " << step);
+      comm->barrier();
+      exit(EXIT_SUCCESS);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void EmergencyExitPostprocessor::writeMetafile(int status )
+{
+   UbFileOutputASCII out(metafile);
+   out.writeBool(false);
+}
+//////////////////////////////////////////////////////////////////////////
+bool EmergencyExitPostprocessor::readMetafile()
+{
+   UbFileInputASCII in(metafile);
+   return in.readBool();
+}
+//////////////////////////////////////////////////////////////////////////
+void EmergencyExitPostprocessor::checkMetafile()
+{
+   std::ifstream file(metafile.c_str()); 
+   if (!file.is_open()) 
+   {
+      writeMetafile(false);
+      return;
+   }
+   file.close();
+}
+                                                       
+
diff --git a/source/VirtualFluidsCore/CoProcessors/EmergencyExitPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/EmergencyExitPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..afe4ce442d71dd7c9fdb6c1a4ba3722ba748ce56
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/EmergencyExitPostprocessor.h
@@ -0,0 +1,40 @@
+/*
+ *  EmergencyExitPostprocessor.h
+ *
+ *  Created on: 05.10.2012
+ *  Author: K. Kucher
+ */
+
+#ifndef EmergencyExitPostprocessor_H
+#define EmergencyExitPostprocessor_H
+
+#include "Postprocessor.h"
+#include "Communicator.h"
+#include "RestartPostprocessor.h"
+
+#include <boost/shared_ptr.hpp>
+class EmergencyExitPostprocessor;
+typedef boost::shared_ptr<EmergencyExitPostprocessor> EmergencyExitPostprocessorPtr;
+
+class EmergencyExitPostprocessor: public Postprocessor 
+{
+public:
+	EmergencyExitPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+                              const std::string& path, RestartPostprocessorPtr rp,
+                              CommunicatorPtr comm);
+	virtual ~EmergencyExitPostprocessor();
+	void update(double step);
+protected:
+	void collectPostprocessData(double step);
+   void writeMetafile(int status);
+   bool readMetafile();
+   void checkMetafile();
+private:
+   std::string path;
+   CommunicatorPtr comm;
+   RestartPostprocessorPtr rp;
+   std::string metafile;
+};
+
+
+#endif /* EmergencyExitPostprocessor_H */
diff --git a/source/VirtualFluidsCore/CoProcessors/InSituCatalystPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/InSituCatalystPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a590b071fcd7a70a2e9f62452c21097df07f0903
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/InSituCatalystPostprocessor.cpp
@@ -0,0 +1,349 @@
+#ifdef VF_CATALYST
+
+#include "InSituCatalystPostprocessor.h"
+#include <LBMKernelETD3Q27.h>
+#include <D3Q27ETBCProcessor.h>
+#include <vector>
+#include <string>
+
+#include <vtkCellType.h>
+#include <vtkPointData.h>
+#include <vtkXMLUnstructuredGridWriter.h>
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+InSituCatalystPostprocessor::InSituCatalystPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+InSituCatalystPostprocessor::InSituCatalystPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, std::string script) : Postprocessor(grid, s)
+{
+   gridRank = Communicator::getInstance()->getProcessID();
+   minInitLevel = this->grid->getCoarsestInitializedLevel();
+   maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   blockVector.resize(maxInitLevel + 1);
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+   }
+
+   Processor = vtkSmartPointer<vtkCPProcessor>::New();
+   Processor->Initialize();
+
+   vtkNew<vtkCPPythonScriptPipeline> pipeline;
+   pipeline->Initialize(script.c_str());
+   Processor->AddPipeline(pipeline.GetPointer());
+
+   buildVTKGrid();
+}
+//////////////////////////////////////////////////////////////////////////
+InSituCatalystPostprocessor::~InSituCatalystPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituCatalystPostprocessor::update(double step)
+{
+   if (scheduler->isDue(step))
+      collectPostprocessData(step);
+
+   UBLOG(logDEBUG3, "InSituCatalystPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituCatalystPostprocessor::collectPostprocessData(double step)
+{
+   unsigned int istep = static_cast<int>(step);
+
+   vtkNew<vtkCPDataDescription> dataDescription;
+   dataDescription->AddInput("input");
+   dataDescription->SetTimeData(step, istep);
+
+   if (Processor->RequestDataDescription(dataDescription.GetPointer()) != 0)
+   {
+      
+      index = 0;
+
+      for (int level = minInitLevel; level <= maxInitLevel; level++)
+      {
+         BOOST_FOREACH(Block3DPtr block, blockVector[level])
+         {
+            if (block)
+            {
+               addPostprocessData(block);
+            }
+         }
+      }
+
+      vtkDoubleArray* rho = vtkDoubleArray::SafeDownCast(unstructuredGrid->GetPointData()->GetArray("Rho"));
+      rho->SetArray(&rhoArray[0], static_cast<vtkIdType>(rhoArray.size()), 1);
+
+      vtkDoubleArray* vx1 = vtkDoubleArray::SafeDownCast(unstructuredGrid->GetPointData()->GetArray("Vx"));
+      vx1->SetArray(&vx1Array[0], static_cast<vtkIdType>(vx1Array.size()), 1);
+
+      vtkDoubleArray* vx2 = vtkDoubleArray::SafeDownCast(unstructuredGrid->GetPointData()->GetArray("Vy"));
+      vx2->SetArray(&vx2Array[0], static_cast<vtkIdType>(vx2Array.size()), 1);
+
+      vtkDoubleArray* vx3 = vtkDoubleArray::SafeDownCast(unstructuredGrid->GetPointData()->GetArray("Vz"));
+      vx3->SetArray(&vx3Array[0], static_cast<vtkIdType>(vx3Array.size()), 1);
+
+      dataDescription->GetInputDescriptionByName("input")->SetGrid(unstructuredGrid);
+      Processor->CoProcess(dataDescription.GetPointer());
+   }
+
+   UBLOG(logINFO, "InSituCatalystPostprocessor step: " << istep);
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituCatalystPostprocessor::addPostprocessData(Block3DPtr block)
+{
+   UbTupleDouble3 org = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+   UbTupleDouble3 nodeOffset = grid->getNodeOffset(block);
+   double         dx = grid->getDeltaX(block);
+
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+   LBMReal f[D3Q27System::ENDF + 1];
+   LBMReal vx1, vx2, vx3, rho;
+
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int maxX1 = (int)(distributions->getNX1());
+   int maxX2 = (int)(distributions->getNX2());
+   int maxX3 = (int)(distributions->getNX3());
+
+   //nummern vergeben und node vector erstellen + daten sammeln
+   CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3, -1);
+   maxX1 -= 2;
+   maxX2 -= 2;
+   maxX3 -= 2;
+
+   
+
+   for (size_t ix3 = minX3; ix3 <= maxX3; ix3++)
+   {
+      for (size_t ix2 = minX2; ix2 <= maxX2; ix2++)
+      {
+         for (size_t ix1 = minX1; ix1 <= maxX1; ix1++)
+         {
+            if (!bcArray.isUndefined(ix1, ix2, ix3) && !bcArray.isSolid(ix1, ix2, ix3))
+            {
+               distributions->getDistribution(f, ix1, ix2, ix3);
+               calcMacros(f, rho, vx1, vx2, vx3);
+               double press = D3Q27System::calcPress(f, rho, vx1, vx2, vx3);
+
+               if (UbMath::isNaN(rho) || UbMath::isInfinity(rho))
+                  UB_THROW(UbException(UB_EXARGS, "rho is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //rho=999.0;
+               if (UbMath::isNaN(press) || UbMath::isInfinity(press))
+                  UB_THROW(UbException(UB_EXARGS, "press is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //press=999.0;
+               if (UbMath::isNaN(vx1) || UbMath::isInfinity(vx1))
+                  UB_THROW(UbException(UB_EXARGS, "vx1 is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //vx1=999.0;
+               if (UbMath::isNaN(vx2) || UbMath::isInfinity(vx2))
+                  UB_THROW(UbException(UB_EXARGS, "vx2 is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //vx2=999.0;
+               if (UbMath::isNaN(vx3) || UbMath::isInfinity(vx3))
+                  UB_THROW(UbException(UB_EXARGS, "vx3 is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //vx3=999.0;
+
+               rhoArray[index] = rho;
+               vx1Array[index] = vx1;
+               vx2Array[index] = vx2;
+               vx3Array[index] = vx3;
+               index++;
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituCatalystPostprocessor::buildVTKGrid()
+{
+   unstructuredGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
+   points = vtkPoints::New();
+   unstructuredGrid->SetPoints(points);
+   arrays[0] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[0]->SetNumberOfComponents(1);
+   arrays[0]->SetName("Rho");
+   arrays[1] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[1]->SetNumberOfComponents(1);
+   arrays[1]->SetName("Vx");
+   arrays[2] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[2]->SetNumberOfComponents(1);
+   arrays[2]->SetName("Vy");
+   arrays[3] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[3]->SetNumberOfComponents(1);
+   arrays[3]->SetName("Vz");
+
+   numOfPoints = 0;
+
+   for (int level = minInitLevel; level <= maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         if (block)
+         {
+            addVTKGridData(block);
+         }
+      }
+   }
+
+   unstructuredGrid->GetPointData()->AddArray(arrays[0]);
+   unstructuredGrid->GetPointData()->AddArray(arrays[1]);
+   unstructuredGrid->GetPointData()->AddArray(arrays[2]);
+   unstructuredGrid->GetPointData()->AddArray(arrays[3]);
+   unstructuredGrid->GetPointData()->SetScalars(arrays[1]);
+
+   rhoArray.resize(numOfPoints);
+   vx1Array.resize(numOfPoints);
+   vx2Array.resize(numOfPoints);
+   vx3Array.resize(numOfPoints);
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituCatalystPostprocessor::addVTKGridData(Block3DPtr block)
+{
+   UbTupleDouble3 org = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+   UbTupleDouble3 nodeOffset = grid->getNodeOffset(block);
+   double         dx = grid->getDeltaX(block);
+
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+   LBMReal f[D3Q27System::ENDF + 1];
+   LBMReal vx1, vx2, vx3, rho;
+
+   //knotennummerierung faengt immer bei 0 an!
+   int SWB, SEB, NEB, NWB, SWT, SET, NET, NWT;
+
+   //Funktionszeiger
+   //typedef void(*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/, LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+
+   //CalcMacrosFct calcMacros = NULL;
+
+   if (block->getKernel()->getCompressible())
+   {
+      calcMacros = &D3Q27System::calcCompMacroscopicValues;
+   }
+   else
+   {
+      calcMacros = &D3Q27System::calcIncompMacroscopicValues;
+   }
+
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int maxX1 = (int)(distributions->getNX1());
+   int maxX2 = (int)(distributions->getNX2());
+   int maxX3 = (int)(distributions->getNX3());
+
+   //nummern vergeben und node vector erstellen + daten sammeln
+   CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3, -1);
+   maxX1 -= 2;
+   maxX2 -= 2;
+   maxX3 -= 2;
+
+   D3Q27BoundaryConditionPtr bcPtr;
+   int nr = points->GetNumberOfPoints();
+
+   double x[3];
+
+   for (size_t ix3 = minX3; ix3 <= maxX3; ix3++)
+   {
+      for (size_t ix2 = minX2; ix2 <= maxX2; ix2++)
+      {
+         for (size_t ix1 = minX1; ix1 <= maxX1; ix1++)
+         {
+            if (!bcArray.isUndefined(ix1, ix2, ix3) && !bcArray.isSolid(ix1, ix2, ix3))
+            {
+               x[0] = double(val<1>(org) -val<1>(nodeOffset) +ix1*dx);
+               x[1] = double(val<2>(org) -val<2>(nodeOffset) +ix2*dx);
+               x[2] = double(val<3>(org) -val<3>(nodeOffset) +ix3*dx);
+
+               points->InsertPoint((vtkIdType)nr, x);
+
+               nodeNumbers(ix1, ix2, ix3) = nr++;
+
+               distributions->getDistribution(f, ix1, ix2, ix3);
+               calcMacros(f, rho, vx1, vx2, vx3);
+               double press = D3Q27System::calcPress(f, rho, vx1, vx2, vx3);
+
+               if (UbMath::isNaN(rho) || UbMath::isInfinity(rho))
+                  UB_THROW(UbException(UB_EXARGS, "rho is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //rho=999.0;
+               if (UbMath::isNaN(press) || UbMath::isInfinity(press))
+                  UB_THROW(UbException(UB_EXARGS, "press is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //press=999.0;
+               if (UbMath::isNaN(vx1) || UbMath::isInfinity(vx1))
+                  UB_THROW(UbException(UB_EXARGS, "vx1 is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //vx1=999.0;
+               if (UbMath::isNaN(vx2) || UbMath::isInfinity(vx2))
+                  UB_THROW(UbException(UB_EXARGS, "vx2 is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //vx2=999.0;
+               if (UbMath::isNaN(vx3) || UbMath::isInfinity(vx3))
+                  UB_THROW(UbException(UB_EXARGS, "vx3 is not a number (nan or -1.#IND) or infinity number -1.#INF in block=" + block->toString() +
+                  ", node=" + UbSystem::toString(ix1) + "," + UbSystem::toString(ix2) + "," + UbSystem::toString(ix3)));
+               //vx3=999.0;
+
+               arrays[0]->InsertNextValue(rho);
+               arrays[1]->InsertNextValue(vx1);
+               arrays[2]->InsertNextValue(vx2);
+               arrays[3]->InsertNextValue(vx3);
+               numOfPoints++;
+            }
+         }
+      }
+   }
+   maxX1 -= 1;
+   maxX2 -= 1;
+   maxX3 -= 1;
+
+   vtkIdType ptIds[8];
+   //cell vector erstellen
+   for (int ix3 = minX3; ix3 <= maxX3; ix3++)
+   {
+      for (int ix2 = minX2; ix2 <= maxX2; ix2++)
+      {
+         for (int ix1 = minX1; ix1 <= maxX1; ix1++)
+         {
+            if ((ptIds[0] = SWB = nodeNumbers(ix1, ix2, ix3)) >= 0
+               && (ptIds[1] = SEB = nodeNumbers(ix1 + 1, ix2, ix3)) >= 0
+               && (ptIds[2] = NWB = nodeNumbers(ix1, ix2 + 1, ix3)) >= 0
+               && (ptIds[3] = NEB = nodeNumbers(ix1 + 1, ix2 + 1, ix3)) >= 0
+               && (ptIds[4] = SWT = nodeNumbers(ix1, ix2, ix3 + 1)) >= 0
+               && (ptIds[5] = SET = nodeNumbers(ix1 + 1, ix2, ix3 + 1)) >= 0
+               && (ptIds[6] = NWT = nodeNumbers(ix1, ix2 + 1, ix3 + 1)) >= 0
+               && (ptIds[7] = NET = nodeNumbers(ix1 + 1, ix2 + 1, ix3 + 1)) >= 0
+               )
+            {
+               unstructuredGrid->InsertNextCell((int)VTK_VOXEL, (vtkIdType)8, ptIds);
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+
+#endif
+
diff --git a/source/VirtualFluidsCore/CoProcessors/InSituCatalystPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/InSituCatalystPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..08da5f64ba36d006d88f8aaa83a9adccbe644bcf
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/InSituCatalystPostprocessor.h
@@ -0,0 +1,54 @@
+#ifdef VF_CATALYST
+
+#ifndef InSituCatalystPostprocessor_h__
+#define InSituCatalystPostprocessor_h__
+
+
+#include <Postprocessor.h>
+#include <Grid3D.h>
+#include <LBMUnitConverter.h>
+
+#include <string>
+
+#include <vtkSmartPointer.h>
+#include <vtkUnstructuredGrid.h>
+#include <vtkDoubleArray.h>
+#include <vtkCPDataDescription.h>
+#include <vtkCPInputDataDescription.h>
+#include <vtkCPProcessor.h>
+#include <vtkCPPythonScriptPipeline.h>
+#include <vtkNew.h>
+
+class InSituCatalystPostprocessor : public Postprocessor
+{
+public:
+   InSituCatalystPostprocessor();
+   InSituCatalystPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, std::string script);
+   virtual ~InSituCatalystPostprocessor(); 
+   void update(double step);
+protected:
+   void collectPostprocessData(double step);
+   void addPostprocessData(Block3DPtr block);
+   void buildVTKGrid();
+   void addVTKGridData(Block3DPtr block);
+private:
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   int minInitLevel;
+   int maxInitLevel;
+   int gridRank;
+   vtkSmartPointer<vtkCPProcessor> Processor;
+   vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid;
+   vtkSmartPointer<vtkPoints> points;
+   vtkSmartPointer<vtkDoubleArray> arrays[4];
+   std::vector<double> vx1Array;
+   std::vector<double> vx2Array;
+   std::vector<double> vx3Array;
+   std::vector<double> rhoArray;
+   int index;
+   int numOfPoints;
+   typedef void(*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/, LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   CalcMacrosFct calcMacros;
+};
+#endif // InSituCatalystPostprocessor_h__
+
+#endif
diff --git a/source/VirtualFluidsCore/CoProcessors/InSituVTKPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/InSituVTKPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..716b2ddd983c6efa7351ecf2bc25beb41ba15743
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/InSituVTKPostprocessor.cpp
@@ -0,0 +1,294 @@
+#ifdef VF_VTK
+
+#include "InSituVTKPostprocessor.h"
+#include <LBMKernelETD3Q27.h>
+#include <D3Q27ETBCProcessor.h>
+#include <vector>
+#include <string>
+
+#include <vtkCellType.h>
+#include <vtkPointData.h>
+#include <vtkXMLUnstructuredGridWriter.h>
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+InSituVTKPostprocessor::InSituVTKPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+InSituVTKPostprocessor::InSituVTKPostprocessor( Grid3DPtr grid, UbSchedulerPtr s, const std::string& configFile, LBMUnitConverterPtr conv ) : Postprocessor(grid, s), conv(conv)
+{
+   gridRank  = Communicator::getInstance()->getProcessID(); 
+   minInitLevel = this->grid->getCoarsestInitializedLevel();
+   maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   readConfigFile(configFile);
+
+   blockVector.resize(maxInitLevel+1);
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+   }
+
+   //initialization of communicator
+   contr = vtkSmartPointer<vtkSocketController>::New();
+   contr->Initialize();
+
+   comm = vtkSmartPointer<vtkSocketCommunicator>::New();
+
+   // Establish connection
+   if (!comm->ConnectTo(wHostname.c_str(), wPort))
+   {
+      cerr << "Client error: Could not connect to the server."<< endl;
+      return;
+   }
+ 
+}
+//////////////////////////////////////////////////////////////////////////
+InSituVTKPostprocessor::~InSituVTKPostprocessor()
+{
+   comm->CloseConnection();
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituVTKPostprocessor::update( double step )
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+
+   UBLOG(logDEBUG3, "InSituVTKPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituVTKPostprocessor::collectPostprocessData( double step )
+{
+   int istep = static_cast<int>(step);
+
+   unstructuredGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
+   points = vtkPoints::New();
+   unstructuredGrid->SetPoints(points);
+   arrays[0] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[0]->SetNumberOfComponents(1);
+   arrays[0]->SetName( "Rho" );
+   arrays[1] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[1]->SetNumberOfComponents(1);
+   arrays[1]->SetName( "Vx" );
+   arrays[2] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[2]->SetNumberOfComponents(1);
+   arrays[2]->SetName( "Vy" );
+   arrays[3] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[3]->SetNumberOfComponents(1);
+   arrays[3]->SetName( "Vz" );
+   arrays[4] = vtkSmartPointer<vtkDoubleArray>::New();
+   arrays[4]->SetNumberOfComponents(1);
+   arrays[4]->SetName( "Press" );
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         if (block)
+         {
+            addPostprocessData(block);
+         }
+      }
+   }
+
+   unstructuredGrid->GetPointData()->AddArray(arrays[0]);
+   unstructuredGrid->GetPointData()->AddArray(arrays[1]);
+   unstructuredGrid->GetPointData()->AddArray(arrays[2]);
+   unstructuredGrid->GetPointData()->AddArray(arrays[3]);
+   unstructuredGrid->GetPointData()->AddArray(arrays[4]);
+   unstructuredGrid->GetPointData()->SetScalars(arrays[1]);
+
+   if (!comm->Send(&istep, 1, 1, 11))
+   {
+      cerr << "Client error: Error sending data." << endl;
+      return;
+   }
+
+   if (!comm->Send(unstructuredGrid, 1, 9))
+   {
+      cerr << "Server error: Error sending data." << endl;
+      return;
+   }
+
+   //vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer = vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
+   //writer->SetInput(unstructuredGrid);
+   //writer->SetFileName("test.vtu");
+   //writer->SetDataModeToAscii();
+   //writer->Update();
+
+   UBLOG(logINFO,"InSituVTKPostprocessor step: " << istep);
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituVTKPostprocessor::addPostprocessData( Block3DPtr block )
+{
+   UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+   UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+   double         dx           = grid->getDeltaX(block);
+
+   LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();     
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal vx1,vx2,vx3,rho;
+
+   //knotennummerierung faengt immer bei 0 an!
+   int SWB,SEB,NEB,NWB,SWT,SET,NET,NWT;
+
+   //Funktionszeiger
+   typedef void (*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/,LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+
+   CalcMacrosFct calcMacros = NULL;
+
+   if(block->getKernel()->getCompressible())
+   {
+      calcMacros = &D3Q27System::calcCompMacroscopicValues;
+   }
+   else
+   {
+      calcMacros = &D3Q27System::calcIncompMacroscopicValues;
+   }
+
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int maxX1 = (int)(distributions->getNX1());
+   int maxX2 = (int)(distributions->getNX2());
+   int maxX3 = (int)(distributions->getNX3());
+
+   //int minX1 = 1;
+   //int minX2 = 1;
+   //int minX3 = 1;
+
+   //int maxX1 = (int)(distributions->getNX1());
+   //int maxX2 = (int)(distributions->getNX2());
+   //int maxX3 = (int)(distributions->getNX3());
+
+   //nummern vergeben und node vector erstellen + daten sammeln
+   CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3,-1);
+   maxX1 -= 2;
+   maxX2 -= 2;
+   maxX3 -= 2;
+
+   D3Q27BoundaryConditionPtr bcPtr;
+   int nr = points->GetNumberOfPoints();
+
+   double x[3];
+
+   for(size_t ix3=minX3; ix3<=maxX3; ix3++)
+   {
+      for(size_t ix2=minX2; ix2<=maxX2; ix2++)
+      {
+         for(size_t ix1=minX1; ix1<=maxX1; ix1++)
+         {
+            if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+            {
+               int index = 0;
+
+               x[0] = double(val<1>(org) - val<1>(nodeOffset) + ix1*dx);
+               x[1] = double(val<2>(org) - val<2>(nodeOffset) + ix2*dx);
+               x[2] = double(val<3>(org) - val<3>(nodeOffset) + ix3*dx);
+
+               points->InsertPoint((vtkIdType)nr, x);
+
+               nodeNumbers(ix1,ix2,ix3) = nr++;
+               
+               distributions->getDistribution(f, ix1, ix2, ix3);
+               calcMacros(f,rho,vx1,vx2,vx3);
+               double press = D3Q27System::calcPress(f,rho,vx1,vx2,vx3);
+
+               if (UbMath::isNaN(rho) || UbMath::isInfinity(rho)) 
+                  UB_THROW( UbException(UB_EXARGS,"rho is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                  ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+               //rho=999.0;
+               if (UbMath::isNaN(press) || UbMath::isInfinity(press)) 
+                  UB_THROW( UbException(UB_EXARGS,"press is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                  ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+               //press=999.0;
+               if (UbMath::isNaN(vx1) || UbMath::isInfinity(vx1)) 
+                  UB_THROW( UbException(UB_EXARGS,"vx1 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                  ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+               //vx1=999.0;
+               if (UbMath::isNaN(vx2) || UbMath::isInfinity(vx2)) 
+                  UB_THROW( UbException(UB_EXARGS,"vx2 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                  ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+               //vx2=999.0;
+               if (UbMath::isNaN(vx3) || UbMath::isInfinity(vx3)) 
+                  UB_THROW( UbException(UB_EXARGS,"vx3 is not a number (nan or -1.#IND) or infinity number -1.#INF in block="+block->toString()+
+                  ", node="+UbSystem::toString(ix1)+","+UbSystem::toString(ix2)+","+UbSystem::toString(ix3)));
+               //vx3=999.0;
+
+               arrays[0]->InsertNextValue(rho * conv->getFactorDensityLbToW2());
+               arrays[1]->InsertNextValue(vx1 * conv->getFactorVelocityLbToW2());
+               arrays[2]->InsertNextValue(vx2 * conv->getFactorVelocityLbToW2());
+               arrays[3]->InsertNextValue(vx3 * conv->getFactorVelocityLbToW2());
+               arrays[4]->InsertNextValue(press * conv->getFactorPressureLbToW2());
+            }
+         }
+      }
+   }
+   maxX1 -= 1;
+   maxX2 -= 1;
+   maxX3 -= 1;
+
+   vtkIdType ptIds[8];
+   //cell vector erstellen
+   for(int ix3=minX3; ix3<=maxX3; ix3++)
+   {
+      for(int ix2=minX2; ix2<=maxX2; ix2++)
+      {
+         for(int ix1=minX1; ix1<=maxX1; ix1++)
+         {
+            if(   (ptIds[0]=SWB=nodeNumbers( ix1  , ix2,   ix3   )) >= 0
+               && (ptIds[1]=SEB=nodeNumbers( ix1+1, ix2,   ix3   )) >= 0
+               && (ptIds[2]=NWB=nodeNumbers( ix1  , ix2+1, ix3   )) >= 0
+               && (ptIds[3]=NEB=nodeNumbers( ix1+1, ix2+1, ix3   )) >= 0
+               && (ptIds[4]=SWT=nodeNumbers( ix1  , ix2,   ix3+1 )) >= 0
+               && (ptIds[5]=SET=nodeNumbers( ix1+1, ix2,   ix3+1 )) >= 0
+               && (ptIds[6]=NWT=nodeNumbers( ix1  , ix2+1, ix3+1 )) >= 0 
+               && (ptIds[7]=NET=nodeNumbers( ix1+1, ix2+1, ix3+1 )) >= 0
+               )
+            {
+               unstructuredGrid->InsertNextCell((int)VTK_VOXEL, (vtkIdType)8, ptIds);
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void InSituVTKPostprocessor::readConfigFile( const std::string& configFile )
+{
+   ifstream ifs;
+   ifs.open (configFile, ifstream::in);
+   if(!ifs) throw UbException(UB_EXARGS,"can not open "+configFile);
+ 
+   string dummy;
+   int wRank = 0;
+   getline(ifs, dummy);
+   int np = Communicator::getInstance()->getNumberOfProcesses();
+
+   while (ifs.good())
+   {
+      getline(ifs, dummy, ';');
+      getline(ifs, wIP, ';');
+      getline(ifs, wHostname, ';');
+      getline(ifs, dummy);
+      wPort = stoi(dummy);
+      if(wRank == gridRank) break;
+      wRank++;
+   }
+   ifs.close();
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+#endif
+
+
diff --git a/source/VirtualFluidsCore/CoProcessors/InSituVTKPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/InSituVTKPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4f0a6749a819cb34e3195b3c6eec049902d951f
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/InSituVTKPostprocessor.h
@@ -0,0 +1,52 @@
+#ifdef VF_VTK
+
+#ifndef InSituVTKPostprocessor_h__
+#define InSituVTKPostprocessor_h__
+
+#include <Postprocessor.h>
+#include <Grid3D.h>
+#include <LBMUnitConverter.h>
+
+#include <string>
+
+//VTK headers
+#include <vtkSocketCommunicator.h>
+#include <vtkSocketController.h>
+#include <vtkSmartPointer.h>
+#include <vtkUnstructuredGrid.h>
+#include <vtkDoubleArray.h>
+
+class InSituVTKPostprocessor : public Postprocessor
+{
+public:
+   InSituVTKPostprocessor();
+   InSituVTKPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, const std::string& configFile, LBMUnitConverterPtr conv);
+   virtual ~InSituVTKPostprocessor(); 
+   void update(double step);
+protected:
+   void collectPostprocessData(double step);
+   void addPostprocessData(Block3DPtr block);
+   void readConfigFile(const std::string& configFile);
+
+   //void clearData();
+private:
+   std::string path;
+   LBMUnitConverterPtr conv;
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   int minInitLevel;
+   int maxInitLevel;
+   int gridRank;
+   vtkSmartPointer<vtkSocketCommunicator> comm;
+   vtkSmartPointer<vtkSocketController>   contr;
+   vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid;
+   vtkSmartPointer<vtkPoints> points;
+   vtkSmartPointer<vtkDoubleArray> arrays[5];
+   int wPort;
+   std::string wHostname;
+   std::string wIP;
+};
+
+#endif // InSituVTKPostprocessor_h__
+
+#endif
+
diff --git a/source/VirtualFluidsCore/CoProcessors/NUPSCounterPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/NUPSCounterPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c09ee03334d59ddf2b9059a079438d40bac3ebc0
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/NUPSCounterPostprocessor.cpp
@@ -0,0 +1,74 @@
+#include "NUPSCounterPostprocessor.h"
+
+
+NUPSCounterPostprocessor::NUPSCounterPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, int numOfThreads, CommunicatorPtr comm)
+                                                   : Postprocessor(grid, s),
+                                                     numOfThreads(numOfThreads),
+                                                     comm(comm),
+                                                     nup(0),
+                                                     nup_t(0),
+                                                     nupsStep(0.0)
+{
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      timer.resetAndStart();
+
+      double nop = comm->getNumberOfProcesses();
+      int minInitLevel = grid->getCoarsestInitializedLevel();
+      int maxInitLevel = grid->getFinestInitializedLevel();
+      int gl = 2;
+      UbTupleInt3 blocknx = grid->getBlockNX();
+      //int nod = (val<1>(blocknx)+gl) * (val<2>(blocknx)+gl) * (val<3>(blocknx)+gl);
+      double nod = (double)(val<1>(blocknx)) * (double)(val<2>(blocknx)) * (double)(val<3>(blocknx));
+      nup = 0;
+
+      for(int level = minInitLevel; level<=maxInitLevel; level++)
+      {
+         int nob = grid->getNumberOfBlocks(level);
+         nup_t += (double)(1<<level) * nob * nod;
+      }
+      nup = nup_t / nop;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+NUPSCounterPostprocessor::~NUPSCounterPostprocessor() 
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void NUPSCounterPostprocessor::update(double step)
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+}
+//////////////////////////////////////////////////////////////////////////
+void NUPSCounterPostprocessor::collectPostprocessData(double step)
+{
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      double time = timer.stop();
+      //double time = timer.elapsed();
+      //std::ofstream ostr;
+      //std::string fname = path;
+      //ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);
+      //if(!ostr)
+      //{ 
+      //   ostr.clear(); 
+      //   std::string path = UbSystem::getPathFromString(fname);
+      //   if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);}
+      //   if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+      //}
+      double nups_t = nup_t*(step-nupsStep)/time;
+      double nups = nup*(step-nupsStep)/time;//timer.getTotalTime();
+      double tnups = nups/(double)numOfThreads;
+      //ostr << nups << std::endl;
+      //ostr.close();
+      UBLOG(logINFO, "Calculation step = "<<step);
+      UBLOG(logINFO, "Total performance = "<<nups_t<<" NUPS");
+      UBLOG(logINFO, "Performance per process = "<<nups<<" NUPS");
+      UBLOG(logINFO, "Performance per thread = "<<tnups<<" NUPS");
+      UBLOG(logINFO, "Time for " << step-nupsStep <<" steps = "<< time <<" s");
+      //timer.resetAndStart();
+      //timer.restart();
+      nupsStep = step;
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/NUPSCounterPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/NUPSCounterPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..48a90c90ce437aa4c1d0eab606d842bc8ae38392
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/NUPSCounterPostprocessor.h
@@ -0,0 +1,35 @@
+/*
+*  NUPSCounterPostprocessor.h
+*
+*  Created on: 03.05.2011
+*  Author: K. Kucher
+*/
+
+#ifndef NUPSCOUNTERPOSTPROCESSOR_H_
+#define NUPSCOUNTERPOSTPROCESSOR_H_
+
+#include "Postprocessor.h"
+#include "Communicator.h"
+#include "basics/utilities/UbTiming.h"
+#include <boost/timer.hpp>
+
+class NUPSCounterPostprocessor: public Postprocessor {
+public:
+   NUPSCounterPostprocessor(Grid3DPtr grid, UbSchedulerPtr s, int numOfThreads, CommunicatorPtr comm);
+   virtual ~NUPSCounterPostprocessor();
+   void update(double step);
+protected:
+   void collectPostprocessData(double step);
+   UbTimer timer;
+   //boost::timer timer;
+   int numOfThreads;
+   double numberOfNodes;
+   double numberOfBlocks;
+   double nup;
+   double nup_t;
+   double nupsStep;
+   CommunicatorPtr comm;
+};
+
+
+#endif 
diff --git a/source/VirtualFluidsCore/CoProcessors/Particles.cpp b/source/VirtualFluidsCore/CoProcessors/Particles.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5e6e5141f1ae80abd9b479f20f49153b42575843
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/Particles.cpp
@@ -0,0 +1,11 @@
+#include "Particles.h"
+
+
+Particles::Particles()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+Particles::~Particles()
+{
+}
+//////////////////////////////////////////////////////////////////////////
diff --git a/source/VirtualFluidsCore/CoProcessors/Particles.h b/source/VirtualFluidsCore/CoProcessors/Particles.h
new file mode 100644
index 0000000000000000000000000000000000000000..c133f9de49021296ed126bc1ec609a1396dad243
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/Particles.h
@@ -0,0 +1,29 @@
+#ifndef PARTICLES_H
+#define PARTICLES_H
+
+#include <boost/shared_ptr.hpp>
+# define numOfvarClass 15
+
+class Particles;
+typedef boost::shared_ptr<Particles> ParticlesPtr;
+
+class Particles 
+{
+public:
+	double x,y,z,xold,yold,zold;
+	double vxold,vyold,vzold;
+	double vxoldf,vyoldf,vzoldf;
+	int ID;
+	int rankOfParticle;
+    int level;
+	//double dx;
+
+
+	Particles();
+	~Particles();
+protected:
+private:
+	
+};
+#endif
+
diff --git a/source/VirtualFluidsCore/CoProcessors/Postprocessor.h b/source/VirtualFluidsCore/CoProcessors/Postprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7b2c730bd6a6920a95a4eb3f7337b7cea6c5b01
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/Postprocessor.h
@@ -0,0 +1,64 @@
+#ifndef POSTPROCESSOR_H
+#define POSTPROCESSOR_H
+
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/serialization/serialization.hpp>
+
+#include <Grid3D.h>
+#include <basics/utilities/UbScheduler.h>
+
+class Postprocessor;
+typedef boost::shared_ptr<Postprocessor> PostprocessorPtr;
+
+class Postprocessor
+{
+public:
+   Postprocessor()
+   {
+
+   }
+
+   Postprocessor(Grid3DPtr grid, UbSchedulerPtr s)
+      : grid(grid)
+      , scheduler(s)
+   {
+      connection = grid->connect(boost::bind(&Postprocessor::update, this, _1));
+   }
+
+   virtual ~Postprocessor()
+   {
+      grid->disconnect(connection);
+   }
+
+   virtual void update(double step) = 0;
+
+   virtual void disconnect()
+   {
+      grid->disconnect(connection);
+   }
+
+   virtual void reconnect(Grid3DPtr grid)
+   {
+      this->grid = grid;
+      this->grid->disconnect(connection);
+      connection = this->grid->connect(boost::bind(&Postprocessor::update, this, _1));
+   }
+
+protected:
+   Grid3DPtr grid;
+   UbSchedulerPtr scheduler;
+private:
+   Grid3D::connection_t connection;
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      //ar & grid;
+      ar & scheduler;
+   }
+};
+#endif
+
diff --git a/source/VirtualFluidsCore/CoProcessors/QCriterionPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/QCriterionPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d70ab731fa0d59688c8debaf9c6cd57f14e46ce2
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/QCriterionPostprocessor.cpp
@@ -0,0 +1,393 @@
+#include "QCriterionPostprocessor.h"
+#include "LBMKernel3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include <vector>
+#include <string>
+#include <boost/foreach.hpp>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+
+
+using namespace std;
+using namespace D3Q27System;
+
+QCriterionPostprocessor::QCriterionPostprocessor(Grid3DPtr grid, const std::string& path, 
+	WbWriter* const writer,
+	UbSchedulerPtr s, CommunicatorPtr comm)
+	: Postprocessor(grid, s),
+	path(path),
+	comm(comm),
+	writer(writer)
+{
+	init();
+}
+//////////////////////////////////////////////////////////////////////////
+void QCriterionPostprocessor::init()
+{
+	gridRank  = comm->getProcessID(); 
+	minInitLevel = this->grid->getCoarsestInitializedLevel();
+	maxInitLevel = this->grid->getFinestInitializedLevel();
+
+	blockVector.resize(maxInitLevel+1);
+
+	for(int level = minInitLevel; level<=maxInitLevel;level++)
+	{
+		grid->getBlocks(level, gridRank, true, blockVector[level]); //grid: private variable in Postprocessor. Initialized by filling with blocks
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+void QCriterionPostprocessor::update(double step)
+{
+	if(scheduler->isDue(step) )
+		collectPostprocessData(step);
+
+	UBLOG(logDEBUG3, "QCriterionPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void QCriterionPostprocessor::collectPostprocessData(double step)
+{
+	int istep = static_cast<int>(step);
+
+	for(int level = minInitLevel; level<=maxInitLevel;level++)
+	{
+		BOOST_FOREACH(Block3DPtr block, blockVector[level])
+		{
+			if (block)
+			{
+				addPostprocessData(block);
+
+			}
+		}
+	}
+
+	string partName = writer->writeOctsWithNodeData(path+ UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep),nodes,cells,datanames,data);
+	size_t found=partName.find_last_of("//");
+	string piece = partName.substr(found+1);
+
+	vector<string> cellDataNames;
+
+	//distributed writing as in MacroscopicValuesPostprocessor.cpp
+	vector<string> pieces = comm->gather(piece); //comm: MPI-Wrapper
+	if (comm->getProcessID() == comm->getRoot())
+	{
+		string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(path+"_"+UbSystem::toString(istep),pieces,datanames,cellDataNames);
+
+		vector<string> filenames;
+		filenames.push_back(pname);
+		if (step == Postprocessor::scheduler->getMinBegin()) //first time in timeseries
+		{
+			WbWriterVtkXmlASCII::getInstance()->writeCollection(path+"_collection",filenames,istep,false);
+		} 
+		else
+		{
+			WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(path+"_collection",filenames,istep,false);
+		}
+		UBLOG(logINFO,"QCriterionPostprocessor step: " << istep);
+	}
+
+	clearData();
+
+
+}
+//////////////////////////////////////////////////////////////////////////
+void QCriterionPostprocessor::clearData()
+{
+	nodes.clear();
+	cells.clear();
+	datanames.clear();
+	data.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+void QCriterionPostprocessor::addPostprocessData(const Block3DPtr block)
+{
+	UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+	UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+	UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+	double         dx           = grid->getDeltaX(block);
+
+	//Diese Daten werden geschrieben:
+	datanames.resize(0);
+	datanames.push_back("q");
+	datanames.push_back("scaleFactor");
+	data.resize(datanames.size());
+
+
+	LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+	BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+	DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();     
+
+	int SWB,SEB,NEB,NWB,SWT,SET,NET,NWT;
+
+	int minX1 = 0;
+	int minX2 = 0;
+	int minX3 = 0;
+
+	int maxX1 = (int)(distributions->getNX1());
+	int maxX2 = (int)(distributions->getNX2());
+	int maxX3 = (int)(distributions->getNX3());
+
+	int currentLevel = block->getLevel();
+	//nummern vergeben und node vector erstellen + daten sammeln
+	CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3,-1);
+	maxX1 -= 2; //-2 wegen ghost layer: 
+	maxX2 -= 2; //0-maxXi-1 ist arraygroesse. 
+	maxX3 -= 2; //ueberlapp 1 in +,- Richtung. zum schreiben werden statt feldern von 1 bis (max-2) felder von 0 bis max-3 verwendet! 
+
+
+	int nr = (int)nodes.size();
+
+	for(int ix3=minX3; ix3<=maxX3; ix3++)
+	{
+		for(int ix2=minX2; ix2<=maxX2; ix2++)
+		{
+			for(int ix1=minX1; ix1<=maxX1; ix1++)
+			{
+				if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+				{
+					//nodeNumbers-vektor wird mit koordinaten befuellt
+					int index = 0;
+					nodeNumbers(ix1,ix2,ix3) = nr++;
+					nodes.push_back( makeUbTuple(float(val<1>(org) - val<1>(nodeOffset) + ix1*dx),
+						float(val<2>(org) - val<2>(nodeOffset) + ix2*dx),
+						float(val<3>(org) - val<3>(nodeOffset) + ix3*dx)) );			
+
+					/////////////////////////////
+					// Geschwindigkeitsvektoren 
+					LBMReal vE[3];
+					LBMReal vW[3];
+					LBMReal vN[3];
+					LBMReal vS[3];
+					LBMReal vT[3];
+					LBMReal vB[3];
+					//hole geschwindigkeiten an nachbarknoten
+					getNeighborVelocities(1,0,0, ix1,  ix2,  ix3, block, vE, vW);
+					getNeighborVelocities(0,1,0, ix1,  ix2,  ix3, block, vN, vS);
+					getNeighborVelocities(0,0,1, ix1,  ix2,  ix3, block, vT, vB);
+					//////////////////////////////////
+					//derivatives
+					LBMReal duxdy=(vN[xdir]-vS[xdir])*0.5;
+					LBMReal duydx=(vE[ydir]-vW[ydir])*0.5;
+					LBMReal duxdz=(vT[xdir]-vB[xdir])*0.5;
+					LBMReal duzdx=(vE[zdir]-vW[zdir])*0.5;
+					LBMReal duydz=(vT[ydir]-vB[ydir])*0.5;
+					LBMReal duzdy=(vN[zdir]-vS[zdir])*0.5;
+
+					LBMReal duxdx=(vE[xdir]-vW[xdir])*0.5;
+					LBMReal duydy=(vN[ydir]-vS[ydir])*0.5;
+					LBMReal duzdz=(vT[zdir]-vB[zdir])*0.5;					
+
+					LBMReal scaleFactor=(double)(1<<(currentLevel-minInitLevel));//pow(2.0,(double)(currentLevel-minInitLevel));//finer grid -> current level higher. coarsest grid: currentLevel=minInitLevel=0
+					// Q=-0.5*(S_ij S_ij - Omega_ij Omega_ij) => regions where vorticity is larger than strain rate
+					LBMReal q=-(duxdy*duydx+duxdz*duzdx+duydz*duzdy+duxdx*duxdx+duydy*duydy+duzdz*duzdz)*scaleFactor;
+
+					data[index++].push_back( q );
+					data[index++].push_back( scaleFactor );
+
+				}
+			}
+		}
+	}
+	maxX1 -= 1;
+	maxX2 -= 1;
+	maxX3 -= 1;
+	//cell vector erstellen
+	for(int ix3=minX3; ix3<=maxX3; ix3++)
+	{
+		for(int ix2=minX2; ix2<=maxX2; ix2++)
+		{
+			for(int ix1=minX1; ix1<=maxX1; ix1++)
+			{
+				if(   (SWB=nodeNumbers( ix1  , ix2,   ix3   )) >= 0
+					&& (SEB=nodeNumbers( ix1+1, ix2,   ix3   )) >= 0
+					&& (NEB=nodeNumbers( ix1+1, ix2+1, ix3   )) >= 0
+					&& (NWB=nodeNumbers( ix1  , ix2+1, ix3   )) >= 0 
+					&& (SWT=nodeNumbers( ix1  , ix2,   ix3+1 )) >= 0
+					&& (SET=nodeNumbers( ix1+1, ix2,   ix3+1 )) >= 0
+					&& (NET=nodeNumbers( ix1+1, ix2+1, ix3+1 )) >= 0
+					&& (NWT=nodeNumbers( ix1  , ix2+1, ix3+1 )) >= 0                )
+				{
+					// for valid points: neighbors are added to cells-vector
+					cells.push_back( makeUbTuple(SWB,SEB,NEB,NWB,SWT,SET,NET,NWT) );
+				}
+			}
+		}
+	}
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void QCriterionPostprocessor::getNeighborVelocities(int offx, int offy, int offz, int ix1, int ix2, int ix3, const Block3DPtr block, LBMReal* vE, LBMReal* vW)
+{
+	LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+	BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+	DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();   
+
+	int minX1 = 0;
+	int minX2 = 0;
+	int minX3 = 0;
+
+	int maxX1 = (int)(distributions->getNX1());
+	int maxX2 = (int)(distributions->getNX2());
+	int maxX3 = (int)(distributions->getNX3());
+	if (maxX1<3) throw UbException(UB_EXARGS,"QCriterionPostprocessor: NX1 too small for FD stencils!");
+	maxX1 -= 2;
+	maxX2 -= 2;
+	maxX3 -= 2;
+	bool checkInterpolation=true;
+	bool neighNodeIsBC=false;
+	D3Q27BoundaryConditionPtr bcPtr;
+
+	int rankSelf= block->getRank(); 
+	if (!(offx+offy+offz)==1) throw UbException(UB_EXARGS,"getNeighborVelocities called for diagonal directions!");
+	//////get neighbor nodes, if existent
+	if ((ix1==0 && offx==1) || (ix2==0 && offy==1) || (ix3==0 && offz==1))
+	{
+		int RankNeighborW; 
+		UbTupleDouble3 orgNodeRW =  grid->getNodeCoordinates(block,  ix1, ix2, ix3);
+		double xp000= ( val<1>(orgNodeRW));
+		double yp000= ( val<2>(orgNodeRW));
+		double zp000= ( val<3>(orgNodeRW));
+
+		int currentLevel = block->getLevel();
+		UbTupleInt3 blockIndexes = grid->getBlockIndexes(xp000,yp000, zp000,currentLevel);
+		Block3DPtr blockNeighW;
+
+		if ((val<1>(blockIndexes)!=0 && offx==1) || (val<2>(blockIndexes)!=0 && offy==1) || (val<3>(blockIndexes)!=0 && offz==1))
+		{
+
+			blockNeighW = grid->getBlock(val<1>(blockIndexes)-offx, val<2>(blockIndexes)-offy, val<3>(blockIndexes)-offz, currentLevel);
+
+		}
+		else if (offx==1 && grid->isPeriodicX1())
+		{
+			blockNeighW = grid->getBlock((grid->getNX1()-1), val<2>(blockIndexes), val<3>(blockIndexes), currentLevel);
+		}
+		else if (offy==1 && grid->isPeriodicX1())
+		{
+			blockNeighW = grid->getBlock(val<1>(blockIndexes),(grid->getNX2()-1),  val<3>(blockIndexes), currentLevel);
+		}
+		else if (offz==1 && grid->isPeriodicX1())
+		{
+			blockNeighW = grid->getBlock( val<1>(blockIndexes), val<2>(blockIndexes),(grid->getNX3()-1), currentLevel);
+		}
+		else neighNodeIsBC;
+
+		if(blockNeighW && blockNeighW->isActive())
+		{	     		     
+			RankNeighborW= blockNeighW->getRank();   
+		}
+		else
+		{
+
+			blockNeighW = block;
+			RankNeighborW= blockNeighW->getRank();
+			checkInterpolation=false;
+		}
+		if (RankNeighborW!=rankSelf)
+		{
+
+			blockNeighW = block;
+			RankNeighborW= blockNeighW->getRank();
+			checkInterpolation=false;
+		}
+
+		///////////////////////////////////////
+		////compute distribution at neighboring nodes from neighboring blocks
+
+		if (checkInterpolation==false || neighNodeIsBC)
+		{
+
+			LBMKernel3DPtr kernelW = blockNeighW->getKernel();
+			BCArray3D<D3Q27BoundaryCondition>& bcArrayW = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernelW->getBCProcessor())->getBCArray();          
+			DistributionArray3DPtr distributionsW = kernelW->getDataSet()->getFdistributions();
+			LBMReal fW2[27];
+			LBMReal fW[27];
+			LBMReal f0[27];
+			LBMReal fE[27];
+			LBMReal v0[3];
+			LBMReal vW2[3];
+			//distributionsW->getDistribution(fW2, std::max(ix1+2*offx,1), std::max(ix2+2*offy,1), std::max(ix3+2*offz,1));
+			//distributionsW->getDistribution(fW, std::max(ix1+offx,1), std::max(ix2+offy,1), std::max(ix3+offz,1));
+			//distributionsW->getDistribution(f0, std::max(ix1    ,1), std::max(ix2    ,1), std::max(ix3    ,1));
+			//distributions->getDistribution(fE, std::max(ix1+offx    ,1), std::max(ix2+offy    ,1), std::max(ix3+offz    ,1)); //E:= plus 1
+			distributionsW->getDistribution(fW2, std::max(ix1+2*offx,0), std::max(ix2+2*offy,0), std::max(ix3+2*offz,0));
+			distributionsW->getDistribution(fW, std::max(ix1+offx,0), std::max(ix2+offy,0), std::max(ix3+offz,0));
+			distributionsW->getDistribution(f0, std::max(ix1    ,0), std::max(ix2    ,0), std::max(ix3    ,0));
+			distributions->getDistribution(fE, std::max(ix1+offx    ,0), std::max(ix2+offy    ,0), std::max(ix3+offz    ,0)); //E:= plus 1
+
+			computeVelocity(fE,vE);
+			computeVelocity(fW,vW);
+			computeVelocity(fW2,vW2);
+			computeVelocity(f0,v0);
+			//second order non-symetric interpolation
+			vW[0]=v0[0]*1.5-vW[0]+0.5*vW2[0];
+			vW[1]=v0[1]*1.5-vW[1]+0.5*vW2[1];
+			vW[2]=v0[2]*1.5-vW[2]+0.5*vW2[2];
+		    //throw UbException(UB_EXARGS,"Parallel or Non-Uniform Simulation -- not yet implemented");
+		}
+		else
+		{
+			LBMKernel3DPtr kernelW = blockNeighW->getKernel();
+			BCArray3D<D3Q27BoundaryCondition>& bcArrayW = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernelW->getBCProcessor())->getBCArray();          
+			DistributionArray3DPtr distributionsW = kernelW->getDataSet()->getFdistributions();
+			LBMReal fW[27];
+
+			if (offx==1)
+			{
+				distributionsW->getDistribution(fW, (distributions->getNX1())-1, ix2, ix3); //moved one block backward, now get last entry
+			}
+			else if (offy==1)
+			{
+				distributionsW->getDistribution(fW, ix1,(distributions->getNX2())-1, ix3); 
+
+			}
+			else if (offz==1)
+			{
+				distributionsW->getDistribution(fW, ix1,ix2,distributions->getNX3()-1); 
+			}
+			computeVelocity(fW,vW);
+		}
+
+
+	}					 
+	else
+	{
+		//data available in current block:
+		LBMReal fW[27];
+		distributions->getDistribution(fW, ix1-offx, ix2-offy, ix3-offz);
+		computeVelocity(fW,vW);
+
+	}
+	if (checkInterpolation==true)
+	{
+		//in plus-direction data is available in current block because of ghost layers
+		LBMReal fE[27];
+		distributions->getDistribution(fE, ix1+offx, ix2+offy, ix3+offz); //E:= plus 1
+		computeVelocity(fE,vE);
+	}
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void QCriterionPostprocessor::computeVelocity(LBMReal* f, LBMReal* v)
+{
+	//////////////////////////////////////////////////////////////////////////
+	//compute x,y,z-velocity components from distribution
+	//////////////////////////////////////////////////////////////////////////
+	//v[xdir] = f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] - f[BW]
+	//+ f[BE] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+	//+ f[BSE] - f[BNW]; 
+
+	//v[ydir] = f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+	//- f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+	//+ f[BNW]; 
+
+	//v[zdir] = f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+	//+ f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+	//- f[BNW];
+
+   v[xdir] = D3Q27System::getIncompVelocityX1(f);
+
+   v[ydir] = D3Q27System::getIncompVelocityX2(f);
+
+   v[zdir] = D3Q27System::getIncompVelocityX3(f);
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/QCriterionPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/QCriterionPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ba0d308f7cefb0faa40cec32223660bef499bfb
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/QCriterionPostprocessor.h
@@ -0,0 +1,62 @@
+//! \file QCriterionPostprocessor.h
+//!  \brief Created on: 25.08.2013
+//!  \author: Sonja Uphoff
+
+
+#ifndef QCriterionPostprocessor_H
+#define QCriterionPostprocessor_H
+
+#include "Postprocessor.h"
+#include "Grid3D.h"
+#include "Block3D.h"
+
+#include "Communicator.h"
+#include "WbWriter.h"
+
+#include <boost/shared_ptr.hpp>
+class QCriterionPostprocessor;
+typedef boost::shared_ptr<QCriterionPostprocessor> QKritPostprocessorPtr;
+
+//! \brief  Computes the value Q with which vortices can be visualized as isocontours to Q=0, writes to .vtk, For uniform, serial setups only!
+//! \details writes at given time intervals specified in scheduler (s)  
+//!          Processing: paraview, take isolines of entry for Q-criterion vortex detection 
+//!			 Q-Criterion: Visualize Vorteces as regions where Vorticity is larger than strain rate (Hunt, 1988)
+//! \author  Sonja Uphoff 
+
+class QCriterionPostprocessor : public Postprocessor
+{
+public:
+	QCriterionPostprocessor(Grid3DPtr grid, const std::string& path, WbWriter* const writer, 
+		UbSchedulerPtr s, CommunicatorPtr comm);
+	//! Make update if timestep is write-timestep specified in UbSchedulerPtr s
+	void update(double step); 
+protected:
+	//! Prepare data and write in .vtk file
+	void collectPostprocessData(double step);
+	//! Q is computed for all points in a block. Data for writing is added to data and cell vectors. 
+	void addPostprocessData(const Block3DPtr block);
+	//! After writing to .vtk-file, all vectors are reset 
+	void clearData();
+	//! Computes macroscopic velocities 
+	void computeVelocity(LBMReal* f, LBMReal* v);
+	//! Computes average and RMS values of macroscopic quantities 
+	void getNeighborVelocities(int offx, int offy, int offz, int ix1, int ix2, int ix3,const Block3DPtr block, LBMReal* vE,LBMReal* vW);
+
+private:
+	void init();
+	std::vector<UbTupleFloat3> nodes;
+	std::vector<UbTupleInt8> cells;
+	std::vector<std::string> datanames; //only one entry for QKrit-Postprocessor: Q
+	std::vector<std::vector<double> > data; 
+	std::vector<std::vector<Block3DPtr> > blockVector;
+	int minInitLevel; //go through all levels for block vector of current process from minInitLevel to maxInitLevel
+	int maxInitLevel;
+	int gridRank;     //comm-Rank des aktuellen prozesses
+	std::string path;
+	WbWriter* writer;
+	CommunicatorPtr comm;
+	enum Values{xdir = 0, ydir = 1, zdir = 2};  	//labels for the different components
+};
+#endif
+
+
diff --git a/source/VirtualFluidsCore/CoProcessors/RestartPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/RestartPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..128195087bba1b466f180838214c16849e0d5a42
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/RestartPostprocessor.cpp
@@ -0,0 +1,286 @@
+#include "RestartPostprocessor.h"
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/archive/binary_iarchive.hpp>
+
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+#include "BoostSerializationClassExportHelper.h"
+
+#include <MemoryUtil.h>
+
+RestartPostprocessor::RestartPostprocessor(Grid3DPtr& grid, UbSchedulerPtr s, CommunicatorPtr comm, const std::string& path, ArchiveType type) :
+   Postprocessor(grid, s),
+   grid(grid),
+   path(path),
+   archiveType(type),
+   comm(comm)
+{
+   restartStep = 0;
+   this->path = path + "/checkpoints";
+   metafile = this->path + "/LastCP.txt";
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      checkMetafile();
+   }
+   comm->barrier();
+   grid = restart();
+}
+//////////////////////////////////////////////////////////////////////////
+RestartPostprocessor::RestartPostprocessor(Grid3DPtr& grid, UbSchedulerPtr s, CommunicatorPtr comm, const std::string& path, int restartStep, ArchiveType type) :
+Postprocessor(grid, s),
+grid(grid),
+path(path),
+archiveType(type),
+comm(comm),
+restartStep(restartStep)
+{
+   this->path = path + "/checkpoints";
+   metafile = this->path + "/LastCP.txt";
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      writeMetafile(restartStep);
+   }
+   comm->barrier();
+   grid = restart();
+}
+//////////////////////////////////////////////////////////////////////////
+RestartPostprocessor::~RestartPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::update(double step)
+{
+   if(scheduler->isDue(step) && step != restartStep)
+   {
+      doCheckPoint(int(step));
+
+      if(comm->getProcessID() == comm->getRoot()) UBLOG(logINFO,"RestartPostprocessor save step: " << step);
+
+      UBLOG(logDEBUG3, "RestartPostprocessor::update:" << step);
+   }   
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::addPostprocessor( PostprocessorPtr p )
+{
+   postprocessors.push_back(p);
+}
+//////////////////////////////////////////////////////////////////////////
+PostprocessorPtr RestartPostprocessor::getPostprocessor(int index)
+{
+   return postprocessors[index];
+}
+//////////////////////////////////////////////////////////////////////////
+std::vector<PostprocessorPtr> RestartPostprocessor::getPostprocessors()
+{
+   return postprocessors;
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::doCheckPoint(int step)
+{
+   UBLOG(logDEBUG3,"Save check point - start");
+
+   int pid = comm->getProcessID();
+   std::string filename = path + "/checkpoint" + UbSystem::toString(step) + "/checkpoint" + UbSystem::toString(pid) + "_" + UbSystem::toString(step);
+
+   if (archiveType == TXT)
+   {
+      saveTxtArchive(filename + ".txt");
+   } 
+   else if(archiveType == BINARY)
+   {
+      saveBinArchive(filename + ".bin");
+   }
+
+   comm->barrier();
+
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      writeMetafile(step);
+   }
+
+   UBLOG(logDEBUG3,"Save check point - end");
+}
+//////////////////////////////////////////////////////////////////////////
+Grid3DPtr RestartPostprocessor::restart()
+{
+   restartStep = readMetafile();
+
+   comm->barrier();
+
+   if (restartStep > 0)
+   {
+      if(comm->getProcessID() == comm->getRoot()) UBLOG(logINFO,"Load check point - start");
+      int pid = comm->getProcessID();
+      std::string filename = path + "/checkpoint" + UbSystem::toString(restartStep) + "/checkpoint" + UbSystem::toString(pid) + "_" + UbSystem::toString(restartStep);
+
+      if (archiveType == TXT)
+      {
+         loadTxtArchive(filename + ".txt");
+      } 
+      else if(archiveType == BINARY)
+      {
+         loadBinArchive(filename + ".bin");
+      }
+
+      this->reconnect(grid);
+      if(comm->getProcessID() == comm->getRoot()) UBLOG(logINFO,"Load check point - end");
+
+      if(comm->getProcessID() == comm->getRoot()) UBLOG(logINFO,"RestartPostprocessor restart step: " << restartStep);
+
+      return grid;
+   } 
+   else
+   {
+      return grid;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::acceptGridVisitors()
+{
+   BOOST_FOREACH(Grid3DVisitorPtr v, gridVisitors)
+   {
+      grid->accept(*(v.get()));
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::acceptBlockVisitors()
+{
+   BOOST_FOREACH(Block3DVisitorPtr v, blockVisitors)
+   {
+      grid->accept(*(v.get()));
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::addGridVisitor( Grid3DVisitorPtr v )
+{
+   gridVisitors.push_back(v);
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::addBlockVisitor( Block3DVisitorPtr v )
+{
+   blockVisitors.push_back(v);
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::saveTxtArchive(std::string filename)
+{
+   std::ofstream file(filename.c_str()); 
+   if(!file)
+   { 
+      file.clear(); 
+      std::string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); file.open(filename.c_str());}
+      if(!file) throw UbException(UB_EXARGS,"couldn't open file "+filename);
+   }
+   boost::archive::text_oarchive oa(file);
+   oa.register_type<Grid3D>();
+   oa << grid;
+
+   int psize = (int)postprocessors.size(); 
+   oa << psize;
+
+   oa.register_type<PostprocessorPtr>();
+   BOOST_FOREACH(PostprocessorPtr pp, postprocessors)
+   {
+      oa << pp;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::loadTxtArchive( std::string filename )
+{
+   std::ifstream file(filename.c_str()); 
+   if (!file.is_open()) UB_THROW( UbException(UB_EXARGS,"Can not open check point file \"" + filename + "\""));
+   boost::archive::text_iarchive ia(file);
+   ia.register_type<Grid3D>();
+   ia >> grid; 
+
+   int psize;
+   ia >> psize;
+
+   ia.register_type<PostprocessorPtr>();
+   for (int i = 0; i < psize; i++)
+   {
+      PostprocessorPtr pp;
+      ia >> pp;
+      pp->reconnect(grid);
+      postprocessors.push_back(pp);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::saveBinArchive( std::string filename )
+{
+   //impotent for binary archive add std::ios::binary
+   std::ofstream file(filename.c_str(), std::ios::binary); 
+   if(!file)
+   { 
+      file.clear(); 
+      std::string path = UbSystem::getPathFromString(filename);
+      if(path.size()>0){ UbSystem::makeDirectory(path); file.open(filename.c_str());}
+      if(!file) throw UbException(UB_EXARGS,"couldn't open file "+filename);
+   }
+   boost::archive::binary_oarchive oa(file);
+   oa.register_type<Grid3D>();
+   oa << grid;
+
+   int psize = (int)postprocessors.size(); 
+   oa << psize;
+
+   oa.register_type<PostprocessorPtr>();
+   BOOST_FOREACH(PostprocessorPtr pp, postprocessors)
+   {
+      oa << pp;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::loadBinArchive( std::string filename )
+{
+   //impotent for binary archive add std::ios::binary
+   std::ifstream file(filename.c_str(), std::ios::binary); 
+   if (!file.is_open()) UB_THROW( UbException(UB_EXARGS,"Can not open check point file \"" + filename + "\""));
+   boost::archive::binary_iarchive ia(file);
+   ia.register_type<Grid3D>();
+   ia >> grid;
+
+   int psize;
+   ia >> psize;
+
+   ia.register_type<PostprocessorPtr>();
+   for (int i = 0; i < psize; i++)
+   {
+      PostprocessorPtr pp;
+      ia >> pp;
+      pp->reconnect(grid);
+      postprocessors.push_back(pp);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::writeMetafile(int step )
+{
+   UbFileOutputASCII out(metafile);
+   out.writeInteger(step);
+}
+//////////////////////////////////////////////////////////////////////////
+int RestartPostprocessor::readMetafile()
+{
+   UbFileInputASCII in(metafile);
+   return in.readInteger();
+}
+//////////////////////////////////////////////////////////////////////////
+void RestartPostprocessor::checkMetafile()
+{
+   std::ifstream file(metafile.c_str()); 
+   if (!file.is_open()) 
+   {
+      writeMetafile(0);
+      return;
+   }
+   file.close();
+}
+
+
+
diff --git a/source/VirtualFluidsCore/CoProcessors/RestartPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/RestartPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..5db82f0947e366467c584c096e4ac0e995d450ac
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/RestartPostprocessor.h
@@ -0,0 +1,51 @@
+#ifndef Restarter_H
+#define Restarter_H
+
+#include "Postprocessor.h"
+#include "Grid3DVisitor.h"
+#include "Block3DVisitor.h"
+#include "Communicator.h"
+
+#include <boost/shared_ptr.hpp>
+class RestartPostprocessor;
+typedef boost::shared_ptr<RestartPostprocessor> RestartPostprocessorPtr;
+
+class RestartPostprocessor : public Postprocessor
+{
+public:
+   enum ArchiveType {TXT, BINARY};
+public:
+   RestartPostprocessor(Grid3DPtr& grid, UbSchedulerPtr s, CommunicatorPtr comm, const std::string& path, ArchiveType typetype = BINARY);
+   RestartPostprocessor(Grid3DPtr& grid, UbSchedulerPtr s, CommunicatorPtr comm, const std::string& path, int restartStep, ArchiveType typetype = BINARY);
+   ~RestartPostprocessor();
+   void update(double step);
+   void addPostprocessor(PostprocessorPtr p);
+   PostprocessorPtr getPostprocessor(int index);
+   std::vector<PostprocessorPtr> getPostprocessors();
+   void addGridVisitor(Grid3DVisitorPtr v);
+   void addBlockVisitor(Block3DVisitorPtr v);
+   void doCheckPoint(int step);
+   Grid3DPtr restart();
+protected:
+   void acceptGridVisitors();
+   void acceptBlockVisitors();
+   void saveTxtArchive(std::string filename);
+   void loadTxtArchive(std::string filename);
+   void saveBinArchive(std::string filename);
+   void loadBinArchive(std::string filename);
+   void writeMetafile(int step);
+   int readMetafile();
+   void checkMetafile();
+private:
+   std::vector<PostprocessorPtr> postprocessors;
+   std::vector<Grid3DVisitorPtr> gridVisitors;
+   std::vector<Block3DVisitorPtr> blockVisitors;
+   Grid3DPtr grid;
+   std::string path;
+   ArchiveType archiveType;
+   CommunicatorPtr comm;
+   int restartStep;
+   std::string metafile;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/CoProcessors/TimeAveragedValuesPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/TimeAveragedValuesPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..27ca8252df0fb6cf66bc934bb1436f46bf9b9468
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/TimeAveragedValuesPostprocessor.cpp
@@ -0,0 +1,512 @@
+#include "TimeAveragedValuesPostprocessor.h"
+#include "LBMKernel3D.h"
+#include "SimulationParameters.h"
+#include "D3Q27ETBCProcessor.h"
+#include <vector>
+#include <sstream>
+#include <string>
+#include <iostream>
+#include <boost/foreach.hpp>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/utilities/UbMath.h"
+
+using namespace std;
+
+TimeAveragedValuesPostprocessor::TimeAveragedValuesPostprocessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+TimeAveragedValuesPostprocessor::TimeAveragedValuesPostprocessor(Grid3DPtr grid, const std::string& path, WbWriter* const writer,
+   UbSchedulerPtr s, int options)
+   : Postprocessor(grid, s),
+   path(path),
+   writer(writer),
+   options(options)
+{
+   gridRank  = grid->getRank();
+   minInitLevel = this->grid->getCoarsestInitializedLevel();
+   maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   blockVector.resize(maxInitLevel+1);
+
+   for (int level = minInitLevel; level<=maxInitLevel; level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+
+      if (blockVector[level].size() > 0)
+         compressible = blockVector[level][0]->getKernel()->getCompressible();
+
+      double begin = s->getMinBegin();
+      double gridTimeStep = grid->getTimeStep();
+
+      if (gridTimeStep == begin || gridTimeStep == 0)
+      {
+         BOOST_FOREACH(Block3DPtr block, blockVector[level])
+         {
+            UbTupleInt3 nx = grid->getBlockNX();
+            if ((options&Velocity) == Velocity)
+            {
+               AverageVelocityArray3DPtr av = AverageVelocityArray3DPtr(new AverageVelocityArray3D(3, val<1>(nx)+1, val<2>(nx)+1, val<3>(nx)+1, 0.0));
+               block->getKernel()->getDataSet()->setAverageVelocity(av);
+            }
+
+            if ((options&Fluctuations) == Fluctuations)
+            {
+               AverageFluctuationsArray3DPtr af = AverageFluctuationsArray3DPtr(new AverageFluctuationsArray3D(6, val<1>(nx)+1, val<2>(nx)+1, val<3>(nx)+1, 0.0));
+               block->getKernel()->getDataSet()->setAverageFluctuations(af);
+            }
+
+            if ((options&Triplecorrelations) == Triplecorrelations)
+            {
+               AverageTriplecorrelationsArray3DPtr at = AverageTriplecorrelationsArray3DPtr(new AverageTriplecorrelationsArray3D(10, val<1>(nx)+1, val<2>(nx)+1, val<3>(nx)+1, 0.0));
+               block->getKernel()->getDataSet()->setAverageTriplecorrelations(at);
+            }
+
+         }
+      }
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeAveragedValuesPostprocessor::update(double step)
+{
+   if (scheduler->isDue(step))
+   {
+      calculateSubtotal();
+   }
+
+   if (step == scheduler->getMaxEnd())
+   {
+      calculateAverageValues(scheduler->getMaxEnd() - scheduler->getMinBegin());
+      collectPostprocessData(step);
+      clearData();
+   }
+
+   UBLOG(logDEBUG3, "AverageValues2Postprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeAveragedValuesPostprocessor::collectPostprocessData(double step)
+{
+   int istep = int(step);
+
+   for (int level = minInitLevel; level<=maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         if (block)
+         {
+            addPostprocessData(block);
+         }
+      }
+   }
+
+   string pfilePath, partPath, subfolder, cfilePath;
+   subfolder = "tav"+UbSystem::toString(istep);
+   pfilePath =  path+"/tav/"+subfolder;
+   partPath = pfilePath+"/tav"+UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep);
+
+   string partName = writer->writeOctsWithNodeData(partPath, nodes, cells, datanames, data);
+   size_t found=partName.find_last_of("/");
+   string piece = partName.substr(found+1);
+   piece = subfolder + "/" + piece;
+
+   vector<string> cellDataNames;
+   CommunicatorPtr comm = Communicator::getInstance();
+   vector<string> pieces = comm->gather(piece);
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(pfilePath, pieces, datanames, cellDataNames);
+      UBLOG(logINFO, "TimeAveragedValuesPostprocessor step: " << istep);
+   }
+
+   clearData();
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeAveragedValuesPostprocessor::clearData()
+{
+   nodes.clear();
+   cells.clear();
+   datanames.clear();
+   data.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeAveragedValuesPostprocessor::addPostprocessData(const Block3DPtr block)
+{
+   UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+   UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+   double         dx           = grid->getDeltaX(block);
+
+   //Diese Daten werden geschrieben:
+   datanames.resize(0);
+
+   if ((options&Velocity) == Velocity)
+   {
+      datanames.push_back("taVx");
+      datanames.push_back("taVy");
+      datanames.push_back("taVz");
+   }
+
+   if ((options&Fluctuations) == Fluctuations)
+   {
+      datanames.push_back("taVxx");
+      datanames.push_back("taVyy");
+      datanames.push_back("taVzz");
+      datanames.push_back("taVxy");
+      datanames.push_back("taVxz");
+      datanames.push_back("taVyz");
+   }
+
+   if ((options&Triplecorrelations) == Triplecorrelations)
+   {
+      datanames.push_back("taVxxx");
+      datanames.push_back("taVxxy");
+      datanames.push_back("taVxxz");
+      datanames.push_back("taVyyy");
+      datanames.push_back("taVyyx");
+      datanames.push_back("taVyyz");
+      datanames.push_back("taVzzz");
+      datanames.push_back("taVzzx");
+      datanames.push_back("taVzzy");
+      datanames.push_back("taVxyz");
+   }
+
+   
+   //datanames.push_back("AvP");
+   //datanames.push_back("AvPrms");
+
+
+   data.resize(datanames.size());
+
+   LBMKernel3DPtr kernel = block->getKernel();
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+   AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageVelocity();
+   AverageValuesArray3DPtr af = kernel->getDataSet()->getAverageFluctuations();
+   AverageValuesArray3DPtr at = kernel->getDataSet()->getAverageTriplecorrelations();
+   //int ghostLayerWidth = kernel->getGhostLayerWidth();
+
+   //knotennummerierung faengt immer bei 0 an!
+   int SWB, SEB, NEB, NWB, SWT, SET, NET, NWT;
+
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int maxX1 = int(distributions->getNX1());
+   int maxX2 = int(distributions->getNX2());
+   int maxX3 = int(distributions->getNX3());
+
+   //nummern vergeben und node vector erstellen + daten sammeln
+   CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3, -1);
+
+   maxX1 -= 2;
+   maxX2 -= 2;
+   maxX3 -= 2;
+
+   //D3Q27BoundaryConditionPtr bcPtr;
+
+   int nr = (int)nodes.size();
+
+   for (int ix3=minX3; ix3<=maxX3; ix3++)
+   {
+      for (int ix2=minX2; ix2<=maxX2; ix2++)
+      {
+         for (int ix1=minX1; ix1<=maxX1; ix1++)
+         {
+            if (!bcArray.isUndefined(ix1, ix2, ix3) && !bcArray.isSolid(ix1, ix2, ix3))
+            {
+               int index = 0;
+               nodeNumbers(ix1, ix2, ix3) = nr++;
+               nodes.push_back(makeUbTuple(float(val<1>(org) -val<1>(nodeOffset) +ix1*dx),
+                  float(val<2>(org) -val<2>(nodeOffset) +ix2*dx),
+                  float(val<3>(org) -val<3>(nodeOffset) +ix3*dx)));
+
+               if ((options&Velocity) == Velocity)
+               {
+                  data[index++].push_back((*av)(Vx, ix1, ix2, ix3));
+                  data[index++].push_back((*av)(Vy, ix1, ix2, ix3));
+                  data[index++].push_back((*av)(Vz, ix1, ix2, ix3));
+               }
+
+               if ((options&Fluctuations) == Fluctuations)
+               {
+                  data[index++].push_back((*af)(Vxx, ix1, ix2, ix3));
+                  data[index++].push_back((*af)(Vyy, ix1, ix2, ix3));
+                  data[index++].push_back((*af)(Vzz, ix1, ix2, ix3));
+                  data[index++].push_back((*af)(Vxy, ix1, ix2, ix3));
+                  data[index++].push_back((*af)(Vxz, ix1, ix2, ix3));
+                  data[index++].push_back((*af)(Vyz, ix1, ix2, ix3));
+               }
+
+               if ((options&Triplecorrelations) == Triplecorrelations)
+               {
+                  data[index++].push_back((*at)(Vxxx, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vxxy, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vxxz, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vyyy, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vyyx, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vyyz, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vzzz, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vzzx, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vzzy, ix1, ix2, ix3));
+                  data[index++].push_back((*at)(Vxyz, ix1, ix2, ix3));
+               }
+
+               //LBMReal vp=(*av)(P, ix1, ix2, ix3);
+               //LBMReal vprms=(*av)(Prms, ix1, ix2, ix3);
+
+            }
+         }
+      }
+   }
+
+   maxX1 -= 1;
+   maxX2 -= 1;
+   maxX3 -= 1;
+
+   //cell vector erstellen
+   for (int ix3=minX3; ix3<=maxX3; ix3++)
+   {
+      for (int ix2=minX2; ix2<=maxX2; ix2++)
+      {
+         for (int ix1=minX1; ix1<=maxX1; ix1++)
+         {
+            if ((SWB=nodeNumbers(ix1, ix2, ix3)) >= 0
+               && (SEB=nodeNumbers(ix1+1, ix2, ix3)) >= 0
+               && (NEB=nodeNumbers(ix1+1, ix2+1, ix3)) >= 0
+               && (NWB=nodeNumbers(ix1, ix2+1, ix3)) >= 0
+               && (SWT=nodeNumbers(ix1, ix2, ix3+1)) >= 0
+               && (SET=nodeNumbers(ix1+1, ix2, ix3+1)) >= 0
+               && (NET=nodeNumbers(ix1+1, ix2+1, ix3+1)) >= 0
+               && (NWT=nodeNumbers(ix1, ix2+1, ix3+1)) >= 0)
+            {
+               cells.push_back(makeUbTuple(SWB, SEB, NEB, NWB, SWT, SET, NET, NWT));
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeAveragedValuesPostprocessor::calculateAverageValues(double timeSteps)
+{
+   for (int level = minInitLevel; level<=maxInitLevel; level++)
+   {
+      int i;
+//#ifdef _OPENMP
+//   #pragma omp parallel for 
+//#endif
+      //BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      for (i = 0; i < blockVector[level].size(); i++)
+      {
+         Block3DPtr block = blockVector[level][i];
+         if (block)
+         {
+            LBMKernel3DPtr kernel = block->getKernel();
+            BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+            DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+            AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageVelocity();
+            AverageValuesArray3DPtr af = kernel->getDataSet()->getAverageFluctuations();
+            AverageValuesArray3DPtr at = kernel->getDataSet()->getAverageTriplecorrelations();
+
+            int minX1 = 0;
+            int minX2 = 0;
+            int minX3 = 0;
+
+            int maxX1 = int(distributions->getNX1());
+            int maxX2 = int(distributions->getNX2());
+            int maxX3 = int(distributions->getNX3());
+
+            maxX1 -= 2;
+            maxX2 -= 2;
+            maxX3 -= 2;
+
+            LBMReal ux, uy, uz, uxx, uzz, uyy, uxy, uxz, uyz;
+
+            for (int ix3=minX3; ix3<=maxX3; ix3++)
+            {
+               for (int ix2=minX2; ix2<=maxX2; ix2++)
+               {
+                  for (int ix1=minX1; ix1<=maxX1; ix1++)
+                  {
+                     if (!bcArray.isUndefined(ix1, ix2, ix3) && !bcArray.isSolid(ix1, ix2, ix3))
+                     {
+                        //////////////////////////////////////////////////////////////////////////
+                        //compute average values
+                        //////////////////////////////////////////////////////////////////////////
+
+                        //mean velocity
+                        if ((options&Velocity) == Velocity)
+                        {
+                           ux = (*av)(Vx, ix1, ix2, ix3)/timeSteps;
+                           uy = (*av)(Vy, ix1, ix2, ix3)/timeSteps;
+                           uz = (*av)(Vz, ix1, ix2, ix3)/timeSteps;
+
+                           (*av)(Vx, ix1, ix2, ix3) = ux;
+                           (*av)(Vy, ix1, ix2, ix3) = uy;
+                           (*av)(Vz, ix1, ix2, ix3) = uz;
+                        }
+
+                        //fluctuations
+                        if ((options&Fluctuations) == Fluctuations)
+                        {
+                           uxx = (*af)(Vxx, ix1, ix2, ix3)/timeSteps;
+                           uyy = (*af)(Vyy, ix1, ix2, ix3)/timeSteps;
+                           uzz = (*af)(Vzz, ix1, ix2, ix3)/timeSteps;
+                           uxy = (*af)(Vxy, ix1, ix2, ix3)/timeSteps;
+                           uxz = (*af)(Vxz, ix1, ix2, ix3)/timeSteps;
+                           uyz = (*af)(Vyz, ix1, ix2, ix3)/timeSteps;
+
+                           (*af)(Vxx, ix1, ix2, ix3) = uxx - ux*ux;
+                           (*af)(Vyy, ix1, ix2, ix3) = uyy - uy*uy;
+                           (*af)(Vzz, ix1, ix2, ix3) = uzz - uz*uz;
+                           (*af)(Vxy, ix1, ix2, ix3) = uxy - ux*uy;
+                           (*af)(Vxz, ix1, ix2, ix3) = uxz - ux*uz;
+                           (*af)(Vyz, ix1, ix2, ix3) = uyz - uy*uz;
+                        }
+
+                        if ((options&Triplecorrelations) == Triplecorrelations)
+                        {
+                           //triple-correlations
+                           (*at)(Vxxx, ix1, ix2, ix3) = (*at)(Vxxx, ix1, ix2, ix3)/timeSteps - 3*uxx*ux + 2*ux*ux*ux;
+                           (*at)(Vxxy, ix1, ix2, ix3) = (*at)(Vxxy, ix1, ix2, ix3)/timeSteps - 2*uxy*ux - uxx*uy + 2*ux*ux*uy;
+                           (*at)(Vxxz, ix1, ix2, ix3) = (*at)(Vxxz, ix1, ix2, ix3)/timeSteps - 2*uxz*ux - uxx*uz + 2*ux*ux*uz;
+                           (*at)(Vyyy, ix1, ix2, ix3) = (*at)(Vyyy, ix1, ix2, ix3)/timeSteps - 3*uyy*uy + 2*uy*uy*uy;
+                           (*at)(Vyyx, ix1, ix2, ix3) = (*at)(Vyyx, ix1, ix2, ix3)/timeSteps - 2*uxy*uy - uyy*ux + 2*uy*uy*ux;
+                           (*at)(Vyyz, ix1, ix2, ix3) = (*at)(Vyyz, ix1, ix2, ix3)/timeSteps - 2*uyz*uy - uyy*uz + 2*uy*uy*uz;
+                           (*at)(Vzzz, ix1, ix2, ix3) = (*at)(Vzzz, ix1, ix2, ix3)/timeSteps - 3*uzz*uz + 2*uz*uz*uz;
+                           (*at)(Vzzx, ix1, ix2, ix3) = (*at)(Vzzx, ix1, ix2, ix3)/timeSteps - 2*uxz*uz - uzz*ux + 2*uz*uz*ux;
+                           (*at)(Vzzy, ix1, ix2, ix3) = (*at)(Vzzy, ix1, ix2, ix3)/timeSteps - 2*uyz*uz - uzz*uy + 2*uz*uz*uy;
+                           (*at)(Vxyz, ix1, ix2, ix3) = (*at)(Vxyz, ix1, ix2, ix3)/timeSteps - uxy*uz - uxz*uy - uyz*ux + 2*ux*uy*uz;
+                        }
+                        //////////////////////////////////////////////////////////////////////////
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeAveragedValuesPostprocessor::calculateSubtotal()
+{
+
+   using namespace D3Q27System;
+
+   //Funktionszeiger
+   calcMacros = NULL;
+   if (compressible)
+   {
+      calcMacros = &calcCompMacroscopicValues;
+   }
+   else
+   {
+      calcMacros = &calcIncompMacroscopicValues;
+   }
+
+   LBMReal f[27];
+#ifdef _OPENMP
+#pragma omp parallel private (f)
+#endif
+  {
+      for (int level = minInitLevel; level<=maxInitLevel; level++)
+      {
+         int i;
+#ifdef _OPENMP
+#pragma omp for schedule(dynamic)
+#endif
+         //BOOST_FOREACH(Block3DPtr block, blockVector[level])
+         for (i = 0; i < blockVector[level].size(); i++)
+         {
+            Block3DPtr block = blockVector[level][i];
+            if (block)
+            {
+               LBMKernel3DPtr kernel = block->getKernel();
+               BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+               DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+               AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageVelocity();
+               AverageValuesArray3DPtr af = kernel->getDataSet()->getAverageFluctuations();
+               AverageValuesArray3DPtr at = kernel->getDataSet()->getAverageTriplecorrelations();
+
+               int minX1 = 0;
+               int minX2 = 0;
+               int minX3 = 0;
+
+               int maxX1 = int(distributions->getNX1());
+               int maxX2 = int(distributions->getNX2());
+               int maxX3 = int(distributions->getNX3());
+
+               maxX1 -= 2;
+               maxX2 -= 2;
+               maxX3 -= 2;
+
+               for (int ix3=minX3; ix3<=maxX3; ix3++)
+               {
+                  for (int ix2=minX2; ix2<=maxX2; ix2++)
+                  {
+                     for (int ix1=minX1; ix1<=maxX1; ix1++)
+                     {
+                        if (!bcArray.isUndefined(ix1, ix2, ix3) && !bcArray.isSolid(ix1, ix2, ix3))
+                        {
+                           //////////////////////////////////////////////////////////////////////////
+                           //read distribution
+                           ////////////////////////////////////////////////////////////////////////////
+                           distributions->getDistribution(f, ix1, ix2, ix3);
+                           //////////////////////////////////////////////////////////////////////////
+                           //compute velocity
+                           //////////////////////////////////////////////////////////////////////////
+                           LBMReal vx, vy, vz, rho;
+                           calcMacros(f, rho, vx, vy, vz);
+                           //double press = D3Q27System::calcPress(f, rho, vx, vy, vz);
+
+                           //////////////////////////////////////////////////////////////////////////
+                           //compute subtotals
+                           //////////////////////////////////////////////////////////////////////////
+
+                           //mean velocity
+                           if ((options&Velocity) == Velocity)
+                           {
+                              (*av)(Vx, ix1, ix2, ix3) = (*av)(Vx, ix1, ix2, ix3) + vx;
+                              (*av)(Vy, ix1, ix2, ix3) = (*av)(Vy, ix1, ix2, ix3) + vy;
+                              (*av)(Vz, ix1, ix2, ix3) = (*av)(Vz, ix1, ix2, ix3) + vz;
+                           }
+
+                           //fluctuations
+                           if ((options&Fluctuations) == Fluctuations)
+                           {
+                              (*af)(Vxx, ix1, ix2, ix3) = (*af)(Vxx, ix1, ix2, ix3) + vx*vx;
+                              (*af)(Vyy, ix1, ix2, ix3) = (*af)(Vyy, ix1, ix2, ix3) + vy*vy;
+                              (*af)(Vzz, ix1, ix2, ix3) = (*af)(Vzz, ix1, ix2, ix3) + vz*vz;
+                              (*af)(Vxy, ix1, ix2, ix3) = (*af)(Vxy, ix1, ix2, ix3) + vx*vy;
+                              (*af)(Vxz, ix1, ix2, ix3) = (*af)(Vxz, ix1, ix2, ix3) + vx*vz;
+                              (*af)(Vyz, ix1, ix2, ix3) = (*af)(Vyz, ix1, ix2, ix3) + vy*vz;
+                           }
+
+                           //triple-correlations
+                           if ((options&Triplecorrelations) == Triplecorrelations)
+                           {
+                              (*at)(Vxxx, ix1, ix2, ix3) = (*at)(Vxxx, ix1, ix2, ix3) + vx*vx*vx;
+                              (*at)(Vxxy, ix1, ix2, ix3) = (*at)(Vxxy, ix1, ix2, ix3) + vx*vx*vy;
+                              (*at)(Vxxz, ix1, ix2, ix3) = (*at)(Vxxz, ix1, ix2, ix3) + vx*vx*vz;
+                              (*at)(Vyyy, ix1, ix2, ix3) = (*at)(Vyyy, ix1, ix2, ix3) + vy*vy*vy;
+                              (*at)(Vyyx, ix1, ix2, ix3) = (*at)(Vyyx, ix1, ix2, ix3) + vy*vy*vx;
+                              (*at)(Vyyz, ix1, ix2, ix3) = (*at)(Vyyz, ix1, ix2, ix3) + vy*vy*vz;
+                              (*at)(Vzzz, ix1, ix2, ix3) = (*at)(Vzzz, ix1, ix2, ix3) + vz*vz*vz;
+                              (*at)(Vzzx, ix1, ix2, ix3) = (*at)(Vzzx, ix1, ix2, ix3) + vz*vz*vx;
+                              (*at)(Vzzy, ix1, ix2, ix3) = (*at)(Vzzy, ix1, ix2, ix3) + vz*vz*vy;
+                              (*at)(Vxyz, ix1, ix2, ix3) = (*at)(Vxyz, ix1, ix2, ix3) + vx*vy*vz;
+                           }
+                           //////////////////////////////////////////////////////////////////////////
+                        }
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+
+
diff --git a/source/VirtualFluidsCore/CoProcessors/TimeAveragedValuesPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/TimeAveragedValuesPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..221a96b492adc774374926485fc55e2cf598471f
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/TimeAveragedValuesPostprocessor.h
@@ -0,0 +1,100 @@
+#ifndef TimeAveragedValuesPostprocessor_H
+#define TimeAveragedValuesPostprocessor_H
+
+#include "Postprocessor.h"
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "WbWriter.h"
+
+#include <boost/shared_ptr.hpp>
+class TimeAveragedValuesPostprocessor;
+typedef boost::shared_ptr<TimeAveragedValuesPostprocessor> AverageValues2PostprocessorPtr;
+
+//! \brief  Computes the time averaged mean velocity and RMS values and writes to parallel .vtk
+//! \details writes at given time intervals specified in scheduler (s), does averaging according to scheduler (Avs) and resets according to scheduler (rs).  <br>
+//!  Computes  the time averaged mean velocity  \f$ u_{mean}=\frac{1}{N}\sum\limits_{i=1}^n u_{i} \f$  and RMS of fluctuations. You need to calculate a square root before plotting RMS. <br>
+//           
+//! \author  Sonja Uphoff, Kostyantyn Kucher 
+// \f$ u_{mean}=\frac{1}{N}\sum\limits_{i=1}^n u_{i} \f$
+class TimeAveragedValuesPostprocessor : public Postprocessor
+{
+public:
+   enum Options
+   {
+      Velocity = 1,
+      Fluctuations = 2,
+      Triplecorrelations = 4
+   };
+public:
+   TimeAveragedValuesPostprocessor();
+   TimeAveragedValuesPostprocessor(Grid3DPtr grid, const std::string& path, WbWriter* const writer,
+      UbSchedulerPtr s, int options);
+   //! Make update
+   void update(double step);
+   //! Resets averaged velocity and RMS-values according to ResetSceduler
+   void reset(double step);
+protected:
+   //! Prepare data and write in .vtk file
+   void collectPostprocessData(double step);
+   //! prepare data
+   void addPostprocessData(const Block3DPtr block);
+   void clearData();
+   //! Computes average values of velocity , fluctuations and triple correlations 
+   void calculateAverageValues(double timeStep);
+   //! Computes subtotal of velocity , fluctuations and triple correlations
+   void calculateSubtotal();
+
+private:
+   std::vector<UbTupleFloat3> nodes;
+   std::vector<UbTupleInt8> cells;
+   std::vector<std::string> datanames;
+   std::vector<std::vector<double> > data;
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   int minInitLevel; //min init level
+   int maxInitLevel;
+   int gridRank;
+   int resetStepRMS;
+   int resetStepMeans;
+   double averageInterval;
+   std::string path;
+   WbWriter* writer;
+   bool restart, compressible;
+   UbSchedulerPtr averageScheduler;  //additional scheduler to averaging after a given interval
+   UbSchedulerPtr resetSchedulerRMS;  //additional scheduler to restart averaging after a given interval
+   UbSchedulerPtr resetSchedulerMeans;  //additional scheduler to restart averaging after a given interval
+   //labels for the different components, e.g. AvVxx for time averaged RMS: 1/n SUM((U-Umean)^2)
+   //you need to calculate a square root before plotting RMS
+   enum Velocity { Vx, Vy, Vz };
+   enum Fluctuations { Vxx, Vyy, Vzz, Vxy, Vxz, Vyz };
+   enum Triplecorrelations { Vxxx, Vxxy, Vxxz, Vyyy, Vyyx, Vyyz, Vzzz, Vzzx, Vzzy, Vxyz };
+   //enum Pressure { P, Prms };
+
+   int options;
+
+   typedef void(*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/, LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   CalcMacrosFct calcMacros;
+
+   //friend class boost::serialization::access;
+   //template<class Archive>
+   //void serialize(Archive & ar, const unsigned int version)
+   //{
+   //   ar & boost::serialization::base_object<Postprocessor>(*this);
+   //   ar & path;
+   //   ar & blockVector;
+   //   ar & minInitLevel;
+   //   ar & maxInitLevel;
+   //   ar & gridRank;
+   //   ar & writer;
+   //   ar & resetStepRMS;
+   //   ar & resetStepMeans;
+   //   ar & AverageInterval;
+   //   ar & averageScheduler;
+   //   ar & resetSchedulerRMS;
+   //   ar & resetSchedulerMeans;
+   //   ar & compressible;
+   //}
+};
+#endif
diff --git a/source/VirtualFluidsCore/CoProcessors/TimeDependentBCPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/TimeDependentBCPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..304d5799c63eadd223c88e29a870e828916ba846
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/TimeDependentBCPostprocessor.cpp
@@ -0,0 +1,30 @@
+#include "TimeDependentBCPostprocessor.h"
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+TimeDependentBCPostprocessor::TimeDependentBCPostprocessor(Grid3DPtr grid) : Postprocessor(grid,  UbSchedulerPtr(new UbScheduler(1)))
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+TimeDependentBCPostprocessor::~TimeDependentBCPostprocessor() 
+{
+	
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeDependentBCPostprocessor::update(double step)
+{
+   BOOST_FOREACH(Interactor3DPtr inter, interactors)
+      inter->updateInteractor( step );
+   UBLOG(logDEBUG3, "TimeDependentBCPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeDependentBCPostprocessor::addInteractor( Interactor3DPtr interactor )
+{
+   interactors.push_back(interactor);
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+
diff --git a/source/VirtualFluidsCore/CoProcessors/TimeDependentBCPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/TimeDependentBCPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..e277c7642b8fb8baae80391ad0ba0079c592af6d
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/TimeDependentBCPostprocessor.h
@@ -0,0 +1,27 @@
+#ifndef TimeDependentBCPOSTPROCESSOR_H
+#define TimeDependentBCPOSTPROCESSOR_H
+
+#include "Postprocessor.h"
+#include "Interactor3D.h"
+
+#include <boost/shared_ptr.hpp>
+class TimeDependentBCPostprocessor;
+typedef boost::shared_ptr<TimeDependentBCPostprocessor> TimeDependentBCPostprocessorPtr;
+
+//! \brief The class update interactors depend of time step. 
+//! \details TimeDependentBCPostprocessor update every time step information in BCAdapters throw Interactors
+//! \author Sonja Uphoff, Kostyantyn Kucher
+class TimeDependentBCPostprocessor: public Postprocessor {
+public:
+	TimeDependentBCPostprocessor(Grid3DPtr grid);
+	virtual ~TimeDependentBCPostprocessor();
+	void update(double step);
+   //! add interactors to Postprocessor
+   void addInteractor(Interactor3DPtr interactor);
+protected:
+private:
+   std::vector<Interactor3DPtr> interactors;
+};
+
+
+#endif /* TimeDependentBCPOSTPROCESSOR_H */
diff --git a/source/VirtualFluidsCore/CoProcessors/TimeseriesPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/TimeseriesPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5e91285a3bbec0a3509d116fa16ff4d73f05661b
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/TimeseriesPostprocessor.cpp
@@ -0,0 +1,84 @@
+/*
+*  TimeseriesWriterPostprocessor.h
+*
+*  Created on: 08.05.2013
+*  Author: uphoff
+*/
+
+#include "TimeseriesPostprocessor.h"
+
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+TimeseriesPostprocessor::TimeseriesPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+                                                             D3Q27IntegrateValuesHelperPtr h1,
+                                                             const std::string& path, CommunicatorPtr comm)
+                                                             : Postprocessor(grid, s),                                                
+                                                               h1(h1),
+                                                               path(path),
+                                                               comm(comm)
+{
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      std::ofstream ostr;
+      //fname = path+"/timeseries/timeseries"+UbSystem::toString(grid->getTimeStep())+".csv";
+      fname = path+".csv";
+      UBLOG(logINFO, "TimeseriesWriterPostprocessor::fname:" << fname);
+      ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);
+      if(!ostr)
+      { 
+         ostr.clear();
+         string path = UbSystem::getPathFromString(fname);
+         if (path.size()>0) { UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app); }
+         if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+      }
+      ostr << "step;rho;vx;vy;vz;volume\n";
+      ostr.close();
+      UBLOG(logINFO, "TimeseriesWriterPostprocessor::Constructor:end");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+TimeseriesPostprocessor::~TimeseriesPostprocessor() 
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeseriesPostprocessor::update(double step)
+{
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+}
+//////////////////////////////////////////////////////////////////////////
+void TimeseriesPostprocessor::collectPostprocessData(double step)
+{
+   h1->calculateMQ();
+
+   UBLOG(logDEBUG3, "TimeseriesWriterPostprocessor::update:" << step);
+
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      int istep = static_cast<int>(step);
+      std::ofstream ostr;
+      double cellsVolume = h1->getCellsVolume();
+
+      double rho=(h1->getRho())/cellsVolume;
+      double vx= (h1->getVx1())/cellsVolume;
+      double vy= (h1->getVx2())/cellsVolume;
+      double vz= (h1->getVx3())/cellsVolume;
+      double volume = cellsVolume;
+
+      ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);
+      if(!ostr)
+      { 
+         ostr.clear();
+         string path = UbSystem::getPathFromString(fname);
+         if(path.size()>0){ UbSystem::makeDirectory(path); ostr.open(fname.c_str(), std::ios_base::out | std::ios_base::app);}
+         if(!ostr) throw UbException(UB_EXARGS,"couldn't open file "+fname);
+      }
+
+      ostr << istep << ";" << rho <<";" << vx << ";" << vy << ";" << vz << ";" << volume << "\n";
+      ostr.close();
+   }
+}
diff --git a/source/VirtualFluidsCore/CoProcessors/TimeseriesPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/TimeseriesPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..9735ab7de153f154b81854a9df47b5208b6d734f
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/TimeseriesPostprocessor.h
@@ -0,0 +1,45 @@
+/*
+ *  TimeseriesPostprocessor.h
+ *
+ *  Created on: 08.05.2013
+ *  Author: uphoff
+ */
+
+#ifndef TimeseriesPOSTPROCESSOR_H
+#define TimeseriesPOSTPROCESSOR_H
+
+#include "Postprocessor.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+
+#include <boost/shared_ptr.hpp>
+
+class TimeseriesPostprocessor;
+typedef boost::shared_ptr<TimeseriesPostprocessor> TimeseriesWriterPostprocessorPtr;
+
+//! \brief     Writes timeseries of density and velocity to a file.
+//! \details   Uses Integrate values helper, scheduler must be set in testcase.
+//! \author    Sonja Uphoff
+//! \date      May 2013
+
+class TimeseriesPostprocessor: public Postprocessor {
+public:
+	TimeseriesPostprocessor(Grid3DPtr grid, UbSchedulerPtr s,
+                                   D3Q27IntegrateValuesHelperPtr h1,
+                                   const std::string& path, CommunicatorPtr comm);
+	virtual ~TimeseriesPostprocessor();
+	//! calls collect PostprocessData.
+   void update(double step); 
+protected:
+   //! object that can compute spacial average values in 3D-subdomain.
+	D3Q27IntegrateValuesHelperPtr h1;  
+	void collectPostprocessData(double step);  
+   CommunicatorPtr comm;
+private:
+	std::string path; //! output filename, e.g.  pathname + "/steps/timeseries"
+   std::string fname;
+};
+
+
+#endif /* TimeseriesPOSTPROCESSOR_H */
diff --git a/source/VirtualFluidsCore/CoProcessors/TurbulenceIntensityPostprocessor.cpp b/source/VirtualFluidsCore/CoProcessors/TurbulenceIntensityPostprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f7dca2cd7b2ed663d88a2756b870744edb1daf9d
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/TurbulenceIntensityPostprocessor.cpp
@@ -0,0 +1,266 @@
+#include "TurbulenceIntensityPostprocessor.h"
+#include "LBMKernel3D.h"
+#include "SimulationParameters.h"
+#include "D3Q27ETBCProcessor.h"
+#include <vector>
+#include <string>
+#include <boost/foreach.hpp>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include "basics/utilities/UbMath.h"
+
+using namespace std;
+
+TurbulenceIntensityPostprocessor::TurbulenceIntensityPostprocessor(Grid3DPtr grid, const std::string& path, 
+                                                                                       WbWriter* const writer,
+                                                                                       UbSchedulerPtr s, CommunicatorPtr comm)
+                                                                                     : Postprocessor(grid, s),
+                                                                                       path(path),
+                                                                                       comm(comm),
+                                                                                       writer(writer)
+{
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+void TurbulenceIntensityPostprocessor::init()
+{
+   gridRank  = grid->getRank();
+   minInitLevel = this->grid->getCoarsestInitializedLevel();
+   maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   blockVector.resize(maxInitLevel+1);
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      grid->getBlocks(level, gridRank, true, blockVector[level]);
+
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         UbTupleInt3 nx = grid->getBlockNX();
+         AverageValuesArray3DPtr averageValues = AverageValuesArray3DPtr(new AverageValuesArray3D(val<1>(nx)+1, val<2>(nx)+1, val<3>(nx)+1, 4, 0.0));
+         block->getKernel()->getDataSet()->setAverageValues(averageValues);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void TurbulenceIntensityPostprocessor::update(double step)
+{
+   calculateAverageValues(int(step));
+
+   if(scheduler->isDue(step) )
+      collectPostprocessData(step);
+
+   UBLOG(logDEBUG3, "TurbulenceIntensityPostprocessor::update:" << step);
+}
+//////////////////////////////////////////////////////////////////////////
+void TurbulenceIntensityPostprocessor::collectPostprocessData(double step)
+{
+   int istep = int(step);
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         if (block)
+         {
+            addPostprocessData(block);
+         }
+      }
+   }
+
+   string partName = writer->writeOctsWithNodeData(path+ UbSystem::toString(gridRank)+ "_" + UbSystem::toString(istep),nodes,cells,datanames,data);
+   size_t found=partName.find_last_of("//");
+   string piece = partName.substr(found+1);
+
+   vector<string> cellDataNames;
+
+   vector<string> pieces = comm->gather(piece);
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      string pname = WbWriterVtkXmlASCII::getInstance()->writeParallelFile(path+"_"+UbSystem::toString(istep),pieces,datanames,cellDataNames);
+
+      vector<string> filenames;
+      filenames.push_back(pname);
+      if (step == Postprocessor::scheduler->getMinBegin())
+      {
+         WbWriterVtkXmlASCII::getInstance()->writeCollection(path+"_collection",filenames,istep,false);
+      } 
+      else
+      {
+         WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(path+"_collection",filenames,istep,false);
+      }
+      UBLOG(logINFO,"TurbulenceIntensityPostprocessor step: " << istep);
+   }
+
+   clearData();
+}
+//////////////////////////////////////////////////////////////////////////
+void TurbulenceIntensityPostprocessor::clearData()
+{
+   nodes.clear();
+   cells.clear();
+   datanames.clear();
+   data.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+void TurbulenceIntensityPostprocessor::addPostprocessData(const Block3DPtr block)
+{
+   UbTupleDouble3 org          = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+   UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+   double         dx           = grid->getDeltaX(block);
+
+   //Diese Daten werden geschrieben:
+   datanames.resize(0);
+   datanames.push_back("TI");
+
+   data.resize(datanames.size());
+
+   LBMKernel3DPtr kernel = block->getKernel();
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+   DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+   AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageValues();
+   //int ghostLayerWidth = kernel->getGhostLayerWidth();
+
+   //knotennummerierung faengt immer bei 0 an!
+   int SWB,SEB,NEB,NWB,SWT,SET,NET,NWT;
+
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int maxX1 = int(distributions->getNX1());
+   int maxX2 = int(distributions->getNX2());
+   int maxX3 = int(distributions->getNX3());
+
+   //nummern vergeben und node vector erstellen + daten sammeln
+   CbArray3D<int> nodeNumbers((int)maxX1, (int)maxX2, (int)maxX3,-1);
+   //D3Q27BoundaryConditionPtr bcPtr;
+   int nr = (int)nodes.size();
+ 
+   for(int ix3=minX3; ix3<maxX3-1; ix3++)
+   {
+      for(int ix2=minX2; ix2<maxX2-1; ix2++)
+      {
+         for(int ix1=minX1; ix1<maxX1-1; ix1++)
+         {
+            if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+            {
+               int index = 0;
+               nodeNumbers(ix1,ix2,ix3) = nr++;
+               nodes.push_back( makeUbTuple(float(val<1>(org) - val<1>(nodeOffset) + ix1*dx),
+                                            float(val<2>(org) - val<2>(nodeOffset) + ix2*dx),
+                                            float(val<3>(org) - val<3>(nodeOffset) + ix3*dx)) );
+
+               //compute turbulence intensity
+               double temp = (*av)(ix1,ix2,ix3,AvVxxyyzz)/
+                            ((*av)(ix1,ix2,ix3,AvVx)*(*av)(ix1,ix2,ix3,AvVx)+
+                             (*av)(ix1,ix2,ix3,AvVy)*(*av)(ix1,ix2,ix3,AvVy)+
+                             (*av)(ix1,ix2,ix3,AvVz)*(*av)(ix1,ix2,ix3,AvVz));
+
+               LBMReal ti = sqrt(temp);
+
+               if (UbMath::isNaN(ti)) UB_THROW( UbException(UB_EXARGS,"TI is not a number (nan or -1.#IND), sqrt(temp), where temp = "+UbSystem::toString(temp)+", AvVx = "+UbSystem::toString((*av)(ix1,ix2,ix3,AvVx))+" AvVy = "+UbSystem::toString((*av)(ix1,ix2,ix3,AvVy))+" AvVz = "+UbSystem::toString((*av)(ix1,ix2,ix3,AvVz))));
+
+               data[index++].push_back(ti);
+            }
+         }
+      }
+   }
+   //cell vector erstellen
+   for(int ix3=minX3; ix3<maxX3-1; ix3++)
+   {
+      for(int ix2=minX2; ix2<maxX2-1; ix2++)
+      {
+         for(int ix1=minX1; ix1<maxX1-1; ix1++)
+         {
+            if(   (SWB=nodeNumbers( ix1  , ix2,   ix3   )) >= 0
+               && (SEB=nodeNumbers( ix1+1, ix2,   ix3   )) >= 0
+               && (NEB=nodeNumbers( ix1+1, ix2+1, ix3   )) >= 0
+               && (NWB=nodeNumbers( ix1  , ix2+1, ix3   )) >= 0 
+               && (SWT=nodeNumbers( ix1  , ix2,   ix3+1 )) >= 0
+               && (SET=nodeNumbers( ix1+1, ix2,   ix3+1 )) >= 0
+               && (NET=nodeNumbers( ix1+1, ix2+1, ix3+1 )) >= 0
+               && (NWT=nodeNumbers( ix1  , ix2+1, ix3+1 )) >= 0                )
+            {
+               cells.push_back( makeUbTuple(SWB,SEB,NEB,NWB,SWT,SET,NET,NWT) );
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void TurbulenceIntensityPostprocessor::calculateAverageValues(double timeStep)
+{
+   using namespace D3Q27System;
+
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+   LBMReal f[27];
+   LBMReal vx, vy, vz;
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blockVector[level])
+      {
+         if (block)
+         {
+            LBMKernel3DPtr kernel = block->getKernel();
+            BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();          
+            DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions(); 
+            AverageValuesArray3DPtr av = kernel->getDataSet()->getAverageValues();
+
+            int minX1 = 0;
+            int minX2 = 0;
+            int minX3 = 0;
+
+            int maxX1 = int(distributions->getNX1());
+            int maxX2 = int(distributions->getNX2());
+            int maxX3 = int(distributions->getNX3());
+
+            for(int ix3=minX3; ix3<maxX3-1; ix3++)
+            {
+               for(int ix2=minX2; ix2<maxX2-1; ix2++)
+               {
+                  for(int ix1=minX1; ix1<maxX1-1; ix1++)
+                  {
+                     if(!bcArray.isUndefined(ix1,ix2,ix3) && !bcArray.isSolid(ix1,ix2,ix3))
+                     {
+                        //////////////////////////////////////////////////////////////////////////
+                        //read distribution
+                        ////////////////////////////////////////////////////////////////////////////
+                        distributions->getDistribution(f, ix1, ix2, ix3);
+                        //////////////////////////////////////////////////////////////////////////
+                        //compute velocity
+                        //////////////////////////////////////////////////////////////////////////
+                        vx = f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] - f[BW]
+                        + f[BE] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+                        + f[BSE] - f[BNW]; 
+
+                        vy = f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+                        - f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+                        + f[BNW]; 
+
+                        vz = f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+                        + f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+                        - f[BNW];
+                        //////////////////////////////////////////////////////////////////////////
+                        //compute average values
+                        //////////////////////////////////////////////////////////////////////////
+                        (*av)(ix1,ix2,ix3,AvVx) = ((*av)(ix1,ix2,ix3,AvVx)*timeStep + vx)/(timeStep+1.0);
+                        (*av)(ix1,ix2,ix3,AvVy) = ((*av)(ix1,ix2,ix3,AvVy)*timeStep + vy)/(timeStep+1.0);
+                        (*av)(ix1,ix2,ix3,AvVz) = ((*av)(ix1,ix2,ix3,AvVz)*timeStep + vz)/(timeStep+1.0);
+
+                        (*av)(ix1,ix2,ix3,AvVxxyyzz) = ((vx-(*av)(ix1,ix2,ix3,AvVx))*(vx-(*av)(ix1,ix2,ix3,AvVx)) +
+                                                         (vy-(*av)(ix1,ix2,ix3,AvVy))*(vy-(*av)(ix1,ix2,ix3,AvVy)) +
+                                                         (vz-(*av)(ix1,ix2,ix3,AvVz))*(vz-(*av)(ix1,ix2,ix3,AvVz)) +
+                                                         (*av)(ix1,ix2,ix3,AvVxxyyzz)*timeStep)/(timeStep+1.0);
+                        //////////////////////////////////////////////////////////////////////////
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+
diff --git a/source/VirtualFluidsCore/CoProcessors/TurbulenceIntensityPostprocessor.h b/source/VirtualFluidsCore/CoProcessors/TurbulenceIntensityPostprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..49bc290591f8b4337a7de95600603774cff9aaa8
--- /dev/null
+++ b/source/VirtualFluidsCore/CoProcessors/TurbulenceIntensityPostprocessor.h
@@ -0,0 +1,42 @@
+#ifndef TurbulenceIntensityPostprocessor_H
+#define TurbulenceIntensityPostprocessor_H
+
+#include "Postprocessor.h"
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "LBMUnitConverter.h"
+#include "Communicator.h"
+
+#include "WbWriter.h"
+
+#include <boost/shared_ptr.hpp>
+class TurbulenceIntensityPostprocessor;
+typedef boost::shared_ptr<TurbulenceIntensityPostprocessor> TurbulenceIntensityPostprocessorPtr;
+
+class TurbulenceIntensityPostprocessor : public Postprocessor
+{
+public:
+   TurbulenceIntensityPostprocessor(Grid3DPtr grid, const std::string& path, WbWriter* const writer, 
+                          UbSchedulerPtr s, CommunicatorPtr comm);
+   void update(double step);
+protected:
+   void collectPostprocessData(double step);
+   void addPostprocessData(const Block3DPtr block);
+   void clearData();
+   void calculateAverageValues(double timeStep);
+private:
+   void init();
+   std::vector<UbTupleFloat3> nodes;
+   std::vector<UbTupleInt8> cells;
+   std::vector<std::string> datanames;
+   std::vector<std::vector<double> > data; 
+   std::vector<std::vector<Block3DPtr> > blockVector;
+   int minInitLevel;
+   int maxInitLevel;
+   int gridRank;
+   std::string path;
+   WbWriter* writer;
+   CommunicatorPtr comm;
+   enum Values{AvVx = 0, AvVy = 1, AvVz = 2, AvVxxyyzz = 3};
+};
+#endif
diff --git a/source/VirtualFluidsCore/Connectors/Block3DConnector.h b/source/VirtualFluidsCore/Connectors/Block3DConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..856671f5c9d3bcc5de851df454d814fb24df278f
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/Block3DConnector.h
@@ -0,0 +1,105 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef BLOCK2DCONNECTOR_H
+#define BLOCK2DCONNECTOR_H
+
+#include <vector>
+#include <string>
+
+#include <basics/utilities/UbTuple.h>
+
+#include <boost/shared_ptr.hpp>
+
+class Block3DConnector;
+typedef boost::shared_ptr<Block3DConnector> Block3DConnectorPtr;
+
+class Block3DConnector
+{
+   //FETOL
+#ifdef VF_FETOL
+public:
+   enum TransmitterType{NONE=0, MPI=1, BOND=2};
+#endif
+public:
+   Block3DConnector() 
+      : sendDir(-1)
+      , invStep(false)
+#ifdef VF_FETOL
+      , ttype(NONE)
+#endif
+   {}
+
+   Block3DConnector(const int& sendDir) 
+      : sendDir(sendDir)
+      , invStep(false)
+#ifdef VF_FETOL
+      , ttype(NONE)
+#endif
+   {}
+
+   virtual ~Block3DConnector() {}
+
+   virtual void init()=0;
+
+   //for synchronize the send- and receive-bufferlength
+   virtual void sendTransmitterDataSize()=0;  
+   virtual void receiveTransmitterDataSize()=0;
+
+   //send operations (should be called in given order!!!)
+   virtual void prepareForSend()=0;
+   virtual void fillSendVectors()=0;
+   virtual void sendVectors()=0;
+   
+   //receive operations (should be called in given order!!!)
+   virtual void prepareForReceive()=0;
+   virtual void receiveVectors()=0;
+   virtual void distributeReceiveVectors()=0;
+
+   //info section
+   virtual bool isLocalConnector()  = 0;
+   virtual bool isRemoteConnector() = 0;
+   virtual bool isInterpolationConnectorCF() = 0;
+   virtual bool isInterpolationConnectorFC() = 0;
+
+   //grid refinement
+   virtual void setInvStep(bool step) {invStep = step;}
+   virtual int getSendDir() const { return sendDir; } 
+
+   //virtual double getSendRecieveTime() = 0;
+   
+   virtual void prepareForSendX1() = 0;
+   virtual void prepareForSendX2() = 0;
+   virtual void prepareForSendX3() = 0;
+
+   virtual void sendVectorsX1() = 0;
+   virtual void sendVectorsX2() = 0;
+   virtual void sendVectorsX3() = 0;
+
+   virtual void prepareForReceiveX1() = 0;
+   virtual void prepareForReceiveX2() = 0;
+   virtual void prepareForReceiveX3() = 0;
+
+   virtual void receiveVectorsX1() = 0;
+   virtual void receiveVectorsX2() = 0;
+   virtual void receiveVectorsX3() = 0;
+
+   //FETOL
+#ifdef VF_FETOL
+   void setTransmitterType(TransmitterType ttype) { this->ttype=ttype;}
+   TransmitterType getTransmitterType() {return ttype;}
+#endif
+
+protected:
+   int  sendDir;
+   bool invStep;
+   //FETOL 
+#ifdef VF_FETOL
+   TransmitterType ttype;
+#endif
+};
+
+#endif //BLOCK2DCONNECTOR_H
diff --git a/source/VirtualFluidsCore/Connectors/Block3DConnectorFactory.cpp b/source/VirtualFluidsCore/Connectors/Block3DConnectorFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..44fc378431cbc7effbb108c74b4e5122be453421
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/Block3DConnectorFactory.cpp
@@ -0,0 +1,50 @@
+#include "Block3DConnectorFactory.h"
+#include "D3Q27ETFullDirectConnector.h"
+#include "D3Q27ETFullVectorConnector.h"
+#include "CoarseToFineNodeSetBlock3DConnector.h"
+#include "FineToCoarseNodeSetBlock3DConnector.h"
+
+Block3DConnectorFactory::Block3DConnectorFactory()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DConnectorFactory::~Block3DConnectorFactory()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DConnectorPtr Block3DConnectorFactory::createSameLevelDirectConnector(Block3DPtr from, Block3DPtr to, int sendDir)
+{
+   return Block3DConnectorPtr(new D3Q27ETFullDirectConnector(from, to, sendDir)); 
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DConnectorPtr Block3DConnectorFactory::createSameLevelVectorConnector(Block3DPtr block,
+   VectorTransmitterPtr sender,
+   VectorTransmitterPtr receiver,
+   int sendDir)
+{
+   return Block3DConnectorPtr(new D3Q27ETFullVectorConnector(block, sender, receiver, sendDir));
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DConnectorPtr Block3DConnectorFactory::createCoarseToFineConnector(Block3DPtr block,
+   VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+   VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+   VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+   VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+   int sendDir, D3Q27InterpolationProcessorPtr iprocessor)
+{
+   return Block3DConnectorPtr (new CoarseToFineNodeSetBlock3DConnector(block,
+      sender00, receiver00, sender01, receiver01,
+      sender10, receiver10, sender11, receiver11,
+      sendDir, iprocessor));
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DConnectorPtr Block3DConnectorFactory::createFineToCoarseConnector(Block3DPtr block,
+   VectorTransmitterPtr sender,
+   VectorTransmitterPtr receiver,
+   int sendDir,
+   D3Q27InterpolationProcessorPtr iprocessor,
+   FineToCoarseBlock3DConnector::CFconnectorType connType)
+{
+   return  Block3DConnectorPtr(new FineToCoarseNodeSetBlock3DConnector(block,
+      sender, receiver, sendDir, iprocessor, connType));
+}
diff --git a/source/VirtualFluidsCore/Connectors/Block3DConnectorFactory.h b/source/VirtualFluidsCore/Connectors/Block3DConnectorFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..4117a4af866172534c30ba0e2bb0520da58b2f67
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/Block3DConnectorFactory.h
@@ -0,0 +1,41 @@
+#ifndef Block3DConnectorFactory_h__
+#define Block3DConnectorFactory_h__
+
+#include "ConnectorFactory.h"
+
+#include <boost/shared_ptr.hpp>
+class Block3DConnectorFactory;
+typedef boost::shared_ptr<Block3DConnectorFactory> Block3DConnectorFactoryPtr;
+
+class Block3DConnectorFactory : public ConnectorFactory
+{
+public:
+   Block3DConnectorFactory();
+   virtual ~Block3DConnectorFactory();
+
+   virtual Block3DConnectorPtr createSameLevelDirectConnector(Block3DPtr from, Block3DPtr to, int sendDir);
+
+   virtual Block3DConnectorPtr createSameLevelVectorConnector(Block3DPtr block,
+      VectorTransmitterPtr sender,
+      VectorTransmitterPtr receiver,
+      int sendDir);
+
+   virtual Block3DConnectorPtr createCoarseToFineConnector(Block3DPtr block,
+      VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+      VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+      VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+      VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+      int sendDir, D3Q27InterpolationProcessorPtr iprocessor);
+
+   virtual Block3DConnectorPtr createFineToCoarseConnector(Block3DPtr block,
+      VectorTransmitterPtr sender,
+      VectorTransmitterPtr receiver,
+      int sendDir,
+      D3Q27InterpolationProcessorPtr iprocessor,
+      FineToCoarseBlock3DConnector::CFconnectorType connType);
+
+private:
+
+};
+#endif // Block3DConnectorFactory_h__
+
diff --git a/source/VirtualFluidsCore/Connectors/CMakePackage.txt b/source/VirtualFluidsCore/Connectors/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de1dc5a88225180b8e40c6cf46f4a6fbb102778f
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
\ No newline at end of file
diff --git a/source/VirtualFluidsCore/Connectors/CoarseToFineBlock3DConnector.cpp b/source/VirtualFluidsCore/Connectors/CoarseToFineBlock3DConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9f30d03726516d7e6a63eae54d3eca8c59e15e5
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/CoarseToFineBlock3DConnector.cpp
@@ -0,0 +1,135 @@
+#include "CoarseToFineBlock3DConnector.h"
+
+
+
+////////////////////////////////////////////////////////////////////////////
+
+CoarseToFineBlock3DConnector::CoarseToFineBlock3DConnector(Block3DPtr block,
+   VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+   VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+   VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+   VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+   int sendDir, D3Q27InterpolationProcessorPtr iprocessor) : Block3DConnector(sendDir)
+   , block(block)
+   , sender00(sender00)
+   , sender01(sender01)
+   , sender10(sender10)
+   , sender11(sender11)
+   , receiver00(receiver00)
+   , receiver01(receiver01)
+   , receiver10(receiver10)
+   , receiver11(receiver11)
+   , iprocessor(iprocessor)
+{
+   if (!(sendDir==D3Q27System::E  || sendDir==D3Q27System::W  || sendDir==D3Q27System::N  || sendDir==D3Q27System::S  || sendDir==D3Q27System::T || sendDir==D3Q27System::B
+      ||  sendDir==D3Q27System::NE || sendDir==D3Q27System::SW || sendDir==D3Q27System::SE || sendDir==D3Q27System::NW
+      ||  sendDir==D3Q27System::TE || sendDir==D3Q27System::BW || sendDir==D3Q27System::BE || sendDir==D3Q27System::TW
+      ||  sendDir==D3Q27System::TN || sendDir==D3Q27System::BS || sendDir==D3Q27System::BN || sendDir==D3Q27System::TS
+      ||  sendDir==D3Q27System::TNE || sendDir==D3Q27System::TNW || sendDir==D3Q27System::TSE || sendDir==D3Q27System::TSW
+      ||  sendDir==D3Q27System::BNE || sendDir==D3Q27System::BNW || sendDir==D3Q27System::BSE || sendDir==D3Q27System::BSW
+      ))
+   {
+      throw UbException(UB_EXARGS, "invalid constructor for this direction");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+bool CoarseToFineBlock3DConnector::isLocalConnector()
+{
+   return !this->isRemoteConnector();
+}
+//////////////////////////////////////////////////////////////////////////
+
+bool CoarseToFineBlock3DConnector::isRemoteConnector()
+{
+   return ((sender11 && sender11->isRemoteTransmitter()) || (receiver11 && receiver11->isRemoteTransmitter())
+      || (sender00 && sender00->isRemoteTransmitter()) || (receiver00 && receiver00->isRemoteTransmitter())
+      || (sender01 && sender01->isRemoteTransmitter()) || (receiver01 && receiver01->isRemoteTransmitter())
+      || (sender10 && sender10->isRemoteTransmitter()) || (receiver10 && receiver10->isRemoteTransmitter()));
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineBlock3DConnector::sendTransmitterDataSize()
+{
+   if (sender00)
+   {
+      UBLOG(logDEBUG5, "CoarseToFineBlock3DConnector<VectorTransmitter>::sendTransmitterDataSize()-sender00 "<<block.lock()->toString()<<" sendDir="<<sendDir);
+      sender00->sendDataSize();
+   }
+   if (sender01)
+   {
+      UBLOG(logDEBUG5, "CoarseToFineBlock3DConnector<VectorTransmitter>::sendTransmitterDataSize()-sender01 "<<block.lock()->toString()<<"sendDir="<<sendDir);
+      sender01->sendDataSize();
+   }
+   if (sender10)
+   {
+      UBLOG(logDEBUG5, "CoarseToFineBlock3DConnector<VectorTransmitter>::sendTransmitterDataSize()-sender10 "<<block.lock()->toString()+"sendDir="<<sendDir);
+      sender10->sendDataSize();
+   }
+   if (sender11)
+   {
+      UBLOG(logDEBUG5, "CoarseToFineBlock3DConnector<VectorTransmitter>::sendTransmitterDataSize()-sender11 "<<block.lock()->toString()<<"sendDir="<<sendDir);
+      sender11->sendDataSize();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineBlock3DConnector::receiveTransmitterDataSize()
+{
+   if (receiver00)
+   {
+      UBLOG(logDEBUG5, "CoarseToFineBlock3DConnector<VectorTransmitter>::receiveTransmitterDataSize()-receiver00 "<<block.lock()->toString()<<"sendDir="<<sendDir);
+      receiver00->receiveDataSize();
+   }
+   if (receiver01)
+   {
+      UBLOG(logDEBUG5, "CoarseToFineBlock3DConnector<VectorTransmitter>::receiveTransmitterDataSize()-receiver01 "<<block.lock()->toString()<<"sendDir="<<sendDir);
+      receiver01->receiveDataSize();
+   }
+   if (receiver10)
+   {
+      UBLOG(logDEBUG5, "CoarseToFineBlock3DConnector<VectorTransmitter>::receiveTransmitterDataSize()-receiver10 "<<block.lock()->toString()<<"sendDir="<<sendDir);
+      receiver10->receiveDataSize();
+   }
+   if (receiver11)
+   {
+      UBLOG(logDEBUG5, "CoarseToFineBlock3DConnector<VectorTransmitter>::receiveTransmitterDataSize()-receiver11 "<<block.lock()->toString()<<"sendDir="<<sendDir);
+      receiver11->receiveDataSize();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineBlock3DConnector::prepareForSend()
+{
+   if (sender00) sender00->prepareForSend();
+   if (sender01) sender01->prepareForSend();
+   if (sender10) sender10->prepareForSend();
+   if (sender11) sender11->prepareForSend();
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineBlock3DConnector::sendVectors()
+{
+   if (sender00) sender00->sendData();
+   if (sender01) sender01->sendData();
+   if (sender10) sender10->sendData();
+   if (sender11) sender11->sendData();
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineBlock3DConnector::prepareForReceive()
+{
+   if (receiver00) receiver00->prepareForReceive();
+   if (receiver01) receiver01->prepareForReceive();
+   if (receiver10) receiver10->prepareForReceive();
+   if (receiver11) receiver11->prepareForReceive();
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineBlock3DConnector::receiveVectors()
+{
+   if (receiver00) receiver00->receiveData();
+   if (receiver01) receiver01->receiveData();
+   if (receiver10) receiver10->receiveData();
+   if (receiver11) receiver11->receiveData();
+}
diff --git a/source/VirtualFluidsCore/Connectors/CoarseToFineBlock3DConnector.h b/source/VirtualFluidsCore/Connectors/CoarseToFineBlock3DConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f1e87aa3a12a18eb1b2699a8ec51dbf2bcef111
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/CoarseToFineBlock3DConnector.h
@@ -0,0 +1,105 @@
+//! \file CoarseToFineBlock3DConnector.h
+//! \brief Base class for connectors that interpolates and sends data from coarse level to fine.  
+//! \author Konstantin Kutscher
+//! \date 18.05.2015
+
+#ifndef CoarseToFineBlock3DConnector_H
+#define CoarseToFineBlock3DConnector_H
+
+#include "TransmitterType.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "D3Q27InterpolationProcessor.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+class Block3D;
+
+//! \class CoarseToFineBlock3DConnector
+//! \brief Base class for connectors that interpolates and sends data from coarse level to fine. 
+//! \details The data is copied in a vector (this is located in the transmitter). 
+//! The vector is transmitted via transmitter. 
+//! The transmitter can be a local, MPI, RCG, CTL or whatever 
+//! which a transmitter that is derived from transmitter base class.
+//!
+//! four fine blocks inside a coarse block:
+//!
+//! |    |    |
+//! |:--:|:---| 
+//! | 01 | 11 | 
+//! | 00 | 10 | 
+//!
+//! send direction:    
+//!
+//! |E<->W   |  N<->S  |  T<->B |
+//! |--------|---------|--------|
+//! |  x3    |   x3    |    x2  |
+//! |  ^     |   ^     |    ^   |
+//! |  +->x2 |  +->x1  |   +->x1|
+
+
+class CoarseToFineBlock3DConnector : public Block3DConnector
+{
+public:
+   CoarseToFineBlock3DConnector(Block3DPtr block,
+      VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+      VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+      VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+      VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+      int sendDir, D3Q27InterpolationProcessorPtr iprocessor);
+
+   virtual ~CoarseToFineBlock3DConnector() {}
+
+   bool isLocalConnector();
+   bool isRemoteConnector();
+
+   virtual void init()=0;
+
+   void sendTransmitterDataSize();
+   void receiveTransmitterDataSize();
+
+   void prepareForSend();
+   void sendVectors();
+
+   void prepareForReceive();
+   void receiveVectors();
+
+   virtual void fillSendVectors()=0;
+   virtual void distributeReceiveVectors() = 0;
+
+   bool isInterpolationConnectorCF() { return true; }
+   bool isInterpolationConnectorFC() { return false; }
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1() {}
+   void sendVectorsX2() {}
+   void sendVectorsX3() {}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> block; //dieser nvd sendet daten und die empfangenen werden diesem nvd zugeordnet
+   VectorTransmitterPtr sender00, receiver00,
+                        sender01, receiver01,
+                        sender10, receiver10,
+                        sender11, receiver11;
+
+   D3Q27InterpolationProcessorPtr iprocessor;
+
+};
+
+
+
+
+#endif 
+
diff --git a/source/VirtualFluidsCore/Connectors/CoarseToFineNodeSetBlock3DConnector.cpp b/source/VirtualFluidsCore/Connectors/CoarseToFineNodeSetBlock3DConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..788a5e7730a8ec0477d567f7b99b287fcfcdbfc3
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/CoarseToFineNodeSetBlock3DConnector.cpp
@@ -0,0 +1,1382 @@
+#include "CoarseToFineNodeSetBlock3DConnector.h"
+
+////////////////////////////////////////////////////////////////////////////
+CoarseToFineNodeSetBlock3DConnector::CoarseToFineNodeSetBlock3DConnector(Block3DPtr block,
+   VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+   VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+   VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+   VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+   int sendDir, D3Q27InterpolationProcessorPtr iprocessor) : CoarseToFineBlock3DConnector(block, sender00, receiver00,
+   sender01, receiver01,
+   sender10, receiver10,
+   sender11, receiver11,
+   sendDir, iprocessor)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void CoarseToFineNodeSetBlock3DConnector::init()
+{
+   bMaxX1 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1();
+   bMaxX2 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2();
+   bMaxX3 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3();
+
+   minX1 = 0;
+   minX2 = 0;
+   minX3 = 0;
+   maxX1 = bMaxX1 - 1;
+   maxX2 = bMaxX2 - 1;
+   maxX3 = bMaxX3 - 1;
+
+   minHalfX1 = 0;
+   minHalfX2 = 0;
+   minHalfX3 = 0;
+
+   maxHalfX1 = 0;
+   maxHalfX2 = 0;
+   maxHalfX3 = 0;
+
+   if (Utilities::isEven(bMaxX1))
+   {
+      minHalfX1 = bMaxX1 / 2 - 1;
+      maxHalfX1 = bMaxX1 / 2 - 1;
+   }
+   else if (Utilities::isOdd(bMaxX1))
+   {
+      minHalfX1 = bMaxX1 / 2;
+      maxHalfX1 = bMaxX1 / 2 - 1;
+   }
+
+   if (Utilities::isEven(bMaxX2))
+   {
+      minHalfX2 = bMaxX2 / 2 - 1;
+      maxHalfX2 = bMaxX2 / 2 - 1;
+   }
+   else if (Utilities::isOdd(bMaxX2))
+   {
+      minHalfX2 = bMaxX2 / 2;
+      maxHalfX2 = bMaxX2 / 2 - 1;
+   }
+
+   if (Utilities::isEven(bMaxX3))
+   {
+      minHalfX3 = bMaxX3 / 2 - 1;
+      maxHalfX3 = bMaxX3 / 2 - 1;
+   }
+   else if (Utilities::isOdd(bMaxX3))
+   {
+      minHalfX3 = bMaxX3 / 2;
+      maxHalfX3 = bMaxX3 / 2 - 1;
+   }
+
+   //int       sendSize = 0;
+   LBMReal initValue = -999.0;
+
+   int sendDataPerNode = 27/*f*/;
+   int iCellSize = 8; //size of interpolation cell
+
+   findCFCells();
+   findFCCells();
+
+   //////////////////////////////////////////////////////
+   //Debug
+   //////////////////////////////////////////////////////
+   if (block.lock()->getGlobalID() == 2234)
+   {
+      int test = 0;
+   }
+
+   if (sender00) sender00->getData().resize(iNodeSetSender00.size()*iCellSize*sendDataPerNode, initValue);
+   else sender00 = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+   if (sender01)  sender01->getData().resize(iNodeSetSender01.size()*iCellSize*sendDataPerNode, initValue);
+   else sender01 = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+   if (sender10)  sender10->getData().resize(iNodeSetSender10.size()*iCellSize*sendDataPerNode, initValue);
+   else sender10 = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+   if (sender11)   sender11->getData().resize(iNodeSetSender11.size()*iCellSize*sendDataPerNode, initValue);
+   else sender11 = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+
+   if (!receiver00) receiver00 = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+   if (!receiver01)  receiver01 = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+   if (!receiver10)  receiver10 = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+   if (!receiver11)   receiver11 = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineNodeSetBlock3DConnector::findCFCells(int lMinX1, int lMinX2, int lMinX3, int lMaxX1, int lMaxX2, int lMaxX3, INodeSet &inodes)
+{
+   int ix1, ix2, ix3;
+   LBMReal x1off, x2off, x3off;
+
+   DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(block.lock()->getKernel()->getBCProcessor())->getBCArray();
+
+   for (ix3 = lMinX3; ix3<=lMaxX3; ix3++)
+   {
+      for (ix2 = lMinX2; ix2<=lMaxX2; ix2++)
+      {
+         for (ix1 = lMinX1; ix1<=lMaxX1; ix1++)
+         {
+            D3Q27ICell icellC;
+
+            int howManySolids = iprocessor->iCellHowManySolids(bcArray, ix1, ix2, ix3);
+
+            if (howManySolids == 0 || howManySolids == 8)
+            {
+               x1off = 0.0;
+               x2off = 0.0;
+               x3off = 0.0;
+            }
+            else
+            {
+               if (!iprocessor->findNeighborICell(bcArray, fFrom, icellC, bMaxX1, bMaxX2, bMaxX3, ix1, ix2, ix3, x1off, x2off, x3off))
+               {
+                  std::string err = "For "+block.lock()->toString()+" x1="+UbSystem::toString(ix1)+", x2=" + UbSystem::toString(ix2)+", x3=" + UbSystem::toString(ix3)+
+                     " interpolation is not implemented for other direction"+
+                     " by using in: "+(std::string)typeid(*this).name()+
+                     " or maybe you have a solid on the block boundary";
+                  UB_THROW(UbException(UB_EXARGS, err));
+               }
+            }
+
+            INodeVector inv;
+            inv.push_back(ix1 + (int)x1off);
+            inv.push_back(ix2 + (int)x2off);
+            inv.push_back(ix3 + (int)x3off);
+            inv.push_back((int)x1off);
+            inv.push_back((int)x2off);
+            inv.push_back((int)x3off);
+            //inodes.insert(inv);
+            inodes.push_back(inv);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//template< typename VectorTransmitter >
+void CoarseToFineNodeSetBlock3DConnector::findCFCells()
+{
+   using namespace D3Q27System;
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+
+   switch (sendDir)
+   {
+      //faces
+   case E: case W:
+      if (sendDir == E)
+      {
+         lMinX1 = maxX1 - 2;
+         lMaxX1 = lMinX1;
+      }
+      else if (sendDir == W)
+      {
+         lMinX1 = 1;
+         lMaxX1 = lMinX1;
+      }
+
+      if (sender00)
+      {
+         lMinX2 = minX2;
+         lMaxX2 = maxHalfX2;
+         lMinX3 = minX3;
+         lMaxX3 = maxHalfX3;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender00);
+      }
+      if (sender10)
+      {
+         lMinX2 = minHalfX2;
+         lMaxX2 = maxX2 - 1;
+         lMinX3 = minX3;
+         lMaxX3 = maxHalfX3;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender10);
+      }
+      if (sender01)
+      {
+         lMinX2 = minX2;
+         lMaxX2 = maxHalfX2;
+         lMinX3 = minHalfX3;
+         lMaxX3 = maxX3 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender01);
+      }
+      if (sender11)
+      {
+         lMinX2 = minHalfX2;
+         lMaxX2 = maxX2 - 1;
+         lMinX3 = minHalfX3;
+         lMaxX3 = maxX3 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender11);
+      }
+      break;
+   case N: case S:
+      if (sendDir == N)
+      {
+         lMinX2 = maxX2 - 2;
+         lMaxX2 = lMinX2;
+      }
+      else if (sendDir == S)
+      {
+         lMinX2 = 1;
+         lMaxX2 = lMinX2;
+      }
+
+      if (sender00)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxHalfX1;
+         lMinX3 = minX3;
+         lMaxX3 = maxHalfX3;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender00);
+      }
+      if (sender10)
+      {
+         lMinX1 = minHalfX1;
+         lMaxX1 = maxX1 - 1;
+         lMinX3 = minX3;
+         lMaxX3 = maxHalfX3;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender10);
+      }
+      if (sender01)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxHalfX1;
+         lMinX3 = minHalfX3;
+         lMaxX3 = maxX3 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender01);
+      }
+      if (sender11)
+      {
+         lMinX1 = minHalfX1;
+         lMaxX1 = maxX1 - 1;
+         lMinX3 = minHalfX3;
+         lMaxX3 = maxX3 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender11);
+      }
+      break;
+   case T: case B:
+      if (sendDir == T)
+      {
+         lMinX3 = maxX3 - 2;
+         lMaxX3 = lMinX3;
+      }
+      else if (sendDir == B)
+      {
+         lMinX3 = 1;
+         lMaxX3 = lMinX3;
+      }
+
+      if (sender00)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxHalfX1;
+         lMinX2 = minX2;
+         lMaxX2 = maxHalfX2;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender00);
+      }
+      if (sender10)
+      {
+         lMinX1 = minHalfX1;
+         lMaxX1 = maxX1 - 1;
+         lMinX2 = minX2;
+         lMaxX2 = maxHalfX2;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender10);
+      }
+      if (sender01)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxHalfX1;
+         lMinX2 = minHalfX2;
+         lMaxX2 = maxX2 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender01);
+      }
+      if (sender11)
+      {
+         lMinX1 = minHalfX1;
+         lMaxX1 = maxX1 - 1;
+         lMinX2 = minHalfX2;
+         lMaxX2 = maxX2 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender11);
+      }
+      break;
+      //edges
+      //N-S-E-W
+   case NE: case SW: case SE: case NW:
+      if (sendDir == NE)
+      {
+         lMinX1 = maxX1 - 2;
+         lMaxX1 = lMinX1 + 1;
+         lMinX2 = maxX2 - 2;
+         lMaxX2 = lMinX2 + 1;
+      }
+      else if (sendDir == SW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = lMinX1 + 1;
+         lMinX2 = 0;
+         lMaxX2 = lMinX2 + 1;
+      }
+      else if (sendDir == SE)
+      {
+         lMinX1 = maxX1 - 2;
+         lMaxX1 = lMinX1 + 1;
+         lMinX2 = 0;
+         lMaxX2 = lMinX2 + 1;
+      }
+      else if (sendDir == NW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = lMinX1 + 1;
+         lMinX2 = maxX2 - 2;
+         lMaxX2 = lMinX2 + 1;
+      }
+
+      if (sender00)
+      {
+         lMinX3 = minX3;
+         lMaxX3 = maxHalfX3;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender00);
+      }
+      if (sender10)
+      {
+         lMinX3 = minHalfX3;
+         lMaxX3 = maxX3 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender10);
+      }
+      break;
+      //T-B-E-W
+   case TE: case BW: case BE: case TW:
+      if (sendDir == TE)
+      {
+         lMinX1 = maxX1 - 2;
+         lMaxX1 = lMinX1 + 1;
+         lMinX3 = maxX3 - 2;
+         lMaxX3 = lMinX3 + 1;
+      }
+      else if (sendDir == BW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = lMinX1 + 2;
+         lMinX3 = 0;
+         lMaxX3 = lMinX3 + 2;
+      }
+      else if (sendDir == BE)
+      {
+         lMinX1 = maxX1 - 2;
+         lMaxX1 = lMinX1 + 1;
+         lMinX3 = 0;
+         lMaxX3 = lMinX3 + 1;
+      }
+      else if (sendDir == TW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = lMinX1 + 1;
+         lMinX3 = maxX3 - 2;
+         lMaxX3 = lMinX3 + 1;
+      }
+
+      if (sender00)
+      {
+         lMinX2 = minX2;
+         lMaxX2 = maxHalfX2;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender00);
+      }
+      if (sender10)
+      {
+         lMinX2 = minHalfX2;
+         lMaxX2 = maxX2 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender10);
+      }
+      break;
+      //T-B-N-S
+   case TN: case BS: case BN: case TS:
+      if (sendDir == TN)
+      {
+         lMinX2 = maxX2 - 2;
+         lMaxX2 = lMinX2 + 1;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = lMinX3 + 1;
+      }
+      else if (sendDir == BS)
+      {
+         lMinX2 = 0;
+         lMaxX2 = lMinX2 + 1;
+         lMinX3 = 0;
+         lMaxX3 = lMinX3 + 1;
+      }
+      else if (sendDir == BN)
+      {
+         lMinX2 = maxX2 - 2;
+         lMaxX2 = lMinX2 + 1;
+         lMinX3 = 0;
+         lMaxX3 = lMinX3 + 1;
+      }
+      else if (sendDir == TS)
+      {
+         lMinX2 = 0;
+         lMaxX2 = lMinX2 + 1;
+         lMinX3 = maxX3 - 2;
+         lMaxX3 = lMinX3 + 1;
+      }
+
+      if (sender00)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxHalfX1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender00);
+      }
+      if (sender10)
+      {
+         lMinX1 = minHalfX1;
+         lMaxX1 = maxX1 - 1;
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender10);
+      }
+      break;
+      //corners
+   case TNE: case TNW: case TSE: case TSW: case BNE: case BNW: case BSE: case BSW:
+      if (sendDir == TNE)
+      {
+         lMinX1 = maxX1-2;
+         lMaxX1 = maxX1-1;
+         lMinX2 = maxX2-2;
+         lMaxX2 = maxX2-1;
+         lMinX3 = maxX3-2;
+         lMaxX3 = maxX3-1;
+      }
+      else if (sendDir == TNW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = 1;
+         lMinX2 = maxX2-2;
+         lMaxX2 = maxX2-1;
+         lMinX3 = maxX3-2;
+         lMaxX3 = maxX3-1;
+      }
+      else if (sendDir == TSE)
+      {
+         lMinX1 = maxX1-2;
+         lMaxX1 = maxX1-1;
+         lMinX2 = 0;
+         lMaxX2 = 1;
+         lMinX3 = maxX3-2;
+         lMaxX3 = maxX3-1;
+      }
+      else if (sendDir == TSW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = 1;
+         lMinX2 = 0;
+         lMaxX2 = 1;
+         lMinX3 = maxX3-2;
+         lMaxX3 = maxX3-1;
+      }
+      else if (sendDir == BNE)
+      {
+         lMinX1 = maxX1-2;
+         lMaxX1 = maxX1-1;
+         lMinX2 = maxX2-2;
+         lMaxX2 = maxX2-1;
+         lMinX3 = 0;
+         lMaxX3 = 1;
+      }
+      else if (sendDir == BNW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = 1;
+         lMinX2 = maxX2-2;
+         lMaxX2 = maxX2-1;
+         lMinX3 = 0;
+         lMaxX3 = 1;
+      }
+      else if (sendDir == BSE)
+      {
+         lMinX1 = maxX1-2;
+         lMaxX1 = maxX1-1;
+         lMinX2 = 0;
+         lMaxX2 = 1;
+         lMinX3 = 0;
+         lMaxX3 = 1;
+      }
+      else if (sendDir == BSW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = 1;
+         lMinX2 = 0;
+         lMaxX2 = 1;
+         lMinX3 = 0;
+         lMaxX3 = 1;
+      }
+      if (sender00)
+      {
+         findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetSender00);
+      }
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//template< typename VectorTransmitter >
+void CoarseToFineNodeSetBlock3DConnector::fillSendVectors()
+{
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+
+   int index00 = 0;
+   int index01 = 0;
+   int index10 = 0;
+   int index11 = 0;
+
+   vector_type& data00 = this->sender00->getData();
+   vector_type& data01 = this->sender01->getData();
+   vector_type& data10 = this->sender10->getData();
+   vector_type& data11 = this->sender11->getData();
+
+   BOOST_FOREACH(INodeVector inode, iNodeSetSender00)
+   {
+      D3Q27ICell icellC;
+      D3Q27ICell icellF;
+      iprocessor->readICell(fFrom, icellC, inode[0], inode[1], inode[2]);
+      iprocessor->interpolateCoarseToFine(icellC, icellF, inode[3], inode[4], inode[5]);
+      writeICellFtoData(data00, index00, icellF);
+   }
+   BOOST_FOREACH(INodeVector inode, iNodeSetSender01)
+   {
+      D3Q27ICell icellC;
+      D3Q27ICell icellF;
+      iprocessor->readICell(fFrom, icellC, inode[0], inode[1], inode[2]);
+      iprocessor->interpolateCoarseToFine(icellC, icellF, inode[3], inode[4], inode[5]);
+      writeICellFtoData(data01, index01, icellF);
+   }
+   BOOST_FOREACH(INodeVector inode, iNodeSetSender10)
+   {
+      D3Q27ICell icellC;
+      D3Q27ICell icellF;
+      iprocessor->readICell(fFrom, icellC, inode[0], inode[1], inode[2]);
+      iprocessor->interpolateCoarseToFine(icellC, icellF, inode[3], inode[4], inode[5]);
+      writeICellFtoData(data10, index10, icellF);
+   }
+   BOOST_FOREACH(INodeVector inode, iNodeSetSender11)
+   {
+      D3Q27ICell icellC;
+      D3Q27ICell icellF;
+      iprocessor->readICell(fFrom, icellC, inode[0], inode[1], inode[2]);
+      iprocessor->interpolateCoarseToFine(icellC, icellF, inode[3], inode[4], inode[5]);
+      writeICellFtoData(data11, index11, icellF);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineNodeSetBlock3DConnector::writeICellFtoData(vector_type& data, int& index, D3Q27ICell& icellF)
+{
+   writeNodeToVector(data, index, icellF.BSW);
+   writeNodeToVector(data, index, icellF.BSE);
+   writeNodeToVector(data, index, icellF.BNW);
+   writeNodeToVector(data, index, icellF.BNE);
+   writeNodeToVector(data, index, icellF.TSW);
+   writeNodeToVector(data, index, icellF.TSE);
+   writeNodeToVector(data, index, icellF.TNW);
+   writeNodeToVector(data, index, icellF.TNE);
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineNodeSetBlock3DConnector::writeNodeToVector(vector_type& data, int& index, LBMReal* inode)
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      data[index++] = inode[i];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineNodeSetBlock3DConnector::findFCCells(int lMinX1, int lMinX2, int lMinX3, int lMaxX1, int lMaxX2, int lMaxX3, INodeSet &inodes)
+{
+   int ix1, ix2, ix3;
+
+   for (ix3 = lMinX3; ix3<=lMaxX3; ix3++)
+   {
+      for (ix2 = lMinX2; ix2<=lMaxX2; ix2++)
+      {
+         for (ix1 = lMinX1; ix1<=lMaxX1; ix1++)
+         {
+            INodeVector inv;
+            inv.push_back(ix1);
+            inv.push_back(ix2);
+            inv.push_back(ix3);
+            //inodes.insert(inv);
+            inodes.push_back(inv);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//template< typename VectorTransmitter >
+void CoarseToFineNodeSetBlock3DConnector::findFCCells()
+{
+   using namespace D3Q27System;
+
+   int lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3;
+   int lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3;
+   int lMin3X1, lMin3X2, lMin3X3, lMax3X1, lMax3X2, lMax3X3;
+   int dummy;
+
+   switch (sendDir)
+   {
+
+      //////////////////////////////////////////////////////
+      //Debug
+      //////////////////////////////////////////////////////
+      if (block.lock()->getGlobalID() == 2234)
+      {
+         int test = 0;
+      }
+
+      //faces
+   case E: case W:
+      if (sendDir == E)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = lMin1X1;
+      }
+      else if (sendDir == W)
+      {
+         lMin1X1 = 3;
+         lMax1X1 = lMin1X1;
+      }
+
+      //int TminX1 = lMinX1; int TminX2 = lMinX2; int TminX3 = lMinX3; int TmaxX1 = lMaxX1; int TmaxX2 = lMaxX2; int TmaxX3 = lMaxX3;
+
+      //if (block.lock()->hasInterpolationFlagCF(E))
+      //{
+      //   if (maxX1==TmaxX1) maxX1 -= 2;
+      //}
+      //if (block.lock()->hasInterpolationFlagCF(W))
+      //{
+      //   if (minX1==TminX1) minX1 += 2;
+      //}
+      //if (block.lock()->hasInterpolationFlagCF(N))
+      //{
+      //   if (maxX2==TmaxX2)  maxX2 -= 2;
+      //}
+      //if (block.lock()->hasInterpolationFlagCF(S))
+      //{
+      //   if (minX2==TminX2)  minX2 += 2;
+      //}
+      //if (block.lock()->hasInterpolationFlagCF(T))
+      //{
+      //   if (maxX3==TmaxX3)  maxX3 -= 2;
+      //}
+      //if (block.lock()->hasInterpolationFlagCF(B))
+      //{
+      //   if (minX3==TminX3)  minX3 += 2;
+      //}
+      if (receiver00)
+      {
+         lMin1X2 = minX2;
+         lMax1X2 = maxHalfX2;
+         lMin1X3 = minX3;
+         lMax1X3 = maxHalfX3;
+         getLocalMinMax(dummy, lMin1X2, lMin1X3, dummy, dummy, dummy);
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin1X2 = minHalfX2;
+         lMax1X2 = maxX2 - 1;
+         lMin1X3 = minX3;
+         lMax1X3 = maxHalfX3;
+         getLocalMinMax(dummy, dummy, lMin1X3, dummy, lMax1X2, dummy);
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver10);
+      }
+      if (receiver01)
+      {
+         lMin1X2 = minX2;
+         lMax1X2 = maxHalfX2;
+         lMin1X3 = minHalfX3;
+         lMax1X3 = maxX3 - 1;
+         getLocalMinMax(dummy, lMin1X2, dummy, dummy, dummy, lMax1X3);
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver01);
+      }
+      if (receiver11)
+      {
+         lMin1X2 = minHalfX2;
+         lMax1X2 = maxX2 - 1;
+         lMin1X3 = minHalfX3;
+         lMax1X3 = maxX3 - 1;
+         getLocalMinMax(dummy, dummy, dummy, dummy, lMax1X2, lMax1X3);
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver11);
+      }
+      break;
+   case N: case S:
+      if (sendDir == N)
+      {
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = lMin1X2;
+      }
+      else if (sendDir == S)
+      {
+         lMin1X2 = 3;
+         lMax1X2 = lMin1X2;
+      }
+
+      if (receiver00)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxHalfX1;
+         lMin1X3 = minX3;
+         lMax1X3 = maxHalfX3;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin1X1 = minHalfX1;
+         lMax1X1 = maxX1 - 1;
+         lMin1X3 = minX3;
+         lMax1X3 = maxHalfX3;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver10);
+      }
+      if (receiver01)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxHalfX1;
+         lMin1X3 = minHalfX3;
+         lMax1X3 = maxX3 - 1;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver01);
+      }
+      if (receiver11)
+      {
+         lMin1X1 = minHalfX1;
+         lMax1X1 = maxX1 - 1;
+         lMin1X3 = minHalfX3;
+         lMax1X3 = maxX3 - 1;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver11);
+      }
+      break;
+   case T: case B:
+      if (sendDir == T)
+      {
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = lMin1X3;
+      }
+      else if (sendDir == B)
+      {
+         lMin1X3 = 3;
+         lMax1X3 = lMin1X3;
+      }
+
+      if (receiver00)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxHalfX1;
+         lMin1X2 = minX2;
+         lMax1X2 = maxHalfX2;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin1X1 = minHalfX1;
+         lMax1X1 = maxX1 - 1;
+         lMin1X2 = minX2;
+         lMax1X2 = maxHalfX2;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver10);
+      }
+      if (receiver01)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxHalfX1;
+         lMin1X2 = minHalfX2;
+         lMax1X2 = maxX2 - 1;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver01);
+      }
+      if (receiver11)
+      {
+         lMin1X1 = minHalfX1;
+         lMax1X1 = maxX1 - 1;
+         lMin1X2 = minHalfX2;
+         lMax1X2 = maxX2 - 1;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver11);
+      }
+      break;
+      //edges
+      //N-S-E-W
+   case NE: case SW: case SE: case NW:
+      if (sendDir == NE)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = lMin1X1 + 2;
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = lMin1X2;
+
+         lMin2X1 = maxX1 - 3;
+         lMax2X1 = lMin2X1;
+         lMin2X2 = maxX2 - 3;
+         lMax2X2 = lMin2X2 + 2;
+      }
+      else if (sendDir == SW)
+      {
+         lMin1X1 = 1;
+         lMax1X1 = lMin1X1 + 2;
+         lMin1X2 = 3;
+         lMax1X2 = lMin1X2;
+
+         lMin2X1 = 3;
+         lMax2X1 = lMin2X1;
+         lMin2X2 = 1;
+         lMax2X2 = lMin2X2 + 2;
+      }
+      else if (sendDir == SE)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = lMin1X1 + 2;
+         lMin1X2 = 3;
+         lMax1X2 = lMin1X2;
+
+         lMin2X1 = maxX1 - 3;
+         lMax2X1 = lMin2X1;
+         lMin2X2 = 1;
+         lMax2X2 = lMin2X2 + 2;
+      }
+      else if (sendDir == NW)
+      {
+         lMin1X1 = 1;
+         lMax1X1 = lMin1X1 + 2;
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = lMin1X2;
+
+         lMin2X1 = 3;
+         lMax2X1 = lMin2X1;
+         lMin2X2 = maxX2 - 3;
+         lMax2X2 = lMin2X2 + 2;
+      }
+
+      if (receiver00)
+      {
+         lMin1X3 = minX3;
+         lMax1X3 = maxHalfX3;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin1X3 = minHalfX3;
+         lMax1X3 = maxX3 - 1;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver10);
+      }
+
+      if (receiver00)
+      {
+         lMin2X3 = minX3;
+         lMax2X3 = maxHalfX3;
+         findFCCells(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin2X3 = minHalfX3;
+         lMax2X3 = maxX3 - 1;
+         findFCCells(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3, iNodeSetReceiver10);
+      }
+      break;
+      //T-B-E-W
+   case TE: case BW: case BE: case TW:
+      if (sendDir == TE)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = lMin1X1 + 2;
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = lMin1X3;
+
+         lMin2X1 = maxX1 - 3;
+         lMax2X1 = lMin2X1;
+         lMin2X3 = maxX3 - 3;
+         lMax2X3 = lMin2X3 + 2;
+      }
+      else if (sendDir == BW)
+      {
+         lMin1X1 = 1;
+         lMax1X1 = lMin1X1 + 2;
+         lMin1X3 = 3;
+         lMax1X3 = lMin1X3;
+
+         lMin2X1 = 3;
+         lMax2X1 = lMin2X1;
+         lMin2X3 = 1;
+         lMax2X3 = lMin2X3 + 2;
+      }
+      else if (sendDir == BE)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = lMin1X1 + 2;
+         lMin1X3 = 3;
+         lMax1X3 = lMin1X3;
+
+
+         lMin2X1 = maxX1 - 3;
+         lMax2X1 = lMin2X1;
+         lMin2X3 = 1;
+         lMax2X3 = lMin2X3 + 2;
+      }
+      else if (sendDir == TW)
+      {
+         lMin1X1 = 1;
+         lMax1X1 = lMin1X1 + 2;
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = lMin1X3;
+
+         lMin2X1 = 3;
+         lMax2X1 = lMin2X1;
+         lMin2X3 = maxX3 - 3;
+         lMax2X3 = lMin2X3 + 2;
+      }
+
+      if (receiver00)
+      {
+         lMin1X2 = minX2;
+         lMax1X2 = maxHalfX2;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin1X2 = minHalfX2;
+         lMax1X2 = maxX2 - 1;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver10);
+      }
+
+      if (receiver00)
+      {
+         lMin2X2 = minX2;
+         lMax2X2 = maxHalfX2;
+         findFCCells(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin2X2 = minHalfX2;
+         lMax2X2 = maxX2 - 1;
+         findFCCells(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3, iNodeSetReceiver10);
+      }
+      break;
+      //T-B-N-S
+   case TN: case BS: case BN: case TS:
+      if (sendDir == TN)
+      {
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = lMin1X2 + 2;
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = lMin1X3;
+
+         lMin2X2 = maxX2 - 3;
+         lMax2X2 = lMin2X2;
+         lMin2X3 = maxX3 - 3;
+         lMax2X3 = lMin2X3 + 2;
+      }
+      else if (sendDir == BS)
+      {
+         lMin1X2 = 1;
+         lMax1X2 = lMin1X2 + 2;
+         lMin1X3 = 3;
+         lMax1X3 = lMin1X3;
+
+         lMin2X2 = 3;
+         lMax2X2 = lMin2X2;
+         lMin2X3 = 1;
+         lMax2X3 = lMin2X3 + 2;
+      }
+      else if (sendDir == BN)
+      {
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = lMin1X2 + 2;
+         lMin1X3 = 3;
+         lMax1X3 = lMin1X3;
+
+         lMin2X2 = maxX2 - 3;
+         lMax2X2 = lMin2X2;
+         lMin2X3 = 1;
+         lMax2X3 = lMin2X3 + 2;
+      }
+      else if (sendDir == TS)
+      {
+         lMin1X2 = 1;
+         lMax1X2 = lMin1X2 + 2;
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = lMin1X3;
+
+         lMin2X2 = 3;
+         lMax2X2 = lMin2X2;
+         lMin2X3 = maxX3 - 3;
+         lMax2X3 = lMin2X3 + 2;
+      }
+
+      if (receiver00)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxHalfX1;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin1X1 = minHalfX1;
+         lMax1X1 = maxX1 - 1;
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver10);
+      }
+
+      if (receiver00)
+      {
+         lMin2X1 = minX1;
+         lMax2X1 = maxHalfX1;
+         findFCCells(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3, iNodeSetReceiver00);
+      }
+      if (receiver10)
+      {
+         lMin2X1 = minHalfX1;
+         lMax2X1 = maxX1 - 1;
+         findFCCells(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3, iNodeSetReceiver10);
+      }
+      break;
+      //corners
+   case TNE: case TNW: case TSE: case TSW: case BNE: case BNW: case BSE: case BSW:
+      if (sendDir == TNE)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = maxX1 - 2;
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = maxX2 - 1;
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = maxX3 - 1;
+
+         lMin2X1 = maxX1 - 3;
+         lMax2X1 = maxX1 - 1;
+         lMin2X2 = maxX2 - 3;
+         lMax2X2 = maxX2 - 2;
+         lMin2X3 = maxX3 - 3;
+         lMax2X3 = maxX3 - 1;
+
+         lMin3X1 = maxX1 - 3;
+         lMax3X1 = maxX1 - 1;
+         lMin3X2 = maxX2 - 3;
+         lMax3X2 = maxX2 - 1;
+         lMin3X3 = maxX3 - 3;
+         lMax3X3 = maxX3 - 2;
+      }
+      else if (sendDir == TNW)
+      {
+         lMin1X1 = 3;
+         lMax1X1 = 3;
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = maxX2 - 1;
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = maxX3 - 1;
+
+         lMin2X1 = 1;
+         lMax2X1 = 3;
+         lMin2X2 = maxX2 - 3;
+         lMax2X2 = maxX2 - 2;
+         lMin2X3 = maxX3 - 3;
+         lMax2X3 = maxX3;
+
+         lMin3X1 = 1;
+         lMax3X1 = 3;
+         lMin3X2 = maxX2 - 3;
+         lMax3X2 = maxX2 - 1;
+         lMin3X3 = maxX3 - 3;
+         lMax3X3 = maxX3 - 2;
+      }
+      else if (sendDir == TSE)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = maxX1 - 2;
+         lMin1X2 = 1;
+         lMax1X2 = 3;
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = maxX3;
+
+         lMin2X1 = maxX1 - 3;
+         lMax2X1 = maxX1 - 1;
+         lMin2X2 = 3;
+         lMax2X2 = 3;
+         lMin2X3 = maxX3 - 3;
+         lMax2X3 = maxX3;
+
+         lMin3X1 = maxX1 - 3;
+         lMax3X1 = maxX1 - 1;
+         lMin3X2 = 1;
+         lMax3X2 = 3;
+         lMin3X3 = maxX3 - 3;
+         lMax3X3 = maxX3 - 2;
+      }
+      else if (sendDir == TSW)
+      {
+         lMin1X1 = 3;
+         lMax1X1 = 3;
+         lMin1X2 = 1;
+         lMax1X2 = 3;
+         lMin1X3 = maxX3 - 3;
+         lMax1X3 = maxX3 - 1;
+
+         lMin2X1 = 1;
+         lMax2X1 = 3;
+         lMin2X2 = 3;
+         lMax2X2 = 3;
+         lMin2X3 = maxX3 - 3;
+         lMax2X3 = maxX3 - 1;
+
+         lMin3X1 = 1;
+         lMax3X1 = 3;
+         lMin3X2 = 1;
+         lMax3X2 = 3;
+         lMin3X3 = maxX3 - 3;
+         lMax3X3 = maxX3 - 2;
+      }
+      else if (sendDir == BNE)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = maxX1 - 2;
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = maxX2 - 1;
+         lMin1X3 = 1;
+         lMax1X3 = 3;
+
+         lMin2X1 = maxX1 - 3;
+         lMax2X1 = maxX1 - 1;
+         lMin2X2 = maxX2 - 3;
+         lMax2X2 = maxX2 - 2;
+         lMin2X3 = 1;
+         lMax2X3 = 3;
+
+         lMin3X1 = maxX1 - 3;
+         lMax3X1 = maxX1 - 1;
+         lMin3X2 = maxX2 - 3;
+         lMax3X2 = maxX2 - 1;
+         lMin3X3 = 3;
+         lMax3X3 = 3;
+      }
+      else if (sendDir == BNW)
+      {
+         lMin1X1 = 3;
+         lMax1X1 = 3;
+         lMin1X2 = maxX2 - 3;
+         lMax1X2 = maxX2 - 1;
+         lMin1X3 = 1;
+         lMax1X3 = 3;
+
+         lMin2X1 = 1;
+         lMax2X1 = 3;
+         lMin2X2 = maxX2 - 3;
+         lMax2X2 = maxX2 - 2;
+         lMin2X3 = 1;
+         lMax2X3 = 3;
+
+         lMin3X1 = 1;
+         lMax3X1 = 3;
+         lMin3X2 = maxX2 - 3;
+         lMax3X2 = maxX2 - 1;
+         lMin3X3 = 3;
+         lMax3X3 = 3;
+      }
+      else if (sendDir == BSE)
+      {
+         lMin1X1 = maxX1 - 3;
+         lMax1X1 = maxX1 - 2;
+         lMin1X2 = 1;
+         lMax1X2 = 3;
+         lMin1X3 = 1;
+         lMax1X3 = 3;
+
+         lMin2X1 = maxX1 - 3;
+         lMax2X1 = maxX1 - 1;
+         lMin2X2 = 3;
+         lMax2X2 = 3;
+         lMin2X3 = 1;
+         lMax2X3 = 3;
+
+         lMin3X1 = maxX1 - 3;
+         lMax3X1 = maxX1 - 1;
+         lMin3X2 = 1;
+         lMax3X2 = 3;
+         lMin3X3 = 3;
+         lMax3X3 = 3;
+      }
+      else if (sendDir == BSW)
+      {
+         lMin1X1 = 3;
+         lMax1X1 = 3;
+         lMin1X2 = 1;
+         lMax1X2 = 3;
+         lMin1X3 = 1;
+         lMax1X3 = 3;
+
+         lMin2X1 = 1;
+         lMax2X1 = 3;
+         lMin2X2 = 3;
+         lMax2X2 = 3;
+         lMin2X3 = 1;
+         lMax2X3 = 3;
+
+         lMin3X1 = 1;
+         lMax3X1 = 3;
+         lMin3X2 = 1;
+         lMax3X2 = 3;
+         lMin3X3 = 3;
+         lMax3X3 = 3;
+      }
+      if (receiver00)
+      {
+         findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetReceiver00);
+      }
+      if (receiver00)
+      {
+         findFCCells(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3, iNodeSetReceiver00);
+      }
+      if (receiver00)
+      {
+         findFCCells(lMin3X1, lMin3X2, lMin3X3, lMax3X1, lMax3X2, lMax3X3, iNodeSetReceiver00);
+      }
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//template< typename VectorTransmitter >
+void CoarseToFineNodeSetBlock3DConnector::distributeReceiveVectors()
+{
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fTo = block.lock()->getKernel()->getDataSet()->getFdistributions();
+
+   int index00 = 0;
+   int index01 = 0;
+   int index10 = 0;
+   int index11 = 0;
+
+   vector_type& data00 = this->receiver00->getData();
+   vector_type& data01 = this->receiver01->getData();
+   vector_type& data10 = this->receiver10->getData();
+   vector_type& data11 = this->receiver11->getData();
+
+   BOOST_FOREACH(INodeVector inode, iNodeSetReceiver00)
+   {
+      LBMReal icellC[27];
+      this->readICellCfromData(data00, index00, icellC);
+      iprocessor->writeINode(fTo, icellC, inode[0], inode[1], inode[2]);
+   }
+   BOOST_FOREACH(INodeVector inode, iNodeSetReceiver01)
+   {
+      LBMReal icellC[27];
+      this->readICellCfromData(data01, index01, icellC);
+      iprocessor->writeINode(fTo, icellC, inode[0], inode[1], inode[2]);
+   }
+   BOOST_FOREACH(INodeVector inode, iNodeSetReceiver10)
+   {
+      LBMReal icellC[27];
+      this->readICellCfromData(data10, index10, icellC);
+      iprocessor->writeINode(fTo, icellC, inode[0], inode[1], inode[2]);
+   }
+   BOOST_FOREACH(INodeVector inode, iNodeSetReceiver11)
+   {
+      LBMReal icellC[27];
+      this->readICellCfromData(data11, index11, icellC);
+      iprocessor->writeINode(fTo, icellC, inode[0], inode[1], inode[2]);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineNodeSetBlock3DConnector::readICellCfromData(vector_type& data, int& index, LBMReal* icellC)
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      icellC[i] = data[index++];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+void CoarseToFineNodeSetBlock3DConnector::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3)
+{
+   using namespace D3Q27System;
+   int TminX1 = minX1; int TminX2 = minX2; int TminX3 = minX3; int TmaxX1 = maxX1; int TmaxX2 = maxX2; int TmaxX3 = maxX3;
+
+   if (block.lock()->hasInterpolationFlagCF(E))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(W))
+   {
+      if (minX1==TminX1) minX1 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(N))
+   {
+      if (maxX2==TmaxX2)  maxX2 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(S))
+   {
+      if (minX2==TminX2)  minX2 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (maxX3==TmaxX3)  maxX3 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (minX3==TminX3)  minX3 += 2;
+   }
+
+   //E-W-N-S
+   if (block.lock()->hasInterpolationFlagCF(NE) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(E))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+      if (maxX2==TmaxX2) maxX2 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(SW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(S))
+   {
+      if (minX1==TminX1) minX1 += 2;
+      if (minX2==TminX2) minX2 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(SE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(S))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+      if (minX2==TminX2) minX2 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(NW) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(W))
+   {
+      if (minX1==TminX1) minX1 += 2;
+      if (maxX2==TmaxX2) maxX2 -= 2;
+   }
+
+   //	////T-B-E-W
+   if (block.lock()->hasInterpolationFlagCF(TE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+      if (maxX3==TmaxX3) maxX3 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(BW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (minX1==TminX1) minX1 += 2;
+      if (minX3==TminX3) minX3 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(BE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+      if (minX3==TminX3) minX3 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(TW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (minX1==TminX1) minX1 += 2;
+      if (maxX3==TmaxX3) maxX3 -= 2;
+   }
+
+
+   ////T-B-N-S
+   if (block.lock()->hasInterpolationFlagCF(TN) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (maxX2==TmaxX2) maxX2 -= 2;
+      if (maxX3==TmaxX3) maxX3 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(BS) && !block.lock()->hasInterpolationFlagCF(S) && !block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (minX2==TminX2) minX2 += 2;
+      if (minX3==TminX3) minX3 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(BN) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (maxX2==TmaxX2) maxX2 -= 2;
+      if (minX3==TminX3) minX3 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(TS) && !block.lock()->hasInterpolationFlagCF(S) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (minX2==TminX2) minX2 += 2;
+      if (maxX3==TmaxX3) maxX3 -= 2;
+   }
+}
+
+
diff --git a/source/VirtualFluidsCore/Connectors/CoarseToFineNodeSetBlock3DConnector.h b/source/VirtualFluidsCore/Connectors/CoarseToFineNodeSetBlock3DConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..488165db4389c4b1b1d27d89acf3fdb0693a7457
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/CoarseToFineNodeSetBlock3DConnector.h
@@ -0,0 +1,102 @@
+//! \file CoarseToFineNodeSetBlock3DConnector.h
+//! \class CoarseToFineNodeSetBlock3DConnector
+//! \brief Connector interpolates and sends data from coarse level to fine.  
+//! \author Konstantin Kutscher
+//! \date 18.05.2015
+
+#ifndef CoarseToFineNodeSetBlock3DConnector_H
+#define CoarseToFineNodeSetBlock3DConnector_H
+
+#include <vector>
+#include <set>
+
+//#include "basics/transmitter/TbTransmitter.h"
+//#include "basics/transmitter/TbTransmitterLocal.h"
+//#include "basics/container/CbVector.h"
+#include "CoarseToFineBlock3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "MathUtil.hpp"
+#include "Grid3D.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+class Block3D;
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+
+
+// send direction:    E<->W     N<->S    T<->B  
+//  ---------          x3       x3        x2    
+// | 01 | 11 |         ^        ^         ^     
+// |----+----|         +-> x2   +->x1     +->x1 
+// | 00 | 10 |                                  
+//  ---------                                   
+
+
+class CoarseToFineNodeSetBlock3DConnector : public CoarseToFineBlock3DConnector
+{
+public:
+   CoarseToFineNodeSetBlock3DConnector(Block3DPtr block,
+      VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+      VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+      VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+      VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+      int sendDir, D3Q27InterpolationProcessorPtr iprocessor);
+
+   void init();
+
+   void fillSendVectors();
+   void distributeReceiveVectors();
+
+protected:
+   typedef std::vector< int > INodeVector;
+   typedef std::vector < INodeVector > INodeSet;
+   INodeSet  iNodeSetSender00;
+   INodeSet  iNodeSetSender01;
+   INodeSet  iNodeSetSender10;
+   INodeSet  iNodeSetSender11;
+   INodeSet  iNodeSetReceiver00;
+   INodeSet  iNodeSetReceiver01;
+   INodeSet  iNodeSetReceiver10;
+   INodeSet  iNodeSetReceiver11;
+
+   void writeICellFtoData(vector_type& data, int& index, D3Q27ICell& icellF);
+   void writeNodeToVector(vector_type& data, int& index, LBMReal* inode);
+   void readICellCfromData(vector_type& data, int& index, LBMReal* icellC);
+
+   void findCFCells();
+   void findCFCells(int lMinX1, int lMinX2, int lMinX3, int lMaxX1, int lMaxX2, int lMaxX3, INodeSet &inodes);
+
+   void findFCCells();
+   void findFCCells(int lMinX1, int lMinX2, int lMinX3, int lMaxX1, int lMaxX2, int lMaxX3, INodeSet &inodes);
+
+   void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3);
+
+   int bMaxX1, bMaxX2, bMaxX3;
+
+   int minX1;
+   int minX2;
+   int minX3;
+
+   int maxX1;
+   int maxX2;
+   int maxX3;
+
+   int minHalfX1;
+   int minHalfX2;
+   int minHalfX3;
+
+   int maxHalfX1;
+   int maxHalfX2;
+   int maxHalfX3;
+};
+
+
+
+#endif 
diff --git a/source/VirtualFluidsCore/Connectors/ConnectorFactory.h b/source/VirtualFluidsCore/Connectors/ConnectorFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ea18fad0b637710f4c111bfdcf350bf964ffd0a
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/ConnectorFactory.h
@@ -0,0 +1,40 @@
+#ifndef ConnectorFactory_h__
+#define ConnectorFactory_h__
+
+#include "Block3DConnector.h"
+#include "TransmitterType.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "FineToCoarseBlock3DConnector.h"
+
+#include <boost/shared_ptr.hpp>
+class ConnectorFactory;
+typedef boost::shared_ptr<ConnectorFactory> ConnectorFactoryPtr;
+
+class ConnectorFactory
+{
+public:
+   ConnectorFactory() {};
+   virtual ~ConnectorFactory() {};
+
+   virtual Block3DConnectorPtr createSameLevelDirectConnector(Block3DPtr from, Block3DPtr to, int sendDir) = 0;
+   virtual Block3DConnectorPtr createSameLevelVectorConnector(Block3DPtr block,
+                                                              VectorTransmitterPtr sender, 
+                                                              VectorTransmitterPtr receiver, 
+                                                              int sendDir) = 0;
+   virtual Block3DConnectorPtr createCoarseToFineConnector(Block3DPtr block,
+                                                            VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+                                                            VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+                                                            VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+                                                            VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+                                                            int sendDir, D3Q27InterpolationProcessorPtr iprocessor) = 0;
+   virtual Block3DConnectorPtr createFineToCoarseConnector(Block3DPtr block, 
+                                                           VectorTransmitterPtr sender, 
+                                                           VectorTransmitterPtr receiver, 
+                                                           int sendDir, 
+                                                           D3Q27InterpolationProcessorPtr iprocessor, 
+                                                           FineToCoarseBlock3DConnector::CFconnectorType connType) = 0;
+
+protected:
+private:
+};
+#endif // ConnectorFactory_h__
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETCFOffVectorConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETCFOffVectorConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..73c14fb6905a5e2b52e993f6e93e0922bd085ce1
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETCFOffVectorConnector.cpp
@@ -0,0 +1 @@
+#include "D3Q27ETCFOffVectorConnector.h"
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETCFOffVectorConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETCFOffVectorConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..588b6bcb3cabbb9626e5b4ed0bd8158f5bb7c3a1
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETCFOffVectorConnector.h
@@ -0,0 +1,1941 @@
+/**
+* @file D3Q27ETCFOffVectorConnector.h
+* @class D3Q27ETCFOffVectorConnector
+* @brief Interpolation from coarse level to fine.
+* @author Kostyantyn Kucher and Ehsan Fard
+* @date 08.06.2011
+*/
+#ifndef D3Q27ETCFOffVectorConnector_H
+#define D3Q27ETCFOffVectorConnector_H
+
+#include <vector>
+
+#include "basics/transmitter/TbTransmitter.h"
+#include "basics/transmitter/TbTransmitterLocal.h"
+#include "basics/container/CbVector.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "MathUtil.hpp"
+#include "Grid3D.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include "D3Q27ETFCVectorConnector.h"
+
+class Block3D;
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+
+//sendrichtung:    E<->W     N<->S    T<->B
+//  ---------       x3       x3        x2
+// | NW | NE |      ^        ^         ^
+// |----+----|      +-> x2   +->x1     +->x1
+// | SW | SE |     
+//  ---------
+// NW==even-odd, SW==even-even, SE==odd-even, NE==odd-odd
+
+template< typename VectorTransmitter >
+class D3Q27ETCFOffVectorConnector : public Block3DConnector
+{
+public:
+	typedef typename VectorTransmitter::value_type  vector_type;
+	typedef boost::shared_ptr< VectorTransmitter > VectorTransmitterPtr;
+public:
+	D3Q27ETCFOffVectorConnector( Block3DPtr block,
+		VectorTransmitterPtr senderEvenEvenSW, VectorTransmitterPtr receiverEvenEvenSW, 
+		VectorTransmitterPtr senderEvenOddNW,  VectorTransmitterPtr receiverEvenOddNW, 
+		VectorTransmitterPtr senderOddEvenSE,  VectorTransmitterPtr receiverOddEvenSE, 
+		VectorTransmitterPtr senderOddOddNE,   VectorTransmitterPtr receiverOddOddNE,
+		int sendDir, D3Q27InterpolationProcessorPtr iprocessor); 
+
+	bool isLocalConnector();
+	bool isRemoteConnector();
+	void init();
+
+	void sendTransmitterDataSize();
+	void receiveTransmitterDataSize();
+
+	void prepareForSend();
+	void sendVectors();
+
+	void prepareForReceive();
+	void receiveVectors();
+
+	void fillSendVectors();
+	void distributeReceiveVectors();
+
+	bool isInterpolationConnectorCF() { return true; }
+	bool isInterpolationConnectorFC() { return false; }
+
+	double getSendRecieveTime();
+
+	void prepareForSendX1() {}
+	void prepareForSendX2() {}
+	void prepareForSendX3() {}
+
+	void sendVectorsX1(){}
+	void sendVectorsX2(){}
+	void sendVectorsX3(){}
+
+	void prepareForReceiveX1() {}
+	void prepareForReceiveX2() {}
+	void prepareForReceiveX3() {}
+
+	void receiveVectorsX1() {}
+	void receiveVectorsX2() {}
+	void receiveVectorsX3() {}
+
+protected:
+	boost::weak_ptr<Block3D> block; //dieser nvd sendet daten und die empfangenen werden diesem nvd zugeordnet
+	VectorTransmitterPtr senderEvenEvenSW, receiverEvenEvenSW, 
+		senderEvenOddNW,  receiverEvenOddNW, 
+		senderOddEvenSE,  receiverOddEvenSE, 
+		senderOddOddNE,   receiverOddOddNE;
+
+	D3Q27InterpolationProcessorPtr iprocessor;
+
+	void writeICellFtoData(vector_type& data, int& index, D3Q27ICell& icellF);
+	void writeNodeToVector(vector_type& data, int& index, LBMReal* inode);
+	void getLocalMinMax(const int& gMin, const int& gMax, const bool& even, int& lMin, int& lMax, const bool& dataDistribution);
+	void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3);
+   void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3, CFconnectorType connType);
+	void fillSendVectorExt(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+
+	void distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+	void readICellCfromData(vector_type& data, int& index, LBMReal* icellC);
+
+   void findCFnodes();
+   void findCFnodes(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+
+	int bMaxX1, bMaxX2, bMaxX3;
+};
+
+////////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+D3Q27ETCFOffVectorConnector<VectorTransmitter>::D3Q27ETCFOffVectorConnector( Block3DPtr block,
+																			VectorTransmitterPtr senderEvenEvenSW, VectorTransmitterPtr receiverEvenEvenSW, 
+																			VectorTransmitterPtr senderEvenOddNW,  VectorTransmitterPtr receiverEvenOddNW, 
+																			VectorTransmitterPtr senderOddEvenSE,  VectorTransmitterPtr receiverOddEvenSE, 
+																			VectorTransmitterPtr senderOddOddNE,   VectorTransmitterPtr receiverOddOddNE,
+																			int sendDir, D3Q27InterpolationProcessorPtr iprocessor) :  Block3DConnector(sendDir)
+																			, block(block)
+																			, senderEvenEvenSW(senderEvenEvenSW)
+																			, senderEvenOddNW(senderEvenOddNW)
+																			, senderOddEvenSE(senderOddEvenSE)
+																			, senderOddOddNE(senderOddOddNE)
+																			, receiverEvenEvenSW(receiverEvenEvenSW)
+																			, receiverEvenOddNW(receiverEvenOddNW)
+																			, receiverOddEvenSE(receiverOddEvenSE)
+																			, receiverOddOddNE(receiverOddOddNE)
+																			, iprocessor(iprocessor)
+{
+	if( !(   sendDir==D3Q27System::E  || sendDir==D3Q27System::W  || sendDir==D3Q27System::N  || sendDir==D3Q27System::S  || sendDir==D3Q27System::T || sendDir==D3Q27System::B 
+         ||  sendDir==D3Q27System::NE || sendDir==D3Q27System::SW || sendDir==D3Q27System::SE || sendDir==D3Q27System::NW
+		   ||  sendDir==D3Q27System::TE || sendDir==D3Q27System::BW || sendDir==D3Q27System::BE || sendDir==D3Q27System::TW
+		   ||  sendDir==D3Q27System::TN || sendDir==D3Q27System::BS || sendDir==D3Q27System::BN || sendDir==D3Q27System::TS
+		   ||  sendDir==D3Q27System::TNE || sendDir==D3Q27System::TNW || sendDir==D3Q27System::TSE || sendDir==D3Q27System::TSW
+		   ||  sendDir==D3Q27System::BNE || sendDir==D3Q27System::BNW || sendDir==D3Q27System::BSE || sendDir==D3Q27System::BSW 
+		) )
+	{
+		throw UbException(UB_EXARGS,"invalid constructor for this direction");
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETCFOffVectorConnector<VectorTransmitter>::isLocalConnector()
+{ 
+	return !this->isRemoteConnector(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETCFOffVectorConnector<VectorTransmitter>::isRemoteConnector() 
+{ 
+	return (   ( senderOddOddNE && senderOddOddNE->isRemoteTransmitter() ) || ( receiverOddOddNE && receiverOddOddNE->isRemoteTransmitter() )
+		|| ( senderEvenEvenSW && senderEvenEvenSW->isRemoteTransmitter() ) || ( receiverEvenEvenSW && receiverEvenEvenSW->isRemoteTransmitter() )
+		|| ( senderEvenOddNW && senderEvenOddNW->isRemoteTransmitter() ) || ( receiverEvenOddNW && receiverEvenOddNW->isRemoteTransmitter() )
+		|| ( senderOddEvenSE && senderOddEvenSE->isRemoteTransmitter() ) || ( receiverOddEvenSE && receiverOddEvenSE->isRemoteTransmitter() ) );
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector<VectorTransmitter>::sendTransmitterDataSize()  
+{ 
+	if(senderEvenEvenSW)
+	{
+		UBLOG(logDEBUG5, "D3Q27ETCFOffVectorConnector<VectorTransmitter>::sendTransmitterDataSize()-senderEvenEvenSW "<<block.lock()->toString()<<" sendDir="<<sendDir);
+		senderEvenEvenSW->sendDataSize(); 
+	}
+	if(senderEvenOddNW)
+	{
+		UBLOG(logDEBUG5, "D3Q27ETCFOffVectorConnector<VectorTransmitter>::sendTransmitterDataSize()-senderEvenOddNW "<<block.lock()->toString()<<"sendDir="<<sendDir);
+		senderEvenOddNW->sendDataSize(); 
+	}
+	if(senderOddEvenSE)
+	{
+		UBLOG(logDEBUG5, "D3Q27ETCFOffVectorConnector<VectorTransmitter>::sendTransmitterDataSize()-senderOddEvenSE "<<block.lock()->toString()+"sendDir="<<sendDir);
+		senderOddEvenSE->sendDataSize(); 
+	}
+	if(senderOddOddNE)
+	{
+		UBLOG(logDEBUG5, "D3Q27ETCFOffVectorConnector<VectorTransmitter>::sendTransmitterDataSize()-senderOddOddNE "<<block.lock()->toString()<<"sendDir="<<sendDir);
+		senderOddOddNE->sendDataSize(); 
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()
+{ 
+	if(receiverEvenEvenSW)
+	{
+		UBLOG(logDEBUG5, "D3Q27ETCFOffVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()-receiverEvenEvenSW "<<block.lock()->toString()<<"sendDir="<<sendDir);
+		receiverEvenEvenSW->receiveDataSize(); 
+	}
+	if(receiverEvenOddNW) 
+	{
+		UBLOG(logDEBUG5, "D3Q27ETCFOffVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()-receiverEvenOddNW "<<block.lock()->toString()<<"sendDir="<<sendDir);
+		receiverEvenOddNW->receiveDataSize(); 
+	}
+	if(receiverOddEvenSE)
+	{
+		UBLOG(logDEBUG5, "D3Q27ETCFOffVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()-receiverOddEvenSE "<<block.lock()->toString()<<"sendDir="<<sendDir);
+		receiverOddEvenSE->receiveDataSize();
+	}
+	if(receiverOddOddNE) 
+	{
+		UBLOG(logDEBUG5, "D3Q27ETCFOffVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()-receiverOddOddNE "<<block.lock()->toString()<<"sendDir="<<sendDir);
+		receiverOddOddNE->receiveDataSize(); 
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector<VectorTransmitter>::prepareForSend()
+{ 
+	if(senderEvenEvenSW) senderEvenEvenSW->prepareForSend(); 
+	if(senderEvenOddNW) senderEvenOddNW->prepareForSend(); 
+	if(senderOddEvenSE) senderOddEvenSE->prepareForSend(); 
+	if(senderOddOddNE) senderOddOddNE->prepareForSend(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector<VectorTransmitter>::sendVectors()     
+{ 
+	if(senderEvenEvenSW) senderEvenEvenSW->sendData();
+	if(senderEvenOddNW) senderEvenOddNW->sendData();
+	if(senderOddEvenSE) senderOddEvenSE->sendData();
+	if(senderOddOddNE) senderOddOddNE->sendData();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector<VectorTransmitter>::prepareForReceive()     
+{ 
+	if(receiverEvenEvenSW) receiverEvenEvenSW->prepareForReceive(); 
+	if(receiverEvenOddNW) receiverEvenOddNW->prepareForReceive(); 
+	if(receiverOddEvenSE) receiverOddEvenSE->prepareForReceive(); 
+	if(receiverOddOddNE) receiverOddOddNE->prepareForReceive(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector<VectorTransmitter>::receiveVectors() 
+{ 
+	if(receiverEvenEvenSW) receiverEvenEvenSW->receiveData(); 
+	if(receiverEvenOddNW) receiverEvenOddNW->receiveData();  
+	if(receiverOddEvenSE) receiverOddEvenSE->receiveData(); 
+	if(receiverOddOddNE) receiverOddOddNE->receiveData(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector<VectorTransmitter>::init()
+{
+	using namespace D3Q27System;
+
+	bMaxX1 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1();
+	bMaxX2 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2();
+	bMaxX3 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3();
+
+	int       sendSize  = 0;
+	LBMReal initValue = -999.0;
+
+	int sendDataPerNode = 27/*f*/;
+	int iCellSize = 8; //size of interpolation cell
+
+	switch(this->sendDir)
+	{		                  
+	case E : case W : sendSize = bMaxX2*bMaxX3*sendDataPerNode*iCellSize; break; 
+	case N : case S : sendSize = bMaxX1*bMaxX3*sendDataPerNode*iCellSize; break; 
+	case T : case B : sendSize = bMaxX1*bMaxX2*sendDataPerNode*iCellSize; break; 		  
+   case NE : case SW :case SE : case NW : sendSize = 2*bMaxX3*sendDataPerNode*iCellSize; break; 		
+   case TE : case BW :case BE : case TW : sendSize = 2*bMaxX2*sendDataPerNode*iCellSize; break; 
+   case TN : case BS :case BN : case TS : sendSize = 2*bMaxX1*sendDataPerNode*iCellSize; break;	
+   case TNE: case TNW:case TSE: case TSW:case BNE: case BNW:case BSE: case BSW: sendSize = 6*bMaxX1*sendDataPerNode*iCellSize; break;
+	default: throw UbException(UB_EXARGS,"direction not allowed in this constructor");
+	}
+	if(senderEvenEvenSW) senderEvenEvenSW->getData().resize(sendSize, initValue);
+	else senderEvenEvenSW = VectorTransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+	if(senderEvenOddNW)  senderEvenOddNW->getData().resize(sendSize, initValue);
+	else senderEvenOddNW = VectorTransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+	if(senderOddEvenSE)  senderOddEvenSE->getData().resize(sendSize, initValue);
+	else senderOddEvenSE = VectorTransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+	if(senderOddOddNE)   senderOddOddNE->getData().resize(sendSize, initValue);
+	else senderOddOddNE = VectorTransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+
+	if(!receiverEvenEvenSW) receiverEvenEvenSW = VectorTransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+	if(!receiverEvenOddNW)  receiverEvenOddNW = VectorTransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+	if(!receiverOddEvenSE)  receiverOddEvenSE = VectorTransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+	if(!receiverOddOddNE)   receiverOddOddNE = VectorTransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+
+   //findCFnodes();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::fillSendVectors() 
+{ 
+	using namespace D3Q27System;
+
+	DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+	int maxX1 = (int)fFrom->getNX1();
+	int maxX2 = (int)fFrom->getNX2();
+	int maxX3 = (int)fFrom->getNX3();
+	int minX1 = 0;
+	int minX2 = 0;
+	int minX3 = 0;
+
+	int indexEvEv = 0;
+	int indexEvOd = 0;
+	int indexOdEv = 0;
+	int indexOdOd = 0;
+
+	vector_type& dataEvEv = this->senderEvenEvenSW->getData();
+	vector_type& dataEvOd = this->senderEvenOddNW->getData();
+	vector_type& dataOdEv = this->senderOddEvenSE->getData();
+	vector_type& dataOdOd = this->senderOddOddNE->getData();
+
+	int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+	//int lMinX1_2, lMinX2_2, lMinX3_2, lMaxX1_2, lMaxX2_2, lMaxX3_2;
+
+   //for coners
+   int lMinX1W = 1;
+   int lMaxX1W = 2;
+
+   int lMinX1E = maxX1-3;
+   int lMaxX1E = maxX1-2;
+
+   int lMinX2S = 1;
+   int lMaxX2S = 2;
+
+   int lMinX2N = maxX2-3;
+   int lMaxX2N = maxX2-2;
+
+   int lMinX3B = 1;
+   int lMaxX3B = 2;
+
+   int lMinX3T = maxX3-3;
+   int lMaxX3T = maxX3-2;
+   
+
+	switch(sendDir)
+	{
+	case E: 
+		lMinX1 = maxX1-3;
+		lMaxX1 = lMinX1 + 1;
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case W:
+      ///////////////////////////////////////
+      ///DEBUG
+      //if (block.lock()->getGlobalID() == 5780)
+      //{
+      //   int test = 0;
+      //}
+      //////////////
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 1;
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case N:
+		lMinX2 = maxX2-3;
+		lMaxX2 = lMinX2 + 1;
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case S:
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 1;
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case T:
+		lMinX3 = maxX3-3;
+		lMaxX3 = lMinX3 + 1;
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case B:
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 1;
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+///N-S-E-W
+	case NE: 
+		lMinX1 = maxX1-3;
+		lMaxX1 = lMinX1 + 2;
+		lMinX2 = maxX2-3;
+		lMaxX2 = lMinX2 + 2;
+	
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      break;
+
+	case SW: 
+		lMinX1 = 0;
+		lMaxX1 = lMinX1 + 2;
+		lMinX2 = 0;
+		lMaxX2 = lMinX2 + 2;
+
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+		
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case SE: 
+		lMinX1 = maxX1-3;
+		lMaxX1 = lMinX1 + 2;
+		lMinX2 = 0;
+		lMaxX2 = lMinX2 + 2;
+
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case NW: 
+		lMinX1 = 0;
+		lMaxX1 = lMinX1 + 2;
+		lMinX2 = maxX2-3;
+		lMaxX2 = lMinX2 + 2;
+
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      break;
+/////T-B-E-W
+	case TE:
+		lMinX1 = maxX1-3;
+		lMaxX1 = lMinX1 + 2;
+		lMinX3 = maxX3-3;
+		lMaxX3 = lMinX3 + 2;
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case BW:
+		lMinX1 = 0;
+		lMaxX1 = lMinX1 + 2;
+		lMinX3 = 0;
+		lMaxX3 = lMinX3 + 2;
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      break;
+
+	case BE:
+		lMinX1 = maxX1-3;
+		lMaxX1 = lMinX1 + 2;
+		lMinX3 = 0;
+		lMaxX3 = lMinX3 + 2;
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case TW:
+		lMinX1 = 0;
+		lMaxX1 = lMinX1 + 2;
+		lMinX3 = maxX3-3;
+		lMaxX3 = lMinX3 + 2;
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+////
+/////T-B-N-S
+	case TN:
+		lMinX2 = maxX2-3;
+		lMaxX2 = lMinX2 + 2;
+		lMinX3 = maxX3-3;
+		lMaxX3 = lMinX3 + 2;
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case BS:
+		lMinX2 = 0;
+		lMaxX2 = lMinX2 + 2;
+		lMinX3 = 0;
+		lMaxX3 = lMinX3 + 2;
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case BN:
+		lMinX2 = maxX2-3;
+		lMaxX2 = lMinX2 + 2;
+		lMinX3 = 0;
+		lMaxX3 = lMinX3 + 2;
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case TS:
+		lMinX2 = 0;
+		lMaxX2 = lMinX2 + 2;
+		lMinX3 = maxX3-3;
+		lMaxX3 = lMinX3 + 2;
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+		fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+
+      //TNE
+   case TNE:
+      lMinX1 = maxX1-3;
+      lMaxX1 = maxX1-1;
+      lMinX2 = maxX2-3;
+      lMaxX2 = maxX2-1;
+      lMinX3 = maxX3-3;
+      lMaxX3 = maxX3-1;
+
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   TNW
+   case TNW:
+      lMinX1 = 0;
+      lMaxX1 = 2;
+      lMinX2 = maxX2-3;
+      lMaxX2 = maxX2-1;
+      lMinX3 = maxX3-3;
+      lMaxX3 = maxX3-1;
+
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   TSE
+   case TSE:
+      lMinX1 = maxX1-3;
+      lMaxX1 = maxX1-1;
+      lMinX2 = 0;
+      lMaxX2 = 2;
+      lMinX3 = maxX3-3;
+      lMaxX3 = maxX3-1;
+
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   TSW
+   case TSW:
+      lMinX1 = 0;
+      lMaxX1 = 2;
+      lMinX2 = 0;
+      lMaxX2 = 2;
+      lMinX3 = maxX3-3;
+      lMaxX3 = maxX3-1;
+
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   BNE
+   case BNE:
+      lMinX1 = maxX1-3;
+      lMaxX1 = maxX1-1;
+      lMinX2 = maxX2-3;
+      lMaxX2 = maxX2-1;
+      lMinX3 = 0;
+      lMaxX3 = 2;
+
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   BNW
+   case BNW:
+      lMinX1 = 0;
+      lMaxX1 = 2;
+      lMinX2 = maxX2-3;
+      lMaxX2 = maxX2-1;
+      lMinX3 = 0;
+      lMaxX3 = 2;
+
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   BSE
+   case BSE:
+      lMinX1 = maxX1-3;
+      lMaxX1 = maxX1-1;
+      lMinX2 = 0;
+      lMaxX2 = 2;
+      lMinX3 = 0;
+      lMaxX3 = 2;
+
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   BSW
+   case BSW:
+      lMinX1 = 0;
+      lMaxX1 = 2;
+      lMinX2 = 0;
+      lMaxX2 = 2;
+      lMinX3 = 0;
+      lMaxX3 = 2;
+
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::getLocalMinMax(const int& gMin, const int& gMax, const bool& even, int& lMin, int& lMax, const bool& dataDistribution)
+{
+	int halfEven = 0;
+	int halfOdd = 0;
+	int dCoef = 0;
+
+	if (dataDistribution)
+		dCoef = 1;
+
+	if (Utilities::isOdd(gMax))
+	{
+		halfEven = gMax/2;
+		halfOdd =  gMax/2;
+	}
+	if (Utilities::isEven(gMax))
+	{
+		halfEven = gMax/2;
+		halfOdd =  gMax/2 - 1 + dCoef;
+	}
+
+	switch (even)
+	{
+	case true :
+		lMin = gMin + dCoef;
+		lMax = lMin + halfEven - dCoef;
+		break;
+	case false :
+		lMin = gMin + halfOdd;
+		lMax = gMax-1;
+		break;
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::fillSendVectorExt(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+	if(data.size() == 0) return;
+	int ix1, ix2, ix3;
+	LBMReal xoff, yoff, zoff;
+	BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(block.lock()->getKernel()->getBCProcessor())->getBCArray();
+
+	for (ix3=lMinX3; ix3<lMaxX3; ix3++)
+	{
+		for (ix2=lMinX2; ix2<lMaxX2; ix2++)
+		{
+			for (ix1=lMinX1; ix1<lMaxX1; ix1++)
+			{
+				D3Q27ICell icellC;
+				D3Q27ICell icellF;
+
+				int howManySolids= iprocessor->iCellHowManySolids(bcArray, ix1, ix2, ix3);
+
+				if(howManySolids == 0 || howManySolids == 8)
+				{
+					iprocessor->readICell(fFrom, icellC, ix1, ix2, ix3);
+					xoff=0.0; 
+					yoff=0.0;
+					zoff=0.0;
+				}
+				else
+				{
+					if(!iprocessor->findNeighborICell(bcArray, fFrom, icellC, bMaxX1, bMaxX2, bMaxX3, ix1, ix2, ix3, xoff, yoff, zoff))
+					{
+						std::string err = "For "+block.lock()->toString()+" x1="+UbSystem::toString(ix1)+", x2=" + UbSystem::toString(ix2)+", x3=" + UbSystem::toString(ix3)+
+							" interpolation is not implemented for other direction"+
+							" by using in: "+(std::string)typeid(*this).name()+ 
+							" or maybe you have a solid on the block boundary";
+						UB_THROW(UbException(UB_EXARGS, err));
+					}
+				}
+
+				iprocessor->interpolateCoarseToFine(icellC, icellF, xoff, yoff, zoff);
+				this->writeICellFtoData(data, index, icellF);
+			}
+		}
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::writeICellFtoData(vector_type& data, int& index, D3Q27ICell& icellF) 
+{
+	writeNodeToVector(data, index, icellF.BSW);
+	writeNodeToVector(data, index, icellF.BSE);
+	writeNodeToVector(data, index, icellF.BNW);
+	writeNodeToVector(data, index, icellF.BNE);
+	writeNodeToVector(data, index, icellF.TSW);
+	writeNodeToVector(data, index, icellF.TSE);
+	writeNodeToVector(data, index, icellF.TNW);
+	writeNodeToVector(data, index, icellF.TNE);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::writeNodeToVector(vector_type& data, int& index, LBMReal* inode)
+{
+	for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+	{
+		data[index++] = inode[i];
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::distributeReceiveVectors() 
+{
+	using namespace D3Q27System;
+
+	DistributionArray3DPtr  fTo = block.lock()->getKernel()->getDataSet()->getFdistributions();
+	int maxX1 = (int)fTo->getNX1();
+	int maxX2 = (int)fTo->getNX2();
+	int maxX3 = (int)fTo->getNX3();
+	int minX1 = 0;
+	int minX2 = 0;
+	int minX3 = 0;
+
+	int indexEvEv = 0;
+	int indexEvOd = 0;
+	int indexOdEv = 0;
+	int indexOdOd = 0;
+
+	vector_type& dataEvEv = this->receiverEvenEvenSW->getData();
+	vector_type& dataEvOd = this->receiverEvenOddNW->getData();
+	vector_type& dataOdEv = this->receiverOddEvenSE->getData();
+	vector_type& dataOdOd = this->receiverOddOddNE->getData();
+
+	int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+	int dummy;
+
+   //for coners
+   int lMinX1W = 3;
+   int lMaxX1W = 3;
+
+   int lMinX1E = maxX1-3;
+   int lMaxX1E = maxX1-2;
+
+   int lMinX2S = 1;
+   int lMaxX2S = 3;
+
+   int lMinX2N = maxX2-3;
+   int lMaxX2N = maxX2-2;
+
+   int lMinX3B = 1;
+   int lMaxX3B = 3;
+
+   int lMinX3T = maxX3-3;
+   int lMaxX3T = maxX3-2;
+
+   ///////////////////////////////////////
+   ///DEBUG
+   //if (block.lock()->getGlobalID() == 5780)
+   //{
+   //   int test = 0;
+   //}
+   //////////////
+
+	switch(sendDir)
+	{
+	case E: 
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 1;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, lMinX2, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, lMaxX2, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case W:
+      ///////////////////////////////////////
+      ///DEBUG
+      //if (block.lock()->getGlobalID() == 5780)
+      //{
+      //   int test = 0;
+      //}
+      //////////////
+		lMinX1 = 3;
+		lMaxX1 = lMinX1 + 1;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, lMinX2, lMinX3, dummy, dummy, dummy, none);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, lMaxX3, none);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, lMaxX2, dummy, none);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, lMaxX3, none);
+ 		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case N:
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 1;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(lMinX1, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, lMaxX1, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case S:
+		lMinX2 = 3;
+		lMaxX2 = lMinX2 + 1;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(lMinX1, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, lMaxX1, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case T:
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(lMinX1, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, lMaxX2, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, lMaxX1, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, dummy, dummy, lMaxX1, lMaxX2, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+	case B:
+		lMinX3 = 3;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(lMinX1, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, lMaxX2, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, lMaxX1, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+		getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, dummy, dummy, lMaxX1, lMaxX2, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+		break;
+
+	//	/////E-W-N-S
+	case NE: 
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 3;
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 1;
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 1;
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 3;
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case SW: 
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 3;
+		lMinX2 = 3;
+		lMaxX2 = lMinX2 + 1;
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+	   lMinX1 = 3;
+		lMaxX1 = lMinX1 + 1;
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 3;
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+	
+	case SE: 
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 3;
+		lMinX2 = 3;
+		lMaxX2 = lMinX2 + 1;
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 1;
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 3;
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case NW: 
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 3;
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 1;
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX1 = 3;
+		lMaxX1 = lMinX1 + 1;
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 3;
+		getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, lMinX3, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+		getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+		getLocalMinMax(dummy, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+//		/////T-B-E-W
+	case TE: 
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 3;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 1;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case BW: 
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 3;
+		lMinX3 = 3;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX1 = 3;
+		lMaxX1 = lMinX1 + 1;
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case BE: 
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 3;
+		lMinX3 = 3;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 1;
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case TW: 
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 3;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX1 = 3;
+		lMaxX1 = lMinX1 + 1;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+		getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+/////////////////////////T-N-B-S
+	case TN:
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 3;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 1;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case BS:
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 3;
+		lMinX3 = 3;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX2 = 3;
+		lMaxX2 = lMinX2 + 1;
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+	
+	
+	case BN:
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 3;
+		lMinX3 = 3;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 1;
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+	case TS:
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 3;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		lMinX2 = 3;
+		lMaxX2 = lMinX2 + 1;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+		getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, dummy);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+		break;
+
+      //TNE
+   case TNE:
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-3;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-3;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-3;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      break;
+      //   TNW
+   case TNW:
+      lMinX1 = 3;
+      lMaxX1 = 4;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = 1;
+      lMaxX1 = 4;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-3;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = 1;
+      lMaxX1 = 4;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-3;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      break;
+      //   TSE
+   case TSE:
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-3;
+      lMinX2 = 1;
+      lMaxX2 = 4;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = 3;
+      lMaxX2 = 4;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = 1;
+      lMaxX2 = 4;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-3;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   TSW
+   case TSW:
+      lMinX1 = 3;
+      lMaxX1 = 4;
+      lMinX2 = 1;
+      lMaxX2 = 4;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = 1;
+      lMaxX1 = 4;
+      lMinX2 = 3;
+      lMaxX2 = 4;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = 1;
+      lMaxX1 = 4;
+      lMinX2 = 1;
+      lMaxX2 = 4;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-3;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   BNE
+   case BNE:
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-3;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = 1;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-3;
+      lMinX3 = 1;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = 3;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      break;
+      //   BNW
+   case BNW:
+      lMinX1 = 3;
+      lMaxX1 = 4;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = 1;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = 1;
+      lMaxX1 = 4;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-3;
+      lMinX3 = 1;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = 1;
+      lMaxX1 = 4;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = 3;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   BSE
+   case BSE:
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-3;
+      lMinX2 = 1;
+      lMaxX2 = 4;
+      lMinX3 = 1;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = 3;
+      lMaxX2 = 4;
+      lMinX3 = 1;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = 1;
+      lMaxX2 = 4;
+      lMinX3 = 3;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+      break;
+      //   BSW
+   case BSW:
+      lMinX1 = 3;
+      lMaxX1 = 4;
+      lMinX2 = 1;
+      lMaxX2 = 4;
+      lMinX3 = 1;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = 1;
+      lMaxX1 = 4;
+      lMinX2 = 3;
+      lMaxX2 = 4;
+      lMinX3 = 1;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      lMinX1 = 1;
+      lMaxX1 = 4;
+      lMinX2 = 1;
+      lMaxX2 = 4;
+      lMinX3 = 3;
+      lMaxX3 = 4;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      break;
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+	if(data.size() == 0) return;
+
+	int ix1, ix2, ix3;
+	for (ix3=lMinX3; ix3<lMaxX3; ix3++)
+	{
+		for (ix2=lMinX2; ix2<lMaxX2; ix2++)
+		{
+			for (ix1=lMinX1; ix1<lMaxX1; ix1++)
+			{
+				LBMReal icellC[27];
+				this->readICellCfromData(data, index, icellC);
+				iprocessor->writeINode(fTo, icellC, ix1, ix2, ix3);
+			}
+		}
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::readICellCfromData(vector_type& data, int& index, LBMReal* icellC) 
+{
+	for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+	{
+		icellC[i] = data[index++];
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3)
+{
+	using namespace D3Q27System;
+	int TminX1=minX1; int TminX2=minX2; int TminX3=minX3; int TmaxX1=maxX1; int TmaxX2=maxX2; int TmaxX3=maxX3;
+
+	if(block.lock()->hasInterpolationFlagCF(E))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 2;	
+	}
+	 if(block.lock()->hasInterpolationFlagCF(W))
+	{
+		if (minX1==TminX1) minX1 += 2;	
+	}
+	 if(block.lock()->hasInterpolationFlagCF(N))
+	{
+		if (maxX2==TmaxX2)  maxX2 -= 2;  
+	}
+	 if(block.lock()->hasInterpolationFlagCF(S))
+	{
+		if (minX2==TminX2)  minX2 += 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(T))
+	{
+		if (maxX3==TmaxX3)  maxX3 -= 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(B))
+	{
+		if (minX3==TminX3)  minX3 += 2;
+	}
+
+	//E-W-N-S
+	 if(block.lock()->hasInterpolationFlagCF(NE) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(E))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 2;
+		if (maxX2==TmaxX2) maxX2 -= 2;
+	}
+	if( block.lock()->hasInterpolationFlagCF(SW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(S))
+	{
+		if (minX1==TminX1) minX1 += 2;
+		if (minX2==TminX2) minX2 += 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(SE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(S))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 2;
+		if (minX2==TminX2) minX2 += 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(NW) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(W))
+	{
+		if (minX1==TminX1) minX1 += 2;
+		if (maxX2==TmaxX2) maxX2 -= 2;
+	}
+	
+//	////T-B-E-W
+	 if(block.lock()->hasInterpolationFlagCF(TE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(T))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 2;
+		if (maxX3==TmaxX3) maxX3 -= 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(BW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(B))
+	{
+		if (minX1==TminX1) minX1 += 2;
+		if (minX3==TminX3) minX3 += 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(BE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(B))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 2;
+		if (minX3==TminX3) minX3 += 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(TW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(T))
+	{
+		if (minX1==TminX1) minX1 += 2;
+		if (maxX3==TmaxX3) maxX3 -= 2;
+	}
+
+
+	////T-B-N-S
+    if (block.lock()->hasInterpolationFlagCF(TN) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(T))
+	{
+		if (maxX2==TmaxX2) maxX2 -= 2; 
+		if (maxX3==TmaxX3) maxX3 -= 2;
+	}
+    if (block.lock()->hasInterpolationFlagCF(BS) && !block.lock()->hasInterpolationFlagCF(S) && !block.lock()->hasInterpolationFlagCF(B))
+	{
+		if (minX2==TminX2) minX2 += 2;
+		if (minX3==TminX3) minX3 += 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(BN) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(B))
+	{
+		if (maxX2==TmaxX2) maxX2 -= 2; 
+		if (minX3==TminX3) minX3 += 2;
+	}
+	 if(block.lock()->hasInterpolationFlagCF(TS) && !block.lock()->hasInterpolationFlagCF(S) && !block.lock()->hasInterpolationFlagCF(T))
+	{
+		if (minX2==TminX2) minX2 += 2;
+		if (maxX3==TmaxX3) maxX3 -= 2;
+	}
+
+    //if (block.lock()->hasInterpolationFlagCF(D3Q27System::TNE)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::TE)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::TN)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::NE)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::T)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::N) && !block.lock()->hasInterpolationFlagCF(D3Q27System::E))
+    //if (!block.lock()->hasInterpolationFlagCF(D3Q27System::TE)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::T)&& !block.lock()->hasInterpolationFlagCF(D3Q27System::E))
+    //{
+    //   if (maxX1==TmaxX1) maxX1 -= 2;
+    //   if (maxX2==TmaxX2) maxX2 -= 2;
+    //   if (maxX3==TmaxX3) maxX3 -= 2;
+    //}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3, CFconnectorType connType)
+{
+   using namespace D3Q27System;
+   int TminX1 = minX1; int TminX2 = minX2; int TminX3 = minX3; int TmaxX1 = maxX1; int TmaxX2 = maxX2; int TmaxX3 = maxX3;
+
+   if (block.lock()->hasInterpolationFlagCF(E))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(W))
+   {
+      if (minX1==TminX1) minX1 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(N))
+   {
+      if (maxX2==TmaxX2)  maxX2 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(S))
+   {
+      if (minX2==TminX2)  minX2 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (maxX3==TmaxX3)  maxX3 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (minX3==TminX3)  minX3 += 2;
+   }
+
+   //E-W-N-S
+   if (block.lock()->hasInterpolationFlagCF(NE) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(E))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+      if (maxX2==TmaxX2) maxX2 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(SW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(S))
+   {
+      if (minX1==TminX1) minX1 += 2;
+      if (minX2==TminX2) minX2 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(SE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(S))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+      if (minX2==TminX2) minX2 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(NW) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(W))
+   {
+      if (minX1==TminX1) minX1 += 2;
+      if (maxX2==TmaxX2) maxX2 -= 2;
+   }
+
+   //	////T-B-E-W
+   if (block.lock()->hasInterpolationFlagCF(TE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+      if (maxX3==TmaxX3) maxX3 -= 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(BW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (minX1==TminX1) minX1 += 2;
+      if (minX3==TminX3) minX3 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(BE) && !block.lock()->hasInterpolationFlagCF(E) && !block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 2;
+      if (minX3==TminX3) minX3 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(TW) && !block.lock()->hasInterpolationFlagCF(W) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (minX1==TminX1) minX1 += 2;
+      if (maxX3==TmaxX3) maxX3 -= 2;
+   }
+
+
+   ////T-B-N-S
+   if (block.lock()->hasInterpolationFlagCF(TN) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      if(connType != none)
+      {
+	      if (maxX2==TmaxX2) maxX2 -= 2;
+	      if (maxX3==TmaxX3) maxX3 -= 2;
+      }
+   }
+   if (block.lock()->hasInterpolationFlagCF(BS) && !block.lock()->hasInterpolationFlagCF(S) && !block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (minX2==TminX2) minX2 += 2;
+      if (minX3==TminX3) minX3 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(BN) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(B))
+   {
+      if (maxX2==TmaxX2) maxX2 -= 2;
+      if (minX3==TminX3) minX3 += 2;
+   }
+   if (block.lock()->hasInterpolationFlagCF(TS) && !block.lock()->hasInterpolationFlagCF(S) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      if (minX2==TminX2) minX2 += 2;
+      if (maxX3==TmaxX3) maxX3 -= 2;
+   }
+
+   //if (block.lock()->hasInterpolationFlagCF(D3Q27System::TNE)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::TE)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::TN)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::NE)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::T)&&!block.lock()->hasInterpolationFlagCF(D3Q27System::N) && !block.lock()->hasInterpolationFlagCF(D3Q27System::E))
+   //{
+   //   if (maxX1==TmaxX1) maxX1 -= 2;
+   //   if (maxX2==TmaxX2) maxX2 -= 2;
+   //   if (maxX3==TmaxX3) maxX3 -= 2;
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::findCFnodes()
+{
+   DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fFrom->getNX1();
+   int maxX2 = (int)fFrom->getNX2();
+   int maxX3 = (int)fFrom->getNX3();
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int indexEvEv = 0;
+   int indexEvOd = 0;
+   int indexOdEv = 0;
+   int indexOdOd = 0;
+
+   vector_type& dataEvEv = this->senderEvenEvenSW->getData();
+   vector_type& dataEvOd = this->senderEvenOddNW->getData();
+   vector_type& dataOdEv = this->senderOddEvenSE->getData();
+   vector_type& dataOdOd = this->senderOddOddNE->getData();
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+   
+   using namespace D3Q27System;
+   if (block.lock()->hasInterpolationFlagCF(W))
+   {
+      lMinX1 = 1;
+      lMaxX1 = lMinX1 + 1;
+
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      findCFnodes(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      findCFnodes(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      findCFnodes(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      findCFnodes(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+   }
+   if (block.lock()->hasInterpolationFlagCF(TN) && !block.lock()->hasInterpolationFlagCF(N) && !block.lock()->hasInterpolationFlagCF(T))
+   {
+      lMinX2 = maxX2-3;
+      lMaxX2 = lMinX2 + 1;
+      lMinX3 = maxX3-3;
+      lMaxX3 = lMinX3 + 1;
+
+      getLocalMinMax(minX1+1, maxX1, true, lMinX1, lMaxX1, false);
+      findCFnodes(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1+1, maxX1, false, lMinX1, lMaxX1, false);
+      findCFnodes(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  >
+void D3Q27ETCFOffVectorConnector< VectorTransmitter>::findCFnodes(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+   if (data.size() == 0) return;
+   int ix1, ix2, ix3;
+   LBMReal xoff, yoff, zoff;
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(block.lock()->getKernel()->getBCProcessor())->getBCArray();
+
+   for (ix3 = lMinX3; ix3<lMaxX3; ix3++)
+   {
+      for (ix2 = lMinX2; ix2<lMaxX2; ix2++)
+      {
+         for (ix1 = lMinX1; ix1<lMaxX1; ix1++)
+         {
+            D3Q27ICell icellC;
+            D3Q27ICell icellF;
+
+            int howManySolids = iprocessor->iCellHowManySolids(bcArray, ix1, ix2, ix3);
+
+            if (howManySolids == 0 || howManySolids == 8)
+            {
+               iprocessor->readICell(fFrom, icellC, ix1, ix2, ix3);
+               xoff = 0.0;
+               yoff = 0.0;
+               zoff = 0.0;
+            }
+            else
+            {
+               if (!iprocessor->findNeighborICell(bcArray, fFrom, icellC, bMaxX1, bMaxX2, bMaxX3, ix1, ix2, ix3, xoff, yoff, zoff))
+               {
+                  std::string err = "For "+block.lock()->toString()+" x1="+UbSystem::toString(ix1)+", x2=" + UbSystem::toString(ix2)+", x3=" + UbSystem::toString(ix3)+
+                     " interpolation is not implemented for other direction"+
+                     " by using in: "+(std::string)typeid(*this).name()+
+                     " or maybe you have a solid on the block boundary";
+                  UB_THROW(UbException(UB_EXARGS, err));
+               }
+            }
+
+            iprocessor->interpolateCoarseToFine(icellC, icellF, xoff, yoff, zoff);
+            this->writeICellFtoData(data, index, icellF);
+            //for (int iix3 = ix3; iix3<=ix3+1; iix3++)
+            //{
+            //   for (int iix2 = ix2; iix2<=ix2+1; iix2++)
+            //   {
+            //      for (int iix1 = ix1; iix1<=ix1+1; iix1++)
+            //      {
+            //         bcArray.setInterfaceCF(iix1, iix2, iix3);
+            //      }
+            //   }
+            //}
+
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+double D3Q27ETCFOffVectorConnector<VectorTransmitter>::getSendRecieveTime()
+{
+	return 0;
+}
+
+#endif 
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETCFVectorConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETCFVectorConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5e24d5d7a1aa882c559e28b43cca2746b22eaa0d
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETCFVectorConnector.cpp
@@ -0,0 +1 @@
+#include "D3Q27ETCFVectorConnector.h"
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETCFVectorConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETCFVectorConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..baffa59f726b1d399f10148b3c53e16a921c3a28
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETCFVectorConnector.h
@@ -0,0 +1,707 @@
+/**
+* @file D3Q27ETCFVectorConnector.h
+* @brief Interpolation from coarse level to fine.
+* @author Kostyantyn Kucher
+* @date 08.06.2011
+*/
+#ifndef D3Q27ETCFVECTORCONNECTOR_H
+#define D3Q27ETCFVECTORCONNECTOR_H
+
+#include <vector>
+
+#include "basics/transmitter/TbTransmitter.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "MathUtil.hpp"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+class Block3D;
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+
+//sendrichtung:    E<->W     N<->S    T<->B
+//  ---------       x3       x3        x2
+// | NW | NE |      ^        ^         ^
+// |----+----|      +-> x2   +->x1     +->x1
+// | SW | SE |     
+//  ---------
+// NW==even-odd, SW==even-even, SE==odd-even, NE==odd-odd
+
+template< typename VectorTransmitter >
+class D3Q27ETCFVectorConnector : public Block3DConnector
+{
+protected:
+   typedef typename VectorTransmitter::value_type  vector_type;
+   typedef boost::shared_ptr< VectorTransmitter > VectorTransmitterPtr;
+public:
+   D3Q27ETCFVectorConnector(  Block3DPtr block,
+      VectorTransmitterPtr senderEvenEvenSW, VectorTransmitterPtr receiverEvenEvenSW, 
+      VectorTransmitterPtr senderEvenOddNW,  VectorTransmitterPtr receiverEvenOddNW, 
+      VectorTransmitterPtr senderOddEvenSE,  VectorTransmitterPtr receiverOddEvenSE, 
+      VectorTransmitterPtr senderOddOddNE,   VectorTransmitterPtr receiverOddOddNE,
+      int sendDir, D3Q27InterpolationProcessorPtr iprocessor); 
+
+   bool isLocalConnector();
+   bool isRemoteConnector();
+   void init();
+
+   void sendTransmitterDataSize();
+   void receiveTransmitterDataSize();
+
+   void prepareForSend();
+   void sendVectors();
+
+   void prepareForReceive();
+   void receiveVectors();
+
+   void fillSendVectors();
+   void distributeReceiveVectors();
+
+   bool isInterpolationConnectorCF() { return true; }
+   bool isInterpolationConnectorFC() { return false; }
+
+   double getSendRecieveTime();
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1(){}
+   void sendVectorsX2(){}
+   void sendVectorsX3(){}
+   
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> block; //dieser nvd sendet daten und die empfangenen werden diesem nvd zugeordnet
+
+   VectorTransmitterPtr senderEvenEvenSW, receiverEvenEvenSW, 
+                        senderEvenOddNW,  receiverEvenOddNW, 
+                        senderOddEvenSE,  receiverOddEvenSE, 
+                        senderOddOddNE,   receiverOddOddNE;
+   
+   D3Q27InterpolationProcessorPtr iprocessor;
+
+   void readICellC(DistributionArray3DPtr f, D3Q27ICell& icellC, const int& x1, const int& x2, const int& x3) ;
+   void writeICellFtoData(vector_type& data, int& index, D3Q27ICell& icellF);
+   void writeNodeToVector(vector_type& data, int& index, LBMReal* inode);
+   void getLocalMinMax(const int& gMin, const int& gMax, const bool& even, int& lMin, int& lMax, const bool& dataDistribution);
+   void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3);
+   void fillSendVectorExt(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+
+   void distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+   void writeICellC(DistributionArray3DPtr f, LBMReal* icellC, const int& x1, const int& x2, const int& x3);
+   void readICellCfromData(vector_type& data, int& index, LBMReal* icellC);
+};
+
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+D3Q27ETCFVectorConnector<VectorTransmitter>::D3Q27ETCFVectorConnector(  Block3DPtr block,
+                         VectorTransmitterPtr senderEvenEvenSW, VectorTransmitterPtr receiverEvenEvenSW, 
+                         VectorTransmitterPtr senderEvenOddNW,  VectorTransmitterPtr receiverEvenOddNW, 
+                         VectorTransmitterPtr senderOddEvenSE,  VectorTransmitterPtr receiverOddEvenSE, 
+                         VectorTransmitterPtr senderOddOddNE,   VectorTransmitterPtr receiverOddOddNE,
+                         int sendDir, D3Q27InterpolationProcessorPtr iprocessor) :  Block3DConnector(sendDir)
+                         , block(block)
+                         , senderEvenEvenSW(senderEvenEvenSW)
+                         , senderEvenOddNW(senderEvenOddNW)
+                         , senderOddEvenSE(senderOddEvenSE)
+                         , senderOddOddNE(senderOddOddNE)
+                         , receiverEvenEvenSW(receiverEvenEvenSW)
+                         , receiverEvenOddNW(receiverEvenOddNW)
+                         , receiverOddEvenSE(receiverOddEvenSE)
+                         , receiverOddOddNE(receiverOddOddNE)
+                         , iprocessor(iprocessor)
+{
+   if( !(   sendDir==D3Q27System::E || sendDir==D3Q27System::W || sendDir==D3Q27System::N 
+      || sendDir==D3Q27System::S || sendDir==D3Q27System::T || sendDir==D3Q27System::B ) )
+   {
+      throw UbException(UB_EXARGS,"invalid constructor for this direction");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETCFVectorConnector<VectorTransmitter>::isLocalConnector()
+{ 
+   return !this->isRemoteConnector(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETCFVectorConnector<VectorTransmitter>::isRemoteConnector() 
+{ 
+   return (   ( senderOddOddNE && senderOddOddNE->isRemoteTransmitter() ) ||  ( receiverOddOddNE && receiverOddOddNE->isRemoteTransmitter() )
+      || ( senderEvenEvenSW && senderEvenEvenSW->isRemoteTransmitter() ) ||  ( receiverEvenEvenSW && receiverEvenEvenSW->isRemoteTransmitter() )
+      || ( senderEvenOddNW && senderEvenOddNW->isRemoteTransmitter() ) ||  ( receiverEvenOddNW && receiverEvenOddNW->isRemoteTransmitter() )
+      || ( senderOddEvenSE && senderOddEvenSE->isRemoteTransmitter() ) ||  ( receiverOddEvenSE && receiverOddEvenSE->isRemoteTransmitter() ) );
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFVectorConnector<VectorTransmitter>::sendTransmitterDataSize()  
+{ 
+   if(senderEvenEvenSW) senderEvenEvenSW->sendDataSize(); 
+   if(senderEvenOddNW) senderEvenOddNW->sendDataSize(); 
+   if(senderOddEvenSE) senderOddEvenSE->sendDataSize(); 
+   if(senderOddOddNE) senderOddOddNE->sendDataSize(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()
+{ 
+   if(receiverEvenEvenSW) receiverEvenEvenSW->receiveDataSize(); 
+   if(receiverEvenOddNW) receiverEvenOddNW->receiveDataSize(); 
+   if(receiverOddEvenSE) receiverOddEvenSE->receiveDataSize(); 
+   if(receiverOddOddNE) receiverOddOddNE->receiveDataSize(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFVectorConnector<VectorTransmitter>::prepareForSend()
+{ 
+   if(senderEvenEvenSW) senderEvenEvenSW->prepareForSend(); 
+   if(senderEvenOddNW) senderEvenOddNW->prepareForSend(); 
+   if(senderOddEvenSE) senderOddEvenSE->prepareForSend(); 
+   if(senderOddOddNE) senderOddOddNE->prepareForSend(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFVectorConnector<VectorTransmitter>::sendVectors()     
+{ 
+   if(senderEvenEvenSW) senderEvenEvenSW->sendData();
+   if(senderEvenOddNW) senderEvenOddNW->sendData();
+   if(senderOddEvenSE) senderOddEvenSE->sendData();
+   if(senderOddOddNE) senderOddOddNE->sendData();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFVectorConnector<VectorTransmitter>::prepareForReceive()     
+{ 
+   if(receiverEvenEvenSW) receiverEvenEvenSW->prepareForReceive(); 
+   if(receiverEvenOddNW) receiverEvenOddNW->prepareForReceive(); 
+   if(receiverOddEvenSE) receiverOddEvenSE->prepareForReceive(); 
+   if(receiverOddOddNE) receiverOddOddNE->prepareForReceive(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFVectorConnector<VectorTransmitter>::receiveVectors() 
+{ 
+   if(receiverEvenEvenSW) receiverEvenEvenSW->receiveData(); 
+   if(receiverEvenOddNW) receiverEvenOddNW->receiveData();  
+   if(receiverOddEvenSE) receiverOddEvenSE->receiveData(); 
+   if(receiverOddOddNE) receiverOddOddNE->receiveData(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFVectorConnector<VectorTransmitter>::init()
+{
+   using namespace D3Q27System;
+
+   int maxX1 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1();
+   int maxX2 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2();
+   int maxX3 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3();
+
+   int       sendSize  = 0;
+   LBMReal initValue = -999.0;
+
+   int sendDataPerNode = 27/*f*/;
+   int iCellSize = 8; //size of interpolation cell
+
+   switch(this->sendDir)
+   {		                  
+   case E : case W : sendSize = maxX2*maxX3*sendDataPerNode*iCellSize; break; 
+   case N : case S : sendSize = maxX1*maxX3*sendDataPerNode*iCellSize; break; 
+   case T : case B : sendSize = maxX1*maxX2*sendDataPerNode*iCellSize; break; 
+   default: throw UbException(UB_EXARGS,"direction not allowed in this constructor");
+   }
+   senderEvenEvenSW->getData().resize(sendSize, initValue);
+   senderEvenOddNW->getData().resize(sendSize, initValue);
+   senderOddEvenSE->getData().resize(sendSize, initValue);
+   senderOddOddNE->getData().resize(sendSize, initValue);
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETCFVectorConnector< VectorTransmitter>::fillSendVectors() 
+{ 
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fFrom->getNX1();
+   int maxX2 = (int)fFrom->getNX2();
+   int maxX3 = (int)fFrom->getNX3();
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int indexEvEv = 0;
+   int indexEvOd = 0;
+   int indexOdEv = 0;
+   int indexOdOd = 0;
+   
+   vector_type& dataEvEv = this->senderEvenEvenSW->getData();
+   vector_type& dataEvOd = this->senderEvenOddNW->getData();
+   vector_type& dataOdEv = this->senderOddEvenSE->getData();
+   vector_type& dataOdOd = this->senderOddOddNE->getData();
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+   
+   switch(sendDir)
+   {
+   case E: 
+      lMinX1 = maxX1-3;
+      lMaxX1 = lMinX1 + 1;
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case W:
+      lMinX1 = 1;
+      lMaxX1 = lMinX1 + 1;
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case N:
+      lMinX2 = maxX2-3;
+      lMaxX2 = lMinX2 + 1;
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case S:
+      lMinX2 = 1;
+      lMaxX2 = lMinX2 + 1;
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case T:
+      lMinX3 = maxX3-3;
+      lMaxX3 = lMinX3 + 1;
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case B:
+      lMinX3 = 1;
+      lMaxX3 = lMinX3 + 1;
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, false);
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, false);
+      fillSendVectorExt(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::getLocalMinMax(const int& gMin, const int& gMax, const bool& even, int& lMin, int& lMax, const bool& dataDistribution)
+{
+   int halfEven = 0;
+   int halfOdd = 0;
+   int dCoef = 0;
+
+   if (dataDistribution)
+      dCoef = 1;
+   
+   if (Utilities::isOdd(gMax))
+   {
+      halfEven = gMax/2;
+      halfOdd =  gMax/2;
+   }
+   if (Utilities::isEven(gMax))
+   {
+      halfEven = gMax/2;
+      halfOdd =  gMax/2 - 1 + dCoef;
+   }
+
+   switch (even)
+   {
+   case true :
+      lMin = gMin + dCoef;
+      lMax = lMin + halfEven - dCoef;
+      break;
+   case false :
+      lMin = gMin + halfOdd;
+      lMax = gMax-1;
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::fillSendVectorExt(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+   int ix1, ix2, ix3;
+   for (ix3=lMinX3; ix3<lMaxX3; ix3++)
+   {
+      for (ix2=lMinX2; ix2<lMaxX2; ix2++)
+      {
+         for (ix1=lMinX1; ix1<lMaxX1; ix1++)
+         {
+            D3Q27ICell icellC;
+            D3Q27ICell icellF;
+            this->readICellC(fFrom, icellC, ix1, ix2, ix3);
+            iprocessor->interpolateCoarseToFine(icellC, icellF);
+            this->writeICellFtoData(data, index, icellF);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::readICellC(DistributionArray3DPtr f, D3Q27ICell& icellC, const int& x1, const int& x2, const int& x3) 
+{
+   f->getDistribution(icellC.BSW, x1, x2, x3);
+   f->getDistribution(icellC.BSE, x1+1, x2, x3);
+   f->getDistribution(icellC.BNW, x1, x2+1, x3);
+   f->getDistribution(icellC.BNE, x1+1, x2+1, x3);
+   f->getDistribution(icellC.TSW, x1, x2, x3+1);
+   f->getDistribution(icellC.TSE, x1+1, x2, x3+1);
+   f->getDistribution(icellC.TNW, x1, x2+1, x3+1);
+   f->getDistribution(icellC.TNE, x1+1, x2+1, x3+1);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::writeICellFtoData(vector_type& data, int& index, D3Q27ICell& icellF) 
+{
+   writeNodeToVector(data, index, icellF.BSW);
+   writeNodeToVector(data, index, icellF.BSE);
+   writeNodeToVector(data, index, icellF.BNW);
+   writeNodeToVector(data, index, icellF.BNE);
+   writeNodeToVector(data, index, icellF.TSW);
+   writeNodeToVector(data, index, icellF.TSE);
+   writeNodeToVector(data, index, icellF.TNW);
+   writeNodeToVector(data, index, icellF.TNE);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::writeNodeToVector(vector_type& data, int& index, LBMReal* inode)
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      data[index++] = inode[i];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::distributeReceiveVectors() 
+{
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fTo = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fTo->getNX1();
+   int maxX2 = (int)fTo->getNX2();
+   int maxX3 = (int)fTo->getNX3();
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+
+   int indexEvEv = 0;
+   int indexEvOd = 0;
+   int indexOdEv = 0;
+   int indexOdOd = 0;
+
+   vector_type& dataEvEv = this->receiverEvenEvenSW->getData();
+   vector_type& dataEvOd = this->receiverEvenOddNW->getData();
+   vector_type& dataOdEv = this->receiverOddEvenSE->getData();
+   vector_type& dataOdOd = this->receiverOddOddNE->getData();
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+   int dummy;
+
+   switch(sendDir)
+   {
+   case E: 
+      lMinX1 = maxX1-4;
+      lMaxX1 = lMinX1 + 1;
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, lMinX2, lMinX3, dummy, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, lMinX3, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case W:
+      lMinX1 = 3;
+      lMaxX1 = lMinX1 + 1;
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, lMinX2, lMinX3, dummy, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, lMinX2, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, lMinX3, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, dummy, dummy, lMaxX2, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case N:
+      lMinX2 = maxX2-4;
+      lMaxX2 = lMinX2 + 1;
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(lMinX1, dummy, lMinX3, dummy, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, lMinX3, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case S:
+      lMinX2 = 3;
+      lMaxX2 = lMinX2 + 1;
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(lMinX1, dummy, lMinX3, dummy, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(lMinX1, dummy, dummy, dummy, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX3, maxX3, true, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, lMinX3, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX3, maxX3, false, lMinX3, lMaxX3, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, dummy, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case T:
+      lMinX3 = maxX3-4;
+      lMaxX3 = lMinX3 + 1;
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+      getLocalMinMax(lMinX1, lMinX2, dummy, dummy, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(lMinX1, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, lMinX2, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   case B:
+      lMinX3 = 3;
+      lMaxX3 = lMinX3 + 1;
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+      getLocalMinMax(lMinX1, lMinX2, dummy, dummy, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvEv, indexEvEv);
+
+      getLocalMinMax(minX1, maxX1, true, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(lMinX1, dummy, dummy, dummy, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataEvOd, indexEvOd);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX2, maxX2, true, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, lMinX2, dummy, lMaxX1, dummy, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdEv, indexOdEv);
+
+      getLocalMinMax(minX1, maxX1, false, lMinX1, lMaxX1, true);
+      getLocalMinMax(minX2, maxX2, false, lMinX2, lMaxX2, true);
+      getLocalMinMax(dummy, dummy, dummy, lMaxX1, lMaxX2, dummy);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, dataOdOd, indexOdOd);
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+   int ix1, ix2, ix3;
+   for (ix3=lMinX3; ix3<lMaxX3; ix3++)
+   {
+      for (ix2=lMinX2; ix2<lMaxX2; ix2++)
+      {
+         for (ix1=lMinX1; ix1<lMaxX1; ix1++)
+         {
+            LBMReal icellC[27];
+            this->readICellCfromData(data, index, icellC);
+            this->writeICellC(fTo, icellC, ix1, ix2, ix3);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::readICellCfromData(vector_type& data, int& index, LBMReal* icellC) 
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      icellC[i] = data[index++];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::writeICellC(DistributionArray3DPtr f, LBMReal* icellC, const int& x1, const int& x2, const int& x3) 
+{
+   f->setDistributionInv(icellC, x1, x2, x3);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETCFVectorConnector< VectorTransmitter>::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3)
+{
+   using namespace D3Q27System;
+
+   if(block.lock()->hasInterpolationFlagCF(E))
+   {
+      maxX1 -= 2;
+   }
+   if(block.lock()->hasInterpolationFlagCF(W))
+   {
+      minX1 += 2;
+   }
+   if(block.lock()->hasInterpolationFlagCF(N))
+   {
+      maxX2 -= 2;  
+   }
+   if(block.lock()->hasInterpolationFlagCF(S))
+   {
+      minX2 += 2;
+   }
+   if(block.lock()->hasInterpolationFlagCF(T))
+   {
+      maxX3 -= 2;
+   }
+   if(block.lock()->hasInterpolationFlagCF(B))
+   {
+      minX3 += 2;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+double D3Q27ETCFVectorConnector<VectorTransmitter>::getSendRecieveTime()
+{
+   return 0;
+}
+
+#endif 
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..08279fe62292d26543f4139ae39e151a60903be5
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector.cpp
@@ -0,0 +1,275 @@
+#include "D3Q27ETDirectConnector.h"
+#include "LBMKernelETD3Q27.h"
+#include "EsoTwistD3Q27System.h"
+
+
+using namespace std;
+
+//Im Anschluss sind die Bulkbereiche synchron 
+
+//*==========================================================*/
+void D3Q27ETDirectConnector::sendVectors()
+{
+   EsoTwist3DPtr  fFrom =  boost::dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions());
+   EsoTwist3DPtr  fTo   = boost::dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions());
+
+   int maxX1 = (int)fFrom->getNX1()-1;
+   int maxX2 = (int)fFrom->getNX2()-1;
+   int maxX3 = (int)fFrom->getNX3()-1;
+
+   LBMReal f[D3Q27System::ENDF+1];
+
+   //EAST
+   if(sendDir==D3Q27System::E)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fFrom->getDistributionInv(f,maxX1-1,x2,x3);
+            fTo->setDistributionForDirection(f,0,x2,x3,EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etE 
+                                                      | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTE 
+                                                      | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etTNE
+                                                      | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBNE
+                                                      | EsoTwistD3Q27System::etBSE);
+         }
+      }
+   }
+   //WEST
+   else if(sendDir==D3Q27System::W)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fFrom->getDistributionInv(f,1,x2,x3);
+            fTo->setDistributionForDirection(f,maxX1,x2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etW 
+                                                        | EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etTW 
+                                                        | EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etTNW
+                                                        | EsoTwistD3Q27System::etTSW | EsoTwistD3Q27System::etBNW
+                                                        | EsoTwistD3Q27System::etBSW);
+         }
+      }
+   }
+   //NORTH
+   else if(sendDir==D3Q27System::N)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)        
+         {                                    
+            fFrom->getDistributionInv(f,x1,maxX2-1,x3);
+            fTo->setDistributionForDirection(f,x1,0,x3,EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etN 
+                                                    | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTN 
+                                                    | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etTNW
+                                                    | EsoTwistD3Q27System::etTNE | EsoTwistD3Q27System::etBNW
+                                                    | EsoTwistD3Q27System::etBNE);
+         }
+      }
+   }
+   //SOUTH
+   else if(sendDir==D3Q27System::S)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fFrom->getDistributionInv(f,x1,1,x3);
+            fTo->setDistributionForDirection(f,x1,maxX2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etS 
+                                                        | EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etTS
+                                                        | EsoTwistD3Q27System::etBS | EsoTwistD3Q27System::etTSW
+                                                        | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBSW
+                                                        | EsoTwistD3Q27System::etBSE);
+         }
+      }
+   }
+
+   //TOP
+   else if(sendDir==D3Q27System::T)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fFrom->getDistributionInv(f,x1,x2,maxX3-1);
+            fTo->setDistributionForDirection(f,x1,x2,0,EsoTwistD3Q27System::etTW | EsoTwistD3Q27System::etT 
+                                                      | EsoTwistD3Q27System::etTE | EsoTwistD3Q27System::etTS
+                                                      | EsoTwistD3Q27System::etTN | EsoTwistD3Q27System::etTNE
+                                                      | EsoTwistD3Q27System::etTNW | EsoTwistD3Q27System::etTSW
+                                                      | EsoTwistD3Q27System::etTSE);
+         }
+      }
+   }
+   //BOTTOM
+   else if(sendDir==D3Q27System::B)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fFrom->getDistributionInv(f,x1,x2,1);
+            fTo->setDistributionForDirection(f,x1,x2,maxX3,EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etB 
+                                                         | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etBS
+                                                         | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etBNE
+                                                         | EsoTwistD3Q27System::etBNW | EsoTwistD3Q27System::etBSW
+                                                         | EsoTwistD3Q27System::etBSE);
+         }
+      }
+   }
+   //NORTHEAST
+   else if(sendDir==D3Q27System::NE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fFrom->getDistributionInv(f,maxX1-1,maxX2-1,x3);
+         fTo->setDistributionForDirection(f,0,0,x3,EsoTwistD3Q27System::etNE
+                                                  | EsoTwistD3Q27System::etTNE
+                                                  | EsoTwistD3Q27System::etBNE);
+      }
+   }
+   //NORTHWEST
+   else if(sendDir==D3Q27System::NW)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fFrom->getDistributionInv(f,1,maxX2-1,x3);
+         fTo->setDistributionForDirection(f,maxX1,0,x3,EsoTwistD3Q27System::etNW
+                                                   | EsoTwistD3Q27System::etTNW
+                                                   | EsoTwistD3Q27System::etBNW);
+      }
+   }
+   //SOUTHWEST
+   else if(sendDir==D3Q27System::SW)
+   {  
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fFrom->getDistributionInv(f,1,1,x3);
+         fTo->setDistributionForDirection(f,maxX1,maxX2,x3,EsoTwistD3Q27System::etSW
+                                                         | EsoTwistD3Q27System::etTSW
+                                                         | EsoTwistD3Q27System::etBSW);
+      }
+   }
+   //SOUTHEAST
+   else if(sendDir==D3Q27System::SE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fFrom->getDistributionInv(f,maxX1-1,1,x3);
+         fTo->setDistributionForDirection(f,0,maxX2,x3,EsoTwistD3Q27System::etSE
+                                                      | EsoTwistD3Q27System::etTSE
+                                                      | EsoTwistD3Q27System::etBSE);
+      }
+   }
+   else if(sendDir==D3Q27System::TE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fFrom->getDistributionInv(f,maxX1-1,x2,maxX3-1);
+         fTo->setDistributionForDirection(f,0,x2,0,EsoTwistD3Q27System::etTE
+                                                | EsoTwistD3Q27System::etTNE
+                                                | EsoTwistD3Q27System::etTSE);
+      }
+   else if(sendDir==D3Q27System::BW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fFrom->getDistributionInv(f,1,x2,1);
+         fTo->setDistributionForDirection(f,maxX1,x2,maxX3,EsoTwistD3Q27System::etBW
+                                                         | EsoTwistD3Q27System::etBNW
+                                                         | EsoTwistD3Q27System::etBSW);
+      }
+   else if(sendDir==D3Q27System::BE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fFrom->getDistributionInv(f,maxX1-1,x2,1);
+         fTo->setDistributionForDirection(f,0,x2,maxX3,EsoTwistD3Q27System::etBE
+                                                      | EsoTwistD3Q27System::etBNE
+                                                      | EsoTwistD3Q27System::etBSE);
+      }
+   else if(sendDir==D3Q27System::TW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fFrom->getDistributionInv(f,1,x2,maxX3-1);
+         fTo->setDistributionForDirection(f,maxX1,x2,0,EsoTwistD3Q27System::etTW
+                                                      | EsoTwistD3Q27System::etTNW
+                                                      | EsoTwistD3Q27System::etTSW);
+      }
+   else if(sendDir==D3Q27System::TN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fFrom->getDistributionInv(f,x1,maxX2-1,maxX3-1);
+         fTo->setDistributionForDirection(f,x1,0,0,EsoTwistD3Q27System::etTN
+                                                | EsoTwistD3Q27System::etTNW
+                                                | EsoTwistD3Q27System::etTNE);
+      }
+   else if(sendDir==D3Q27System::BS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fFrom->getDistributionInv(f,x1,1,1);
+         fTo->setDistributionForDirection(f,x1,maxX2,maxX3,EsoTwistD3Q27System::etBS
+                                                         | EsoTwistD3Q27System::etBSW
+                                                         | EsoTwistD3Q27System::etBSE);
+      }
+   else if(sendDir==D3Q27System::BN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fFrom->getDistributionInv(f,x1,maxX2-1,1);
+         fTo->setDistributionForDirection(f,x1,0,maxX3,EsoTwistD3Q27System::etBN
+                                                      | EsoTwistD3Q27System::etBNW
+                                                      | EsoTwistD3Q27System::etBNE);
+      }
+
+   else if(sendDir==D3Q27System::TS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fFrom->getDistributionInv(f,x1,1,maxX3-1);
+         fTo->setDistributionForDirection(f,x1,maxX2,0,EsoTwistD3Q27System::etTS
+                                                      | EsoTwistD3Q27System::etTSW
+                                                      | EsoTwistD3Q27System::etTSE);
+      }
+
+   else if(sendDir==D3Q27System::TSW)
+   {
+      fFrom->getDistributionInv(f,1,1,maxX3-1);
+      fTo->setDistributionForDirection(f,maxX1,maxX2,0,EsoTwistD3Q27System::etTSW);
+   }
+   else if(sendDir==D3Q27System::TSE)
+   {
+      fFrom->getDistributionInv(f,maxX1-1,1,maxX3-1);
+      fTo->setDistributionForDirection(f,0,maxX2,0,EsoTwistD3Q27System::etTSE);
+   }
+   else if(sendDir==D3Q27System::TNW)
+   {
+      fFrom->getDistributionInv(f,1,maxX2-1,maxX3-1);
+      fTo->setDistributionForDirection(f,maxX1,0,0,EsoTwistD3Q27System::etTNW);
+   }
+   else if(sendDir==D3Q27System::TNE)
+   {
+      fFrom->getDistributionInv(f,maxX1-1,maxX2-1,maxX3-1);
+      fTo->setDistributionForDirection(f,0,0,0,EsoTwistD3Q27System::etTNE);
+   }
+   else if(sendDir==D3Q27System::BSW)
+   {
+      fFrom->getDistributionInv(f,1,1,1);
+      fTo->setDistributionForDirection(f,maxX1,maxX2,maxX3,EsoTwistD3Q27System::etBSW);
+   }
+   else if(sendDir==D3Q27System::BSE)
+   {
+      fFrom->getDistributionInv(f,maxX1-1,1,1);
+      fTo->setDistributionForDirection(f,0,maxX2,maxX3,EsoTwistD3Q27System::etBSE);
+   }
+   else if(sendDir==D3Q27System::BNW)
+   {
+      fFrom->getDistributionInv(f,1,maxX2-1,1);
+      fTo->setDistributionForDirection(f,maxX1,0,maxX3,EsoTwistD3Q27System::etBNW);
+   }
+   else if(sendDir==D3Q27System::BNE)
+   {
+      fFrom->getDistributionInv(f,maxX1-1,maxX2-1,1);
+      fTo->setDistributionForDirection(f,0,0,maxX3,EsoTwistD3Q27System::etBNE);
+   }
+   else UB_THROW( UbException(UB_EXARGS,"unknown dir") );
+}
+//////////////////////////////////////////////////////////////////////////
+double D3Q27ETDirectConnector::getSendRecieveTime()
+{
+   return 0;
+}
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7cc7119ab07c61780e170c267de4d7115c1fe69
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector.h
@@ -0,0 +1,60 @@
+#ifndef D3Q27DIRECTCONNECTOR_H
+#define D3Q27DIRECTCONNECTOR_H
+
+#include <boost/weak_ptr.hpp>
+
+#include "Block3DConnector.h"
+#include "Block3D.h"
+
+class D3Q27ETDirectConnector : public Block3DConnector
+{
+public:
+   D3Q27ETDirectConnector(Block3DPtr from, Block3DPtr to, const int& sendDir) 
+      :  Block3DConnector(sendDir)
+        , from(from)
+        , to(to)
+   {
+
+   }
+   
+   void sendTransmitterDataSize()    { }  
+   void receiveTransmitterDataSize() { }
+   void init()                       { }
+   void prepareForReceive()          { }
+   void prepareForSend()             { }
+   void fillSendVectors()            { }
+   void sendVectors();//                { }
+   void receiveVectors()             { }
+   
+   void distributeReceiveVectors()   { }
+
+   bool isLocalConnector()  { return true;  }
+   bool isRemoteConnector() { return false; }
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return false; }
+
+   double getSendRecieveTime();
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1(){}
+   void sendVectorsX2(){}
+   void sendVectorsX3(){}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> from;
+   boost::weak_ptr<Block3D> to;
+};
+
+#endif //D3Q27DIRECTCONNECTOR_H
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector2.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e17616314b1fc308d0d80f4db34f4c0c1abdd202
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector2.cpp
@@ -0,0 +1,435 @@
+#include "D3Q27ETDirectConnector2.h"
+#include "LBMKernelETD3Q27.h"
+#include "EsoTwistD3Q27System.h"
+
+
+using namespace std;
+
+//Im Anschluss sind die Bulkbereiche synchron 
+
+//*==========================================================*/
+void D3Q27ETDirectConnector2::sendVectors()
+{
+   EsoTwist3DPtr  fFrom =  boost::dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions());
+   EsoTwist3DPtr  fTo   = boost::dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions());
+
+   int maxX1 = (int)fFrom->getNX1()-1;
+   int maxX2 = (int)fFrom->getNX2()-1;
+   int maxX3 = (int)fFrom->getNX3()-1;
+
+   LBMReal f[D3Q27System::ENDF+1];
+
+   //EAST
+   //if(sendDir==D3Q27System::E)
+   //{
+   //   for(int x3=1; x3<maxX3; x3++)   
+   //   {
+   //      for(int x2=1; x2<maxX2; x2++)   
+   //      {
+   //         fFrom->getDistribution(f,maxX1,x2,x3);
+   //         fTo->setDistributionInvForDirection(f,1,x2,x3,EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etE 
+   //            | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTE 
+   //            | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etTNE
+   //            | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBNE
+   //            | EsoTwistD3Q27System::etBSE);
+
+   //         //////////DEBUG
+   //         //LBMReal fdebug[D3Q27System::ENDF+1];
+   //         //fTo->getDistribution(fdebug,0,x2,x3);
+
+   //        
+   //         //////////DEBUG
+   //         //fTo->getDistribution(fdebug,0,x2,x3);
+
+   //         fFrom->getDistribution(f,maxX1-1,x2,x3);
+   //         fTo->setDistributionInvForDirection(f,0,x2,x3,EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etE 
+   //            | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTE 
+   //            | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etTNE
+   //            | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBNE
+   //            | EsoTwistD3Q27System::etBSE);
+
+   //      }
+   //   }
+   //}
+   ////WEST
+   //else if(sendDir==D3Q27System::W)
+   //{
+   //   for(int x3=1; x3<maxX3; x3++)   
+   //   {
+   //      for(int x2=1; x2<maxX2; x2++)   
+   //      {
+   //         fFrom->getDistribution(f,0,x2,x3);
+   //         fTo->setDistributionInvForDirection(f,maxX1-1,x2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etW 
+   //            | EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etTW 
+   //            | EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etTNW
+   //            | EsoTwistD3Q27System::etTSW | EsoTwistD3Q27System::etBNW
+   //            | EsoTwistD3Q27System::etBSW);
+   //         fFrom->getDistribution(f,1,x2,x3);
+   //         fTo->setDistributionInvForDirection(f,maxX1,x2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etW 
+   //            | EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etTW 
+   //            | EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etTNW
+   //            | EsoTwistD3Q27System::etTSW | EsoTwistD3Q27System::etBNW
+   //            | EsoTwistD3Q27System::etBSW);
+   //      }
+   //   }
+   //}
+   //NORTH
+   /*else*/ if(sendDir==D3Q27System::N)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)        
+         {                                    
+            fFrom->getDistribution(f,x1,maxX2,x3);
+            fTo->setDistributionInvForDirection(f,x1,1,x3,EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etN 
+                                                | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTN 
+                                                | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etTNW
+                                                | EsoTwistD3Q27System::etTNE | EsoTwistD3Q27System::etBNW
+                                                | EsoTwistD3Q27System::etBNE);
+            //fFrom->getDistribution(f,x1,maxX2-1,x3);
+            //fTo->setDistributionInvForDirection(f,x1,0,x3,EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etN 
+            //                                    | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTN 
+            //                                    | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etTNW
+            //                                    | EsoTwistD3Q27System::etTNE | EsoTwistD3Q27System::etBNW
+            //                                    | EsoTwistD3Q27System::etBNE);
+         }
+      }
+   }
+   //SOUTH
+   /*else*/ if(sendDir==D3Q27System::S)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fFrom->getDistribution(f,x1,0,x3);
+            fTo->setDistributionInvForDirection(f,x1,maxX2-1,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etS 
+               | EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etTS
+               | EsoTwistD3Q27System::etBS | EsoTwistD3Q27System::etTSW
+               | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBSW
+               | EsoTwistD3Q27System::etBSE);
+
+
+            
+            //fFrom->getDistribution(f,x1,1,x3);
+
+            ////////////DEBUG
+            //LBMReal fdebug[D3Q27System::ENDF+1];
+            //fTo->getDistribution(fdebug,x1,maxX2,x3);
+            //
+            //fTo->setDistributionInvForDirection(f,x1,maxX2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etS 
+            //   | EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etTS
+            //   | EsoTwistD3Q27System::etBS | EsoTwistD3Q27System::etTSW
+            //   | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBSW
+            //   | EsoTwistD3Q27System::etBSE);
+
+            ////////////DEBUG
+            //fTo->getDistribution(fdebug,x1,maxX2,x3);
+
+            //int deb = 0;
+         }
+      }
+   }
+
+   //TOP
+   else if(sendDir==D3Q27System::T)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {      
+            ////////////DEBUG
+            LBMReal fdebug[D3Q27System::ENDF+1];
+            fTo->getDistribution(fdebug,x1,x2,0);
+            
+            fFrom->getDistribution(f,x1,x2,maxX3);
+            fTo->setDistributionInvForDirection(f,x1,x2,1,EsoTwistD3Q27System::etTW | EsoTwistD3Q27System::etT 
+               | EsoTwistD3Q27System::etTE | EsoTwistD3Q27System::etTS
+               | EsoTwistD3Q27System::etTN | EsoTwistD3Q27System::etTNE
+               | EsoTwistD3Q27System::etTNW | EsoTwistD3Q27System::etTSW
+               | EsoTwistD3Q27System::etTSE);
+            //fFrom->getDistribution(f,x1,x2,maxX3-1);
+            //fTo->setDistributionInvForDirection(f,x1,x2,0,EsoTwistD3Q27System::etTW | EsoTwistD3Q27System::etT 
+            //   | EsoTwistD3Q27System::etTE | EsoTwistD3Q27System::etTS
+            //   | EsoTwistD3Q27System::etTN | EsoTwistD3Q27System::etTNE
+            //   | EsoTwistD3Q27System::etTNW | EsoTwistD3Q27System::etTSW
+            //   | EsoTwistD3Q27System::etTSE);
+            ////////////DEBUG
+            fTo->getDistribution(fdebug,x1,x2,0);
+            int deb = 0;
+         }
+      }
+   }
+   //BOTTOM
+   else if(sendDir==D3Q27System::B)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fFrom->getDistribution(f,x1,x2,0);
+            
+            ////////////DEBUG
+            LBMReal fdebug1[D3Q27System::ENDF+1];
+            fTo->getDistribution(fdebug1,x1,x2,maxX3-1);
+
+            fTo->setDistributionInvForDirection(f,x1,x2,maxX3-1,EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etB 
+               | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etBS
+               | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etBNE
+               | EsoTwistD3Q27System::etBNW | EsoTwistD3Q27System::etBSW
+               | EsoTwistD3Q27System::etBSE);
+
+            fTo->getDistribution(fdebug1,x1,x2,maxX3-1);
+
+            ////////////DEBUG
+            LBMReal fdebug[D3Q27System::ENDF+1];
+            fTo->getDistribution(fdebug,x1,x2,maxX3);
+
+            fFrom->getDistribution(f,x1,x2,1);
+            fTo->setDistributionInvForDirection(f,x1,x2,maxX3,EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etB 
+               | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etBS
+               | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etBNE
+               | EsoTwistD3Q27System::etBNW | EsoTwistD3Q27System::etBSW
+               | EsoTwistD3Q27System::etBSE);
+            //fTo->setDistributionInvForDirection(f,x1,x2,maxX3,EsoTwistD3Q27System::etTW | EsoTwistD3Q27System::etT 
+            //   | EsoTwistD3Q27System::etTE | EsoTwistD3Q27System::etTS
+            //   | EsoTwistD3Q27System::etTN | EsoTwistD3Q27System::etTNE
+            //   | EsoTwistD3Q27System::etTNW | EsoTwistD3Q27System::etTSW
+            //   | EsoTwistD3Q27System::etTSE);
+            fTo->getDistribution(fdebug,x1,x2,maxX3);
+            int deb = 0;
+            LBMReal temp1, temp2;
+            for (int i = 0; i<26;i++)
+            {
+               temp1 = fTo->getDistributionInvForDirection(x1,x2,maxX3,i);
+               temp2 = fTo->getDistributionInvForDirection(x1,x2,maxX3,D3Q27System::INVDIR[i]);
+               fTo->setDistributionInvForDirection(temp1,x1,x2,maxX3,D3Q27System::INVDIR[i]);
+               fTo->setDistributionInvForDirection(temp2,x1,x2,maxX3,i);
+            }
+         }
+      }
+   }
+   ////NORTHEAST
+   //else if(sendDir==D3Q27System::NE)
+   //{   
+   //   for(int x3=1; x3<maxX3; x3++)   
+   //   {
+   //      fFrom->getDistribution(f,maxX1,maxX2,x3);
+   //      fTo->setDistributionInvForDirection(f,1,1,x3,EsoTwistD3Q27System::etNE
+   //         | EsoTwistD3Q27System::etTNE
+   //         | EsoTwistD3Q27System::etBNE);
+   //      fFrom->getDistribution(f,maxX1-1,maxX2-1,x3);
+   //      fTo->setDistributionInvForDirection(f,0,0,x3,EsoTwistD3Q27System::etNE
+   //         | EsoTwistD3Q27System::etTNE
+   //         | EsoTwistD3Q27System::etBNE);
+   //   }
+   //}
+   ////NORTHWEST
+   //else if(sendDir==D3Q27System::NW)
+   //{   
+   //   for(int x3=1; x3<maxX3; x3++)   
+   //   {
+   //      fFrom->getDistribution(f,0,maxX2,x3);
+   //      fTo->setDistributionInvForDirection(f,maxX1-1,1,x3,EsoTwistD3Q27System::etNW
+   //                                       | EsoTwistD3Q27System::etTNW
+   //                                       | EsoTwistD3Q27System::etBNW);
+   //      fFrom->getDistribution(f,1,maxX2-1,x3);
+   //      fTo->setDistributionInvForDirection(f,maxX1,0,x3,EsoTwistD3Q27System::etNW
+   //         | EsoTwistD3Q27System::etTNW
+   //         | EsoTwistD3Q27System::etBNW);
+   //   }
+   //}
+   ////SOUTHWEST
+   //else if(sendDir==D3Q27System::SW)
+   //{  
+   //   for(int x3=1; x3<maxX3; x3++)   
+   //   {
+   //      fFrom->getDistribution(f,0,0,x3);
+   //      fTo->setDistributionInvForDirection(f,maxX1-1,maxX2-1,x3,EsoTwistD3Q27System::etSW
+   //         | EsoTwistD3Q27System::etTSW
+   //         | EsoTwistD3Q27System::etBSW);
+   //      fFrom->getDistribution(f,1,1,x3);
+   //      fTo->setDistributionInvForDirection(f,maxX1,maxX2,x3,EsoTwistD3Q27System::etSW
+   //                                       | EsoTwistD3Q27System::etTSW
+   //                                       | EsoTwistD3Q27System::etBSW);
+
+   //   }
+   //}
+   ////SOUTHEAST
+   //else if(sendDir==D3Q27System::SE)
+   //{   
+   //   for(int x3=1; x3<maxX3; x3++)   
+   //   {
+   //      fFrom->getDistribution(f,maxX1,0,x3);
+   //      fTo->setDistributionInvForDirection(f,1,maxX2-1,x3,EsoTwistD3Q27System::etSE
+   //         | EsoTwistD3Q27System::etTSE
+   //         | EsoTwistD3Q27System::etBSE);
+   //      fFrom->getDistribution(f,maxX1-1,1,x3);
+   //      fTo->setDistributionInvForDirection(f,0,maxX2,x3,EsoTwistD3Q27System::etSE
+   //                                       | EsoTwistD3Q27System::etTSE
+   //                                       | EsoTwistD3Q27System::etBSE);
+   //   }
+   //}
+   //else if(sendDir==D3Q27System::TE)
+   //   for(int x2=1; x2<maxX2; x2++)
+   //   {
+   //      fFrom->getDistribution(f,maxX1,x2,maxX3);
+   //      fTo->setDistributionInvForDirection(f,1,x2,1,EsoTwistD3Q27System::etTE
+   //         | EsoTwistD3Q27System::etTNE
+   //         | EsoTwistD3Q27System::etTSE);
+   //      fFrom->getDistribution(f,maxX1-1,x2,maxX3-1);
+   //      fTo->setDistributionInvForDirection(f,0,x2,0,EsoTwistD3Q27System::etTE
+   //                                       | EsoTwistD3Q27System::etTNE
+   //                                       | EsoTwistD3Q27System::etTSE);
+
+   //   }
+   //else if(sendDir==D3Q27System::BW)
+   //   for(int x2=1; x2<maxX2; x2++)
+   //   {
+   //      fFrom->getDistribution(f,0,x2,0);
+   //      fTo->setDistributionInvForDirection(f,maxX1-1,x2,maxX3-1,EsoTwistD3Q27System::etBW
+   //         | EsoTwistD3Q27System::etBNW
+   //         | EsoTwistD3Q27System::etBSW);
+   //      fFrom->getDistribution(f,1,x2,1);
+   //      fTo->setDistributionInvForDirection(f,maxX1,x2,maxX3,EsoTwistD3Q27System::etBW
+   //                                       | EsoTwistD3Q27System::etBNW
+   //                                       | EsoTwistD3Q27System::etBSW);
+   //   }
+   //else if(sendDir==D3Q27System::BE)
+   //   for(int x2=1; x2<maxX2; x2++)
+   //   {
+   //      fFrom->getDistribution(f,maxX1,x2,0);
+   //      fTo->setDistributionInvForDirection(f,1,x2,maxX3-1,EsoTwistD3Q27System::etBE
+   //         | EsoTwistD3Q27System::etBNE
+   //         | EsoTwistD3Q27System::etBSE);
+   //      fFrom->getDistribution(f,maxX1-1,x2,1);
+   //      fTo->setDistributionInvForDirection(f,0,x2,maxX3,EsoTwistD3Q27System::etBE
+   //                                       | EsoTwistD3Q27System::etBNE
+   //                                       | EsoTwistD3Q27System::etBSE);
+   //   }
+   //else if(sendDir==D3Q27System::TW)
+   //   for(int x2=1; x2<maxX2; x2++)
+   //   {
+   //      fFrom->getDistribution(f,0,x2,maxX3);
+   //      fTo->setDistributionInvForDirection(f,maxX1-1,x2,1,EsoTwistD3Q27System::etTW
+   //         | EsoTwistD3Q27System::etTNW
+   //         | EsoTwistD3Q27System::etTSW);
+   //      fFrom->getDistribution(f,1,x2,maxX3-1);
+   //      fTo->setDistributionInvForDirection(f,maxX1,x2,0,EsoTwistD3Q27System::etTW
+   //                                       | EsoTwistD3Q27System::etTNW
+   //                                       | EsoTwistD3Q27System::etTSW);
+   //   }
+   //else if(sendDir==D3Q27System::TN)
+   //   for(int x1=1; x1<maxX1; x1++)
+   //   {
+   //      fFrom->getDistribution(f,x1,maxX2,maxX3);
+   //      fTo->setDistributionInvForDirection(f,x1,1,1,EsoTwistD3Q27System::etTN
+   //         | EsoTwistD3Q27System::etTNW
+   //         | EsoTwistD3Q27System::etTNE);
+   //      fFrom->getDistribution(f,x1,maxX2-1,maxX3-1);
+   //      fTo->setDistributionInvForDirection(f,x1,0,0,EsoTwistD3Q27System::etTN
+   //                                       | EsoTwistD3Q27System::etTNW
+   //                                       | EsoTwistD3Q27System::etTNE);
+
+   //   }
+   //else if(sendDir==D3Q27System::BS)
+   //   for(int x1=1; x1<maxX1; x1++)
+   //   {
+   //      fFrom->getDistribution(f,x1,0,0);
+   //      fTo->setDistributionInvForDirection(f,x1,maxX2-1,maxX3-1,EsoTwistD3Q27System::etBS
+   //         | EsoTwistD3Q27System::etBSW
+   //         | EsoTwistD3Q27System::etBSE);
+   //      fFrom->getDistribution(f,x1,1,1);
+   //      fTo->setDistributionInvForDirection(f,x1,maxX2,maxX3,EsoTwistD3Q27System::etBS
+   //                                       | EsoTwistD3Q27System::etBSW
+   //                                       | EsoTwistD3Q27System::etBSE);
+   //   }
+   //else if(sendDir==D3Q27System::BN)
+   //   for(int x1=1; x1<maxX1; x1++)
+   //   {
+   //      fFrom->getDistribution(f,x1,maxX2,0);
+   //      fTo->setDistributionInvForDirection(f,x1,1,maxX3-1,EsoTwistD3Q27System::etBN
+   //         | EsoTwistD3Q27System::etBNW
+   //         | EsoTwistD3Q27System::etBNE);
+   //      fFrom->getDistribution(f,x1,maxX2-1,1);
+   //      fTo->setDistributionInvForDirection(f,x1,0,maxX3,EsoTwistD3Q27System::etBN
+   //                                       | EsoTwistD3Q27System::etBNW
+   //                                       | EsoTwistD3Q27System::etBNE);
+   //   }
+
+   //else if(sendDir==D3Q27System::TS)
+   //   for(int x1=1; x1<maxX1; x1++)
+   //   {
+   //      fFrom->getDistribution(f,x1,0,maxX3);
+   //      fTo->setDistributionInvForDirection(f,x1,maxX2-1,1,EsoTwistD3Q27System::etTS
+   //         | EsoTwistD3Q27System::etTSW
+   //         | EsoTwistD3Q27System::etTSE);
+   //      fFrom->getDistribution(f,x1,1,maxX3-1);
+   //      fTo->setDistributionInvForDirection(f,x1,maxX2,0,EsoTwistD3Q27System::etTS
+   //                                       | EsoTwistD3Q27System::etTSW
+   //                                       | EsoTwistD3Q27System::etTSE);
+   //   }
+
+   //else if(sendDir==D3Q27System::TSW)
+   //{
+   //   fFrom->getDistribution(f,0,0,maxX3);
+   //   fTo->setDistributionInvForDirection(f,maxX1-1,maxX2-1,1,EsoTwistD3Q27System::etTSW);
+   //   fFrom->getDistribution(f,1,1,maxX3-1);
+   //   fTo->setDistributionInvForDirection(f,maxX1,maxX2,0,EsoTwistD3Q27System::etTSW);
+   //}
+   //else if(sendDir==D3Q27System::TSE)
+   //{
+   //   fFrom->getDistribution(f,maxX1,0,maxX3);
+   //   fTo->setDistributionInvForDirection(f,1,maxX2-1,1,EsoTwistD3Q27System::etTSE);
+   //   fFrom->getDistribution(f,maxX1-1,1,maxX3-1);
+   //   fTo->setDistributionInvForDirection(f,0,maxX2,0,EsoTwistD3Q27System::etTSE);
+   //}
+   //else if(sendDir==D3Q27System::TNW)
+   //{
+   //   fFrom->getDistribution(f,0,maxX2,maxX3);
+   //   fTo->setDistributionInvForDirection(f,maxX1-1,1,1,EsoTwistD3Q27System::etTNW);
+   //   fFrom->getDistribution(f,1,maxX2-1,maxX3-1);
+   //   fTo->setDistributionInvForDirection(f,maxX1,0,0,EsoTwistD3Q27System::etTNW);
+   //}
+   //else if(sendDir==D3Q27System::TNE)
+   //{
+   //   fFrom->getDistribution(f,maxX1,maxX2,maxX3);
+   //   fTo->setDistributionInvForDirection(f,1,1,1,EsoTwistD3Q27System::etTNE);
+   //   fFrom->getDistribution(f,maxX1-1,maxX2-1,maxX3-1);
+   //   fTo->setDistributionInvForDirection(f,0,0,0,EsoTwistD3Q27System::etTNE);
+   //}
+   //else if(sendDir==D3Q27System::BSW)
+   //{
+   //   fFrom->getDistribution(f,0,0,0);
+   //   fTo->setDistributionInvForDirection(f,maxX1-1,maxX2-1,maxX3-1,EsoTwistD3Q27System::etBSW);
+   //   fFrom->getDistribution(f,1,1,1);
+   //   fTo->setDistributionInvForDirection(f,maxX1,maxX2,maxX3,EsoTwistD3Q27System::etBSW);
+   //}
+   //else if(sendDir==D3Q27System::BSE)
+   //{
+   //   fFrom->getDistribution(f,maxX1,0,0);
+   //   fTo->setDistributionInvForDirection(f,1,maxX2-1,maxX3-1,EsoTwistD3Q27System::etBSE);
+   //   fFrom->getDistribution(f,maxX1-1,1,1);
+   //   fTo->setDistributionInvForDirection(f,0,maxX2,maxX3,EsoTwistD3Q27System::etBSE);
+   //}
+   //else if(sendDir==D3Q27System::BNW)
+   //{
+   //   fFrom->getDistribution(f,0,maxX2,0);
+   //   fTo->setDistributionInvForDirection(f,maxX1-1,1,maxX3-1,EsoTwistD3Q27System::etBNW);
+   //   fFrom->getDistribution(f,1,maxX2-1,1);
+   //   fTo->setDistributionInvForDirection(f,maxX1,0,maxX3,EsoTwistD3Q27System::etBNW);
+   //}
+   //else if(sendDir==D3Q27System::BNE)
+   //{
+   //   fFrom->getDistribution(f,maxX1,maxX2,0);
+   //   fTo->setDistributionInvForDirection(f,1,1,maxX3-1,EsoTwistD3Q27System::etBNE);
+   //   fFrom->getDistribution(f,maxX1-1,maxX2-1,1);
+   //   fTo->setDistributionInvForDirection(f,0,0,maxX3,EsoTwistD3Q27System::etBNE);
+   //}
+   //else UB_THROW( UbException(UB_EXARGS,"unknown dir") );
+}
+//////////////////////////////////////////////////////////////////////////
+//double D3Q27ETDirectConnector2::getSendRecieveTime()
+//{
+//   return 0;
+//}
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector2.h b/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector2.h
new file mode 100644
index 0000000000000000000000000000000000000000..eeb790d687b34de3bad5d6a39bb50995d77e827f
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETDirectConnector2.h
@@ -0,0 +1,21 @@
+#ifndef D3Q27ETDirectConnector2_H
+#define D3Q27ETDirectConnector2_H
+
+#include <boost/weak_ptr.hpp>
+
+#include "LocalBlock3DConnector.h"
+#include "Block3D.h"
+
+class D3Q27ETDirectConnector2 : public LocalBlock3DConnector
+{
+public:
+   D3Q27ETDirectConnector2(Block3DPtr from, Block3DPtr to, const int& sendDir) 
+      :  LocalBlock3DConnector(from, to, sendDir)
+   {
+
+   }
+   void sendVectors();
+};
+
+#endif //D3Q27ETDirectConnector2_H
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFCOffVectorConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETFCOffVectorConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..41e9f74caf2663a9e78d20ff26002faf5548f4f3
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFCOffVectorConnector.cpp
@@ -0,0 +1,3 @@
+#include "D3Q27ETFCOffVectorConnector.h"
+
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFCOffVectorConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETFCOffVectorConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..827ef9711b55083cec53e0115f632cc535e18fe0
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFCOffVectorConnector.h
@@ -0,0 +1,1437 @@
+/**
+* @file D3Q27ETFCOffVectorConnector.h
+* @class D3Q27ETFCVectorConnector
+* @brief Interpolation from fine level to coarse.
+* @author Kostyantyn Kucher and Ehsan Fard
+* @date 08.06.2011
+*/
+#ifndef D3Q27ETFCOffVectorConnector_H
+#define D3Q27ETFCOffVectorConnector_H
+
+#include <vector>
+
+#include "basics/transmitter/TbTransmitter.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "Grid3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "MathUtil.hpp"
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include "D3Q27ETFCVectorConnector.h"
+//#include "FineToCoarseBlock3DConnector.h"
+
+class Block3D;
+
+//enum CFconnectorType {EvenOddNW, EvenEvenSW, OddEvenSE, OddOddNE};
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+
+template< typename VectorTransmitter >
+class D3Q27ETFCOffVectorConnector : public Block3DConnector
+{
+public:
+
+protected:
+	typedef typename VectorTransmitter::value_type  vector_type;
+	typedef boost::shared_ptr< VectorTransmitter > VectorTransmitterPtr;
+public:
+   D3Q27ETFCOffVectorConnector(Block3DPtr block, VectorTransmitterPtr sender, VectorTransmitterPtr receiver, int sendDir, 
+      D3Q27InterpolationProcessorPtr iprocessor, CFconnectorType connType);
+
+	bool isLocalConnector();
+	bool isRemoteConnector();
+	void init();
+
+	void sendTransmitterDataSize();
+	void receiveTransmitterDataSize();
+
+	void prepareForSend();
+	void sendVectors();
+
+	void prepareForReceive();
+	void receiveVectors();
+
+	void fillSendVectors();
+	void distributeReceiveVectors();
+
+	bool isInterpolationConnectorCF() { return false; }
+	bool isInterpolationConnectorFC() { return true; }
+
+	double getSendRecieveTime();
+
+	void prepareForSendX1() {}
+	void prepareForSendX2() {}
+	void prepareForSendX3() {}
+
+	void sendVectorsX1(){}
+	void sendVectorsX2(){}
+	void sendVectorsX3(){}
+
+	void prepareForReceiveX1() {}
+	void prepareForReceiveX2() {}
+	void prepareForReceiveX3() {}
+
+	void receiveVectorsX1() {}
+	void receiveVectorsX2() {}
+	void receiveVectorsX3() {}
+
+protected:
+	boost::weak_ptr<Block3D> block; //dieser nvd sendet daten und die empfangenen werden diesem nvd zugeordnet
+	//gegenstelle muss "inversen" connector besitzen
+	VectorTransmitterPtr sender, receiver;
+
+	D3Q27InterpolationProcessorPtr iprocessor;
+
+   CFconnectorType connType;
+
+	void writeICellCtoData(vector_type& data, int& index, LBMReal* icellC);
+	void writeNodeToVector(vector_type& data, int& index, LBMReal* inode);
+	void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3);
+   void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3, CFconnectorType connType);
+	void getLocalMinMaxCF(int gMax, int& lMin, int& lMax);
+	void fillSendVector(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+
+	void distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+	void readICellFfromData(vector_type& data, int& index, D3Q27ICell& icellF);
+	void readNodeFromVector(vector_type& data, int& index, LBMReal* inode);
+	void getLocalOffsets(const int& gMax, int& oMin);
+	void getLocalMins(int& minX1, int& minX2, int& minX3, const int& oMinX1, const int& oMinX2, const int& oMinX3);
+
+	int bMaxX1, bMaxX2, bMaxX3;
+};
+////////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+D3Q27ETFCOffVectorConnector<VectorTransmitter>::D3Q27ETFCOffVectorConnector(Block3DPtr block, VectorTransmitterPtr sender, 
+																			VectorTransmitterPtr receiver, int sendDir, 
+																			D3Q27InterpolationProcessorPtr iprocessor,
+                                                         CFconnectorType connType)
+																			: Block3DConnector(sendDir)
+																			, block(block)
+																			, sender(sender)
+																			, receiver(receiver)
+																			, iprocessor(iprocessor)
+																			, connType(connType)
+{
+	if( !(   sendDir==D3Q27System::E  || sendDir==D3Q27System::W  || sendDir==D3Q27System::N  || sendDir==D3Q27System::S  || sendDir==D3Q27System::T || sendDir==D3Q27System::B 
+		||  sendDir==D3Q27System::NE || sendDir==D3Q27System::SW || sendDir==D3Q27System::SE || sendDir==D3Q27System::NW
+		||  sendDir==D3Q27System::TE || sendDir==D3Q27System::BW ||  sendDir==D3Q27System::BE || sendDir==D3Q27System::TW
+		||  sendDir==D3Q27System::TN || sendDir==D3Q27System::BS ||  sendDir==D3Q27System::BN || sendDir==D3Q27System::TS 
+
+		||  sendDir==D3Q27System::TNE || sendDir==D3Q27System::TNW ||  sendDir==D3Q27System::TSE || sendDir==D3Q27System::TSW
+		||  sendDir==D3Q27System::BNE || sendDir==D3Q27System::BNW ||  sendDir==D3Q27System::BSE || sendDir==D3Q27System::BSW 
+		
+		) )
+	{
+		throw UbException(UB_EXARGS,"invalid constructor for this direction");
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETFCOffVectorConnector<VectorTransmitter>::isLocalConnector()
+{ 
+	return !this->isRemoteConnector(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETFCOffVectorConnector<VectorTransmitter>::isRemoteConnector() 
+{ 
+	return sender->isRemoteTransmitter()  ||  receiver->isRemoteTransmitter();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCOffVectorConnector<VectorTransmitter>::sendTransmitterDataSize()  
+{ 
+	if(sender)
+	{
+		UBLOG(logDEBUG5, "D3Q27ETFCOffVectorConnector<VectorTransmitter>::sendTransmitterDataSize()"<<block.lock()->toString()+"sendDir="<<sendDir);
+		sender->sendDataSize(); 
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCOffVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()
+{ 
+	if(receiver)
+	{
+		UBLOG(logDEBUG5, "D3Q27ETFCOffVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()"<<block.lock()->toString()<<"sendDir="<<sendDir);
+		receiver->receiveDataSize();
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCOffVectorConnector<VectorTransmitter>::prepareForSend()
+{ 
+	if(sender) sender->prepareForSend(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCOffVectorConnector<VectorTransmitter>::sendVectors()     
+{ 
+	if(sender) sender->sendData();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCOffVectorConnector<VectorTransmitter>::prepareForReceive()     
+{ 
+	if(receiver) receiver->prepareForReceive(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCOffVectorConnector<VectorTransmitter>::receiveVectors() 
+{ 
+	if(receiver) receiver->receiveData(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCOffVectorConnector<VectorTransmitter>::init()
+{
+	using namespace D3Q27System;
+
+	bMaxX1 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1();
+	bMaxX2 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2();
+	bMaxX3 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3();
+
+	int       sendSize  = 0;
+	LBMReal initValue = -999.0;
+
+	int sendDataPerNode = 27/*f*/;
+	int iCellSize = 1; //size of interpolation cell
+
+	switch(this->sendDir)
+	{		                  
+	case E : case W : sendSize = (bMaxX2-1)/2*(bMaxX3-1)/2*sendDataPerNode*iCellSize; break; 
+	case N : case S : sendSize = (bMaxX1-1)/2*(bMaxX3-1)/2*sendDataPerNode*iCellSize; break; 
+	case T : case B : sendSize = (bMaxX1-1)/2*(bMaxX2-1)/2*sendDataPerNode*iCellSize; break; 		  
+	case NE : case SW :case SE : case NW : sendSize = (3*bMaxX3-3)*sendDataPerNode*iCellSize; break; // buffer overhead, should be (3*bMaxX3-6) for even bMax3		
+	case TE : case BW :case BE : case TW : sendSize = (3*bMaxX2-3)*sendDataPerNode*iCellSize; break; 
+	case TN : case BS :case BN : case TS : sendSize = (3*bMaxX1-3)*sendDataPerNode*iCellSize; break;	
+   case TNE: case TNW:case TSE: case TSW:case BNE: case BNW:case BSE: case BSW: sendSize = 3*(3*bMaxX1-3)*sendDataPerNode*iCellSize; break;
+	default: throw UbException(UB_EXARGS,"direction not allowed in this constructor");
+	}
+	sender->getData().resize(sendSize, initValue);
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::fillSendVectors() 
+{ 
+	using namespace D3Q27System;
+
+	DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+	int maxX1 = (int)fFrom->getNX1();
+	int maxX2 = (int)fFrom->getNX2();
+	int maxX3 = (int)fFrom->getNX3();
+	int minX1 = 0;
+	int minX2 = 0;
+	int minX3 = 0;
+
+	int oMinX1, oMinX2, oMinX3; 
+	getLocalOffsets(maxX1, oMinX1);
+	getLocalOffsets(maxX2, oMinX2);
+	getLocalOffsets(maxX3, oMinX3);
+
+	int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+	int index = 0;
+	vector_type& data = sender->getData();
+
+	lMinX1 = minX1+1; lMinX2 = minX2+1; lMinX3 = minX3+1;
+	lMaxX1 = maxX1-2; lMaxX2 = maxX2-2; lMaxX3 = maxX3-2;
+
+   ///////////////////////////////////////
+   ///DEBUG
+#ifdef _DEBUG
+   if (block.lock()->getGlobalID() == 2558)
+   {
+      int test = 0;
+   }
+#endif
+   //////////////
+
+	switch(sendDir)
+	{
+	case E: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case W: 
+      ///////////////////////////////////////
+      ///DEBUG
+#ifdef _DEBUG
+      if (block.lock()->getGlobalID() == 2516)
+      {
+         int test = 0;
+      }
+#endif
+      //////////////
+		//getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, none);
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = 5;
+		lMaxX1 = lMinX1 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;  
+	case N:
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case S:
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX2 = 5;
+		lMaxX2 = lMinX2 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case T:
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case B:
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX3 = 5;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	//	////N-S-E-W
+	case NE: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 +5;
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 + 1;
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case SW: 
+		
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 5;
+		lMinX2 = 5;
+		lMaxX2 = lMinX2 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX1 = 5;
+		lMaxX1 = lMinX1 + 1;
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case SE: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 +5;
+		lMinX2 = 5;
+		lMaxX2 = lMinX2 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 + 1;
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		break;
+
+	case NW: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 5;
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX1 = 5;
+		lMaxX1 = lMinX1 + 1;
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+//////T-B-E-W
+	case TE: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 +5;
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 + 1;
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case BW: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 5;
+		lMinX3 = 5;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX1 = 5;
+		lMaxX1 = lMinX1 + 1;
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case BE: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 +5;
+		lMinX3 = 5;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX1 = maxX1-7;
+		lMaxX1 = lMinX1 + 1;
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case TW: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX1 = 1;
+		lMaxX1 = lMinX1 + 5;
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX1 = 5;
+		lMaxX1 = lMinX1 + 1;
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+///////////////T-B-N-S
+//
+	case TN: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 5;
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 1;
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case BS: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 5;
+		lMinX3 = 5;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX2 = 5;
+		lMaxX2 = lMinX2 + 1;
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case BN: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 5;
+		lMinX3 = 5;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX2 = maxX2-7;
+		lMaxX2 = lMinX2 + 1;
+		lMinX3 = 1;
+		lMaxX3 = lMinX3 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case TS: 
+		getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+		getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+		lMinX2 = 1;
+		lMaxX2 = lMinX2 + 5;
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 1;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+		lMinX2 = 5;
+		lMaxX2 = lMinX2 + 1;
+		lMinX3 = maxX3-7;
+		lMaxX3 = lMinX3 + 5;
+		fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+   
+   //TNE
+   case TNE:
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-6;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-2;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-2;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-2;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-6;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-2;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-2;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-2;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+
+
+   //TNW
+   case TNW:
+      lMinX1 = 5;
+      lMaxX1 = 6;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-2;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-2;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = 1;
+      lMaxX1 = 6;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-6;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-2;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = 1;
+      lMaxX1 = 6;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-2;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+
+      break;
+   
+   //      TSE
+   case TSE:
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-6;
+      lMinX2 = 1;
+      lMaxX2 = 6;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-2;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-2;
+      lMinX2 = 5;
+      lMaxX2 = 6;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-2;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-2;
+      lMinX2 = 1;
+      lMaxX2 = 6;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      break;
+   //      TSW
+   case TSW:
+      lMinX1 = 5;
+      lMaxX1 = 6;
+      lMinX2 = 1;
+      lMaxX2 = 6;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-2;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = 1;
+      lMaxX1 = 6;
+      lMinX2 = 5;
+      lMaxX2 = 6;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-2;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = 1;
+      lMaxX1 = 6;
+      lMinX2 = 1;
+      lMaxX2 = 6;
+      lMinX3 = maxX3-7;
+      lMaxX3 = maxX3-6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      break;
+   //      BNE
+   case BNE:
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-6;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-2;
+      lMinX3 = 1;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-2;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-6;
+      lMinX3 = 1;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-2;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-2;
+      lMinX3 = 5;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      break;
+   //      BNW
+   case BNW:
+      lMinX1 = 5;
+      lMaxX1 = 6;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-2;
+      lMinX3 = 1;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = 1;
+      lMaxX1 = 6;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-6;
+      lMinX3 = 1;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = 1;
+      lMaxX1 = 6;
+      lMinX2 = maxX2-7;
+      lMaxX2 = maxX2-2;
+      lMinX3 = 5;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      break;
+
+
+   //      BSE
+   case BSE:
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-6;
+      lMinX2 = 1;
+      lMaxX2 = 6;
+      lMinX3 = 1;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-2;
+      lMinX2 = 5;
+      lMaxX2 = 6;
+      lMinX3 = 1;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = maxX1-7;
+      lMaxX1 = maxX1-2;
+      lMinX2 = 1;
+      lMaxX2 = 6;
+      lMinX3 = 5;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      break;
+
+   //BSW
+   case BSW:
+      lMinX1 = 5;
+      lMaxX1 = 6;
+      lMinX2 = 1;
+      lMaxX2 = 6;
+      lMinX3 = 1;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      
+      lMinX1 = 1;
+      lMaxX1 = 6;
+      lMinX2 = 5;
+      lMaxX2 = 6;
+      lMinX3 = 1;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      lMinX1 = 1;
+      lMaxX1 = 6;
+      lMinX2 = 1;
+      lMaxX2 = 6;
+      lMinX3 = 5;
+      lMaxX3 = 6;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+
+      break;
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::fillSendVector(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+	int ix1, ix2, ix3;
+	LBMReal xoff, yoff, zoff;
+	BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(block.lock()->getKernel()->getBCProcessor())->getBCArray();
+
+	for (ix3=lMinX3; ix3<lMaxX3; ix3+=2)
+	{
+		for (ix2=lMinX2; ix2<lMaxX2; ix2+=2)
+		{
+			for (ix1=lMinX1; ix1<lMaxX1; ix1+=2)
+			{
+				LBMReal icellC[27];
+				D3Q27ICell icellF;
+
+				int howManySolids= iprocessor->iCellHowManySolids(bcArray, ix1, ix2, ix3);
+
+				if(howManySolids == 0 || howManySolids == 8)
+				{
+					iprocessor->readICell(fFrom, icellF, ix1, ix2, ix3);
+					xoff=0.0; 
+					yoff=0.0;
+					zoff=0.0;
+				}
+				else
+				{
+					if(!iprocessor->findNeighborICell(bcArray, fFrom, icellF, bMaxX1, bMaxX2, bMaxX3, ix1, ix2, ix3, xoff, yoff, zoff))
+					{
+						std::string err = "For "+block.lock()->toString()+" x1="+UbSystem::toString(ix1)+", x2=" + UbSystem::toString(ix2)+", x3=" + UbSystem::toString(ix3)+
+							" interpolation is not implemented for other direction"+
+							" by using in: "+(std::string)typeid(*this).name()+ 
+							" or maybe you have a solid on the block boundary";
+						UB_THROW(UbException(UB_EXARGS, err));
+					}
+				}
+
+				iprocessor->interpolateFineToCoarse(icellF, icellC, xoff, yoff, zoff);
+				this->writeICellCtoData(data, index, icellC);
+			}
+		}
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::writeICellCtoData(vector_type& data, int& index, LBMReal* icellC) 
+{
+	for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+	{
+		data[index++] = icellC[i];
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::getLocalMinMaxCF(int gMax, int& lMin, int& lMax)
+{
+	if (Utilities::isOdd(gMax))
+	{
+		if(connType == OddEvenSE || connType == OddOddNE)
+		{
+			lMin = 1;
+			lMax = gMax;
+		}
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::distributeReceiveVectors() 
+{
+	using namespace D3Q27System;
+
+	DistributionArray3DPtr  fTo = block.lock()->getKernel()->getDataSet()->getFdistributions();
+	int maxX1 = (int)fTo->getNX1();
+	int maxX2 = (int)fTo->getNX2();
+	int maxX3 = (int)fTo->getNX3();
+	int minX1 = 0;
+	int minX2 = 0;
+	int minX3 = 0;
+
+	int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+	int index = 0;
+	vector_type& data = receiver->getData();
+
+	lMinX1 = minX1; lMinX2 = minX2; lMinX3 = minX3;
+	lMaxX1 = maxX1-1; lMaxX2 = maxX2-1; lMaxX3 = maxX3-1;
+
+	switch(sendDir)
+	{
+	case E: 
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 1;
+		getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+		getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case W: 
+      ///////////////////////////////////////
+      ///DEBUG
+      //if (block.lock()->getGlobalID() == 2554)
+      //{
+      //   int test = 0;
+      //}
+      //////////////
+		lMinX1 = 2;
+		lMaxX1 = lMinX1 + 1;
+		getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+		getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;  
+	case N:
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 1;
+		getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+		getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case S:
+		lMinX2 = 2;
+		lMaxX2 = lMinX2 + 1;
+		getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+		getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case T:
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+		getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	case B:
+		lMinX3 = 2;
+		lMaxX3 = lMinX3 + 1;
+		getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+		getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+		/////E-W-N-S
+	case NE: 
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 3;
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 3;
+		getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case SW: 
+		lMinX1 = 0;
+		lMaxX1 = lMinX1 + 3;
+		lMinX2 = 0;
+		lMaxX2 = lMinX2 + 3;
+		getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case SE: 
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 3;
+		lMinX2 = 0;
+		lMaxX2 = lMinX2 + 3;
+		getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case NW: 
+		lMinX1 = 0;
+		lMaxX1 = lMinX1 + 3;
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 3;
+		getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	//	
+	//	/////T-B-E-W
+	case TE:
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 3;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	
+	case BW:
+		lMinX1 = 0;
+		lMaxX1 = lMinX1 + 3;
+		lMinX3 = 0;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+	
+	case BE:
+		lMinX1 = maxX1-4;
+		lMaxX1 = lMinX1 + 3;
+		lMinX3 = 0;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case TW:
+		lMinX1 = 0;
+		lMaxX1 = lMinX1 + 3;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	//	////////////////T-B-N-S
+	//	
+	case TN:
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 3;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case BS:
+		lMinX2 = 0;
+		lMaxX2 = lMinX2 + 3;
+		lMinX3 = 0;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case BN:
+		lMinX2 = maxX2-4;
+		lMaxX2 = lMinX2 + 3;
+		lMinX3 = 0;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+	case TS:
+		lMinX2 = 0;
+		lMaxX2 = lMinX2 + 3;
+		lMinX3 = maxX3-4;
+		lMaxX3 = lMinX3 + 3;
+		getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+		distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+		break;
+
+   //   //TNE
+   case TNE:
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+      //   TNW
+   case TNW:
+      lMinX1 = 0;
+      lMaxX1 = 3;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+      //   TSE
+   case TSE:
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = 0;
+      lMaxX2 = 3;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+      //   TSW
+   case TSW:
+      lMinX1 = 0;
+      lMaxX1 = 3;
+      lMinX2 = 0;
+      lMaxX2 = 3;
+      lMinX3 = maxX3-4;
+      lMaxX3 = maxX3-1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+      //   BNE
+   case BNE:
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = 0;
+      lMaxX3 = 3;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+      //   BNW
+   case BNW:
+      lMinX1 = 0;
+      lMaxX1 = 3;
+      lMinX2 = maxX2-4;
+      lMaxX2 = maxX2-1;
+      lMinX3 = 0;
+      lMaxX3 = 3;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+      //   BSE
+   case BSE:
+      lMinX1 = maxX1-4;
+      lMaxX1 = maxX1-1;
+      lMinX2 = 0;
+      lMaxX2 = 3;
+      lMinX3 = 0;
+      lMaxX3 = 3;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+         //BSW
+   case BSW:
+      lMinX1 = 0;
+      lMaxX1 = 3;
+      lMinX2 = 0;
+      lMaxX2 = 3;
+      lMinX3 = 0;
+      lMaxX3 = 3;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+	if(data.size() == 0) return; 
+
+	int ix1, ix2, ix3;
+	for (ix3=lMinX3; ix3<lMaxX3; ix3+=2)
+	{
+		for (ix2=lMinX2; ix2<lMaxX2; ix2+=2)
+		{
+			for (ix1=lMinX1; ix1<lMaxX1; ix1+=2)
+			{
+				D3Q27ICell icellF;
+				this->readICellFfromData(data, index, icellF);
+				iprocessor->writeICell(fTo, icellF, ix1, ix2, ix3);
+			}
+		}
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::readICellFfromData(vector_type& data, int& index, D3Q27ICell& icellF) 
+{
+	readNodeFromVector(data, index, icellF.BSW);
+	readNodeFromVector(data, index, icellF.BSE);
+	readNodeFromVector(data, index, icellF.BNW);
+	readNodeFromVector(data, index, icellF.BNE);
+	readNodeFromVector(data, index, icellF.TSW);
+	readNodeFromVector(data, index, icellF.TSE);
+	readNodeFromVector(data, index, icellF.TNW);
+	readNodeFromVector(data, index, icellF.TNE);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::readNodeFromVector(vector_type& data, int& index, LBMReal* inode)
+{
+	for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+	{
+		inode[i] = data[index++];
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3)
+{
+	using namespace D3Q27System;
+    int TminX1=minX1; int TminX2=minX2; int TminX3=minX3; int TmaxX1=maxX1; int TmaxX2=maxX2; int TmaxX3=maxX3;
+
+	if(block.lock()->hasInterpolationFlagFC(E))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 3;
+	}
+	if(block.lock()->hasInterpolationFlagFC(W))
+	{
+		if (minX1==TminX1) minX1 += 4;
+	}
+	if(block.lock()->hasInterpolationFlagFC(N))
+	{
+		if (maxX2==TmaxX2) maxX2 -= 3;
+	}
+	if(block.lock()->hasInterpolationFlagFC(S))
+	{
+		if (minX2==TminX2) minX2 += 4;
+	}
+	if(block.lock()->hasInterpolationFlagFC(T))
+	{
+		if (maxX3==TmaxX3) maxX3 -= 3;
+	}
+	if(block.lock()->hasInterpolationFlagFC(B))
+	{
+		if (minX3==TminX3) minX3 += 4;
+	}
+
+	////////////
+	/////E-W-N-S
+	if(block.lock()->hasInterpolationFlagFC(NE)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(E))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 3;
+		if (maxX2==TmaxX2) maxX2 -= 3;
+	}
+	if(block.lock()->hasInterpolationFlagFC(SW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(S))
+	{
+		if (minX1==TminX1) minX1 += 4;
+		if (minX2==TminX2) minX2 += 4;
+	}
+	if(block.lock()->hasInterpolationFlagFC(SE)&& !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(S))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 3;
+		if (minX2==TminX2) minX2 += 4;
+	}
+	if(block.lock()->hasInterpolationFlagFC(NW)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(W))
+	{
+		if (minX1==TminX1) minX1 += 4;
+		if (maxX2==TmaxX2) maxX2 -= 3;
+	}
+
+	//////T-B-E-W
+	if(block.lock()->hasInterpolationFlagFC(TE) && !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(T))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 3;
+		if (maxX3==TmaxX3) maxX3 -= 3;
+	}
+	if(block.lock()->hasInterpolationFlagFC(BW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(B))
+	{
+		if (minX1==TminX1) minX1 += 4;
+		if (minX3==TminX3) minX3 += 4;
+	}
+	if(block.lock()->hasInterpolationFlagFC(BE)&& !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(B))
+	{
+		if (maxX1==TmaxX1) maxX1 -= 3;
+		if (minX3==TminX3) minX3 += 4;
+	}
+	if(block.lock()->hasInterpolationFlagFC(TW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(T))
+	{
+		if (minX1==TminX1) minX1 += 4;
+		if (maxX3==TmaxX3) maxX3 -= 3;
+	}
+
+
+	////T-B-N-S
+	if(block.lock()->hasInterpolationFlagFC(TN)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(T))
+	{
+		if (maxX2==TmaxX2) maxX2 -= 3; 
+		if (maxX3==TmaxX3) maxX3 -= 3;
+	}
+	if(block.lock()->hasInterpolationFlagFC(BS)&& !block.lock()->hasInterpolationFlagFC(S) && !block.lock()->hasInterpolationFlagFC(B))
+	{
+		if (minX2==TminX2) minX2 += 4;
+		if (minX3==TminX3) minX3 += 4;
+	}
+	if(block.lock()->hasInterpolationFlagFC(BN)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(B))
+	{
+		if (maxX2==TmaxX2) maxX2 -= 3; 
+		if (minX3==TminX3) minX3 += 4;
+	}
+	if(block.lock()->hasInterpolationFlagFC(TS) && !block.lock()->hasInterpolationFlagFC(S) && !block.lock()->hasInterpolationFlagFC(T))
+	{
+		if (minX2==TminX2) minX2 += 4;
+		if (maxX3==TmaxX3) maxX3 -= 3;
+	}
+
+   //if (block.lock()->hasInterpolationFlagFC(D3Q27System::TNE)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::TE)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::TN)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::NE)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::T)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::N) && !block.lock()->hasInterpolationFlagFC(D3Q27System::E))
+   //if (!block.lock()->hasInterpolationFlagFC(D3Q27System::TE)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::T) && !block.lock()->hasInterpolationFlagFC(D3Q27System::E))
+   //{
+   //   if (maxX1==TmaxX1) maxX1 -= 3;
+   //   if (maxX2==TmaxX2) maxX2 -= 3;
+   //   if (maxX3==TmaxX3) maxX3 -= 3;
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  >
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3, CFconnectorType connType)
+{
+   using namespace D3Q27System;
+   int TminX1 = minX1; int TminX2 = minX2; int TminX3 = minX3; int TmaxX1 = maxX1; int TmaxX2 = maxX2; int TmaxX3 = maxX3;
+
+   if (block.lock()->hasInterpolationFlagFC(E))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 3;
+   }
+   if (block.lock()->hasInterpolationFlagFC(W))
+   {
+      if (minX1==TminX1) minX1 += 4;
+   }
+   if (block.lock()->hasInterpolationFlagFC(N))
+   {
+      if (maxX2==TmaxX2) maxX2 -= 3;
+   }
+   if (block.lock()->hasInterpolationFlagFC(S))
+   {
+      if (minX2==TminX2) minX2 += 4;
+   }
+   if (block.lock()->hasInterpolationFlagFC(T))
+   {
+      if (maxX3==TmaxX3) maxX3 -= 3;
+   }
+   if (block.lock()->hasInterpolationFlagFC(B))
+   {
+      if (minX3==TminX3) minX3 += 4;
+   }
+
+   ////////////
+   /////E-W-N-S
+   if (block.lock()->hasInterpolationFlagFC(NE)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(E))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 3;
+      if (maxX2==TmaxX2) maxX2 -= 3;
+   }
+   if (block.lock()->hasInterpolationFlagFC(SW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(S))
+   {
+      if (minX1==TminX1) minX1 += 4;
+      if (minX2==TminX2) minX2 += 4;
+   }
+   if (block.lock()->hasInterpolationFlagFC(SE)&& !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(S))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 3;
+      if (minX2==TminX2) minX2 += 4;
+   }
+   if (block.lock()->hasInterpolationFlagFC(NW)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(W))
+   {
+      if (minX1==TminX1) minX1 += 4;
+      if (maxX2==TmaxX2) maxX2 -= 3;
+   }
+
+   //////T-B-E-W
+   if (block.lock()->hasInterpolationFlagFC(TE) && !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(T))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 3;
+      if (maxX3==TmaxX3) maxX3 -= 3;
+   }
+   if (block.lock()->hasInterpolationFlagFC(BW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(B))
+   {
+      if (minX1==TminX1) minX1 += 4;
+      if (minX3==TminX3) minX3 += 4;
+   }
+   if (block.lock()->hasInterpolationFlagFC(BE)&& !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(B))
+   {
+      if (maxX1==TmaxX1) maxX1 -= 3;
+      if (minX3==TminX3) minX3 += 4;
+   }
+   if (block.lock()->hasInterpolationFlagFC(TW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(T))
+   {
+      if (minX1==TminX1) minX1 += 4;
+      if (maxX3==TmaxX3) maxX3 -= 3;
+   }
+
+
+   ////T-B-N-S
+   if (block.lock()->hasInterpolationFlagFC(TN)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(T)&& connType != none)
+   {
+      if (maxX2==TmaxX2) maxX2 -= 3;
+      if (maxX3==TmaxX3) maxX3 -= 3;
+   }
+   if (block.lock()->hasInterpolationFlagFC(BS)&& !block.lock()->hasInterpolationFlagFC(S) && !block.lock()->hasInterpolationFlagFC(B))
+   {
+      if (minX2==TminX2) minX2 += 4;
+      if (minX3==TminX3) minX3 += 4;
+   }
+   if (block.lock()->hasInterpolationFlagFC(BN)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(B))
+   {
+      if (maxX2==TmaxX2) maxX2 -= 3;
+      if (minX3==TminX3) minX3 += 4;
+   }
+   if (block.lock()->hasInterpolationFlagFC(TS) && !block.lock()->hasInterpolationFlagFC(S) && !block.lock()->hasInterpolationFlagFC(T))
+   {
+      if (minX2==TminX2) minX2 += 4;
+      if (maxX3==TmaxX3) maxX3 -= 3;
+   }
+
+   //if (block.lock()->hasInterpolationFlagFC(D3Q27System::TNE)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::TE)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::TN)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::NE)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::T)&&!block.lock()->hasInterpolationFlagFC(D3Q27System::N) && !block.lock()->hasInterpolationFlagFC(D3Q27System::E))
+   //{
+   //   if (maxX1==TmaxX1) maxX1 -= 3;
+   //   if (maxX2==TmaxX2) maxX2 -= 3;
+   //   if (maxX3==TmaxX3) maxX3 -= 3;
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::getLocalOffsets(const int& gMax, int& oMin)
+{
+	if (Utilities::isEven(gMax))
+	{
+		oMin = 0;
+	}
+	if (Utilities::isOdd(gMax))
+	{
+		oMin = -1;
+	}
+
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCOffVectorConnector< VectorTransmitter>::getLocalMins(int& minX1, int& minX2, int& minX3, const int& oMinX1, const int& oMinX2, const int& oMinX3)
+{
+	using namespace D3Q27System;
+
+	switch(sendDir)
+	{
+	case E: case W:
+		if(connType == OddEvenSE)
+			minX2 += oMinX2;
+		if(connType == OddOddNE)
+		{
+			minX2 += oMinX2;
+			minX3 += oMinX3;
+		}
+		if(connType == EvenOddNW)
+			minX3 += oMinX3;
+		break;
+	case N: case S:
+		if(connType == OddEvenSE)
+			minX1 += oMinX1;
+		if(connType == OddOddNE)
+		{
+			minX1 += oMinX1;
+			minX3 += oMinX3;
+		}
+		if(connType == EvenOddNW)
+			minX3 += oMinX3;
+		break;
+	case T: case B:
+		if(connType == OddEvenSE)
+			minX1 += oMinX1;
+		if(connType == OddOddNE)
+		{
+			minX1 += oMinX1;
+			minX2 += oMinX2;
+		}
+		if(connType == EvenOddNW)
+			minX2 += oMinX2;
+		break;
+
+		/////
+	case NE: case SW: case SE: case NW:
+		//case SW:
+		if(connType == OddEvenSE)
+			//minX2 += oMinX2;
+		if(connType == OddOddNE)
+		{
+			//minX2 += oMinX2;
+			minX3 += oMinX3;
+		}
+		if(connType == EvenOddNW)
+			minX3 += oMinX3;
+		break;
+
+		//////
+	case TE: case BW: case BE: case TW:
+		if(connType == OddEvenSE)
+	//		minX1 += oMinX1;
+		if(connType == OddOddNE)
+		{
+	//		minX1 += oMinX1;
+			minX2 += oMinX2;
+		}
+		if(connType == EvenOddNW)
+			minX2 += oMinX2;
+		break;
+
+	//	//////
+	case TN: case BS: case BN: case TS:
+		if(connType == OddEvenSE)
+			minX1 += oMinX1;
+		if(connType == OddOddNE)
+		{
+			minX1 += oMinX1;
+			//minX3 += oMinX3;
+		}
+		if(connType == EvenOddNW)
+			//minX3 += oMinX3;
+		break;
+
+	//	/////
+	//	case TNE: case TNW: case TSE: case TSW: case BNE: case BNW: case BSE: case BSW:
+	//	if(connType == OddEvenSE)
+	//	//	minX1 += oMinX1;
+	//	if(connType == OddOddNE)
+	//	{
+	//		//minX1 += oMinX1;
+	//		//minX3 += oMinX3;
+	//	}
+	//	if(connType == EvenOddNW)
+	//		//minX3 += oMinX3;
+	//	break;
+	}
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+double D3Q27ETFCOffVectorConnector<VectorTransmitter>::getSendRecieveTime()
+{
+	return 0;
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..09740a2d4849a8ea8e8c71cd838ceec625212066
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.cpp
@@ -0,0 +1 @@
+#include "D3Q27ETFCVectorConnector.h"
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ea9870807cade26e59486e7110356f2b6a0cb03
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.h
@@ -0,0 +1,537 @@
+/**
+* @file D3Q27ETFCVectorConnector.h
+* @brief Interpolation from fine level to coarse.
+* @author Kostyantyn Kucher
+* @date 08.06.2011
+*/
+#ifndef D3Q27ETFCVECTORCONNECTOR_H
+#define D3Q27ETFCVECTORCONNECTOR_H
+
+#include <vector>
+
+#include "basics/transmitter/TbTransmitter.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "MathUtil.hpp"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+class Block3D;
+enum CFconnectorType {EvenOddNW, EvenEvenSW, OddEvenSE, OddOddNE, none};
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+
+template< typename VectorTransmitter >
+class D3Q27ETFCVectorConnector : public Block3DConnector
+{
+public:
+
+protected:
+   typedef typename VectorTransmitter::value_type  vector_type;
+   typedef boost::shared_ptr< VectorTransmitter > VectorTransmitterPtr;
+public:
+   D3Q27ETFCVectorConnector(Block3DPtr block, VectorTransmitterPtr sender, VectorTransmitterPtr receiver, int sendDir, D3Q27InterpolationProcessorPtr iprocessor, CFconnectorType connType); 
+
+   bool isLocalConnector();
+   bool isRemoteConnector();
+   void init();
+
+   void sendTransmitterDataSize();
+   void receiveTransmitterDataSize();
+
+   void prepareForSend();
+   void sendVectors();
+
+   void prepareForReceive();
+   void receiveVectors();
+
+   void fillSendVectors();
+   void distributeReceiveVectors();
+
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return true; }
+
+   double getSendRecieveTime();
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1(){}
+   void sendVectorsX2(){}
+   void sendVectorsX3(){}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> block; //dieser nvd sendet daten und die empfangenen werden diesem nvd zugeordnet
+   //gegenstelle muss "inversen" connector besitzen
+
+   VectorTransmitterPtr sender, receiver;
+
+   D3Q27InterpolationProcessorPtr iprocessor;
+
+   CFconnectorType connType;
+
+   void readICellF(DistributionArray3DPtr f, D3Q27ICell& icellF, const int& x1, const int& x2, const int& x3) ;
+   void writeICellCtoData(vector_type& data, int& index, LBMReal* icellC);
+   void writeNodeToVector(vector_type& data, int& index, LBMReal* inode);
+   void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3);
+   void getLocalMinMaxCF(int gMax, int& lMin, int& lMax);
+   void fillSendVector(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+
+   void distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+   void readICellFfromData(vector_type& data, int& index, D3Q27ICell& icellF);
+   void writeICellF(DistributionArray3DPtr f, D3Q27ICell& icellF, const int& x1, const int& x2, const int& x3);
+   void readNodeFromVector(vector_type& data, int& index, LBMReal* inode);
+   void getLocalOffsets(const int& gMax, int& oMin);
+   void getLocalMins(int& minX1, int& minX2, int& minX3, const int& oMinX1, const int& oMinX2, const int& oMinX3);
+};
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+D3Q27ETFCVectorConnector<VectorTransmitter>::D3Q27ETFCVectorConnector(Block3DPtr block, VectorTransmitterPtr sender, 
+                                                                      VectorTransmitterPtr receiver, int sendDir, 
+                                                                      D3Q27InterpolationProcessorPtr iprocessor,
+                                                                      CFconnectorType connType) 
+                                                                      : Block3DConnector(sendDir)
+                                                                      , block(block)
+                                                                      , sender(sender)
+                                                                      , receiver(receiver)
+                                                                      , iprocessor(iprocessor)
+                                                                      , connType(connType)
+{
+   if( !(   sendDir==D3Q27System::E || sendDir==D3Q27System::W || sendDir==D3Q27System::N 
+      || sendDir==D3Q27System::S || sendDir==D3Q27System::T || sendDir==D3Q27System::B ) )
+   {
+      throw UbException(UB_EXARGS,"invalid constructor for this direction");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETFCVectorConnector<VectorTransmitter>::isLocalConnector()
+{ 
+   return !this->isRemoteConnector(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETFCVectorConnector<VectorTransmitter>::isRemoteConnector() 
+{ 
+   return sender->isRemoteTransmitter()  ||  receiver->isRemoteTransmitter();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::sendTransmitterDataSize()  
+{ 
+   if(sender) sender->sendDataSize(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()
+{ 
+   if(receiver) receiver->receiveDataSize(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::prepareForSend()
+{ 
+   if(sender) sender->prepareForSend(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::sendVectors()     
+{ 
+   if(sender) sender->sendData();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::prepareForReceive()     
+{ 
+   if(receiver) receiver->prepareForReceive(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::receiveVectors() 
+{ 
+   if(receiver) receiver->receiveData(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::init()
+{
+   using namespace D3Q27System;
+
+   int maxX1 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1();
+   int maxX2 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2();
+   int maxX3 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3();
+
+   int       sendSize  = 0;
+   LBMReal initValue = -999.0;
+
+   int sendDataPerNode = 27/*f*/;
+   int iCellSize = 1; //size of interpolation cell
+
+   switch(this->sendDir)
+   {		                  
+   case E : case W : sendSize = maxX2*maxX3*sendDataPerNode*iCellSize; break; 
+   case N : case S : sendSize = maxX1*maxX3*sendDataPerNode*iCellSize; break; 
+   case T : case B : sendSize = maxX1*maxX2*sendDataPerNode*iCellSize; break; 
+   default: throw UbException(UB_EXARGS,"direction not allowed in this constructor");
+   }
+    sender->getData().resize(sendSize, initValue);
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector< VectorTransmitter>::fillSendVectors() 
+{ 
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fFrom->getNX1();
+   int maxX2 = (int)fFrom->getNX2();
+   int maxX3 = (int)fFrom->getNX3();
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int oMinX1, oMinX2, oMinX3; 
+   getLocalOffsets(maxX1, oMinX1);
+   getLocalOffsets(maxX2, oMinX2);
+   getLocalOffsets(maxX3, oMinX3);
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+   int index = 0;
+   vector_type& data = sender->getData();
+
+   lMinX1 = minX1+1; lMinX2 = minX2+1; lMinX3 = minX3+1;
+   lMaxX1 = maxX1-2; lMaxX2 = maxX2-2; lMaxX3 = maxX3-2;
+
+   switch(sendDir)
+   {
+   case E: 
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX1 = maxX1-7;
+      lMaxX1 = lMinX1 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case W: 
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX1 = 5;
+      lMaxX1 = lMinX1 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;  
+   case N:
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX2 = maxX2-7;
+      lMaxX2 = lMinX2 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case S:
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX2 = 5;
+      lMaxX2 = lMinX2 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case T:
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX3 = maxX3-7;
+      lMaxX3 = lMinX3 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case B:
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX3 = 5;
+      lMaxX3 = lMinX3 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::fillSendVector(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+   int ix1, ix2, ix3;
+   for (ix3=lMinX3; ix3<lMaxX3; ix3+=2)
+   {
+      for (ix2=lMinX2; ix2<lMaxX2; ix2+=2)
+      {
+         for (ix1=lMinX1; ix1<lMaxX1; ix1+=2)
+         {
+            LBMReal icellC[27];
+            D3Q27ICell icellF;
+            this->readICellF(fFrom, icellF, ix1, ix2, ix3);
+            iprocessor->interpolateFineToCoarse(icellF, icellC);
+            this->writeICellCtoData(data, index, icellC);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::readICellF(DistributionArray3DPtr f, D3Q27ICell& icellF, const int& x1, const int& x2, const int& x3) 
+{
+   f->getDistribution(icellF.BSW, x1, x2, x3);
+   f->getDistribution(icellF.BSE, x1+1, x2, x3);
+   f->getDistribution(icellF.BNW, x1, x2+1, x3);
+   f->getDistribution(icellF.BNE, x1+1, x2+1, x3);
+   f->getDistribution(icellF.TSW, x1, x2, x3+1);
+   f->getDistribution(icellF.TSE, x1+1, x2, x3+1);
+   f->getDistribution(icellF.TNW, x1, x2+1, x3+1);
+   f->getDistribution(icellF.TNE, x1+1, x2+1, x3+1);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::writeICellCtoData(vector_type& data, int& index, LBMReal* icellC) 
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      data[index++] = icellC[i];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::getLocalMinMaxCF(int gMax, int& lMin, int& lMax)
+{
+   if (Utilities::isOdd(gMax))
+   {
+      if(connType == OddEvenSE || connType == OddOddNE)
+      {
+         lMin = 1;
+         lMax = gMax;
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::distributeReceiveVectors() 
+{
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fTo = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fTo->getNX1();
+   int maxX2 = (int)fTo->getNX2();
+   int maxX3 = (int)fTo->getNX3();
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+   int index = 0;
+   vector_type& data = receiver->getData();
+
+   lMinX1 = minX1; lMinX2 = minX2; lMinX3 = minX3;
+   lMaxX1 = maxX1-1; lMaxX2 = maxX2-1; lMaxX3 = maxX3-1;
+
+   switch(sendDir)
+   {
+   case E: 
+      lMinX1 = maxX1-4;
+      lMaxX1 = lMinX1 + 1;
+      getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+      getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case W: 
+      lMinX1 = 2;
+      lMaxX1 = lMinX1 + 1;
+      getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+      getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;  
+   case N:
+      lMinX2 = maxX2-4;
+      lMaxX2 = lMinX2 + 1;
+      getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+      getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case S:
+      lMinX2 = 2;
+      lMaxX2 = lMinX2 + 1;
+      getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+      getLocalMinMaxCF(maxX3, lMinX3, lMaxX3);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case T:
+      lMinX3 = maxX3-4;
+      lMaxX3 = lMinX3 + 1;
+      getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+      getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case B:
+      lMinX3 = 2;
+      lMaxX3 = lMinX3 + 1;
+      getLocalMinMaxCF(maxX1, lMinX1, lMaxX1);
+      getLocalMinMaxCF(maxX2, lMinX2, lMaxX2);
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+   int ix1, ix2, ix3;
+   for (ix3=lMinX3; ix3<lMaxX3; ix3+=2)
+   {
+      for (ix2=lMinX2; ix2<lMaxX2; ix2+=2)
+      {
+         for (ix1=lMinX1; ix1<lMaxX1; ix1+=2)
+         {
+            D3Q27ICell icellF;
+            this->readICellFfromData(data, index, icellF);
+            this->writeICellF(fTo, icellF, ix1, ix2, ix3);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::writeICellF(DistributionArray3DPtr f, D3Q27ICell& icellF, const int& x1, const int& x2, const int& x3) 
+{
+   f->setDistributionInv(icellF.BSW, x1, x2, x3);
+   f->setDistributionInv(icellF.BSE, x1+1, x2, x3);
+   f->setDistributionInv(icellF.BNW, x1, x2+1, x3);
+   f->setDistributionInv(icellF.BNE, x1+1, x2+1, x3);
+   f->setDistributionInv(icellF.TSW, x1, x2, x3+1);
+   f->setDistributionInv(icellF.TSE, x1+1, x2, x3+1);
+   f->setDistributionInv(icellF.TNW, x1, x2+1, x3+1);
+   f->setDistributionInv(icellF.TNE, x1+1, x2+1, x3+1);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::readICellFfromData(vector_type& data, int& index, D3Q27ICell& icellF) 
+{
+   readNodeFromVector(data, index, icellF.BSW);
+   readNodeFromVector(data, index, icellF.BSE);
+   readNodeFromVector(data, index, icellF.BNW);
+   readNodeFromVector(data, index, icellF.BNE);
+   readNodeFromVector(data, index, icellF.TSW);
+   readNodeFromVector(data, index, icellF.TSE);
+   readNodeFromVector(data, index, icellF.TNW);
+   readNodeFromVector(data, index, icellF.TNE);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::readNodeFromVector(vector_type& data, int& index, LBMReal* inode)
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      inode[i] = data[index++];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3)
+{
+   using namespace D3Q27System;
+
+   if(block.lock()->hasInterpolationFlagFC(E))
+   {
+      maxX1 -= 3;
+   }
+   if(block.lock()->hasInterpolationFlagFC(W))
+   {
+      minX1 += 4;
+   }
+   if(block.lock()->hasInterpolationFlagFC(N))
+   {
+      maxX2 -= 3;
+   }
+   if(block.lock()->hasInterpolationFlagFC(S))
+   {
+      minX2 += 4;
+   }
+   if(block.lock()->hasInterpolationFlagFC(T))
+   {
+      maxX3 -= 3;
+   }
+   if(block.lock()->hasInterpolationFlagFC(B))
+   {
+      minX3 += 4;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::getLocalOffsets(const int& gMax, int& oMin)
+{
+   if (Utilities::isEven(gMax))
+   {
+      oMin = 0;
+   }
+   if (Utilities::isOdd(gMax))
+   {
+      oMin = -1;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::getLocalMins(int& minX1, int& minX2, int& minX3, const int& oMinX1, const int& oMinX2, const int& oMinX3)
+{
+   using namespace D3Q27System;
+
+   switch(sendDir)
+   {
+   case E: case W:
+      if(connType == OddEvenSE)
+         minX2 += oMinX2;
+      if(connType == OddOddNE)
+      {
+         minX2 += oMinX2;
+         minX3 += oMinX3;
+      }
+      if(connType == EvenOddNW)
+         minX3 += oMinX3;
+      break;
+   case N: case S:
+      if(connType == OddEvenSE)
+         minX1 += oMinX1;
+      if(connType == OddOddNE)
+      {
+         minX1 += oMinX1;
+         minX3 += oMinX3;
+      }
+      if(connType == EvenOddNW)
+         minX3 += oMinX3;
+      break;
+   case T: case B:
+      if(connType == OddEvenSE)
+         minX1 += oMinX1;
+      if(connType == OddOddNE)
+      {
+         minX1 += oMinX1;
+         minX2 += oMinX2;
+      }
+      if(connType == EvenOddNW)
+         minX2 += oMinX2;
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+double D3Q27ETFCVectorConnector<VectorTransmitter>::getSendRecieveTime()
+{
+   return 0;
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.h.bak b/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.h.bak
new file mode 100644
index 0000000000000000000000000000000000000000..aae19e2d5fc9a3a657832e9f8564a7ff3a017f3e
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFCVectorConnector.h.bak
@@ -0,0 +1,511 @@
+/**
+* @file D3Q27ETFCVectorConnector.h
+* @brief Interpolation from fine level to coarse.
+* @author Kostyantyn Kucher
+* @date 08.06.2011
+*/
+#ifndef D3Q27ETFCVECTORCONNECTOR_H
+#define D3Q27ETFCVECTORCONNECTOR_H
+
+#include <vector>
+
+#include "basics/transmitter/TbTransmitter.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "MathUtil.hpp"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+class Block3D;
+enum CFconnectorType {EvenOddNW, EvenEvenSW, OddEvenSE, OddOddNE};
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+
+template< typename VectorTransmitter >
+class D3Q27ETFCVectorConnector : public Block3DConnector
+{
+public:
+
+protected:
+   typedef typename VectorTransmitter::value_type  vector_type;
+   typedef boost::shared_ptr< VectorTransmitter > VectorTransmitterPtr;
+public:
+   D3Q27ETFCVectorConnector(Block3DPtr block, VectorTransmitterPtr sender, VectorTransmitterPtr receiver, int sendDir, D3Q27InterpolationProcessorPtr iprocessor, CFconnectorType connType); 
+
+   bool isLocalConnector();
+   bool isRemoteConnector();
+   void init();
+
+   void sendTransmitterDataSize();
+   void receiveTransmitterDataSize();
+
+   void prepareForSend();
+   void sendVectors();
+
+   void prepareForReceive();
+   void receiveVectors();
+
+   void fillSendVectors();
+   void distributeReceiveVectors();
+
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return true; }
+
+   double getSendRecieveTime();
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1(){}
+   void sendVectorsX2(){}
+   void sendVectorsX3(){}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> block; //dieser nvd sendet daten und die empfangenen werden diesem nvd zugeordnet
+   //gegenstelle muss "inversen" connector besitzen
+
+   VectorTransmitterPtr sender, receiver;
+
+   D3Q27InterpolationProcessorPtr iprocessor;
+
+   CFconnectorType connType;
+
+   void readICellF(DistributionArray3DPtr f, D3Q27ICell& icellF, const int& x1, const int& x2, const int& x3) ;
+   void writeICellCtoData(vector_type& data, int& index, LBMReal* icellC);
+   void writeNodeToVector(vector_type& data, int& index, LBMReal* inode);
+   void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3);
+   void fillSendVector(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+
+   void distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index);
+   void readICellFfromData(vector_type& data, int& index, D3Q27ICell& icellF);
+   void writeICellF(DistributionArray3DPtr f, D3Q27ICell& icellF, const int& x1, const int& x2, const int& x3);
+   void readNodeFromVector(vector_type& data, int& index, LBMReal* inode);
+   void getLocalOffsets(const int& gMax, int& oMin);
+   void getLocalMins(int& minX1, int& minX2, int& minX3, const int& oMinX1, const int& oMinX2, const int& oMinX3);
+};
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+D3Q27ETFCVectorConnector<VectorTransmitter>::D3Q27ETFCVectorConnector(Block3DPtr block, VectorTransmitterPtr sender, 
+                                                                      VectorTransmitterPtr receiver, int sendDir, 
+                                                                      D3Q27InterpolationProcessorPtr iprocessor,
+                                                                      CFconnectorType connType) 
+                                                                      : Block3DConnector(sendDir)
+                                                                      , block(block)
+                                                                      , sender(sender)
+                                                                      , receiver(receiver)
+                                                                      , iprocessor(iprocessor)
+                                                                      , connType(connType)
+{
+   if( !(   sendDir==D3Q27System::E || sendDir==D3Q27System::W || sendDir==D3Q27System::N 
+      || sendDir==D3Q27System::S || sendDir==D3Q27System::T || sendDir==D3Q27System::B ) )
+   {
+      throw UbException(UB_EXARGS,"invalid constructor for this direction");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETFCVectorConnector<VectorTransmitter>::isLocalConnector()
+{ 
+   return !this->isRemoteConnector(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETFCVectorConnector<VectorTransmitter>::isRemoteConnector() 
+{ 
+   return sender->isRemoteTransmitter()  ||  receiver->isRemoteTransmitter();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::sendTransmitterDataSize()  
+{ 
+   if(sender) sender->sendDataSize(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::receiveTransmitterDataSize()
+{ 
+   if(receiver) receiver->receiveDataSize(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::prepareForSend()
+{ 
+   if(sender) sender->prepareForSend(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::sendVectors()     
+{ 
+   if(sender) sender->sendData();
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::prepareForReceive()     
+{ 
+   if(receiver) receiver->prepareForReceive(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::receiveVectors() 
+{ 
+   if(receiver) receiver->receiveData(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector<VectorTransmitter>::init()
+{
+   using namespace D3Q27System;
+
+   int maxX1 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1();
+   int maxX2 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2();
+   int maxX3 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3();
+
+   int       sendSize  = 0;
+   LBMReal initValue = -999.0;
+
+   int sendDataPerNode = 27/*f*/;
+   int iCellSize = 8; //size of interpolation cell
+
+   switch(this->sendDir)
+   {		                  
+   case E : case W : sendSize = maxX2*maxX3*sendDataPerNode*iCellSize; break; 
+   case N : case S : sendSize = maxX1*maxX3*sendDataPerNode*iCellSize; break; 
+   case T : case B : sendSize = maxX1*maxX2*sendDataPerNode*iCellSize; break; 
+   default: throw UbException(UB_EXARGS,"direction not allowed in this constructor");
+   }
+    sender->getData().resize(sendSize, initValue);
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETFCVectorConnector< VectorTransmitter>::fillSendVectors() 
+{ 
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fFrom->getNX1();
+   int maxX2 = (int)fFrom->getNX2();
+   int maxX3 = (int)fFrom->getNX3();
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int oMinX1, oMinX2, oMinX3; 
+   getLocalOffsets(maxX1, oMinX1);
+   getLocalOffsets(maxX2, oMinX2);
+   getLocalOffsets(maxX3, oMinX3);
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+   int index = 0;
+   vector_type& data = sender->getData();
+
+   lMinX1 = minX1+1; lMinX2 = minX2+1; lMinX3 = minX3+1;
+   lMaxX1 = maxX1-2; lMaxX2 = maxX2-2; lMaxX3 = maxX3-2;
+
+   switch(sendDir)
+   {
+   case E: 
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX1 = maxX1-7;
+      lMaxX1 = lMinX1 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case W: 
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX1 = 5;
+      lMaxX1 = lMinX1 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;  
+   case N:
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX2 = maxX2-7;
+      lMaxX2 = lMinX2 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case S:
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX2 = 5;
+      lMaxX2 = lMinX2 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case T:
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX3 = maxX3-7;
+      lMaxX3 = lMinX3 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case B:
+      getLocalMinMax(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3);
+      getLocalMins(lMinX1, lMinX2, lMinX3, oMinX1, oMinX2, oMinX3);
+      lMinX3 = 5;
+      lMaxX3 = lMinX3 + 1;
+      fillSendVector(fFrom, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::fillSendVector(DistributionArray3DPtr fFrom, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+   int ix1, ix2, ix3;
+   for (ix3=lMinX3; ix3<lMaxX3; ix3+=2)
+   {
+      for (ix2=lMinX2; ix2<lMaxX2; ix2+=2)
+      {
+         for (ix1=lMinX1; ix1<lMaxX1; ix1+=2)
+         {
+            LBMReal icellC[27];
+            D3Q27ICell icellF;
+            this->readICellF(fFrom, icellF, ix1, ix2, ix3);
+            iprocessor->interpolateFineToCoarse(icellF, icellC);
+            this->writeICellCtoData(data, index, icellC);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::readICellF(DistributionArray3DPtr f, D3Q27ICell& icellF, const int& x1, const int& x2, const int& x3) 
+{
+   f->getDistribution(icellF.BSW, x1, x2, x3);
+   f->getDistribution(icellF.BSE, x1+1, x2, x3);
+   f->getDistribution(icellF.BNW, x1, x2+1, x3);
+   f->getDistribution(icellF.BNE, x1+1, x2+1, x3);
+   f->getDistribution(icellF.TSW, x1, x2, x3+1);
+   f->getDistribution(icellF.TSE, x1+1, x2, x3+1);
+   f->getDistribution(icellF.TNW, x1, x2+1, x3+1);
+   f->getDistribution(icellF.TNE, x1+1, x2+1, x3+1);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::writeICellCtoData(vector_type& data, int& index, LBMReal* icellC) 
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      data[index++] = icellC[i];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::distributeReceiveVectors() 
+{
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fTo = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fTo->getNX1();
+   int maxX2 = (int)fTo->getNX2();
+   int maxX3 = (int)fTo->getNX3();
+   int minX1 = 0;
+   int minX2 = 0;
+   int minX3 = 0;
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+   int index = 0;
+   vector_type& data = receiver->getData();
+
+   lMinX1 = minX1; lMinX2 = minX2; lMinX3 = minX3;
+   lMaxX1 = maxX1-1; lMaxX2 = maxX2-1; lMaxX3 = maxX3-1;
+
+   switch(sendDir)
+   {
+   case E: 
+      lMinX1 = maxX1-4;
+      lMaxX1 = lMinX1 + 1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case W: 
+      lMinX1 = 2;
+      lMaxX1 = lMinX1 + 1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;  
+   case N:
+      lMinX2 = maxX2-4;
+      lMaxX2 = lMinX2 + 1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case S:
+      lMinX2 = 2;
+      lMaxX2 = lMinX2 + 1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case T:
+      lMinX3 = maxX3-4;
+      lMaxX3 = lMinX3 + 1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   case B:
+      lMinX3 = 2;
+      lMaxX3 = lMinX3 + 1;
+      distributeReceiveVector(fTo, lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, data, index);
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::distributeReceiveVector(DistributionArray3DPtr fTo, const int& lMinX1, const int& lMinX2, const int& lMinX3, const int& lMaxX1, const int& lMaxX2, const int& lMaxX3, vector_type& data, int& index)
+{
+   int ix1, ix2, ix3;
+   for (ix3=lMinX3; ix3<lMaxX3; ix3+=2)
+   {
+      for (ix2=lMinX2; ix2<lMaxX2; ix2+=2)
+      {
+         for (ix1=lMinX1; ix1<lMaxX1; ix1+=2)
+         {
+            D3Q27ICell icellF;
+            this->readICellFfromData(data, index, icellF);
+            this->writeICellF(fTo, icellF, ix1, ix2, ix3);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::writeICellF(DistributionArray3DPtr f, D3Q27ICell& icellF, const int& x1, const int& x2, const int& x3) 
+{
+   f->setDistributionInv(icellF.BSW, x1, x2, x3);
+   f->setDistributionInv(icellF.BSE, x1+1, x2, x3);
+   f->setDistributionInv(icellF.BNW, x1, x2+1, x3);
+   f->setDistributionInv(icellF.BNE, x1+1, x2+1, x3);
+   f->setDistributionInv(icellF.TSW, x1, x2, x3+1);
+   f->setDistributionInv(icellF.TSE, x1+1, x2, x3+1);
+   f->setDistributionInv(icellF.TNW, x1, x2+1, x3+1);
+   f->setDistributionInv(icellF.TNE, x1+1, x2+1, x3+1);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::readICellFfromData(vector_type& data, int& index, D3Q27ICell& icellF) 
+{
+   readNodeFromVector(data, index, icellF.BSW);
+   readNodeFromVector(data, index, icellF.BSE);
+   readNodeFromVector(data, index, icellF.BNW);
+   readNodeFromVector(data, index, icellF.BNE);
+   readNodeFromVector(data, index, icellF.TSW);
+   readNodeFromVector(data, index, icellF.TSE);
+   readNodeFromVector(data, index, icellF.TNW);
+   readNodeFromVector(data, index, icellF.TNE);
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::readNodeFromVector(vector_type& data, int& index, LBMReal* inode)
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      inode[i] = data[index++];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3)
+{
+   using namespace D3Q27System;
+
+   if(block.lock()->hasInterpolationFlagFC(E))
+   {
+      maxX1 -= 3;
+   }
+   if(block.lock()->hasInterpolationFlagFC(W))
+   {
+      minX1 += 4;
+   }
+   if(block.lock()->hasInterpolationFlagFC(N))
+   {
+      maxX2 -= 3;
+   }
+   if(block.lock()->hasInterpolationFlagFC(S))
+   {
+      minX2 += 4;
+   }
+   if(block.lock()->hasInterpolationFlagFC(T))
+   {
+      maxX3 -= 3;
+   }
+   if(block.lock()->hasInterpolationFlagFC(B))
+   {
+      minX3 += 4;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::getLocalOffsets(const int& gMax, int& oMin)
+{
+   if (MathUtil::isEven(gMax))
+   {
+      oMin = 0;
+   }
+   if (MathUtil::isOdd(gMax))
+   {
+      oMin = -1;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+template<  typename VectorTransmitter  > 
+void D3Q27ETFCVectorConnector< VectorTransmitter>::getLocalMins(int& minX1, int& minX2, int& minX3, const int& oMinX1, const int& oMinX2, const int& oMinX3)
+{
+   using namespace D3Q27System;
+
+   switch(sendDir)
+   {
+   case E: case W:
+      if(connType == OddEvenSE)
+         minX2 += oMinX2;
+      if(connType == OddOddNE)
+      {
+         minX2 += oMinX2;
+         minX3 += oMinX3;
+      }
+      if(connType == EvenOddNW)
+         minX3 += oMinX3;
+      break;
+   case N: case S:
+      if(connType == OddEvenSE)
+         minX1 += oMinX1;
+      if(connType == OddOddNE)
+      {
+         minX1 += oMinX1;
+         minX3 += oMinX3;
+      }
+      if(connType == EvenOddNW)
+         minX3 += oMinX3;
+      break;
+   case T: case B:
+      if(connType == OddEvenSE)
+         minX1 += oMinX1;
+      if(connType == OddOddNE)
+      {
+         minX1 += oMinX1;
+         minX2 += oMinX2;
+      }
+      if(connType == EvenOddNW)
+         minX2 += oMinX2;
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+double D3Q27ETFCVectorConnector<VectorTransmitter>::getSendRecieveTime()
+{
+   return 0;
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..871834d190b09346402121e6e905df4b549186d2
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.cpp
@@ -0,0 +1,257 @@
+#include "D3Q27ETFullDirectConnector.h"
+#include "LBMKernelETD3Q27.h"
+#include "EsoTwistD3Q27System.h"
+
+
+using namespace std;
+
+D3Q27ETFullDirectConnector::D3Q27ETFullDirectConnector(Block3DPtr from, Block3DPtr to, int sendDir)
+   : LocalBlock3DConnector(from, to, sendDir)
+
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27ETFullDirectConnector::~D3Q27ETFullDirectConnector()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullDirectConnector::init()
+{
+   fFrom =  boost::dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions());
+   fTo   = boost::dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions());
+
+   maxX2 = (int)fFrom->getNX2()-1;
+   maxX3 = (int)fFrom->getNX3()-1;
+   maxX1 = (int)fFrom->getNX1()-1;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullDirectConnector::sendVectors()
+{
+   //EAST
+   if(sendDir==D3Q27System::E)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fillData(fFrom,maxX1-1,x2,x3);
+            distributeData(fTo,0,x2,x3);
+         }
+      }
+   }
+   //WEST
+   else if(sendDir==D3Q27System::W)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fillData(fFrom,1,x2,x3);
+            distributeData(fTo,maxX1,x2,x3);
+         }
+      }
+   }
+   //NORTH
+   else if(sendDir==D3Q27System::N)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)        
+         {                                    
+            fillData(fFrom,x1,maxX2-1,x3);
+            distributeData(fTo,x1,0,x3);
+         }
+      }
+   }
+   //SOUTH
+   else if(sendDir==D3Q27System::S)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(fFrom,x1,1,x3);
+            distributeData(fTo,x1,maxX2,x3);
+         }
+      }
+   }
+
+   //TOP
+   else if(sendDir==D3Q27System::T)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(fFrom,x1,x2,maxX3-1);
+            distributeData(fTo,x1,x2,0);
+         }
+      }
+   }
+   //BOTTOM
+   else if(sendDir==D3Q27System::B)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(fFrom,x1,x2,1);
+            distributeData(fTo,x1,x2,maxX3);
+         }
+      }
+   }
+   //NORTHEAST
+   else if(sendDir==D3Q27System::NE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(fFrom,maxX1-1,maxX2-1,x3);
+         distributeData(fTo,0,0,x3);
+      }
+   }
+   //NORTHWEST
+   else if(sendDir==D3Q27System::NW)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(fFrom,1,maxX2-1,x3);
+         distributeData(fTo,maxX1,0,x3);
+      }
+   }
+   //SOUTHWEST
+   else if(sendDir==D3Q27System::SW)
+   {  
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(fFrom,1,1,x3);
+         distributeData(fTo,maxX1,maxX2,x3);
+      }
+   }
+   //SOUTHEAST
+   else if(sendDir==D3Q27System::SE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(fFrom,maxX1-1,1,x3);
+         distributeData(fTo,0,maxX2,x3);
+      }
+   }
+   else if(sendDir==D3Q27System::TE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(fFrom,maxX1-1,x2,maxX3-1);
+         distributeData(fTo,0,x2,0);
+      }
+   else if(sendDir==D3Q27System::BW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(fFrom,1,x2,1);
+         distributeData(fTo,maxX1,x2,maxX3);
+      }
+   else if(sendDir==D3Q27System::BE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(fFrom,maxX1-1,x2,1);
+         distributeData(fTo,0,x2,maxX3);
+      }
+   else if(sendDir==D3Q27System::TW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(fFrom,1,x2,maxX3-1);
+         distributeData(fTo,maxX1,x2,0);
+      }
+   else if(sendDir==D3Q27System::TN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(fFrom,x1,maxX2-1,maxX3-1);
+         distributeData(fTo,x1,0,0);
+      }
+   else if(sendDir==D3Q27System::BS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(fFrom,x1,1,1);
+         distributeData(fTo,x1,maxX2,maxX3);
+      }
+   else if(sendDir==D3Q27System::BN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(fFrom,x1,maxX2-1,1);
+         distributeData(fTo,x1,0,maxX3);
+      }
+
+   else if(sendDir==D3Q27System::TS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(fFrom,x1,1,maxX3-1);
+         distributeData(fTo,x1,maxX2,0);
+      }
+
+   else if(sendDir==D3Q27System::TSW)
+   {
+      fillData(fFrom,1,1,maxX3-1);
+      distributeData(fTo,maxX1,maxX2,0);
+   }
+   else if(sendDir==D3Q27System::TSE)
+   {
+      fillData(fFrom,maxX1-1,1,maxX3-1);
+      distributeData(fTo,0,maxX2,0);
+   }
+   else if(sendDir==D3Q27System::TNW)
+   {
+      fillData(fFrom,1,maxX2-1,maxX3-1);
+      distributeData(fTo,maxX1,0,0);
+   }
+   else if(sendDir==D3Q27System::TNE)
+   {
+      fillData(fFrom,maxX1-1,maxX2-1,maxX3-1);
+      distributeData(fTo,0,0,0);
+   }
+   else if(sendDir==D3Q27System::BSW)
+   {
+      fillData(fFrom,1,1,1);
+      distributeData(fTo,maxX1,maxX2,maxX3);
+   }
+   else if(sendDir==D3Q27System::BSE)
+   {
+      fillData(fFrom,maxX1-1,1,1);
+      distributeData(fTo,0,maxX2,maxX3);
+   }
+   else if(sendDir==D3Q27System::BNW)
+   {
+      fillData(fFrom,1,maxX2-1,1);
+      distributeData(fTo,maxX1,0,maxX3);
+   }
+   else if(sendDir==D3Q27System::BNE)
+   {
+      fillData(fFrom,maxX1-1,maxX2-1,1);
+      distributeData(fTo,0,0,maxX3);
+   }
+   else UB_THROW( UbException(UB_EXARGS,"unknown dir") );
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullDirectConnector::fillData(EsoTwist3DPtr  fFrom, const int& x1, const int& x2, const int& x3)
+{
+   if(invStep)
+   {
+      fFrom->getDistribution(f,x1,x2,x3);
+   }
+   else
+   {
+      fFrom->getDistributionInv(f,x1,x2,x3);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullDirectConnector::distributeData(EsoTwist3DPtr  fTo, const int& x1, const int& x2, const int& x3)
+{
+   if(invStep)
+   {
+      fTo->setDistributionInv(f,x1,x2,x3);
+   }
+   else
+   {
+      fTo->setDistribution(f,x1,x2,x3);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd93b325de164c6c13c8d1a189dd843d72271c17
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector.h
@@ -0,0 +1,39 @@
+/**
+* @file D3Q27ETFullDirectConnector.h
+* @brief Connector send and receive full distribution in shared memory
+*         
+* @author Kostyantyn Kucher
+* @date 08.06.2011
+*/
+#ifndef D3Q27ETFULLDIRECTCONNECTOR_H
+#define D3Q27ETFULLDIRECTCONNECTOR_H
+
+#include <boost/weak_ptr.hpp>
+
+#include "LocalBlock3DConnector.h"
+#include "Block3D.h"
+#include "D3Q27System.h"
+
+class D3Q27ETFullDirectConnector : public LocalBlock3DConnector
+{
+public:
+   D3Q27ETFullDirectConnector(Block3DPtr from, Block3DPtr to, int sendDir);
+   virtual ~D3Q27ETFullDirectConnector();
+   void init();                       
+   void sendVectors();
+
+ protected:
+   EsoTwist3DPtr  fFrom;
+   EsoTwist3DPtr  fTo;
+   int maxX1;
+   int maxX2;
+   int maxX3;
+   LBMReal f[D3Q27System::ENDF+1];
+
+   void fillData(EsoTwist3DPtr  fFrom, const int& x1, const int& x2, const int& x3);
+   void distributeData(EsoTwist3DPtr  fTo, const int& x1, const int& x2, const int& x3);
+};
+
+
+#endif 
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3056fc7137fbe934b6dfe560959f559e0b5ba5f5
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.cpp
@@ -0,0 +1,289 @@
+#include "D3Q27ETFullDirectConnector2.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+
+
+using namespace std;
+
+D3Q27ETFullDirectConnector2::D3Q27ETFullDirectConnector2(Block3DPtr from, Block3DPtr to, int sendDir) 
+   : LocalBlock3DConnector(from, to, sendDir)
+
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullDirectConnector2::init()
+{
+   maxX1 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1()-1;
+   maxX2 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2()-1;
+   maxX3 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3()-1;
+
+   fFrom =  boost::dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions());
+   fTo   = boost::dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions());
+
+   //localDistributionsFrom = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+   //nonLocalDistributionsFrom = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   //zeroDistributionsFrom = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getZeroDistributions();
+
+   //localDistributionsTo = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+   //nonLocalDistributionsTo = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   //zeroDistributionsTo = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getZeroDistributions();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullDirectConnector2::sendVectors()
+{
+   //EsoTwist3DPtr  fFrom =  boost::dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions());
+   //EsoTwist3DPtr  fTo   = boost::dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions());
+
+   //int maxX1 = (int)fFrom->getNX1()-1;
+   //int maxX2 = (int)fFrom->getNX2()-1;
+   //int maxX3 = (int)fFrom->getNX3()-1;
+
+   //LBMReal f[D3Q27System::ENDF+1];
+
+   //localDistributionsFrom    = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+   //nonLocalDistributionsFrom = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   //zeroDistributionsFrom     = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getZeroDistributions();
+
+   //localDistributionsTo      = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+   //nonLocalDistributionsTo   = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   //zeroDistributionsTo       = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getZeroDistributions();
+
+   localDistributionsFrom = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fFrom)->getLocalDistributions();
+   nonLocalDistributionsFrom = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fFrom)->getNonLocalDistributions();
+   zeroDistributionsFrom = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fFrom)->getZeroDistributions();
+
+   localDistributionsTo = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fTo)->getLocalDistributions();
+   nonLocalDistributionsTo = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fTo)->getNonLocalDistributions();
+   zeroDistributionsTo = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->fTo)->getZeroDistributions();
+
+   //EAST
+   if(sendDir==D3Q27System::E)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fillData(maxX1-1,x2,x3);
+            distributeData(0,x2,x3);
+         }
+      }
+   }
+   //WEST
+   else if(sendDir==D3Q27System::W)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fillData(1,x2,x3);
+            distributeData(maxX1,x2,x3);
+         }
+      }
+   }
+   //NORTH
+   else if(sendDir==D3Q27System::N)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)        
+         {                                    
+            fillData(x1,maxX2-1,x3);
+            distributeData(x1,0,x3);
+         }
+      }
+   }
+   //SOUTH
+   else if(sendDir==D3Q27System::S)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(x1,1,x3);
+            distributeData(x1,maxX2,x3);
+         }
+      }
+   }
+
+   //TOP
+   else if(sendDir==D3Q27System::T)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(x1,x2,maxX3-1);
+            distributeData(x1,x2,0);
+         }
+      }
+   }
+   //BOTTOM
+   else if(sendDir==D3Q27System::B)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(x1,x2,1);
+            distributeData(x1,x2,maxX3);
+         }
+      }
+   }
+   //NORTHEAST
+   else if(sendDir==D3Q27System::NE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(maxX1-1,maxX2-1,x3);
+         distributeData(0,0,x3);
+      }
+   }
+   //NORTHWEST
+   else if(sendDir==D3Q27System::NW)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(1,maxX2-1,x3);
+         distributeData(maxX1,0,x3);
+      }
+   }
+   //SOUTHWEST
+   else if(sendDir==D3Q27System::SW)
+   {  
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(1,1,x3);
+         distributeData(maxX1,maxX2,x3);
+      }
+   }
+   //SOUTHEAST
+   else if(sendDir==D3Q27System::SE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(maxX1-1,1,x3);
+         distributeData(0,maxX2,x3);
+      }
+   }
+   else if(sendDir==D3Q27System::TE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(maxX1-1,x2,maxX3-1);
+         distributeData(0,x2,0);
+      }
+   else if(sendDir==D3Q27System::BW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(1,x2,1);
+         distributeData(maxX1,x2,maxX3);
+      }
+   else if(sendDir==D3Q27System::BE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(maxX1-1,x2,1);
+         distributeData(0,x2,maxX3);
+      }
+   else if(sendDir==D3Q27System::TW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(1,x2,maxX3-1);
+         distributeData(maxX1,x2,0);
+      }
+   else if(sendDir==D3Q27System::TN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(x1,maxX2-1,maxX3-1);
+         distributeData(x1,0,0);
+      }
+   else if(sendDir==D3Q27System::BS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(x1,1,1);
+         distributeData(x1,maxX2,maxX3);
+      }
+   else if(sendDir==D3Q27System::BN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(x1,maxX2-1,1);
+         distributeData(x1,0,maxX3);
+      }
+
+   else if(sendDir==D3Q27System::TS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(x1,1,maxX3-1);
+         distributeData(x1,maxX2,0);
+      }
+
+   else if(sendDir==D3Q27System::TSW)
+   {
+      fillData(1,1,maxX3-1);
+      distributeData(maxX1,maxX2,0);
+   }
+   else if(sendDir==D3Q27System::TSE)
+   {
+      fillData(maxX1-1,1,maxX3-1);
+      distributeData(0,maxX2,0);
+   }
+   else if(sendDir==D3Q27System::TNW)
+   {
+      fillData(1,maxX2-1,maxX3-1);
+      distributeData(maxX1,0,0);
+   }
+   else if(sendDir==D3Q27System::TNE)
+   {
+      fillData(maxX1-1,maxX2-1,maxX3-1);
+      distributeData(0,0,0);
+   }
+   else if(sendDir==D3Q27System::BSW)
+   {
+      fillData(1,1,1);
+      distributeData(maxX1,maxX2,maxX3);
+   }
+   else if(sendDir==D3Q27System::BSE)
+   {
+      fillData(maxX1-1,1,1);
+      distributeData(0,maxX2,maxX3);
+   }
+   else if(sendDir==D3Q27System::BNW)
+   {
+      fillData(1,maxX2-1,1);
+      distributeData(maxX1,0,maxX3);
+   }
+   else if(sendDir==D3Q27System::BNE)
+   {
+      fillData(maxX1-1,maxX2-1,1);
+      distributeData(0,0,maxX3);
+   }
+   else UB_THROW( UbException(UB_EXARGS,"unknown dir") );
+}
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27ETFullDirectConnector2::fillData(/*EsoTwist3DPtr  fFrom,*/ int x1, int x2, int x3)
+//{
+//   if(rfStep)
+//   {
+//      fFrom->getDistribution(f,x1,x2,x3);
+//   }
+//   else
+//   {
+//      fFrom->getDistributionInv(f,x1,x2,x3);
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27ETFullDirectConnector2::distributeData(/*EsoTwist3DPtr  fTo,*/ int x1, int x2, int x3)
+//{
+//   if(rfStep)
+//   {
+//      fTo->setDistributionInv(f,x1,x2,x3);
+//   }
+//   else
+//   {
+//      fTo->setDistribution(f,x1,x2,x3);
+//   }
+//}
+//////////////////////////////////////////////////////////////////////////
+//double D3Q27ETFullDirectConnector2::getSendRecieveTime()
+//{
+//   return 0;
+//}
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.cpp_old b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.cpp_old
new file mode 100644
index 0000000000000000000000000000000000000000..78e0ee25568a4a9c36dbd88c71fce78a94486468
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.cpp_old
@@ -0,0 +1,274 @@
+#include "D3Q27ETFullDirectConnector2.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+
+
+using namespace std;
+
+D3Q27ETFullDirectConnector2::D3Q27ETFullDirectConnector2(Block3DPtr from, Block3DPtr to, const int& sendDir) 
+   :  Block3DConnector(sendDir)
+   , from(from)
+   , to(to)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullDirectConnector2::init()
+{
+   maxX1 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1()-1;
+   maxX2 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2()-1;
+   maxX3 = (int)this->from.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3()-1;
+
+   fFrom =  boost::dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions());
+   fTo   = boost::dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions());
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullDirectConnector2::sendVectors()
+{
+   //EsoTwist3DPtr  fFrom =  boost::dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions());
+   //EsoTwist3DPtr  fTo   = boost::dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions());
+
+   //int maxX1 = (int)fFrom->getNX1()-1;
+   //int maxX2 = (int)fFrom->getNX2()-1;
+   //int maxX3 = (int)fFrom->getNX3()-1;
+
+   //LBMReal f[D3Q27System::ENDF+1];
+
+   localDistributionsFrom    = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+   nonLocalDistributionsFrom = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   zeroDistributionsFrom     = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->from.lock()->getKernel()->getDataSet()->getFdistributions())->getZeroDistributions();
+
+   localDistributionsTo      = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+   nonLocalDistributionsTo   = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   zeroDistributionsTo       = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(this->to.lock()->getKernel()->getDataSet()->getFdistributions())->getZeroDistributions();
+
+   //EAST
+   if(sendDir==D3Q27System::E)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fillData(maxX1-1,x2,x3);
+            distributeData(0,x2,x3);
+         }
+      }
+   }
+   //WEST
+   else if(sendDir==D3Q27System::W)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fillData(1,x2,x3);
+            distributeData(maxX1,x2,x3);
+         }
+      }
+   }
+   //NORTH
+   else if(sendDir==D3Q27System::N)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)        
+         {                                    
+            fillData(x1,maxX2-1,x3);
+            distributeData(x1,0,x3);
+         }
+      }
+   }
+   //SOUTH
+   else if(sendDir==D3Q27System::S)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(x1,1,x3);
+            distributeData(x1,maxX2,x3);
+         }
+      }
+   }
+
+   //TOP
+   else if(sendDir==D3Q27System::T)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(x1,x2,maxX3-1);
+            distributeData(x1,x2,0);
+         }
+      }
+   }
+   //BOTTOM
+   else if(sendDir==D3Q27System::B)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fillData(x1,x2,1);
+            distributeData(x1,x2,maxX3);
+         }
+      }
+   }
+   //NORTHEAST
+   else if(sendDir==D3Q27System::NE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(maxX1-1,maxX2-1,x3);
+         distributeData(0,0,x3);
+      }
+   }
+   //NORTHWEST
+   else if(sendDir==D3Q27System::NW)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(1,maxX2-1,x3);
+         distributeData(maxX1,0,x3);
+      }
+   }
+   //SOUTHWEST
+   else if(sendDir==D3Q27System::SW)
+   {  
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(1,1,x3);
+         distributeData(maxX1,maxX2,x3);
+      }
+   }
+   //SOUTHEAST
+   else if(sendDir==D3Q27System::SE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         fillData(maxX1-1,1,x3);
+         distributeData(0,maxX2,x3);
+      }
+   }
+   else if(sendDir==D3Q27System::TE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(maxX1-1,x2,maxX3-1);
+         distributeData(0,x2,0);
+      }
+   else if(sendDir==D3Q27System::BW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(1,x2,1);
+         distributeData(maxX1,x2,maxX3);
+      }
+   else if(sendDir==D3Q27System::BE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(maxX1-1,x2,1);
+         distributeData(0,x2,maxX3);
+      }
+   else if(sendDir==D3Q27System::TW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         fillData(1,x2,maxX3-1);
+         distributeData(maxX1,x2,0);
+      }
+   else if(sendDir==D3Q27System::TN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(x1,maxX2-1,maxX3-1);
+         distributeData(x1,0,0);
+      }
+   else if(sendDir==D3Q27System::BS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(x1,1,1);
+         distributeData(x1,maxX2,maxX3);
+      }
+   else if(sendDir==D3Q27System::BN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(x1,maxX2-1,1);
+         distributeData(x1,0,maxX3);
+      }
+
+   else if(sendDir==D3Q27System::TS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fillData(x1,1,maxX3-1);
+         distributeData(x1,maxX2,0);
+      }
+
+   else if(sendDir==D3Q27System::TSW)
+   {
+      fillData(1,1,maxX3-1);
+      distributeData(maxX1,maxX2,0);
+   }
+   else if(sendDir==D3Q27System::TSE)
+   {
+      fillData(maxX1-1,1,maxX3-1);
+      distributeData(0,maxX2,0);
+   }
+   else if(sendDir==D3Q27System::TNW)
+   {
+      fillData(1,maxX2-1,maxX3-1);
+      distributeData(maxX1,0,0);
+   }
+   else if(sendDir==D3Q27System::TNE)
+   {
+      fillData(maxX1-1,maxX2-1,maxX3-1);
+      distributeData(0,0,0);
+   }
+   else if(sendDir==D3Q27System::BSW)
+   {
+      fillData(1,1,1);
+      distributeData(maxX1,maxX2,maxX3);
+   }
+   else if(sendDir==D3Q27System::BSE)
+   {
+      fillData(maxX1-1,1,1);
+      distributeData(0,maxX2,maxX3);
+   }
+   else if(sendDir==D3Q27System::BNW)
+   {
+      fillData(1,maxX2-1,1);
+      distributeData(maxX1,0,maxX3);
+   }
+   else if(sendDir==D3Q27System::BNE)
+   {
+      fillData(maxX1-1,maxX2-1,1);
+      distributeData(0,0,maxX3);
+   }
+   else UB_THROW( UbException(UB_EXARGS,"unknown dir") );
+}
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27ETFullDirectConnector2::fillData(/*EsoTwist3DPtr  fFrom,*/ int x1, int x2, int x3)
+//{
+//   if(rfStep)
+//   {
+//      fFrom->getDistribution(f,x1,x2,x3);
+//   }
+//   else
+//   {
+//      fFrom->getDistributionInv(f,x1,x2,x3);
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27ETFullDirectConnector2::distributeData(/*EsoTwist3DPtr  fTo,*/ int x1, int x2, int x3)
+//{
+//   if(rfStep)
+//   {
+//      fTo->setDistributionInv(f,x1,x2,x3);
+//   }
+//   else
+//   {
+//      fTo->setDistribution(f,x1,x2,x3);
+//   }
+//}
+//////////////////////////////////////////////////////////////////////////
+double D3Q27ETFullDirectConnector2::getSendRecieveTime()
+{
+   return 0;
+}
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.h b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.h
new file mode 100644
index 0000000000000000000000000000000000000000..61d2e0fdbd0beb7f54eabe2ca5bfe74ce532884d
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.h
@@ -0,0 +1,193 @@
+/**
+* @file D3Q27ETFullDirectConnector.h
+* @brief Connector send and receive full distribution in shared memory
+*         
+* @author Kostyantyn Kucher
+* @date 08.06.2011
+*/
+#ifndef D3Q27ETFULLDIRECTCONNECTOR2_H
+#define D3Q27ETFULLDIRECTCONNECTOR2_H
+
+#include <boost/weak_ptr.hpp>
+
+#include "LocalBlock3DConnector.h"
+#include "Block3D.h"
+#include "D3Q27System.h"
+#include "basics/container/CbArray3D.h"
+#include "basics/container/CbArray4D.h"
+
+class D3Q27ETFullDirectConnector2 : public LocalBlock3DConnector
+{
+public:
+   //D3Q27ETFullDirectConnector2() {}
+   D3Q27ETFullDirectConnector2(Block3DPtr from, Block3DPtr to, int sendDir);
+   void init();
+   void sendVectors();
+
+ protected:
+   //void fillData(EsoTwist3DPtr  fFrom, int x1, int x2, int x3);
+   //void distributeData(EsoTwist3DPtr  fTo, int x1, int x2, int x3);
+
+   //void fillData(int x1, int x2, int x3);
+   //void distributeData(int x1, int x2, int x3);
+
+   inline void fillData(int x1, int x2, int x3);
+   inline void distributeData(int x1, int x2, int x3);
+private:
+
+   LBMReal f[D3Q27System::ENDF+1];
+
+   int maxX1;
+   int maxX2;
+   int maxX3;
+
+   CbArray4D <LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributionsFrom; 
+   CbArray4D <LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributionsFrom; 
+   CbArray3D <LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributionsFrom;
+
+   CbArray4D <LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributionsTo; 
+   CbArray4D <LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributionsTo; 
+   CbArray3D <LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributionsTo;
+
+   EsoTwist3DPtr  fFrom;
+   EsoTwist3DPtr  fTo;  
+};
+
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27ETFullDirectConnector2::fillData(int x1, int x2, int x3)
+{
+   if(invStep)
+   {
+      f[D3Q27System::E] = (*this->localDistributionsFrom)(D3Q27System::ET_E, x1,x2,x3);
+      f[D3Q27System::N] = (*this->localDistributionsFrom)(D3Q27System::ET_N,x1,x2,x3);  
+      f[D3Q27System::T] = (*this->localDistributionsFrom)(D3Q27System::ET_T,x1,x2,x3);
+      f[D3Q27System::NE] = (*this->localDistributionsFrom)(D3Q27System::ET_NE,x1,x2,x3);
+      f[D3Q27System::NW] = (*this->localDistributionsFrom)(D3Q27System::ET_NW,x1+1,x2,x3);
+      f[D3Q27System::TE] = (*this->localDistributionsFrom)(D3Q27System::ET_TE,x1,x2,x3);
+      f[D3Q27System::TW] = (*this->localDistributionsFrom)(D3Q27System::ET_TW, x1+1,x2,x3);
+      f[D3Q27System::TN] = (*this->localDistributionsFrom)(D3Q27System::ET_TN,x1,x2,x3);
+      f[D3Q27System::TS] = (*this->localDistributionsFrom)(D3Q27System::ET_TS,x1,x2+1,x3);
+      f[D3Q27System::TNE] = (*this->localDistributionsFrom)(D3Q27System::ET_TNE,x1,x2,x3);
+      f[D3Q27System::TNW] = (*this->localDistributionsFrom)(D3Q27System::ET_TNW,x1+1,x2,x3);
+      f[D3Q27System::TSE] = (*this->localDistributionsFrom)(D3Q27System::ET_TSE,x1,x2+1,x3);
+      f[D3Q27System::TSW] = (*this->localDistributionsFrom)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+
+      f[D3Q27System::W ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_W,x1+1,x2,x3  );
+      f[D3Q27System::S ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_S,x1,x2+1,x3  );
+      f[D3Q27System::B ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_B,x1,x2,x3+1  );
+      f[D3Q27System::SW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+      f[D3Q27System::SE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SE,x1,x2+1,x3 );
+      f[D3Q27System::BW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+      f[D3Q27System::BE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BE,x1,x2,x3+1 );
+      f[D3Q27System::BS] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+      f[D3Q27System::BN] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BN,x1,x2,x3+1 );
+      f[D3Q27System::BSW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+      f[D3Q27System::BSE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+      f[D3Q27System::BNW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+      f[D3Q27System::BNE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNE,x1,x2,x3+1);
+
+      f[D3Q27System::ZERO] = (*this->zeroDistributionsFrom)(x1,x2,x3);
+   }
+   else
+   {
+      f[D3Q27System::INV_E] = (*this->localDistributionsFrom)(D3Q27System::ET_E, x1,x2,x3);
+      f[D3Q27System::INV_N] = (*this->localDistributionsFrom)(D3Q27System::ET_N,x1,x2,x3);  
+      f[D3Q27System::INV_T] = (*this->localDistributionsFrom)(D3Q27System::ET_T,x1,x2,x3);
+      f[D3Q27System::INV_NE] = (*this->localDistributionsFrom)(D3Q27System::ET_NE,x1,x2,x3);
+      f[D3Q27System::INV_NW] = (*this->localDistributionsFrom)(D3Q27System::ET_NW,x1+1,x2,x3);
+      f[D3Q27System::INV_TE] = (*this->localDistributionsFrom)(D3Q27System::ET_TE,x1,x2,x3);
+      f[D3Q27System::INV_TW] = (*this->localDistributionsFrom)(D3Q27System::ET_TW, x1+1,x2,x3);
+      f[D3Q27System::INV_TN] = (*this->localDistributionsFrom)(D3Q27System::ET_TN,x1,x2,x3);
+      f[D3Q27System::INV_TS] = (*this->localDistributionsFrom)(D3Q27System::ET_TS,x1,x2+1,x3);
+      f[D3Q27System::INV_TNE] = (*this->localDistributionsFrom)(D3Q27System::ET_TNE,x1,x2,x3);
+      f[D3Q27System::INV_TNW] = (*this->localDistributionsFrom)(D3Q27System::ET_TNW,x1+1,x2,x3);
+      f[D3Q27System::INV_TSE] = (*this->localDistributionsFrom)(D3Q27System::ET_TSE,x1,x2+1,x3);
+      f[D3Q27System::INV_TSW] = (*this->localDistributionsFrom)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+
+      f[D3Q27System::INV_W ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_W,x1+1,x2,x3  );
+      f[D3Q27System::INV_S ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_S,x1,x2+1,x3  );
+      f[D3Q27System::INV_B ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_B,x1,x2,x3+1  );
+      f[D3Q27System::INV_SW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+      f[D3Q27System::INV_SE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SE,x1,x2+1,x3 );
+      f[D3Q27System::INV_BW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+      f[D3Q27System::INV_BE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BE,x1,x2,x3+1 );
+      f[D3Q27System::INV_BS] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+      f[D3Q27System::INV_BN] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BN,x1,x2,x3+1 );
+      f[D3Q27System::INV_BSW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+      f[D3Q27System::INV_BSE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+      f[D3Q27System::INV_BNW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+      f[D3Q27System::INV_BNE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNE,x1,x2,x3+1);
+
+      f[D3Q27System::ZERO] = (*this->zeroDistributionsFrom)(x1,x2,x3);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27ETFullDirectConnector2::distributeData(int x1, int x2, int x3)
+{
+   if(invStep)
+   {
+      (*this->localDistributionsTo)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::E];
+      (*this->localDistributionsTo)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::N];
+      (*this->localDistributionsTo)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::T];
+      (*this->localDistributionsTo)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::NE];
+      (*this->localDistributionsTo)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::NW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::TE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::TW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::TN];
+      (*this->localDistributionsTo)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::TS];
+      (*this->localDistributionsTo)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::TNE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::TNW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::TSE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::TSW];
+
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::W ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::S ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::B ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::SW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::SE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::BW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::BE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::BS];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::BN];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::BSW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::BSE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::BNW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::BNE];
+
+      (*this->zeroDistributionsTo)(x1,x2,x3) = f[D3Q27System::ZERO];
+   }
+   else
+   {
+      (*this->localDistributionsTo)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::INV_E];
+      (*this->localDistributionsTo)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::INV_N];
+      (*this->localDistributionsTo)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::INV_T];
+      (*this->localDistributionsTo)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::INV_NE];
+      (*this->localDistributionsTo)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::INV_NW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::INV_TE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::INV_TW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::INV_TN];
+      (*this->localDistributionsTo)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::INV_TS];
+      (*this->localDistributionsTo)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::INV_TNE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::INV_TNW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::INV_TSE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::INV_TSW];
+
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::INV_W ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::INV_S ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::INV_B ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::INV_SW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::INV_SE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::INV_BW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::INV_BS];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BN];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::INV_BSW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::INV_BSE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::INV_BNW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::INV_BNE];
+
+      (*this->zeroDistributionsTo)(x1,x2,x3) = f[D3Q27System::ZERO];
+   }
+}
+#endif 
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.h_old b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.h_old
new file mode 100644
index 0000000000000000000000000000000000000000..4fd38ce2013f8619880c86c2403fbc216ea318f9
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFullDirectConnector2.h_old
@@ -0,0 +1,226 @@
+/**
+* @file D3Q27ETFullDirectConnector.h
+* @brief Connector send and receive full distribution in shared memory
+*         
+* @author Kostyantyn Kucher
+* @date 08.06.2011
+*/
+#ifndef D3Q27ETFULLDIRECTCONNECTOR2_H
+#define D3Q27ETFULLDIRECTCONNECTOR2_H
+
+#include <boost/weak_ptr.hpp>
+
+#include "Block3DConnector.h"
+#include "Block3D.h"
+#include "D3Q27System.h"
+#include "basics/container/CbArray3D.h"
+#include "basics/container/CbArray4D.h"
+
+class D3Q27ETFullDirectConnector2 : public Block3DConnector
+{
+public:
+   D3Q27ETFullDirectConnector2() {}
+   D3Q27ETFullDirectConnector2(Block3DPtr from, Block3DPtr to, const int& sendDir);
+   
+   void sendTransmitterDataSize()    { }  
+   void receiveTransmitterDataSize() { }
+   void init();
+   void prepareForReceive()          { }
+   void prepareForSend()             { }
+   void fillSendVectors()            { }
+   void sendVectors();
+   void receiveVectors()             { }
+   
+   void distributeReceiveVectors()   { }
+
+   bool isLocalConnector()  { return true;  }
+   bool isRemoteConnector() { return false; }
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return false; }
+
+   double getSendRecieveTime();
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1(){}
+   void sendVectorsX2(){}
+   void sendVectorsX3(){}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+ protected:
+   //void fillData(EsoTwist3DPtr  fFrom, int x1, int x2, int x3);
+   //void distributeData(EsoTwist3DPtr  fTo, int x1, int x2, int x3);
+
+   //void fillData(int x1, int x2, int x3);
+   //void distributeData(int x1, int x2, int x3);
+
+   inline void fillData(int x1, int x2, int x3);
+   inline void distributeData(int x1, int x2, int x3);
+private:
+   boost::weak_ptr<Block3D> from;
+   boost::weak_ptr<Block3D> to;
+   LBMReal f[D3Q27System::ENDF+1];
+
+   int maxX1;
+   int maxX2;
+   int maxX3;
+
+   CbArray4D <LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributionsFrom; 
+   CbArray4D <LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributionsFrom; 
+   CbArray3D <LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributionsFrom;
+
+   CbArray4D <LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributionsTo; 
+   CbArray4D <LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributionsTo; 
+   CbArray3D <LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributionsTo;
+
+   EsoTwist3DPtr  fFrom;
+   EsoTwist3DPtr  fTo;  
+};
+
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27ETFullDirectConnector2::fillData(int x1, int x2, int x3)
+{
+   if(invStep)
+   {
+      f[D3Q27System::E] = (*this->localDistributionsFrom)(D3Q27System::ET_E, x1,x2,x3);
+      f[D3Q27System::N] = (*this->localDistributionsFrom)(D3Q27System::ET_N,x1,x2,x3);  
+      f[D3Q27System::T] = (*this->localDistributionsFrom)(D3Q27System::ET_T,x1,x2,x3);
+      f[D3Q27System::NE] = (*this->localDistributionsFrom)(D3Q27System::ET_NE,x1,x2,x3);
+      f[D3Q27System::NW] = (*this->localDistributionsFrom)(D3Q27System::ET_NW,x1+1,x2,x3);
+      f[D3Q27System::TE] = (*this->localDistributionsFrom)(D3Q27System::ET_TE,x1,x2,x3);
+      f[D3Q27System::TW] = (*this->localDistributionsFrom)(D3Q27System::ET_TW, x1+1,x2,x3);
+      f[D3Q27System::TN] = (*this->localDistributionsFrom)(D3Q27System::ET_TN,x1,x2,x3);
+      f[D3Q27System::TS] = (*this->localDistributionsFrom)(D3Q27System::ET_TS,x1,x2+1,x3);
+      f[D3Q27System::TNE] = (*this->localDistributionsFrom)(D3Q27System::ET_TNE,x1,x2,x3);
+      f[D3Q27System::TNW] = (*this->localDistributionsFrom)(D3Q27System::ET_TNW,x1+1,x2,x3);
+      f[D3Q27System::TSE] = (*this->localDistributionsFrom)(D3Q27System::ET_TSE,x1,x2+1,x3);
+      f[D3Q27System::TSW] = (*this->localDistributionsFrom)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+
+      f[D3Q27System::W ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_W,x1+1,x2,x3  );
+      f[D3Q27System::S ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_S,x1,x2+1,x3  );
+      f[D3Q27System::B ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_B,x1,x2,x3+1  );
+      f[D3Q27System::SW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+      f[D3Q27System::SE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SE,x1,x2+1,x3 );
+      f[D3Q27System::BW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+      f[D3Q27System::BE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BE,x1,x2,x3+1 );
+      f[D3Q27System::BS] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+      f[D3Q27System::BN] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BN,x1,x2,x3+1 );
+      f[D3Q27System::BSW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+      f[D3Q27System::BSE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+      f[D3Q27System::BNW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+      f[D3Q27System::BNE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNE,x1,x2,x3+1);
+
+      f[D3Q27System::ZERO] = (*this->zeroDistributionsFrom)(x1,x2,x3);
+   }
+   else
+   {
+      f[D3Q27System::INV_E] = (*this->localDistributionsFrom)(D3Q27System::ET_E, x1,x2,x3);
+      f[D3Q27System::INV_N] = (*this->localDistributionsFrom)(D3Q27System::ET_N,x1,x2,x3);  
+      f[D3Q27System::INV_T] = (*this->localDistributionsFrom)(D3Q27System::ET_T,x1,x2,x3);
+      f[D3Q27System::INV_NE] = (*this->localDistributionsFrom)(D3Q27System::ET_NE,x1,x2,x3);
+      f[D3Q27System::INV_NW] = (*this->localDistributionsFrom)(D3Q27System::ET_NW,x1+1,x2,x3);
+      f[D3Q27System::INV_TE] = (*this->localDistributionsFrom)(D3Q27System::ET_TE,x1,x2,x3);
+      f[D3Q27System::INV_TW] = (*this->localDistributionsFrom)(D3Q27System::ET_TW, x1+1,x2,x3);
+      f[D3Q27System::INV_TN] = (*this->localDistributionsFrom)(D3Q27System::ET_TN,x1,x2,x3);
+      f[D3Q27System::INV_TS] = (*this->localDistributionsFrom)(D3Q27System::ET_TS,x1,x2+1,x3);
+      f[D3Q27System::INV_TNE] = (*this->localDistributionsFrom)(D3Q27System::ET_TNE,x1,x2,x3);
+      f[D3Q27System::INV_TNW] = (*this->localDistributionsFrom)(D3Q27System::ET_TNW,x1+1,x2,x3);
+      f[D3Q27System::INV_TSE] = (*this->localDistributionsFrom)(D3Q27System::ET_TSE,x1,x2+1,x3);
+      f[D3Q27System::INV_TSW] = (*this->localDistributionsFrom)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+
+      f[D3Q27System::INV_W ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_W,x1+1,x2,x3  );
+      f[D3Q27System::INV_S ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_S,x1,x2+1,x3  );
+      f[D3Q27System::INV_B ] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_B,x1,x2,x3+1  );
+      f[D3Q27System::INV_SW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+      f[D3Q27System::INV_SE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_SE,x1,x2+1,x3 );
+      f[D3Q27System::INV_BW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+      f[D3Q27System::INV_BE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BE,x1,x2,x3+1 );
+      f[D3Q27System::INV_BS] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+      f[D3Q27System::INV_BN] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BN,x1,x2,x3+1 );
+      f[D3Q27System::INV_BSW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+      f[D3Q27System::INV_BSE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+      f[D3Q27System::INV_BNW] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+      f[D3Q27System::INV_BNE] = (*this->nonLocalDistributionsFrom)(D3Q27System::ET_BNE,x1,x2,x3+1);
+
+      f[D3Q27System::ZERO] = (*this->zeroDistributionsFrom)(x1,x2,x3);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27ETFullDirectConnector2::distributeData(int x1, int x2, int x3)
+{
+   if(invStep)
+   {
+      (*this->localDistributionsTo)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::E];
+      (*this->localDistributionsTo)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::N];
+      (*this->localDistributionsTo)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::T];
+      (*this->localDistributionsTo)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::NE];
+      (*this->localDistributionsTo)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::NW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::TE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::TW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::TN];
+      (*this->localDistributionsTo)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::TS];
+      (*this->localDistributionsTo)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::TNE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::TNW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::TSE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::TSW];
+
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::W ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::S ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::B ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::SW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::SE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::BW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::BE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::BS];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::BN];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::BSW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::BSE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::BNW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::BNE];
+
+      (*this->zeroDistributionsTo)(x1,x2,x3) = f[D3Q27System::ZERO];
+   }
+   else
+   {
+      (*this->localDistributionsTo)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::INV_E];
+      (*this->localDistributionsTo)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::INV_N];
+      (*this->localDistributionsTo)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::INV_T];
+      (*this->localDistributionsTo)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::INV_NE];
+      (*this->localDistributionsTo)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::INV_NW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::INV_TE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::INV_TW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::INV_TN];
+      (*this->localDistributionsTo)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::INV_TS];
+      (*this->localDistributionsTo)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::INV_TNE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::INV_TNW];
+      (*this->localDistributionsTo)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::INV_TSE];
+      (*this->localDistributionsTo)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::INV_TSW];
+
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::INV_W ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::INV_S ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::INV_B ];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::INV_SW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::INV_SE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::INV_BW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::INV_BS];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BN];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::INV_BSW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::INV_BSE];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::INV_BNW];
+      (*this->nonLocalDistributionsTo)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::INV_BNE];
+
+      (*this->zeroDistributionsTo)(x1,x2,x3) = f[D3Q27System::ZERO];
+   }
+}
+#endif 
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFullVectorConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETFullVectorConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b987db5c3d3465d8f7762642b573ae4a442511fd
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFullVectorConnector.cpp
@@ -0,0 +1,491 @@
+#include "D3Q27ETFullVectorConnector.h"
+
+//////////////////////////////////////////////////////////////////////////
+D3Q27ETFullVectorConnector::D3Q27ETFullVectorConnector(Block3DPtr block
+   , VectorTransmitterPtr sender
+   , VectorTransmitterPtr receiver
+   , int sendDir)
+   : RemoteBlock3DConnector(block, sender, receiver, sendDir)
+{
+   if (!block || !sender || !receiver)
+      UB_THROW(UbException(UB_EXARGS, "sender or receiver == NULL!!"));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullVectorConnector::init()
+{
+   int maxX1 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1()-1;
+   int maxX2 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2()-1;
+   int maxX3 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3()-1;
+
+   int anz = 27;
+   switch (sendDir)
+   {
+   case D3Q27System::ZERO: UB_THROW(UbException(UB_EXARGS, "ZERO not allowed")); break;
+   case D3Q27System::E:
+   case D3Q27System::W: sender->getData().resize(maxX2*maxX3*anz, 0.0);   break;
+   case D3Q27System::N:
+   case D3Q27System::S: sender->getData().resize(maxX1*maxX3*anz, 0.0);   break;
+   case D3Q27System::T:
+   case D3Q27System::B: sender->getData().resize(maxX1*maxX2*anz, 0.0);   break;
+
+   case D3Q27System::NE:
+   case D3Q27System::SW:
+   case D3Q27System::SE:
+   case D3Q27System::NW:  sender->getData().resize(maxX3*anz, 0.0);   break;
+
+   case D3Q27System::TE:
+   case D3Q27System::BW:
+   case D3Q27System::BE:
+   case D3Q27System::TW:  sender->getData().resize(maxX2*anz, 0.0);   break;
+
+   case D3Q27System::TN:
+   case D3Q27System::BS:
+   case D3Q27System::BN:
+   case D3Q27System::TS:  sender->getData().resize(maxX1*anz, 0.0);   break;
+
+   case D3Q27System::TNE:
+   case D3Q27System::BSW:
+   case D3Q27System::BNE:
+   case D3Q27System::TSW:
+   case D3Q27System::TSE:
+   case D3Q27System::BNW:
+   case D3Q27System::BSE:
+   case D3Q27System::TNW:  sender->getData().resize(anz, 0.0);   break;
+
+   default: UB_THROW(UbException(UB_EXARGS, "unknown sendDir"));
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullVectorConnector::fillSendVectors()
+{
+   EsoTwist3DPtr  fFrom = boost::dynamic_pointer_cast<EsoTwist3D>(block.lock()->getKernel()->getDataSet()->getFdistributions());
+   int maxX1 = (int)fFrom->getNX1()-1;
+   int maxX2 = (int)fFrom->getNX2()-1;
+   int maxX3 = (int)fFrom->getNX3()-1;
+
+   int sendDirForEdge[3];
+
+   int index = 0;
+   //EAST
+   if (sendDir==D3Q27System::E)
+   {
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         for (int x2 = 1; x2<maxX2; x2++)
+         {
+            fillData(fFrom, index, maxX1-1, x2, x3);
+         }
+      }
+   }
+   //WEST
+   else if (sendDir==D3Q27System::W)
+   {
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         for (int x2 = 1; x2<maxX2; x2++)
+         {
+            fillData(fFrom, index, 1, x2, x3);
+         }
+      }
+   }
+   //NORTH
+   else if (sendDir==D3Q27System::N)
+   {
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         for (int x1 = 1; x1<maxX1; x1++)
+         {
+            fillData(fFrom, index, x1, maxX2-1, x3);
+         }
+      }
+   }
+   //SOUTH
+   else if (sendDir==D3Q27System::S)
+   {
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         for (int x1 = 1; x1<maxX1; x1++)
+         {
+            fillData(fFrom, index, x1, 1, x3);
+         }
+      }
+   }
+   //TOP
+   else if (sendDir==D3Q27System::T)
+   {
+      for (int x2 = 1; x2<maxX2; x2++)
+      {
+         for (int x1 = 1; x1<maxX1; x1++)
+         {
+            fillData(fFrom, index, x1, x2, maxX3-1);
+         }
+      }
+   }
+   //BOTTOM
+   else if (sendDir==D3Q27System::B)
+   {
+      for (int x2 = 1; x2<maxX2; x2++)
+      {
+         for (int x1 = 1; x1<maxX1; x1++)
+         {
+            fillData(fFrom, index, x1, x2, 1);
+         }
+      }
+   }
+   //NE NW SW SE
+   else if (sendDir==D3Q27System::NE || sendDir==D3Q27System::NW || sendDir==D3Q27System::SW || sendDir==D3Q27System::SE)
+   {
+      int x1 = 0;
+      int x2 = 0;
+      switch (sendDir)
+      {
+      case D3Q27System::NE:   x1 = maxX1-1; x2 = maxX2-1;
+         sendDirForEdge[0] = D3Q27System::NE;
+         sendDirForEdge[1] = D3Q27System::TNE;
+         sendDirForEdge[2] = D3Q27System::BNE;
+         break;
+      case D3Q27System::NW:   x1 = 1;       x2 = maxX2-1;
+         sendDirForEdge[0] = D3Q27System::NW;
+         sendDirForEdge[1] = D3Q27System::TNW;
+         sendDirForEdge[2] = D3Q27System::BNW;
+         break;
+      case D3Q27System::SW:   x1 = 1;       x2 = 1;
+         sendDirForEdge[0] = D3Q27System::SW;
+         sendDirForEdge[1] = D3Q27System::TSW;
+         sendDirForEdge[2] = D3Q27System::BSW;
+         break;
+      case D3Q27System::SE:   x1 = maxX1-1; x2 = 1;
+         sendDirForEdge[0] = D3Q27System::SE;
+         sendDirForEdge[1] = D3Q27System::TSE;
+         sendDirForEdge[2] = D3Q27System::BSE;
+         break;
+      }
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         fillData(fFrom, index, x1, x2, x3);
+      }
+   }
+   //TE TW BW BE
+   else if (sendDir==D3Q27System::TE || sendDir==D3Q27System::TW || sendDir==D3Q27System::BW || sendDir==D3Q27System::BE)
+   {
+      int x1 = 0;
+      int x3 = 0;
+      switch (sendDir)
+      {
+      case D3Q27System::TE:   x1 = maxX1-1; x3 = maxX3-1;
+         sendDirForEdge[0] = D3Q27System::TE;
+         sendDirForEdge[1] = D3Q27System::TNE;
+         sendDirForEdge[2] = D3Q27System::TSE;
+         break;
+      case D3Q27System::TW:   x1 = 1;       x3 = maxX3-1;
+         sendDirForEdge[0] = D3Q27System::TW;
+         sendDirForEdge[1] = D3Q27System::TNW;
+         sendDirForEdge[2] = D3Q27System::TSW;
+         break;
+      case D3Q27System::BW:   x1 = 1;       x3 = 1;
+         sendDirForEdge[0] = D3Q27System::BW;
+         sendDirForEdge[1] = D3Q27System::BNW;
+         sendDirForEdge[2] = D3Q27System::BSW;
+         break;
+      case D3Q27System::BE:   x1 = maxX1-1; x3 = 1;
+         sendDirForEdge[0] = D3Q27System::BE;
+         sendDirForEdge[1] = D3Q27System::BNE;
+         sendDirForEdge[2] = D3Q27System::BSE;
+         break;
+      }
+      for (int x2 = 1; x2<maxX2; x2++)
+      {
+         fillData(fFrom, index, x1, x2, x3);
+      }
+   }
+   //TN BN BS TS
+   else if (sendDir==D3Q27System::TN || sendDir==D3Q27System::BN || sendDir==D3Q27System::BS || sendDir==D3Q27System::TS)
+   {
+      int x2 = 0;
+      int x3 = 0;
+      switch (sendDir)
+      {
+      case D3Q27System::TN:   x3 = maxX3-1; x2 = maxX2-1;
+         sendDirForEdge[0] = D3Q27System::TN;
+         sendDirForEdge[1] = D3Q27System::TNE;
+         sendDirForEdge[2] = D3Q27System::TNW;
+         break;
+      case D3Q27System::BN:   x3 = 1;       x2 = maxX2-1;
+         sendDirForEdge[0] = D3Q27System::BN;
+         sendDirForEdge[1] = D3Q27System::BNE;
+         sendDirForEdge[2] = D3Q27System::BNW;
+         break;
+      case D3Q27System::BS:   x3 = 1;       x2 = 1;
+         sendDirForEdge[0] = D3Q27System::BS;
+         sendDirForEdge[1] = D3Q27System::BSE;
+         sendDirForEdge[2] = D3Q27System::BSW;
+         break;
+      case D3Q27System::TS:   x3 = maxX3-1; x2 = 1;
+         sendDirForEdge[0] = D3Q27System::TS;
+         sendDirForEdge[1] = D3Q27System::TSE;
+         sendDirForEdge[2] = D3Q27System::TSW;
+         break;
+      }
+      for (int x1 = 1; x1<maxX1; x1++)
+      {
+         fillData(fFrom, index, x1, x2, x3);
+      }
+   }
+   //TNE TNW TSW TSE BNE BNW BSW BSE
+   else if (sendDir==D3Q27System::TNE || sendDir==D3Q27System::TNW || sendDir==D3Q27System::TSW || sendDir==D3Q27System::TSE
+      || sendDir==D3Q27System::BNE || sendDir==D3Q27System::BNW || sendDir==D3Q27System::BSW || sendDir==D3Q27System::BSE)
+   {
+      int x1 = 0;
+      int x2 = 0;
+      int x3 = 0;
+      switch (sendDir)
+      {
+      case D3Q27System::TNE:   x1 = maxX1-1; x2 = maxX2-1; x3 = maxX3-1; break;
+      case D3Q27System::TNW:   x1 = 1;       x2 = maxX2-1; x3 = maxX3-1; break;
+      case D3Q27System::TSW:   x1 = 1;       x2 = 1;       x3 = maxX3-1; break;
+      case D3Q27System::TSE:   x1 = maxX1-1; x2 = 1;       x3 = maxX3-1; break;
+      case D3Q27System::BNE:   x1 = maxX1-1; x2 = maxX2-1; x3 = 1;       break;
+      case D3Q27System::BNW:   x1 = 1;       x2 = maxX2-1; x3 = 1;       break;
+      case D3Q27System::BSW:   x1 = 1;       x2 = 1;       x3 = 1;       break;
+      case D3Q27System::BSE:   x1 = maxX1-1; x2 = 1;       x3 = 1;       break;
+      }
+      fillData(fFrom, index, x1, x2, x3);
+   }
+   else UB_THROW(UbException(UB_EXARGS, "unknown dir"));
+}
+////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullVectorConnector::distributeReceiveVectors()
+{
+   receiver->saveData();
+   /*e.g. connector sendet nach EAST --> empfaengt daten aus WEST ;-)*/
+   EsoTwist3DPtr  fTo = boost::dynamic_pointer_cast<EsoTwist3D>(block.lock()->getKernel()->getDataSet()->getFdistributions());
+   int maxX1 = (int)fTo->getNX1()-1;
+   int maxX2 = (int)fTo->getNX2()-1;
+   int maxX3 = (int)fTo->getNX3()-1;
+   int index = 0;
+   int sendDirForEdge[3];
+
+   if (sendDir==D3Q27System::W)
+   {
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         for (int x2 = 1; x2<maxX2; x2++)
+         {
+            distributeData(fTo, index, 0, x2, x3);
+         }
+      }
+   }
+   else if (sendDir==D3Q27System::E)
+   {
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         for (int x2 = 1; x2<maxX2; x2++)
+         {
+            distributeData(fTo, index, maxX1, x2, x3);
+         }
+      }
+   }
+   else if (sendDir==D3Q27System::S)
+   {
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         for (int x1 = 1; x1<maxX1; x1++)
+         {
+            distributeData(fTo, index, x1, 0, x3);
+         }
+      }
+   }
+   else if (sendDir==D3Q27System::N)
+   {
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         for (int x1 = 1; x1<maxX1; x1++)
+         {
+            distributeData(fTo, index, x1, maxX2, x3);
+         }
+      }
+   }
+   else if (sendDir==D3Q27System::B)
+   {
+      for (int x2 = 1; x2<maxX2; x2++)
+      {
+         for (int x1 = 1; x1<maxX1; x1++)
+         {
+            distributeData(fTo, index, x1, x2, 0);
+         }
+      }
+   }
+   else if (sendDir==D3Q27System::T)
+   {
+      for (int x2 = 1; x2<maxX2; x2++)
+      {
+         for (int x1 = 1; x1<maxX1; x1++)
+         {
+            distributeData(fTo, index, x1, x2, maxX3);
+         }
+      }
+   }
+   //NE NW SW SE
+   else if (sendDir==D3Q27System::NE || sendDir==D3Q27System::NW || sendDir==D3Q27System::SW || sendDir==D3Q27System::SE)
+   {
+      int inversDir = D3Q27System::getInvertDirection(sendDir);
+      int x1 = 0;
+      int x2 = 0;
+      switch (sendDir)  //wenn sendir NE dann kommen werte von SW
+      {
+      case D3Q27System::NE:   x1 = maxX1; x2 = maxX2;
+         sendDirForEdge[0] = D3Q27System::SW;
+         sendDirForEdge[1] = D3Q27System::TSW;
+         sendDirForEdge[2] = D3Q27System::BSW;
+         break;
+      case D3Q27System::NW:   x1 = 0;     x2 = maxX2;
+         sendDirForEdge[0] = D3Q27System::SE;
+         sendDirForEdge[1] = D3Q27System::TSE;
+         sendDirForEdge[2] = D3Q27System::BSE;
+         break;
+      case D3Q27System::SW:   x1 = 0;     x2 = 0;
+         sendDirForEdge[0] = D3Q27System::NE;
+         sendDirForEdge[1] = D3Q27System::TNE;
+         sendDirForEdge[2] = D3Q27System::BNE;
+         break;
+      case D3Q27System::SE:   x1 = maxX1; x2 = 0;
+         sendDirForEdge[0] = D3Q27System::NW;
+         sendDirForEdge[1] = D3Q27System::TNW;
+         sendDirForEdge[2] = D3Q27System::BNW;
+         break;
+      }
+      for (int x3 = 1; x3<maxX3; x3++)
+      {
+         distributeData(fTo, index, x1, x2, x3);
+      }
+
+   }
+   //TE TW BW BE
+   else if (sendDir==D3Q27System::TE || sendDir==D3Q27System::TW || sendDir==D3Q27System::BW || sendDir==D3Q27System::BE)
+
+   {
+      int inversDir = D3Q27System::getInvertDirection(sendDir);
+      int x1 = 0;
+      int x3 = 0;
+      switch (sendDir)  //wenn sendir NE dann kommen werte von SW
+      {
+      case D3Q27System::TE:   x1 = maxX1; x3 = maxX3;
+         sendDirForEdge[0] = D3Q27System::BW;
+         sendDirForEdge[1] = D3Q27System::BNW;
+         sendDirForEdge[2] = D3Q27System::BSW;
+         break;
+      case D3Q27System::TW:   x1 = 0;     x3 = maxX3;
+         sendDirForEdge[0] = D3Q27System::BE;
+         sendDirForEdge[1] = D3Q27System::BNE;
+         sendDirForEdge[2] = D3Q27System::BSE;
+         break;
+      case D3Q27System::BW:   x1 = 0;     x3 = 0;
+         sendDirForEdge[0] = D3Q27System::TE;
+         sendDirForEdge[1] = D3Q27System::TNE;
+         sendDirForEdge[2] = D3Q27System::TSE;
+         break;
+      case D3Q27System::BE:   x1 = maxX1; x3 = 0;
+         sendDirForEdge[0] = D3Q27System::TW;
+         sendDirForEdge[1] = D3Q27System::TNW;
+         sendDirForEdge[2] = D3Q27System::TSW;
+         break;
+      }
+      for (int x2 = 1; x2<maxX2; x2++)
+      {
+         distributeData(fTo, index, x1, x2, x3);
+      }
+   }
+   //TN BN BS TS
+   else if (sendDir==D3Q27System::TN || sendDir==D3Q27System::BN || sendDir==D3Q27System::BS || sendDir==D3Q27System::TS)
+   {
+      int inversDir = D3Q27System::getInvertDirection(sendDir);
+      int x2 = 0;
+      int x3 = 0;
+      switch (sendDir)
+      {
+      case D3Q27System::TN:   x3 = maxX3; x2 = maxX2;
+         sendDirForEdge[0] = D3Q27System::BS;
+         sendDirForEdge[1] = D3Q27System::BSE;
+         sendDirForEdge[2] = D3Q27System::BSW;
+         break;
+      case D3Q27System::BN:   x3 = 0;       x2 = maxX2;
+         sendDirForEdge[0] = D3Q27System::TS;
+         sendDirForEdge[1] = D3Q27System::TSE;
+         sendDirForEdge[2] = D3Q27System::TSW;
+         break;
+      case D3Q27System::BS:   x3 = 0;       x2 = 0;
+         sendDirForEdge[0] = D3Q27System::TN;
+         sendDirForEdge[1] = D3Q27System::TNE;
+         sendDirForEdge[2] = D3Q27System::TNW;
+         break;
+      case D3Q27System::TS:   x3 = maxX3; x2 = 0;
+         sendDirForEdge[0] = D3Q27System::BN;
+         sendDirForEdge[1] = D3Q27System::BNE;
+         sendDirForEdge[2] = D3Q27System::BNW;
+         break;
+
+      }
+      for (int x1 = 1; x1<maxX1; x1++)
+      {
+         distributeData(fTo, index, x1, x2, x3);
+      }
+   }
+   //TNE TNW TSW TSE BNE BNW BSW BSE
+   else if (sendDir==D3Q27System::TNE || sendDir==D3Q27System::TNW || sendDir==D3Q27System::TSW || sendDir==D3Q27System::TSE
+      || sendDir==D3Q27System::BNE || sendDir==D3Q27System::BNW || sendDir==D3Q27System::BSW || sendDir==D3Q27System::BSE)
+   {
+      int inversDir = D3Q27System::getInvertDirection(sendDir);
+      int x1 = 0;
+      int x2 = 0;
+      int x3 = 0;
+      unsigned long int etDir = 0;
+      switch (sendDir)
+      {
+      case D3Q27System::TNE:   x1 = maxX1; x2 = maxX2; x3 = maxX3; etDir = EsoTwistD3Q27System::etTNE; break;
+      case D3Q27System::TNW:   x1 = 0; x2 = maxX2; x3 = maxX3; etDir = EsoTwistD3Q27System::etTNW; break;
+      case D3Q27System::TSW:   x1 = 0; x2 = 0; x3 = maxX3; etDir = EsoTwistD3Q27System::etTSW; break;
+      case D3Q27System::TSE:   x1 = maxX1; x2 = 0; x3 = maxX3; etDir = EsoTwistD3Q27System::etTSE; break;
+      case D3Q27System::BNE:   x1 = maxX1; x2 = maxX2; x3 = 0; etDir = EsoTwistD3Q27System::etBNE; break;
+      case D3Q27System::BNW:   x1 = 0; x2 = maxX2; x3 = 0; etDir = EsoTwistD3Q27System::etBNW; break;
+      case D3Q27System::BSW:   x1 = 0; x2 = 0; x3 = 0; etDir = EsoTwistD3Q27System::etBSW; break;
+      case D3Q27System::BSE:   x1 = maxX1; x2 = 0; x3 = 0; etDir = EsoTwistD3Q27System::etBSE; break;
+      }
+      distributeData(fTo, index, x1, x2, x3);
+   }
+   else UB_THROW(UbException(UB_EXARGS, "unknown dir"));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullVectorConnector::fillData(EsoTwist3DPtr  fFrom, int& index, const int& x1, const int& x2, const int& x3)
+{
+   LBMReal f[D3Q27System::ENDF+1];
+
+   vector_type& data = sender->getData();
+
+   if (!invStep)
+      fFrom->getDistributionInv(f, x1, x2, x3);
+   else
+      fFrom->getDistribution(f, x1, x2, x3);
+
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+      data[index++] = f[i];
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETFullVectorConnector::distributeData(EsoTwist3DPtr  fTo, int& index, const int& x1, const int& x2, const int& x3)
+{
+   vector_type& data = receiver->getData();
+
+   if (!invStep)
+   {
+      for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+         fTo->setDistributionForDirection(data[index++], x1, x2, x3, i);
+   }
+   else
+   {
+      for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+         fTo->setDistributionInvForDirection(data[index++], x1, x2, x3, i);
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETFullVectorConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETFullVectorConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..2ac709a20f37ec52ec151e5f3bd999b0af790a55
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETFullVectorConnector.h
@@ -0,0 +1,39 @@
+#ifndef D3Q27ETFULLVECTORCONNECTOR_H
+#define D3Q27ETFULLVECTORCONNECTOR_H
+
+#include <vector>
+
+#include "RemoteBlock3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "EsoTwistD3Q27System.h"
+
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+class D3Q27ETFullVectorConnector : public RemoteBlock3DConnector
+{
+public:
+   D3Q27ETFullVectorConnector(  Block3DPtr block
+      , VectorTransmitterPtr sender
+      , VectorTransmitterPtr receiver
+      , int sendDir); 
+
+   void init();
+
+   void fillSendVectors();
+   void distributeReceiveVectors();
+
+protected:
+   void fillData(EsoTwist3DPtr  fFrom, int& index, const int& x1, const int& x2, const int& x3);
+   void distributeData(EsoTwist3DPtr  fTo, int& index, const int& x1, const int& x2, const int& x3);
+
+};
+
+
+
+#endif //D3Q27VECTORCONNECTOR_H
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETOffConnectorFactory.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETOffConnectorFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6dd574b515cdede56d1cca84a97657dcb7e0e5dd
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETOffConnectorFactory.cpp
@@ -0,0 +1,38 @@
+//#include "D3Q27ETOffConnectorFactory.h"
+//#include "TransmitterType.h"
+//#include "D3Q27ETCFOffVectorConnector.h"
+//#include "D3Q27ETFCOffVectorConnector.h"
+//#include "D3Q27ETFCVectorConnector.h"
+//#include "FineToCoarseBlock3DConnector.h"
+//
+//D3Q27ETOffConnectorFactory::D3Q27ETOffConnectorFactory()
+//{
+//}
+////////////////////////////////////////////////////////////////////////////
+//D3Q27ETOffConnectorFactory::~D3Q27ETOffConnectorFactory()
+//{
+//}
+////////////////////////////////////////////////////////////////////////////
+//Block3DConnectorPtr D3Q27ETOffConnectorFactory::createCoarseToFineConnector(Block3DPtr block,
+//   VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+//   VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+//   VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+//   VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+//   int sendDir, D3Q27InterpolationProcessorPtr iprocessor)
+//{
+//   return Block3DConnectorPtr(new D3Q27ETCFOffVectorConnector<VectorTransmitter>(block,
+//      sender00, receiver00, sender01, receiver01,
+//      sender10, receiver10, sender11, receiver11,
+//      sendDir, iprocessor));
+//}
+////////////////////////////////////////////////////////////////////////////
+//Block3DConnectorPtr D3Q27ETOffConnectorFactory::createFineToCoarseConnector(Block3DPtr block,
+//   VectorTransmitterPtr sender,
+//   VectorTransmitterPtr receiver,
+//   int sendDir,
+//   D3Q27InterpolationProcessorPtr iprocessor,
+//   FineToCoarseBlock3DConnector::CFconnectorType connType)
+//{
+//   return  Block3DConnectorPtr(new D3Q27ETFCOffVectorConnector<VectorTransmitter>(block,
+//      sender, receiver, sendDir, iprocessor, connType));
+//}
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETOffConnectorFactory.h b/source/VirtualFluidsCore/Connectors/D3Q27ETOffConnectorFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..2ad0c48deb49ef9a64314267aac77012f743807f
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETOffConnectorFactory.h
@@ -0,0 +1,34 @@
+//#ifndef D3Q27ETOffConnectorFactory_h__
+//#define D3Q27ETOffConnectorFactory_h__
+//
+//#include "Block3DConnectorFactory.h"
+//
+//#include <boost/shared_ptr.hpp>
+//class D3Q27ETOffConnectorFactory;
+//typedef boost::shared_ptr<D3Q27ETOffConnectorFactory> D3Q27ETOffConnectorFactoryPtr;
+//
+//class D3Q27ETOffConnectorFactory : public Block3DConnectorFactory
+//{
+//public:
+//   D3Q27ETOffConnectorFactory();
+//   virtual ~D3Q27ETOffConnectorFactory();
+//
+//   virtual Block3DConnectorPtr createCoarseToFineConnector(Block3DPtr block,
+//      VectorTransmitterPtr sender00, VectorTransmitterPtr receiver00,
+//      VectorTransmitterPtr sender01, VectorTransmitterPtr receiver01,
+//      VectorTransmitterPtr sender10, VectorTransmitterPtr receiver10,
+//      VectorTransmitterPtr sender11, VectorTransmitterPtr receiver11,
+//      int sendDir, D3Q27InterpolationProcessorPtr iprocessor);
+//
+//   virtual Block3DConnectorPtr createFineToCoarseConnector(Block3DPtr block,
+//      VectorTransmitterPtr sender,
+//      VectorTransmitterPtr receiver,
+//      int sendDir,
+//      D3Q27InterpolationProcessorPtr iprocessor,
+//      FineToCoarseBlock3DConnector::CFconnectorType connType);
+//
+//private:
+//
+//};
+//#endif // D3Q27ETOffConnectorFactory_h__
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETVectorConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETVectorConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3923c6c2ea6bc7f931919c1f8df39384509c8e9d
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETVectorConnector.cpp
@@ -0,0 +1,2 @@
+#include "D3Q27ETVectorConnector.h"
+
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETVectorConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETVectorConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..34c5fe0c64eb1fb2da1c0cf332f046ba4207071b
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETVectorConnector.h
@@ -0,0 +1,720 @@
+#ifndef D3Q27VECTORCONNECTOR_H
+#define D3Q27VECTORCONNECTOR_H
+
+#include <vector>
+
+#include "basics/transmitter/TbTransmitter.h"
+#include "basics/container/CbVector.h"
+#include "basics/utilities/UbTiming.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "EsoTwistD3Q27System.h"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+class Block3D;
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+template< typename VectorTransmitter > //TbTransmitter< CbVector<LBMReal> >
+class D3Q27ETVectorConnector : public Block3DConnector
+{
+public:
+   //typedef CbVector<LBMReal> DataType;
+   //typedef boost::shared_ptr< TbTransmitter< DataType > > TransmitterPtr;
+   typedef typename VectorTransmitter::value_type  vector_type;
+   typedef boost::shared_ptr< VectorTransmitter >  VectorTransmitterPtr;
+public:
+   D3Q27ETVectorConnector(  Block3DPtr block
+                       , VectorTransmitterPtr sender
+                       , VectorTransmitterPtr receiver
+                       , int sendDir); 
+
+   bool isLocalConnector();
+   bool isRemoteConnector();
+
+   void init();
+
+   void sendTransmitterDataSize();
+   void receiveTransmitterDataSize();
+   
+   void prepareForSend();
+   void sendVectors();
+   
+   void prepareForReceive();
+   void receiveVectors();
+   
+   void fillSendVectors();
+   void distributeReceiveVectors();
+
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return false; }
+
+   double getSendRecieveTime();
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1(){}
+   void sendVectorsX2(){}
+   void sendVectorsX3(){}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> block; //dieser nvd sendet daten und die empfangenen werden diesem nvd zugeordnet
+                             //gegenstelle muss "inversen" connector besitzen
+
+   VectorTransmitterPtr sender;
+   VectorTransmitterPtr receiver;
+   UbTiming timer;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+D3Q27ETVectorConnector< VectorTransmitter >::D3Q27ETVectorConnector(   Block3DPtr block
+                                               , VectorTransmitterPtr sender
+                                               , VectorTransmitterPtr receiver
+                                               , int sendDir )
+                                               :  Block3DConnector(sendDir)
+                                               , block(block)
+                                               , sender(sender)
+                                               , receiver(receiver)
+{
+   if(!block || !sender || !receiver) 
+      UB_THROW( UbException(UB_EXARGS,"sender or receiver == NULL!!") );
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETVectorConnector< VectorTransmitter >::isLocalConnector()  
+{ 
+   return !this->isRemoteConnector(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+bool D3Q27ETVectorConnector< VectorTransmitter >::isRemoteConnector() 
+{ 
+   return (   ( sender && sender->isRemoteTransmitter() ) 
+      || ( receiver && receiver->isRemoteTransmitter() ) );
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::sendTransmitterDataSize()
+{ 
+   assert(sender  !=NULL); sender->sendDataSize();        
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::receiveTransmitterDataSize()
+{ 
+   assert(receiver!=NULL); receiver->receiveDataSize();   
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::prepareForSend()            
+{ 
+   assert(sender  !=NULL); sender->prepareForSend();      
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::sendVectors()                
+{ 
+   assert(sender  !=NULL); sender->sendData();            
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::prepareForReceive()          
+{ 
+   assert(receiver!=NULL); receiver->prepareForReceive(); 
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::receiveVectors()             
+{ 
+   assert(receiver!=NULL); receiver->receiveData();       
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::init()
+{
+   int maxX1 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1()-1;
+   int maxX2 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2()-1;
+   int maxX3 = (int)block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3()-1;
+
+   int anz = 9;
+   switch(sendDir)
+   {		                  
+   case D3Q27System::ZERO : UB_THROW( UbException(UB_EXARGS,"ZERO not allowed") ); break;
+   case D3Q27System::E    : 
+   case D3Q27System::W    : sender->getData().resize(maxX2*maxX3*anz, 0.0);   break; 
+   case D3Q27System::N    :
+   case D3Q27System::S    : sender->getData().resize(maxX1*maxX3*anz, 0.0);   break; 
+   case D3Q27System::T    : 
+   case D3Q27System::B    : sender->getData().resize(maxX1*maxX2*anz, 0.0);   break; 
+
+   case D3Q27System::NE  :   
+   case D3Q27System::SW  :   
+   case D3Q27System::SE  :   
+   case D3Q27System::NW  :  sender->getData().resize(maxX3*3, 0.0);   break; 
+
+   case D3Q27System::TE  :   
+   case D3Q27System::BW  :   
+   case D3Q27System::BE  :   
+   case D3Q27System::TW  :  sender->getData().resize(maxX2*3, 0.0);   break; 
+
+   case D3Q27System::TN  :   
+   case D3Q27System::BS  :   
+   case D3Q27System::BN  :   
+   case D3Q27System::TS  :  sender->getData().resize(maxX1*3, 0.0);   break;
+
+   case D3Q27System::TNE : 
+   case D3Q27System::BSW : 
+   case D3Q27System::BNE : 
+   case D3Q27System::TSW : 
+   case D3Q27System::TSE : 
+   case D3Q27System::BNW : 
+   case D3Q27System::BSE : 
+   case D3Q27System::TNW :  sender->getData().resize(1, 0.0);   break;
+
+   default: UB_THROW( UbException(UB_EXARGS,"unknown sendDir") );
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::fillSendVectors() 
+{ 
+   DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fFrom->getNX1()-1;
+   int maxX2 = (int)fFrom->getNX2()-1;
+   int maxX3 = (int)fFrom->getNX3()-1;
+
+   LBMReal f[D3Q27System::ENDF+1];
+   int sendDirForEdge[3];
+
+   vector_type& data = sender->getData();
+
+   int index = 0;
+   //EAST
+   if(sendDir==D3Q27System::E)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fFrom->getDistributionInv(f,maxX1-1,x2,x3);
+            data[index++] = f[D3Q27System::E]; 
+            data[index++] = f[D3Q27System::NE]; 
+            data[index++] = f[D3Q27System::SE];
+            data[index++] = f[D3Q27System::TE]; 
+            data[index++] = f[D3Q27System::BE];
+            data[index++] = f[D3Q27System::TNE];
+            data[index++] = f[D3Q27System::TSE];
+            data[index++] = f[D3Q27System::BNE];
+            data[index++] = f[D3Q27System::BSE];
+         }
+      }
+   }
+   //WEST
+   else if(sendDir==D3Q27System::W)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fFrom->getDistributionInv(f,1,x2,x3);
+            data[index++] = f[D3Q27System::W ]; 
+            data[index++] = f[D3Q27System::NW]; 
+            data[index++] = f[D3Q27System::SW];
+            data[index++] = f[D3Q27System::TW]; 
+            data[index++] = f[D3Q27System::BW];
+            data[index++] = f[D3Q27System::TNW];
+            data[index++] = f[D3Q27System::TSW];
+            data[index++] = f[D3Q27System::BNW];
+            data[index++] = f[D3Q27System::BSW];
+         }
+      }
+   }
+   //NORTH
+   else if(sendDir==D3Q27System::N)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)        
+         {                                    
+            fFrom->getDistributionInv(f,x1,maxX2-1,x3);
+            data[index++] = f[D3Q27System::N ]; 
+            data[index++] = f[D3Q27System::NE]; 
+            data[index++] = f[D3Q27System::NW];
+            data[index++] = f[D3Q27System::TN]; 
+            data[index++] = f[D3Q27System::BN];
+            data[index++] = f[D3Q27System::TNE];
+            data[index++] = f[D3Q27System::TNW];
+            data[index++] = f[D3Q27System::BNE];
+            data[index++] = f[D3Q27System::BNW];
+         }
+      }
+   }
+   //SOUTH
+   else if(sendDir==D3Q27System::S)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fFrom->getDistributionInv(f,x1,1,x3);
+            data[index++] = f[D3Q27System::S ]; 
+            data[index++] = f[D3Q27System::SE]; 
+            data[index++] = f[D3Q27System::SW];
+            data[index++] = f[D3Q27System::TS]; 
+            data[index++] = f[D3Q27System::BS];
+            data[index++] = f[D3Q27System::TSE];
+            data[index++] = f[D3Q27System::TSW];
+            data[index++] = f[D3Q27System::BSE];
+            data[index++] = f[D3Q27System::BSW];
+         }
+      }
+   }
+   //TOP
+   else if(sendDir==D3Q27System::T)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fFrom->getDistributionInv(f,x1,x2,maxX3-1);
+            data[index++] = f[D3Q27System::T ]; 
+            data[index++] = f[D3Q27System::TE]; 
+            data[index++] = f[D3Q27System::TW];
+            data[index++] = f[D3Q27System::TN]; 
+            data[index++] = f[D3Q27System::TS];
+            data[index++] = f[D3Q27System::TNE];
+            data[index++] = f[D3Q27System::TNW];
+            data[index++] = f[D3Q27System::TSE];
+            data[index++] = f[D3Q27System::TSW];
+         }
+      }
+   }
+   //BOTTOM
+   else if(sendDir==D3Q27System::B)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            fFrom->getDistributionInv(f,x1,x2,1);
+            data[index++] = f[D3Q27System::B ]; 
+            data[index++] = f[D3Q27System::BE]; 
+            data[index++] = f[D3Q27System::BW];
+            data[index++] = f[D3Q27System::BN]; 
+            data[index++] = f[D3Q27System::BS];
+            data[index++] = f[D3Q27System::BNE];
+            data[index++] = f[D3Q27System::BNW];
+            data[index++] = f[D3Q27System::BSE];
+            data[index++] = f[D3Q27System::BSW];
+         }
+      }
+   }
+   //NE NW SW SE
+   else if(sendDir==D3Q27System::NE || sendDir==D3Q27System::NW || sendDir==D3Q27System::SW || sendDir==D3Q27System::SE)
+   {
+      int x1 = 0;
+      int x2 = 0;
+      switch(sendDir)  
+      {
+      case D3Q27System::NE:   x1=maxX1-1; x2=maxX2-1; 
+         sendDirForEdge[0]=D3Q27System::NE; 
+         sendDirForEdge[1]=D3Q27System::TNE;
+         sendDirForEdge[2]=D3Q27System::BNE; 
+         break;
+      case D3Q27System::NW:   x1=1;       x2=maxX2-1; 
+         sendDirForEdge[0]=D3Q27System::NW; 
+         sendDirForEdge[1]=D3Q27System::TNW;
+         sendDirForEdge[2]=D3Q27System::BNW;          
+         break;
+      case D3Q27System::SW:   x1=1;       x2=1;       
+         sendDirForEdge[0]=D3Q27System::SW; 
+         sendDirForEdge[1]=D3Q27System::TSW;
+         sendDirForEdge[2]=D3Q27System::BSW; 
+         break;
+      case D3Q27System::SE:   x1=maxX1-1; x2=1;       
+         sendDirForEdge[0]=D3Q27System::SE; 
+         sendDirForEdge[1]=D3Q27System::TSE;
+         sendDirForEdge[2]=D3Q27System::BSE; 
+         break;
+      }
+      for(int x3=1; x3<maxX3; x3++)
+      {
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[0]); 
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[1]); 
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[2]); 
+      }
+   }
+   //TE TW BW BE
+   else if(sendDir==D3Q27System::TE || sendDir==D3Q27System::TW || sendDir==D3Q27System::BW || sendDir==D3Q27System::BE)
+   {
+      int x1 = 0;
+      int x3 = 0;
+      switch(sendDir)  
+      {
+      case D3Q27System::TE:   x1=maxX1-1; x3=maxX3-1; 
+         sendDirForEdge[0]=D3Q27System::TE; 
+         sendDirForEdge[1]=D3Q27System::TNE;
+         sendDirForEdge[2]=D3Q27System::TSE; 
+         break;
+      case D3Q27System::TW:   x1=1;       x3=maxX3-1; 
+         sendDirForEdge[0]=D3Q27System::TW; 
+         sendDirForEdge[1]=D3Q27System::TNW;
+         sendDirForEdge[2]=D3Q27System::TSW; 
+         break;
+      case D3Q27System::BW:   x1=1;       x3=1;       
+         sendDirForEdge[0]=D3Q27System::BW; 
+         sendDirForEdge[1]=D3Q27System::BNW;
+         sendDirForEdge[2]=D3Q27System::BSW; 
+         break;
+      case D3Q27System::BE:   x1=maxX1-1; x3=1;      
+         sendDirForEdge[0]=D3Q27System::BE; 
+         sendDirForEdge[1]=D3Q27System::BNE;
+         sendDirForEdge[2]=D3Q27System::BSE; 
+         break;
+      }
+      for(int x2=1; x2<maxX2; x2++) 
+      {
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[0]); 
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[1]); 
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[2]); 
+      }
+   }
+   //TN BN BS TS
+   else if(sendDir==D3Q27System::TN || sendDir==D3Q27System::BN || sendDir==D3Q27System::BS || sendDir==D3Q27System::TS)
+   {
+      int x2 = 0;
+      int x3 = 0;
+      switch(sendDir)  
+      {
+      case D3Q27System::TN:   x3=maxX3-1; x2=maxX2-1; 
+         sendDirForEdge[0]=D3Q27System::TN; 
+         sendDirForEdge[1]=D3Q27System::TNE;
+         sendDirForEdge[2]=D3Q27System::TNW; 
+         break;
+      case D3Q27System::BN:   x3=1;       x2=maxX2-1; 
+         sendDirForEdge[0]=D3Q27System::BN; 
+         sendDirForEdge[1]=D3Q27System::BNE;
+         sendDirForEdge[2]=D3Q27System::BNW; 
+         break;
+      case D3Q27System::BS:   x3=1;       x2=1;       
+         sendDirForEdge[0]=D3Q27System::BS; 
+         sendDirForEdge[1]=D3Q27System::BSE;
+         sendDirForEdge[2]=D3Q27System::BSW; 
+         break;
+      case D3Q27System::TS:   x3=maxX3-1; x2=1;       
+         sendDirForEdge[0]=D3Q27System::TS; 
+         sendDirForEdge[1]=D3Q27System::TSE;
+         sendDirForEdge[2]=D3Q27System::TSW; 
+         break;
+      }
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[0]); 
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[1]); 
+         data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDirForEdge[2]);
+      }
+   }
+   //TNE TNW TSW TSE BNE BNW BSW BSE
+   else if(sendDir==D3Q27System::TNE || sendDir==D3Q27System::TNW || sendDir==D3Q27System::TSW || sendDir==D3Q27System::TSE
+      || sendDir==D3Q27System::BNE || sendDir==D3Q27System::BNW || sendDir==D3Q27System::BSW || sendDir==D3Q27System::BSE)
+   {
+      int x1 = 0;
+      int x2 = 0;
+      int x3 = 0;
+      switch(sendDir) 
+      {
+      case D3Q27System::TNE:   x1=maxX1-1; x2=maxX2-1; x3=maxX3-1; break;
+      case D3Q27System::TNW:   x1=1;       x2=maxX2-1; x3=maxX3-1; break;
+      case D3Q27System::TSW:   x1=1;       x2=1;       x3=maxX3-1; break;
+      case D3Q27System::TSE:   x1=maxX1-1; x2=1;       x3=maxX3-1; break;
+      case D3Q27System::BNE:   x1=maxX1-1; x2=maxX2-1; x3=1;       break;
+      case D3Q27System::BNW:   x1=1;       x2=maxX2-1; x3=1;       break;
+      case D3Q27System::BSW:   x1=1;       x2=1;       x3=1;       break;
+      case D3Q27System::BSE:   x1=maxX1-1; x2=1;       x3=1;       break;
+      }
+      data[index++] = fFrom->getDistributionInvForDirection(x1,x2,x3,sendDir);
+   }
+   else UB_THROW( UbException(UB_EXARGS,"unknown dir") );
+}
+////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter >
+void D3Q27ETVectorConnector< VectorTransmitter >::distributeReceiveVectors()
+{
+   /*e.g. connector sendet nach EAST --> empfaengt daten aus WEST ;-)*/
+   DistributionArray3DPtr  fTo = block.lock()->getKernel()->getDataSet()->getFdistributions();
+   int maxX1 = (int)fTo->getNX1()-1;
+   int maxX2 = (int)fTo->getNX2()-1;
+   int maxX3 = (int)fTo->getNX3()-1;
+   int index = 0;
+   int sendDirForEdge[3];
+
+   vector_type& data = receiver->getData();
+
+   if(sendDir==D3Q27System::W)
+   {
+      for(int x3=1; x3<maxX3; x3++)  
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::E);
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::NE); 
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::SE);
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::TE); 
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::BE);
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::TNE);
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::TSE);
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::BNE);
+            fTo->setDistributionForDirection(data[index++],0,x2,x3,D3Q27System::BSE);
+         }
+      }
+   }
+   else if(sendDir==D3Q27System::E)
+   {
+      for(int x3=1; x3<maxX3; x3++)  
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::W );
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::NW);
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::SW);
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::TW);
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::BW); 
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::TNW);
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::TSW);
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::BNW);
+            fTo->setDistributionForDirection(data[index++],maxX1,x2,x3,D3Q27System::BSW);
+         }
+      }
+   }
+   else if(sendDir==D3Q27System::S)
+   {
+      for(int x3=1; x3<maxX3; x3++)  
+      {
+         for(int x1=1; x1<maxX1; x1++)   
+         {
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::N );
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::NE);
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::NW);
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::TN);
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::BN);
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::TNE);
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::TNW);
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::BNE);
+            fTo->setDistributionForDirection(data[index++],x1,0,x3,D3Q27System::BNW);
+         }
+      }
+   }
+   else if(sendDir==D3Q27System::N)
+   {
+      for(int x3=1; x3<maxX3; x3++)  
+      {
+         for(int x1=1; x1<maxX1; x1++)    
+         {
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::S );
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::SE); 
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::SW); 
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::TS); 
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::BS);
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::TSE);
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::TSW);
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::BSE);
+            fTo->setDistributionForDirection(data[index++],x1,maxX2,x3,D3Q27System::BSW);
+         }
+      }
+   }
+   else if(sendDir==D3Q27System::B)
+   {
+      for(int x2=1; x2<maxX2; x2++)  
+      {
+         for(int x1=1; x1<maxX1; x1++)   
+         {
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::T );
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::TE);
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::TW);
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::TN); 
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::TS);
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::TNE);
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::TNW);
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::TSE);
+            fTo->setDistributionForDirection(data[index++],x1,x2,0,D3Q27System::TSW);
+         }
+      }
+   }
+   else if(sendDir==D3Q27System::T)
+   {
+      for(int x2=1; x2<maxX2; x2++)  
+      {
+         for(int x1=1; x1<maxX1; x1++)   
+         {
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::B );
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::BE);
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::BW);
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::BN);
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::BS);
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::BNE);
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::BNW);
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::BSE);
+            fTo->setDistributionForDirection(data[index++],x1,x2,maxX3,D3Q27System::BSW);
+         }
+      }
+   }
+   //NE NW SW SE
+   else if(sendDir==D3Q27System::NE || sendDir==D3Q27System::NW || sendDir==D3Q27System::SW || sendDir==D3Q27System::SE)
+   {
+      int inversDir = D3Q27System::getInvertDirection(sendDir);
+      int x1 = 0;
+      int x2 = 0;
+      switch(sendDir)  //wenn sendir NE dann kommen werte von SW
+      {
+      case D3Q27System::NE:   x1=maxX1; x2=maxX2; 
+         sendDirForEdge[0]=D3Q27System::SW; 
+         sendDirForEdge[1]=D3Q27System::TSW;
+         sendDirForEdge[2]=D3Q27System::BSW;
+         break;
+      case D3Q27System::NW:   x1=0;     x2=maxX2; 
+         sendDirForEdge[0]=D3Q27System::SE; 
+         sendDirForEdge[1]=D3Q27System::TSE;
+         sendDirForEdge[2]=D3Q27System::BSE;        
+         break;
+      case D3Q27System::SW:   x1=0;     x2=0;       
+         sendDirForEdge[0]=D3Q27System::NE; 
+         sendDirForEdge[1]=D3Q27System::TNE;
+         sendDirForEdge[2]=D3Q27System::BNE;  
+         break;
+      case D3Q27System::SE:   x1=maxX1; x2=0;  
+         sendDirForEdge[0]=D3Q27System::NW; 
+         sendDirForEdge[1]=D3Q27System::TNW;
+         sendDirForEdge[2]=D3Q27System::BNW; 
+         break;
+      }
+      for(int x3=1; x3<maxX3; x3++)
+      {
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[0]);
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[1]);
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[2]);
+      }
+
+   }
+   //TE TW BW BE
+   else if(sendDir==D3Q27System::TE || sendDir==D3Q27System::TW || sendDir==D3Q27System::BW || sendDir==D3Q27System::BE)
+
+   {
+      int inversDir = D3Q27System::getInvertDirection(sendDir);
+      int x1 = 0;
+      int x3 = 0;
+      switch(sendDir)  //wenn sendir NE dann kommen werte von SW
+      {
+      case D3Q27System::TE:   x1=maxX1; x3=maxX3; 
+         sendDirForEdge[0]=D3Q27System::BW; 
+         sendDirForEdge[1]=D3Q27System::BNW;
+         sendDirForEdge[2]=D3Q27System::BSW;
+         break;
+      case D3Q27System::TW:   x1=0;     x3=maxX3; 
+         sendDirForEdge[0]=D3Q27System::BE; 
+         sendDirForEdge[1]=D3Q27System::BNE;
+         sendDirForEdge[2]=D3Q27System::BSE; 
+         break;
+      case D3Q27System::BW:   x1=0;     x3=0;       
+         sendDirForEdge[0]=D3Q27System::TE; 
+         sendDirForEdge[1]=D3Q27System::TNE;
+         sendDirForEdge[2]=D3Q27System::TSE; 
+         break;
+      case D3Q27System::BE:   x1=maxX1; x3=0;      
+         sendDirForEdge[0]=D3Q27System::TW; 
+         sendDirForEdge[1]=D3Q27System::TNW;
+         sendDirForEdge[2]=D3Q27System::TSW; 
+         break;
+      }
+      for(int x2=1; x2<maxX2; x2++) 
+      {  
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[0]);
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[1]);
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[2]);
+      }
+   }
+   //TN BN BS TS
+   else if(sendDir==D3Q27System::TN || sendDir==D3Q27System::BN || sendDir==D3Q27System::BS || sendDir==D3Q27System::TS)
+   {
+      int inversDir = D3Q27System::getInvertDirection(sendDir);
+      int x2 = 0;
+      int x3 = 0;
+      switch(sendDir)  
+      {
+      case D3Q27System::TN:   x3=maxX3; x2=maxX2; 
+         sendDirForEdge[0]=D3Q27System::BS; 
+         sendDirForEdge[1]=D3Q27System::BSE;
+         sendDirForEdge[2]=D3Q27System::BSW;
+         break;
+      case D3Q27System::BN:   x3=0;       x2=maxX2; 
+         sendDirForEdge[0]=D3Q27System::TS; 
+         sendDirForEdge[1]=D3Q27System::TSE;
+         sendDirForEdge[2]=D3Q27System::TSW; 
+         break;
+      case D3Q27System::BS:   x3=0;       x2=0;  
+         sendDirForEdge[0]=D3Q27System::TN; 
+         sendDirForEdge[1]=D3Q27System::TNE;
+         sendDirForEdge[2]=D3Q27System::TNW; 
+         break;
+      case D3Q27System::TS:   x3=maxX3; x2=0;       
+         sendDirForEdge[0]=D3Q27System::BN; 
+         sendDirForEdge[1]=D3Q27System::BNE;
+         sendDirForEdge[2]=D3Q27System::BNW; 
+         break;
+
+      }
+      for(int x1=1; x1<maxX1; x1++) 
+      {  
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[0]);
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[1]);
+         fTo->setDistributionForDirection(data[index++],x1, x2, x3, sendDirForEdge[2]);
+      }
+   }
+   //TNE TNW TSW TSE BNE BNW BSW BSE
+   else if(sendDir==D3Q27System::TNE || sendDir==D3Q27System::TNW || sendDir==D3Q27System::TSW || sendDir==D3Q27System::TSE
+      || sendDir==D3Q27System::BNE || sendDir==D3Q27System::BNW || sendDir==D3Q27System::BSW || sendDir==D3Q27System::BSE)
+   {
+      int inversDir = D3Q27System::getInvertDirection(sendDir);
+      int x1 = 0;
+      int x2 = 0;
+      int x3 = 0;
+      unsigned long int etDir = 0;
+      switch(sendDir) 
+      {
+      case D3Q27System::TNE:   x1=maxX1; x2=maxX2; x3=maxX3; etDir=EsoTwistD3Q27System::etTNE; break;
+      case D3Q27System::TNW:   x1=0; x2=maxX2; x3=maxX3; etDir=EsoTwistD3Q27System::etTNW; break;
+      case D3Q27System::TSW:   x1=0; x2=0; x3=maxX3; etDir=EsoTwistD3Q27System::etTSW; break;
+      case D3Q27System::TSE:   x1=maxX1; x2=0; x3=maxX3; etDir=EsoTwistD3Q27System::etTSE; break;
+      case D3Q27System::BNE:   x1=maxX1; x2=maxX2; x3=0; etDir=EsoTwistD3Q27System::etBNE; break;
+      case D3Q27System::BNW:   x1=0; x2=maxX2; x3=0; etDir=EsoTwistD3Q27System::etBNW; break;
+      case D3Q27System::BSW:   x1=0; x2=0; x3=0; etDir=EsoTwistD3Q27System::etBSW; break;
+      case D3Q27System::BSE:   x1=maxX1; x2=0; x3=0; etDir=EsoTwistD3Q27System::etBSE; break;
+      }
+      fTo->setDistributionForDirection(data[index++],x1, x2, x3, inversDir);
+   }
+   else UB_THROW( UbException(UB_EXARGS,"unknown dir") );
+}
+//////////////////////////////////////////////////////////////////////////
+template< typename VectorTransmitter > 
+double D3Q27ETVectorConnector<VectorTransmitter>::getSendRecieveTime()
+{
+   return 0;
+}
+
+#endif //D3Q27VECTORCONNECTOR_H
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETWithInvDirectConnector.cpp b/source/VirtualFluidsCore/Connectors/D3Q27ETWithInvDirectConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5c588b8e6ffdcc83dca330d4ca60ac1dab41c8f4
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETWithInvDirectConnector.cpp
@@ -0,0 +1,371 @@
+#include "D3Q27ETWithInvDirectConnector.h"
+#include "LBMKernelETD3Q27.h"
+#include "EsoTwistD3Q27System.h"
+
+
+using namespace std;
+
+//Im Anschluss sind die Bulkbereiche synchron 
+
+//*==========================================================*/
+void D3Q27ETWithInvDirectConnector::sendVectors()
+{
+   EsoTwist3DPtr  fFrom =  boost::dynamic_pointer_cast<EsoTwist3D>(from.lock()->getKernel()->getDataSet()->getFdistributions());
+   EsoTwist3DPtr  fTo   = boost::dynamic_pointer_cast<EsoTwist3D>(to.lock()->getKernel()->getDataSet()->getFdistributions());
+
+   int maxX1 = (int)fFrom->getNX1()-1;
+   int maxX2 = (int)fFrom->getNX2()-1;
+   int maxX3 = (int)fFrom->getNX3()-1;
+
+   LBMReal f[D3Q27System::ENDF+1];
+
+   //EAST
+   if(sendDir==D3Q27System::E)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            if(invStep) fFrom->getDistribution(f,maxX1-1,x2,x3);
+            else fFrom->getDistributionInv(f,maxX1-1,x2,x3);
+            if(invStep) fTo->setDistributionInvForDirection(f,0,x2,x3,EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etE 
+                                                      | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTE 
+                                                      | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etTNE
+                                                      | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBNE
+                                                      | EsoTwistD3Q27System::etBSE);
+            else fTo->setDistributionForDirection(f,0,x2,x3,EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etE 
+                                                      | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTE 
+                                                      | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etTNE
+                                                      | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBNE
+                                                      | EsoTwistD3Q27System::etBSE);
+         }
+      }
+   }
+   //WEST
+   else if(sendDir==D3Q27System::W)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x2=1; x2<maxX2; x2++)   
+         {
+            if(invStep) fFrom->getDistribution(f,1,x2,x3);
+            else fFrom->getDistributionInv(f,1,x2,x3);
+            if(invStep) fTo->setDistributionInvForDirection(f,maxX1,x2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etW 
+                                                      | EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etTW 
+                                                      | EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etTNW
+                                                      | EsoTwistD3Q27System::etTSW | EsoTwistD3Q27System::etBNW
+                                                      | EsoTwistD3Q27System::etBSW);
+            else fTo->setDistributionForDirection(f,maxX1,x2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etW 
+                                                        | EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etTW 
+                                                        | EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etTNW
+                                                        | EsoTwistD3Q27System::etTSW | EsoTwistD3Q27System::etBNW
+                                                        | EsoTwistD3Q27System::etBSW);
+         }
+      }
+   }
+   //NORTH
+   else if(sendDir==D3Q27System::N)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)        
+         {                                    
+            if(invStep) fFrom->getDistribution(f,x1,maxX2-1,x3);
+            else fFrom->getDistributionInv(f,x1,maxX2-1,x3);
+            if(invStep) fTo->setDistributionInvForDirection(f,x1,0,x3,EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etN 
+                                                      | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTN 
+                                                      | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etTNW
+                                                      | EsoTwistD3Q27System::etTNE | EsoTwistD3Q27System::etBNW
+                                                      | EsoTwistD3Q27System::etBNE);
+            else fTo->setDistributionForDirection(f,x1,0,x3,EsoTwistD3Q27System::etNW | EsoTwistD3Q27System::etN 
+                                                    | EsoTwistD3Q27System::etNE | EsoTwistD3Q27System::etTN 
+                                                    | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etTNW
+                                                    | EsoTwistD3Q27System::etTNE | EsoTwistD3Q27System::etBNW
+                                                    | EsoTwistD3Q27System::etBNE);
+         }
+      }
+   }
+   //SOUTH
+   else if(sendDir==D3Q27System::S)
+   {
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            if(invStep) fFrom->getDistribution(f,x1,1,x3);
+            else fFrom->getDistributionInv(f,x1,1,x3);
+            if(invStep) fTo->setDistributionInvForDirection(f,x1,maxX2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etS 
+                                                         | EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etTS
+                                                         | EsoTwistD3Q27System::etBS | EsoTwistD3Q27System::etTSW
+                                                         | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBSW
+                                                         | EsoTwistD3Q27System::etBSE);
+            else fTo->setDistributionForDirection(f,x1,maxX2,x3,EsoTwistD3Q27System::etSW | EsoTwistD3Q27System::etS 
+                                                        | EsoTwistD3Q27System::etSE | EsoTwistD3Q27System::etTS
+                                                        | EsoTwistD3Q27System::etBS | EsoTwistD3Q27System::etTSW
+                                                        | EsoTwistD3Q27System::etTSE | EsoTwistD3Q27System::etBSW
+                                                        | EsoTwistD3Q27System::etBSE);
+         }
+      }
+   }
+
+   //TOP
+   else if(sendDir==D3Q27System::T)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            if(invStep) fFrom->getDistribution(f,x1,x2,maxX3-1);
+            else fFrom->getDistributionInv(f,x1,x2,maxX3-1);
+            if(invStep) fTo->setDistributionInvForDirection(f,x1,x2,0,EsoTwistD3Q27System::etTW | EsoTwistD3Q27System::etT 
+                                                      | EsoTwistD3Q27System::etTE | EsoTwistD3Q27System::etTS
+                                                      | EsoTwistD3Q27System::etTN | EsoTwistD3Q27System::etTNE
+                                                      | EsoTwistD3Q27System::etTNW | EsoTwistD3Q27System::etTSW
+                                                      | EsoTwistD3Q27System::etTSE);
+            else fTo->setDistributionForDirection(f,x1,x2,0,EsoTwistD3Q27System::etTW | EsoTwistD3Q27System::etT 
+                                                      | EsoTwistD3Q27System::etTE | EsoTwistD3Q27System::etTS
+                                                      | EsoTwistD3Q27System::etTN | EsoTwistD3Q27System::etTNE
+                                                      | EsoTwistD3Q27System::etTNW | EsoTwistD3Q27System::etTSW
+                                                      | EsoTwistD3Q27System::etTSE);
+         }
+      }
+   }
+   //BOTTOM
+   else if(sendDir==D3Q27System::B)
+   {
+      for(int x2=1; x2<maxX2; x2++)   
+      {
+         for(int x1=1; x1<maxX1; x1++)            
+         {                                        
+            if(invStep) fFrom->getDistribution(f,x1,x2,1);
+            else fFrom->getDistributionInv(f,x1,x2,1);
+            if(invStep) fTo->setDistributionInvForDirection(f,x1,x2,maxX3,EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etB 
+                                                         | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etBS
+                                                         | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etBNE
+                                                         | EsoTwistD3Q27System::etBNW | EsoTwistD3Q27System::etBSW
+                                                         | EsoTwistD3Q27System::etBSE);
+            else fTo->setDistributionForDirection(f,x1,x2,maxX3,EsoTwistD3Q27System::etBW | EsoTwistD3Q27System::etB 
+                                                         | EsoTwistD3Q27System::etBE | EsoTwistD3Q27System::etBS
+                                                         | EsoTwistD3Q27System::etBN | EsoTwistD3Q27System::etBNE
+                                                         | EsoTwistD3Q27System::etBNW | EsoTwistD3Q27System::etBSW
+                                                         | EsoTwistD3Q27System::etBSE);
+         }
+      }
+   }
+   //NORTHEAST
+   else if(sendDir==D3Q27System::NE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         if(invStep) fFrom->getDistribution(f,maxX1-1,maxX2-1,x3);
+         else fFrom->getDistributionInv(f,maxX1-1,maxX2-1,x3);
+         if(invStep) fTo->setDistributionInvForDirection(f,0,0,x3,EsoTwistD3Q27System::etNE
+                                                   | EsoTwistD3Q27System::etTNE
+                                                   | EsoTwistD3Q27System::etBNE);
+         else fTo->setDistributionForDirection(f,0,0,x3,EsoTwistD3Q27System::etNE
+                                                  | EsoTwistD3Q27System::etTNE
+                                                  | EsoTwistD3Q27System::etBNE);
+      }
+   }
+   //NORTHWEST
+   else if(sendDir==D3Q27System::NW)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         if(invStep)fFrom->getDistribution(f,1,maxX2-1,x3);
+         else fFrom->getDistributionInv(f,1,maxX2-1,x3);
+         if(invStep) fTo->setDistributionInvForDirection(f,maxX1,0,x3,EsoTwistD3Q27System::etNW
+                                                   | EsoTwistD3Q27System::etTNW
+                                                   | EsoTwistD3Q27System::etBNW);
+         else fTo->setDistributionForDirection(f,maxX1,0,x3,EsoTwistD3Q27System::etNW
+                                                   | EsoTwistD3Q27System::etTNW
+                                                   | EsoTwistD3Q27System::etBNW);
+      }
+   }
+   //SOUTHWEST
+   else if(sendDir==D3Q27System::SW)
+   {  
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         if(invStep) fFrom->getDistribution(f,1,1,x3);
+         else fFrom->getDistributionInv(f,1,1,x3);
+         if(invStep) fTo->setDistributionInvForDirection(f,maxX1,maxX2,x3,EsoTwistD3Q27System::etSW
+                                                         | EsoTwistD3Q27System::etTSW
+                                                         | EsoTwistD3Q27System::etBSW);
+         else fTo->setDistributionForDirection(f,maxX1,maxX2,x3,EsoTwistD3Q27System::etSW
+                                                         | EsoTwistD3Q27System::etTSW
+                                                         | EsoTwistD3Q27System::etBSW);
+      }
+   }
+   //SOUTHEAST
+   else if(sendDir==D3Q27System::SE)
+   {   
+      for(int x3=1; x3<maxX3; x3++)   
+      {
+         if(invStep) fFrom->getDistribution(f,maxX1-1,1,x3);
+         else fFrom->getDistributionInv(f,maxX1-1,1,x3);
+         if(invStep) fTo->setDistributionInvForDirection(f,0,maxX2,x3,EsoTwistD3Q27System::etSE
+                                                      | EsoTwistD3Q27System::etTSE
+                                                      | EsoTwistD3Q27System::etBSE);
+         else fTo->setDistributionForDirection(f,0,maxX2,x3,EsoTwistD3Q27System::etSE
+                                                      | EsoTwistD3Q27System::etTSE
+                                                      | EsoTwistD3Q27System::etBSE);
+      }
+   }
+   else if(sendDir==D3Q27System::TE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         if(invStep) fFrom->getDistribution(f,maxX1-1,x2,maxX3-1);
+         else fFrom->getDistributionInv(f,maxX1-1,x2,maxX3-1);
+         if(invStep) fTo->setDistributionInvForDirection(f,0,x2,0,EsoTwistD3Q27System::etTE
+                                                | EsoTwistD3Q27System::etTNE
+                                                | EsoTwistD3Q27System::etTSE);
+         else fTo->setDistributionForDirection(f,0,x2,0,EsoTwistD3Q27System::etTE
+                                                | EsoTwistD3Q27System::etTNE
+                                                | EsoTwistD3Q27System::etTSE);
+      }
+   else if(sendDir==D3Q27System::BW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         if(invStep) fFrom->getDistribution(f,1,x2,1);
+         else fFrom->getDistributionInv(f,1,x2,1);
+         if(invStep) fTo->setDistributionInvForDirection(f,maxX1,x2,maxX3,EsoTwistD3Q27System::etBW
+                                                         | EsoTwistD3Q27System::etBNW
+                                                         | EsoTwistD3Q27System::etBSW);
+         else fTo->setDistributionForDirection(f,maxX1,x2,maxX3,EsoTwistD3Q27System::etBW
+                                                         | EsoTwistD3Q27System::etBNW
+                                                         | EsoTwistD3Q27System::etBSW);
+      }
+   else if(sendDir==D3Q27System::BE)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         if(invStep) fFrom->getDistribution(f,maxX1-1,x2,1);
+         else fFrom->getDistributionInv(f,maxX1-1,x2,1);
+         if(invStep) fTo->setDistributionInvForDirection(f,0,x2,maxX3,EsoTwistD3Q27System::etBE
+                                                      | EsoTwistD3Q27System::etBNE
+                                                      | EsoTwistD3Q27System::etBSE);
+         else fTo->setDistributionForDirection(f,0,x2,maxX3,EsoTwistD3Q27System::etBE
+                                                      | EsoTwistD3Q27System::etBNE
+                                                      | EsoTwistD3Q27System::etBSE);
+      }
+   else if(sendDir==D3Q27System::TW)
+      for(int x2=1; x2<maxX2; x2++)
+      {
+         if(invStep) fFrom->getDistribution(f,1,x2,maxX3-1);
+         else fFrom->getDistributionInv(f,1,x2,maxX3-1);
+         if(invStep) fTo->setDistributionInvForDirection(f,maxX1,x2,0,EsoTwistD3Q27System::etTW
+                                                      | EsoTwistD3Q27System::etTNW
+                                                      | EsoTwistD3Q27System::etTSW);
+         else fTo->setDistributionForDirection(f,maxX1,x2,0,EsoTwistD3Q27System::etTW
+                                                      | EsoTwistD3Q27System::etTNW
+                                                      | EsoTwistD3Q27System::etTSW);
+      }
+   else if(sendDir==D3Q27System::TN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         if(invStep) fFrom->getDistribution(f,x1,maxX2-1,maxX3-1);
+         else fFrom->getDistributionInv(f,x1,maxX2-1,maxX3-1);
+         if(invStep) fTo->setDistributionInvForDirection(f,x1,0,0,EsoTwistD3Q27System::etTN
+                                                | EsoTwistD3Q27System::etTNW
+                                                | EsoTwistD3Q27System::etTNE);
+         else fTo->setDistributionForDirection(f,x1,0,0,EsoTwistD3Q27System::etTN
+                                                | EsoTwistD3Q27System::etTNW
+                                                | EsoTwistD3Q27System::etTNE);
+      }
+   else if(sendDir==D3Q27System::BS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         fFrom->getDistributionInv(f,x1,1,1);
+         fTo->setDistributionForDirection(f,x1,maxX2,maxX3,EsoTwistD3Q27System::etBS
+                                                         | EsoTwistD3Q27System::etBSW
+                                                         | EsoTwistD3Q27System::etBSE);
+      }
+   else if(sendDir==D3Q27System::BN)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         if(invStep) fFrom->getDistribution(f,x1,maxX2-1,1);
+         else fFrom->getDistributionInv(f,x1,maxX2-1,1);
+         if(invStep) fTo->setDistributionInvForDirection(f,x1,0,maxX3,EsoTwistD3Q27System::etBN
+                                                      | EsoTwistD3Q27System::etBNW
+                                                      | EsoTwistD3Q27System::etBNE);
+         else fTo->setDistributionForDirection(f,x1,0,maxX3,EsoTwistD3Q27System::etBN
+                                                      | EsoTwistD3Q27System::etBNW
+                                                      | EsoTwistD3Q27System::etBNE);
+      }
+
+   else if(sendDir==D3Q27System::TS)
+      for(int x1=1; x1<maxX1; x1++)
+      {
+         if(invStep) fFrom->getDistribution(f,x1,1,maxX3-1);
+         else fFrom->getDistributionInv(f,x1,1,maxX3-1);
+         if(invStep) fTo->setDistributionInvForDirection(f,x1,maxX2,0,EsoTwistD3Q27System::etTS
+                                                      | EsoTwistD3Q27System::etTSW
+                                                      | EsoTwistD3Q27System::etTSE);
+         else fTo->setDistributionForDirection(f,x1,maxX2,0,EsoTwistD3Q27System::etTS
+                                                      | EsoTwistD3Q27System::etTSW
+                                                      | EsoTwistD3Q27System::etTSE);
+      }
+
+   else if(sendDir==D3Q27System::TSW)
+   {
+      if(invStep) fFrom->getDistribution(f,1,1,maxX3-1);
+      else fFrom->getDistributionInv(f,1,1,maxX3-1);
+      if(invStep) fTo->setDistributionInvForDirection(f,maxX1,maxX2,0,EsoTwistD3Q27System::etTSW);
+      else fTo->setDistributionForDirection(f,maxX1,maxX2,0,EsoTwistD3Q27System::etTSW);
+   }
+   else if(sendDir==D3Q27System::TSE)
+   {
+      if(invStep) fFrom->getDistribution(f,maxX1-1,1,maxX3-1);
+      else fFrom->getDistributionInv(f,maxX1-1,1,maxX3-1);
+      if(invStep) fTo->setDistributionInvForDirection(f,0,maxX2,0,EsoTwistD3Q27System::etTSE);
+      else fTo->setDistributionForDirection(f,0,maxX2,0,EsoTwistD3Q27System::etTSE);
+   }
+   else if(sendDir==D3Q27System::TNW)
+   {
+      if(invStep) fFrom->getDistribution(f,1,maxX2-1,maxX3-1);
+      else fFrom->getDistributionInv(f,1,maxX2-1,maxX3-1);
+      if(invStep) fTo->setDistributionInvForDirection(f,maxX1,0,0,EsoTwistD3Q27System::etTNW);
+      else fTo->setDistributionForDirection(f,maxX1,0,0,EsoTwistD3Q27System::etTNW);
+   }
+   else if(sendDir==D3Q27System::TNE)
+   {
+      if(invStep) fFrom->getDistribution(f,maxX1-1,maxX2-1,maxX3-1);
+      else fFrom->getDistributionInv(f,maxX1-1,maxX2-1,maxX3-1);
+      if(invStep) fTo->setDistributionInvForDirection(f,0,0,0,EsoTwistD3Q27System::etTNE);
+      else fTo->setDistributionForDirection(f,0,0,0,EsoTwistD3Q27System::etTNE);
+   }
+   else if(sendDir==D3Q27System::BSW)
+   {
+      if(invStep) fFrom->getDistribution(f,1,1,1);
+      else fFrom->getDistributionInv(f,1,1,1);
+      if(invStep) fTo->setDistributionInvForDirection(f,maxX1,maxX2,maxX3,EsoTwistD3Q27System::etBSW);
+      else fTo->setDistributionForDirection(f,maxX1,maxX2,maxX3,EsoTwistD3Q27System::etBSW);
+   }
+   else if(sendDir==D3Q27System::BSE)
+   {
+      if(invStep) fFrom->getDistribution(f,maxX1-1,1,1);
+      else fFrom->getDistributionInv(f,maxX1-1,1,1);
+      if(invStep) fTo->setDistributionInvForDirection(f,0,maxX2,maxX3,EsoTwistD3Q27System::etBSE);
+      else fTo->setDistributionForDirection(f,0,maxX2,maxX3,EsoTwistD3Q27System::etBSE);
+   }
+   else if(sendDir==D3Q27System::BNW)
+   {
+      if(invStep) fFrom->getDistribution(f,1,maxX2-1,1);
+      else fFrom->getDistributionInv(f,1,maxX2-1,1);
+      if(invStep) fTo->setDistributionInvForDirection(f,maxX1,0,maxX3,EsoTwistD3Q27System::etBNW);
+      else fTo->setDistributionForDirection(f,maxX1,0,maxX3,EsoTwistD3Q27System::etBNW);
+   }
+   else if(sendDir==D3Q27System::BNE)
+   {
+      if(invStep) fFrom->getDistribution(f,maxX1-1,maxX2-1,1);
+      else fFrom->getDistributionInv(f,maxX1-1,maxX2-1,1);
+      if(invStep) fTo->setDistributionInvForDirection(f,0,0,maxX3,EsoTwistD3Q27System::etBNE);
+      else fTo->setDistributionForDirection(f,0,0,maxX3,EsoTwistD3Q27System::etBNE);
+   }
+   else UB_THROW( UbException(UB_EXARGS,"unknown dir") );
+}
+//////////////////////////////////////////////////////////////////////////
+double D3Q27ETWithInvDirectConnector::getSendRecieveTime()
+{
+   return 0;
+}
diff --git a/source/VirtualFluidsCore/Connectors/D3Q27ETWithInvDirectConnector.h b/source/VirtualFluidsCore/Connectors/D3Q27ETWithInvDirectConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..486053ebaced7edbd0b4459bba47a820b347c40c
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/D3Q27ETWithInvDirectConnector.h
@@ -0,0 +1,60 @@
+#ifndef D3Q27ETWithInvDIRECTCONNECTOR_H
+#define D3Q27ETWithInvDIRECTCONNECTOR_H
+
+#include <boost/weak_ptr.hpp>
+
+#include "Block3DConnector.h"
+#include "Block3D.h"
+
+class D3Q27ETWithInvDirectConnector : public Block3DConnector
+{
+public:
+   D3Q27ETWithInvDirectConnector(Block3DPtr from, Block3DPtr to, const int& sendDir)
+      :  Block3DConnector(sendDir)
+        , from(from)
+        , to(to)
+   {
+
+   }
+   
+   void sendTransmitterDataSize()    { }  
+   void receiveTransmitterDataSize() { }
+   void init()                       { }
+   void prepareForReceive()          { }
+   void prepareForSend()             { }
+   void fillSendVectors()            { }
+   void sendVectors();//                { }
+   void receiveVectors()             { }
+   
+   void distributeReceiveVectors()   { }
+
+   bool isLocalConnector()  { return true;  }
+   bool isRemoteConnector() { return false; }
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return false; }
+
+   double getSendRecieveTime();
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1(){}
+   void sendVectorsX2(){}
+   void sendVectorsX3(){}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> from;
+   boost::weak_ptr<Block3D> to;
+};
+
+#endif //D3Q27DIRECTCONNECTOR_H
+
diff --git a/source/VirtualFluidsCore/Connectors/FineToCoarseBlock3DConnector.cpp b/source/VirtualFluidsCore/Connectors/FineToCoarseBlock3DConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d861e19f682a21e9fdf37a127789ad7b6d0e603
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/FineToCoarseBlock3DConnector.cpp
@@ -0,0 +1,77 @@
+#include "FineToCoarseBlock3DConnector.h"
+
+////////////////////////////////////////////////////////////////////////////
+FineToCoarseBlock3DConnector::FineToCoarseBlock3DConnector(Block3DPtr block, VectorTransmitterPtr sender,
+   VectorTransmitterPtr receiver, int sendDir,
+   D3Q27InterpolationProcessorPtr iprocessor,
+   CFconnectorType connType)
+   : Block3DConnector(sendDir)
+   , block(block)
+   , sender(sender)
+   , receiver(receiver)
+   , iprocessor(iprocessor)
+   , connType(connType)
+{
+   if (!(sendDir==D3Q27System::E  || sendDir==D3Q27System::W  || sendDir==D3Q27System::N  || sendDir==D3Q27System::S  || sendDir==D3Q27System::T || sendDir==D3Q27System::B
+      ||  sendDir==D3Q27System::NE || sendDir==D3Q27System::SW || sendDir==D3Q27System::SE || sendDir==D3Q27System::NW
+      ||  sendDir==D3Q27System::TE || sendDir==D3Q27System::BW ||  sendDir==D3Q27System::BE || sendDir==D3Q27System::TW
+      ||  sendDir==D3Q27System::TN || sendDir==D3Q27System::BS ||  sendDir==D3Q27System::BN || sendDir==D3Q27System::TS
+
+      ||  sendDir==D3Q27System::TNE || sendDir==D3Q27System::TNW ||  sendDir==D3Q27System::TSE || sendDir==D3Q27System::TSW
+      ||  sendDir==D3Q27System::BNE || sendDir==D3Q27System::BNW ||  sendDir==D3Q27System::BSE || sendDir==D3Q27System::BSW
+
+      ))
+   {
+      throw UbException(UB_EXARGS, "invalid constructor for this direction");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+bool FineToCoarseBlock3DConnector::isLocalConnector()
+{
+   return !this->isRemoteConnector();
+}
+//////////////////////////////////////////////////////////////////////////
+bool FineToCoarseBlock3DConnector::isRemoteConnector()
+{
+   return sender->isRemoteTransmitter()  ||  receiver->isRemoteTransmitter();
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseBlock3DConnector::sendTransmitterDataSize()
+{
+   if (sender)
+   {
+      UBLOG(logDEBUG5, "FineToCoarseBlock3DConnector<VectorTransmitter>::sendTransmitterDataSize()"<<block.lock()->toString()+"sendDir="<<sendDir);
+      sender->sendDataSize();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseBlock3DConnector::receiveTransmitterDataSize()
+{
+   if (receiver)
+   {
+      UBLOG(logDEBUG5, "FineToCoarseBlock3DConnector<VectorTransmitter>::receiveTransmitterDataSize()"<<block.lock()->toString()<<"sendDir="<<sendDir);
+      receiver->receiveDataSize();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseBlock3DConnector::prepareForSend()
+{
+   if (sender) sender->prepareForSend();
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseBlock3DConnector::sendVectors()
+{
+   if (sender) sender->sendData();
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseBlock3DConnector::prepareForReceive()
+{
+   if (receiver) receiver->prepareForReceive();
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseBlock3DConnector::receiveVectors()
+{
+   if (receiver) receiver->receiveData();
+}
+
+
diff --git a/source/VirtualFluidsCore/Connectors/FineToCoarseBlock3DConnector.h b/source/VirtualFluidsCore/Connectors/FineToCoarseBlock3DConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..c27b041d5110066281c1a5aefcbd53c963990f75
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/FineToCoarseBlock3DConnector.h
@@ -0,0 +1,95 @@
+//! \file FineToCoarseBlock3DConnector.h
+//! \brief Base class for connectors that interpolates and sends data from fine level to coarse.  
+//! \author Konstantin Kutscher
+//! \date 21.05.2015
+
+#ifndef FineToCoarseBlock3DConnector_H
+#define FineToCoarseBlock3DConnector_H
+
+#include "TransmitterType.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27InterpolationProcessor.h"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+class Block3D;
+
+//! \class FineToCoarseBlock3DConnector
+//! \brief Base class for connectors that interpolates and sends data from fine level to coarse.  
+//! \details The data is copied in a vector (this is located in the transmitter). 
+//! The vector is transmitted via transmitter. 
+//! The transmitter can be a local, MPI, RCG, CTL or whatever 
+//! which a transmitter that is derived from transmitter base class.
+//!
+//! four fine blocks inside a coarse block:
+//!
+//! |    |    |
+//! |:--:|:---| 
+//! | 01 | 11 | 
+//! | 00 | 10 | 
+//!
+//! send direction:    
+//!
+//! |E<->W   |  N<->S  |  T<->B |
+//! |--------|---------|--------|
+//! |  x3    |   x3    |    x2  |
+//! |  ^     |   ^     |    ^   |
+//! |  +->x2 |  +->x1  |   +->x1|
+
+class FineToCoarseBlock3DConnector : public Block3DConnector
+{
+public:
+   enum CFconnectorType { Type00, Type10, Type01, Type11 };
+public:
+   FineToCoarseBlock3DConnector(Block3DPtr block, VectorTransmitterPtr sender, VectorTransmitterPtr receiver, int sendDir, D3Q27InterpolationProcessorPtr iprocessor, CFconnectorType connType);
+
+   bool isLocalConnector();
+   bool isRemoteConnector();
+   
+   void sendTransmitterDataSize();
+   void receiveTransmitterDataSize();
+
+   void prepareForSend();
+   void sendVectors();
+
+   void prepareForReceive();
+   void receiveVectors();
+
+   virtual void init()=0;
+   virtual void fillSendVectors()=0;
+   virtual void distributeReceiveVectors()=0;
+
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return true; }
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1() {}
+   void sendVectorsX2() {}
+   void sendVectorsX3() {}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> block; 
+   VectorTransmitterPtr sender, receiver;
+   D3Q27InterpolationProcessorPtr iprocessor;
+   CFconnectorType connType;
+};
+
+
+
+#endif 
+
diff --git a/source/VirtualFluidsCore/Connectors/FineToCoarseNodeSetBlock3DConnector.cpp b/source/VirtualFluidsCore/Connectors/FineToCoarseNodeSetBlock3DConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..449ed5eb9364b3ca7d261b8598117799bcebe039
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/FineToCoarseNodeSetBlock3DConnector.cpp
@@ -0,0 +1,1232 @@
+#include "FineToCoarseNodeSetBlock3DConnector.h"
+
+//////////////////////////////////////////////////////////////////////////
+FineToCoarseNodeSetBlock3DConnector::FineToCoarseNodeSetBlock3DConnector(Block3DPtr block, VectorTransmitterPtr sender, VectorTransmitterPtr receiver,
+   int sendDir, D3Q27InterpolationProcessorPtr iprocessor, CFconnectorType connType) : FineToCoarseBlock3DConnector(block, sender, receiver, sendDir, iprocessor, connType)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::init()
+{
+   bMaxX1 = (int)FineToCoarseBlock3DConnector::block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX1();
+   bMaxX2 = (int)FineToCoarseBlock3DConnector::block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX2();
+   bMaxX3 = (int)FineToCoarseBlock3DConnector::block.lock()->getKernel()->getDataSet()->getFdistributions()->getNX3();
+
+   minX1 = 0;
+   minX2 = 0;
+   minX3 = 0;
+   maxX1 = bMaxX1 - 1;
+   maxX2 = bMaxX2 - 1;
+   maxX3 = bMaxX3 - 1;
+
+   minOffX1 = 0;
+   minOffX2 = 0;
+   minOffX3 = 0;
+
+   maxOffX1 = 0;
+   maxOffX2 = 0;
+   maxOffX3 = 0;
+
+   if (Utilities::isEven(bMaxX1))
+   {
+      minOffX1 = 0;
+      maxOffX1 = 0;
+   }
+   else if (Utilities::isOdd(bMaxX1))
+   {
+      minOffX1 = 1;
+      maxOffX1 = -1;
+   }
+
+   if (Utilities::isEven(bMaxX2))
+   {
+      minOffX2 = 0;
+      maxOffX2 = 0;
+   }
+   else if (Utilities::isOdd(bMaxX2))
+   {
+      minOffX2 = 1;
+      maxOffX2 = -1;
+   }
+
+   if (Utilities::isEven(bMaxX3))
+   {
+      minOffX3 = 0;
+      maxOffX3 = 0;
+   }
+   else if (Utilities::isOdd(bMaxX3))
+   {
+      minOffX3 = 1;
+      maxOffX3 = -1;
+   }
+
+   //int       sendSize = 0;
+   LBMReal initValue = -999.0;
+
+   int sendDataPerNode = 27/*f*/;
+   int iCellSize = 1; //size of interpolation cell
+
+   findFCCells();
+   findCFCells();
+
+   //////////////////////////////////////////////////////
+   //Debug
+   //////////////////////////////////////////////////////
+   if (FineToCoarseBlock3DConnector::block.lock()->getGlobalID() == 2183)
+   {
+      int test = 0;
+   }
+
+
+   if (FineToCoarseBlock3DConnector::sender) FineToCoarseBlock3DConnector::sender->getData().resize(iNodeSetSender.size()*iCellSize*sendDataPerNode, initValue);
+   else FineToCoarseBlock3DConnector::sender = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+
+   if (!FineToCoarseBlock3DConnector::receiver) FineToCoarseBlock3DConnector::receiver = VectorTransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::findFCCells(int lMinX1, int lMinX2, int lMinX3, int lMaxX1, int lMaxX2, int lMaxX3, INodeSet &inodes)
+{
+   //////////////////////////////////////////////////////
+   //Debug
+   //////////////////////////////////////////////////////
+   if (FineToCoarseBlock3DConnector::block.lock()->getGlobalID() == 2183)
+   {
+      int test = 0;
+   }
+
+
+   int ix1, ix2, ix3;
+   LBMReal x1off, x2off, x3off;
+
+   DistributionArray3DPtr  fFrom = FineToCoarseBlock3DConnector::block.lock()->getKernel()->getDataSet()->getFdistributions();
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(FineToCoarseBlock3DConnector::block.lock()->getKernel()->getBCProcessor())->getBCArray();
+
+   for (ix3 = lMinX3; ix3<=lMaxX3; ix3 += 2)
+   {
+      for (ix2 = lMinX2; ix2<=lMaxX2; ix2 += 2)
+      {
+         for (ix1 = lMinX1; ix1<=lMaxX1; ix1 += 2)
+         {
+            D3Q27ICell icellC;
+
+            int howManySolids = FineToCoarseBlock3DConnector::iprocessor->iCellHowManySolids(bcArray, ix1, ix2, ix3);
+
+            if (howManySolids == 0 || howManySolids == 8)
+            {
+               x1off = 0.0;
+               x2off = 0.0;
+               x3off = 0.0;
+            }
+            else
+            {
+               if (!iprocessor->findNeighborICell(bcArray, fFrom, icellC, bMaxX1, bMaxX2, bMaxX3, ix1, ix2, ix3, x1off, x2off, x3off))
+               {
+                  std::string err = "For "+FineToCoarseBlock3DConnector::block.lock()->toString()+" x1="+UbSystem::toString(ix1)+", x2=" + UbSystem::toString(ix2)+", x3=" + UbSystem::toString(ix3)+
+                     " interpolation is not implemented for other direction"+
+                     " by using in: "+(std::string)typeid(*this).name()+
+                     " or maybe you have a solid on the block boundary";
+                  UB_THROW(UbException(UB_EXARGS, err));
+               }
+            }
+
+            INodeVector inv;
+            inv.push_back(ix1 + (int)x1off);
+            inv.push_back(ix2 + (int)x2off);
+            inv.push_back(ix3 + (int)x3off);
+            inv.push_back((int)x1off);
+            inv.push_back((int)x2off);
+            inv.push_back((int)x3off);
+            //inodes.insert(inv);
+            inodes.push_back(inv);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+
+void FineToCoarseNodeSetBlock3DConnector::findFCCells()
+{
+   using namespace D3Q27System;
+
+   int lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3;
+   int lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3;
+   int lMin3X1, lMin3X2, lMin3X3, lMax3X1, lMax3X2, lMax3X3;
+
+   //lMin1X1 = minX1+1; lMin1X2 = minX2+1; lMin1X3 = minX3+1;
+   //lMax1X1 = maxX1-1; lMax1X2 = maxX2-1; lMax1X3 = maxX3-1;
+   //getLocalMinMax(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3);
+
+   //lMin2X1 = minX1+1; lMin2X2 = minX2+1; lMin2X3 = minX3+1;
+   //lMax2X1 = maxX1-1; lMax2X2 = maxX2-1; lMax2X3 = maxX3-1;
+   //getLocalMinMax(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3);
+
+   //lMin3X1 = minX1+1; lMin3X2 = minX2+1; lMin3X3 = minX3+1;
+   //lMax3X1 = maxX1-1; lMax3X2 = maxX2-1; lMax3X3 = maxX3-1;
+   //getLocalMinMax(lMin3X1, lMin3X2, lMin3X3, lMax3X1, lMax3X2, lMax3X3);
+
+   switch (sendDir)
+   {
+      //faces
+   case E: case W:
+      if (sendDir == E)
+      {
+         lMin1X1 = maxX1 - 6;
+         lMax1X1 = lMin1X1;
+      }
+      else if (sendDir == W)
+      {
+         lMin1X1 = 5;
+         lMax1X1 = lMin1X1;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMin1X2 = minX2;
+         lMax1X2 = maxX2 + maxOffX2 - 1;
+         lMin1X3 = minX3;
+         lMax1X3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMin1X2 = minX2 + minOffX2;
+         lMax1X2 = maxX2 - 1;
+         lMin1X3 = minX3;
+         lMax1X3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type01)
+      {
+         lMin1X2 = minX2;
+         lMax1X2 = maxX2 + maxOffX2 - 1;
+         lMin1X3 = minX3 + minOffX3;
+         lMax1X3 = maxX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type11)
+      {
+         lMin1X2 = minX2 + minOffX2;
+         lMax1X2 = maxX2 - 1;
+         lMin1X3 = minX3 + minOffX3;
+         lMax1X3 = maxX3 - 1;
+      }
+      findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetSender);
+      break;
+   case N: case S:
+      if (sendDir == N)
+      {
+         lMin1X2 = maxX2 - 6;
+         lMax1X2 = lMin1X2;
+      }
+      else if (sendDir == S)
+      {
+         lMin1X2 = 5;
+         lMax1X2 = lMin1X2;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxX1 + maxOffX1 - 1;
+         lMin1X3 = minX3;
+         lMax1X3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMin1X1 = minX1 + minOffX1;
+         lMax1X1 = maxX1 - 1;
+         lMin1X3 = minX3;
+         lMax1X3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type01)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxX1 + maxOffX1 - 1;
+         lMin1X3 = minX3 + minOffX3;
+         lMax1X3 = maxX3;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type11)
+      {
+         lMin1X1 = minX1 + minOffX1;
+         lMax1X1 = maxX1 - 1;
+         lMin1X3 = minX3 + minOffX3;
+         lMax1X3 = maxX3 - 1;
+      }
+      findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetSender);
+      break;
+   case T: case B:
+      if (sendDir == T)
+      {
+         lMin1X3 = maxX3 - 6;
+         lMax1X3 = lMin1X3;
+      }
+      else if (sendDir == B)
+      {
+         lMin1X3 = 5;
+         lMax1X3 = lMin1X3;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxX1 + maxOffX1 - 1;
+         lMin1X2 = minX2;
+         lMax1X2 = maxX2 + maxOffX2 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMin1X1 = minX1 + minOffX1;
+         lMax1X1 = maxX1 - 1;
+         lMin1X2 = minX2;
+         lMax1X2 = maxX2 + maxOffX2 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type01)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxX1 + maxOffX1 - 1;
+         lMin1X2 = minX2 + minOffX2;
+         lMax1X2 = maxX2 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type11)
+      {
+         lMin1X1 = minX1 + minOffX1;
+         lMax1X1 = maxX1 - 1;
+         lMin1X2 = minX2 + minOffX2;
+         lMax1X2 = maxX2 - 1;
+      }
+      findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetSender);
+      break;
+      //edges
+      //N-S-E-W
+   case NE: case SW: case SE: case NW:
+      if (sendDir == NE)
+      {
+         lMin1X1 = maxX1 - 6;
+         lMax1X1 = lMin1X1 + 4;
+         lMin1X2 = maxX2 - 6;
+         lMax1X2 = lMin1X2;
+
+         lMin2X1 = maxX1 - 6;
+         lMax2X1 = lMin2X1;
+         lMin2X2 = maxX2 - 6;
+         lMax2X2 = lMin2X2 + 4;
+      }
+      else if (sendDir == SW)
+      {
+         lMin1X1 = 1;
+         lMax1X1 = lMin1X1 + 4;
+         lMin1X2 = 5;
+         lMax1X2 = lMin1X2;
+
+         lMin2X1 = 5;
+         lMax2X1 = lMin2X1;
+         lMin2X2 = 1;
+         lMax2X2 = lMin2X2 + 4;
+      }
+      else if (sendDir == SE)
+      {
+         lMin1X1 = maxX1 - 6;
+         lMax1X1 = lMin1X1 + 4;
+         lMin1X2 = 5;
+         lMax1X2 = lMin1X2;
+
+         lMin2X1 = maxX1 - 6;
+         lMax2X1 = lMin2X1;
+         lMin2X2 = 1;
+         lMax2X2 = lMin2X2 + 4;
+      }
+      else if (sendDir == NW)
+      {
+         lMin1X1 = 1;
+         lMax1X1 = lMin1X1 + 4;
+         lMin1X2 = maxX2 - 6;
+         lMax1X2 = lMin1X2;
+
+         lMin2X1 = 5;
+         lMax2X1 = lMin2X1;
+         lMin2X2 = maxX2 - 6;
+         lMax2X2 = lMin2X2 + 4;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMin1X3 = minX3;
+         lMax1X3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMin1X3 = minX3 + minOffX3;
+         lMax1X3 = maxX3 - 1;
+      }
+
+      findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetSender);
+      findFCCells(lMin2X1, lMin2X2, lMin1X3, lMax2X1, lMax2X2, lMax1X3, iNodeSetSender);
+
+      break;
+      //T-B-E-W
+   case TE: case BW: case BE: case TW:
+      if (sendDir == TE)
+      {
+         lMin1X1 = maxX1 - 6;
+         lMax1X1 = lMin1X1 + 4;
+         lMin1X3 = maxX3 - 6;
+         lMax1X3 = lMin1X3;
+
+         lMin2X1 = maxX1 - 6;
+         lMax2X1 = lMin2X1;
+         lMin2X3 = maxX3 - 6;
+         lMax2X3 = lMin2X3 + 4;
+      }
+      else if (sendDir == BW)
+      {
+         lMin1X1 = 1;
+         lMax1X1 = lMin1X1 + 4;
+         lMin1X3 = 5;
+         lMax1X3 = lMin1X3;
+
+         lMin2X1 = 5;
+         lMax2X1 = lMin2X1;
+         lMin2X3 = 1;
+         lMax2X3 = lMin2X3 + 4;
+      }
+      else if (sendDir == BE)
+      {
+         lMin1X1 = maxX1 - 6;
+         lMax1X1 = lMin1X1 + 4;
+         lMin1X3 = 5;
+         lMax1X3 = lMin1X3;
+
+
+         lMin2X1 = maxX1 - 6;
+         lMax2X1 = lMin2X1;
+         lMin2X3 = 1;
+         lMax2X3 = lMin2X3 + 4;
+      }
+      else if (sendDir == TW)
+      {
+         lMin1X1 = 1;
+         lMax1X1 = lMin1X1 + 5;
+         lMin1X3 = maxX3 - 6;
+         lMax1X3 = lMin1X3;
+
+         lMin2X1 = 5;
+         lMax2X1 = lMin2X1;
+         lMin2X3 = maxX3 - 6;
+         lMax2X3 = lMin2X3 + 4;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMin1X2 = minX2;
+         lMax1X2 = maxX2 + maxOffX2 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMin1X2 = minX2 + minOffX2;
+         lMax1X2 = maxX2 - 1;
+      }
+
+      findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetSender);
+      findFCCells(lMin2X1, lMin1X2, lMin2X3, lMax2X1, lMax1X2, lMax2X3, iNodeSetSender);
+      break;
+      //T-B-N-S
+   case TN: case BS: case BN: case TS:
+      if (sendDir == TN)
+      {
+         lMin1X2 = maxX2 - 6;
+         lMax1X2 = lMin1X2 + 4;
+         lMin1X3 = maxX3 - 6;
+         lMax1X3 = lMin1X3;
+
+         lMin2X2 = maxX2 - 6;
+         lMax2X2 = lMin2X2;
+         lMin2X3 = maxX3 - 6;
+         lMax2X3 = lMin2X3 + 4;
+      }
+      else if (sendDir == BS)
+      {
+         lMin1X2 = 1;
+         lMax1X2 = lMin1X2 + 4;
+         lMin1X3 = 5;
+         lMax1X3 = lMin1X3;
+
+         lMin2X2 = 5;
+         lMax2X2 = lMin2X2;
+         lMin2X3 = 1;
+         lMax2X3 = lMin2X3 + 4;
+      }
+      else if (sendDir == BN)
+      {
+         lMin1X2 = maxX2 - 6;
+         lMax1X2 = lMin1X2 + 4;
+         lMin1X3 = 5;
+         lMax1X3 = lMin1X3;
+
+         lMin2X2 = maxX2 - 6;
+         lMax2X2 = lMin2X2;
+         lMin2X3 = 1;
+         lMax2X3 = lMin2X3 + 4;
+      }
+      else if (sendDir == TS)
+      {
+         lMin1X2 = 1;
+         lMax1X2 = lMin1X2 + 4;
+         lMin1X3 = maxX3 - 6;
+         lMax1X3 = lMin1X3;
+
+         lMin2X2 = 5;
+         lMax2X2 = lMin2X2;
+         lMin2X3 = maxX3 - 6;
+         lMax2X3 = lMin2X3 + 4;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMin1X1 = minX1;
+         lMax1X1 = maxX1 + maxOffX1 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMin1X1 = minX1 + minOffX1;
+         lMax1X1 = maxX1 - 1;
+      }
+
+      findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetSender);
+      findFCCells(lMin1X1, lMin2X2, lMin2X3, lMax1X1, lMax2X2, lMax2X3, iNodeSetSender);
+      break;
+      //corners
+   case TNE: case TNW: case TSE: case TSW: case BNE: case BNW: case BSE: case BSW:
+      if (sendDir == TNE)
+      {
+         lMin1X1 = maxX1-6;
+         lMax1X1 = maxX1-6;
+         lMin1X2 = maxX2-6;
+         lMax1X2 = maxX2-2;
+         lMin1X3 = maxX3-6;
+         lMax1X3 = maxX3-2;
+
+         lMin2X1 = maxX1-6;
+         lMax2X1 = maxX1-2;
+         lMin2X2 = maxX2-6;
+         lMax2X2 = maxX2-6;
+         lMin2X3 = maxX3-6;
+         lMax2X3 = maxX3-1;
+
+         lMin3X1 = maxX1-6;
+         lMax3X1 = maxX1-2;
+         lMin3X2 = maxX2-6;
+         lMax3X2 = maxX2-2;
+         lMin3X3 = maxX3-6;
+         lMax3X3 = maxX3-5;
+      }
+      else if (sendDir == TNW)
+      {
+         lMin1X1 = 5;
+         lMax1X1 = 5;
+         lMin1X2 = maxX2-6;
+         lMax1X2 = maxX2-2;
+         lMin1X3 = maxX3-6;
+         lMax1X3 = maxX3-2;
+
+         lMin2X1 = 1;
+         lMax2X1 = 5;
+         lMin2X2 = maxX2-6;
+         lMax2X2 = maxX2-6;
+         lMin2X3 = maxX3-6;
+         lMax2X3 = maxX3-2;
+
+         lMin3X1 = 1;
+         lMax3X1 = 5;
+         lMin3X2 = maxX2-6;
+         lMax3X2 = maxX2-2;
+         lMin3X3 = maxX3-6;
+         lMax3X3 = maxX3-6;
+      }
+      else if (sendDir == TSE)
+      {
+         lMin1X1 = maxX1-6;
+         lMax1X1 = maxX1-6;
+         lMin1X2 = 1;
+         lMax1X2 = 5;
+         lMin1X3 = maxX3-6;
+         lMax1X3 = maxX3-2;
+
+         lMin2X1 = maxX1-6;
+         lMax2X1 = maxX1-2;
+         lMin2X2 = 5;
+         lMax2X2 = 5;
+         lMin2X3 = maxX3-6;
+         lMax2X3 = maxX3-2;
+
+         lMin3X1 = maxX1-6;
+         lMax3X1 = maxX1-2;
+         lMin3X2 = 1;
+         lMax3X2 = 5;
+         lMin3X3 = maxX3-6;
+         lMax3X3 = maxX3-6;
+      }
+      else if (sendDir == TSW)
+      {
+         lMin1X1 = 5;
+         lMax1X1 = 5;
+         lMin1X2 = 1;
+         lMax1X2 = 5;
+         lMin1X3 = maxX3-6;
+         lMax1X3 = maxX3-2;
+
+         lMin2X1 = 1;
+         lMax2X1 = 5;
+         lMin2X2 = 5;
+         lMax2X2 = 5;
+         lMin2X3 = maxX3-6;
+         lMax2X3 = maxX3-2;
+
+         lMin3X1 = 1;
+         lMax3X1 = 5;
+         lMin3X2 = 1;
+         lMax3X2 = 5;
+         lMin3X3 = maxX3-6;
+         lMax3X3 = maxX3-6;
+      }
+      else if (sendDir == BNE)
+      {
+         lMin1X1 = maxX1-6;
+         lMax1X1 = maxX1-6;
+         lMin1X2 = maxX2-6;
+         lMax1X2 = maxX2-2;
+         lMin1X3 = 1;
+         lMax1X3 = 5;
+
+         lMin2X1 = maxX1-6;
+         lMax2X1 = maxX1-2;
+         lMin2X2 = maxX2-6;
+         lMax2X2 = maxX2-6;
+         lMin2X3 = 1;
+         lMax2X3 = 5;
+
+         lMin3X1 = maxX1-6;
+         lMax3X1 = maxX1-2;
+         lMin3X2 = maxX2-6;
+         lMax3X2 = maxX2-2;
+         lMin3X3 = 5;
+         lMax3X3 = 5;
+      }
+      else if (sendDir == BNW)
+      {
+         lMin1X1 = 5;
+         lMax1X1 = 5;
+         lMin1X2 = maxX2-6;
+         lMax1X2 = maxX2-2;
+         lMin1X3 = 1;
+         lMax1X3 = 5;
+
+         lMin2X1 = 1;
+         lMax2X1 = 5;
+         lMin2X2 = maxX2-6;
+         lMax2X2 = maxX2-6;
+         lMin2X3 = 1;
+         lMax2X3 = 5;
+
+         lMin3X1 = 1;
+         lMax3X1 = 5;
+         lMin3X2 = maxX2-6;
+         lMax3X2 = maxX2-2;
+         lMin3X3 = 5;
+         lMax3X3 = 5;
+      }
+      else if (sendDir == BSE)
+      {
+         lMin1X1 = maxX1-6;
+         lMax1X1 = maxX1-6;
+         lMin1X2 = 1;
+         lMax1X2 = 5;
+         lMin1X3 = 1;
+         lMax1X3 = 5;
+
+         lMin2X1 = maxX1-6;
+         lMax2X1 = maxX1-2;
+         lMin2X2 = 5;
+         lMax2X2 = 5;
+         lMin2X3 = 1;
+         lMax2X3 = 5;
+
+         lMin3X1 = maxX1-5;
+         lMax3X1 = maxX1-2;
+         lMin3X2 = 1;
+         lMax3X2 = 5;
+         lMin3X3 = 5;
+         lMax3X3 = 5;
+      }
+      else if (sendDir == BSW)
+      {
+         lMin1X1 = 5;
+         lMax1X1 = 5;
+         lMin1X2 = 1;
+         lMax1X2 = 5;
+         lMin1X3 = 1;
+         lMax1X3 = 5;
+
+         lMin2X1 = 1;
+         lMax2X1 = 5;
+         lMin2X2 = 5;
+         lMax2X2 = 5;
+         lMin2X3 = 1;
+         lMax2X3 = 5;
+
+         lMin3X1 = 1;
+         lMax3X1 = 5;
+         lMin3X2 = 1;
+         lMax3X2 = 5;
+         lMin3X3 = 5;
+         lMax3X3 = 5;
+      }
+      findFCCells(lMin1X1, lMin1X2, lMin1X3, lMax1X1, lMax1X2, lMax1X3, iNodeSetSender);
+      findFCCells(lMin2X1, lMin2X2, lMin2X3, lMax2X1, lMax2X2, lMax2X3, iNodeSetSender);
+      findFCCells(lMin3X1, lMin3X2, lMin3X3, lMax3X1, lMax3X2, lMax3X3, iNodeSetSender);
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::fillSendVectors()
+{
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fFrom = block.lock()->getKernel()->getDataSet()->getFdistributions();
+
+   int index = 0;
+
+   vector_type& data = this->sender->getData();
+
+   BOOST_FOREACH(INodeVector inode, iNodeSetSender)
+   {
+      LBMReal icellC[27];
+      D3Q27ICell icellF;
+      iprocessor->readICell(fFrom, icellF, inode[0], inode[1], inode[2]);
+      iprocessor->interpolateFineToCoarse(icellF, icellC, inode[3], inode[4], inode[5]);
+      writeICellCtoData(data, index, icellC);
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::readICellFfromData(vector_type& data, int& index, D3Q27ICell& icellF)
+{
+   readNodeFromVector(data, index, icellF.BSW);
+   readNodeFromVector(data, index, icellF.BSE);
+   readNodeFromVector(data, index, icellF.BNW);
+   readNodeFromVector(data, index, icellF.BNE);
+   readNodeFromVector(data, index, icellF.TSW);
+   readNodeFromVector(data, index, icellF.TSE);
+   readNodeFromVector(data, index, icellF.TNW);
+   readNodeFromVector(data, index, icellF.TNE);
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::readNodeFromVector(vector_type& data, int& index, LBMReal* inode)
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      inode[i] = data[index++];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::writeICellCtoData(vector_type& data, int& index, LBMReal* icellC)
+{
+   for (int i = D3Q27System::STARTF; i < D3Q27System::ENDF+1; i++)
+   {
+      data[index++] = icellC[i];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::findCFCells(int lMinX1, int lMinX2, int lMinX3, int lMaxX1, int lMaxX2, int lMaxX3, INodeSet &inodes)
+{
+   int ix1, ix2, ix3;
+
+   for (ix3 = lMinX3; ix3<=lMaxX3; ix3 += 2)
+   {
+      for (ix2 = lMinX2; ix2<=lMaxX2; ix2 += 2)
+      {
+         for (ix1 = lMinX1; ix1<=lMaxX1; ix1 += 2)
+         {
+            INodeVector inv;
+            inv.push_back(ix1);
+            inv.push_back(ix2);
+            inv.push_back(ix3);
+            //inodes.insert(inv);
+            inodes.push_back(inv);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::findCFCells()
+{
+   using namespace D3Q27System;
+
+   int lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3;
+
+   //////////////////////////////////////////////////////
+   //Debug
+   //////////////////////////////////////////////////////
+   if (block.lock()->getGlobalID() == 2183)
+   {
+      int test = 0;
+   }
+
+   switch (sendDir)
+   {
+      //faces
+   case E: case W:
+      if (sendDir == E)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = lMinX1;
+      }
+      else if (sendDir == W)
+      {
+         lMinX1 = 2;
+         lMaxX1 = lMinX1;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMinX2 = minX2;
+         lMaxX2 = maxX2 + maxOffX2 - 1;
+         lMinX3 = minX3;
+         lMaxX3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMinX2 = minX2 + minOffX2;
+         lMaxX2 = maxX2 - 1;
+         lMinX3 = minX3;
+         lMaxX3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type01)
+      {
+         lMinX2 = minX2;
+         lMaxX2 = maxX2 + maxOffX2 - 1;
+         lMinX3 = minX3 + minOffX3;
+         lMaxX3 = maxX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type11)
+      {
+         lMinX2 = minX2 + minOffX2;
+         lMaxX2 = maxX2 - 1;
+         lMinX3 = minX3 + minOffX3;
+         lMaxX3 = maxX3 - 1;
+      }
+      findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetReceiver);
+      break;
+   case N: case S:
+      if (sendDir == N)
+      {
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = lMinX2;
+      }
+      else if (sendDir == S)
+      {
+         lMinX2 = 2;
+         lMaxX2 = lMinX2;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxX1 + maxOffX1 - 1;
+         lMinX3 = minX3;
+         lMaxX3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMinX1 = minX1 + minOffX1;
+         lMaxX1 = maxX1;
+         lMinX3 = minX3;
+         lMaxX3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type01)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxX1 + maxOffX1 - 1;
+         lMinX3 = minX3 + minOffX3;
+         lMaxX3 = maxX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type11)
+      {
+         lMinX1 = minX1 + minOffX1;
+         lMaxX1 = maxX1 - 1;
+         lMinX3 = minX3 + minOffX3;
+         lMaxX3 = maxX3 - 1;
+      }
+      findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetReceiver);
+      break;
+   case T: case B:
+      if (sendDir == T)
+      {
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = lMinX3;
+      }
+      else if (sendDir == B)
+      {
+         lMinX3 = 2;
+         lMaxX3 = lMinX3;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxX1 + maxOffX1 - 1;
+         lMinX2 = minX2;
+         lMaxX2 = maxX2 + maxOffX2 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMinX1 = minX1 + minOffX1;
+         lMaxX1 = maxX1 - 1;
+         lMinX2 = minX2;
+         lMaxX2 = maxX2 + maxOffX2 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type01)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxX1 + maxOffX1 - 1;
+         lMinX2 = minX2 + minOffX2;
+         lMaxX2 = maxX2 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type11)
+      {
+         lMinX1 = minX1 + minOffX1;
+         lMaxX1 = maxX1 - 1;
+         lMinX2 = minX2 + minOffX2;
+         lMaxX2 = maxX2 - 1;
+      }
+      findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetReceiver);
+      break;
+
+      //edges
+      //N-S-E-W
+   case NE: case SW: case SE: case NW:
+      if (sendDir == NE)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = lMinX1 + 2;
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = lMinX2 + 2;
+      }
+      else if (sendDir == SW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = lMinX1 + 3;
+         lMinX2 = 0;
+         lMaxX2 = lMinX2 + 3;
+      }
+      else if (sendDir == SE)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = lMinX1 + 2;
+         lMinX2 = 0;
+         lMaxX2 = lMinX2 + 2;
+      }
+      else if (sendDir == NW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = lMinX1 + 2;
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = lMinX2 + 2;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMinX3 = minX3;
+         lMaxX3 = maxX3 + maxOffX3 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMinX3 = minX3 + minOffX3;
+         lMaxX3 = maxX3 - 1;
+      }
+
+      findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetReceiver);
+      break;
+      //T-B-E-W
+   case TE: case BW: case BE: case TW:
+      if (sendDir == TE)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = lMinX1 + 2;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = lMinX3 + 2;
+      }
+      else if (sendDir == BW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = lMinX1 + 2;
+         lMinX3 = 0;
+         lMaxX3 = lMinX3 + 2;
+      }
+      else if (sendDir == BE)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = lMinX1 + 2;
+         lMinX3 = 0;
+         lMaxX3 = lMinX3 + 2;
+      }
+      else if (sendDir == TW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = lMinX1 + 2;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = lMinX3 + 2;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMinX2 = minX2;
+         lMaxX2 = maxX2 + maxOffX2 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMinX2 = minX2 + minOffX2;
+         lMaxX2 = maxX2 - 1;
+      }
+
+      findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetReceiver);
+      break;
+      //T-B-N-S
+   case TN: case BS: case BN: case TS:
+      if (sendDir == TN)
+      {
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = lMinX2 + 2;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = lMinX3 + 2;
+      }
+      else if (sendDir == BS)
+      {
+         lMinX2 = 0;
+         lMaxX2 = lMinX2 + 2;
+         lMinX3 = 0;
+         lMaxX3 = lMinX3 + 2;
+      }
+      else if (sendDir == BN)
+      {
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = lMinX2 + 2;
+         lMinX3 = 0;
+         lMaxX3 = lMinX3 + 2;
+      }
+      else if (sendDir == TS)
+      {
+         lMinX2 = 0;
+         lMaxX2 = lMinX2 + 2;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = lMinX3 + 2;
+      }
+
+      if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type00)
+      {
+         lMinX1 = minX1;
+         lMaxX1 = maxX1 + maxOffX1 - 1;
+      }
+      else if (FineToCoarseBlock3DConnector::connType ==FineToCoarseBlock3DConnector::Type10)
+      {
+         lMinX1 = minX1 + minOffX1;
+         lMaxX1 = maxX1 - 1;
+      }
+
+      findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetReceiver);
+      break;
+      //corners
+   case TNE: case TNW: case TSE: case TSW: case BNE: case BNW: case BSE: case BSW:
+      if (sendDir == TNE)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = maxX1 - 1;
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = maxX2 - 1;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = maxX3 - 1;
+      }
+      else if (sendDir == TNW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = 2;
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = maxX2 - 1;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = maxX3 - 1;
+      }
+      else if (sendDir == TSE)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = maxX1 - 1;
+         lMinX2 = 0;
+         lMaxX2 = 2;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = maxX3 - 1;
+      }
+      else if (sendDir == TSW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = 2;
+         lMinX2 = 0;
+         lMaxX2 = 2;
+         lMinX3 = maxX3 - 3;
+         lMaxX3 = maxX3 - 1;
+      }
+      else if (sendDir == BNE)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = maxX1 - 1;
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = maxX2 - 1;
+         lMinX3 = 0;
+         lMaxX3 = 2;
+      }
+      else if (sendDir == BNW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = 2;
+         lMinX2 = maxX2 - 3;
+         lMaxX2 = maxX2 - 1;
+         lMinX3 = 0;
+         lMaxX3 = 2;
+      }
+      else if (sendDir == BSE)
+      {
+         lMinX1 = maxX1 - 3;
+         lMaxX1 = maxX1 - 1;
+         lMinX2 = 0;
+         lMaxX2 = 2;
+         lMinX3 = 0;
+         lMaxX3 = 2;
+      }
+      else if (sendDir == BSW)
+      {
+         lMinX1 = 0;
+         lMaxX1 = 2;
+         lMinX2 = 0;
+         lMaxX2 = 2;
+         lMinX3 = 0;
+         lMaxX3 = 2;
+      }
+      findCFCells(lMinX1, lMinX2, lMinX3, lMaxX1, lMaxX2, lMaxX3, iNodeSetReceiver);
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void FineToCoarseNodeSetBlock3DConnector::distributeReceiveVectors()
+{
+   using namespace D3Q27System;
+
+   DistributionArray3DPtr  fTo = FineToCoarseBlock3DConnector::block.lock()->getKernel()->getDataSet()->getFdistributions();
+
+   int index = 0;
+
+   vector_type& data = this->receiver->getData();
+
+   BOOST_FOREACH(INodeVector inode, iNodeSetReceiver)
+   {
+      D3Q27ICell icellF;
+      this->readICellFfromData(data, index, icellF);
+      iprocessor->writeICell(fTo, icellF, inode[0], inode[1], inode[2]);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//
+//void FineToCoarseNodeSetBlock3DConnector::getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3)
+//{
+//   using namespace D3Q27System;
+//   int TminX1 = minX1; int TminX2 = minX2; int TminX3 = minX3; int TmaxX1 = maxX1; int TmaxX2 = maxX2; int TmaxX3 = maxX3;
+//
+//   if (block.lock()->hasInterpolationFlagFC(E))
+//   {
+//      if (maxX1==TmaxX1) maxX1 -= 2;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(W))
+//   {
+//      if (minX1==TminX1) minX1 += 4;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(N))
+//   {
+//      if (maxX2==TmaxX2) maxX2 -= 2;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(S))
+//   {
+//      if (minX2==TminX2) minX2 += 4;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(T))
+//   {
+//      if (maxX3==TmaxX3) maxX3 -= 2;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(B))
+//   {
+//      if (minX3==TminX3) minX3 += 4;
+//   }
+//
+//   ////////////
+//   /////E-W-N-S
+//   if (block.lock()->hasInterpolationFlagFC(NE)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(E))
+//   {
+//      if (maxX1==TmaxX1) maxX1 -= 2;
+//      if (maxX2==TmaxX2) maxX2 -= 2;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(SW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(S))
+//   {
+//      if (minX1==TminX1) minX1 += 4;
+//      if (minX2==TminX2) minX2 += 4;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(SE)&& !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(S))
+//   {
+//      if (maxX1==TmaxX1) maxX1 -= 2;
+//      if (minX2==TminX2) minX2 += 4;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(NW)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(W))
+//   {
+//      if (minX1==TminX1) minX1 += 4;
+//      if (maxX2==TmaxX2) maxX2 -= 2;
+//   }
+//
+//   //////T-B-E-W
+//   if (block.lock()->hasInterpolationFlagFC(TE) && !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(T))
+//   {
+//      if (maxX1==TmaxX1) maxX1 -= 2;
+//      if (maxX3==TmaxX3) maxX3 -= 2;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(BW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(B))
+//   {
+//      if (minX1==TminX1) minX1 += 4;
+//      if (minX3==TminX3) minX3 += 4;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(BE)&& !block.lock()->hasInterpolationFlagFC(E) && !block.lock()->hasInterpolationFlagFC(B))
+//   {
+//      if (maxX1==TmaxX1) maxX1 -= 2;
+//      if (minX3==TminX3) minX3 += 4;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(TW)&& !block.lock()->hasInterpolationFlagFC(W) && !block.lock()->hasInterpolationFlagFC(T))
+//   {
+//      if (minX1==TminX1) minX1 += 4;
+//      if (maxX3==TmaxX3) maxX3 -= 2;
+//   }
+//
+//
+//   ////T-B-N-S
+//   if (block.lock()->hasInterpolationFlagFC(TN)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(T))
+//   {
+//      if (maxX2==TmaxX2) maxX2 -= 2;
+//      if (maxX3==TmaxX3) maxX3 -= 2;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(BS)&& !block.lock()->hasInterpolationFlagFC(S) && !block.lock()->hasInterpolationFlagFC(B))
+//   {
+//      if (minX2==TminX2) minX2 += 4;
+//      if (minX3==TminX3) minX3 += 4;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(BN)&& !block.lock()->hasInterpolationFlagFC(N) && !block.lock()->hasInterpolationFlagFC(B))
+//   {
+//      if (maxX2==TmaxX2) maxX2 -= 2;
+//      if (minX3==TminX3) minX3 += 4;
+//   }
+//   if (block.lock()->hasInterpolationFlagFC(TS) && !block.lock()->hasInterpolationFlagFC(S) && !block.lock()->hasInterpolationFlagFC(T))
+//   {
+//      if (minX2==TminX2) minX2 += 4;
+//      if (maxX3==TmaxX3) maxX3 -= 2;
+//   }
+//}
+//////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/Connectors/FineToCoarseNodeSetBlock3DConnector.h b/source/VirtualFluidsCore/Connectors/FineToCoarseNodeSetBlock3DConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..647b387e049376dc2d4c328803bf357756c85192
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/FineToCoarseNodeSetBlock3DConnector.h
@@ -0,0 +1,80 @@
+/// \file CoarseToFineNodeSetBlock3DConnector.h
+/// \class CoarseToFineNodeSetBlock3DConnector
+/// \brief Connector interpolates and sends data from coarse level to fine.  
+/// \author Konstantin Kutscher
+/// \date 21.05.2015
+
+#ifndef FineToCoarseNodeSetBlock3DConnector_H
+#define FineToCoarseNodeSetBlock3DConnector_H
+
+#include <vector>
+#include "FineToCoarseBlock3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "Grid3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "MathUtil.hpp"
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include "D3Q27ETFCVectorConnector.h"
+
+class Block3D;
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+
+class FineToCoarseNodeSetBlock3DConnector : public FineToCoarseBlock3DConnector
+{
+public:
+   FineToCoarseNodeSetBlock3DConnector(Block3DPtr block, VectorTransmitterPtr sender, VectorTransmitterPtr receiver, int sendDir, D3Q27InterpolationProcessorPtr iprocessor, CFconnectorType connType);
+   void init();
+   void fillSendVectors();
+   void distributeReceiveVectors();
+protected:
+   typedef std::vector< int > INodeVector;
+   typedef std::vector < INodeVector > INodeSet;
+   INodeSet  iNodeSetSender;
+   INodeSet  iNodeSetReceiver;
+
+   void readICellFfromData(vector_type& data, int& index, D3Q27ICell& icellF);
+   void readNodeFromVector(vector_type& data, int& index, LBMReal* inode);
+
+   void writeICellCtoData(vector_type& data, int& index, LBMReal* icellC);
+
+   void findFCCells();
+   void findFCCells(int lMinX1, int lMinX2, int lMinX3, int lMaxX1, int lMaxX2, int lMaxX3, INodeSet &inodes);
+
+   void findCFCells();
+   void findCFCells(int lMinX1, int lMinX2, int lMinX3, int lMaxX1, int lMaxX2, int lMaxX3, INodeSet &inodes);
+
+   //void getLocalMinMax(int& minX1, int& minX2, int& minX3, int& maxX1, int& maxX2, int& maxX3);
+
+
+   int bMaxX1, bMaxX2, bMaxX3;
+   
+   int minX1;
+   int minX2;
+   int minX3;
+
+   int maxX1;
+   int maxX2;
+   int maxX3;
+
+   int minOffX1;
+   int minOffX2;
+   int minOffX3;
+
+   int maxOffX1;
+   int maxOffX2;
+   int maxOffX3;
+};
+
+
+
+
+
+#endif
diff --git a/source/VirtualFluidsCore/Connectors/LocalBlock3DConnector.h b/source/VirtualFluidsCore/Connectors/LocalBlock3DConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..10d7bb7a5bd9b4878382f4136d0f8183aeeb5075
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/LocalBlock3DConnector.h
@@ -0,0 +1,59 @@
+#ifndef LocalBlock3DConnector_H
+#define LocalBlock3DConnector_H
+
+#include <boost/weak_ptr.hpp>
+
+#include "Block3DConnector.h"
+#include "Block3D.h"
+
+class LocalBlock3DConnector : public Block3DConnector
+{
+public:
+   LocalBlock3DConnector(Block3DPtr from, Block3DPtr to, int sendDir)
+      : Block3DConnector(sendDir)
+      , from(from)
+      , to(to)
+   {
+
+   }
+   virtual ~LocalBlock3DConnector() {}
+   void sendTransmitterDataSize() {}
+   void receiveTransmitterDataSize() {}
+   virtual void init() = 0;
+   void prepareForReceive() {}
+   void prepareForSend() {}
+   void fillSendVectors() {}
+   virtual void sendVectors()=0;
+   void receiveVectors() {}
+
+   void distributeReceiveVectors() {}
+
+   bool isLocalConnector() { return true; }
+   bool isRemoteConnector() { return false; }
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return false; }
+
+   double getSendRecieveTime();
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1() {}
+   void sendVectorsX2() {}
+   void sendVectorsX3() {}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> from;
+   boost::weak_ptr<Block3D> to;
+};
+
+#endif //LocalBlock3DConnector_H
diff --git a/source/VirtualFluidsCore/Connectors/RemoteBlock3DConnector.cpp b/source/VirtualFluidsCore/Connectors/RemoteBlock3DConnector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fcf06f32261773442845babd69f280ff341b9145
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/RemoteBlock3DConnector.cpp
@@ -0,0 +1,64 @@
+#include "RemoteBlock3DConnector.h"
+
+//////////////////////////////////////////////////////////////////////////
+RemoteBlock3DConnector::RemoteBlock3DConnector(Block3DPtr block
+   , VectorTransmitterPtr sender
+   , VectorTransmitterPtr receiver
+   , int sendDir)
+   : Block3DConnector(sendDir)
+   , block(block)
+   , sender(sender)
+   , receiver(receiver)
+{
+   if (!block || !sender || !receiver)
+      UB_THROW(UbException(UB_EXARGS, "sender or receiver == NULL!!"));
+}
+//////////////////////////////////////////////////////////////////////////
+
+bool RemoteBlock3DConnector::isLocalConnector()
+{
+   return !this->isRemoteConnector();
+}
+//////////////////////////////////////////////////////////////////////////
+
+bool RemoteBlock3DConnector::isRemoteConnector()
+{
+   return ((sender && sender->isRemoteTransmitter())
+      || (receiver && receiver->isRemoteTransmitter()));
+}
+//////////////////////////////////////////////////////////////////////////
+
+void RemoteBlock3DConnector::sendTransmitterDataSize()
+{
+   assert(sender  !=NULL); sender->sendDataSize();
+}
+//////////////////////////////////////////////////////////////////////////
+
+void RemoteBlock3DConnector::receiveTransmitterDataSize()
+{
+   assert(receiver!=NULL); receiver->receiveDataSize();
+}
+//////////////////////////////////////////////////////////////////////////
+
+void RemoteBlock3DConnector::prepareForSend()
+{
+   assert(sender  !=NULL); sender->prepareForSend();
+}
+//////////////////////////////////////////////////////////////////////////
+
+void RemoteBlock3DConnector::sendVectors()
+{
+   assert(sender  !=NULL); sender->sendData();
+}
+//////////////////////////////////////////////////////////////////////////
+
+void RemoteBlock3DConnector::prepareForReceive()
+{
+   assert(receiver!=NULL); receiver->prepareForReceive();
+}
+//////////////////////////////////////////////////////////////////////////
+
+void RemoteBlock3DConnector::receiveVectors()
+{
+   assert(receiver!=NULL); receiver->receiveData();
+}
diff --git a/source/VirtualFluidsCore/Connectors/RemoteBlock3DConnector.h b/source/VirtualFluidsCore/Connectors/RemoteBlock3DConnector.h
new file mode 100644
index 0000000000000000000000000000000000000000..886c9d5208c2e09864f0fcfc982a88f33de5050b
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/RemoteBlock3DConnector.h
@@ -0,0 +1,72 @@
+#ifndef RemoteBlock3DConnector_H
+#define RemoteBlock3DConnector_H
+
+#include <vector>
+
+#include "TransmitterType.h"
+#include "Block3DConnector.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+#include "LBMKernelETD3Q27.h"
+#include "EsoTwistD3Q27System.h"
+
+
+//daten werden in einen vector (dieser befindet sich im transmitter) kopiert
+//der vector wird via transmitter uebertragen
+//transmitter kann ein lokal, MPI, RCG, CTL oder was auch immer fuer ein
+//transmitter sein, der von Transmitter abgeleitet ist ;-)
+class RemoteBlock3DConnector : public Block3DConnector
+{
+public:
+   RemoteBlock3DConnector(Block3DPtr block
+      , VectorTransmitterPtr sender
+      , VectorTransmitterPtr receiver
+      , int sendDir);
+
+   bool isLocalConnector();
+   bool isRemoteConnector();
+
+   virtual void init() = 0;
+
+   void sendTransmitterDataSize();
+   void receiveTransmitterDataSize();
+
+   void prepareForSend();
+   void sendVectors();
+
+   void prepareForReceive();
+   void receiveVectors();
+
+   virtual void fillSendVectors() = 0;
+   virtual void distributeReceiveVectors() = 0;
+
+   bool isInterpolationConnectorCF() { return false; }
+   bool isInterpolationConnectorFC() { return false; }
+
+   double getSendRecieveTime() { return 0; }
+
+   void prepareForSendX1() {}
+   void prepareForSendX2() {}
+   void prepareForSendX3() {}
+
+   void sendVectorsX1() {}
+   void sendVectorsX2() {}
+   void sendVectorsX3() {}
+
+   void prepareForReceiveX1() {}
+   void prepareForReceiveX2() {}
+   void prepareForReceiveX3() {}
+
+   void receiveVectorsX1() {}
+   void receiveVectorsX2() {}
+   void receiveVectorsX3() {}
+
+protected:
+   boost::weak_ptr<Block3D> block; 
+   VectorTransmitterPtr sender;
+   VectorTransmitterPtr receiver;
+};
+
+
+#endif //RemoteBlock3DConnector_H
+
diff --git a/source/VirtualFluidsCore/Connectors/TransmitterType.h b/source/VirtualFluidsCore/Connectors/TransmitterType.h
new file mode 100644
index 0000000000000000000000000000000000000000..aaeb295a3a300899086878d03155f237b61cb3e2
--- /dev/null
+++ b/source/VirtualFluidsCore/Connectors/TransmitterType.h
@@ -0,0 +1,16 @@
+#ifndef TransmitterType_h__
+#define TransmitterType_h__
+
+#include "basics/transmitter/TbTransmitter.h"
+#include "basics/transmitter/TbTransmitterLocal.h"
+#include "basics/container/CbVector.h"
+#include "D3Q27System.h"
+#include <boost/shared_ptr.hpp>
+
+
+typedef TbTransmitter< CbVector< LBMReal > > VectorTransmitter;
+typedef VectorTransmitter::value_type  vector_type;
+typedef boost::shared_ptr< TbTransmitter< CbVector< LBMReal > > > VectorTransmitterPtr;
+
+#endif // TransmitterType_h__
+
diff --git a/source/VirtualFluidsCore/Data/CMakePackage.txt b/source/VirtualFluidsCore/Data/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSoA.cpp b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSoA.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a1053e787bac627681efadf1157631275148e98b
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSoA.cpp
@@ -0,0 +1,594 @@
+#include "D3Q27EsoTwist3DSoA.h"
+#include <D3Q27System.h>
+#include "EsoTwistD3Q27System.h"
+
+D3Q27EsoTwist3DSoA::D3Q27EsoTwist3DSoA()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27EsoTwist3DSoA::D3Q27EsoTwist3DSoA( const size_t& nx1, const size_t& nx2, const size_t& nx3, LBMReal value )
+{
+   this->NX1 = nx1;
+   this->NX2 = nx2;
+   this->NX3 = nx3;
+
+   d.E   = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.W   = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.N   = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.S   = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.T   = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.B   = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.NE  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.SW  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.SE  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.NW  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.TE  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.BW  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.BE  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.TW  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.TN  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.BS  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.BN  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.TS  = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.TNE = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.TNW = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.TSE = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.TSW = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.BNE = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.BNW = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.BSE = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.BSW = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1+1, nx2+1, nx3+1, value));
+   d.ZERO= CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1, nx2, nx3, value));
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27EsoTwist3DSoA::~D3Q27EsoTwist3DSoA()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::swap()
+{
+   std::swap(d.E  , d.W  );
+   std::swap(d.N  , d.S  );
+   std::swap(d.T  , d.B  );
+   std::swap(d.NE , d.SW );
+   std::swap(d.NW , d.SE );
+   std::swap(d.TE , d.BW );
+   std::swap(d.TW , d.BE );
+   std::swap(d.TN , d.BS );
+   std::swap(d.TS , d.BN );
+   std::swap(d.TNE, d.BSW);
+   std::swap(d.TNW, d.BSE);
+   std::swap(d.TSE, d.BNW);
+   std::swap(d.TSW, d.BNE);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::getDistribution(LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   size_t x1p = x1 + 1;
+   size_t x2p = x2 + 1;
+   size_t x3p = x3 + 1;
+
+   f[D3Q27System::E]   = (*d.E)(x1,x2,x3);
+   f[D3Q27System::N]   = (*d.N)(x1,x2,x3);  
+   f[D3Q27System::T]   = (*d.T)(x1,x2,x3);
+   f[D3Q27System::NE]  = (*d.NE)(x1,x2,x3);
+   f[D3Q27System::NW]  = (*d.NW)(x1p,x2,x3);
+   f[D3Q27System::TE]  = (*d.TE)(x1,x2,x3);
+   f[D3Q27System::TW]  = (*d.TW)(x1p,x2,x3);
+   f[D3Q27System::TN]  = (*d.TN)(x1,x2,x3);
+   f[D3Q27System::TS]  = (*d.TS)(x1,x2p,x3);
+   f[D3Q27System::TNE] = (*d.TNE)(x1,x2,x3);
+   f[D3Q27System::TNW] = (*d.TNW)(x1p,x2,x3);
+   f[D3Q27System::TSE] = (*d.TSE)(x1,x2p,x3);
+   f[D3Q27System::TSW] = (*d.TSW)(x1p,x2p,x3);
+
+   f[D3Q27System::W ]  = (*d.W)(x1p,x2,x3);
+   f[D3Q27System::S ]  = (*d.S)(x1,x2p,x3);
+   f[D3Q27System::B ]  = (*d.B)(x1,x2,x3p);
+   f[D3Q27System::SW]  = (*d.SW)(x1p,x2p,x3);
+   f[D3Q27System::SE]  = (*d.SE)(x1,x2p,x3);
+   f[D3Q27System::BW]  = (*d.BW)(x1p,x2,x3p);
+   f[D3Q27System::BE]  = (*d.BE)(x1,x2,x3p);
+   f[D3Q27System::BS]  = (*d.BS)(x1,x2p,x3p);
+   f[D3Q27System::BN]  = (*d.BN)(x1,x2,x3p);
+   f[D3Q27System::BSW] = (*d.BSW)(x1p,x2p,x3p);
+   f[D3Q27System::BSE] = (*d.BSE)(x1,x2p,x3p);
+   f[D3Q27System::BNW] = (*d.BNW)(x1p,x2,x3p);
+   f[D3Q27System::BNE] = (*d.BNE)(x1,x2,x3p);
+
+   f[D3Q27System::ZERO] = (*d.ZERO)(x1,x2,x3);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   size_t x1p = x1 + 1;
+   size_t x2p = x2 + 1;
+   size_t x3p = x3 + 1;
+
+   (*d.E)(x1,x2,x3)     = f[D3Q27System::INV_E];
+   (*d.N)(x1,x2,x3)     = f[D3Q27System::INV_N];
+   (*d.T)(x1,x2,x3)     = f[D3Q27System::INV_T];
+   (*d.NE)(x1,x2,x3)    = f[D3Q27System::INV_NE];
+   (*d.NW)(x1p,x2,x3)   = f[D3Q27System::INV_NW];
+   (*d.TE)(x1,x2,x3)    = f[D3Q27System::INV_TE];
+   (*d.TW)(x1p,x2,x3)   = f[D3Q27System::INV_TW];
+   (*d.TN)(x1,x2,x3)    = f[D3Q27System::INV_TN];
+   (*d.TS)(x1,x2p,x3)   = f[D3Q27System::INV_TS];
+   (*d.TNE)(x1,x2,x3)   = f[D3Q27System::INV_TNE];
+   (*d.TNW)(x1p,x2,x3)  = f[D3Q27System::INV_TNW];
+   (*d.TSE)(x1,x2p,x3)  = f[D3Q27System::INV_TSE];
+   (*d.TSW)(x1p,x2p,x3) = f[D3Q27System::INV_TSW];
+
+   (*d.W)(x1p,x2,x3)     = f[D3Q27System::INV_W ];
+   (*d.S)(x1,x2p,x3)     = f[D3Q27System::INV_S ];
+   (*d.B)(x1,x2,x3p)     = f[D3Q27System::INV_B ];
+   (*d.SW)(x1p,x2p,x3)   = f[D3Q27System::INV_SW];
+   (*d.SE)(x1,x2p,x3)    = f[D3Q27System::INV_SE];
+   (*d.BW)(x1p,x2,x3p)   = f[D3Q27System::INV_BW];
+   (*d.BE)(x1,x2,x3p)    = f[D3Q27System::INV_BE];
+   (*d.BS)(x1,x2p,x3p)   = f[D3Q27System::INV_BS];
+   (*d.BN)(x1,x2,x3p)    = f[D3Q27System::INV_BN];
+   (*d.BSW)(x1p,x2p,x3p) = f[D3Q27System::INV_BSW];
+   (*d.BSE)(x1,x2p,x3p)  = f[D3Q27System::INV_BSE];
+   (*d.BNW)(x1p,x2,x3p)  = f[D3Q27System::INV_BNW];
+   (*d.BNE)(x1,x2,x3p)   = f[D3Q27System::INV_BNE];
+
+   (*d.ZERO)(x1,x2,x3) = f[D3Q27System::ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::getDistributionInv(LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   f[D3Q27System::INV_E] = (*d.E)(x1,x2,x3);
+   f[D3Q27System::INV_N] = (*d.N)(x1,x2,x3);  
+   f[D3Q27System::INV_T] = (*d.T)(x1,x2,x3);
+   f[D3Q27System::INV_NE] = (*d.NE)(x1,x2,x3);
+   f[D3Q27System::INV_NW] = (*d.NW)(x1+1,x2,x3);
+   f[D3Q27System::INV_TE] = (*d.TE)(x1,x2,x3);
+   f[D3Q27System::INV_TW] = (*d.TW)(x1+1,x2,x3);
+   f[D3Q27System::INV_TN] = (*d.TN)(x1,x2,x3);
+   f[D3Q27System::INV_TS] = (*d.TS)(x1,x2+1,x3);
+   f[D3Q27System::INV_TNE] = (*d.TNE)(x1,x2,x3);
+   f[D3Q27System::INV_TNW] = (*d.TNW)(x1+1,x2,x3);
+   f[D3Q27System::INV_TSE] = (*d.TSE)(x1,x2+1,x3);
+   f[D3Q27System::INV_TSW] = (*d.TSW)(x1+1,x2+1,x3);
+
+   f[D3Q27System::INV_W ] = (*d.W)(x1+1,x2,x3  );
+   f[D3Q27System::INV_S ] = (*d.S)(x1,x2+1,x3  );
+   f[D3Q27System::INV_B ] = (*d.B)(x1,x2,x3+1  );
+   f[D3Q27System::INV_SW] = (*d.SW)(x1+1,x2+1,x3 );
+   f[D3Q27System::INV_SE] = (*d.SE)(x1,x2+1,x3 );
+   f[D3Q27System::INV_BW] = (*d.BW)(x1+1,x2,x3+1 );
+   f[D3Q27System::INV_BE] = (*d.BE)(x1,x2,x3+1 );
+   f[D3Q27System::INV_BS] = (*d.BS)(x1,x2+1,x3+1 );
+   f[D3Q27System::INV_BN] = (*d.BN)(x1,x2,x3+1 );
+   f[D3Q27System::INV_BSW] = (*d.BSW)(x1+1,x2+1,x3+1);
+   f[D3Q27System::INV_BSE] = (*d.BSE)(x1,x2+1,x3+1);
+   f[D3Q27System::INV_BNW] = (*d.BNW)(x1+1,x2,x3+1);
+   f[D3Q27System::INV_BNE] = (*d.BNE)(x1,x2,x3+1);
+
+   f[D3Q27System::ZERO] = (*d.ZERO)(x1,x2,x3);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   //(*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::E];
+   //(*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::N];
+   //(*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::T];
+   //(*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::NE];
+   //(*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::NW];
+   //(*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::TE];
+   //(*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::TW];
+   //(*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::TN];
+   //(*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::TS];
+   //(*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::TNE];
+   //(*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::TNW];
+   //(*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::TSE];
+   //(*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::TSW];
+
+   //(*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::W ];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::S ];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::B ];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::SW];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::SE];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::BW];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::BE];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::BS];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::BN];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::BSW];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::BSE];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::BNW];
+   //(*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::BNE];
+
+   //(*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+   //bool directionFlag = false;
+   //if ((direction & EsoTwistD3Q27System::etE) == EsoTwistD3Q27System::etE)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::E]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etW) == EsoTwistD3Q27System::etW)
+   //   (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::W]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etS) == EsoTwistD3Q27System::etS)
+   //   (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::S]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etN) == EsoTwistD3Q27System::etN)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::N]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etB) == EsoTwistD3Q27System::etB)
+   //   (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::B]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etT) == EsoTwistD3Q27System::etT)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::T]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etSW) == EsoTwistD3Q27System::etSW)
+   //   (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::SW]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etNE) == EsoTwistD3Q27System::etNE)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::NE]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etNW) == EsoTwistD3Q27System::etNW)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::NW]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etSE) == EsoTwistD3Q27System::etSE)
+   //   (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::SE]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etBW) == EsoTwistD3Q27System::etBW)
+   //   (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::BW]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etTE) == EsoTwistD3Q27System::etTE)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::TE]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etTW) == EsoTwistD3Q27System::etTW)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::TW]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etBE) == EsoTwistD3Q27System::etBE)
+   //   (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::BE]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etBS) == EsoTwistD3Q27System::etBS)
+   //   (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::BS]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etTN) == EsoTwistD3Q27System::etTN)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::TN]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etTS) == EsoTwistD3Q27System::etTS)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::TS]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etBN) == EsoTwistD3Q27System::etBN)
+   //   (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::BN]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etBSW) == EsoTwistD3Q27System::etBSW)
+   //   (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::BSW]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etTNE) == EsoTwistD3Q27System::etTNE)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::TNE]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etBSE) == EsoTwistD3Q27System::etBSE)
+   //   (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::BSE]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etTNW) == EsoTwistD3Q27System::etTNW)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::TNW]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etBNW) == EsoTwistD3Q27System::etBNW)
+   //   (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::BNW]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etTSE) == EsoTwistD3Q27System::etTSE)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::TSE]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etBNE) == EsoTwistD3Q27System::etBNE)
+   //   (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::BNE]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW)
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::TSW]; directionFlag=true;
+   //if ((direction & EsoTwistD3Q27System::ZERO) == EsoTwistD3Q27System::ZERO)
+   //   (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO]; directionFlag=true;
+//#ifdef _DEBUG
+//   if(!directionFlag)UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );
+//#endif //DEBUG
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction)
+{
+   //switch (direction)
+   //{
+   //case D3Q27System::E :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f;
+   //   break;
+   //case D3Q27System::W :
+   //   (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::S :
+   //   (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::N :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f;
+   //   break;
+   //case D3Q27System::B :
+   //   (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::T :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f;
+   //   break;
+   //case D3Q27System::SW :
+   //   (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::NE :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f;
+   //   break;
+   //case D3Q27System::NW :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f;
+   //   break;
+   //case D3Q27System::SE :
+   //   (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f;
+   //   break;
+   //case D3Q27System::BW :
+   //   (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::TE :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f;
+   //   break;
+   //case D3Q27System::TW :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f;
+   //   break;
+   //case D3Q27System::BE :
+   //   (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f;
+   //   break;
+   //case D3Q27System::BS :
+   //   (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::TN :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f;
+   //   break;
+   //case D3Q27System::TS :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f;
+   //   break;
+   //case D3Q27System::BN :
+   //   (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f;
+   //   break;
+   //case D3Q27System::BSW :
+   //   (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::TNE :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f;
+   //   break;
+   //case D3Q27System::BSE :
+   //   (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f;
+   //   break;
+   //case D3Q27System::TNW :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f;
+   //   break;
+   //case D3Q27System::BNW :
+   //   (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f;
+   //   break;
+   //case D3Q27System::TSE :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f;
+   //   break;
+   //case D3Q27System::BNE :
+   //   (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f;
+   //   break;
+   //case D3Q27System::TSW :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f;
+   //   break;
+   //case D3Q27System::ZERO :
+   //   (*this->zeroDistributions)(x1,x2,x3) = f;
+   //   break;
+   //default:
+   //   UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );     
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+//   bool directionFlag = false;
+//   if ((direction & EsoTwistD3Q27System::etE) == EsoTwistD3Q27System::etE)
+//      (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::E]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etW) == EsoTwistD3Q27System::etW)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::W]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etS) == EsoTwistD3Q27System::etS)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::S]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etN) == EsoTwistD3Q27System::etN)
+//      (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::N]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etB) == EsoTwistD3Q27System::etB)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::B]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etT) == EsoTwistD3Q27System::etT)
+//      (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::T]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etSW) == EsoTwistD3Q27System::etSW)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::SW]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etNE) == EsoTwistD3Q27System::etNE)
+//      (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::NE]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etNW) == EsoTwistD3Q27System::etNW)
+//      (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::NW]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etSE) == EsoTwistD3Q27System::etSE)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::SE]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etBW) == EsoTwistD3Q27System::etBW)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::BW]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etTE) == EsoTwistD3Q27System::etTE)
+//      (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::TE]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etTW) == EsoTwistD3Q27System::etTW)
+//      (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::TW]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etBE) == EsoTwistD3Q27System::etBE)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::BE]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etBS) == EsoTwistD3Q27System::etBS)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::BS]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etTN) == EsoTwistD3Q27System::etTN)
+//      (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::TN]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etTS) == EsoTwistD3Q27System::etTS)
+//      (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::TS]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etBN) == EsoTwistD3Q27System::etBN)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::BN]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etBSW) == EsoTwistD3Q27System::etBSW)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::BSW]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etTNE) == EsoTwistD3Q27System::etTNE)
+//      (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::TNE]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etBSE) == EsoTwistD3Q27System::etBSE)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::BSE]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etTNW) == EsoTwistD3Q27System::etTNW)
+//      (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::TNW]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etBNW) == EsoTwistD3Q27System::etBNW)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::BNW]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etTSE) == EsoTwistD3Q27System::etTSE)
+//      (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::TSE]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etBNE) == EsoTwistD3Q27System::etBNE)
+//      (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1)= f[D3Q27System::BNE]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW)
+//      (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::TSW]; directionFlag=true;
+//   if ((direction & EsoTwistD3Q27System::ZERO) == EsoTwistD3Q27System::ZERO)
+//      (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO]; directionFlag=true;
+//#ifdef _DEBUG
+//   if(!directionFlag)UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );
+//#endif //DEBUG
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSoA::setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+   //switch (direction)
+   //{
+   //case D3Q27System::E :
+   //   (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::W :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f;
+   //   break;
+   //case D3Q27System::S :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f;
+   //   break;
+   //case D3Q27System::N :
+   //   (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::B :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f;
+   //   break;
+   //case D3Q27System::T :
+   //   (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::SW :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f;
+   //   break;
+   //case D3Q27System::NE :
+   //   (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::NW :
+   //   (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f;
+   //   break;
+   //case D3Q27System::SE :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f;
+   //   break;
+   //case D3Q27System::BW :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f;
+   //   break;
+   //case D3Q27System::TE :
+   //   (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::TW :
+   //   (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f;
+   //   break;
+   //case D3Q27System::BE :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f;
+   //   break;
+   //case D3Q27System::BS :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f;
+   //   break;
+   //case D3Q27System::TN :
+   //   (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::TS :
+   //   (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f;
+   //   break;
+   //case D3Q27System::BN :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f;
+   //   break;
+   //case D3Q27System::BSW :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f;
+   //   break;
+   //case D3Q27System::TNE :
+   //   (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f;
+   //   break;
+   //case D3Q27System::BSE :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f;
+   //   break;
+   //case D3Q27System::TNW :
+   //   (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f;
+   //   break;
+   //case D3Q27System::BNW :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f;
+   //   break;
+   //case D3Q27System::TSE :
+   //   (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f;
+   //   break;
+   //case D3Q27System::BNE :
+   //   (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f;
+   //   break;
+   //case D3Q27System::TSW :
+   //   (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f;
+   //   break;
+   //case D3Q27System::ZERO :
+   //   (*this->zeroDistributions)(x1,x2,x3) = f;
+   //   break;
+   //default:
+   //   UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );     
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+LBMReal D3Q27EsoTwist3DSoA::getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction)
+{
+   //switch (direction)
+   //{
+   //case D3Q27System::E :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    );
+   //case D3Q27System::W :
+   //   return (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3);
+   //case D3Q27System::S :
+   //   return (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3);
+   //case D3Q27System::N :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    );
+   //case D3Q27System::B :
+   //   return (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3);
+   //case D3Q27System::T :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  );
+   //case D3Q27System::SW :
+   //   return (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3);
+   //case D3Q27System::NE :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   );
+   //case D3Q27System::NW :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   );
+   //case D3Q27System::SE :
+   //   return (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3);
+   //case D3Q27System::BW :
+   //   return (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3);
+   //case D3Q27System::TE :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 );
+   //case D3Q27System::TW :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 );
+   //case D3Q27System::BE :
+   //   return (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3);
+   //case D3Q27System::BS :
+   //   return (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3);
+   //case D3Q27System::TN :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 );
+   //case D3Q27System::TS :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 );
+   //case D3Q27System::BN :
+   //   return (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3);
+   //case D3Q27System::BSW :
+   //   return (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3);
+   //case D3Q27System::TNE :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+   //case D3Q27System::BSE :
+   //   return (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3);
+   //case D3Q27System::TNW :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1);
+   //case D3Q27System::BNW :
+   //   return (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3);
+   //case D3Q27System::TSE :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1);
+   //case D3Q27System::BNE :
+   //   return (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+   //case D3Q27System::TSW :
+   //   return (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1);
+   //case D3Q27System::ZERO :
+   //   return (*this->zeroDistributions)(x1,x2,x3);
+   //default:
+   //   UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );     
+   //}
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+size_t D3Q27EsoTwist3DSoA::getNX1() const
+{
+   return NX1;
+}
+//////////////////////////////////////////////////////////////////////////
+size_t D3Q27EsoTwist3DSoA::getNX2() const
+{
+   return NX2;
+}
+//////////////////////////////////////////////////////////////////////////
+size_t D3Q27EsoTwist3DSoA::getNX3() const
+{
+   return NX3;
+}
+//////////////////////////////////////////////////////////////////////////
+Distributions D3Q27EsoTwist3DSoA::getDistributions()
+{
+   return d;
+}
+//////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSoA.h b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSoA.h
new file mode 100644
index 0000000000000000000000000000000000000000..94e362c2b3d3af0bcc1b6035493d9c0c93b1fa29
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSoA.h
@@ -0,0 +1,91 @@
+#ifndef D3Q27EsoTwist3DSoA_h
+#define D3Q27EsoTwist3DSoA_h
+
+#include "EsoTwist3D.h"
+//#include "D3Q27System.h"
+//#include "basics/container/CbArray4D.h"
+#include <basics/container/CbArray3D.h>
+//#include <boost/serialization/serialization.hpp>
+//#include <boost/serialization/base_object.hpp>
+
+
+struct Distributions
+{
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr E;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr W;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr N;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr S;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr T;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr B;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr NE;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr SW;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr SE;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr NW;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr TE;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr BW;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr BE;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr TW;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr TN;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr BS;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr BN;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr TS;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr TNE;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr TNW;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr TSE;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr TSW;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr BNE;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr BNW;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr BSE;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr BSW;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr ZERO;
+};
+
+
+class D3Q27EsoTwist3DSoA : public EsoTwist3D
+{
+public:
+   D3Q27EsoTwist3DSoA();
+   D3Q27EsoTwist3DSoA(const size_t& nx1, const size_t& nx2, const size_t& nx3, LBMReal value);
+   //////////////////////////////////////////////////////////////////////////
+   ~D3Q27EsoTwist3DSoA();
+   //////////////////////////////////////////////////////////////////////////
+   void swap();
+   //////////////////////////////////////////////////////////////////////////
+   virtual void getDistribution( LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   ////////////////////////////////////////////////////////////////////////
+   virtual void getDistributionInv( LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual LBMReal getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual LBMReal getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX1() const;
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX2() const;
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX3() const;
+   //////////////////////////////////////////////////////////////////////////
+   Distributions getDistributions();
+   //////////////////////////////////////////////////////////////////////////
+   void getDistributionAfterLastStep(LBMReal* const f, size_t x1, size_t x2, size_t x3);
+
+protected:
+   Distributions d;
+   size_t NX1, NX2, NX3;
+
+};
+
+#endif
+
diff --git a/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..68173279730e22414810bfa7354980077ad8ca41
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp
@@ -0,0 +1,628 @@
+#include "D3Q27EsoTwist3DSplittedVector.h"
+#include "EsoTwistD3Q27System.h"
+
+D3Q27EsoTwist3DSplittedVector::D3Q27EsoTwist3DSplittedVector()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27EsoTwist3DSplittedVector::D3Q27EsoTwist3DSplittedVector( size_t nx1, size_t nx2, size_t nx3, LBMReal value )
+{
+   this->NX1 = nx1;
+   this->NX2 = nx2;
+   this->NX3 = nx3;
+
+   this->localDistributions    = CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr(new CbArray4D<LBMReal,IndexerX4X3X2X1>(13, nx1+1, nx2+1, nx3+1, value));
+   this->nonLocalDistributions = CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr(new CbArray4D<LBMReal,IndexerX4X3X2X1>(13, nx1+1, nx2+1, nx3+1, value));
+
+   this->zeroDistributions     = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1, nx2, nx3, value));
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27EsoTwist3DSplittedVector::~D3Q27EsoTwist3DSplittedVector()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::swap()
+{
+   std::swap( this->localDistributions, this->nonLocalDistributions );
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::getDistribution(LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   f[D3Q27System::E] = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+   f[D3Q27System::N] = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3);  
+   f[D3Q27System::T] = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+   f[D3Q27System::NE] = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+   f[D3Q27System::NW] = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3);
+   f[D3Q27System::TE] = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+   f[D3Q27System::TW] = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3);
+   f[D3Q27System::TN] = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+   f[D3Q27System::TS] = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3);
+   f[D3Q27System::TNE] = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+   f[D3Q27System::TNW] = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3);
+   f[D3Q27System::TSE] = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3);
+   f[D3Q27System::TSW] = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+
+   f[D3Q27System::W ] = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3  );
+   f[D3Q27System::S ] = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3  );
+   f[D3Q27System::B ] = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1  );
+   f[D3Q27System::SW] = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+   f[D3Q27System::SE] = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 );
+   f[D3Q27System::BW] = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+   f[D3Q27System::BE] = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 );
+   f[D3Q27System::BS] = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+   f[D3Q27System::BN] = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 );
+   f[D3Q27System::BSW] = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+   f[D3Q27System::BSE] = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+   f[D3Q27System::BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+   f[D3Q27System::BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1);
+
+   f[D3Q27System::ZERO] = (*this->zeroDistributions)(x1,x2,x3);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::INV_E];
+   (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::INV_N];
+   (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::INV_T];
+   (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::INV_NE];
+   (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::INV_NW];
+   (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::INV_TE];
+   (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::INV_TW];
+   (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::INV_TN];
+   (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::INV_TS];
+   (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::INV_TNE];
+   (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::INV_TNW];
+   (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::INV_TSE];
+   (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::INV_TSW];
+
+   (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::INV_W ];
+   (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::INV_S ];
+   (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::INV_B ];
+   (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::INV_SW];
+   (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::INV_SE];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::INV_BW];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BE];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::INV_BS];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BN];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::INV_BSW];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::INV_BSE];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::INV_BNW];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::INV_BNE];
+
+   (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::getDistributionInv(LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   f[D3Q27System::INV_E] = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+   f[D3Q27System::INV_N] = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3);  
+   f[D3Q27System::INV_T] = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+   f[D3Q27System::INV_NE] = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+   f[D3Q27System::INV_NW] = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3);
+   f[D3Q27System::INV_TE] = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+   f[D3Q27System::INV_TW] = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3);
+   f[D3Q27System::INV_TN] = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+   f[D3Q27System::INV_TS] = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3);
+   f[D3Q27System::INV_TNE] = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+   f[D3Q27System::INV_TNW] = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3);
+   f[D3Q27System::INV_TSE] = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3);
+   f[D3Q27System::INV_TSW] = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+
+   f[D3Q27System::INV_W ] = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3  );
+   f[D3Q27System::INV_S ] = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3  );
+   f[D3Q27System::INV_B ] = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1  );
+   f[D3Q27System::INV_SW] = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+   f[D3Q27System::INV_SE] = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 );
+   f[D3Q27System::INV_BW] = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+   f[D3Q27System::INV_BE] = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 );
+   f[D3Q27System::INV_BS] = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+   f[D3Q27System::INV_BN] = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 );
+   f[D3Q27System::INV_BSW] = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+   f[D3Q27System::INV_BSE] = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+   f[D3Q27System::INV_BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+   f[D3Q27System::INV_BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1);
+
+   f[D3Q27System::ZERO] = (*this->zeroDistributions)(x1,x2,x3);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::E];
+   (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::N];
+   (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::T];
+   (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::NE];
+   (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::NW];
+   (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::TE];
+   (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::TW];
+   (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::TN];
+   (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::TS];
+   (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::TNE];
+   (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::TNW];
+   (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::TSE];
+   (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::TSW];
+
+   (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::W ];
+   (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::S ];
+   (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::B ];
+   (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::SW];
+   (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::SE];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::BW];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::BE];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::BS];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::BN];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::BSW];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::BSE];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::BNW];
+   (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::BNE];
+
+   (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+   bool directionFlag = false;
+   if ((direction & EsoTwistD3Q27System::etE) == EsoTwistD3Q27System::etE)
+      (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::E]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etW) == EsoTwistD3Q27System::etW)
+      (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::W]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etS) == EsoTwistD3Q27System::etS)
+      (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::S]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etN) == EsoTwistD3Q27System::etN)
+      (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::N]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etB) == EsoTwistD3Q27System::etB)
+      (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::B]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etT) == EsoTwistD3Q27System::etT)
+      (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::T]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etSW) == EsoTwistD3Q27System::etSW)
+      (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::SW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etNE) == EsoTwistD3Q27System::etNE)
+      (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::NE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etNW) == EsoTwistD3Q27System::etNW)
+      (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::NW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etSE) == EsoTwistD3Q27System::etSE)
+      (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::SE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBW) == EsoTwistD3Q27System::etBW)
+      (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::BW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTE) == EsoTwistD3Q27System::etTE)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::TE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTW) == EsoTwistD3Q27System::etTW)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::TW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBE) == EsoTwistD3Q27System::etBE)
+      (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::BE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBS) == EsoTwistD3Q27System::etBS)
+      (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::BS]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTN) == EsoTwistD3Q27System::etTN)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::TN]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTS) == EsoTwistD3Q27System::etTS)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::TS]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBN) == EsoTwistD3Q27System::etBN)
+      (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::BN]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBSW) == EsoTwistD3Q27System::etBSW)
+      (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::BSW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTNE) == EsoTwistD3Q27System::etTNE)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::TNE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBSE) == EsoTwistD3Q27System::etBSE)
+      (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::BSE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTNW) == EsoTwistD3Q27System::etTNW)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::TNW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBNW) == EsoTwistD3Q27System::etBNW)
+      (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::BNW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTSE) == EsoTwistD3Q27System::etTSE)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::TSE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBNE) == EsoTwistD3Q27System::etBNE)
+      (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::BNE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::TSW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::ZERO) == EsoTwistD3Q27System::ZERO)
+      (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO]; directionFlag=true;
+#ifdef _DEBUG
+   if(!directionFlag)UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );
+#endif //DEBUG
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction)
+{
+   switch (direction)
+   {
+   case D3Q27System::E :
+      (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f;
+      break;
+   case D3Q27System::W :
+      (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::S :
+      (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::N :
+      (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f;
+      break;
+   case D3Q27System::B :
+      (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::T :
+      (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f;
+      break;
+   case D3Q27System::SW :
+      (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::NE :
+      (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f;
+      break;
+   case D3Q27System::NW :
+      (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f;
+      break;
+   case D3Q27System::SE :
+      (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f;
+      break;
+   case D3Q27System::BW :
+      (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::TE :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f;
+      break;
+   case D3Q27System::TW :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f;
+      break;
+   case D3Q27System::BE :
+      (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f;
+      break;
+   case D3Q27System::BS :
+      (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::TN :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f;
+      break;
+   case D3Q27System::TS :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f;
+      break;
+   case D3Q27System::BN :
+      (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f;
+      break;
+   case D3Q27System::BSW :
+      (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::TNE :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f;
+      break;
+   case D3Q27System::BSE :
+      (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f;
+      break;
+   case D3Q27System::TNW :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f;
+      break;
+   case D3Q27System::BNW :
+      (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f;
+      break;
+   case D3Q27System::TSE :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f;
+      break;
+   case D3Q27System::BNE :
+      (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f;
+      break;
+   case D3Q27System::TSW :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f;
+      break;
+   case D3Q27System::ZERO :
+      (*this->zeroDistributions)(x1,x2,x3) = f;
+      break;
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );     
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+   bool directionFlag = false;
+   if ((direction & EsoTwistD3Q27System::etE) == EsoTwistD3Q27System::etE)
+       (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::E]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etW) == EsoTwistD3Q27System::etW)
+      (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::W]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etS) == EsoTwistD3Q27System::etS)
+       (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::S]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etN) == EsoTwistD3Q27System::etN)
+      (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::N]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etB) == EsoTwistD3Q27System::etB)
+       (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::B]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etT) == EsoTwistD3Q27System::etT)
+      (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::T]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etSW) == EsoTwistD3Q27System::etSW)
+       (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::SW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etNE) == EsoTwistD3Q27System::etNE)
+      (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::NE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etNW) == EsoTwistD3Q27System::etNW)
+       (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::NW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etSE) == EsoTwistD3Q27System::etSE)
+      (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::SE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBW) == EsoTwistD3Q27System::etBW)
+       (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::BW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTE) == EsoTwistD3Q27System::etTE)
+      (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::TE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTW) == EsoTwistD3Q27System::etTW)
+       (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::TW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBE) == EsoTwistD3Q27System::etBE)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::BE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBS) == EsoTwistD3Q27System::etBS)
+       (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::BS]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTN) == EsoTwistD3Q27System::etTN)
+      (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::TN]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTS) == EsoTwistD3Q27System::etTS)
+       (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::TS]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBN) == EsoTwistD3Q27System::etBN)
+      (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::BN]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBSW) == EsoTwistD3Q27System::etBSW)
+       (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::BSW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTNE) == EsoTwistD3Q27System::etTNE)
+      (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::TNE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBSE) == EsoTwistD3Q27System::etBSE)
+       (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::BSE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTNW) == EsoTwistD3Q27System::etTNW)
+      (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::TNW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBNW) == EsoTwistD3Q27System::etBNW)
+       (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::BNW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTSE) == EsoTwistD3Q27System::etTSE)
+      (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::TSE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBNE) == EsoTwistD3Q27System::etBNE)
+       (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1)= f[D3Q27System::BNE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW)
+      (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::TSW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::ZERO) == EsoTwistD3Q27System::ZERO)
+      (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO]; directionFlag=true;
+#ifdef _DEBUG
+   if(!directionFlag)UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );
+#endif //DEBUG
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+   switch (direction)
+   {
+   case D3Q27System::E :
+      (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::W :
+      (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f;
+      break;
+   case D3Q27System::S :
+      (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f;
+      break;
+   case D3Q27System::N :
+      (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::B :
+      (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f;
+      break;
+   case D3Q27System::T :
+      (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::SW :
+      (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f;
+      break;
+   case D3Q27System::NE :
+      (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::NW :
+      (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f;
+      break;
+   case D3Q27System::SE :
+      (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f;
+      break;
+   case D3Q27System::BW :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f;
+      break;
+   case D3Q27System::TE :
+      (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::TW :
+      (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f;
+      break;
+   case D3Q27System::BE :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f;
+      break;
+   case D3Q27System::BS :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f;
+      break;
+   case D3Q27System::TN :
+      (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::TS :
+      (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f;
+      break;
+   case D3Q27System::BN :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f;
+      break;
+   case D3Q27System::BSW :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f;
+      break;
+   case D3Q27System::TNE :
+      (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f;
+      break;
+   case D3Q27System::BSE :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f;
+      break;
+   case D3Q27System::TNW :
+      (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f;
+      break;
+   case D3Q27System::BNW :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f;
+      break;
+   case D3Q27System::TSE :
+      (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f;
+      break;
+   case D3Q27System::BNE :
+      (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f;
+      break;
+   case D3Q27System::TSW :
+      (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f;
+      break;
+   case D3Q27System::ZERO :
+      (*this->zeroDistributions)(x1,x2,x3) = f;
+      break;
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );     
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+LBMReal D3Q27EsoTwist3DSplittedVector::getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction)
+{
+   switch (direction)
+   {
+   case D3Q27System::W :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    );
+   case D3Q27System::E :
+      return (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3);
+   case D3Q27System::N :
+      return (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3);
+   case D3Q27System::S :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    );
+   case D3Q27System::T :
+      return (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3);
+   case D3Q27System::B :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  );
+   case D3Q27System::NE :
+      return (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3);
+   case D3Q27System::SW :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   );
+   case D3Q27System::SE :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   );
+   case D3Q27System::NW :
+      return (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3);
+   case D3Q27System::TE :
+      return (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3);
+   case D3Q27System::BW :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 );
+   case D3Q27System::BE :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 );
+   case D3Q27System::TW :
+      return (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3);
+   case D3Q27System::TN :
+      return (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3);
+   case D3Q27System::BS :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 );
+   case D3Q27System::BN :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 );
+   case D3Q27System::TS :
+      return (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3);
+   case D3Q27System::TNE :
+      return (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3);
+   case D3Q27System::BSW :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+   case D3Q27System::TNW :
+      return (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3);
+   case D3Q27System::BSE :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1);
+   case D3Q27System::TSE :
+      return (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3);
+   case D3Q27System::BNW :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1);
+   case D3Q27System::TSW :
+      return (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+   case D3Q27System::BNE :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1);
+   case D3Q27System::ZERO :
+      return (*this->zeroDistributions)(x1,x2,x3);
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );     
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+LBMReal D3Q27EsoTwist3DSplittedVector::getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction)
+{
+   switch (direction)
+   {
+   case D3Q27System::E :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    );
+   case D3Q27System::W :
+      return (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3);
+   case D3Q27System::S :
+      return (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3);
+   case D3Q27System::N :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    );
+   case D3Q27System::B :
+      return (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3);
+   case D3Q27System::T :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  );
+   case D3Q27System::SW :
+      return (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3);
+   case D3Q27System::NE :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   );
+   case D3Q27System::NW :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   );
+   case D3Q27System::SE :
+      return (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3);
+   case D3Q27System::BW :
+      return (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3);
+   case D3Q27System::TE :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 );
+   case D3Q27System::TW :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 );
+   case D3Q27System::BE :
+      return (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3);
+   case D3Q27System::BS :
+      return (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3);
+   case D3Q27System::TN :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 );
+   case D3Q27System::TS :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 );
+   case D3Q27System::BN :
+      return (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3);
+   case D3Q27System::BSW :
+      return (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3);
+   case D3Q27System::TNE :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+   case D3Q27System::BSE :
+      return (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3);
+   case D3Q27System::TNW :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1);
+   case D3Q27System::BNW :
+      return (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3);
+   case D3Q27System::TSE :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1);
+   case D3Q27System::BNE :
+      return (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+   case D3Q27System::TSW :
+      return (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1);
+   case D3Q27System::ZERO :
+      return (*this->zeroDistributions)(x1,x2,x3);
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );     
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+size_t D3Q27EsoTwist3DSplittedVector::getNX1() const
+{
+   return NX1;
+}
+//////////////////////////////////////////////////////////////////////////
+size_t D3Q27EsoTwist3DSplittedVector::getNX2() const
+{
+   return NX2;
+}
+//////////////////////////////////////////////////////////////////////////
+size_t D3Q27EsoTwist3DSplittedVector::getNX3() const
+{
+   return NX3;
+}
+//////////////////////////////////////////////////////////////////////////
+CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr D3Q27EsoTwist3DSplittedVector::getLocalDistributions()
+{
+   return this->localDistributions;
+}
+//////////////////////////////////////////////////////////////////////////
+CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr D3Q27EsoTwist3DSplittedVector::getNonLocalDistributions()
+{
+   return this->nonLocalDistributions;
+}
+//////////////////////////////////////////////////////////////////////////
+CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr D3Q27EsoTwist3DSplittedVector::getZeroDistributions()
+{
+   return this->zeroDistributions;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27EsoTwist3DSplittedVector::getDistributionAfterLastStep( LBMReal* const f, size_t x1, size_t x2, size_t x3 )
+{
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.h b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.h
new file mode 100644
index 0000000000000000000000000000000000000000..126c0f54a33237dc48c16e785eb1a070b84e0667
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.h
@@ -0,0 +1,75 @@
+#ifndef D3Q27EsoTwist3DSplittedVector_h
+#define D3Q27EsoTwist3DSplittedVector_h
+
+#include "EsoTwist3D.h"
+#include "D3Q27System.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/base_object.hpp>
+
+class D3Q27EsoTwist3DSplittedVector : public EsoTwist3D
+{
+public:
+   D3Q27EsoTwist3DSplittedVector();
+   D3Q27EsoTwist3DSplittedVector(size_t nx1, size_t nx2, size_t nx3, LBMReal value);
+   //////////////////////////////////////////////////////////////////////////
+   ~D3Q27EsoTwist3DSplittedVector();
+   //////////////////////////////////////////////////////////////////////////
+   void swap();
+   //////////////////////////////////////////////////////////////////////////
+   virtual void getDistribution( LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   ////////////////////////////////////////////////////////////////////////
+   virtual void getDistributionInv( LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual LBMReal getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual LBMReal getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX1() const;
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX2() const;
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX3() const;
+   //////////////////////////////////////////////////////////////////////////
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr getLocalDistributions();
+   //////////////////////////////////////////////////////////////////////////
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr getNonLocalDistributions();
+   //////////////////////////////////////////////////////////////////////////
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr getZeroDistributions();
+   //////////////////////////////////////////////////////////////////////////
+   void getDistributionAfterLastStep(LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   
+protected:
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributions;
+   size_t NX1, NX2, NX3;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object< EsoTwist3D >(*this);
+      ar & NX1; 
+      ar & NX2; 
+      ar & NX3;
+      ar &  localDistributions;
+      ar &  nonLocalDistributions;
+      ar &  zeroDistributions;
+   }
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVectorEx.cpp b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVectorEx.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e4dab25180b0b817f12bdf33fae5ccc91f58f494
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVectorEx.cpp
@@ -0,0 +1,13 @@
+#include "D3Q27EsoTwist3DSplittedVectorEx.h"
+
+D3Q27EsoTwist3DSplittedVectorEx::D3Q27EsoTwist3DSplittedVectorEx( int nx1, int nx2, int nx3, LBMReal value )
+{
+   this->NX1 = nx1;
+   this->NX2 = nx2;
+   this->NX3 = nx3;
+
+   this->localDistributions    = CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr(new CbArray4D<LBMReal,IndexerX4X3X2X1>(13, nx1, nx2, nx3, value));
+   this->nonLocalDistributions = CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr(new CbArray4D<LBMReal,IndexerX4X3X2X1>(13, nx1, nx2, nx3, value));
+
+   this->zeroDistributions     = CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr(new CbArray3D<LBMReal,IndexerX3X2X1>(nx1, nx2, nx3, value));
+}
diff --git a/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVectorEx.h b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVectorEx.h
new file mode 100644
index 0000000000000000000000000000000000000000..72344f4a8ad6e3f98512d7d3eae8482aa2659d6f
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVectorEx.h
@@ -0,0 +1,15 @@
+#ifndef D3Q27EsoTwist3DSplittedVectorEx_h
+#define D3Q27EsoTwist3DSplittedVectorEx_h
+
+#include "D3Q27EsoTwist3DSplittedVector.h"
+
+class D3Q27EsoTwist3DSplittedVectorEx : public D3Q27EsoTwist3DSplittedVector
+{
+public:
+   D3Q27EsoTwist3DSplittedVectorEx(int nx1, int nx2, int nx3, LBMReal value);
+protected:
+private:
+};
+
+#endif
+
diff --git a/source/VirtualFluidsCore/Data/DataSet3D.h b/source/VirtualFluidsCore/Data/DataSet3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba28e3232393644e5fa106c06651ab0c240ad201
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/DataSet3D.h
@@ -0,0 +1,134 @@
+#ifndef DataSet3D_h
+#define DataSet3D_h
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+#include "DistributionArray3D.h"
+
+class DataSet3D;
+typedef boost::shared_ptr<DataSet3D> DataSet3DPtr;
+
+typedef CbArray4D<LBMReal,IndexerX4X3X2X1> AverageValuesArray3D;
+typedef boost::shared_ptr< AverageValuesArray3D > AverageValuesArray3DPtr;
+
+typedef CbArray4D<LBMReal, IndexerX4X3X2X1> AverageVelocityArray3D;
+typedef boost::shared_ptr< AverageValuesArray3D > AverageVelocityArray3DPtr;
+
+typedef CbArray4D<LBMReal, IndexerX4X3X2X1> AverageFluctuationsArray3D;
+typedef boost::shared_ptr< AverageFluctuationsArray3D > AverageFluctuationsArray3DPtr;
+
+typedef CbArray4D<LBMReal, IndexerX4X3X2X1> AverageTriplecorrelationsArray3D;
+typedef boost::shared_ptr< AverageValuesArray3D > AverageTriplecorrelationsArray3DPtr;
+
+typedef CbArray4D<LBMReal,IndexerX4X3X2X1> ShearStressValuesArray3D;
+typedef boost::shared_ptr< ShearStressValuesArray3D > ShearStressValuesArray3DPtr;
+
+typedef CbArray3D<LBMReal, IndexerX3X2X1> ViscosityArray3D;
+typedef boost::shared_ptr< ViscosityArray3D > ViscosityArray3DPtr;
+
+class DataSet3D
+{
+public:
+   DistributionArray3DPtr getFdistributions() const;
+   void setFdistributions(DistributionArray3DPtr distributions);
+
+   AverageVelocityArray3DPtr getAverageVelocity() const;
+   void setAverageVelocity(AverageVelocityArray3DPtr values);
+
+   AverageFluctuationsArray3DPtr getAverageFluctuations() const;
+   void setAverageFluctuations(AverageFluctuationsArray3DPtr values);
+
+   AverageTriplecorrelationsArray3DPtr getAverageTriplecorrelations() const;
+   void setAverageTriplecorrelations(AverageTriplecorrelationsArray3DPtr values);
+
+
+
+   
+   AverageValuesArray3DPtr getAverageValues() const;
+   void setAverageValues(AverageValuesArray3DPtr values);
+   
+   ShearStressValuesArray3DPtr getShearStressValues() const;
+   void setShearStressValues(ShearStressValuesArray3DPtr values);
+protected:
+private:
+   DistributionArray3DPtr mFdistributions;
+   AverageValuesArray3DPtr mAverageValues;
+
+   AverageVelocityArray3DPtr mAverageVelocity;
+   AverageFluctuationsArray3DPtr mAverageFluktuations;
+   AverageTriplecorrelationsArray3DPtr mAverageTriplecorrelations;
+
+   ShearStressValuesArray3DPtr mShearStressValues;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & mFdistributions;
+      ar & mAverageValues;
+      ar & mShearStressValues;
+   }
+};
+
+inline DistributionArray3DPtr DataSet3D::getFdistributions() const
+{ 
+   return mFdistributions; 
+}
+
+inline void DataSet3D::setFdistributions(DistributionArray3DPtr distributions)
+{ 
+   mFdistributions = distributions; 
+}
+
+inline AverageValuesArray3DPtr DataSet3D::getAverageValues() const
+{ 
+   return mAverageValues; 
+}
+
+inline void DataSet3D::setAverageValues(AverageValuesArray3DPtr values)
+{ 
+   mAverageValues = values; 
+}
+
+inline AverageVelocityArray3DPtr DataSet3D::getAverageVelocity() const
+{
+   return mAverageVelocity;
+}
+
+inline void DataSet3D::setAverageVelocity(AverageVelocityArray3DPtr values)
+{
+   mAverageVelocity = values;
+}
+
+inline AverageFluctuationsArray3DPtr DataSet3D::getAverageFluctuations() const
+{
+   return mAverageFluktuations;
+}
+
+inline void DataSet3D::setAverageFluctuations(AverageFluctuationsArray3DPtr values)
+{
+   mAverageFluktuations = values;
+}
+
+inline AverageTriplecorrelationsArray3DPtr DataSet3D::getAverageTriplecorrelations() const
+{
+   return mAverageTriplecorrelations;
+}
+
+inline void DataSet3D::setAverageTriplecorrelations(AverageTriplecorrelationsArray3DPtr values)
+{
+   mAverageTriplecorrelations = values;
+}
+
+inline ShearStressValuesArray3DPtr DataSet3D::getShearStressValues() const
+{ 
+   return mShearStressValues; 
+}
+
+inline void DataSet3D::setShearStressValues(ShearStressValuesArray3DPtr values)
+{ 
+   mShearStressValues = values; 
+}
+#endif
diff --git a/source/VirtualFluidsCore/Data/DistributionArray3D.h b/source/VirtualFluidsCore/Data/DistributionArray3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..b27ffb702fd9f4f9e412fed58ef0f5026fb26db2
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/DistributionArray3D.h
@@ -0,0 +1,38 @@
+#ifndef DistributionArray3D_H
+#define DistributionArray3D_H
+
+#include <LBMSystem.h>
+#include <boost/serialization/serialization.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+class DistributionArray3D;
+typedef boost::shared_ptr<DistributionArray3D> DistributionArray3DPtr;
+
+class DistributionArray3D
+{
+public:
+   DistributionArray3D() {};
+   virtual ~DistributionArray3D(){};
+   virtual size_t getNX1() const = 0;
+   virtual size_t getNX2() const = 0;
+   virtual size_t getNX3() const = 0;
+   virtual void getDistribution(LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0;
+   virtual void setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0;
+   virtual void getDistributionInv( LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0;
+   virtual void setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0;
+   virtual void setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0;
+   virtual void setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction) = 0;
+   virtual LBMReal getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction) = 0;
+   virtual void setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0;
+   virtual void setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0;
+   virtual LBMReal getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction) = 0;
+   virtual void swap() = 0;
+protected:
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {}
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Data/EsoTwist3D.h b/source/VirtualFluidsCore/Data/EsoTwist3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..b127bce285b02ed5b1beec1721f11599c37f8bd0
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/EsoTwist3D.h
@@ -0,0 +1,61 @@
+#ifndef ESOTWIST3D_H
+#define ESOTWIST3D_H
+
+#include "DistributionArray3D.h"
+#include <LBMSystem.h>
+#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/base_object.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+class EsoTwist3D;
+typedef boost::shared_ptr<EsoTwist3D> EsoTwist3DPtr;
+
+class EsoTwistD3Q27UnrollArray{};
+class EsoTwistPlusD3Q27UnrollArray{};
+class EsoTwistPlusD3Q19UnrollArray{};
+
+class EsoTwist3D : public DistributionArray3D
+{
+public:
+   EsoTwist3D(){};
+   virtual ~EsoTwist3D(){};
+   //////////////////////////////////////////////////////////////////////////
+   virtual void swap() = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual void getDistribution(LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0;
+   ////////////////////////////////////////////////////////////////////////
+   virtual void getDistributionInv( LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   //virtual void getDistributionInvForDirection(LBMReal* const& f, const size_t& x1, const size_t& x2, const size_t& x3, const unsigned long int& direction) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual LBMReal getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual LBMReal getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction) = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual size_t getNX1() const = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual size_t getNX2() const = 0;
+   //////////////////////////////////////////////////////////////////////////
+   virtual size_t getNX3() const = 0;
+   //////////////////////////////////////////////////////////////////////////
+  
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object< DistributionArray3D >(*this);
+   }
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Data/EsoTwistD3Q27SparseData.cpp b/source/VirtualFluidsCore/Data/EsoTwistD3Q27SparseData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d0508e8fff066cba78da67438c90f7359090672
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/EsoTwistD3Q27SparseData.cpp
@@ -0,0 +1,628 @@
+#include "EsoTwistD3Q27SparseData.h"
+#include "EsoTwistD3Q27System.h"
+
+EsoTwistD3Q27SparseData::SparseData EsoTwistD3Q27SparseData::localDistributions;
+EsoTwistD3Q27SparseData::SparseData EsoTwistD3Q27SparseData::nonLocalDistributions;
+EsoTwistD3Q27SparseData::SparseData EsoTwistD3Q27SparseData::zeroDistributions;
+
+size_t EsoTwistD3Q27SparseData::nx1=0;
+size_t EsoTwistD3Q27SparseData::nx2=0;
+size_t EsoTwistD3Q27SparseData::nx3=0;
+size_t EsoTwistD3Q27SparseData::nx4=0;
+size_t EsoTwistD3Q27SparseData::nx5=0;
+//////////////////////////////////////////////////////////////////////////
+EsoTwistD3Q27SparseData::EsoTwistD3Q27SparseData()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+EsoTwistD3Q27SparseData::EsoTwistD3Q27SparseData( size_t ibx[3], size_t nx[3], size_t level, double value )
+{
+   this->NX1 = nx[0];
+   this->NX2 = nx[1];
+   this->NX3 = nx[2];
+
+   this->ox1 = ibx[0]*nx[0]; 
+   this->ox2 = ibx[1]*nx[1];
+   this->ox3 = ibx[2]*nx[2];
+   this->level = level;
+
+   ld = SparseDataPtr(&localDistributions);
+   nld = SparseDataPtr(&nonLocalDistributions);
+   zd = SparseDataPtr(&zeroDistributions);
+
+   for(int x3 = 0; x3 < NX3; x3++)
+   {
+      for(int x2 = 0; x2 < NX2; x2++)
+      {
+         for(int x1 = 0; x1 < NX1; x1++)
+         {
+            for(int f = 0; f < 13; f++)
+            {
+               ld->insert(std::make_pair(index4D(f,x1,x2,x3),value));
+               nld->insert(std::make_pair(index4D(f,x1,x2,x3),value));
+            }
+            zd->insert(std::make_pair(index3D(x1,x2,x3),value));
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+EsoTwistD3Q27SparseData::~EsoTwistD3Q27SparseData()
+{
+   ld = SparseDataPtr();
+   nld = SparseDataPtr();
+   zd = SparseDataPtr();
+
+}
+//////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::swap()
+{
+   std::swap( this->ld, this->nld );
+}
+//////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::getDistribution(LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   size_t x1plus = x1+1;
+   size_t x2plus = x2+1;
+   size_t x3plus = x3+1;
+
+   f[D3Q27System::E] = (*ld)[index4D(D3Q27System::ET_E, x1,x2,x3)];
+   f[D3Q27System::N] = (*ld)[index4D(D3Q27System::ET_N,x1,x2,x3)];  
+   f[D3Q27System::T] = (*ld)[index4D(D3Q27System::ET_T,x1,x2,x3)];
+   f[D3Q27System::NE] = (*ld)[index4D(D3Q27System::ET_NE,x1,x2,x3)];
+   f[D3Q27System::NW] = (*ld)[index4D(D3Q27System::ET_NW,x1plus,x2,x3)];
+   f[D3Q27System::TE] = (*ld)[index4D(D3Q27System::ET_TE,x1,x2,x3)];
+   f[D3Q27System::TW] = (*ld)[index4D(D3Q27System::ET_TW, x1plus,x2,x3)];
+   f[D3Q27System::TN] = (*ld)[index4D(D3Q27System::ET_TN,x1,x2,x3)];
+   f[D3Q27System::TS] = (*ld)[index4D(D3Q27System::ET_TS,x1,x2plus,x3)];
+   f[D3Q27System::TNE] = (*ld)[index4D(D3Q27System::ET_TNE,x1,x2,x3)];
+   f[D3Q27System::TNW] = (*ld)[index4D(D3Q27System::ET_TNW,x1plus,x2,x3)];
+   f[D3Q27System::TSE] = (*ld)[index4D(D3Q27System::ET_TSE,x1,x2plus,x3)];
+   f[D3Q27System::TSW] = (*ld)[index4D(D3Q27System::ET_TSW,x1plus,x2plus,x3)];
+
+   f[D3Q27System::W ] = (*nld)[index4D(D3Q27System::ET_W,x1plus,x2,x3  )];
+   f[D3Q27System::S ] = (*nld)[index4D(D3Q27System::ET_S,x1,x2plus,x3  )];
+   f[D3Q27System::B ] = (*nld)[index4D(D3Q27System::ET_B,x1,x2,x3plus  )];
+   f[D3Q27System::SW] = (*nld)[index4D(D3Q27System::ET_SW,x1plus,x2plus,x3 )];
+   f[D3Q27System::SE] = (*nld)[index4D(D3Q27System::ET_SE,x1,x2plus,x3 )];
+   f[D3Q27System::BW] = (*nld)[index4D(D3Q27System::ET_BW,x1plus,x2,x3plus )];
+   f[D3Q27System::BE] = (*nld)[index4D(D3Q27System::ET_BE,x1,x2,x3plus )];
+   f[D3Q27System::BS] = (*nld)[index4D(D3Q27System::ET_BS,x1,x2plus,x3plus )];
+   f[D3Q27System::BN] = (*nld)[index4D(D3Q27System::ET_BN,x1,x2,x3plus )];
+   f[D3Q27System::BSW] = (*nld)[index4D(D3Q27System::ET_BSW,x1plus,x2plus,x3plus)];
+   f[D3Q27System::BSE] = (*nld)[index4D(D3Q27System::ET_BSE,x1,x2plus,x3plus)];
+   f[D3Q27System::BNW] = (*nld)[index4D(D3Q27System::ET_BNW,x1plus,x2,x3plus)];
+   f[D3Q27System::BNE] = (*nld)[index4D(D3Q27System::ET_BNE,x1,x2,x3plus)];
+
+   f[D3Q27System::ZERO] = (*zd)[index3D(x1,x2,x3)];
+}
+////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   size_t x1plus = x1+1;
+   size_t x2plus = x2+1;
+   size_t x3plus = x3+1;
+
+   (*ld)[index4D(D3Q27System::ET_E,x1,  x2,  x3)] = f[D3Q27System::INV_E];
+   (*ld)[index4D(D3Q27System::ET_N,x1,  x2,  x3)] = f[D3Q27System::INV_N];
+   (*ld)[index4D(D3Q27System::ET_T,x1,  x2,  x3)] = f[D3Q27System::INV_T];
+   (*ld)[index4D(D3Q27System::ET_NE,x1,  x2,  x3)] = f[D3Q27System::INV_NE];
+   (*ld)[index4D(D3Q27System::ET_NW,x1plus,x2,  x3)] = f[D3Q27System::INV_NW];
+   (*ld)[index4D(D3Q27System::ET_TE,x1,  x2,  x3)] = f[D3Q27System::INV_TE];
+   (*ld)[index4D(D3Q27System::ET_TW,x1plus,x2,  x3)] = f[D3Q27System::INV_TW];
+   (*ld)[index4D(D3Q27System::ET_TN,x1,  x2,  x3)] = f[D3Q27System::INV_TN];
+   (*ld)[index4D(D3Q27System::ET_TS,x1,  x2plus,x3)] = f[D3Q27System::INV_TS];
+   (*ld)[index4D(D3Q27System::ET_TNE,x1,  x2,  x3)] = f[D3Q27System::INV_TNE];
+   (*ld)[index4D(D3Q27System::ET_TNW,x1plus,x2,  x3)] = f[D3Q27System::INV_TNW];
+   (*ld)[index4D(D3Q27System::ET_TSE,x1,  x2plus,x3)] = f[D3Q27System::INV_TSE];
+   (*ld)[index4D(D3Q27System::ET_TSW,x1plus,x2plus,x3)] = f[D3Q27System::INV_TSW];
+
+   (*nld)[index4D(D3Q27System::ET_W,x1plus,x2,  x3    )] = f[D3Q27System::INV_W ];
+   (*nld)[index4D(D3Q27System::ET_S,x1,  x2plus,x3    )] = f[D3Q27System::INV_S ];
+   (*nld)[index4D(D3Q27System::ET_B,x1,  x2,  x3plus  )] = f[D3Q27System::INV_B ];
+   (*nld)[index4D(D3Q27System::ET_SW,x1plus,x2plus,x3   )] = f[D3Q27System::INV_SW];
+   (*nld)[index4D(D3Q27System::ET_SE,x1,  x2plus,x3   )] = f[D3Q27System::INV_SE];
+   (*nld)[index4D(D3Q27System::ET_BW,x1plus,x2,  x3plus )] = f[D3Q27System::INV_BW];
+   (*nld)[index4D(D3Q27System::ET_BE,x1,  x2,  x3plus )] = f[D3Q27System::INV_BE];
+   (*nld)[index4D(D3Q27System::ET_BS,x1,  x2plus,x3plus )] = f[D3Q27System::INV_BS];
+   (*nld)[index4D(D3Q27System::ET_BN,x1,  x2,  x3plus )] = f[D3Q27System::INV_BN];
+   (*nld)[index4D(D3Q27System::ET_BSW,x1plus,x2plus,x3plus)] = f[D3Q27System::INV_BSW];
+   (*nld)[index4D(D3Q27System::ET_BSE,x1,  x2plus,x3plus)] = f[D3Q27System::INV_BSE];
+   (*nld)[index4D(D3Q27System::ET_BNW,x1plus,x2,  x3plus)] = f[D3Q27System::INV_BNW];
+   (*nld)[index4D(D3Q27System::ET_BNE,x1,  x2,  x3plus)] = f[D3Q27System::INV_BNE];
+
+   (*zd)[index3D(x1,x2,x3)] = f[D3Q27System::ZERO];
+}
+////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::getDistributionInv(LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   size_t x1plus = x1+1;
+   size_t x2plus = x2+1;
+   size_t x3plus = x3+1;
+
+   f[D3Q27System::INV_E] = (*ld)[index4D(D3Q27System::ET_E, x1,x2,x3)];
+   f[D3Q27System::INV_N] = (*ld)[index4D(D3Q27System::ET_N,x1,x2,x3)];  
+   f[D3Q27System::INV_T] = (*ld)[index4D(D3Q27System::ET_T,x1,x2,x3)];
+   f[D3Q27System::INV_NE] = (*ld)[index4D(D3Q27System::ET_NE,x1,x2,x3)];
+   f[D3Q27System::INV_NW] = (*ld)[index4D(D3Q27System::ET_NW,x1plus,x2,x3)];
+   f[D3Q27System::INV_TE] = (*ld)[index4D(D3Q27System::ET_TE,x1,x2,x3)];
+   f[D3Q27System::INV_TW] = (*ld)[index4D(D3Q27System::ET_TW, x1plus,x2,x3)];
+   f[D3Q27System::INV_TN] = (*ld)[index4D(D3Q27System::ET_TN,x1,x2,x3)];
+   f[D3Q27System::INV_TS] = (*ld)[index4D(D3Q27System::ET_TS,x1,x2plus,x3)];
+   f[D3Q27System::INV_TNE] = (*ld)[index4D(D3Q27System::ET_TNE,x1,x2,x3)];
+   f[D3Q27System::INV_TNW] = (*ld)[index4D(D3Q27System::ET_TNW,x1plus,x2,x3)];
+   f[D3Q27System::INV_TSE] = (*ld)[index4D(D3Q27System::ET_TSE,x1,x2plus,x3)];
+   f[D3Q27System::INV_TSW] = (*ld)[index4D(D3Q27System::ET_TSW,x1plus,x2plus,x3)];
+
+   f[D3Q27System::INV_W ] = (*nld)[index4D(D3Q27System::ET_W,x1plus,x2,x3  )];
+   f[D3Q27System::INV_S ] = (*nld)[index4D(D3Q27System::ET_S,x1,x2plus,x3  )];
+   f[D3Q27System::INV_B ] = (*nld)[index4D(D3Q27System::ET_B,x1,x2,x3plus  )];
+   f[D3Q27System::INV_SW] = (*nld)[index4D(D3Q27System::ET_SW,x1plus,x2plus,x3 )];
+   f[D3Q27System::INV_SE] = (*nld)[index4D(D3Q27System::ET_SE,x1,x2plus,x3 )];
+   f[D3Q27System::INV_BW] = (*nld)[index4D(D3Q27System::ET_BW,x1plus,x2,x3plus )];
+   f[D3Q27System::INV_BE] = (*nld)[index4D(D3Q27System::ET_BE,x1,x2,x3plus )];
+   f[D3Q27System::INV_BS] = (*nld)[index4D(D3Q27System::ET_BS,x1,x2plus,x3plus )];
+   f[D3Q27System::INV_BN] = (*nld)[index4D(D3Q27System::ET_BN,x1,x2,x3plus )];
+   f[D3Q27System::INV_BSW] = (*nld)[index4D(D3Q27System::ET_BSW,x1plus,x2plus,x3plus)];
+   f[D3Q27System::INV_BSE] = (*nld)[index4D(D3Q27System::ET_BSE,x1,x2plus,x3plus)];
+   f[D3Q27System::INV_BNW] = (*nld)[index4D(D3Q27System::ET_BNW,x1plus,x2,x3plus)];
+   f[D3Q27System::INV_BNE] = (*nld)[index4D(D3Q27System::ET_BNE,x1,x2,x3plus)];
+
+   f[D3Q27System::ZERO] = (*zd)[index3D(x1,x2,x3)];
+}
+//////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3)
+{
+   size_t x1plus = x1+1;
+   size_t x2plus = x2+1;
+   size_t x3plus = x3+1;
+
+   (*ld)[index4D(D3Q27System::ET_E,x1,  x2,  x3)] = f[D3Q27System::E];
+   (*ld)[index4D(D3Q27System::ET_N,x1,  x2,  x3)] = f[D3Q27System::N];
+   (*ld)[index4D(D3Q27System::ET_T,x1,  x2,  x3)] = f[D3Q27System::T];
+   (*ld)[index4D(D3Q27System::ET_NE,x1,  x2,  x3)] = f[D3Q27System::NE];
+   (*ld)[index4D(D3Q27System::ET_NW,x1plus,x2,  x3)] = f[D3Q27System::NW];
+   (*ld)[index4D(D3Q27System::ET_TE,x1,  x2,  x3)] = f[D3Q27System::TE];
+   (*ld)[index4D(D3Q27System::ET_TW,x1plus,x2,  x3)] = f[D3Q27System::TW];
+   (*ld)[index4D(D3Q27System::ET_TN,x1,  x2,  x3)] = f[D3Q27System::TN];
+   (*ld)[index4D(D3Q27System::ET_TS,x1,  x2plus,x3)] = f[D3Q27System::TS];
+   (*ld)[index4D(D3Q27System::ET_TNE,x1,  x2,  x3)] = f[D3Q27System::TNE];
+   (*ld)[index4D(D3Q27System::ET_TNW,x1plus,x2,  x3)] = f[D3Q27System::TNW];
+   (*ld)[index4D(D3Q27System::ET_TSE,x1,  x2plus,x3)] = f[D3Q27System::TSE];
+   (*ld)[index4D(D3Q27System::ET_TSW,x1plus,x2plus,x3)] = f[D3Q27System::TSW];
+
+   (*nld)[index4D(D3Q27System::ET_W,x1plus,x2,  x3    )] = f[D3Q27System::W ];
+   (*nld)[index4D(D3Q27System::ET_S,x1,  x2plus,x3    )] = f[D3Q27System::S ];
+   (*nld)[index4D(D3Q27System::ET_B,x1,  x2,  x3plus  )] = f[D3Q27System::B ];
+   (*nld)[index4D(D3Q27System::ET_SW,x1plus,x2plus,x3   )] = f[D3Q27System::SW];
+   (*nld)[index4D(D3Q27System::ET_SE,x1,  x2plus,x3   )] = f[D3Q27System::SE];
+   (*nld)[index4D(D3Q27System::ET_BW,x1plus,x2,  x3plus )] = f[D3Q27System::BW];
+   (*nld)[index4D(D3Q27System::ET_BE,x1,  x2,  x3plus )] = f[D3Q27System::BE];
+   (*nld)[index4D(D3Q27System::ET_BS,x1,  x2plus,x3plus )] = f[D3Q27System::BS];
+   (*nld)[index4D(D3Q27System::ET_BN,x1,  x2,  x3plus )] = f[D3Q27System::BN];
+   (*nld)[index4D(D3Q27System::ET_BSW,x1plus,x2plus,x3plus)] = f[D3Q27System::BSW];
+   (*nld)[index4D(D3Q27System::ET_BSE,x1,  x2plus,x3plus)] = f[D3Q27System::BSE];
+   (*nld)[index4D(D3Q27System::ET_BNW,x1plus,x2,  x3plus)] = f[D3Q27System::BNW];
+   (*nld)[index4D(D3Q27System::ET_BNE,x1,  x2,  x3plus)] = f[D3Q27System::BNE];
+
+   (*zd)[index3D(x1,x2,x3)] = f[D3Q27System::ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+   size_t x1plus = x1+1;
+   size_t x2plus = x2+1;
+   size_t x3plus = x3+1;
+
+   bool directionFlag = false;
+   if ((direction & EsoTwistD3Q27System::etE) == EsoTwistD3Q27System::etE)
+      (*nld)[index4D(D3Q27System::ET_W,x1plus,x2,  x3    )] = f[D3Q27System::E]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etW) == EsoTwistD3Q27System::etW)
+      (*ld)[index4D(D3Q27System::ET_E,x1,  x2,  x3)] = f[D3Q27System::W]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etS) == EsoTwistD3Q27System::etS)
+      (*ld)[index4D(D3Q27System::ET_N,x1,  x2,  x3)] = f[D3Q27System::S]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etN) == EsoTwistD3Q27System::etN)
+      (*nld)[index4D(D3Q27System::ET_S,x1,  x2plus,x3    )] = f[D3Q27System::N]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etB) == EsoTwistD3Q27System::etB)
+      (*ld)[index4D(D3Q27System::ET_T,x1,  x2,  x3)] = f[D3Q27System::B]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etT) == EsoTwistD3Q27System::etT)
+      (*nld)[index4D(D3Q27System::ET_B,x1,  x2,  x3plus  )] = f[D3Q27System::T]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etSW) == EsoTwistD3Q27System::etSW)
+      (*ld)[index4D(D3Q27System::ET_NE,x1,  x2,  x3)] = f[D3Q27System::SW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etNE) == EsoTwistD3Q27System::etNE)
+      (*nld)[index4D(D3Q27System::ET_SW,x1plus,x2plus,x3   )] = f[D3Q27System::NE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etNW) == EsoTwistD3Q27System::etNW)
+      (*nld)[index4D(D3Q27System::ET_SE,x1,  x2plus,x3   )] = f[D3Q27System::NW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etSE) == EsoTwistD3Q27System::etSE)
+      (*ld)[index4D(D3Q27System::ET_NW,x1plus,x2,  x3)] = f[D3Q27System::SE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBW) == EsoTwistD3Q27System::etBW)
+      (*ld)[index4D(D3Q27System::ET_TE,x1,  x2,  x3)] = f[D3Q27System::BW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTE) == EsoTwistD3Q27System::etTE)
+      (*nld)[index4D(D3Q27System::ET_BW,x1plus,x2,  x3plus )] = f[D3Q27System::TE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTW) == EsoTwistD3Q27System::etTW)
+      (*nld)[index4D(D3Q27System::ET_BE,x1,  x2,  x3plus )] = f[D3Q27System::TW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBE) == EsoTwistD3Q27System::etBE)
+      (*ld)[index4D(D3Q27System::ET_TW,x1plus,x2,  x3)] = f[D3Q27System::BE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBS) == EsoTwistD3Q27System::etBS)
+      (*ld)[index4D(D3Q27System::ET_TN,x1,  x2,  x3)] = f[D3Q27System::BS]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTN) == EsoTwistD3Q27System::etTN)
+      (*nld)[index4D(D3Q27System::ET_BS,x1,  x2plus,x3plus )] = f[D3Q27System::TN]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTS) == EsoTwistD3Q27System::etTS)
+      (*nld)[index4D(D3Q27System::ET_BN,x1,  x2,  x3plus )] = f[D3Q27System::TS]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBN) == EsoTwistD3Q27System::etBN)
+      (*ld)[index4D(D3Q27System::ET_TS,x1,  x2plus,x3)] = f[D3Q27System::BN]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBSW) == EsoTwistD3Q27System::etBSW)
+      (*ld)[index4D(D3Q27System::ET_TNE,x1,  x2,  x3)] = f[D3Q27System::BSW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTNE) == EsoTwistD3Q27System::etTNE)
+      (*nld)[index4D(D3Q27System::ET_BSW,x1plus,x2plus,x3plus)] = f[D3Q27System::TNE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBSE) == EsoTwistD3Q27System::etBSE)
+      (*ld)[index4D(D3Q27System::ET_TNW,x1plus,x2,  x3)] = f[D3Q27System::BSE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTNW) == EsoTwistD3Q27System::etTNW)
+      (*nld)[index4D(D3Q27System::ET_BSE,x1,  x2plus,x3plus)] = f[D3Q27System::TNW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBNW) == EsoTwistD3Q27System::etBNW)
+      (*ld)[index4D(D3Q27System::ET_TSE,x1,  x2plus,x3)] = f[D3Q27System::BNW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTSE) == EsoTwistD3Q27System::etTSE)
+      (*nld)[index4D(D3Q27System::ET_BNW,x1plus,x2,  x3plus)] = f[D3Q27System::TSE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBNE) == EsoTwistD3Q27System::etBNE)
+      (*ld)[index4D(D3Q27System::ET_TSW,x1plus,x2plus,x3)] = f[D3Q27System::BNE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW)
+      (*nld)[index4D(D3Q27System::ET_BNE,x1,  x2,  x3plus)] = f[D3Q27System::TSW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::ZERO) == EsoTwistD3Q27System::ZERO)
+      (*zd)[index3D(x1,x2,x3)] = f[D3Q27System::ZERO]; directionFlag=true;
+#ifdef _DEBUG
+   if(!directionFlag)UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );
+#endif //DEBUG
+}
+//////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction)
+{
+   switch (direction)
+   {
+   case D3Q27System::E :
+      (*nld)[index4D(D3Q27System::ET_W,x1+1,x2,  x3    )] = f;
+      break;
+   case D3Q27System::W :
+      (*ld)[index4D(D3Q27System::ET_E,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::S :
+      (*ld)[index4D(D3Q27System::ET_N,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::N :
+      (*nld)[index4D(D3Q27System::ET_S,x1,  x2+1,x3    )] = f;
+      break;
+   case D3Q27System::B :
+      (*ld)[index4D(D3Q27System::ET_T,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::T :
+      (*nld)[index4D(D3Q27System::ET_B,x1,  x2,  x3+1  )] = f;
+      break;
+   case D3Q27System::SW :
+      (*ld)[index4D(D3Q27System::ET_NE,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::NE :
+      (*nld)[index4D(D3Q27System::ET_SW,x1+1,x2+1,x3   )] = f;
+      break;
+   case D3Q27System::NW :
+      (*nld)[index4D(D3Q27System::ET_SE,x1,  x2+1,x3   )] = f;
+      break;
+   case D3Q27System::SE :
+      (*ld)[index4D(D3Q27System::ET_NW,x1+1,x2,  x3)] = f;
+      break;
+   case D3Q27System::BW :
+      (*ld)[index4D(D3Q27System::ET_TE,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::TE :
+      (*nld)[index4D(D3Q27System::ET_BW,x1+1,x2,  x3+1 )] = f;
+      break;
+   case D3Q27System::TW :
+      (*nld)[index4D(D3Q27System::ET_BE,x1,  x2,  x3+1 )] = f;
+      break;
+   case D3Q27System::BE :
+      (*ld)[index4D(D3Q27System::ET_TW,x1+1,x2,  x3)] = f;
+      break;
+   case D3Q27System::BS :
+      (*ld)[index4D(D3Q27System::ET_TN,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::TN :
+      (*nld)[index4D(D3Q27System::ET_BS,x1,  x2+1,x3+1 )] = f;
+      break;
+   case D3Q27System::TS :
+      (*nld)[index4D(D3Q27System::ET_BN,x1,  x2,  x3+1 )] = f;
+      break;
+   case D3Q27System::BN :
+      (*ld)[index4D(D3Q27System::ET_TS,x1,  x2+1,x3)] = f;
+      break;
+   case D3Q27System::BSW :
+      (*ld)[index4D(D3Q27System::ET_TNE,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::TNE :
+      (*nld)[index4D(D3Q27System::ET_BSW,x1+1,x2+1,x3+1)] = f;
+      break;
+   case D3Q27System::BSE :
+      (*ld)[index4D(D3Q27System::ET_TNW,x1+1,x2,  x3)] = f;
+      break;
+   case D3Q27System::TNW :
+      (*nld)[index4D(D3Q27System::ET_BSE,x1,  x2+1,x3+1)] = f;
+      break;
+   case D3Q27System::BNW :
+      (*ld)[index4D(D3Q27System::ET_TSE,x1,  x2+1,x3)] = f;
+      break;
+   case D3Q27System::TSE :
+      (*nld)[index4D(D3Q27System::ET_BNW,x1+1,x2,  x3+1)] = f;
+      break;
+   case D3Q27System::BNE :
+      (*ld)[index4D(D3Q27System::ET_TSW,x1+1,x2+1,x3)] = f;
+      break;
+   case D3Q27System::TSW :
+      (*nld)[index4D(D3Q27System::ET_BNE,x1,  x2,  x3+1)] = f;
+      break;
+   case D3Q27System::ZERO :
+      (*zd)[index3D(x1,x2,x3)] = f;
+      break;
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Direction didn't find"));     
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+   size_t x1plus = x1+1;
+   size_t x2plus = x2+1;
+   size_t x3plus = x3+1;
+
+   bool directionFlag = false;
+   if ((direction & EsoTwistD3Q27System::etE) == EsoTwistD3Q27System::etE)
+      (*ld)[index4D(D3Q27System::ET_E,x1,  x2,  x3)] = f[D3Q27System::E]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etW) == EsoTwistD3Q27System::etW)
+      (*nld)[index4D(D3Q27System::ET_W,x1plus,x2,  x3    )] = f[D3Q27System::W]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etS) == EsoTwistD3Q27System::etS)
+      (*nld)[index4D(D3Q27System::ET_S,x1,  x2plus,x3    )] = f[D3Q27System::S]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etN) == EsoTwistD3Q27System::etN)
+      (*ld)[index4D(D3Q27System::ET_N,x1,  x2,  x3)] = f[D3Q27System::N]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etB) == EsoTwistD3Q27System::etB)
+      (*nld)[index4D(D3Q27System::ET_B,x1,  x2,  x3plus  )] = f[D3Q27System::B]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etT) == EsoTwistD3Q27System::etT)
+      (*ld)[index4D(D3Q27System::ET_T,x1,  x2,  x3)] = f[D3Q27System::T]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etSW) == EsoTwistD3Q27System::etSW)
+      (*nld)[index4D(D3Q27System::ET_SW,x1plus,x2plus,x3   )] = f[D3Q27System::SW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etNE) == EsoTwistD3Q27System::etNE)
+      (*ld)[index4D(D3Q27System::ET_NE,x1,  x2,  x3)] = f[D3Q27System::NE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etNW) == EsoTwistD3Q27System::etNW)
+      (*ld)[index4D(D3Q27System::ET_NW,x1plus,x2,  x3)] = f[D3Q27System::NW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etSE) == EsoTwistD3Q27System::etSE)
+      (*nld)[index4D(D3Q27System::ET_SE,x1,  x2plus,x3   )] = f[D3Q27System::SE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBW) == EsoTwistD3Q27System::etBW)
+      (*nld)[index4D(D3Q27System::ET_BW,x1plus,x2,  x3plus )] = f[D3Q27System::BW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTE) == EsoTwistD3Q27System::etTE)
+      (*ld)[index4D(D3Q27System::ET_TE,x1,  x2,  x3)] = f[D3Q27System::TE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTW) == EsoTwistD3Q27System::etTW)
+      (*ld)[index4D(D3Q27System::ET_TW,x1plus,x2,  x3)] = f[D3Q27System::TW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBE) == EsoTwistD3Q27System::etBE)
+      (*nld)[index4D(D3Q27System::ET_BE,x1,  x2,  x3plus )] = f[D3Q27System::BE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBS) == EsoTwistD3Q27System::etBS)
+      (*nld)[index4D(D3Q27System::ET_BS,x1,  x2plus,x3plus )] = f[D3Q27System::BS]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTN) == EsoTwistD3Q27System::etTN)
+      (*ld)[index4D(D3Q27System::ET_TN,x1,  x2,  x3)] = f[D3Q27System::TN]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTS) == EsoTwistD3Q27System::etTS)
+      (*ld)[index4D(D3Q27System::ET_TS,x1,  x2plus,x3)] = f[D3Q27System::TS]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBN) == EsoTwistD3Q27System::etBN)
+      (*nld)[index4D(D3Q27System::ET_BN,x1,  x2,  x3plus )] = f[D3Q27System::BN]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBSW) == EsoTwistD3Q27System::etBSW)
+      (*nld)[index4D(D3Q27System::ET_BSW,x1plus,x2plus,x3plus)] = f[D3Q27System::BSW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTNE) == EsoTwistD3Q27System::etTNE)
+      (*ld)[index4D(D3Q27System::ET_TNE,x1,  x2,  x3)] = f[D3Q27System::TNE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBSE) == EsoTwistD3Q27System::etBSE)
+      (*nld)[index4D(D3Q27System::ET_BSE,x1,  x2plus,x3plus)] = f[D3Q27System::BSE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTNW) == EsoTwistD3Q27System::etTNW)
+      (*ld)[index4D(D3Q27System::ET_TNW,x1plus,x2,  x3)] = f[D3Q27System::TNW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBNW) == EsoTwistD3Q27System::etBNW)
+      (*nld)[index4D(D3Q27System::ET_BNW,x1plus,x2,  x3plus)] = f[D3Q27System::BNW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTSE) == EsoTwistD3Q27System::etTSE)
+      (*ld)[index4D(D3Q27System::ET_TSE,x1,  x2plus,x3)] = f[D3Q27System::TSE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etBNE) == EsoTwistD3Q27System::etBNE)
+      (*nld)[index4D(D3Q27System::ET_BNE,x1,  x2,  x3plus)] = f[D3Q27System::BNE]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW)
+      (*ld)[index4D(D3Q27System::ET_TSW,x1plus,x2plus,x3)] = f[D3Q27System::TSW]; directionFlag=true;
+   if ((direction & EsoTwistD3Q27System::ZERO) == EsoTwistD3Q27System::ZERO)
+      (*zd)[index3D(x1,x2,x3)] = f[D3Q27System::ZERO]; directionFlag=true;
+#ifdef _DEBUG
+   if(!directionFlag)UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );
+#endif //DEBUG
+}
+//////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction)
+{
+   switch (direction)
+   {
+   case D3Q27System::E :
+      (*ld)[index4D(D3Q27System::ET_E,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::W :
+      (*nld)[index4D(D3Q27System::ET_W,x1+1,x2,  x3    )] = f;
+      break;
+   case D3Q27System::S :
+      (*nld)[index4D(D3Q27System::ET_S,x1,  x2+1,x3    )] = f;
+      break;
+   case D3Q27System::N :
+      (*ld)[index4D(D3Q27System::ET_N,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::B :
+      (*nld)[index4D(D3Q27System::ET_B,x1,  x2,  x3+1  )] = f;
+      break;
+   case D3Q27System::T :
+      (*ld)[index4D(D3Q27System::ET_T,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::SW :
+      (*nld)[index4D(D3Q27System::ET_SW,x1+1,x2+1,x3   )] = f;
+      break;
+   case D3Q27System::NE :
+      (*ld)[index4D(D3Q27System::ET_NE,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::NW :
+      (*ld)[index4D(D3Q27System::ET_NW,x1+1,x2,  x3)] = f;
+      break;
+   case D3Q27System::SE :
+      (*nld)[index4D(D3Q27System::ET_SE,x1,  x2+1,x3   )] = f;
+      break;
+   case D3Q27System::BW :
+      (*nld)[index4D(D3Q27System::ET_BW,x1+1,x2,  x3+1 )] = f;
+      break;
+   case D3Q27System::TE :
+      (*ld)[index4D(D3Q27System::ET_TE,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::TW :
+      (*ld)[index4D(D3Q27System::ET_TW,x1+1,x2,  x3)] = f;
+      break;
+   case D3Q27System::BE :
+      (*nld)[index4D(D3Q27System::ET_BE,x1,  x2,  x3+1 )] = f;
+      break;
+   case D3Q27System::BS :
+      (*nld)[index4D(D3Q27System::ET_BS,x1,  x2+1,x3+1 )] = f;
+      break;
+   case D3Q27System::TN :
+      (*ld)[index4D(D3Q27System::ET_TN,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::TS :
+      (*ld)[index4D(D3Q27System::ET_TS,x1,  x2+1,x3)] = f;
+      break;
+   case D3Q27System::BN :
+      (*nld)[index4D(D3Q27System::ET_BN,x1,  x2,  x3+1 )] = f;
+      break;
+   case D3Q27System::BSW :
+      (*nld)[index4D(D3Q27System::ET_BSW,x1+1,x2+1,x3+1)] = f;
+      break;
+   case D3Q27System::TNE :
+      (*ld)[index4D(D3Q27System::ET_TNE,x1,  x2,  x3)] = f;
+      break;
+   case D3Q27System::BSE :
+      (*nld)[index4D(D3Q27System::ET_BSE,x1,  x2+1,x3+1)] = f;
+      break;
+   case D3Q27System::TNW :
+      (*ld)[index4D(D3Q27System::ET_TNW,x1+1,x2,  x3)] = f;
+      break;
+   case D3Q27System::BNW :
+      (*nld)[index4D(D3Q27System::ET_BNW,x1+1,x2,  x3+1)] = f;
+      break;
+   case D3Q27System::TSE :
+      (*ld)[index4D(D3Q27System::ET_TSE,x1,  x2+1,x3)] = f;
+      break;
+   case D3Q27System::BNE :
+      (*nld)[index4D(D3Q27System::ET_BNE,x1,  x2,  x3+1)] = f;
+      break;
+   case D3Q27System::TSW :
+      (*ld)[index4D(D3Q27System::ET_TSW,x1+1,x2+1,x3)] = f;
+      break;
+   case D3Q27System::ZERO :
+      (*zd)[index3D(x1,x2,x3)] = f;
+      break;
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Direction didn't find"));     
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+LBMReal EsoTwistD3Q27SparseData::getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction)
+{
+   switch (direction)
+   {
+   case D3Q27System::E :
+      return (*nld)[index4D(D3Q27System::ET_W,x1+1,x2,  x3    )];
+   case D3Q27System::W :
+      return (*ld)[index4D(D3Q27System::ET_E,x1,  x2,  x3)];
+   case D3Q27System::S :
+      return (*ld)[index4D(D3Q27System::ET_N,x1,  x2,  x3)];
+   case D3Q27System::N :
+      return (*nld)[index4D(D3Q27System::ET_S,x1,  x2+1,x3    )];
+   case D3Q27System::B :
+      return (*ld)[index4D(D3Q27System::ET_T,x1,  x2,  x3)];
+   case D3Q27System::T :
+      return (*nld)[index4D(D3Q27System::ET_B,x1,  x2,  x3+1  )];
+   case D3Q27System::SW :
+      return (*ld)[index4D(D3Q27System::ET_NE,x1,  x2,  x3)];
+   case D3Q27System::NE :
+      return (*nld)[index4D(D3Q27System::ET_SW,x1+1,x2+1,x3   )];
+   case D3Q27System::NW :
+      return (*nld)[index4D(D3Q27System::ET_SE,x1,  x2+1,x3   )];
+   case D3Q27System::SE :
+      return (*ld)[index4D(D3Q27System::ET_NW,x1+1,x2,  x3)];
+   case D3Q27System::BW :
+      return (*ld)[index4D(D3Q27System::ET_TE,x1,  x2,  x3)];
+   case D3Q27System::TE :
+      return (*nld)[index4D(D3Q27System::ET_BW,x1+1,x2,  x3+1 )];
+   case D3Q27System::TW :
+      return (*nld)[index4D(D3Q27System::ET_BE,x1,  x2,  x3+1 )];
+   case D3Q27System::BE :
+      return (*ld)[index4D(D3Q27System::ET_TW,x1+1,x2,  x3)];
+   case D3Q27System::BS :
+      return (*ld)[index4D(D3Q27System::ET_TN,x1,  x2,  x3)];
+   case D3Q27System::TN :
+      return (*nld)[index4D(D3Q27System::ET_BS,x1,  x2+1,x3+1 )];
+   case D3Q27System::TS :
+      return (*nld)[index4D(D3Q27System::ET_BN,x1,  x2,  x3+1 )];
+   case D3Q27System::BN :
+      return (*ld)[index4D(D3Q27System::ET_TS,x1,  x2+1,x3)];
+   case D3Q27System::BSW :
+      return (*ld)[index4D(D3Q27System::ET_TNE,x1,  x2,  x3)];
+   case D3Q27System::TNE :
+      return (*nld)[index4D(D3Q27System::ET_BSW,x1+1,x2+1,x3+1)];
+   case D3Q27System::BSE :
+      return (*ld)[index4D(D3Q27System::ET_TNW,x1+1,x2,  x3)];
+   case D3Q27System::TNW :
+      return (*nld)[index4D(D3Q27System::ET_BSE,x1,  x2+1,x3+1)];
+   case D3Q27System::BNW :
+      return (*ld)[index4D(D3Q27System::ET_TSE,x1,  x2+1,x3)];
+   case D3Q27System::TSE :
+      return (*nld)[index4D(D3Q27System::ET_BNW,x1+1,x2,  x3+1)];
+   case D3Q27System::BNE :
+      return (*ld)[index4D(D3Q27System::ET_TSW,x1+1,x2+1,x3)];
+   case D3Q27System::TSW :
+      return (*nld)[index4D(D3Q27System::ET_BNE,x1,  x2,  x3+1)];
+   case D3Q27System::ZERO :
+      return (*zd)[index3D(x1,x2,x3)];
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Direction didn't find") );     
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+size_t EsoTwistD3Q27SparseData::getNX1() const
+{
+   return NX1;
+}
+//////////////////////////////////////////////////////////////////////////
+size_t EsoTwistD3Q27SparseData::getNX2() const
+{
+   return NX2;
+}
+//////////////////////////////////////////////////////////////////////////
+size_t EsoTwistD3Q27SparseData::getNX3() const
+{
+   return NX3;
+}
+//////////////////////////////////////////////////////////////////////////
+EsoTwistD3Q27SparseData::SparseDataPtr EsoTwistD3Q27SparseData::getLocalDistributions()
+{
+   return ld;
+}
+//////////////////////////////////////////////////////////////////////////
+EsoTwistD3Q27SparseData::SparseDataPtr EsoTwistD3Q27SparseData::getNonLocalDistributions()
+{
+   return nld;
+}
+//////////////////////////////////////////////////////////////////////////
+EsoTwistD3Q27SparseData::SparseDataPtr EsoTwistD3Q27SparseData::getZeroDistributions()
+{
+   return zd;
+}
+//////////////////////////////////////////////////////////////////////////
+void EsoTwistD3Q27SparseData::setSize( int nx[4] )
+{
+   nx1 = 13;
+   nx2 = nx[0];
+   nx3 = nx[1];
+   nx4 = nx[2];
+   nx5 = nx[3];
+}
+//////////////////////////////////////////////////////////////////////////
+
+
+
+
diff --git a/source/VirtualFluidsCore/Data/EsoTwistD3Q27SparseData.h b/source/VirtualFluidsCore/Data/EsoTwistD3Q27SparseData.h
new file mode 100644
index 0000000000000000000000000000000000000000..9798891d90e244989ab83c68a29aec091e260296
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/EsoTwistD3Q27SparseData.h
@@ -0,0 +1,105 @@
+#ifndef EsoTwistD3Q27SparseData_h
+#define EsoTwistD3Q27SparseData_h
+
+#include "EsoTwist3D.h"
+#include <D3Q27System.h>
+
+#include <boost/unordered_map.hpp>
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/base_object.hpp>
+
+class EsoTwistD3Q27SparseData;
+typedef boost::shared_ptr<EsoTwistD3Q27SparseData> EsoTwistD3Q27SparseDataPtr;
+
+class EsoTwistD3Q27SparseData : public EsoTwist3D
+{
+public:
+   typedef boost::unordered_map<size_t, LBMReal> SparseData;
+   typedef boost::shared_ptr<SparseData> SparseDataPtr;
+   //typedef std::map<size_t, LBMReal> SparseData;
+   //typedef boost::shared_ptr<SparseData> SparseDataPtr;
+public:
+   EsoTwistD3Q27SparseData();
+   EsoTwistD3Q27SparseData(size_t ibx[3], size_t nx[3], size_t level, double value );
+   //////////////////////////////////////////////////////////////////////////
+   ~EsoTwistD3Q27SparseData();
+   //////////////////////////////////////////////////////////////////////////
+   void swap();
+   //////////////////////////////////////////////////////////////////////////
+   virtual void getDistribution( LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistribution(const LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   ////////////////////////////////////////////////////////////////////////
+   virtual void getDistributionInv( LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInv(const LBMReal* const f, size_t x1, size_t x2, size_t x3);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual LBMReal getDistributionInvForDirection(size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInvForDirection(const LBMReal* const f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual void setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3, unsigned long int direction);
+   //////////////////////////////////////////////////////////////////////////
+   virtual LBMReal getDistributionForDirection(size_t x1, size_t x2, size_t x3, int direction);
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX1() const;
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX2() const;
+   //////////////////////////////////////////////////////////////////////////
+   size_t getNX3() const;
+   ////////////////////////////////////////////////////////////////////////
+   SparseDataPtr getLocalDistributions();
+   //////////////////////////////////////////////////////////////////////////
+   SparseDataPtr getNonLocalDistributions();
+   //////////////////////////////////////////////////////////////////////////
+   SparseDataPtr getZeroDistributions();
+   //////////////////////////////////////////////////////////////////////////
+   static void setSize(int nx[]);
+   //////////////////////////////////////////////////////////////////////////
+   inline size_t index4D(size_t x1, size_t x2, size_t x3, size_t x4)
+   {
+      //return nx1*(nx2*(nx3*x4+x3)+x2)+x1;
+      return nx1*(nx2*(nx3*(nx4*level+(x4+ox3))+(x3+ox2))+(x2+ox1))+x1;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   inline size_t index3D(size_t x1, size_t x2, size_t x3)
+   {
+      //return  nx2 * ( nx3 * x3 + x2) + x1 ;
+      return nx2*(nx3*(nx4*level+(x3+ox3))+(x2+ox2))+(x1+ox1);
+   }
+
+protected:
+   static SparseData localDistributions;
+   static SparseData nonLocalDistributions;
+   static SparseData zeroDistributions;
+   SparseDataPtr ld;  //local distributions;
+   SparseDataPtr nld; //non local distributions;
+   SparseDataPtr zd;  //zero distributions;
+   size_t NX1, NX2, NX3;
+   static size_t nx1, nx2, nx3, nx4, nx5;
+   size_t ox1, ox2, ox3;
+   size_t level;
+
+
+
+
+   //friend class boost::serialization::access;
+   //template<class Archive>
+   //void serialize(Archive & ar, const unsigned int version)
+   //{
+   //   ar & boost::serialization::base_object< EsoTwist3D >(*this);
+   //   ar & NX1; 
+   //   ar & NX2; 
+   //   ar & NX3;
+   //   ar &  localDistributions;
+   //   ar &  nonLocalDistributions;
+   //   ar &  zeroDistributions;
+   //}
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp b/source/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0de7648cae41de1e926f9f8f1e9ff5454c65c077
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp
@@ -0,0 +1,92 @@
+#include "EsoTwistD3Q27System.h"
+
+//index                                                              0   1   2   3   4   5  6   7   8    9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  
+//f:                                                                 E,  W,  N,  S,  T,  B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW ZERO
+const int EsoTwistD3Q27System::ETX1[EsoTwistD3Q27System::ENDF+1] = { 0,  1,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  0,  1,  0 };
+const int EsoTwistD3Q27System::ETX2[EsoTwistD3Q27System::ENDF+1] = { 0,  0,  0,  1,  0,  0,  0,  1,  0, -1,  0,  0,  0,  0,  0,  1, -1,  0,  0, -1,  0,  1,  0, -1,  0,  1,  0 };
+const int EsoTwistD3Q27System::ETX3[EsoTwistD3Q27System::ENDF+1] = { 0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0, -1,  0,  1,  1,  0,  0, -1,  0, -1,  0,  1,  0,  1,  0 };
+
+const int EsoTwistD3Q27System::etINVDIR[EsoTwistD3Q27System::ENDF+1] = { D3Q27System::INV_E,   
+                                                                           D3Q27System::INV_W,  
+                                                                           D3Q27System::INV_N,  
+                                                                           D3Q27System::INV_S,  
+                                                                           D3Q27System::INV_T,  
+                                                                           D3Q27System::INV_B,  
+                                                                           D3Q27System::INV_NE, 
+                                                                           D3Q27System::INV_SW, 
+                                                                           D3Q27System::INV_SE, 
+                                                                           D3Q27System::INV_NW,
+                                                                           D3Q27System::INV_TE, 
+                                                                           D3Q27System::INV_BW, 
+                                                                           D3Q27System::INV_BE, 
+                                                                           D3Q27System::INV_TW, 
+                                                                           D3Q27System::INV_TN, 
+                                                                           D3Q27System::INV_BS, 
+                                                                           D3Q27System::INV_BN, 
+                                                                           D3Q27System::INV_TS, 
+                                                                           D3Q27System::INV_TNE,
+                                                                           D3Q27System::INV_TNW,
+                                                                           D3Q27System::INV_TSE,
+                                                                           D3Q27System::INV_TSW,
+                                                                           D3Q27System::INV_BNE,
+                                                                           D3Q27System::INV_BNW,
+                                                                           D3Q27System::INV_BSE,
+                                                                           D3Q27System::INV_BSW,
+                                                                           D3Q27System::ZERO};
+
+const unsigned long int EsoTwistD3Q27System::etDIR[EsoTwistD3Q27System::ENDF+1] = { etE,   
+                                                                                    etW,  
+                                                                                    etN,  
+                                                                                    etS,  
+                                                                                    etT,  
+                                                                                    etB,  
+                                                                                    etNE, 
+                                                                                    etSW, 
+                                                                                    etSE, 
+                                                                                    etNW,
+                                                                                    etTE, 
+                                                                                    etBW, 
+                                                                                    etBE, 
+                                                                                    etTW, 
+                                                                                    etTN, 
+                                                                                    etBS, 
+                                                                                    etBN, 
+                                                                                    etTS,
+                                                                                    etTNE,
+                                                                                    etTNW,
+                                                                                    etTSE,
+                                                                                    etTSW,
+                                                                                    etBNE,
+                                                                                    etBNW,
+                                                                                    etBSE,
+                                                                                    etBSW,
+                                                                                    etZERO};
+
+ const unsigned long int EsoTwistD3Q27System::etZERO = 1;/*f0 */
+ const unsigned long int EsoTwistD3Q27System::etE =  2;    /*f1 */
+ const unsigned long int EsoTwistD3Q27System::etW =  4;    /*f2 */
+ const unsigned long int EsoTwistD3Q27System::etN =  8;    /*f3 */
+ const unsigned long int EsoTwistD3Q27System::etS =  16;   /*f4 */
+ const unsigned long int EsoTwistD3Q27System::etT =  32;    /*f5 */
+ const unsigned long int EsoTwistD3Q27System::etB =  64;   /*f6 */
+ const unsigned long int EsoTwistD3Q27System::etNE = 128;  /*f7 */
+ const unsigned long int EsoTwistD3Q27System::etSW = 256;  /*f8 */
+ const unsigned long int EsoTwistD3Q27System::etSE = 512;  /*f9 */
+ const unsigned long int EsoTwistD3Q27System::etNW = 1024;  /*f10*/
+ const unsigned long int EsoTwistD3Q27System::etTE = 2048;  /*f11*/
+ const unsigned long int EsoTwistD3Q27System::etBW = 4096;  /*f12*/
+ const unsigned long int EsoTwistD3Q27System::etBE = 8192;  /*f13*/
+ const unsigned long int EsoTwistD3Q27System::etTW = 16384;  /*f14*/
+ const unsigned long int EsoTwistD3Q27System::etTN = 32768;  /*f15*/
+ const unsigned long int EsoTwistD3Q27System::etBS = 65536;  /*f16*/
+ const unsigned long int EsoTwistD3Q27System::etBN = 131072;  /*f17*/
+ const unsigned long int EsoTwistD3Q27System::etTS = 262144;  /*f18*/
+ const unsigned long int EsoTwistD3Q27System::etTNE = 524288;
+ const unsigned long int EsoTwistD3Q27System::etTNW = 1048576;
+ const unsigned long int EsoTwistD3Q27System::etTSE = 2097152;
+ const unsigned long int EsoTwistD3Q27System::etTSW = 4194304;
+ const unsigned long int EsoTwistD3Q27System::etBNE = 8388608;
+ const unsigned long int EsoTwistD3Q27System::etBNW = 16777216;
+ const unsigned long int EsoTwistD3Q27System::etBSE = 33554432;
+const unsigned long int EsoTwistD3Q27System::etBSW = 67108864;
+
diff --git a/source/VirtualFluidsCore/Data/EsoTwistD3Q27System.h b/source/VirtualFluidsCore/Data/EsoTwistD3Q27System.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5924623daff2d9e485a086140a9e96ceb5d0714
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/EsoTwistD3Q27System.h
@@ -0,0 +1,108 @@
+#ifndef ESOTWISTD3Q27SYSTEM_H
+#define ESOTWISTD3Q27SYSTEM_H
+
+#include "D3Q27System.h"
+
+struct EsoTwistD3Q27System
+{
+   const static int FSTARTDIR = D3Q27System::FSTARTDIR;
+   const static int FENDDIR   = D3Q27System::FENDDIR;   //gellerstyle: meint alle frichtungen OHNE f0
+
+   const static int STARTF    = D3Q27System::STARTF;
+   const static int ENDF  		= D3Q27System::ENDF;
+
+   const static int STARTDIR  = D3Q27System::STARTDIR;
+   const static int ENDDIR		= D3Q27System::ENDDIR;
+
+   static const int ZERO = D3Q27System::ZERO;/*f0 */
+   static const int E =  D3Q27System::E;    /*f1 */ 
+   static const int W =  D3Q27System::W;    /*f2 */ 
+   static const int N =  D3Q27System::N;    /*f3 */ 
+   static const int S =  D3Q27System::S;   /*f4 */ 
+   static const int T =  D3Q27System::T;    /*f5 */ 
+   static const int B =  D3Q27System::B;   /*f6 */ 
+   static const int NE = D3Q27System::NE;  /*f7 */ 
+   static const int SW = D3Q27System::SW;  /*f8 */ 
+   static const int SE = D3Q27System::SE;  /*f9 */ 
+   static const int NW = D3Q27System::NW;  /*f10*/ 
+   static const int TE = D3Q27System::TE;  /*f11*/ 
+   static const int BW = D3Q27System::BW;  /*f12*/ 
+   static const int BE = D3Q27System::BE;  /*f13*/ 
+   static const int TW = D3Q27System::TW;  /*f14*/ 
+   static const int TN = D3Q27System::TN;  /*f15*/ 
+   static const int BS = D3Q27System::BS;  /*f16*/ 
+   static const int BN = D3Q27System::BN;  /*f17*/ 
+   static const int TS = D3Q27System::TS;  /*f18*/ 
+   static const int TNE = D3Q27System::TNE;
+   static const int TNW = D3Q27System::TNW;
+   static const int TSE = D3Q27System::TSE;
+   static const int TSW = D3Q27System::TSW;
+   static const int BNE = D3Q27System::BNE;
+   static const int BNW = D3Q27System::BNW;
+   static const int BSE = D3Q27System::BSE;
+   static const int BSW = D3Q27System::BSW;
+ 
+
+   static const int INV_E   = D3Q27System::W;  
+   static const int INV_W   = D3Q27System::E;  
+   static const int INV_N   = D3Q27System::S;  
+   static const int INV_S   = D3Q27System::N;  
+   static const int INV_T   = D3Q27System::B;  
+   static const int INV_B   = D3Q27System::T;  
+   static const int INV_NE  = D3Q27System::SW; 
+   static const int INV_SW  = D3Q27System::NE; 
+   static const int INV_SE  = D3Q27System::NW; 
+   static const int INV_NW  = D3Q27System::SE; 
+   static const int INV_TE  = D3Q27System::BW; 
+   static const int INV_BW  = D3Q27System::TE; 
+   static const int INV_BE  = D3Q27System::TW; 
+   static const int INV_TW  = D3Q27System::BE; 
+   static const int INV_TN  = D3Q27System::BS; 
+   static const int INV_BS  = D3Q27System::TN; 
+   static const int INV_BN  = D3Q27System::TS; 
+   static const int INV_TS  = D3Q27System::BN; 
+   static const int INV_TNE = D3Q27System::BSW;
+   static const int INV_TNW = D3Q27System::BSE;
+   static const int INV_TSE = D3Q27System::BNW;
+   static const int INV_TSW = D3Q27System::BNE;
+   static const int INV_BNE = D3Q27System::TSW;
+   static const int INV_BNW = D3Q27System::TSE;
+   static const int INV_BSE = D3Q27System::TNW;
+   static const int INV_BSW = D3Q27System::TNE;
+
+   static const unsigned long int etZERO;// 1;/*f0 */
+   static const unsigned long int etE;//  2;    /*f1 */
+   static const unsigned long int etW;//  4;    /*f2 */
+   static const unsigned long int etN;//  8;    /*f3 */
+   static const unsigned long int etS;//  16;   /*f4 */
+   static const unsigned long int etT;//  32;    /*f5 */
+   static const unsigned long int etB;//  64;   /*f6 */
+   static const unsigned long int etNE;// 128;  /*f7 */
+   static const unsigned long int etSW;// 256;  /*f8 */
+   static const unsigned long int etSE;// 512;  /*f9 */
+   static const unsigned long int etNW;// 1024;  /*f10*/
+   static const unsigned long int etTE;// 2048;  /*f11*/
+   static const unsigned long int etBW;// 4096;  /*f12*/
+   static const unsigned long int etBE;// 8192;  /*f13*/
+   static const unsigned long int etTW;// 16384;  /*f14*/
+   static const unsigned long int etTN;// 32768;  /*f15*/
+   static const unsigned long int etBS;// 65536;  /*f16*/
+   static const unsigned long int etBN;// 131072;  /*f17*/
+   static const unsigned long int etTS;// 262144;  /*f18*/
+   static const unsigned long int etTNE;// 524288;
+   static const unsigned long int etTNW;// 1048576;
+   static const unsigned long int etTSE;// 2097152;
+   static const unsigned long int etTSW;// 4194304;
+   static const unsigned long int etBNE;// 8388608;
+   static const unsigned long int etBNW;// 16777216;
+   static const unsigned long int etBSE;// 33554432;
+   static const unsigned long int etBSW;// = 67108864;
+
+   const static int ETX1[ENDF+1];
+   const static int ETX2[ENDF+1];
+   const static int ETX3[ENDF+1];
+   const static int etINVDIR[ENDF+1]; 
+   const static unsigned long int etDIR[ENDF+1]; 
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Data/SparseMatrix3D.cpp b/source/VirtualFluidsCore/Data/SparseMatrix3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b624bf691ab7bc1c5b141a36e37615d08fbeb515
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/SparseMatrix3D.cpp
@@ -0,0 +1,39 @@
+#include "SparseMatrix3D.h"
+
+
+size_t SparseMatrix3D::nx1 = 0;
+size_t SparseMatrix3D::nx2 = 0;
+size_t SparseMatrix3D::nx3 = 0;
+//////////////////////////////////////////////////////////////////////////
+SparseMatrix3D::SparseMatrix3D()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+SparseMatrix3D::~SparseMatrix3D()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+SparseMatrix3DPtr SparseMatrix3D::getInstance()
+{
+   if( !SparseMatrix3D::instance )
+      SparseMatrix3D::instance = SparseMatrix3DPtr(new SparseMatrix3D());
+   return SparseMatrix3D::instance;
+}
+//////////////////////////////////////////////////////////////////////////
+void SparseMatrix3D::setDimensions(size_t nx1, size_t nx2, size_t nx3) 
+{
+   SparseMatrix3D::nx1 = nx1;
+   SparseMatrix3D::nx2 = nx2;
+   SparseMatrix3D::nx3 = nx3;
+}
+//////////////////////////////////////////////////////////////////////////
+void SparseMatrix3D::getDimensions(size_t& nx1, size_t& nx2, size_t& nx3) 
+{
+   nx1 = SparseMatrix3D::nx1;
+   nx2 = SparseMatrix3D::nx2;
+   nx3 = SparseMatrix3D::nx3;
+}
+/////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/Data/SparseMatrix3D.h b/source/VirtualFluidsCore/Data/SparseMatrix3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa4ad47da33577f256f5b070985e6a46bd5ba263
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/SparseMatrix3D.h
@@ -0,0 +1,29 @@
+#ifndef SparseMatrix3D_h
+#define SparseMatrix3D_h
+
+#include <boost/unordered_map.hpp>
+
+#include <boost/shared_ptr.hpp>
+class SparseMatrix3D;
+typedef boost::shared_ptr<SparseMatrix3D> SparseMatrix3DPtr;
+
+class SparseMatrix3D
+{
+public:
+   static SparseMatrix3DPtr getInstance();
+   static void setDimensions(size_t nx1, size_t nx2, size_t nx3);
+   static void getDimensions(size_t& nx1, size_t& nx2, size_t& nx3);
+   virtual ~SparseMatrix3D();
+   //////////////////////////////////////////////////////////////////////////
+   inline size_t index(size_t x1, size_t x2, size_t x3)
+   {
+      return  nx1 * ( nx2 * x3 + x2) + x1 ;
+   }
+protected:
+private:
+   SparseMatrix3D();
+   static SparseMatrix3DPtr instance;
+   static size_t nx1, nx2, nx3;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Data/SparseMatrix4D.cpp b/source/VirtualFluidsCore/Data/SparseMatrix4D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4ebbf7f6b57426d4d062ee168db849e5e04bdb81
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/SparseMatrix4D.cpp
@@ -0,0 +1,42 @@
+#include "SparseMatrix4D.h"
+
+
+size_t SparseMatrix4D::nx1 = 0;
+size_t SparseMatrix4D::nx2 = 0;
+size_t SparseMatrix4D::nx3 = 0;
+size_t SparseMatrix4D::nx4 = 0;
+//////////////////////////////////////////////////////////////////////////
+SparseMatrix4D::SparseMatrix4D()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+SparseMatrix4D::~SparseMatrix4D()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+SparseMatrix4DPtr SparseMatrix4D::getInstance()
+{
+   if( !SparseMatrix4D::instance )
+      SparseMatrix4D::instance = SparseMatrix4DPtr(new SparseMatrix4D());
+   return SparseMatrix4D::instance;
+}
+//////////////////////////////////////////////////////////////////////////
+void SparseMatrix4D::setDimensions(size_t nx1, size_t nx2, size_t nx3, size_t nx4) 
+{
+   SparseMatrix4D::nx1 = nx1;
+   SparseMatrix4D::nx2 = nx2;
+   SparseMatrix4D::nx3 = nx3;
+   SparseMatrix4D::nx4 = nx4;
+}
+//////////////////////////////////////////////////////////////////////////
+void SparseMatrix4D::getDimensions(size_t& nx1, size_t& nx2, size_t& nx3, size_t& nx4) 
+{
+   nx1 = SparseMatrix4D::nx1;
+   nx2 = SparseMatrix4D::nx2;
+   nx3 = SparseMatrix4D::nx3;
+   nx4 = SparseMatrix4D::nx4;
+}
+/////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/Data/SparseMatrix4D.h b/source/VirtualFluidsCore/Data/SparseMatrix4D.h
new file mode 100644
index 0000000000000000000000000000000000000000..011112472ed142611d507a5ffb4b259df7cb258d
--- /dev/null
+++ b/source/VirtualFluidsCore/Data/SparseMatrix4D.h
@@ -0,0 +1,29 @@
+#ifndef SparseMatrix4D_h
+#define SparseMatrix4D_h
+
+#include <boost/unordered_map.hpp>
+
+#include <boost/shared_ptr.hpp>
+class SparseMatrix4D;
+typedef boost::shared_ptr<SparseMatrix4D> SparseMatrix4DPtr;
+
+class SparseMatrix4D
+{
+public:
+   static SparseMatrix4DPtr getInstance();
+   static void setDimensions(size_t nx1, size_t nx2, size_t nx3, size_t x4);
+   static void getDimensions(size_t& nx1, size_t& nx2, size_t& nx3, size_t& x4);
+   virtual ~SparseMatrix4D();
+   //////////////////////////////////////////////////////////////////////////
+   inline size_t index(size_t x1, size_t x2, size_t x3, size_t x4)
+   {
+      return nx4*(nx3*(nx2*x1+x2)+x3)+x4;
+   }
+protected:
+private:
+   SparseMatrix4D();
+   static SparseMatrix4DPtr instance;
+   static size_t nx1, nx2, nx3, nx4;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/FETOL/CMakePackage.txt b/source/VirtualFluidsCore/FETOL/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/FETOL/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/FETOL/FETOLCalculator.cpp b/source/VirtualFluidsCore/FETOL/FETOLCalculator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..60e37f0d0fd950d52bde55b7301de6edeccccdaf
--- /dev/null
+++ b/source/VirtualFluidsCore/FETOL/FETOLCalculator.cpp
@@ -0,0 +1,384 @@
+#if defined VF_FETOL
+
+#if defined(_WIN32) || defined(_WIN64)
+   #include <winsock2.h>
+#endif
+
+#include "FETOLCalculator.h"
+#include <basics/utilities/UbException.h>
+#include <D3Q27OffsetInterpolationProcessor.h>
+#include <FETOLSetConnectorsBlockVisitor.h>
+
+//problem with Windows, by Unix should be uncomment 
+#include <JM.h>
+using namespace fetol;
+
+FETOLCalculator::FETOLCalculator()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+FETOLCalculator::FETOLCalculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread) : 
+   Calculator(grid, sync, mainThread)
+
+{
+   remoteMPIConns.resize(maxLevel+1);
+   remoteBondConns.resize(maxLevel+1);
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCalculator::calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error)
+{
+   UBLOG(logDEBUG1, "FETOLCalculator::calculate() - started");
+   try
+   {
+      int anzLevel = maxLevel-minLevel+1;
+
+      int minInitLevel       = minLevel;
+      int maxInitLevel       = maxLevel-minLevel;
+      int straightStartLevel = minInitLevel;
+      int internalIterations = 1 << (maxInitLevel-minInitLevel);
+      int forwardStartLevel;
+      int threshold;
+      int startStep = int(grid->getTimeStep())+1;
+
+      if (startStep > 1)
+      {
+         vector<int> cs;
+         cs.push_back(startStep);
+         Communicator::getInstance()->broadcastInts(cs);
+         startStep = cs[0];
+      }
+
+      //UBLOG(logINFO, "startStep="<<startStep);
+      int anzCalcSteps = static_cast<int>(endTime);
+#ifdef TIMING
+      UbTimer timer;
+      double time[6];
+#endif
+
+      //////////////////////////////////////////////////////////////////////////
+      //      UBLOG(logINFO, "Number of connectors = " <<this->localConns[0].size());
+      //////////////////////////////////////////////////////////////////////////
+
+      
+
+      for(calcStep=startStep; calcStep<=anzCalcSteps; calcStep++)
+      {
+
+       
+
+         //exchange data between blocks for visualization
+         //sync->wait();
+         ////if(visScheduler->isDue((double)(calcStep-1)))
+         ////{
+         //   //exchangeBlockData(minInitLevel, maxInitLevel, true);
+         ////}
+
+         ////wait for write dump files
+         //sync->wait();
+         //write dump 
+         if (mainThread) 
+         {
+            try
+            {
+               UBLOG(logDEBUG1,"JM::getApplicationState(): "<<JM::getApplicationState());
+               grid->doPostProcess((double)(calcStep-1));
+            }
+            catch (...)
+            {
+               ifRestart(straightStartLevel, maxInitLevel, false);
+            }
+         }
+            sync->wait();
+
+
+         //////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+         UBLOG(logINFO, "calcStep = " <<calcStep);
+#endif
+         UBLOG(logDEBUG1, "FETOLCalculator::calculate() calcStep = " <<calcStep);
+         //////////////////////////////////////////////////////////////////////////
+
+         for(int staggeredStep=1; staggeredStep<=internalIterations; staggeredStep++)
+         {
+            forwardStartLevel = straightStartLevel;
+            if(staggeredStep == internalIterations) straightStartLevel = minInitLevel;
+            else
+            {
+               for(straightStartLevel=maxInitLevel,threshold=1;
+                  (staggeredStep&threshold)!=threshold; straightStartLevel--,threshold<<=1);
+            }
+            //////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            timer.resetAndStart();
+#endif
+            //////////////////////////////////////////////////////////////////////////
+            calculateBlocks(straightStartLevel, maxInitLevel);
+            //calculateBlocks(minInitLevel, maxInitLevel, staggeredStep);
+            //////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[0] = timer.stop();
+            //UBLOG(logINFO, "calculateBlocks time = " <<time);
+#endif
+            //////////////////////////////////////////////////////////////////////////
+
+            //exchange data between blocks
+            //Sleep(10000);
+            try
+            {
+               UBLOG(logDEBUG1,"JM::getApplicationState(): "<<JM::getApplicationState());
+               exchangeFETOLBlockData(straightStartLevel, maxInitLevel, false);
+            }
+            catch (...)
+            {
+               ifRestart(straightStartLevel, maxInitLevel, false);
+            }
+
+            UBLOG(logDEBUG1,"JM::getApplicationState(): "<<JM::getApplicationState());
+
+            //////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[1] = timer.stop();
+            //UBLOG(logINFO, "exchangeBlockData time = " <<time);
+#endif
+            //////////////////////////////////////////////////////////////////////////
+
+            applyBCs(straightStartLevel, maxInitLevel);
+            //////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[2] = timer.stop();
+            //UBLOG(logINFO, "applyBCs time = " <<time);
+#endif
+            //////////////////////////////////////////////////////////////////////////
+
+            //swap distributions in kernel
+            swapDistributions(straightStartLevel, maxInitLevel);
+            //////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[3] = timer.stop();
+            //UBLOG(logINFO, "swapDistributions time = " <<time);
+#endif
+            //////////////////////////////////////////////////////////////////////////
+
+//            if (refinement)
+//            {
+//               //exchange data between blocks for grid refinement
+//               //exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+//               if(straightStartLevel<maxInitLevel)
+//                  exchangeBlockData(straightStartLevel, maxInitLevel, true);
+//               //exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+//               //////////////////////////////////////////////////////////////////////////
+//#ifdef TIMING
+//               time[4] = timer.stop();
+//               UBLOG(logINFO, "refinement exchangeBlockData time = " <<time);
+//#endif
+//               //////////////////////////////////////////////////////////////////////////
+//               //now ghost nodes have actual values
+//               //interpolation of interface nodes between grid levels
+//               interpolation(straightStartLevel, maxInitLevel);
+//               //////////////////////////////////////////////////////////////////////////
+//#ifdef TIMING
+//               time[5] = timer.stop();
+//               UBLOG(logINFO, "refinement interpolation time = " <<time);
+//#endif
+//               //////////////////////////////////////////////////////////////////////////
+//            }
+
+         }
+         //exchange data between blocks for visualization
+         if(mainThread) visScheduler->isDue((double)(calcStep-1));
+         if((int)visScheduler->getNextDueTime() == calcStep)
+         {
+            try
+            {
+               UBLOG(logDEBUG1,"JM::getApplicationState(): "<<JM::getApplicationState());
+               exchangeFETOLBlockData(straightStartLevel, maxInitLevel, true);
+            }
+            catch (...)
+            {
+               ifRestart(straightStartLevel, maxInitLevel, false);
+            }
+         }
+         //now ghost nodes have actual values
+
+      }
+      error = boost::exception_ptr();
+      UBLOG(logDEBUG1, "FETOLCalculator::calculate() - stoped");
+   }
+   catch( std::exception& e )
+   {
+      //error = boost::current_exception();
+      UBLOG(logERROR, e.what());
+      UBLOG(logERROR, " step = "<<calcStep);
+      exit(EXIT_FAILURE);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+void FETOLCalculator::initRemoteConnectors()
+{
+   Calculator::initRemoteConnectors();
+   initFETOLConnectors();
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCalculator::initFETOLConnectors()
+{
+   UBLOG(logDEBUG5, "FETOLCalculator::initFETOLConnectors():start");
+   for(int l = minLevel; l <= maxLevel; l++)
+   {
+      BOOST_FOREACH(Block3DConnectorPtr c, remoteConns[l])
+      {
+         if(c->getTransmitterType() == Block3DConnector::MPI)
+         {
+            remoteMPIConns[l].push_back(c);
+         }
+         else if(c->getTransmitterType() == Block3DConnector::BOND)
+         {
+            remoteBondConns[l].push_back(c);
+         }
+         else
+         {
+            UB_THROW( UbException(UB_EXARGS,"Transmitter type isn't exist!"));
+         }
+      }
+   }
+   UBLOG(logDEBUG5, "FETOLCalculator::initFETOLConnectors():remoteMPIConns.size = "<<remoteMPIConns[0].size());
+   UBLOG(logDEBUG5, "FETOLCalculator::initFETOLConnectors():remoteBondConns.size = "<<remoteBondConns[0].size());
+   UBLOG(logDEBUG5, "FETOLCalculator::initFETOLConnectors():end");
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCalculator::exchangeFETOLBlockData(int startLevel, int maxInitLevel, bool invStep)
+{
+   UBLOG(logDEBUG5, "FETOLCalculator::exchangeFETOLBlockData():start");
+   sync->wait();
+   UBLOG(logDEBUG5, "FETOLCalculator::exchangeFETOLBlockData():localConns:start");
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(localConns[level]);
+
+      connectorsSend(localConns[level], invStep);
+
+      connectorsReceive(localConns[level], invStep);
+   }
+   UBLOG(logDEBUG5, "FETOLCalculator::exchangeFETOLBlockData():localConns:end");
+   sync->wait();
+
+   UBLOG(logDEBUG5, "FETOLCalculator::exchangeFETOLBlockData():remoteMPIConns:start");
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(remoteMPIConns[level]);
+
+      connectorsSend(remoteMPIConns[level], invStep);
+
+      connectorsReceive(remoteMPIConns[level], invStep);
+   }
+   UBLOG(logDEBUG5, "FETOLCalculator::exchangeFETOLBlockData():remoteMPIConns:end");
+
+   UBLOG(logDEBUG5, "FETOLCalculator::exchangeFETOLBlockData():remoteBondConns:start");
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(remoteBondConns[level]);
+
+      connectorsSend(remoteBondConns[level], invStep);
+
+      connectorsReceive(remoteBondConns[level], invStep);
+   }
+   UBLOG(logDEBUG5, "FETOLCalculator::exchangeFETOLBlockData():remoteBondConns:end");
+   UBLOG(logDEBUG5, "FETOLCalculator::exchangeFETOLBlockData():end");
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCalculator::ifRestart(int startLevel, int maxInitLevel, bool invStep)
+{
+   UBLOG(logINFO, "before paused");
+   while (JM::getApplicationState() != paused)
+   {
+      ; //NOP
+   }
+
+   UBLOG(logINFO,"JM::getApplicationState(): "<<JM::getApplicationState());
+
+   while (JM::getApplicationState() == paused) 
+   {
+      ; //NOP
+   }
+   UBLOG(logINFO, "after paused");
+   deleteConnectors(remoteConns);
+   deleteConnectors(remoteMPIConns);
+   deleteConnectors(remoteBondConns);
+   grid->deleteConnectors();
+   D3Q27InterpolationProcessorPtr iProcessor(new D3Q27OffsetInterpolationProcessor());
+   CommunicatorPtr comm = FETOLCommunicator::getInstance();
+   double nueLB=1;
+   FETOLSetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
+   grid->accept( setConnsVisitor );
+   initRemoteConnectors();
+   vector<int> cs;
+   cs.push_back(calcStep);
+   Communicator::getInstance()->broadcastInts(cs);
+   exchangeFETOLBlockData(startLevel, maxInitLevel, false);
+   //UBLOG(logINFO,"new exchange JM::getApplicationState(): "<<JM::getApplicationState());
+}
+
+//////////////////////////////////////////////////////////////////////////
+//void FETOLCalculator::connectorsPrepare(std::vector< Block3DConnectorPtr >& connectors)
+//{
+//   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+//   {
+//      c->prepareForReceive();
+//      c->prepareForSend();
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void FETOLCalculator::connectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+//{
+//   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+//   {
+//      c->setInvStep(invStep);
+//      c->fillSendVectors();
+//      c->sendVectors();
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void FETOLCalculator::connectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+//{
+//   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+//   {
+//      c->receiveVectors();
+//      c->setInvStep(invStep);
+//      c->distributeReceiveVectors();
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void FETOLCalculator::bondConnectorsPrepare(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+//{
+//   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+//   {
+//      c->prepareForReceive();
+//      c->prepareForSend();
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void FETOLCalculator::bondConnectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+//{
+//   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+//   {
+//      c->setInvStep(invStep);
+//      c->fillSendVectors();
+//      c->sendVectors();
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void FETOLCalculator::bondConnectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+//{
+//   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+//   {
+//      c->receiveVectors();
+//      c->setInvStep(invStep);
+//      c->distributeReceiveVectors();
+//   }
+//}
+
+//////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/source/VirtualFluidsCore/FETOL/FETOLCalculator.h b/source/VirtualFluidsCore/FETOL/FETOLCalculator.h
new file mode 100644
index 0000000000000000000000000000000000000000..a28433938600b260960fa13addbfc18534be12ec
--- /dev/null
+++ b/source/VirtualFluidsCore/FETOL/FETOLCalculator.h
@@ -0,0 +1,39 @@
+#if defined VF_FETOL
+
+#ifndef FETOLCALCULATOR_H
+#define FETOLCALCULATOR_H
+
+#include "Calculator.h"
+
+
+class FETOLCalculator;
+typedef boost::shared_ptr<FETOLCalculator> FETOLCalculator2Ptr;
+
+#include "CalculationManager.h"
+
+class FETOLCalculator : public Calculator
+{
+public:
+   FETOLCalculator();
+   FETOLCalculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread = true);
+   virtual ~FETOLCalculator(){}
+   void calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error);
+protected:
+   void initRemoteConnectors();
+   void exchangeFETOLBlockData(int startLevel, int maxInitLevel, bool invStep);
+   //void connectorsPrepare(std::vector< Block3DConnectorPtr >& connectors);
+   //void connectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   //void connectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   //void bondConnectorsPrepare(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   //void bondConnectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   //void bondConnectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   void initFETOLConnectors();
+   void ifRestart(int startLevel, int maxInitLevel, bool invStep);
+private:
+   std::vector< std::vector< Block3DConnectorPtr > > remoteMPIConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteBondConns;
+};
+
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/FETOL/FETOLCommunicator.cpp b/source/VirtualFluidsCore/FETOL/FETOLCommunicator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..046bfc0f205c9e99da82a90aa258bd8992cbd61a
--- /dev/null
+++ b/source/VirtualFluidsCore/FETOL/FETOLCommunicator.cpp
@@ -0,0 +1,260 @@
+#if defined VF_MPI && defined VF_FETOL
+
+#include "FETOLCommunicator.h"
+#include <MPICommunicator.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/utilities/UbException.h>
+
+#include <boost/foreach.hpp>
+
+#include <fbond.h>
+#include <Version.h>
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////
+FETOLCommunicator::FETOLCommunicator()
+{
+   bond::init();
+
+   mpi_comm = MPICommunicator::getInstance();
+   mpi_rank = mpi_comm->getProcessID();
+   mpi_size = mpi_comm->getNumberOfProcesses();
+
+   BID = bond::bundleID();
+   numberOfBundles = bond::bundleCount();
+   numberOfProcesses = bond::processCount();
+   PID = bond::processID();
+   bundleSizes.resize(numberOfBundles);
+   bond::bundleSizes(numberOfBundles, &bundleSizes[0]);
+
+   root = 0;
+}
+//////////////////////////////////////////////////////////////////////////
+FETOLCommunicator::~FETOLCommunicator()
+{
+   bond::finalize();
+}
+//////////////////////////////////////////////////////////////////////////
+CommunicatorPtr FETOLCommunicator::getInstance()
+{
+   if( !Communicator::instance )
+      Communicator::instance = CommunicatorPtr(new FETOLCommunicator());
+   return Communicator::instance;
+}//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getBundleID()
+{
+   return bond::bundleID();
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getNumberOfBundles()
+{
+   return bond::bundleCount();
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getBONDProcessID()
+{
+   return bond::processID();
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getBONDProcessCount()
+{
+   return bond::processCount();
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getProcessID()
+{
+   return PID;
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getProcessID(int bundle, int rank)
+{
+   return bond::processID_for_bundleID_and_MPIRank(bundle, rank);
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getNumberOfProcesses()
+{
+   return numberOfProcesses;
+}
+//////////////////////////////////////////////////////////////////////////
+void* FETOLCommunicator::getNativeCommunicator()
+{
+   return mpi_comm->getNativeCommunicator();
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getRoot() 
+{
+   return root;
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getBundleRoot() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getProcessRoot() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getNumberOfProcessesInBundle(int bundle)
+{
+   return bundleSizes[bundle];
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getMPIRank()
+{
+   return mpi_rank;
+}
+//////////////////////////////////////////////////////////////////////////
+int FETOLCommunicator::getMPICommSize()
+{
+   return mpi_size;
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCommunicator::broadcastInts(std::vector<int>& values)
+{
+   int rcount;
+
+   if (PID == root) 
+   {
+      UBLOG(logDEBUG5, "bond::send-start: "<<"Bundle ID="<<BID<<", PID="<<PID<<", MPI rank="<<mpi_rank);
+      rcount = (int)values.size();
+
+      for(int i = 1; i < numberOfProcesses; i++)
+      {
+         bond::sendComplete(&rcount, 1, MPI_INT, i, 0);
+      }
+      if (rcount > 0)
+      {
+         for(int i = 1; i < numberOfProcesses; i++)
+         {
+            bond::sendComplete(&values[0], rcount, MPI_INT, i, 0);
+         }
+      }
+      UBLOG(logDEBUG5, "bond::send-end: "<<"Bundle ID="<<BID<<", PID="<<PID<<", MPI rank="<<mpi_rank);
+   }
+   else 
+   {
+      UBLOG(logDEBUG5, "bond::receive-start: "<<"Bundle ID="<<BID<<", PID="<<PID<<", MPI rank="<<mpi_rank);
+      bond::receiveComplete(&rcount, 1, MPI_INT, root, 0);
+      if (rcount > 0)
+      {
+         values.resize(rcount);
+         bond::receiveComplete(&values[0], (int)values.size(), MPI_INT, root, 0);
+      }
+      UBLOG(logDEBUG5, "bond::receive-end: "<<"Bundle ID="<<BID<<", PID="<<PID<<", MPI rank="<<mpi_rank);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+std::vector<std::string> FETOLCommunicator::gatherStrings(const std::string& str)
+{
+   vector<string> parts;
+   vector<string> strings;
+   int scount;
+   vector<char> rbuf(1);
+   vector<int> rcounts(1);
+
+   if (PID == root)
+   {
+      rcounts.resize(numberOfProcesses - 1);
+      strings.push_back(str);
+
+      for (int i = 1; i < numberOfProcesses; i++)
+      {
+         bond::receiveComplete(&rcounts[i-1], 1, MPI_INT, i, 0);
+      }
+      for (int i = 1; i < numberOfProcesses; i++)
+      {
+         rbuf.resize(rcounts[i-1]);
+         bond::receiveComplete(&rbuf[0], rcounts[i-1], MPI_CHAR, i, 0);
+         string s(&rbuf[0], rcounts[i-1]);
+         if (s != "") strings.push_back(s);
+      }
+   }
+   else
+   {
+      scount = (int)str.length();
+      bond::sendComplete(&scount, 1, MPI_INT, root, 0);
+      bond::sendComplete((char *)str.c_str(), scount, MPI_CHAR, root, 0);
+   }
+   return strings;
+}
+//////////////////////////////////////////////////////////////////////////
+std::vector<double> FETOLCommunicator::gatherDoubles(std::vector<double>& values) 
+{
+   return mpi_comm->gatherDoubles(values);
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCommunicator::allGatherInts(std::vector<int>& svalues, std::vector<int>& rvalues)
+{
+   int scount;
+   vector<int> rbuf;
+   vector<int> rcounts;
+
+   if (PID == root)
+   {
+      rvalues.resize(0);
+      rvalues.insert(rvalues.end(), svalues.begin(), svalues.end());
+      rcounts.resize(numberOfProcesses - 1);
+
+      for (int i = 1; i < numberOfProcesses; i++)
+      {
+         bond::receiveComplete(&rcounts[i-1], 1, MPI_INT, i, 0);
+      }
+      for (int i = 1; i < numberOfProcesses; i++)
+      {
+         if(rcounts[i-1] > 0)
+         {
+            rbuf.resize(rcounts[i-1]);
+            bond::receiveComplete(&rbuf[0], rcounts[i-1], MPI_INT, i, 0);
+            rvalues.insert(rvalues.end(), rbuf.begin(), rbuf.end());
+         }
+      }
+   }
+   else
+   {
+      scount = (int)svalues.size();
+      bond::sendComplete(&scount, 1, MPI_INT, root, 0);
+      if(scount > 0)
+         bond::sendComplete(&svalues[0], scount, MPI_INT, root, 0);
+   }
+
+   if(rvalues.size() > 0)
+      broadcastInts(rvalues);
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCommunicator::sendSerializedObject(std::stringstream& ss, int target) 
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCommunicator::receiveSerializedObject(std::stringstream& ss, int source) 
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLCommunicator::barrier()
+{
+   int flag = 0;
+
+   if (PID == root)
+   {
+      for (int i = 1; i < numberOfProcesses; i++)
+      {
+         bond::receiveComplete(&flag, 1, MPI_INT, i, 0);
+      }
+
+      for (int i = 1; i < numberOfProcesses; i++)
+      {
+         bond::sendComplete(&flag, 1, MPI_INT, i, 0);
+      }
+   }
+   else
+   {
+      bond::sendComplete(&flag, 1, MPI_INT, root, 0);
+      bond::receiveComplete(&flag, 1, MPI_INT, root, 0);
+   }
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/FETOL/FETOLCommunicator.h b/source/VirtualFluidsCore/FETOL/FETOLCommunicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2cea5c5a0c9a0876f1396cea9970f748ffbe364
--- /dev/null
+++ b/source/VirtualFluidsCore/FETOL/FETOLCommunicator.h
@@ -0,0 +1,56 @@
+#if defined VF_MPI && defined VF_FETOL
+
+#ifndef FETOLCommunicator_H
+#define FETOLCommunicator_H
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include <MPICommunicator.h>
+
+#include <boost/shared_ptr.hpp>
+class FETOLCommunicator;
+typedef boost::shared_ptr<FETOLCommunicator> BondCommunicatorPtr;
+
+///\brief Communicator for agent-based framework BOND
+
+class FETOLCommunicator : public Communicator
+{
+private:
+   FETOLCommunicator();
+public:
+   ~FETOLCommunicator();
+   static CommunicatorPtr getInstance();
+   int getBundleID();
+   int getNumberOfBundles();
+   int getProcessID();
+   int getProcessID(int bundle, int rank);
+   int getNumberOfProcesses();
+   int getBONDProcessID();
+   int getBONDProcessCount();
+   int getMPIRank();
+   int getMPICommSize();
+   int getRoot();
+   int getBundleRoot();
+   int getProcessRoot();
+   int getNumberOfProcessesInBundle(int bundle);
+   void* getNativeCommunicator();
+   void broadcastInts(std::vector<int>& values);
+   std::vector<std::string> gatherStrings(const std::string& str);
+   std::vector<double> gatherDoubles(std::vector<double>& values); 
+   void allGatherInts(std::vector<int>& svalues, std::vector<int>& rvalues);
+   void sendSerializedObject(std::stringstream& ss, int target);
+   void receiveSerializedObject(std::stringstream& ss, int source);
+   void barrier();
+private:
+   CommunicatorPtr mpi_comm;
+   int mpi_rank, mpi_size;
+   int numberOfBundles, BID, numberOfProcesses, PID;
+   int root;
+   std::vector<int> bundleSizes;
+};
+
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/FETOL/FETOLSetConnectorsBlockVisitor.cpp b/source/VirtualFluidsCore/FETOL/FETOLSetConnectorsBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b23349c691edd3e4e58d022dc3b30ab2a5b045a0
--- /dev/null
+++ b/source/VirtualFluidsCore/FETOL/FETOLSetConnectorsBlockVisitor.cpp
@@ -0,0 +1,289 @@
+#if defined VF_MPI && defined VF_FETOL
+
+#include "FETOLSetConnectorsBlockVisitor.h"
+#include "D3Q27ETFullVectorConnector.h"
+#include "D3Q27ETFullDirectConnector.h"
+#include "D3Q27ETFullDirectConnector2.h"
+#include "D3Q27ETFullVectorConnector.h"
+#include "D3Q27ETCFVectorConnector.h"
+#include "D3Q27ETFCVectorConnector.h"
+#include "D3Q27ETCFOffVectorConnector.h"
+#include "D3Q27ETFCOffVectorConnector.h"
+#include "Grid3DSystem.h"
+#include "D3Q27ETDirectConnector.h"
+#include <basics/transmitter/TbTransmitterLocal.h>
+
+FETOLSetConnectorsBlockVisitor::FETOLSetConnectorsBlockVisitor(CommunicatorPtr comm, bool fullConnector, int dirs, 
+                                                               LBMReal nue, D3Q27InterpolationProcessorPtr iProcessor) :
+                                                               Block3DVisitor(0, Grid3DSystem::MAXLEVEL), 
+                                                               fullConnector(fullConnector),
+                                                               dirs(dirs),
+                                                               nue(nue),
+                                                               iProcessor(iProcessor)
+{
+   this->comm = boost::dynamic_pointer_cast<FETOLCommunicator>(comm);
+   gridBundle = this->comm->getBundleID();
+   gridRank = comm->getProcessID();
+   UBLOG(logDEBUG5, "D3Q27BondSetConnectorsBlockVisitor: gridBundle = "<<gridBundle<<" gridRank = "<<gridRank);
+}
+//////////////////////////////////////////////////////////////////////////
+FETOLSetConnectorsBlockVisitor::~FETOLSetConnectorsBlockVisitor(void)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLSetConnectorsBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if(!block) return;
+
+   //UBLOG(logDEBUG5, "D3Q27BondSetConnectorsBlockVisitor::visit() - start");
+   //gridBundle = comm->getBundleID();
+   //grid->setBundle(gridBundle);
+
+   //gridRank = comm->getProcessID();
+   //grid->setRank(gridRank);
+   
+   setSameLevelConnectors(grid, block);
+
+   //if(grid->getFinestInitializedLevel() > grid->getCoarsestInitializedLevel())
+   //   setInterpolationConnectors(grid, block);
+
+   //UBLOG(logDEBUG5, "D3Q27BondSetConnectorsBlockVisitor::visit() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLSetConnectorsBlockVisitor::setSameLevelConnectors(Grid3DPtr grid, Block3DPtr block)
+{
+   int blockBundle = block->getBundle();
+   int blockRank = block->getRank();
+   if (gridBundle == blockBundle && gridRank == blockRank && block->isActive())
+   {
+      block->clearWeight();
+      std::vector<Block3DPtr> neighbors; 
+      int ix1 = block->getX1();
+      int ix2 = block->getX2();
+      int ix3 = block->getX3();
+      int level = block->getLevel();
+
+      for( int dir = 0; dir < dirs; dir++)
+      {
+         Block3DPtr neighBlock = grid->getNeighborBlock(dir, ix1, ix2, ix3, level);
+
+         if(neighBlock)
+         {
+            int neighBlockBundle = neighBlock->getBundle();
+            int neighBlockRank = neighBlock->getRank();
+            if(blockBundle == neighBlockBundle && blockRank == neighBlockRank && neighBlock->isActive())
+            {
+               Block3DConnectorPtr connector;
+               connector = Block3DConnectorPtr(new D3Q27ETFullDirectConnector2( block, neighBlock, dir));
+               block->setConnector(connector);
+            }
+            else if(blockBundle == neighBlockBundle && blockRank != neighBlockRank && neighBlock->isActive())
+            {
+               setRemoteConnectors(block, neighBlock, dir); 
+            }
+            else if(blockBundle != neighBlockBundle && neighBlock->isActive())
+            {
+               setBundleConnectors(block, neighBlock, dir);  
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLSetConnectorsBlockVisitor::setRemoteConnectors(Block3DPtr sblock, Block3DPtr tblock, int dir)
+{
+   CreateTransmittersHelper helper;
+   CreateTransmittersHelper::TransmitterPtr sender, receiver;
+   helper.createTransmitters(sblock, tblock, dir, CreateTransmittersHelper::NONE, sender, receiver, comm, CreateTransmittersHelper::MPI2BOND);
+
+   Block3DConnectorPtr connector;
+   connector = Block3DConnectorPtr(new D3Q27ETFullVectorConnector< TbTransmitter< CbVector< LBMReal > > >(sblock, sender, receiver, dir));
+   connector->setTransmitterType(Block3DConnector::MPI);
+   UBLOG(logDEBUG5,"setTransmitterType: "<< Block3DConnector::MPI);
+   sblock->setConnector(connector);
+   UBLOG(logDEBUG5, "D3Q27BondSetConnectorsBlockVisitor::setRemoteConnectors() - sblock = "<<sblock->toString());
+}
+//////////////////////////////////////////////////////////////////////////
+void FETOLSetConnectorsBlockVisitor::setBundleConnectors(Block3DPtr sblock, Block3DPtr tblock, int dir)
+{
+   CreateTransmittersHelper helper;
+   CreateTransmittersHelper::TransmitterPtr sender, receiver;
+   bool MPIpool = true;
+   bool orthogonal = false;
+   helper.createTransmitters(sblock, tblock, dir, CreateTransmittersHelper::NONE, sender, receiver, comm, CreateTransmittersHelper::BOND);
+
+   Block3DConnectorPtr connector;
+   connector = Block3DConnectorPtr(new D3Q27ETFullVectorConnector< TbTransmitter< CbVector< LBMReal > > >(sblock, sender, receiver, dir));
+   connector->setTransmitterType(Block3DConnector::BOND);
+   UBLOG(logDEBUG5,"setTransmitterType: "<< Block3DConnector::BOND);
+   sblock->setConnector(connector);
+   UBLOG(logDEBUG5, "D3Q27BondSetConnectorsBlockVisitor::setBundleConnectors() - sblock = "<<sblock->toString());
+}
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27BondSetConnectorsBlockVisitor::setInterpolationConnectors(Grid3DPtr grid, Block3DPtr block)
+//{
+//   //int blockRank = block->getRank();
+//
+//   //search for all blocks with different ranks
+//   if (block->hasInterpolationFlagCF() && block->isActive())
+//   {
+//      int fbx1 = block->getX1() << 1;
+//      int fbx2 = block->getX2() << 1;
+//      int fbx3 = block->getX3() << 1;
+//      int level = block->getLevel() + 1;
+//
+//      if( block->hasInterpolationFlagCF(D3Q27System::E))
+//      {
+//         Block3DPtr fblockSW = grid->getBlock(fbx1+1,fbx2,fbx3,level);
+//         Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3,level);
+//         Block3DPtr fblockNW = grid->getBlock(fbx1+1,fbx2,fbx3+1,level);
+//         Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+//
+//         setInterpolationConnectors(grid, fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::E);
+//      }
+//      if( block->hasInterpolationFlagCF(D3Q27System::W))
+//      {
+//         Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3,level);
+//         Block3DPtr fblockSE = grid->getBlock(fbx1,fbx2+1,fbx3,level);
+//         Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2,fbx3+1,level);
+//         Block3DPtr fblockNE = grid->getBlock(fbx1,fbx2+1,fbx3+1,level);
+//
+//         setInterpolationConnectors(grid, fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::W);
+//      }
+//      if( block->hasInterpolationFlagCF(D3Q27System::N))
+//      {
+//         Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2+1,fbx3,level);
+//         Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3,level);
+//         Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2+1,fbx3+1,level);
+//         Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+//
+//         setInterpolationConnectors(grid, fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::N);
+//      }
+//      if( block->hasInterpolationFlagCF(D3Q27System::S))
+//      {
+//         Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3,level);
+//         Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3,level);
+//         Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2,fbx3+1,level);
+//         Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2,fbx3+1,level);
+//
+//         setInterpolationConnectors(grid, fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::S);
+//      }
+//      if( block->hasInterpolationFlagCF(D3Q27System::T))
+//      {
+//         Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3+1,level);
+//         Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3+1,level);
+//         Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2+1,fbx3+1,level);
+//         Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+//
+//         setInterpolationConnectors(grid, fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::T);
+//      }
+//      if( block->hasInterpolationFlagCF(D3Q27System::B))
+//      {
+//         Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3,level);
+//         Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3,level);
+//         Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2+1,fbx3,level);
+//         Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2+1,fbx3,level);
+//
+//         setInterpolationConnectors(grid, fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::B);
+//      }
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27BondSetConnectorsBlockVisitor::setInterpolationConnectors(Grid3DPtr grid, Block3DPtr fBlockSW, Block3DPtr fBlockSE, Block3DPtr fBlockNW, Block3DPtr fBlockNE, Block3DPtr cBlock, int dir)
+//{
+//   int fBlockSWRank = -999, fBlockSERank = -999, fBlockNWRank = -999, fBlockNERank = -999;
+//   if(fBlockSW) fBlockSWRank = fBlockSW->getRank();
+//   if(fBlockNW) fBlockNWRank = fBlockNW->getRank();
+//   if(fBlockSE) fBlockSERank = fBlockSE->getRank();
+//   if(fBlockNE) fBlockNERank = fBlockNE->getRank();
+//   int cBlockRank   = cBlock->getRank();
+//
+//   LBMReal omegaF;
+//   if(fBlockSW) omegaF =LBMSystem::calcCollisionFactor(nue, fBlockSW->getLevel());
+//   if(fBlockNW) omegaF =LBMSystem::calcCollisionFactor(nue, fBlockNW->getLevel());
+//   if(fBlockSE) omegaF =LBMSystem::calcCollisionFactor(nue, fBlockSE->getLevel());
+//   if(fBlockNE) omegaF =LBMSystem::calcCollisionFactor(nue, fBlockNE->getLevel());
+//   LBMReal omegaC = LBMSystem::calcCollisionFactor(nue, cBlock->getLevel());
+//   iProcessor->setOmegas(omegaC, omegaF);
+//
+//   D3Q27InterpolationProcessorPtr cIProcessor(iProcessor->clone());
+//   D3Q27InterpolationProcessorPtr fIProcessorSW(iProcessor->clone());
+//   D3Q27InterpolationProcessorPtr fIProcessorSE(iProcessor->clone());
+//   D3Q27InterpolationProcessorPtr fIProcessorNW(iProcessor->clone());
+//   D3Q27InterpolationProcessorPtr fIProcessorNE(iProcessor->clone());
+//
+//   D3Q27CreateTransmittersHelper::TransmitterPtr senderCFevenEvenSW, receiverCFevenEvenSW, 
+//      senderCFevenOddNW,  receiverCFevenOddNW, 
+//      senderCFoddEvenSE,  receiverCFoddEvenSE, 
+//      senderCFoddOddNE,   receiverCFoddOddNE,
+//      senderFCevenEvenSW, receiverFCevenEvenSW, 
+//      senderFCevenOddNW,  receiverFCevenOddNW, 
+//      senderFCoddEvenSE,  receiverFCoddEvenSE, 
+//      senderFCoddOddNE,   receiverFCoddOddNE;
+//
+//   if(fBlockSW) createTransmitters(cBlock, fBlockSW, dir, senderCFevenEvenSW, receiverCFevenEvenSW, senderFCevenEvenSW, receiverFCevenEvenSW);
+//   if(fBlockNW) createTransmitters(cBlock, fBlockNW, dir, senderCFevenOddNW, receiverCFevenOddNW, senderFCevenOddNW, receiverFCevenOddNW);
+//   if(fBlockSE) createTransmitters(cBlock, fBlockSE, dir, senderCFoddEvenSE, receiverCFoddEvenSE, senderFCoddEvenSE, receiverFCoddEvenSE);
+//   if(fBlockNE) createTransmitters(cBlock, fBlockNE, dir, senderCFoddOddNE, receiverCFoddOddNE, senderFCoddOddNE, receiverFCoddOddNE);
+//
+//   if(cBlockRank == gridRank)
+//   {
+//      Block3DConnectorPtr connector( new D3Q27ETCFOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(cBlock, 
+//         senderCFevenEvenSW, receiverCFevenEvenSW, senderCFevenOddNW,  receiverCFevenOddNW, 
+//         senderCFoddEvenSE,  receiverCFoddEvenSE,  senderCFoddOddNE,   receiverCFoddOddNE, 
+//         dir, cIProcessor) );
+//      cBlock->setConnector(connector);
+//   }
+//   if(fBlockSW && fBlockSWRank == gridRank)
+//   {
+//      Block3DConnectorPtr connector( new D3Q27ETFCOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(fBlockSW, 
+//         senderFCevenEvenSW, receiverFCevenEvenSW, dir, fIProcessorSW, EvenEvenSW) );
+//      fBlockSW->setConnector(connector);
+//   }
+//   if(fBlockNW && fBlockNWRank == gridRank)
+//   {
+//      Block3DConnectorPtr connector( new D3Q27ETFCOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(fBlockNW, 
+//         senderFCevenOddNW, receiverFCevenOddNW, dir, fIProcessorNW, EvenOddNW) );
+//      fBlockNW->setConnector(connector);
+//   }
+//   if(fBlockSE && fBlockSERank == gridRank)
+//   {
+//      Block3DConnectorPtr connector( new D3Q27ETFCOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(fBlockSE, 
+//         senderFCoddEvenSE, receiverFCoddEvenSE, dir, fIProcessorSE, OddEvenSE) );
+//      fBlockSE->setConnector(connector);
+//   }
+//   if(fBlockNE && fBlockNERank == gridRank)
+//   {
+//      Block3DConnectorPtr connector( new D3Q27ETFCOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(fBlockNE, 
+//         senderFCoddOddNE, receiverFCoddOddNE, dir, fIProcessorNE, OddOddNE) );
+//      fBlockNE->setConnector(connector);
+//   }
+//}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27BondSetConnectorsBlockVisitor::createTransmitters(Block3DPtr cBlock, Block3DPtr fBlock, int dir, 
+//                                                         D3Q27CreateTransmittersHelper::TransmitterPtr& senderCF, 
+//                                                         D3Q27CreateTransmittersHelper::TransmitterPtr& receiverCF, 
+//                                                         D3Q27CreateTransmittersHelper::TransmitterPtr& senderFC, 
+//                                                         D3Q27CreateTransmittersHelper::TransmitterPtr& receiverFC)
+//{
+//   D3Q27CreateTransmittersHelper helper;
+//   bool MPIpool = true;
+//   bool orthogonal = false;
+//   int fBlockRank = fBlock->getRank();
+//   int cBlockRank = cBlock->getRank();
+//   if(fBlockRank == cBlockRank && fBlockRank == gridRank)
+//   {
+//      senderCF = receiverFC = D3Q27CreateTransmittersHelper::TransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+//      senderFC = receiverCF = D3Q27CreateTransmittersHelper::TransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+//   }
+//   else if(cBlockRank == gridRank)
+//   {
+//      helper.createTransmitters(cBlock, fBlock, dir, senderCF, receiverCF, comm);
+//   }
+//   else if(fBlockRank == gridRank)
+//   {
+//      helper.createTransmitters(fBlock, cBlock, dir, senderFC, receiverFC, comm);
+//   }
+//}
+
+#endif
diff --git a/source/VirtualFluidsCore/FETOL/FETOLSetConnectorsBlockVisitor.h b/source/VirtualFluidsCore/FETOL/FETOLSetConnectorsBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..23e2aad7516ffbae3884795935b4042dc79030c4
--- /dev/null
+++ b/source/VirtualFluidsCore/FETOL/FETOLSetConnectorsBlockVisitor.h
@@ -0,0 +1,41 @@
+#if defined VF_MPI && defined VF_FETOL
+
+#ifndef D3Q27BondSetConnectorsBlockVisitor_H
+#define D3Q27BondSetConnectorsBlockVisitor_H
+
+#include "Block3DVisitor.h"
+#include "D3Q27System.h"
+#include "FETOLCommunicator.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "CreateTransmittersHelper.h"
+
+class FETOLSetConnectorsBlockVisitor : public Block3DVisitor
+{
+public:
+   FETOLSetConnectorsBlockVisitor(CommunicatorPtr comm, bool fullConnector, int dirs, LBMReal nue, D3Q27InterpolationProcessorPtr iProcessor);
+   virtual ~FETOLSetConnectorsBlockVisitor();
+   void visit(Grid3DPtr grid, Block3DPtr block);
+   //////////////////////////////////////////////////////////////////////////
+protected:
+   void setSameLevelConnectors(Grid3DPtr grid, Block3DPtr block);
+   void setRemoteConnectors(Block3DPtr sblock, Block3DPtr tblock, int dir);
+   void setBundleConnectors(Block3DPtr sblock, Block3DPtr tblock, int dir);
+   //void setInterpolationConnectors(Grid3DPtr grid, Block3DPtr block);
+   //void setInterpolationConnectors(Grid3DPtr grid, Block3DPtr fBlockSW, Block3DPtr fBlockSE, Block3DPtr fBlockNW, Block3DPtr fBlockNE, Block3DPtr cBlock, int dir);
+   //void createTransmitters(Block3DPtr cBlock, Block3DPtr fBlock, int dir, 
+   //                        D3Q27CreateTransmittersHelper::TransmitterPtr& senderCF, 
+   //                        D3Q27CreateTransmittersHelper::TransmitterPtr& receiverCF, 
+   //                        D3Q27CreateTransmittersHelper::TransmitterPtr& senderFC, 
+   //                        D3Q27CreateTransmittersHelper::TransmitterPtr& receiverFC);
+   BondCommunicatorPtr comm;
+   bool fullConnector;
+   int dirs;
+   int gridBundle;
+   int gridRank;
+   LBMReal nue;
+   D3Q27InterpolationProcessorPtr iProcessor;
+};
+
+#endif //D3Q27SETCONNECTORSVISITOR_H
+
+#endif
diff --git a/source/VirtualFluidsCore/FETOL/FETOLTransmitterBondPool.h b/source/VirtualFluidsCore/FETOL/FETOLTransmitterBondPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..50bbb2c3b9a87f482202001a43410e24b91c1779
--- /dev/null
+++ b/source/VirtualFluidsCore/FETOL/FETOLTransmitterBondPool.h
@@ -0,0 +1,510 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifdef VF_FETOL
+
+#ifndef FETOLTRANSMITTERBONDPOOL_H
+#define FETOLTRANSMITTERBONDPOOL_H
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+#include <mpi.h>
+
+#include "fbond.h"
+#include "Version.h"
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/container/CbVector.h>
+#include <basics/container/CbVectorPool.h>
+
+#include <boost/shared_ptr.hpp>
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//TbCbVectorBondPoolSender/Receiver
+//diese verschicken immer einen VectorPool. Letztlich einen langen vector,
+//der eigentlich aus vielen kleinen besteht
+//jeder BondPoolVector hat einen pointer auf die startadresse in diesem vector
+//die informationen werden im TbBondVectorPool verwaltet
+//BondPoolVector verhaelt sich nach aussen hin mit einschraenkungen wie ein std::vector
+//und kann somit bei den vector connector verwendet werden
+//man kann die klassen theoretisch verallgemeinern.
+
+template<typename T> class TbCbVectorSenderBondPool;
+template<typename T> class TbCbVectorReceiverBondPool;
+
+/*==================================================================*/
+//! \brief The class sends always one VectorPool.
+//! \details It is a long vector, which actually consists of many small.
+//!         Each BondPoolVector has a pointer to the start address in this vector.
+//!         The information is managed in TbCbBondVectorPool.
+//!         BondPool vectors behaves outwardly with limitations such as a std::vector
+//!         and can thus be used in the vector connector.
+//! \author Kostyantyn Kucher
+
+template<typename T>
+class TbCbVectorBondPool : public CbVectorPool<T>
+{
+public:
+   typedef boost::shared_ptr< TbCbVectorBondPool< T > > BondPoolPtr;
+
+   //////////////////////////////////////////////////////////////////////////
+   typedef std::map< int, BondPoolPtr >      BondPoolPtrMap;
+   typedef typename BondPoolPtrMap::iterator BondPoolPtrMapIter;
+
+   //da BasisKlasse templateKlasse ist MUSS man hier die typedefs nochmal wiederholen!
+   typedef typename CbVector<T>::value_type value_type;
+   typedef typename CbVector<T>::size_type  size_type;
+   typedef std::vector< value_type >        Pool;
+
+   typedef unsigned CbVectorKey;
+   typedef std::map< CbVectorKey, CbVector< value_type >* /*ptrVector*/  > CbVectorMap;
+   typedef typename CbVectorMap::iterator CbVectorMapIter;
+
+   //////////////////////////////////////////////////////////////////////////
+   friend class TbCbVectorSenderBondPool< T >; 
+   friend class TbCbVectorReceiverBondPool< T >; 
+
+protected:
+   //////////////////////////////////////////////////////////////////////////
+   static BondPoolPtrMap poolMap;
+public:
+   //////////////////////////////////////////////////////////////////////////
+   //STATIC MEMBERS
+   //////////////////////////////////////////////////////////////////////////
+   //!createTbCbVectorBondPool:
+   //! \param poolKey      : Schluessel fuer eindeutige Indizierung in Map
+   //! \param bondRemoteRank: bond-rank of receiver/sender 
+   //! \param bondTag       : with the bond-tag it is received/sent  
+
+static BondPoolPtr createTbCbVectorBondPool(const int& poolKey, const int& bondRemoteRank, const int& bondTag, const size_type& startPoolSize = 20000 ) //startPoolSize*sizeof(T)/1024/1024 [MB]
+   {
+      if( poolMap.find(poolKey)!=poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"es ist bereits ein Pool mit dem key vorhanden!!!");
+      }
+
+      //pool erstellen
+      BondPoolPtr bondPool(new TbCbVectorBondPool<T>(poolKey, bondRemoteRank, bondTag, startPoolSize) ); 
+
+      //pool "speichern"
+      TbCbVectorBondPool< value_type >::poolMap[poolKey] = bondPool;
+
+      return bondPool; 
+   }
+   static void deleteTbCbVectorBondPool(const int& poolKey)
+   {
+      BondPoolPtrMapIter it = TbCbVectorBondPool< value_type >::poolMap.find(poolKey);
+      if( it==poolMap.end() )
+      {
+         throw UbException(UB_EXARGS,"kein Pool mit dem key vorhanden");
+      }
+      TbCbVectorBondPool< value_type >::poolMap.erase(it);
+   }
+   /*==================================================================*/
+   static BondPoolPtr getTbCbVectorBondPool(const int& poolKey)
+   {
+      BondPoolPtrMapIter it;
+      if( (it=TbCbVectorBondPool< T >::poolMap.find(poolKey))!=TbCbVectorBondPool< T >::poolMap.end() ) 
+      {
+         return it->second;
+      }
+      return BondPoolPtr();
+   }
+   /*==================================================================*/
+   static std::string getInfoString()
+   {
+      std::stringstream out;  
+      out<<"TbCbVectorBondPool<"<< typeid( T ).name()  << ") - Info:"<<std::endl;
+      for(BondPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+         out<<"pool with key("            <<std::setw(15)<<it->first<<") "
+         <<"stores "                  <<std::setw(12)<<it->second->getNofStoredVectors() <<" vectors " 
+         <<", elements to transfer = "<<std::setw(15)<<it->second->getPoolSize() 
+         <<" ( "<< it->second->getPoolSize()*sizeof( T ) / ( 1024.0 * 1024.0 ) << " MB )" <<std::endl;
+      return out.str();
+   }
+   /*==================================================================*/
+   //! checks if all vectors have one to one pool-entries
+   static bool consistencyCheck()
+   {
+      for(BondPoolPtrMapIter it=poolMap.begin(); it!=poolMap.end(); ++it)
+      {
+         if( !it->second-> CbVectorPool<T>::consistencyCheck() ) 
+         {
+            return false;         
+         }
+      }
+
+      return true;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void eraseMap()
+   {
+      poolMap.clear();
+   }
+protected:
+   //////////////////////////////////////////////////////////////////////////
+TbCbVectorBondPool(const int& poolKey, const int& bondRemoteRank, const int& bondTag, const size_type& startPoolSize )
+      :    CbVectorPool< value_type >( startPoolSize ) 
+      , poolKey(poolKey)                           
+      , nofStoredVectors(0) //=Anzahl an Vectoren im Pool, wird bei send/receiveDataOrder gesetzt
+      , counterPrepareReceiveDataOrder(0)          
+      , counterSendDataOrder(0)                    
+      , counterReceiveDataOrder(0)                 
+      , counterPrepareForReceive(0)                
+      , counterReceive(0)                          
+      , counterPrepareForSend(0)                   
+      , counterSend(0)                             
+      , bondRemoteRank(bondRemoteRank)               
+      , bondTag(bondTag)                              
+   {
+      if     ( (std::string)typeid(value_type).name()==(std::string)typeid(double).name() ) mpiDataType = MPI_DOUBLE;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(float).name()  ) mpiDataType = MPI_FLOAT;
+      else if( (std::string)typeid(value_type).name()==(std::string)typeid(int).name()    ) mpiDataType = MPI_INT;
+      else throw UbException(UB_EXARGS,"no BondDataType for T"+(std::string)typeid(T).name());
+   }
+public:
+   /*==================================================================*/
+   //!returns key of Pool in BondPoolMap
+   int  getPoolKey()    const { return  this->poolKey;       }
+   /*==================================================================*/
+   //!returns rank of process pool data will be send to/received from
+   int  getRemoteRank() const { return  this->bondRemoteRank; }
+   /*==================================================================*/
+   //!returns tag of process pool data will be send to/received from
+   int  getRemoteTag()  const { return  this->bondTag;        }
+
+protected:
+   /*==================================================================*/
+   void sendDataOrder()
+   {
+      counterSendDataOrder++;
+      if(counterSendDataOrder==this->cbVectorMap.size())
+      {
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::sendDataOrder():start"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1;
+         tmpSendOrderVec.resize(nofElements);//std::vector< unsigned > vec(nofElements);
+         unsigned index = 0;
+         tmpSendOrderVec[index++] = (unsigned)this->pool.size(); //= laenge des vectors
+         if(this->nextCbVectorStartIndexInPool != this->pool.size())  throw UbException(UB_EXARGS,"an dieser Stelle sollten nextStartIndex und pool.size() identisch sein!!!");
+         for(CbVectorMapIter it = this->cbVectorMap.begin(); it!=this->cbVectorMap.end(); ++it)
+         {
+            CbVectorKey vectorKey=0;
+            size_type   dataSize=0, startIndexInPool=0;
+            this->getCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+            if(it->first != vectorKey) throw UbException(UB_EXARGS,"key mismatch!");
+
+            tmpSendOrderVec[index++] = (unsigned)vectorKey;         //vectorKey == allocator.getAllocatorKey()
+            tmpSendOrderVec[index++] = (unsigned)startIndexInPool;  //startIndex in poolVector
+            tmpSendOrderVec[index++] = (unsigned)dataSize;          //dataSize
+         }
+
+         try
+         {
+            sendRequest = bond::sendFuture(&tmpSendOrderVec[0], (int)tmpSendOrderVec.size(), MPI_UNSIGNED, bondRemoteRank, bondTag);
+         }
+         catch (...)
+         {
+            std::cerr << "it is bond exception in sendDataOrder()" << std::endl;
+            throw;
+         }
+                  
+         counterSendDataOrder=0;
+
+         nofStoredVectors = this->cbVectorMap.size();
+
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::sendDataOrder():end"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void receiveDataOrder()
+   {
+      counterReceiveDataOrder++;
+      if(counterReceiveDataOrder==this->cbVectorMap.size())
+      {
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::receiveDataOrder():start"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+
+         unsigned nofElements = (unsigned)this->cbVectorMap.size()*3+1; //map MUSS auf beiden seiten gleich gross sein, sonst hat man ein grundsaetzliches problem ;-)
+
+         std::vector< unsigned > tmpRecvOrderVec;
+         tmpRecvOrderVec.resize(nofElements);
+         
+         try
+         {
+            bond::receiveComplete(&tmpRecvOrderVec[0], nofElements, MPI_UNSIGNED, bondRemoteRank, bondTag);
+         }
+         catch (...)
+         {
+            std::cerr << "it is bond exception in receiveDataOrder()" << std::endl;
+            throw;
+         }
+
+         if(nofElements!=(unsigned)tmpRecvOrderVec.size())
+            throw UbException(UB_EXARGS,"error... vec size stimmt nicht");
+
+         unsigned index = 0;
+         this->nextCbVectorStartIndexInPool = tmpRecvOrderVec[index++]; //= laenge des vectors
+         this->pool.resize(this->nextCbVectorStartIndexInPool);
+         CbVectorMapIter it = this->cbVectorMap.begin();
+         for(/*index*/; index<nofElements; index+=3, ++it)
+         {
+            CbVectorKey vectorKey        = (CbVectorKey)tmpRecvOrderVec.at(index  );
+            size_type   startIndexInPool = (size_type)tmpRecvOrderVec.at(index+1);
+            size_type   dataSize         = (size_type)tmpRecvOrderVec.at(index+2);
+
+            if(it==this->cbVectorMap.end() || it->first != vectorKey ) 
+               throw UbException(UB_EXARGS,"entweder hat map nicht die gleiche reihenfolge oder vectorKey nicht vorhanden");
+
+            this->setCbVectorData(*it->second/*vec*/, vectorKey, startIndexInPool, dataSize );
+         }
+         if(it!=this->cbVectorMap.end())
+            throw UbException(UB_EXARGS,"error... in der map sind scheinbar noch weiter elemente vorhanden, die es auf der send seite nicht gibt...");
+
+         counterReceiveDataOrder = 0;
+         nofStoredVectors = this->cbVectorMap.size();
+
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::receiveDataOrder():end"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+
+#ifdef _DEBUG
+         orgPoolVectorStartPointer = &this->pool[0];
+#endif
+      }
+   }
+   /*==================================================================*/
+   void prepareForSendData()
+   {
+      //da sendDataOrder einen request verwendet muss man hier immer abfragen
+      if(counterPrepareForSend==0)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::prepareForSendData():start"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+         if (sendRequest)
+         {
+            try
+            {
+               sendRequest->complete();
+            }
+            catch (...)
+            {
+               std::cerr << "it is bond exception in prepareForSendData()" << std::endl;
+               throw;
+            }
+            sendRequest = std::tr1::shared_ptr<bond::FutureSend>();
+         }
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::prepareForSendData():end"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+      }
+
+      counterPrepareForSend++;
+
+      if(counterPrepareForSend==nofStoredVectors)
+      {
+         counterPrepareForSend=0;  
+      }
+   }
+   /*==================================================================*/
+   void sendData()
+   {
+      counterSend++;
+      if(counterSend==nofStoredVectors)
+      {
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array address changed - unknown behavior");
+#endif
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::sendData():start"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+         try
+         {
+            bond::sendComplete(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, bondRemoteRank, bondTag);
+         }
+         catch(...)
+         {
+            std::cerr << "it is bond exception in sendData()" << std::endl;
+            throw;
+         }
+         counterSend=0;
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::sendData():end"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+      }
+   }
+   /*==================================================================*/
+   void prepareForReceiveData()
+   {
+      counterPrepareForReceive++;
+      if(counterPrepareForReceive==this->nofStoredVectors)
+      {
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::prepareForReceiveData():start"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+#ifdef _DEBUG
+         if(this->orgPoolVectorStartPointer != &this->pool[0] ) throw UbException(UB_EXARGS, "ups, pool array adress changed - unknown behavoir");
+#endif
+         try
+         {
+            receiveRequest = bond::receiveFuture(&this->pool[0],(int)this->nextCbVectorStartIndexInPool, mpiDataType, bondRemoteRank, bondTag);
+         }
+         catch (...)
+         {
+         	std::cerr << "it is bond exception in prepareForReceiveData()" << std::endl;
+            throw;
+         }
+
+         
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::prepareForReceiveData():end"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+         counterPrepareForReceive=0;
+      }
+   }
+   /*==================================================================*/
+   void receiveData()
+   {
+      if(counterReceive==0)
+      {
+
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::receiveData():start"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+         
+         try
+         {
+            receiveRequest->complete();
+         }
+         catch (...)
+         {
+            std::cerr << "it is bond exception in receiveData()" << std::endl;
+            throw;
+         }
+         UBLOG(logDEBUG5, "TbCbVectorBondPool::receiveData():end"<<" bondRemoteRank="<<bondRemoteRank<<" bondTag="<<bondTag);
+      }
+      counterReceive++;
+      if(counterReceive==this->nofStoredVectors) //alle receiver waren hier
+      {
+         counterReceive=0;
+      }
+   }
+
+protected:
+   int       poolKey; //eindeutiger schluessel fuer pool
+   size_type nofStoredVectors;
+
+   size_type counterPrepareReceiveDataOrder;
+   size_type counterSendDataOrder;
+   size_type counterReceiveDataOrder;
+   size_type counterPrepareForReceive;
+   size_type counterReceive;
+   size_type counterPrepareForSend;
+   size_type counterSend;
+
+   std::vector< unsigned > tmpSendOrderVec; //wird zur temp speicherung der anordnung benoetigt
+   MPI_Datatype mpiDataType;
+
+   std::tr1::shared_ptr<bond::FutureSend> sendRequest;
+   std::tr1::shared_ptr<bond::FutureReceive> receiveRequest;
+
+   int bondRemoteRank, bondTag;
+
+#ifdef _DEBUG
+   T* orgPoolVectorStartPointer;
+#endif
+};
+
+template<typename T>
+typename TbCbVectorBondPool<T>::BondPoolPtrMap TbCbVectorBondPool<T>::poolMap;
+
+//////////////////////////////////////////////////////////////////////////
+//  TbSenderBondPool
+//////////////////////////////////////////////////////////////////////////
+template<typename T>
+class TbCbVectorSenderBondPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorSenderBondPool(const unsigned int& cbVectorKey, TbCbVectorBondPool< T >* bondVectorPool)
+      : bondVectorPool(bondVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey,this->bondVectorPool) );
+   }
+   ~TbCbVectorSenderBondPool()
+   {
+      if( this->bondVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorBondPool< T >::deleteTbCbVectorBondPool(this->bondVectorPool->getPoolKey());  
+      }
+   }
+
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()          { this->bondVectorPool->sendDataOrder(); }
+   void receiveDataSize()       { throw UbException(UB_EXARGS,"TbBondPoolSender sends only");  }   
+   CbVector< T >& receiveData() { throw UbException(UB_EXARGS,"TbBondPoolSender sends only");  }
+   void prepareForSend()        { this->bondVectorPool->prepareForSendData(); }
+   void sendData()              { this->bondVectorPool->sendData(); }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { return  this->bondVectorPool->getRemoteRank(); }
+   int  getSendTbTag()    const { return  this->bondVectorPool->getRemoteTag();  }
+   int  getRecvFromRank() const { throw UbException(UB_EXARGS,"TbCbVectorSenderBondPool sends only"); }
+   int  getRecvFromTag()  const { throw UbException(UB_EXARGS,"TbCbVectorSenderBondPool sends only"); }
+
+   std::string toString() const { return "TbCbVectorSenderBondPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getSendTbRank())+"("+UbSystem::toString(getSendTbTag())+")"; }
+
+protected:
+   TbCbVectorBondPool<T>* bondVectorPool;
+};
+
+
+/*==================================================================*/
+template<typename T>
+class TbCbVectorReceiverBondPool : public TbTransmitter< CbVector< T >  >
+{
+public:
+   typedef CbVector< T > value_type;   
+
+public:
+   TbCbVectorReceiverBondPool(const unsigned int& cbVectorKey, TbCbVectorBondPool< T >* bondVectorPool)
+      : bondVectorPool(bondVectorPool)
+   { 
+      this->getData().setAllocator( new CbVectorAllocatorPool<T>(cbVectorKey, this->bondVectorPool) );
+   }
+   ~TbCbVectorReceiverBondPool()
+   {
+      if( this->bondVectorPool->getNofStoredVectors()==1 ) //last entry!
+      {
+         TbCbVectorBondPool< T >::deleteTbCbVectorBondPool(this->bondVectorPool->getPoolKey());  
+      }
+   }
+   bool isLocalTransmitter()  const { return false;                        }
+   bool isRemoteTransmitter() const { return !this->isLocalTransmitter();  }
+
+   void sendDataSize()      { throw UbException(UB_EXARGS,"TbCbVectorReceiverBondPool receives only");  }   
+   void receiveDataSize()   { this->bondVectorPool->receiveDataOrder(); }  
+   void sendData()          { throw UbException(UB_EXARGS,"TbCbVectorReceiverBondPool receives only"); }
+   void prepareForReceive() { this->bondVectorPool->prepareForReceiveData(); }
+   CbVector< T >& receiveData()
+   { 
+      this->bondVectorPool->receiveData();
+      return this->getData();
+   }
+
+   //info-section (usable for remote transmitter)
+   int  getSendTbRank()   const { throw UbException(UB_EXARGS,"TbCbVectorReceiverBondPool receives only"); }
+   int  getSendTbTag()    const { throw UbException(UB_EXARGS,"TbCbVectorReceiverBondPool receives only"); }
+   int  getRecvFromRank() const { return  this->bondVectorPool->getRemoteRank();  }
+   int  getRecvFromTag()  const { return  this->bondVectorPool->getRemoteTag();  }
+
+   std::string toString() const { return "TbCbVectorReceiverBondPool<"+(std::string)typeid(T).name()+" to rank (tag)"+UbSystem::toString(getRecvFromRank())+"("+UbSystem::toString(getRecvFromTag())+")"; }
+
+protected:
+   TbCbVectorBondPool<T>* bondVectorPool;
+};
+
+
+
+#endif //TBTRANSMITTERBONDPOOL_H
+ 
+#endif //VF_FETOL
diff --git a/source/VirtualFluidsCore/Geometry/CMakePackage.txt b/source/VirtualFluidsCore/Geometry/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de1dc5a88225180b8e40c6cf46f4a6fbb102778f
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
\ No newline at end of file
diff --git a/source/VirtualFluidsCore/Geometry/CoordinateTransformation3D.cpp b/source/VirtualFluidsCore/Geometry/CoordinateTransformation3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0d20dadd41c1c4ad2f93eea2f8ddc7dc3fb5de67
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/CoordinateTransformation3D.cpp
@@ -0,0 +1,254 @@
+#include <numerics/geometry3d/CoordinateTransformation3D.h>
+#include <basics/utilities/UbMath.h>
+
+using namespace std;
+
+CoordinateTransformation3D::CoordinateTransformation3D()
+{
+   this->setTransformationValues(0.0,0.0,0.0,1.0,1.0,1.0,0.0,0.0,0.0);
+}
+/*======================================================*/
+CoordinateTransformation3D::CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma) 
+{
+   this->setTransformationValues(originX1, originX2, originX3, dx1, dx2, dx3, alpha, beta, gamma);
+}
+/*======================================================*/
+CoordinateTransformation3D::CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3) 
+{
+   this->setTransformationValues(originX1, originX2, originX3, dx1, dx2, dx3, 0.0, 0.0, 0.0);
+}
+/*======================================================*/
+CoordinateTransformation3D::CoordinateTransformation3D(CoordinateTransformation3D* transformation)
+{
+   this->setTransformationValues(transformation->Tx1 , transformation->Tx2 , transformation->Tx3 , transformation->Sx1 , transformation->Sx2 , transformation->Sx3, transformation->alpha, transformation->beta, transformation->gamma);
+}
+/*======================================================*/
+// void CoordinateTransformation3D::init()
+// {
+//    this->Tx1   = 0.0;      this->Tx2   = 0.0;	this->Tx3   = 0.0;
+//    this->Sx1   = 1.0;      this->Sx2   = 1.0;	this->Sx3   = 1.0;
+//    this->alpha = 0.0;		this->beta = 0.0;		this->gamma = 0.0;
+// 
+//    this->toX1factorX1   = 1.0; this->toX1factorX2   = 0.0; this->toX1factorX3   = 0.0;
+//    this->toX2factorX1   = 0.0; this->toX2factorX2   = 1.0; this->toX2factorX3   = 0.0;
+//    this->toX3factorX1   = 0.0; this->toX3factorX2   = 0.0; this->toX3factorX3   = 1.0;
+//    this->toX1delta      = 0.0; this->toX2delta      = 0.0; this->toX3delta      = 0.0;
+//    this->fromX1factorX1 = 1.0; this->fromX1factorX2 = 0.0; this->fromX1factorX3 = 0.0;
+//    this->fromX2factorX1 = 0.0; this->fromX2factorX2 = 1.0; this->fromX2factorX3 = 0.0;
+//    this->fromX3factorX1 = 0.0; this->fromX3factorX2 = 0.0; this->fromX3factorX3 = 1.0;
+//    
+//    this->active         = false;
+//    this->transformation = false;
+// }
+/*======================================================*/
+
+/**====  Set transformation values
+@param a     transformed coordinate system x0 (in global coordinates)
+@param b     transformed coordinate system y0 (in global coordinates)
+@param c     transformed coordinate system z0 (in global coordinates)
+@param dx1    x coordinate scaling       (dx_transformed/dx_global)
+@param dx2    y coordinate scaling       (dy_transformed/dy_global)
+@param dx3    z coordinate scaling       (dz_transformed/dz_global)
+@param alpha rotation around z angle    (positive FROM global TO transformed coordinate system)
+@param beta  rotation around y angle            
+@param gamma rotation around x angle            
+@exception IllegalArgumentException if one of the scale values is between -1.0E-8 and 1.0E-8
+**/
+
+void CoordinateTransformation3D::setTransformationValues(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma)
+{
+   if(UbMath::zero(dx1) || UbMath::zero(dx2) || UbMath::zero(dx3))
+      throw UbException(UB_EXARGS,"error: at least one delta==0.0");
+   
+   this->Tx1   = originX1; this->Tx2  = originX2; this->Tx3   = originX3;
+   this->Sx1   = dx1;	   this->Sx2  = dx2;	     this->Sx3   = dx3;
+   this->alpha = alpha;	   this->beta = beta;     this->gamma = gamma;
+
+   double ra   = UbMath::PI*alpha/180.0;
+   double cosA = cos(ra);
+   double sinA = sin(ra);
+   double rb   = UbMath::PI*beta/180.0;
+   double cosB = cos(rb);
+   double sinB = sin(rb);
+   double rg   = UbMath::PI*gamma/180.0;
+   double cosG = cos(rg);
+   double sinG = sin(rg);
+
+   //Matrix-Werte von T_invers  (indizes: 12 = spalte 1 zeile 2)
+   double divisor = (Sx1*Sx2*Sx3);
+   
+   this->toX1factorX1 = +cosB*cosA*Sx2*Sx3/divisor;
+   this->toX1factorX2 = -cosB*sinA*Sx1*Sx3/divisor;
+   this->toX1factorX3 = +sinB*Sx1*Sx2/divisor;
+   this->toX1delta    = (-Tx3*Sx1*Sx2*sinB       
+                         +Tx2*Sx1*Sx3*sinA*cosB  
+                         -Tx1*Sx2*Sx3*cosB*cosA)/divisor;
+   
+   this->toX2factorX1 = Sx2*Sx3*(sinG*sinB*cosA+cosG*sinA)/divisor;
+   this->toX2factorX2 = Sx1*Sx3*(-sinG*sinB*sinA+cosG*cosA)/divisor;
+   this->toX2factorX3 = -Sx1*Sx2*cosB*sinG/divisor;
+   this->toX2delta    = (-Tx2*Sx1*Sx3*cosG*cosA
+                         +Tx3*Sx1*Sx2*sinG*cosB
+                         +Tx2*Sx1*Sx3*sinG*sinA*sinB
+                         -Tx1*Sx2*Sx3*cosG*sinA
+                         -Tx1*Sx2*Sx3*sinB*sinG*cosA   )/divisor;
+   
+
+   this->toX3factorX1 = Sx2*Sx3*(-cosG*sinB*cosA+sinG*sinA)/divisor;
+   this->toX3factorX2 = Sx1*Sx3*(sinB*cosG*sinA+sinG*cosA)/divisor;
+   this->toX3factorX3 = Sx1*Sx2*cosB*cosG/divisor;
+   this->toX3delta    = (-Tx2*Sx1*Sx3*sinG*cosA
+                         -Tx3*Sx1*Sx2*cosG*cosB
+                         -Tx2*Sx1*Sx3*cosG*sinA*sinB
+                         -Tx1*Sx2*Sx3*sinG*sinA
+                         +Tx1*Sx2*Sx3*sinB*cosG*cosA  )/divisor;
+                        
+   //Matrix-Werte von T_invers  (indizes: 12 = spalte 1 zeile 2)
+   this->fromX1factorX1 =  cosB*cosA*Sx1;
+   this->fromX1factorX2 =  (sinG*sinB*cosA+cosG*sinA)*Sx1;
+   this->fromX1factorX3 =  (-cosG*sinB*cosA+sinG*sinA)*Sx1;
+   this->fromX1delta    =  Tx1;
+
+   this->fromX2factorX1 =  -cosB*sinA*Sx2;
+   this->fromX2factorX2 =  -(sinG*sinB*sinA-cosG*cosA)*Sx2;
+   this->fromX2factorX3 =  (cosG*sinB*sinA+sinG*cosA)*Sx2;
+   this->fromX2delta    =  Tx2;
+   
+   this->fromX3factorX1 =  sinB*Sx3;
+   this->fromX3factorX2 =  -sinG*cosB*Sx3;
+   this->fromX3factorX3 =  cosG*cosB*Sx3;
+   this->fromX3delta    =  Tx3;
+
+   this->active         =  true;
+   
+   this->transformation =  true;
+}
+/*======================================================*/
+/**
+Set transformation active state (if this IS a transformation)
+@param active true to be active, false otherwise
+**/
+void CoordinateTransformation3D::setActive(const bool& active)
+{
+   if(this->active == active) return;
+   if(this->transformation)   this->active = active;
+}
+/*======================================================*/
+/**
+Transform FROM global coordinates TO transformed coordinates.
+@param x1  the global x coordinate
+@param x2  the global y coordinate
+@param x3  the global z coordinate
+**/
+double CoordinateTransformation3D::transformForwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->toX1factorX1*x1 + this->toX1factorX2*x2 + this->toX1factorX3*x3 + this->toX1delta;
+   else             return x1;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformForwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->toX2factorX1*x1 + this->toX2factorX2*x2 + this->toX2factorX3*x3 + this->toX2delta;
+   else             return x2;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformForwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->toX3factorX1*x1 + this->toX3factorX2*x2 + this->toX3factorX3*x3 + this->toX3delta;
+   else             return x3;
+}
+/*======================================================*/
+/**
+Transform FROM global coordinates TO transformed coordinates (ignoring rotation).
+@param x1  the global x coordinate
+**/
+double CoordinateTransformation3D::transformForwardToX1CoordinateIgnoringRotation(const double& x1) const
+{
+   if(this->active) return (x1-this->Tx1)/this->Sx1;
+   else             return x1;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformForwardToX2CoordinateIgnoringRotation(const double& x2) const
+{
+   if(this->active) return (x2-this->Tx2)/this->Sx2;
+   else             return x2;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformForwardToX3CoordinateIgnoringRotation(const double& x3) const
+{
+   if(this->active) return (x3-this->Tx3)/this->Sx3;
+   else             return x3;
+}
+/*======================================================*/
+/**
+Transform FROM transformed coordinates TO global coordinates.
+@param x1  the transformed x coordinate
+@param x2  the transformed y coordinate
+@param x3  the transformed z coordinate
+**/
+double CoordinateTransformation3D::transformBackwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->fromX1factorX1*x1 + this->fromX1factorX2*x2 + this->fromX1factorX3*x3 + this->fromX1delta;
+   else             return x1;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformBackwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->fromX2factorX1*x1 + this->fromX2factorX2*x2 + this->fromX2factorX3*x3 + this->fromX2delta;
+   else             return x2;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformBackwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const
+{
+   if(this->active) return this->fromX3factorX1*x1 + this->fromX3factorX2*x2 + this->fromX3factorX3*x3 + this->fromX3delta;
+   else             return x3;
+}
+/*======================================================*/
+/**
+Transform FROM transformed coordinates TO global coordinates (ignoring rotation).
+@param x1  the transformed x coordinate
+**/
+double CoordinateTransformation3D::transformBackwardToX1CoordinateIgnoringRotation(const double& x1) const
+{
+   if(this->active) return x1*this->Sx1+this->Tx1;
+   else             return x1;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformBackwardToX2CoordinateIgnoringRotation(const double& x2) const
+{
+   if(this->active) return x2*this->Sx2+this->Tx2;
+   else             return x2;
+}
+/*======================================================*/
+double CoordinateTransformation3D::transformBackwardToX3CoordinateIgnoringRotation(const double& x3) const
+{
+   if(this->active) return x3*this->Sx3+this->Tx3;
+   else             return x3;
+}
+/*======================================================*/
+/**
+Returns a string representation of this transformation.
+@return a string representation of this transformation
+**/
+string CoordinateTransformation3D::toString() const
+{
+   stringstream ss;
+    ss<<" CoordinateTransformation3D\n";
+//    ss<<"[isTransformation="<<this->transformation;
+//    ss<<", isActive="<<this->active<<endl;
+    ss<<" ,a="<<this->Tx1<<", b="<<this->Tx2<<", c="<<this->Tx3<<endl;
+    ss<<" , dx1="<<this->Sx1<<", dx2="<<this->Sx2<<", dx2="<<this->Sx3<<endl;
+//    ss<<" , alpha="<<this->alpha<<", beta="<<this->beta<endl;
+//    ss<<"]";
+//    ss<<"[to11="<<this->to11<<", to12="<<this->to12<<", to13="<<this->to13;
+//    ss<<", to21="<<this->to21<<", to22="<<this->to22<<", to23="<<this->to23;
+//    ss<<", to31="<<this->to31<<", to32="<<this->to32<<", to33="<<this->to33;
+//    ss<<", toA="<<this->toA<<", toB="<<this->toB<<", toC="<<this->toC;
+//    ss<<", from11="<<this->from11<<", from12="<<this->from12<<", from13="<<this->from13;
+//    ss<<", from21="<<this->from21<<", from22="<<this->from22<<", from23="<<this->from23;
+//    ss<<", from31="<<this->from31<<", from32="<<this->from32<<", from33="<<this->from33;
+//    ss<<", fromA="<<this->fromA; ss<<", fromB="<<this->fromB; ss<<", fromC="<<this->fromC;
+//    ss<<"]}";
+   return ss.str();
+}
+                                     
diff --git a/source/VirtualFluidsCore/Geometry/CoordinateTransformation3D.h b/source/VirtualFluidsCore/Geometry/CoordinateTransformation3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b0b83dec47590765f0d99e2cb37565d78b5cafd
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/CoordinateTransformation3D.h
@@ -0,0 +1,178 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef COORDINATETRANSFORMATION3D_H
+#define COORDINATETRANSFORMATION3D_H
+
+#ifdef RCF_USE_BOOST_SERIALIZATION
+   #include <boost/archive/text_oarchive.hpp>
+   #include <boost/archive/text_iarchive.hpp>	
+#endif //RCF_USE_BOOST_SERIALIZATION
+
+#include <cmath>
+#include <string>
+#include <sstream>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+#include <basics/utilities/UbFileOutput.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class CoordinateTransformation3D;
+typedef VFSharedPtr<CoordinateTransformation3D> CoordinateTransformation3DPtr;
+
+#include <boost/serialization/serialization.hpp>
+
+//description:     x1/x2/x3 = alt, x1*/x2*/x3* = neu
+//   x2      
+//   ^             x*
+//   |            /
+//   |           2*
+//   4          /
+//   |         /
+//   3        1*                     => neues coordsys ist um originX1=originX2=originX3=2 verschoben
+//   |       /                          neues dx1=dx2=dx2=2 -> skalierung um 2 in x1-,x2- und x3-richtung
+//   2      /                           ERST verdrehung um alpha um "x1" achse
+//   |       \                          DANN verdrehung um beta  um "x2" achse
+//   1         \                        DANN verdrehung um gamma um "x3" achse
+//   |           x1*
+//   |--1--2--3--4--5------------- > x1
+//
+// Bemerkung: kann sein, dass die Verdrehung um x1 und x3 vertauschst sind 
+//            - muss mal einer prüfen ...
+
+
+
+class CoordinateTransformation3D
+{
+public:
+   CoordinateTransformation3D();
+   CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma);
+   CoordinateTransformation3D(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3);
+   CoordinateTransformation3D(CoordinateTransformation3D* transformation);
+   
+   void setTransformationValues(const double& originX1, const double& originX2, const double& originX3, const double& dx1, const double& dx2, const double& dx3, const double& alpha, const double& beta, const double& gamma);
+   double getX1CoordinateOffset()  const { return this->Tx1;   }   //Translation
+   double getX2CoordinateOffset()  const { return this->Tx2;   }
+   double getX3CoordinateOffset()  const { return this->Tx3;   }
+   double getX1CoordinateScaling() const { return this->Sx1;   }	 //Scaling
+   double getX2CoordinateScaling() const { return this->Sx2;   }
+   double getX3CoordinateScaling() const { return this->Sx3;   }
+   double getRotationX1Angle()     const { return this->alpha; }
+   double getRotationX2Angle()     const { return this->beta;  }
+   double getRotationX3Angle()     const { return this->gamma; }	 //Rotation
+
+   //Achtung die Winkel passen nicht überein -siehe setTransformationValues 
+   void setRotationX1Angle(double alpha) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, alpha, this->beta, this->gamma); }
+   void setRotationX2Angle(double beta ) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, this->alpha, beta, this->gamma); }
+   void setRotationX3Angle(double gamma) { this->setTransformationValues(this->Tx1, this->Tx2, this->Tx3, this->Sx1, this->Sx2, this->Sx3, this->alpha, this->beta, gamma); }
+
+   void setActive(const bool& active);
+   bool isActive()          const { return this->active; }
+   bool isTransformation()  const { return this->transformation; }
+
+   double transformForwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformForwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformForwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformForwardToX1CoordinateIgnoringRotation(const double& x1) const;
+   double transformForwardToX2CoordinateIgnoringRotation(const double& x2) const;
+   double transformForwardToX3CoordinateIgnoringRotation(const double& x3) const;
+   double transformBackwardToX1Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformBackwardToX2Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformBackwardToX3Coordinate(const double& x1, const double& x2, const double& x3) const;
+   double transformBackwardToX1CoordinateIgnoringRotation(const double& x1) const;
+   double transformBackwardToX2CoordinateIgnoringRotation(const double& x2) const;
+   double transformBackwardToX3CoordinateIgnoringRotation(const double& x3) const;
+   std::string toString() const;
+
+   //------------- implements CAB serialization ----- start
+   void write(UbFileOutput* out) const
+   {
+      out->writeString("Coordtransfomartion3D");
+      out->writeDouble(this->Tx1);
+      out->writeDouble(this->Tx2);
+      out->writeDouble(this->Tx3);
+      out->writeDouble(this->Sx1);
+      out->writeDouble(this->Sx2);
+      out->writeDouble(this->Sx3);
+      out->writeDouble(this->alpha);
+      out->writeDouble(this->beta );
+      out->writeDouble(this->gamma);
+   }
+   void read(UbFileInput* in)
+   {
+      in->readString();
+      this->Tx1   = in->readDouble();
+      this->Tx2   = in->readDouble();
+      this->Tx3   = in->readDouble();
+      this->Sx1   = in->readDouble();
+      this->Sx2   = in->readDouble();
+      this->Sx3   = in->readDouble();
+      this->alpha = in->readDouble();
+      this->beta  = in->readDouble();
+      this->gamma = in->readDouble();
+
+      this->setTransformationValues(Tx1,Tx2,Tx3,Sx1,Sx2,Sx3,alpha,beta,gamma);
+   }
+   //------------- implements CAB serialization ----- end
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      ar & Tx1;   ar & Tx2; ar & Tx3; 
+      ar & Sx1;   ar & Sx2; ar & Sx3; 
+      ar & alpha; ar & beta; ar & gamma;
+      
+      ar & toX1factorX1; ar & toX1factorX2; ar & toX1factorX3; ar & toX1delta;
+      ar & toX2factorX1; ar & toX2factorX2; ar & toX2factorX3; ar & toX2delta;
+      ar & toX3factorX1; ar & toX3factorX2; ar & toX3factorX3; ar & toX3delta;
+
+      ar & fromX1factorX1; ar & fromX1factorX2; ar & fromX1factorX3; ar & fromX1delta;
+      ar & fromX2factorX1; ar & fromX2factorX2; ar & fromX2factorX3; ar & fromX2delta;
+      ar & fromX3factorX1; ar & fromX3factorX2; ar & fromX3factorX3; ar & fromX3delta;
+
+      ar & active;
+      ar & transformation;
+   }
+#endif //CAB_RCF
+
+private:
+   double Tx1, Tx2, Tx3, Sx1, Sx2, Sx3, alpha, beta, gamma;
+
+   double toX1factorX1, toX1factorX2, toX1factorX3, toX1delta;
+   double toX2factorX1, toX2factorX2, toX2factorX3, toX2delta;
+   double toX3factorX1, toX3factorX2, toX3factorX3, toX3delta;
+
+   double fromX1factorX1, fromX1factorX2, fromX1factorX3, fromX1delta;
+   double fromX2factorX1, fromX2factorX2, fromX2factorX3, fromX2delta;
+   double fromX3factorX1, fromX3factorX2, fromX3factorX3, fromX3delta;
+
+   bool   active;
+   bool   transformation;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & Tx1;   ar & Tx2; ar & Tx3; 
+      ar & Sx1;   ar & Sx2; ar & Sx3; 
+      ar & alpha; ar & beta; ar & gamma;
+
+      ar & toX1factorX1; ar & toX1factorX2; ar & toX1factorX3; ar & toX1delta;
+      ar & toX2factorX1; ar & toX2factorX2; ar & toX2factorX3; ar & toX2delta;
+      ar & toX3factorX1; ar & toX3factorX2; ar & toX3factorX3; ar & toX3delta;
+
+      ar & fromX1factorX1; ar & fromX1factorX2; ar & fromX1factorX3; ar & fromX1delta;
+      ar & fromX2factorX1; ar & fromX2factorX2; ar & fromX2factorX3; ar & fromX2delta;
+      ar & fromX3factorX1; ar & fromX3factorX2; ar & fromX3factorX3; ar & fromX3delta;
+
+      ar & active;
+      ar & transformation;
+   }
+};
+
+#endif //COORDINATETRANSFORMATION3D_H
diff --git a/source/VirtualFluidsCore/Geometry/Creator/CMakePackage.txt b/source/VirtualFluidsCore/Geometry/Creator/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7fc2bbf84209dc05bd7aa85886b2250007c2a107
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/CMakePackage.txt
@@ -0,0 +1,12 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
+
+#SET(SUBDIRPATH numerics/geometry3d/creator) 
+#SET(OPTION_LABEL BUILD_GEOMETRY3DCREATOR)
+#
+#SET(CURRENT_DIR ${SOURCE_ROOT}/${SUBDIRPATH})
+#
+#OPTION(${OPTION_LABEL} "${CURRENT_DIR}" ON)
+#IF(${OPTION_LABEL})
+#   COLLECT_PACKAGE_DATA( ${CURRENT_DIR} ${SUBDIRPATH} ALL_SOURCES)
+#ENDIF(${OPTION_LABEL})
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbCuboid3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbCuboid3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b8478f8bdfaa680584e96e0f10b92a5b8726c3c
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbCuboid3DCreator.h
@@ -0,0 +1,77 @@
+#ifndef GBCUBOID3DCREATOR_H
+#define GBCUBOID3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbCuboid3D.h>     
+
+#ifdef CAB_QT 
+#include <numerics/geometry3d/presentation/QGbCuboid3DInstrument.h>
+#include <QtGui/QWidget>
+#include <QtGui/QDialog>
+#endif
+
+#ifdef CAB_VTK 
+#include <numerics/geometry3d/presentation/vtkGbCuboid3D.h>
+#endif
+
+class GbCuboid3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbCuboid3DCreator* getInstance()
+   {
+      static GbCuboid3DCreator instance;
+      return &instance;
+   }
+
+   GbCuboid3D* createGbObject3D() { return new GbCuboid3D(); }          
+
+   std::string getGbObject3DTypeID() { return "GbCuboid3D"; };
+   std::string toString()            { return "GbCuboid3DCreator"; }
+
+private:
+   GbCuboid3DCreator() : GbObject3DCreator() {}
+
+   GbCuboid3DCreator( const GbCuboid3DCreator& );                  //no copy allowed 
+   const GbCuboid3DCreator& operator=( const GbCuboid3DCreator& ); //no copy allowed
+
+#ifdef CAB_QT 
+public:
+   GbCuboid3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0)
+   {                                                              
+      GbCuboid3D* cuboid = this->createGbObject3D();
+      cuboid->getPoint2()->setX1(2.0);
+      cuboid->getPoint2()->setX2(2.0);
+      cuboid->getPoint2()->setX3(2.0);
+
+      QGbCuboid3DInstrument instrument(parent, flags);
+      instrument.setGbCuboid3D(cuboid);
+      if (instrument.exec()) { return cuboid; }
+      delete cuboid;
+
+      return NULL;
+   }
+
+   QDialog* getSpecificInstrument(QWidget* parent=0, Qt::WFlags flags=0) { return new QGbCuboid3DInstrument(parent, flags); }
+
+   void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      GbCuboid3D* cuboid = dynamic_cast<GbCuboid3D*>(gbObj);
+      if(!cuboid) throw UbException(UB_EXARGS,"selected object to edit is no GbCuboid3D!");
+
+      QGbCuboid3DInstrument instrument(parent, flags);
+      instrument.setGbCuboid3D(cuboid);
+      instrument.exec();
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbCuboid3D(dynamic_cast<GbCuboid3D*>(object)); }
+#endif
+
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbCuboid3DCreator::getInstance()), CAB_GbCuboid3DCreator);
+#endif
+
+#endif   
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbCylinder3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbCylinder3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca9614d7d50f5ba8f32f9a7cc134503a5d9cf49b
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbCylinder3DCreator.h
@@ -0,0 +1,81 @@
+#ifndef GBCYLINDER3DCREATOR_H
+#define GBCYLINDER3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbCylinder3D.h>
+
+#ifdef CAB_QT 
+#include <numerics/geometry3d/presentation/QGbCylinder3DInstrument.h>
+#include <QtGui/QWidget>
+#include <QtGui/QDialog>
+#endif
+
+#ifdef CAB_VTK
+#include <numerics/geometry3d/presentation/vtkGbCylinder3D.h>
+#endif
+
+
+class GbCylinder3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbCylinder3DCreator* getInstance()
+   {
+      static GbCylinder3DCreator instance;
+      return &instance;
+   }
+
+   GbCylinder3D* createGbObject3D() { return new GbCylinder3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "GbCylinder3D";        }
+   std::string toString()           { return "GbCylinder3DCreator"; }
+
+private:
+   GbCylinder3DCreator( const GbCylinder3DCreator& );                  //no copy allowed 
+   const GbCylinder3DCreator& operator=( const GbCylinder3DCreator& ); //no copy allowed
+GbCylinder3DCreator() : GbObject3DCreator() {}
+
+#ifdef CAB_QT
+public:
+
+   GbCylinder3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0)
+   {                                                              
+      GbCylinder3D* cylinder = this->createGbObject3D();
+      cylinder->setRadius(2.0);
+      cylinder->setPoint1(0.0, 0.0, 0.0);
+      cylinder->setPoint2(0.0, 5.0, 0.0);
+
+      QGbCylinder3DInstrument instrument(parent, flags);
+      instrument.setGbCylinder3D(cylinder);
+      if (instrument.exec()){ return cylinder; }
+      delete cylinder;
+
+      return NULL;
+   }
+
+   QDialog* getSpecificInstrument(QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      return new QGbCylinder3DInstrument(parent, flags);
+   }
+
+   void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      GbCylinder3D* cylinder = dynamic_cast<GbCylinder3D*>(gbObj);
+      if(!cylinder) throw UbException(UB_EXARGS,"selected object to edit is no GbCylinder3D!");
+
+      QGbCylinder3DInstrument instrument(parent, flags);
+      instrument.setGbCylinder3D(cylinder);
+      instrument.exec();
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbCylinder3D(dynamic_cast<GbCylinder3D*>(object)); }
+#endif
+
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbCylinder3DCreator::getInstance()), CAB_GbCylinder3DCreator);
+#endif
+
+#endif   
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbLine3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbLine3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..460613f8e3b65dbdad516a507501f7a035ccf13d
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbLine3DCreator.h
@@ -0,0 +1,31 @@
+#ifndef GBLINE3DCREATOR_H
+#define GBLINE3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbLine3D.h>
+
+class GbLine3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbLine3DCreator* getInstance()
+   {
+      static GbLine3DCreator instance;
+      return &instance;
+   }
+
+   GbLine3D* createGbObject3D() { return new GbLine3D(); }
+
+   std::string getGbObject3DTypeID(){ return "GbLine3D";        }
+   std::string toString()           { return "GbLine3DCreator"; }
+
+private:
+   GbLine3DCreator( const GbLine3DCreator& );                  //no copy allowed 
+   const GbLine3DCreator& operator=( const GbLine3DCreator& ); //no copy allowed
+   GbLine3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbLine3DCreator::getInstance()), CAB_GbLine3DCreator);
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbObject3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbObject3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1a8fd785fcc325ab78252f2034663d49df3c25c
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbObject3DCreator.h
@@ -0,0 +1,77 @@
+#ifndef GBOBJECT3DCREATOR_H
+#define GBOBJECT3DCREATOR_H
+
+#include <string>
+
+#include <basics/objects/ObObjectCreator.h>
+#include <basics/utilities/UbAutoRun.hpp>
+
+#include <numerics/geometry3d/GbObject3D.h>
+
+#ifdef CAB_QT 
+#include <qdialog.h>
+#endif
+
+#ifdef CAB_VTK
+#include <userinterface/presentation/vtkPoElement3D.h>
+#endif
+
+#ifdef CAB_PARAVIEW 
+#include "vtkPVSource.h"
+#endif          
+
+class GbObject3DCreator : public ObObjectCreator                           
+{                                       
+protected:
+   GbObject3DCreator() {}
+private:
+   GbObject3DCreator( const GbObject3DCreator& );                  //no copy allowed !!!
+   const GbObject3DCreator& operator=( const GbObject3DCreator& ); //no copy allowed
+public:
+   virtual ~GbObject3DCreator(){}
+
+   virtual std::string getTypeID() { return getGbObject3DTypeID();}
+   virtual ObObject* createObObject()
+   {
+      return this->createGbObject3D();
+   }
+
+
+   virtual GbObject3D* createGbObject3D()=0;
+   virtual std::string getGbObject3DTypeID()=0;                       
+   virtual std::string toString() { return "GbObject3DCreator"; }     
+
+#ifdef CAB_QT 
+   virtual GbObject3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0) { throw UbException(UB_EXARGS,"Not implemented..."); }
+   virtual void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)  { throw UbException(UB_EXARGS,"Not implemented..."); }
+#endif
+   //die Teile von ObObjectCreator ...
+#ifdef CAB_QT 
+   void showSpecificInstrument(ObObject* object,QWidget* parent=0)
+   {
+      GbObject3D* geoObj = dynamic_cast<GbObject3D*>(object);
+      this->editGbObject3DwithQt(geoObj, parent);
+   }
+   virtual ObObject* createObObjectWithQt() { return this->createGbObject3DwithQt();}
+   virtual QObObjectSpecificInstrument* getSpecificInstrument() { throw UbException(UB_EXARGS,"not implemented"); }
+
+#endif
+#ifdef CAB_VTK 
+   virtual Presentator* createObjectPresentator(ObObject *object) { return NULL; }
+#endif
+
+
+#ifdef CAB_PARAVIEW 
+   virtual vtkPVSource* createPVSource(vtkPVWindow *Window) {  throw UbException(UB_EXARGS,"vtkPVSource* createPVSource"); }
+#endif
+
+
+};
+
+#include <numerics/geometry3d/creator/GbObject3DFactory.h>
+
+/*=========================================================================*/
+#endif
+
+
+
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbObject3DFactory.cpp b/source/VirtualFluidsCore/Geometry/Creator/GbObject3DFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eacc1cc086e46e0e3599dd1a318698d7d5fa2332
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbObject3DFactory.cpp
@@ -0,0 +1,97 @@
+#include <numerics/geometry3d/creator/GbObject3DFactory.h>
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+//#include <numerics/geometry3d/creator/GbPoint3DCreator.h>
+// #include <numerics/geometry3d/creator/GbCuboid3DCreator.h>
+// #include <numerics/geometry3d/creator/GbSphere3DCreator.h>
+// #include <numerics/geometry3d/creator/GbCylinder3DCreator.h>
+// #include <numerics/geometry3d/creator/GbLine3DCreator.h>
+// #include <numerics/geometry3d/creator/GbPolygon3DCreator.h>
+// #include <numerics/geometry3d/creator/GbTriangle3DCreator.h>
+// #include <numerics/geometry3d/creator/GbTriangularMesh3DCreator.h>
+
+using namespace std;
+
+//GbObject3DFactory* GbObject3DFactory::instance = NULL;
+
+/*======================================================================*/
+GbObject3DFactory::GbObject3DFactory() 
+   : ObObjectFactory()
+{
+}
+/*======================================================================*/  
+GbObject3DFactory* GbObject3DFactory::getInstance()
+{
+   static GbObject3DFactory instance;
+   return &instance;
+}
+
+///*======================================================================*/
+//void GbObject3DFactory::addGbObject3DCreator(GbObject3DCreator* creator)
+//{
+//   //cout<<"Meth:"<<creator->toString()<<" Meth-ID:"<<creator->getGbObject3DTypeID()<<endl;
+//   creatorSet.insert(pair<string, GbObject3DCreator*>(creator->getGbObject3DTypeID(), creator));
+//}
+//
+//void GbObject3DFactory::deleteGbObject3DCreator(GbObject3DCreator* creator)
+//{
+//   throw UbException(UB_EXARGS,"GbObject3DFactory::deleteGbObject3DCreator not yet implemented");
+//   // this.creatorSet.delete(creator);
+//}
+
+/*======================================================================*/
+GbObject3D* GbObject3DFactory::createGbObject3D(UbFileInput *in) 
+{
+   string str = in->readString();
+   //cout<<"GbObject3DFactory::createGbObject3D:"<<str<<endl;
+
+   GbObject3D *gbObject3D = createEmptyGbObject3D(str);
+
+   if(!gbObject3D)
+      throw UbException(UB_EXARGS,"creator for type available");
+   
+   gbObject3D->read(in);
+
+   return gbObject3D;
+}
+/*======================================================================*/
+GbObject3D* GbObject3DFactory::createEmptyGbObject3D(string objectType)
+{
+   typedef std::map<string, ObObjectCreator*>::iterator CreatorIterator;
+   std::map<string, ObObjectCreator*>* creatorSet = this->getCreatorSet();
+   CreatorIterator creatorIterator = creatorSet->find(objectType);
+
+   if(creatorIterator == creatorSet->end()) 
+      throw UbException(UB_EXARGS,"factory has no creator for "+objectType);
+
+   GbObject3DCreator *creator = dynamic_cast<GbObject3DCreator*>(creatorIterator->second);
+
+   if(!creator) 
+      throw UbException(UB_EXARGS,"factory has no creator for "+objectType);
+
+   return creator->createGbObject3D();
+}
+/*======================================================================*/
+//GbObject3DCreator* GbObject3DFactory::getCreator(string objectType)
+//{
+//   CreatorIterator creatorIterator = creatorSet.find(objectType);
+//   if(creatorIterator == creatorSet.end()) throw UbException(UB_EXARGS,"factory has no creator for "+objectType);
+//   GbObject3DCreator *creator = creatorIterator->second;
+//   if(!creator) throw UbException(UB_EXARGS,"factory has no creator for "+objectType);
+//   return(creator);
+//}
+/*======================================================================*/
+string GbObject3DFactory::toString() 
+{
+   stringstream ss;
+   ss<<"GbObject2DFactory";
+   int a=1;
+   std::map<std::string, ObObjectCreator*>::iterator creatorIterator; 
+   std::map<std::string, ObObjectCreator*>* tmp = this->getCreatorSet();
+   for(creatorIterator=tmp->begin(); creatorIterator!=tmp->end(); creatorIterator++)
+   {
+      ss<<(a++)<<". ";
+      ss<<creatorIterator->second->getTypeID();
+      ss<<endl;
+   }
+   return(ss.str());
+}
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbObject3DFactory.h b/source/VirtualFluidsCore/Geometry/Creator/GbObject3DFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..f01d1dd45f7c766a4703c3d22cf10747a394e53c
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbObject3DFactory.h
@@ -0,0 +1,43 @@
+#ifndef GBOBJECT3DFACTORY_H
+#define GBOBJECT3DFACTORY_H
+
+#include <string>
+#include <sstream>
+#include <map>
+
+#include <basics/objects/ObObjectFactory.h>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+
+class GbObject3D;
+class GbObject3DCreator;
+
+class GbObject3DFactory : public ObObjectFactory
+{
+private:
+   GbObject3DFactory();
+   GbObject3DFactory( const GbObject3DFactory& );                  //no copy allowed 
+   const GbObject3DFactory& operator=( const GbObject3DFactory& ); //no copy allowed
+public:
+   static GbObject3DFactory* getInstance();
+   
+   GbObject3D* createGbObject3D(UbFileInput* in);
+
+   //void addGbObject3DCreator(GbObject3DCreator* creator);
+   //void deleteGbObject3DCreator(GbObject3DCreator* creator);
+   //std::map<std::string, GbObject3DCreator*>* getCreatorSet() { return &creatorSet;   }
+
+   std::string toString();
+   GbObject3D* createEmptyGbObject3D(std::string objectType);
+   //GbObject3DCreator* getCreator(std::string objectTypeID);
+
+private:
+   
+   
+   //std::map<std::string, GbObject3DCreator*> creatorSet;
+   //typedef std::map<std::string, GbObject3DCreator*>::iterator CreatorIterator;
+};
+/*=========================================================================*/
+#endif
+
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbPoint3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbPoint3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..40bb5835c3d9899cd63d18447c953eaa7a85d0b2
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbPoint3DCreator.h
@@ -0,0 +1,31 @@
+#ifndef GBPOINT3DCREATOR_H
+#define GBPOINT3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+class GbPoint3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbPoint3DCreator* getInstance()
+   {
+      static GbPoint3DCreator instance;
+      return &instance;
+   }
+   
+   GbPoint3D* createGbObject3D() { return new GbPoint3D(); }
+   
+   std::string getGbObject3DTypeID() { return "GbPoint3D";        }
+   std::string toString()            { return "GbPoint3DCreator"; }
+
+private:
+   GbPoint3DCreator( const GbPoint3DCreator& );                  //no copy allowed 
+   const GbPoint3DCreator& operator=( const GbPoint3DCreator& ); //no copy allowed
+   GbPoint3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbPoint3DCreator::getInstance()), CAB_GbPoint3DCreator);
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbPolygon3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbPolygon3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..703397747d8caa917fd2af14b36059db9e79a9cc
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbPolygon3DCreator.h
@@ -0,0 +1,32 @@
+#ifndef GBPOLYGON3DCREATOR_H
+#define GBPOLYGON3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+class GbPolygon3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbPolygon3DCreator* getInstance()
+   {
+      static GbPolygon3DCreator instance;
+      return &instance;
+   }
+
+   GbPolygon3D* createGbObject3D() { return new GbPolygon3D(); }
+
+   std::string getGbObject3DTypeID() { return "GbPolygon3D";        }
+   std::string toString()            { return "GbPolygon3DCreator"; }
+
+private:
+   GbPolygon3DCreator( const GbPolygon3DCreator& );                  //no copy allowed 
+   const GbPolygon3DCreator& operator=( const GbPolygon3DCreator& ); //no copy allowed
+
+   GbPolygon3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbPolygon3DCreator::getInstance()), CAB_GbPolygon3DCreator);
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbQuadFaceMesh3DCreator.cpp b/source/VirtualFluidsCore/Geometry/Creator/GbQuadFaceMesh3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f0d818aa7263f0dbf5ddcdf33dc92fe067a23709
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbQuadFaceMesh3DCreator.cpp
@@ -0,0 +1,66 @@
+#include <numerics/geometry3d/creator/GbQuadFaceMesh3DCreator.h>
+#include <numerics/geometry3d/GbQuadFaceMesh3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+using namespace std;
+
+/***************************************************************************/
+GbObject3D* GbQuadFaceMesh3DCreator::createGbObject3D() 
+{ 
+   return new GbQuadFaceMesh3D(); 
+}
+/***************************************************************************/
+GbQuadFaceMesh3D* GbQuadFaceMesh3DCreator::createQuadMesh3D(int nodesX1, int nodesX2, float startX1, float startX2, double knotenabstandX1, double knotenabstandX2, float nullNiveau, string name)
+{
+   vector<GbQuadFaceMesh3D::Vertex> *vertices = new vector<GbQuadFaceMesh3D::Vertex>;
+   vector<GbQuadFaceMesh3D::QuadFace> *quads = new vector<GbQuadFaceMesh3D::QuadFace>;
+   for(int x1=0;x1<nodesX1;x1++)
+   {
+      for(int x2=0;x2<nodesX2;x2++)
+      {
+         vertices->push_back(GbQuadFaceMesh3D::Vertex((float)(x1*knotenabstandX1+startX1), (float)(x2*knotenabstandX2+startX2), nullNiveau));
+      }
+   }
+   for(int x1=0;x1<nodesX1-1;x1++)
+   {
+      for(int x2=0;x2<nodesX2-1;x2++)
+      {
+         int index = x1*nodesX2+x2;
+         quads->push_back(GbQuadFaceMesh3D::QuadFace(index, index+nodesX2, index+nodesX2+1, index+1));
+      }
+   }
+   
+   return (new GbQuadFaceMesh3D(name, vertices, quads));
+}
+
+/*============================================================*/
+
+#ifdef CAB_QT 
+
+GbQuadFaceMesh3D* GbQuadFaceMesh3DCreator::createGbObject3DwithQt()
+{
+   //QString s = QFileDialog::getOpenFileName(NULL,NULL,NULL,"open file dialog","Choose a STL file" );
+   //QString s = QFileDialog::getOpenFileName(NULL, "Choose a STL file", "/home", "*.stl");
+   //QFileDialog* fd = new QFileDialog( NULL );
+   //fd->setIconText(QString("Hallo"));
+   //fd->show();
+   //TODO: Open File Dialog einbauen.		
+   //UbFileInputASCII in( s.toAscii().data() );
+   //stringstream stream;
+   //stream <<"TriangularMesh3D ";//<<_objCount++;
+   //GbQuadFaceMesh3D *mesh = NULL;//GbQuadFaceMesh3DCreator::readMeshFromSTLFile(&in, stream.str() );
+   //return mesh;
+   return NULL;
+}
+//QDialog* getSpecificInstrument()  {  return 0;}
+void GbQuadFaceMesh3DCreator::editGbObject3DwithQt(GbObject3D* gbObj)
+{ 
+
+}
+#endif
+#ifdef CAB_VTK
+Presentator* GbQuadFaceMesh3DCreator::createObjectPresentator(ObObject *object) 
+{
+   return NULL;
+}
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbQuadFaceMesh3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbQuadFaceMesh3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..ac43dd4fe141e9b8b6c0150b8968d4ebf178377b
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbQuadFaceMesh3DCreator.h
@@ -0,0 +1,52 @@
+#ifndef GBQUADFACEMESH3DCREATOR_H
+#define GBQUADFACEMESH3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+
+class GbQuadFaceMesh3D;
+
+#ifdef CAB_QT 
+
+#endif
+
+#ifdef CAB_VTK
+//#include <numerics/geometry3d/presentation/vtkGbQuadangularMesh3D.h>
+#endif
+
+class GbQuadFaceMesh3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbQuadFaceMesh3DCreator* getInstance()
+   {
+      static GbQuadFaceMesh3DCreator instance;
+      return &instance;
+   }
+   static GbQuadFaceMesh3D *createQuadMesh3D(int nodesX1, int nodesX2, float startX1, float startX2, double knotenabstandX1, double knotenabstandX2, float nullNiveau, std::string name);
+
+   GbObject3D* createGbObject3D();
+   
+   std::string getGbObject3DTypeID() { return "GbQuadFaceMesh3D";        }
+   std::string toString()            { return "GbQuadFaceMesh3DCreator"; }
+
+#ifdef CAB_QT 
+
+   GbQuadFaceMesh3D* createGbObject3DwithQt();
+   //QDialog* getSpecificInstrument()  {  return 0;}
+   void editGbObject3DwithQt(GbObject3D* gbObj);
+#endif
+#ifdef CAB_VTK
+   Presentator* createObjectPresentator(ObObject *object);
+#endif
+
+
+private:
+   GbQuadFaceMesh3DCreator( const GbQuadFaceMesh3DCreator& );                  //no copy allowed 
+   const GbQuadFaceMesh3DCreator& operator=( const GbQuadFaceMesh3DCreator& ); //no copy allowed
+   GbQuadFaceMesh3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbQuadFaceMesh3DCreator::getInstance()), CAB_GbQuadFaceMesh3DCreator);
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbSphere3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbSphere3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..81e70daf041d2c71fb090a0c2b0034552891ee4f
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbSphere3DCreator.h
@@ -0,0 +1,126 @@
+#ifndef GBSPHERE3DCREATOR_H
+#define GBSPHERE3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbSphere3D.h>
+
+#ifdef CAB_QT 
+#include <numerics/geometry3d/presentation/QGbSphere3DInstrument.h>
+#include <QtGui/QWidget>
+#include <QtGui/QDialog>
+#endif
+
+#ifdef CAB_VTK
+#include <numerics/geometry3d/presentation/vtkGbSphere3D.h>
+#endif
+
+#ifdef CAB_PARAVIEW 
+#include "vtkSMSourceProxy.h"
+#include "vtkSMProperty.h"
+#include "vtkSMDoubleVectorProperty.h"
+#endif
+
+class GbSphere3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbSphere3DCreator* getInstance()
+   {
+      static GbSphere3DCreator instance;
+      return &instance;
+   }
+
+   GbSphere3D* createGbObject3D() { return new GbSphere3D(); }
+
+   std::string getGbObject3DTypeID() { return "GbSphere3D"; };
+   std::string toString()            { return "GbSphere3DCreator"; }
+
+private:
+   GbSphere3DCreator( const GbSphere3DCreator& );                  //no copy allowed 
+   const GbSphere3DCreator& operator=( const GbSphere3DCreator& ); //no copy allowed
+   GbSphere3DCreator() : GbObject3DCreator() {}
+
+#ifdef CAB_QT 
+public:
+
+   GbSphere3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      GbSphere3D* sphere = this->createGbObject3D();
+      sphere->setRadius(3.0);
+      sphere->setCenterX1Coordinate(6.0);
+
+      QGbSphere3DInstrument instrument(parent, flags);
+      instrument.setGbSphere3D(sphere);
+      if (instrument.exec()) { return sphere; }
+      delete sphere;
+      return NULL;
+   }
+   QDialog* getSpecificInstrument(QWidget* parent=0, Qt::WFlags flags=0) { return new QGbSphere3DInstrument(parent, flags); }
+
+   void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+      GbSphere3D* sphere = dynamic_cast<GbSphere3D*>(gbObj);
+      if(!sphere) throw UbException(UB_EXARGS,"selected object to edit is no GbSphere3D");
+
+      QGbSphere3DInstrument instrument(parent, flags);
+      instrument.setGbSphere3D(sphere);
+      instrument.exec();
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbSphere3D(dynamic_cast<GbSphere3D*>(object)); }
+#endif
+  
+
+#ifdef CAB_PARAVIEW
+   vtkPVSource* createPVSource(vtkPVWindow *Window);
+#endif
+};
+
+#ifdef CAB_PARAVIEW                  
+vtkPVSource* GbSphere3DCreator::createPVSource(vtkPVWindow *Window)
+{
+   GbSphere3D *mysphere = this->createGbObject3D();
+   mysphere->setCenterX1Coordinate(2.0);
+   mysphere->setCenterX2Coordinate(1.0);
+   mysphere->setCenterX3Coordinate(3.0);
+   mysphere->setRadius(0.3);
+
+   vtkPVSource* pvs = Window->CreatePVSource("SphereSource");
+   pvs->CreateProperties();
+   if (pvs)
+   {
+      pvs->IsPermanentOn();
+      pvs->Accept(1, 1);
+      //pvs->SetTraceReferenceObject(this->GetWindow());
+      pvs->SetTraceReferenceObject(Window);
+   }
+   //vtkPVDisplayGUI *settingsGUI= pvs->GetPVOutput();
+
+   vtkSMSourceProxy* proxy = pvs->GetProxy();
+   vtkSMProperty *prop = proxy->GetProperty("Center");
+
+   vtkSMDoubleVectorProperty *doubleprop = vtkSMDoubleVectorProperty::SafeDownCast(proxy->GetProperty("Center"));
+   doubleprop->SetElement(0, mysphere->getX1Centroid());
+   doubleprop->SetElement(1, mysphere->getX2Centroid());
+   doubleprop->SetElement(2, mysphere->getX3Centroid());
+   pvs->SetLabel("Kugel");
+
+   doubleprop = vtkSMDoubleVectorProperty::SafeDownCast(proxy->GetProperty("Radius"));
+   doubleprop->SetElement(0, mysphere->getRadius());
+
+   pvs->GetPVWidget("Center")->ResetInternal();
+   pvs->GetPVWidget("Radius")->ResetInternal();
+
+   pvs->SetVisibility(TRUE);
+   pvs->AcceptCallback();
+   pvs->Update();
+   return pvs;
+}
+#endif
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbSphere3DCreator::getInstance()), CAB_GbSphere3DCreator);
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbTriFaceMesh3DCreator.cpp b/source/VirtualFluidsCore/Geometry/Creator/GbTriFaceMesh3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8129dfeaf8f58d17d22220dc23c9b432995b7667
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbTriFaceMesh3DCreator.cpp
@@ -0,0 +1,355 @@
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/utilities/UbTiming.h>
+
+using namespace std;
+
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   if(meshName.empty())
+   {
+      size_t pos=filename.rfind("/");
+      if(pos!=string::npos) meshName = filename.substr(pos+1);
+      else                  meshName = filename;
+   }
+
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   string ext=stlfile.getFileExtension();
+
+   //in "kleinbuchstaben" umwandeln
+   transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int))tolower); //(int(*)(int)) ist irgendso ein fieser cast, weil tolower ne alte c-methode ist
+
+   //UBLOG(logINFO, "GbTriFaceMesh3DCreator::readMeshFromFile - read " <<filename );
+
+   if     ( !ext.compare("ply" ) ) return GbTriFaceMesh3DCreator::readMeshFromPLYFile(filename, meshName,splitAlg , removeRedundantNodes);
+   else if( !ext.compare("stl" ) ) return GbTriFaceMesh3DCreator::readMeshFromSTLFile(filename, meshName,splitAlg , removeRedundantNodes);
+   else if( !ext.compare("inp" ) ) return GbTriFaceMesh3DCreator::readMeshFromAVSFile(filename, meshName,splitAlg , removeRedundantNodes);
+   else if( !ext.compare("mesh") ) return GbTriFaceMesh3DCreator::readMeshFromMeshFile(filename, meshName,splitAlg , removeRedundantNodes);
+   //else if( !ext.compare("raw") ) return GbTriFaceMesh3DCreator::readMeshFromRAWFile(filename,splitAlg , meshName);
+   else throw UbException(UB_EXARGS,"fileformat "+ext);
+
+   return NULL;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromMeshFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII meshfile(filename);
+   if(!meshfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromMeshFile(&meshfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromMeshFile(UbFileInput* in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+
+   while( !in->eof() )
+   {
+      std::string line = in->readStringLine();
+      if( line.find("Vertices") !=std::string::npos )
+         break;
+   }
+   int numVertices = in->readInteger();
+
+   UBLOG(logDEBUG1,"Number of vertices "<<numVertices);
+
+   nodes->resize(numVertices);
+   
+   float x, y, z;
+   for (int i=0; i<numVertices; i++)
+   {
+      x = in->readFloat();
+      y = in->readFloat();
+      z = in->readFloat();
+      in->readLine();
+      (*nodes)[i] = GbTriFaceMesh3D::Vertex(x,y,z);
+   }
+   UBLOG(logDEBUG1," - read vertices (#"<<numVertices<<") done");
+
+   while( !in->eof() )
+   {
+      std::string line = in->readStringLine();
+      if( line.find("Triangles") !=std::string::npos )
+         break;
+   }
+   int numFaces = in->readInteger();
+   triangles->reserve(numFaces);
+   UBLOG(logDEBUG1,"Number of faces    "<<numFaces);
+
+   int j,k,l;
+   for(int i=0; i<numFaces; i++)
+   {
+      j = in->readInteger()-1;
+      k = in->readInteger()-1;
+      l = in->readInteger()-1;
+      in->readLine();
+
+      (*triangles).push_back(GbTriFaceMesh3D::TriFace(j,k,l));
+   }
+   UBLOG(logDEBUG1," - read faces (#"<<(int)triangles->size()<<", #nonTriangles="<<(int)triangles->size()-numFaces<<") done");
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes );
+
+   return mesh;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromPLYFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII plyfile(filename);
+   if(!plyfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromPLYFile(&plyfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromPLYFile(UbFileInput* in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   //cout<<"GbTriangularMesh3DFile.readMeshFromPLYFile !!! Dieses Format hat leider redundante Knoten ..."<<endl;
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   
+   float x, y, z;
+   string dummy;
+
+   int numVertices = in->readIntegerAfterString("element vertex");
+   int numFaces    = in->readIntegerAfterString("element face");
+   in->setPosAfterLineWithString("end_header");
+   
+   UBLOG(logDEBUG1,"Number of vertices "<<numVertices);
+   UBLOG(logDEBUG1,"Number of faces    "<<numFaces);
+   
+   nodes->resize(numVertices);
+   triangles->reserve(numFaces);
+
+   int onePercent = (int)UbMath::max(1,UbMath::integerRounding(numVertices*0.01));
+   for (int i=0; i<numVertices; i++)
+   {
+      if( i%onePercent==0 )
+         cout<<" - read vertices (#"<<numVertices<<") "<<UbMath::integerRounding(i/(double)numVertices*100.0)<<"% "<<"\r"<<flush;
+      x = in->readFloat();
+      y = in->readFloat();
+      z = in->readFloat();
+      in->readLine();
+      (*nodes)[i] = GbTriFaceMesh3D::Vertex(x,y,z);
+   }
+   UBLOG(logDEBUG1," - read vertices (#"<<numVertices<<") done");
+
+   int p,j,k,l,n;
+   onePercent = (int)UbMath::max(1,UbMath::integerRounding(numFaces*0.01));
+   for(int i=0; i<numFaces; i++)
+   {
+      if( i%onePercent==0 ) cout<<" - read faces (#"<<numFaces<<") "<<UbMath::integerRounding(i/(double)numFaces*100.0)<<"% "<<"\r"<<flush;
+      
+      p = in->readInteger();
+      if(p==3)  //Dreieck, alles andere wird stumpf ingnoriert
+      {
+         j = in->readInteger();
+         k = in->readInteger();
+         l = in->readInteger();
+
+         if(   !UbMath::inClosedInterval(j,0,numVertices-1) 
+            || !UbMath::inClosedInterval(k,0,numVertices-1) 
+            || !UbMath::inClosedInterval(l,0,numVertices-1) ) 
+         {         
+            throw UbException(UB_EXARGS,"dreiecksindex ist groesser als max Knotenindex oder kleiner 0");
+         }
+         triangles->push_back(GbTriFaceMesh3D::TriFace(j,k,l));
+      }
+      else if(p==4)  //Viereck --> wird zu zwei Dreiecken!
+      {
+         j = in->readInteger();
+         k = in->readInteger();
+         l = in->readInteger();
+         n = in->readInteger();
+         numFaces++;
+         i++;
+
+         if(   !UbMath::inClosedInterval(j,0,numVertices-1) 
+            || !UbMath::inClosedInterval(k,0,numVertices-1) 
+            || !UbMath::inClosedInterval(l,0,numVertices-1) 
+            || !UbMath::inClosedInterval(n,0,numVertices-1) 
+            ) 
+         {         
+            throw UbException(UB_EXARGS,"vierecksindex ist groesser als max Knotenindex oder kleiner 0");
+         }
+         triangles->push_back(GbTriFaceMesh3D::TriFace(j,k,l));
+         triangles->push_back(GbTriFaceMesh3D::TriFace(l,n,j));
+      }
+
+      in->readLine();
+
+   }
+   UBLOG(logDEBUG1," - read faces (#"<<(int)triangles->size()<<", #nonTriangles="<<(int)triangles->size()-numFaces<<") done");
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes);
+   
+   return mesh;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromSTLFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromSTLFile(&stlfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromSTLFile(UbFileInput *in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator::readMeshFromSTLFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   double x, y, z;
+   int nr=0;
+
+   in->readLine();
+   while(dummy!="endsolid")
+   {
+      in->readLine();
+      in->readLine();
+      dummy = in->readString();
+      if(dummy!="vertex") throw UbException(UB_EXARGS,"no vertex format");
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in->readLine();
+      in->readString();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in->readLine();
+      in->readString();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      triangles->push_back(GbTriFaceMesh3D::TriFace(nr,nr+1,nr+2));
+      in->readLine();
+      in->readLine();
+      in->readLine();
+      dummy = in->readString();
+      nr+=3;
+      //std::cout<<"read mesh "<< nr <<" \n";
+   }
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes);
+   
+   return mesh;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromAVSFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromAVSFile(&stlfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromAVSFile(UbFileInput *in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg , bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator.readMeshFromAVSFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   in->readLine();
+   int numberNodes = in->readInteger();
+   int numberTris  = in->readInteger();
+   in->readLine();
+
+   double x,y,z;
+   for(int u=0;u<numberNodes;u++)
+   {
+      in->readInteger();
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      in->readLine();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+   }
+   int id1,id2,id3;
+   for(int u=0;u<numberTris;u++)
+   {
+      in->readInteger();
+      in->readInteger();
+      in->readString();
+      id1 = in->readInteger();
+      id2 = in->readInteger();
+      id3 = in->readInteger();
+      triangles->push_back(GbTriFaceMesh3D::TriFace(id1-1,id2-1,id3-1));
+   }
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes);
+   
+   return mesh;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(string filename, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(&stlfile,meshName,splitAlg,removeRedundantNodes);
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3DCreator::readMeshFromVTKASCIIFile(UbFileInput *in, string meshName, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator.readMeshFromVTKASCIIFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   vector<GbTriFaceMesh3D::Vertex>    *nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   
+   in->readString();
+   int numberNodes = in->readInteger();
+   in->readLine();
+
+   double x,y,z;
+   for(int u=0;u<numberNodes;u++)
+   {
+      x=in->readDouble();
+      y=in->readDouble();
+      z=in->readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      //cout<<u<<" - x,y,z:"<<x<<","<<y<<","<<z<<endl;
+      //x=in->readDouble();
+      //y=in->readDouble();
+      //z=in->readDouble();
+      //nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      //x=in->readDouble();
+      //y=in->readDouble();
+      //z=in->readDouble();
+      //nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      //in->readLine();
+   }
+   in->readLine();
+   in->readString();
+   int numberTris  = in->readInteger();
+   in->readLine();
+   UBLOG(logDEBUG1,"numberTris:"<<numberTris);
+
+   int id1,id2,id3;
+   for(int u=0;u<numberTris;u++)
+   {
+      in->readInteger();
+      id1 = in->readInteger();
+      id2 = in->readInteger();
+      id3 = in->readInteger();
+      triangles->push_back(GbTriFaceMesh3D::TriFace(id1,id2,id3));
+      //cout<<u<<" - id1,id2,id3:"<<id1<<","<<id2<<","<<id3<<endl;
+   }
+   UBLOG(logDEBUG1,"Tris gelesen");
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D(meshName, nodes, triangles, splitAlg, removeRedundantNodes);
+   UBLOG(logDEBUG1,"mesh erzeugt (with remove redundant nodes = "<< boolalpha <<removeRedundantNodes<<")");
+
+
+   return mesh;
+}
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbTriFaceMesh3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbTriFaceMesh3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..0fb144d8548b22c1e76999c22db0bc1a448a4ef6
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbTriFaceMesh3DCreator.h
@@ -0,0 +1,84 @@
+#ifndef GBTRIFACEMESH3DCREATOR_H
+#define GBTRIFACEMESH3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+#ifdef CAB_QT 
+#include <qfiledialog.h>    
+#endif
+
+#ifdef CAB_VTK
+#include <numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h>
+#endif
+
+class GbTriFaceMesh3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbTriFaceMesh3DCreator* getInstance()
+   {
+      static GbTriFaceMesh3DCreator instance;
+      return &instance;
+   }
+   static GbTriFaceMesh3D* readMeshFromFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromMeshFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+   static GbTriFaceMesh3D* readMeshFromMeshFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromPLYFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+   static GbTriFaceMesh3D* readMeshFromPLYFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromSTLFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true); 
+   static GbTriFaceMesh3D* readMeshFromSTLFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromAVSFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true); 
+   static GbTriFaceMesh3D* readMeshFromAVSFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   static GbTriFaceMesh3D* readMeshFromVTKASCIIFile(std::string filename, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true); 
+   static GbTriFaceMesh3D* readMeshFromVTKASCIIFile(UbFileInput* in, std::string meshName="", GbTriFaceMesh3D::KDTREE_SPLITAGORITHM splitAlg = GbTriFaceMesh3D::KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+
+   GbTriFaceMesh3D* createGbObject3D() { return new GbTriFaceMesh3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "GbTriFaceMesh3D"; };
+   std::string toString()           { return "GbTriFaceMesh3DCreator"; }
+
+#ifdef CAB_QT 
+
+
+   GbTriFaceMesh3D* createGbObject3DwithQt()
+   {
+	   //QString s = QFileDialog::getOpenFileName(NULL,NULL,NULL,"open file dialog","Choose a STL file" );
+	   QString s = QFileDialog::getOpenFileName(NULL, "Choose a STL file", "/home", "*.stl");
+      //QFileDialog* fd = new QFileDialog( NULL );
+      //fd->setIconText(QString("Hallo"));
+      //fd->show();
+      //TODO: Open File Dialog einbauen.		
+      UbFileInputASCII in( s.toAscii().data() );
+      stringstream stream;
+      stream <<"TriangularMesh3D ";//<<_objCount++;
+      GbTriFaceMesh3D *mesh = NULL;//GbTriFaceMesh3DCreator::readMeshFromSTLFile(&in, stream.str() );
+      return mesh;
+   }
+   //QDialog* getSpecificInstrument()  {  return 0;}
+   void editGbObject3DwithQt(GbObject3D* gbObj)
+   { 
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbTriangularMesh3D((GbTriangularMesh3D*)object); }
+#endif
+
+
+private:
+   GbTriFaceMesh3DCreator( const GbTriFaceMesh3DCreator& );                  //no copy allowed 
+   const GbTriFaceMesh3DCreator& operator=( const GbTriFaceMesh3DCreator& ); //no copy allowed
+   GbTriFaceMesh3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbTriFaceMesh3DCreator::getInstance()), CAB_GbTriFaceMesh3DCreator);
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbTriangle3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbTriangle3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c075d6a022824fbd59bc15f844b48bc80221f10
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbTriangle3DCreator.h
@@ -0,0 +1,31 @@
+#ifndef GBTRIANGLE3DCREATOR_H
+#define GBTRIANGLE3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+class GbTriangle3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbTriangle3DCreator* getInstance()
+   {
+      static GbTriangle3DCreator instance;
+      return &instance;
+   }
+
+   GbTriangle3D* createGbObject3D() { return new GbTriangle3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "GbTriangle3D";        }
+   std::string toString()           { return "GbTriangle3DCreator"; }
+
+private:
+   GbTriangle3DCreator( const GbTriangle3DCreator& ); //no copy allowed 
+   const GbTriangle3DCreator& operator=( const GbTriangle3DCreator& ); //no copy allowed
+   GbTriangle3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbTriangle3DCreator::getInstance()), CAB_GbTriangle3DCreator);
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbTriangularMesh3DCreator.cpp b/source/VirtualFluidsCore/Geometry/Creator/GbTriangularMesh3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bfb42296037a0b86bc374b083250e2889fa9e5ee
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbTriangularMesh3DCreator.cpp
@@ -0,0 +1,258 @@
+#include <numerics/geometry3d/creator/GbTriangularMesh3DCreator.h>
+#include <algorithm>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+                                               
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromFile(string filename, string meshName)
+{
+   if(meshName.empty())
+   {
+      size_t pos=filename.rfind("/");
+      if(pos!=string::npos) meshName = filename.substr(pos+1);
+      else                  meshName = filename; 
+   }
+   
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   string ext=stlfile.getFileExtension();
+
+   //in "kleinbuchstaben" umwandeln
+   transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int))tolower);
+
+   if     ( !ext.compare("ply") ) return GbTriangularMesh3DCreator::readMeshFromPLYFile(filename, meshName);
+   else if( !ext.compare("stl") ) return GbTriangularMesh3DCreator::readMeshFromSTLFile(filename, meshName);
+   else if( !ext.compare("gts") ) return GbTriangularMesh3DCreator::readMeshFromGTSFile(filename, meshName);
+   else if( !ext.compare("raw") ) return GbTriangularMesh3DCreator::readMeshFromRAWFile(filename, meshName);
+   else throw UbException(UB_EXARGS,"unrecognized fileformat "+ext);
+
+   return NULL;
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromSTLFile(string filename, string meshName) 
+{
+   UbFileInputASCII stlfile(filename);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+filename);
+   return GbTriangularMesh3DCreator::readMeshFromSTLFile(&stlfile,meshName);
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromSTLFile(UbFileInput* in, string meshName) 
+{
+   UBLOG(logINFO,"GbTriangularMesh3DFile.readMeshFromSTLFile !!! Dieses Format hat leider redundante Knoten ...");
+   vector<GbPoint3D*>     *nodes     = new vector<GbPoint3D*>;
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   nodes->resize(0, NULL);
+   triangles->resize(0, NULL);
+   double x, y, z;
+   //int nr=0;
+   string dummy;
+   GbPoint3D     *node1    = NULL;                      
+   GbPoint3D     *node2    = NULL;
+   GbPoint3D     *node3    = NULL;
+   GbTriangle3D *triangle = NULL;
+   in->readLine();
+   while(dummy!="endsolid")
+   {		
+      in->readLine();	
+      in->readLine();	
+      dummy = in->readString(); if(dummy!="vertex") throw UbException(UB_EXARGS,"no vertex format");
+      x=in->readDouble(); 
+      y=in->readDouble();           
+      z=in->readDouble(); 
+      node1 = new GbPoint3D(x,y,z); nodes->push_back(node1);
+      in->readLine();	
+      in->readString();	
+      x=in->readDouble();
+      y=in->readDouble(); 
+      z=in->readDouble();	
+      node2 = new GbPoint3D(x,y,z); nodes->push_back(node2);
+      in->readLine();	
+      in->readString();	
+      x=in->readDouble();
+      y=in->readDouble(); 
+      z=in->readDouble();	
+      node3 = new GbPoint3D(x,y,z); nodes->push_back(node3); 
+      triangle = new GbTriangle3D(node1, node2, node3); triangles->push_back(triangle);
+      in->readLine();
+      in->readLine();
+      in->readLine();
+      dummy = in->readString();		
+   }
+   return new GbTriangularMesh3D(meshName, nodes, triangles);
+}                                     
+/*======================================================================*/
+/**
+* Returns a triangular mesh created from the specified TICAD source ASCII stream (system.dat format).
+* @param in the input stream
+* @param meshName the name of the created mesh
+* @return a triangular mesh created from the specified TICAD source ASCII stream
+* @exception IOException if any error occurs in creating the triangular mesh
+*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromGTSFile(string inputfile, string meshName) 
+{
+   UbFileInputASCII gtlfile(inputfile);
+   if(!gtlfile) throw UbException(UB_EXARGS,"cannot open file "+inputfile);
+   return GbTriangularMesh3DCreator::readMeshFromGTSFile(&gtlfile,meshName);
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromGTSFile(UbFileInput *in, string meshName) 
+{
+   UBLOG(logINFO,"GbTriangularMesh3DFile.readMeshFromGTSFile !!! ");
+   vector<GbPoint3D*>     *nodes     = new vector<GbPoint3D*>;
+   vector<GbLine3D*>      *edges     = new vector<GbLine3D*>;
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   nodes->resize(0, NULL);
+   edges->resize(0, NULL);
+   triangles->resize(0, NULL);
+   double x, y, z;
+   int point1, point2, point3;
+   //int nr = 0;
+   //in->readLine();
+   int nodesize     = in->readInteger();
+   int edgesize     = in->readInteger();
+   int trianglesize = in->readInteger();
+   UBLOG(logINFO,"node-/edge-/trianglesize: "<<nodesize<<" / "<<edgesize<<" / "<<trianglesize);
+
+   for(int i=0; i<nodesize;i++)
+   {		
+      in->readLine();	
+      x=in->readDouble(); 
+      y=in->readDouble();  
+      z=in->readDouble(); 
+      nodes->push_back(new GbPoint3D(x,y,z));
+   }
+   for(int i=0; i<edgesize;i++)
+   {		
+      in->readLine();	
+      point1=in->readInteger()-1; 
+      point2=in->readInteger()-1; 
+      edges->push_back(new GbLine3D((*nodes)[point1],(*nodes)[point2]));
+   }
+   for(int i=0; i<trianglesize;i++)
+   {		
+      in->readLine();	
+      point1=in->readInteger();                
+      point2=in->readInteger(); 
+      point3=in->readInteger(); 
+      //triangles->push_back(new GbTriangle3D((*nodes)[point1-1],(*nodes)[point2-1],(*nodes)[point3-1]));
+      triangles->push_back(new GbTriangle3D((GbPoint3D*)(*edges)[point1-1]->getPoint1(),(GbPoint3D*)(*edges)[point2-1]->getPoint1(),(GbPoint3D*)(*edges)[point3-1]->getPoint1()));
+   }
+   return(new GbTriangularMesh3D(meshName, nodes, edges, triangles));
+}                                  
+/*======================================================================*/
+/**
+* Returns a triangular mesh created from the specified TICAD source ASCII stream (system.dat format).
+* @param in the input stream
+* @param meshName the name of the created mesh
+* @return a triangular mesh created from the specified TICAD source ASCII stream
+* @exception IOException if any error occurs in creating the triangular mesh
+*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromPLYFile(string inputfile, string meshName) 
+{
+   UbFileInputASCII plyfile(inputfile);
+   if(!plyfile) throw UbException(UB_EXARGS,"cannot open file "+inputfile);
+   return GbTriangularMesh3DCreator::readMeshFromPLYFile(&plyfile,meshName);
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromPLYFile(UbFileInput *in, string meshName) 
+{
+   //cout<<"GbTriangularMesh3DFile.readMeshFromPLYFile !!! Dieses Format hat leider redundante Knoten ..."<<endl;
+   vector<GbPoint3D*>     *nodes     = new vector<GbPoint3D*>;
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   nodes->resize(0, NULL);
+   triangles->resize(0, NULL);
+   double x, y, z;
+   int nr=0;
+   string dummy;
+   int numVertices, numFaces;
+   GbPoint3D     *node     = NULL;
+   GbPoint3D     *node1    = NULL;
+   GbPoint3D     *node2    = NULL;
+   GbPoint3D     *node3    = NULL;
+   GbTriangle3D *triangle = NULL;
+   in->readLine();
+   in->readLine();
+   in->readString(); in->readString(); numVertices = in->readInteger();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readLine();
+   in->readString(); in->readString(); numFaces = in->readInteger(); in->readLine();
+   in->readLine();
+   in->readLine();
+   UBLOG(logINFO,"Number of vertices "<<numVertices);
+   UBLOG(logINFO,"Number of faces    "<<numFaces);
+   for (int i=0; i<numVertices; i++)
+   {
+      x = in->readDouble();
+      y = in->readDouble();
+      z = in->readDouble();
+      //       cout<<x<<y<<z;
+      //       in->readString(); in->readString(); in->readString();
+      in->readLine();
+      node = new GbPoint3D(x,y,z); nodes->push_back(node); 
+   }
+   nr=0;
+
+   for (int i=0; i<numFaces; i++)
+   {
+      in->readString();
+      int j,k,l;
+      j = in->readInteger(); k = in->readInteger(); l = in->readInteger();
+      node1 = (*nodes)[j];
+      node2 = (*nodes)[k];
+      node3 = (*nodes)[l];
+      in->readLine();
+      nr++;
+      triangle = new GbTriangle3D(node1, node2, node3); triangles->push_back(triangle); 
+   }
+
+   return(new GbTriangularMesh3D(meshName, nodes, triangles));
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromRAWFile(string inputfile, string meshName) 
+{
+   UbFileInputASCII stlfile(inputfile);
+   if(!stlfile) throw UbException(UB_EXARGS,"cannot open file "+inputfile);
+   return GbTriangularMesh3DCreator::readMeshFromRAWFile(&stlfile,meshName);
+}
+/*======================================================================*/
+GbTriangularMesh3D* GbTriangularMesh3DCreator::readMeshFromRAWFile(UbFileInput *in, string meshName) 
+{
+   UBLOG(logINFO,"GbTriangularMesh3DFile.readMeshFromGTSFile !!! ");
+   vector<GbPoint3D*>     *nodes     = new vector<GbPoint3D*>;
+   vector<GbLine3D*>      *edges     = new vector<GbLine3D*>;
+   vector<GbTriangle3D*>  *triangles = new vector<GbTriangle3D*>;
+   nodes->resize(0, NULL);
+   edges->resize(0, NULL);
+   triangles->resize(0, NULL);
+   double x, y, z;
+   int point1, point2, point3;
+   //int nr = 0;
+   //in->readLine();
+   int nodesize     = in->readInteger();
+   int trianglesize = in->readInteger();
+   int edgesize = 0;
+   UBLOG(logINFO,"node-/edge-/trianglesize "<<nodesize<<" / "<<edgesize<<" / "<<trianglesize);
+
+   for(int i=0; i<nodesize;i++)
+   {		
+      in->readLine();	
+      x=in->readDouble(); 
+      y=in->readDouble();  
+      z=in->readDouble(); 
+      nodes->push_back(new GbPoint3D(x,y,z));
+   }
+   for(int i=0; i<trianglesize;i++)
+   {		
+      in->readLine();	
+      point1=in->readInteger();                
+      point2=in->readInteger(); 
+      point3=in->readInteger(); 
+      triangles->push_back(new GbTriangle3D((*nodes)[point1],(*nodes)[point2],(*nodes)[point3]));
+   }
+   return(new GbTriangularMesh3D(meshName, nodes, edges, triangles));
+}                                  
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbTriangularMesh3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbTriangularMesh3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..d090115e321256764dae67df8afcad2e07df2a7e
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbTriangularMesh3DCreator.h
@@ -0,0 +1,83 @@
+#ifndef GBTRIANGULARMESH3DCREATOR_H
+#define GBTRIANGULARMESH3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbTriangularMesh3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+
+#ifdef CAB_QT 
+#include <qfiledialog.h>    
+#endif
+
+#ifdef CAB_VTK
+#include <numerics/geometry3d/presentation/vtkGbTriangularMesh3D.h>
+#endif
+
+class GbTriangularMesh3DCreator : public GbObject3DCreator              
+{                                       
+public:
+   static GbTriangularMesh3DCreator* getInstance()
+   {
+      static GbTriangularMesh3DCreator instance;
+      return &instance;
+   }
+   
+   static GbTriangularMesh3D* readMeshFromFile(std::string filename, std::string meshName="");
+
+   static GbTriangularMesh3D* readMeshFromSTLFile(std::string filename, std::string meshName);
+   static GbTriangularMesh3D* readMeshFromGTSFile(std::string filename, std::string meshName);     
+   static GbTriangularMesh3D* readMeshFromPLYFile(std::string filename, std::string meshName);
+   //static GbTriangularMesh3D* readMeshFromAVSFile(std::string filename, std::string meshName);
+   static GbTriangularMesh3D* readMeshFromRAWFile(std::string inputFile, std::string meshName);
+
+   static GbTriangularMesh3D* readMeshFromSTLFile(UbFileInput* infile, std::string meshName);
+   static GbTriangularMesh3D* readMeshFromGTSFile(UbFileInput* infile, std::string meshName);     
+   static GbTriangularMesh3D* readMeshFromPLYFile(UbFileInput* infile, std::string meshName);
+   //static GbTriangularMesh3D* readMeshFromAVSFile(UbFileInput* infile, std::string meshName);
+   static GbTriangularMesh3D* readMeshFromRAWFile(UbFileInput* infile, std::string meshName);
+	
+   
+	GbTriangularMesh3D* createGbObject3D() { return new GbTriangularMesh3D(); }
+   
+   std::string getGbObject3DTypeID(){ return "GbTriangularMesh3D"; };
+   std::string toString()           { return "GbTriangularMesh3DCreator"; }
+
+#ifdef CAB_QT 
+
+   GbTriangularMesh3D* createGbObject3DwithQt(QWidget* parent=0, Qt::WFlags flags=0)
+   {
+	   //QString s = QFileDialog::getOpenFileName(NULL,NULL,NULL,"open file dialog","Choose a STL file" );
+	   QString s = QFileDialog::getOpenFileName(NULL, "Choose a STL file", "/home", "*.stl");
+      //QFileDialog* fd = new QFileDialog( NULL );
+      //fd->setIconText(QString("Hallo"));
+      //fd->show();
+      //TODO: Open File Dialog einbauen.		
+      UbFileInputASCII in( s.toAscii().data() );
+      stringstream stream;
+      stream <<"TriangularMesh3D ";//<<_objCount++;
+      GbTriangularMesh3D *mesh = GbTriangularMesh3DCreator::readMeshFromSTLFile(&in, stream.str() );
+      mesh->deleteRedundantNodes();
+      return mesh;
+   }
+   //QDialog* getSpecificInstrument()  {  return 0;}
+   void editGbObject3DwithQt(GbObject3D* gbObj, QWidget* parent=0, Qt::WFlags flags=0)
+   { 
+   }
+#endif
+#ifdef CAB_VTK
+public:
+   Presentator* createObjectPresentator(ObObject *object) { return new vtkGbTriangularMesh3D((GbTriangularMesh3D*)object); }
+#endif
+
+
+private:
+   GbTriangularMesh3DCreator( const GbTriangularMesh3DCreator& );                  //no copy allowed 
+   const GbTriangularMesh3DCreator& operator=( const GbTriangularMesh3DCreator& ); //no copy allowed
+   GbTriangularMesh3DCreator() : GbObject3DCreator() {}
+};
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbTriangularMesh3DCreator::getInstance()), CAB_GbTriangularMesh3DCreator);
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbVoxelMatrix3DCreator.cpp b/source/VirtualFluidsCore/Geometry/Creator/GbVoxelMatrix3DCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..52b09e9aeca68ec4f46e49edff4301782a690456
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbVoxelMatrix3DCreator.cpp
@@ -0,0 +1,84 @@
+#include <numerics/geometry3d/creator/GbVoxelMatrix3DCreator.h>
+#include <numerics/geometry3d/GbVoxelMatrix3D.h>
+#include <basics/utilities/UbFileInputASCII.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbLogger.h>
+
+using namespace std;
+
+/***************************************************************************/
+GbVoxelMatrix3D* GbVoxelMatrix3DCreator::createFromRawFloatFile(  string filename, int nodesX1, int nodesX2, int nodesX3, float threshold)
+{
+   UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromRawFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+   ifstream in(filename.c_str(), ios::binary);
+   if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+   
+   in.seekg( 0, ios::end );     //Ende springen
+   fstream::off_type length = in.tellg(); //Position abfragen
+   in.seekg( 0, ios::beg );    //An den Anfang springen 
+   if( (nodesX1*nodesX2*nodesX3)*sizeof(float) != (long)length )
+   {
+      throw UbException(UB_EXARGS,"number of nodes doesn't match filesize");
+   }
+
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+   GbVoxelMatrix3D* voxelGeo = new GbVoxelMatrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID, threshold);
+   
+   UBLOG(logINFO,"  - init values");
+   float val;
+   for(int x3=0; x3<nodesX3; x3++)
+      for(int x2=0; x2<nodesX2; x2++)
+         for(int x1=0; x1<nodesX1; x1++)
+         {
+            in.read((char*)&val,sizeof(float));
+            //if( !UbMath::equal(val, 0.0f) ) 
+            if( UbMath::greater(val, threshold) ) 
+            {
+               (*voxelGeo)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+            }
+         }
+   
+   UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromRawFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+
+   return voxelGeo;
+}
+/***************************************************************************/
+GbVoxelMatrix3D* GbVoxelMatrix3DCreator::createFromVtiASCIIFloatFile(  string filename, int nodesX1, int nodesX2, int nodesX3, float threshold)
+{
+   UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromVtiASCIIFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+   UbFileInputASCII in(filename);
+   //ifstream in(filename.c_str(), ios::binary);
+   if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   //in.readLine(); !!!manchmal hat das vti file noch die xml version dabei ...
+
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+   GbVoxelMatrix3D* voxelGeo = new GbVoxelMatrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID, threshold);
+
+   UBLOG(logINFO,"  - init values");
+   int val;
+   int u=0;
+   for(int x3=0; x3<nodesX3; x3++)
+      for(int x2=0; x2<nodesX2; x2++)
+         for(int x1=0; x1<nodesX1; x1++)
+         {
+            val = in.readInteger();
+            
+            //u++; if(u>125000) UBLOG(logINFO,"val:"<<u<<" "<<val);
+
+            //if( !UbMath::equal(val, 0.0f) ) 
+            if( UbMath::greater(val, threshold) ) 
+            {
+               (*voxelGeo)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+            }
+         }
+
+         UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromVtiASCIIFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+
+         return voxelGeo;
+}
+
diff --git a/source/VirtualFluidsCore/Geometry/Creator/GbVoxelMatrix3DCreator.h b/source/VirtualFluidsCore/Geometry/Creator/GbVoxelMatrix3DCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..33e77c6bc8c8a434629f947f28c36ded6e8d2d86
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/Creator/GbVoxelMatrix3DCreator.h
@@ -0,0 +1,81 @@
+#ifndef GBVOXELMATRIX3DCREATOR_H
+#define GBVOXELMATRIX3DCREATOR_H
+
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbVoxelMatrix3D.h>     
+#include <iostream>
+#include <fstream>
+
+class GbVoxelMatrix3DCreator : public GbObject3DCreator              
+{               
+public:
+   enum DataType {t8bit, t16bit};
+public:
+   static GbVoxelMatrix3DCreator* getInstance()
+   {
+      static GbVoxelMatrix3DCreator instance;
+      return &instance;
+   }
+
+   GbVoxelMatrix3D* createGbObject3D() { return new GbVoxelMatrix3D(); }          
+   GbVoxelMatrix3D* createFromRawFloatFile(  std::string filename, int nodesX1, int nodesX2, int nodesX3, float threshold=0.0);
+   GbVoxelMatrix3D* createFromVtiASCIIFloatFile(  std::string filename, int nodesX1, int nodesX2, int nodesX3, float threshold=0.0);
+
+   std::string getGbObject3DTypeID() { return "GbVoxelMatrix3D"; };
+   std::string toString()            { return "GbVoxelMatrix3DCreator"; }
+
+private:
+   GbVoxelMatrix3DCreator() : GbObject3DCreator() {}
+
+   GbVoxelMatrix3DCreator( const GbVoxelMatrix3DCreator& );                  //no copy allowed 
+   const GbVoxelMatrix3DCreator& operator=( const GbVoxelMatrix3DCreator& ); //no copy allowed
+
+public:
+   template< typename T >
+   GbVoxelMatrix3D* createFromRawFile(std::string filename, int nodesX1, int nodesX2, int nodesX3, float threshold)
+   {
+      UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromRawFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+
+      std::ifstream in(filename.c_str(), std::ios::binary);
+      if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+
+      in.seekg( 0, std::ios::end );     //Ende springen
+      std::fstream::off_type length = in.tellg(); //Position abfragen
+      in.seekg( 0, std::ios::beg );    //An den Anfang springen 
+      long m_size = (nodesX1*nodesX2*nodesX3)*sizeof(T);
+      if( m_size != (long)length )
+      {
+         throw UbException(UB_EXARGS,"number of nodes doesn't match filesize: " + UbSystem::toString(length));
+      }
+
+      UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+      GbVoxelMatrix3D* voxelGeo = new GbVoxelMatrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID, threshold);
+
+      UBLOG(logINFO,"  - init values");
+      T val;
+      for(int x3=0; x3<nodesX3; x3++)
+         for(int x2=0; x2<nodesX2; x2++)
+            for(int x1=0; x1<nodesX1; x1++)
+            {
+               in.read((char*)&val,sizeof(T));
+               //if( !UbMath::equal(val, 0.0f) ) 
+               //if( UbMath::greater(val, (T)threshold) ) 
+               if(val > (T)threshold)
+               {
+                  (*voxelGeo)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+               }
+            }
+
+      UBLOG(logINFO,"GbVoxelMatrix3DCreator::createFromRawFloatFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+
+      return voxelGeo;
+   }
+};
+
+
+
+#ifndef SWIG
+UB_AUTO_RUN_NAMED( GbObject3DFactory::getInstance()->addObObjectCreator(GbVoxelMatrix3DCreator::getInstance()), CAB_GbVoxelMatrix3DCreator);
+#endif
+
+#endif  //GBVOXELMATRIX3DCREATOR_H 
diff --git a/source/VirtualFluidsCore/Geometry/GbCuboid3D.cpp b/source/VirtualFluidsCore/Geometry/GbCuboid3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eae8f331512e53ec99aefd73bc55d9dadbc9aed3
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbCuboid3D.cpp
@@ -0,0 +1,633 @@
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/creator/GbCuboid3DCreator.h>
+
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+using namespace std;
+
+/*=======================================================*/
+ObObjectCreator* GbCuboid3D::getCreator()
+{
+   return GbCuboid3DCreator::getInstance();
+}
+/*=======================================================*/
+// Konstruktor
+GbCuboid3D::GbCuboid3D() : GbObject3D()
+{
+   this->setName("cuboid");
+   this->p1 = new GbPoint3D(0.0, 0.0, 0.0);
+   this->p2 = new GbPoint3D(0.0, 0.0, 0.0);
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+}
+/*=======================================================*/
+GbCuboid3D::GbCuboid3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b):GbObject3D()
+{
+   this->setName("cuboid");
+   this->p1 = new GbPoint3D(x1a, x2a, x3a);
+   this->p1->addObserver(this);
+	this->p2 = new GbPoint3D(x1b, x2b, x3b);     
+   this->p2->addObserver(this);
+}
+/*=======================================================*/
+GbCuboid3D::GbCuboid3D(GbPoint3D* p1, GbPoint3D* p2) : GbObject3D()
+{
+   this->setName("cuboid");
+	if(!p1 || !p2) throw UbException(UB_EXARGS,"one point ==NULL");
+   this->p1 = p1;
+   this->p1->addObserver(this);
+   this->p2 = p2;
+   this->p2->addObserver(this);
+}
+/*=======================================================*/
+GbCuboid3D::GbCuboid3D(GbCuboid3D* cuboid) : GbObject3D()
+{
+   this->setName("cuboid");
+   if(!cuboid->getPoint1() || !cuboid->getPoint2()) throw UbException(UB_EXARGS,"cuboid ==NULL");
+   this->p1 = cuboid->getPoint1()->clone();
+   this->p1->addObserver(this);
+   this->p2 = cuboid->getPoint2()->clone();
+   this->p2->addObserver(this);
+}
+/*=======================================================*/
+// Destruktor
+GbCuboid3D::~GbCuboid3D()
+{
+   //cout<<"~GbCuboid3D()"<<endl;
+   if(this->p1) this->p1->removeObserver(this);
+   if(this->p2) this->p2->removeObserver(this);
+}
+/*=======================================================*/
+void GbCuboid3D::finalize() 
+{ 
+   if(this->p1) 
+   {
+      this->p1->removeObserver(this);
+      this->p1->finalize();
+      delete this->p1; 
+      this->p1=NULL;
+   } 
+   if(this->p2)
+   {
+      this->p2->removeObserver(this);
+      this->p2->finalize();
+      delete this->p2; 
+      this->p2=NULL;
+   }
+}
+/*=======================================================*/
+void GbCuboid3D::setPoint1(GbPoint3D* point1)
+{ 
+   if(this->p1) this->p1->removeObserver(this);
+   this->p1 = point1;  
+   this->p1->addObserver(this);
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCuboid3D::setPoint2(GbPoint3D* point2)
+{ 
+   if(this->p2) this->p2->removeObserver(this);
+   this->p2 = point2;  
+   this->p2->addObserver(this);
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCuboid3D::setPoints(GbPoint3D* point1, GbPoint3D* point2)
+{ 
+   if(this->p1) this->p1->removeObserver(this);
+   if(this->p2) this->p2->removeObserver(this);
+
+   this->p1 = point1; 
+   this->p2 = point2;
+
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCuboid3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3) 
+{
+   this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() );
+}
+/*=======================================================*/
+double GbCuboid3D::getX1Centroid()
+{
+   return (0.5*(p1->x1 + p2->x1)); 
+}
+/*=======================================================*/
+double GbCuboid3D::getX1Minimum()   
+{
+	return (this->p1->x1 < this->p2->x1 ? this->p1->x1 : this->p2->x1);
+}
+/*=======================================================*/
+double GbCuboid3D::getX1Maximum()   
+{
+	return (this->p1->x1 > this->p2->x1 ? this->p1->x1 : this->p2->x1);
+}
+/*=======================================================*/
+double GbCuboid3D::getX2Centroid()
+{
+   return (0.5*(p1->x2 + p2->x2)); 
+}
+/*=======================================================*/
+double GbCuboid3D::getX2Minimum()   
+{
+	return (this->p1->x2 < this->p2->x2 ? this->p1->x2 : this->p2->x2);
+}	
+/*=======================================================*/
+double GbCuboid3D::getX2Maximum()   
+{
+	return ( this->p1->x2 > this->p2->x2 ? this->p1->x2 : this->p2->x2);
+}
+/*=======================================================*/
+double GbCuboid3D::getX3Centroid()
+{
+   return (0.5*(p1->x3 + p2->x3)); 
+}
+/*=======================================================*/
+double GbCuboid3D::getX3Minimum()   
+{	
+	return (this->p1->x3 < this->p2->x3 ? this->p1->x3 : this->p2->x3);
+}	
+/*=======================================================*/
+double GbCuboid3D::getX3Maximum()   
+{
+	return (this->p1->x3 > this->p2->x3 ? this->p1->x3 : this->p2->x3);
+}
+/*=======================================================*/
+double GbCuboid3D::getLengthX1() 
+{ 
+   return (this->getX1Maximum() - this->getX1Minimum() ); 
+}
+/*=======================================================*/
+double GbCuboid3D::getLengthX2() 
+{ 
+   return (this->getX2Maximum() - this->getX2Minimum());  
+}
+/*=======================================================*/
+double GbCuboid3D::getLengthX3() 
+{ 
+   return (this->getX3Maximum() - this->getX3Minimum()); 
+}
+/*=======================================================*/
+bool GbCuboid3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   //true, wenn 'in Object' oder 'auf Boundary'!
+   if     (UbMath::less(x1p,this->getX1Minimum()))    return false;
+   else if(UbMath::less(x2p,this->getX2Minimum()))    return false;
+   else if(UbMath::less(x3p,this->getX3Minimum()))    return false;
+   else if(UbMath::greater(x1p,this->getX1Maximum())) return false;
+   else if(UbMath::greater(x2p,this->getX2Maximum())) return false;
+   else if(UbMath::greater(x3p,this->getX3Maximum())) return false;
+
+   return true;
+}
+/*=======================================================*/
+bool GbCuboid3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   pointIsOnBoundary = false;
+   
+   //true, wenn 'in Object' oder 'auf Boundary'!
+   if     (UbMath::less(x1p,this->getX1Minimum()))    return false;
+	else if(UbMath::less(x2p,this->getX2Minimum()))    return false;
+	else if(UbMath::less(x3p,this->getX3Minimum()))    return false;
+	else if(UbMath::greater(x1p,this->getX1Maximum())) return false;
+	else if(UbMath::greater(x2p,this->getX2Maximum())) return false;
+	else if(UbMath::greater(x3p,this->getX3Maximum())) return false;
+	
+   if     (UbMath::equal(x1p,this->getX1Minimum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x2p,this->getX2Minimum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x3p,this->getX3Minimum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x1p,this->getX1Maximum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x2p,this->getX2Maximum())) pointIsOnBoundary = true;
+   else if(UbMath::equal(x3p,this->getX3Maximum())) pointIsOnBoundary = true;
+   
+   return true;
+}
+/*=======================================================*/
+bool GbCuboid3D::isCellInsideGbObject3D(const double& x1p1,const double& x2p1,const double& x3p1,const double& x1p2,const double& x2p2,const double& x3p2)
+{
+   if     ( UbMath::less   (x1p1, this->getX1Minimum() ) ) return false;
+   else if( UbMath::less   (x2p1, this->getX2Minimum() ) ) return false;
+   else if( UbMath::less   (x3p1, this->getX3Minimum() ) ) return false;
+   else if( UbMath::greater(x1p2, this->getX1Maximum() ) ) return false;
+   else if( UbMath::greater(x2p2, this->getX2Maximum() ) ) return false;
+   else if( UbMath::greater(x3p2, this->getX3Maximum() ) ) return false;
+
+   return true;
+}
+/*=======================================================*/
+bool GbCuboid3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der CuboidUmrandung
+//returns true:
+//  - cell cuts  cuboid3D
+//  - cell boxes cuboid3D
+//returns false:
+//  - cell completely inside cuboid3D ( = cuboid3D boxes cell)
+//  - cell und cuboid3D haben kein gemeinsames Volumen
+{
+   //erstmal die dumm Loesung
+   if(   !this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) 
+      && this->isCellInsideOrCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )
+   {
+      return true;
+   }
+
+   return false;
+
+   //GbCuboid3D* cube = GbSystem3D::clipRectangle3D(*this->p1, *this->p2, x1a,x2a,x3a,x1b,x2b,x3b);
+   //if(cube) 
+   //{
+   //   cube->finalize();
+   //   delete cube;
+   //   return true;
+   //}
+
+   //return false;
+}
+/*=======================================================*/
+bool GbCuboid3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//returns true:
+//  - cell completely inside cuboid3D ( = cuboid3D boxes cell)
+//  - cell cuts  cuboid3D
+//  - cell boxes cuboid3D
+//returns false:
+//  - cell und cuboid3D haben kein gemeinsames Volumen
+{
+    //simpler check, da unser GbCuboid3D ein AABB is:
+   //  anfA        midA         endA             anfB    midB    endB
+   //   |            x<-- dxA -->|                 |<-dxB->x       |
+   //                |<----------------- T --------------->|
+   //ist |T| <= dxA + dxB -> overlap!
+
+   if(     UbMath::lessEqual(  std::fabs( this->getX1Centroid() - 0.5*(x1b+x1a)      /*Tx1*/      )
+                             , 0.5*( this->getLengthX1()        + std::fabs(x1b-x1a) /*dx1A+dx1B*/) )
+
+        && UbMath::lessEqual(  std::fabs( this->getX2Centroid() - 0.5*(x2b+x2a)      /*Tx2*/      )
+                             , 0.5*( this->getLengthX2()        + std::fabs(x2b-x2a) /*dx2A+dx2B*/) )
+
+        && UbMath::lessEqual(  std::fabs( this->getX3Centroid() - 0.5*(x3b+x3a)      /*Tx3*/      )
+                             , 0.5*( this->getLengthX3()        + std::fabs(x3b-x3a) /*dx3A+dx3B*/) ) )
+    {
+       return true;
+    }
+
+    return false;
+
+    // if(   this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)
+   //    || this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) ) return true;
+   //
+   //return false;
+}
+/*=======================================================*/
+vector<GbTriangle3D*> GbCuboid3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles;
+   GbPoint3D p1(getX1Minimum(),getX2Minimum(),getX3Minimum());
+   GbPoint3D p2(getX1Maximum(),getX2Minimum(),getX3Minimum());
+   GbPoint3D p3(getX1Maximum(),getX2Maximum(),getX3Minimum());
+   GbPoint3D p4(getX1Minimum(),getX2Maximum(),getX3Minimum());
+   GbPoint3D p5(getX1Minimum(),getX2Minimum(),getX3Maximum());
+   GbPoint3D p6(getX1Maximum(),getX2Minimum(),getX3Maximum());
+   GbPoint3D p7(getX1Maximum(),getX2Maximum(),getX3Maximum());
+   GbPoint3D p8(getX1Minimum(),getX2Maximum(),getX3Maximum());
+
+   GbPoint3D pUnten(getX1Centroid(),getX2Centroid(),getX3Minimum());
+   GbPoint3D pOben(getX1Centroid(),getX2Centroid(),getX3Maximum());
+   GbPoint3D pLinks(getX1Minimum(), getX2Centroid(),getX3Centroid());
+   GbPoint3D pRechts(getX1Maximum(), getX2Centroid(),getX3Centroid());
+   GbPoint3D pVorne(getX1Centroid(),getX2Minimum(),getX3Centroid());
+   GbPoint3D pHinten(getX1Centroid(),getX2Maximum(),getX3Centroid());
+
+   //"unten"
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(pUnten),new GbPoint3D(p3)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(p1),new GbPoint3D(pUnten)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(pUnten),new GbPoint3D(p4)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p4),new GbPoint3D(pUnten)));
+   //"oben"
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p5),new GbPoint3D(p6),new GbPoint3D(pOben)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p6),new GbPoint3D(p7),new GbPoint3D(pOben)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p5),new GbPoint3D(pOben),new GbPoint3D(p8)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pOben),new GbPoint3D(p7),new GbPoint3D(p8)));
+   //"links"
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p4),new GbPoint3D(p1),new GbPoint3D(pLinks)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p4),new GbPoint3D(pLinks),new GbPoint3D(p8)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p8),new GbPoint3D(pLinks),new GbPoint3D(p5)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pLinks),new GbPoint3D(p1),new GbPoint3D(p5)));
+   //"rechts"                                                               
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(p3),new GbPoint3D(pRechts)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pRechts),new GbPoint3D(p3),new GbPoint3D(p7)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p2),new GbPoint3D(pRechts),new GbPoint3D(p6)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pRechts),new GbPoint3D(p7),new GbPoint3D(p6)));
+   //"hinten"                                                                       
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(p4),new GbPoint3D(pHinten)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p3),new GbPoint3D(pHinten),new GbPoint3D(p7)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p7),new GbPoint3D(pHinten),new GbPoint3D(p8)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pHinten),new GbPoint3D(p4),new GbPoint3D(p8)));
+   //"vorne"                                                                        
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p2),new GbPoint3D(pVorne)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pVorne),new GbPoint3D(p2),new GbPoint3D(p6)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(pVorne),new GbPoint3D(p5)));
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(pVorne),new GbPoint3D(p6),new GbPoint3D(p5)));
+   return triangles;
+}
+/*=======================================================*/
+void GbCuboid3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+   /*0*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Minimum(),(float)getX3Minimum()));
+   /*1*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Minimum(),(float)getX3Minimum()));
+   /*2*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Maximum(),(float)getX3Minimum()));
+   /*3*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Maximum(),(float)getX3Minimum()));
+   
+   /*4*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Minimum(),(float)getX3Maximum()));
+   /*5*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Minimum(),(float)getX3Maximum()));
+   /*6*/nodes.push_back( makeUbTuple((float)getX1Maximum(),(float)getX2Maximum(),(float)getX3Maximum()));
+   /*7*/nodes.push_back( makeUbTuple((float)getX1Minimum(),(float)getX2Maximum(),(float)getX3Maximum()));
+
+   //"unten"
+   triangles.push_back( makeUbTuple( 0, 1, 2) );
+   triangles.push_back( makeUbTuple( 0, 2, 3) );
+   //"oben"
+   triangles.push_back( makeUbTuple( 4, 5, 6) );
+   triangles.push_back( makeUbTuple( 4, 6, 7) );
+   //"links"
+   triangles.push_back( makeUbTuple( 0, 3, 7) );
+   triangles.push_back( makeUbTuple( 0, 7, 4) );
+   //"rechts"                                                               
+   triangles.push_back( makeUbTuple( 1, 2, 6) );
+   triangles.push_back( makeUbTuple( 1, 6, 5) );
+   //"hinten"                                                                       
+   triangles.push_back( makeUbTuple( 3, 2, 7) );  
+   triangles.push_back( makeUbTuple( 2, 7, 6) );
+   //"vorne"                                                                        
+   triangles.push_back( makeUbTuple( 0, 1, 5) );
+   triangles.push_back( makeUbTuple( 0, 5, 4) );
+}
+/*=======================================================*/
+string GbCuboid3D::toString() 
+{
+   stringstream ss;
+   ss<<"GbCuboid3D[";
+   ss<<"p1="<<this->p1->toString();
+   ss<<", p2="<<this->p2->toString();
+   ss<<"]";
+   return ss.str();
+}
+/*=======================================================*/
+GbPoint3D* GbCuboid3D::calculateInterSectionPoint3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"not correct implemented");
+}
+/*=======================================================*/
+GbLine3D* GbCuboid3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   return GbSystem3D::createClipLine3D(point1, point2,
+                                       p1->getX1Coordinate(),p1->getX2Coordinate(),p1->getX3Coordinate(),
+                                       p2->getX1Coordinate(),p2->getX2Coordinate(),p2->getX3Coordinate() );
+}
+/*==========================================================*/
+void GbCuboid3D::objectChanged(UbObservable* changedObject)
+{
+   GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject);
+   if(!point || (this->p1!=point && this->p2!=point)) return;
+
+   this->notifyObserversObjectChanged();
+}
+/*==========================================================*/
+void GbCuboid3D::objectWillBeDeleted(UbObservable* objectForDeletion)
+{
+   if(this->p1)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p1);
+      if(objectForDeletion == observedObj) { this->p1 = NULL; }
+   }
+   if(this->p2)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p2);
+      if(objectForDeletion == observedObj) { this->p2 = NULL; }
+   }
+   //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo
+}
+/*=======================================================*/
+void GbCuboid3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   p1->write(out);
+   p2->write(out);
+}
+/*=======================================================*/
+void GbCuboid3D::read(UbFileInput* in) 
+{  
+   in->readString();                                    
+   this->p1 = new GbPoint3D;
+   p1->read(in);
+   in->readString();                                    
+   this->p2 = new GbPoint3D;
+   p2->read(in);
+}
+/*=======================================================*/
+void GbCuboid3D::translate(const double& tx1, const double& tx2, const double& tx3)
+{  
+   this->p1->translate(tx1, tx2, tx3);
+   this->p2->translate(tx1, tx2, tx3);
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCuboid3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{  
+   double lenX1 = this->getLengthX1();
+   double lenX2 = this->getLengthX2();
+   double lenX3 = this->getLengthX3();
+
+   double deltaX1 = lenX1*sx1 - lenX1;
+   double deltaX2 = lenX2*sx2 - lenX2;
+   double deltaX3 = lenX3*sx3 - lenX3;
+
+   double p1X1 = this->p1->getX1Coordinate();
+   double p1X2 = this->p1->getX2Coordinate();
+   double p1X3 = this->p1->getX3Coordinate();
+
+   double p2X1 = this->p2->getX1Coordinate();
+   double p2X2 = this->p2->getX2Coordinate();
+   double p2X3 = this->p2->getX3Coordinate();
+
+   this->p1->setCoordinates(p1X1 - 0.5*deltaX1
+                           ,p1X2 - 0.5*deltaX2
+                           ,p1X3 - 0.5*deltaX3);
+
+   this->p2->setCoordinates(p2X1 + 0.5*deltaX1
+                           ,p2X2 + 0.5*deltaX2
+                           ,p2X3 + 0.5*deltaX3);
+}
+/*==========================================================*/
+double GbCuboid3D::getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   if( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )       return 1.0*(x1b-x1a)*(x2b-x2a)*(x3b-x3a);
+   if( !(this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)) )   return 0.0;
+
+   GbCuboid3D* cube = GbSystem3D::clipRectangle3D(*this->p1, *this->p2, x1a,x2a,x3a,x1b,x2b,x3b);
+
+   if(cube) 
+   {
+      double eps;
+      eps  = (cube->getLengthX1())*(cube->getLengthX2())*(cube->getLengthX3());
+      cube->finalize();
+      delete cube;
+      return eps;
+   }
+   return 0.0;
+}
+/*==========================================================*/
+double GbCuboid3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   double minB[3]   = { this->getX1Minimum(), this->getX2Minimum(), this->getX3Minimum() };
+   double maxB[3]   = { this->getX1Maximum(), this->getX2Maximum(), this->getX3Maximum() };
+   double origin[3] = { x1,  x2,  x3  }; //point
+   double dir[3]    = { rx1, rx2, rx3 }; //ray 
+
+   bool inside = true;
+   char quadrant[3];
+   int  whichPlane;
+   double maxT[3];
+   double candidatePlane[3];
+
+   /* Find candidate planes; this loop can be avoided if
+   rays cast all from the eye(assume perpsective view) */
+   for(int i=0; i<3; i++)
+   {
+      if(origin[i] < minB[i])
+      {
+         quadrant[i] = 1/*LEFT*/;
+         candidatePlane[i] = minB[i];
+         inside = false;
+      }
+      else if(origin[i] > maxB[i]) 
+      {
+         quadrant[i] = 0/*RIGHT*/;
+         candidatePlane[i] = maxB[i];
+         inside = false;
+      }
+      else	
+      {
+         quadrant[i] = 2/*MIDDLE*/;
+      }
+   }
+   /* Ray origin inside bounding box */
+   if(inside)
+   {
+      //throw UbException(UB_EXARGS,"not done");
+      return 0.0;
+   }
+
+   /* Calculate T distances to candidate planes */
+   for(int i=0; i<3; i++)
+   {
+      if( quadrant[i]!=2/*MIDDLE*/ && fabs(dir[i])>1.E-10 )
+      {
+         maxT[i] = (candidatePlane[i]-origin[i])/dir[i];
+      }
+      else maxT[i] = -1.0;
+   }
+
+   /* Get largest of the maxT's for final choice of intersection */
+   whichPlane = 0;
+   for(int i=1; i<3; i++)
+      if (maxT[whichPlane] < maxT[i])
+            whichPlane = i;
+   
+   /* Check final candidate actually inside box */
+   if(maxT[whichPlane]< -1.E-10) return -1.0;
+   double dummy;
+   for(int i= 0; i<3; i++)
+   {
+      if( whichPlane!= i) 
+      {
+         dummy = origin[i] + maxT[whichPlane]*dir[i];
+         if(dummy < minB[i] || dummy > maxB[i])
+            return -1.0;
+      } 
+   }
+
+   return maxT[whichPlane] ;				/* ray hits box */
+}	
+// /*==========================================================*/
+// double GbCuboid3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+// {
+//     double absX,absMaxX,absY,absMaxY,absZ,absMaxZ;
+//  
+//     if(rx1<0.0)     absX    = this->getX1Maximum() - x1;
+//     else            absX    = this->getX1Minimum() - x1;
+//     if(1-(rx1<0.0)) absMaxX = this->getX1Maximum() - x1;
+//     else            absMaxX = this->getX1Minimum() - x1;
+//  
+//     if(rx2<0.0)     absY    = this->getX2Maximum() - x2;
+//     else            absY    = this->getX2Minimum() - x2;
+//     if(1-(rx2<0.0)) absMaxY = this->getX2Maximum() - x2;
+//     else            absMaxY = this->getX2Minimum() - x2;
+//  
+//     if(rx3<0.0)     absZ    = this->getX3Maximum() - x3;
+//     else            absZ    = this->getX3Minimum() - x3;
+//     if(1-(rx3<0.0)) absMaxZ = this->getX3Maximum() - x3;
+//     else            absMaxZ = this->getX3Minimum() - x3;
+//  
+//     
+//     //tmin ist die verschneidung des Gerade (Ray) durch die naehere Gerade (MinX oder MaxX)
+//     //tmax ist die verschneidung des Gerade (Ray) durch die weiteste Gerade (MinX oder MaxX)
+//     //analog fuer tymin und tymax 
+//     double tmin, tymin, tzmin, tmax, tymax, tzmax;
+// 
+//     if(!UbMath::zero(rx1)) tmin  = tmax  = 1.0/rx1;     
+//     else if(rx1<0.0)       tmin  = tmax  = -UbMath::getPositiveInfinity<double>();
+//     else                   tmin  = tmax  = UbMath::getPositiveInfinity<double>();
+// 
+//     if(!UbMath::zero(rx2)) tymin = tymax = 1.0/rx2;     
+//     else if(rx2<0.0)       tymin = tymax = -UbMath::getPositiveInfinity<double>();
+//     else                   tymin = tymax = UbMath::getPositiveInfinity<double>();
+// 
+//     if(!UbMath::zero(rx3)) tzmin = tzmax = 1.0/rx3;     
+//     else if(rx1<0.0)       tzmin = tzmax = -UbMath::getPositiveInfinity<double>();
+//     else                   tzmin = tzmax = UbMath::getPositiveInfinity<double>();
+// 
+//     //tmin  *= absX;
+//     //tmax  *= absMaxX;
+//     //tymin *= absY;
+//     //tymax *= absMaxY;
+//     //tzmin *= absZ;
+//     //tzmax *= absMaxZ;
+//  
+//     //0 * 1/0  vermeiden, da es ein Undefined wert produziert 
+//     if( !UbMath::zero(absX) || !UbMath::zero(rx1) ) tmin *= absX;
+//     else                                            tmin  = tymin;
+// 
+//     if( !UbMath::zero(absY) || !UbMath::zero(rx2))    tymin *= absY;
+//     else                                              tymin  = tmin;
+//     
+//     if( !UbMath::zero(absZ) || !UbMath::zero(rx3))    tzmin *= absZ;
+//     else                                              tzmin  = tymin;
+//  
+//     if( !UbMath::zero(absMaxX) || !UbMath::zero(rx1)) tmax *= absMaxX;
+//     else                                              tmax  = tymax;
+//     
+//     if( !UbMath::zero(absMaxY) || !UbMath::zero(rx2)) tymax *= absMaxY;
+//     else                                              tymax  = tmax;
+//     
+//     if( !UbMath::zero(absMaxZ) || !UbMath::zero(rx3)) tzmax *= absMaxZ;
+//     else                                              tzmax = tymax;
+//  
+//     //in dieser Fall gibt es keine Verschneidung
+//     if( (tmin > tymax) || (tymin > tmax) ) return -1;
+// 
+//     tmin = UbMath::max3(tmin,tymin,tzmin);
+//     tmax = UbMath::min3(tmax,tymax,tzmax);
+//  
+//     if( (tmin > tzmax) || (tzmin > tmax) ) return -1;
+//     if(tmin >= 0.0) return tmin ;
+//  
+//     return tmax;
+//}
diff --git a/source/VirtualFluidsCore/Geometry/GbCuboid3D.h b/source/VirtualFluidsCore/Geometry/GbCuboid3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ae16a6cf319de978e01ba29c2ddbce104a2a72b
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbCuboid3D.h
@@ -0,0 +1,144 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBCUBOID3D_H
+#define GBCUBOID3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <vector>
+#include <cmath>
+
+#include "GbPoint3D.h
+#include "UbObserver.h"
+#include "UbMath.h"
+
+class GbLine3D;
+class GbObject3DCreator;
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbCuboid3D;
+typedef VFSharedPtr<GbCuboid3D> GbCuboid3DPtr;
+
+
+class GbCuboid3D : public GbObject3D, public UbObserver
+{
+public:              
+   GbCuboid3D();
+   GbCuboid3D(const double& minX1,const double& minX2, const double& minX3, const double& maxX1,const double& maxX2, const double& maxX3);
+   GbCuboid3D(GbPoint3D *p1, GbPoint3D *p2);
+   GbCuboid3D(GbCuboid3D *cuboid);
+   ~GbCuboid3D();   
+
+   GbCuboid3D* clone()    { return new GbCuboid3D(this); }
+   void finalize();
+
+   GbPoint3D* getPoint1() { return this->p1; }
+   GbPoint3D* getPoint2() { return this->p2; }
+
+   void setPoint1(GbPoint3D* point1);
+   void setPoint2(GbPoint3D* point2);
+   void setPoints(GbPoint3D* point1, GbPoint3D* point2);
+
+   double getX1Centroid();
+   double getX1Minimum();
+   double getX1Maximum();
+   double getX2Centroid();
+   double getX2Minimum();
+   double getX2Maximum();
+   double getX3Centroid();
+   double getX3Minimum();
+   double getX3Maximum();
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+
+   void translate(const double& x1, const double& x2, const double& x3);
+   void rotate(const double& rx1, const double& rx2, const double& rx3) {}
+   void scale(const double& sx1, const double& sx2, const double& sx3);
+
+   double getLengthX1();
+   double getLengthX2();
+   double getLengthX3();
+
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary);
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); 
+   bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+   GbPoint3D*  calculateInterSectionPoint3D(GbPoint3D& point1, GbPoint3D &point2);
+   //GbCuboid3D* createClippedRectangle3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   GbLine3D*   createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+
+   double getDistance(GbPoint3D* p)
+   {
+      return this->getDistance( p->getX1Coordinate(), p->getX2Coordinate(), p->getX3Coordinate() );
+   } 
+   double getDistance(const double& x1p, const double& x2p, const double& x3p)
+   {
+      throw UbException( UB_EXARGS, "not implemented" );
+
+      // falls punkt innerhalt ist: minimalen abstand ausrechnen
+      if( this->isPointInGbObject3D(x1p,x2p,x3p) )
+      {
+         double x1Dist = UbMath::min( std::abs(x1p-this->getX1Minimum()),std::abs(x1p-this->getX1Maximum()) );
+         double x2Dist = UbMath::min( std::abs(x2p-this->getX2Minimum()),std::abs(x2p-this->getX2Maximum()) );
+         double x3Dist = UbMath::min( std::abs(x3p-this->getX3Minimum()),std::abs(x3p-this->getX3Maximum()) );
+
+         return UbMath::min( x1Dist, x2Dist, x3Dist );
+      }
+      else
+      {
+
+      }
+   }
+
+   std::string toString();
+
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject);
+   void objectWillBeDeleted(UbObservable* objectForDeletion);
+
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & p1;
+      ar & p2;
+   }
+#endif //CAB_RCF
+
+protected:
+   GbPoint3D* p1;
+   GbPoint3D* p2;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbCuboid3D>("GbCuboid3D")             , SF_GbCuboid3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbCuboid3D >()), SF_GbCuboid3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbCuboid3D>() ), SF_GbCuboid3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+#endif   
diff --git a/source/VirtualFluidsCore/Geometry/GbCylinder3D.cpp b/source/VirtualFluidsCore/Geometry/GbCylinder3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e439a52966dc20ca95cdc965da9d890ccd8a01e8
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbCylinder3D.cpp
@@ -0,0 +1,1262 @@
+#include <numerics/geometry3d/GbCylinder3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <basics/utilities/UbInfinity.h>
+
+#include <numerics/geometry3d/creator/GbCylinder3DCreator.h>
+
+using namespace std;
+
+/*=======================================================*/
+ObObjectCreator* GbCylinder3D::getCreator()
+{
+   return GbCylinder3DCreator::getInstance();
+}
+// Konstruktor
+/*==========================================================*/
+GbCylinder3D::GbCylinder3D()
+   : minX1(0.0)   , minX2(0.0)   , minX3(0.0)
+   , maxX1(0.0)   , maxX2(0.0)   , maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   GbPoint3D* p1 = new GbPoint3D();
+   GbPoint3D* p2 = new GbPoint3D();
+   mLine = new GbLine3D(p1,p2);
+   this->mLine->addObserver(this);
+   mRad = 0.0;
+   cylinderType = GbCylinder3D::NOTPARALLELTOAXIS;
+   this->mLine->addObserver(this);
+   this->calculateValues();
+}
+/*=======================================================*/
+GbCylinder3D::GbCylinder3D(GbCylinder3D* cylinder)
+   : minX1(0.0)   , minX2(0.0)   , minX3(0.0)
+   , maxX1(0.0)   , maxX2(0.0)   , maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   mRad         = cylinder->getRadius();
+   cylinderType = cylinder->cylinderType;
+   mLine        = cylinder->getLine()->clone();
+
+   this->mLine->addObserver(this);
+   this->calculateValues();
+}
+/*==========================================================*/
+GbCylinder3D::GbCylinder3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b, const double& rad)
+   : minX1(0.0)   , minX2(0.0)   , minX3(0.0)
+   , maxX1(0.0)   , maxX2(0.0)   , maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   mLine = new GbLine3D;
+   //Min/Max, damit gewaehrleistet ist, dass Startpunkt immer der "Achs-Minimale" ist
+   //Anm.: bin nich tsicher ob weiter unten irgendwelche Algos drauf beruhen...
+   //      geht nat nur solange, zylinder achs-parallel, aber das ist erzeit so!!!
+   mLine->setPoints( new GbPoint3D(min(x1a,x1b), min(x2a,x2b), min(x3a,x3b))
+	                 ,new GbPoint3D(max(x1a,x1b), max(x2a,x2b), max(x3a,x3b)));
+   //mLine->setPoints( new GbPoint3D(x1a,x2a,x3a),new GbPoint3D(x1b, x2b ,x3b ));
+   this->mLine->addObserver(this);
+   mRad = fabs(rad);
+
+   this->calculateValues();
+}
+/*==========================================================*/
+GbCylinder3D::GbCylinder3D(GbPoint3D* p1, GbPoint3D* p2, const double& rad)
+   : minX1(0.0), minX2(0.0), minX3(0.0)
+   , maxX1(0.0), maxX2(0.0), maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   mRad = rad;
+
+   mLine = new GbLine3D(p1,p2);
+   this->mLine->addObserver(this);
+   this->calculateValues();
+}
+/*==========================================================*/
+GbCylinder3D::GbCylinder3D(GbLine3D* line, const double& rad)
+   : minX1(0.0), minX2(0.0), minX3(0.0)
+   , maxX1(0.0), maxX2(0.0), maxX3(0.0)
+   , centerX1(0.0), centerX2(0.0), centerX3(0.0)
+{
+   this->setName("cylinder");
+   mRad = rad;
+
+   this->mLine = line;
+   this->mLine->addObserver(this);
+
+   this->calculateValues();
+}
+/*==========================================================*/
+// Destruktor
+GbCylinder3D::~GbCylinder3D()
+{
+   if(mLine) this->mLine->removeObserver(this);
+   mLine = NULL;
+}
+/*=======================================================*/
+void GbCylinder3D::calculateValues()
+{
+   double x1a = mLine->getPoint1()->x1;    double x1b = mLine->getPoint2()->x1;
+   double x2a = mLine->getPoint1()->x2;    double x2b = mLine->getPoint2()->x2;
+   double x3a = mLine->getPoint1()->x3;    double x3b = mLine->getPoint2()->x3;
+
+   if     (x1a!=x1b && x2a==x2b && x3a==x3b)  this->cylinderType = X1PARALLEL;
+   else if(x2a!=x2b && x1a==x1b && x3a==x3b)  this->cylinderType = X2PARALLEL;
+   else if(x3a!=x3b && x1a==x1b && x2a==x2b)  this->cylinderType = X3PARALLEL;
+   // nach dem serialisieren ruft er den Standardkonstruktor auf wo alles 0 ist und bricht sonst hier ab
+   else if(x3a==x3b && x1a==x1b && x2a==x2b)  this->cylinderType = X1PARALLEL; 
+   else                                       this->cylinderType = NOTPARALLELTOAXIS;
+
+   if((this->cylinderType & NOTPARALLELTOAXIS)==NOTPARALLELTOAXIS)
+      throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Zylinder erlaubt... isPointInObject3D funzt sonst ned");
+
+   if(this->isParallelToX1Axis())
+   {
+      minX1 = mLine->getX1Minimum();
+      maxX1 = mLine->getX1Maximum();
+      minX2 = mLine->getX2Centroid()-mRad; 
+      maxX2 = mLine->getX2Centroid()+mRad;
+      minX3 = mLine->getX3Centroid()-mRad; 
+      maxX3 = mLine->getX3Centroid()+mRad;
+   }
+   else if(this->isParallelToX2Axis()) 
+   {
+      minX1 = mLine->getX1Centroid()-mRad;
+      maxX1 = mLine->getX1Centroid()+mRad;
+      minX2 = mLine->getX2Minimum();   
+      maxX2 = mLine->getX2Maximum();
+      minX3 = mLine->getX3Centroid()-mRad;
+      maxX3 = mLine->getX3Centroid()+mRad;
+   }
+   else if(this->isParallelToX3Axis()) 
+   {
+      minX1 = mLine->getX1Centroid()-mRad;  
+      maxX1 = mLine->getX1Centroid()+mRad;
+      minX2 = mLine->getX2Centroid()-mRad;
+      maxX2 = mLine->getX2Centroid()+mRad;
+      minX3 = mLine->getX3Minimum();
+      maxX3 = mLine->getX3Maximum();
+   }
+
+   centerX1 = mLine->getX1Centroid();
+   centerX2 = mLine->getX2Centroid();
+   centerX3 = mLine->getX3Centroid();
+}
+ 
+/*=======================================================*/
+void GbCylinder3D::finalize()
+{
+   if(this->mLine)
+   {
+      mLine->finalize();
+      delete mLine;
+      mLine=NULL;
+   }
+}
+/*=======================================================*/
+double GbCylinder3D::getHeight()
+{
+   if(mLine) return mLine->getLength(); return 0.0;
+}
+/*=======================================================*/
+GbPoint3D* GbCylinder3D::getPoint1()
+{
+   if(this->mLine) return this->mLine->getPoint1();
+   return NULL;
+}
+/*=======================================================*/
+GbPoint3D* GbCylinder3D::getPoint2()
+{
+   if(this->mLine) return this->mLine->getPoint2();
+   return NULL;
+}
+/*=======================================================*/
+void GbCylinder3D::setRadius(const double& radius)
+{
+   this->mRad = std::fabs(radius);
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCylinder3D::setLine(GbLine3D* line)
+{
+   if(this->mLine) this->mLine->removeObserver(this);
+   this->mLine = line;
+   this->mLine->addObserver(this);
+   this->calculateValues();
+
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbCylinder3D::setPoint1(const double& x1, const double& x2, const double& x3)
+{
+   if(!mLine->getPoint1()) throw UbException(UB_EXARGS,"line has no point1");
+   mLine->getPoint1()->setCoordinates(x1,x2,x3);
+   this->calculateValues();
+
+   //this->notifyObserversObjectChanged(); //wird automatisch aufgerufen, da der point (this) benachrichtigt...
+}
+/*=======================================================*/
+void GbCylinder3D::setPoint2(const double& x1, const double& x2, const double& x3)
+{
+   if(!mLine->getPoint2()) throw UbException(UB_EXARGS,"line has no point2");
+   mLine->getPoint2()->setCoordinates(x1,x2,x3);
+   this->calculateValues();
+
+   //this->notifyObserversObjectChanged(); //wird automatisch aufgerufen, da der point (this) benachrichtigt...
+}
+/*==========================================================*/
+bool GbCylinder3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   //true, wenn 'in Object' oder 'auf Boundary'!
+   if     ( this->isParallelToX1Axis() && (UbMath::less(x1p,minX1) || UbMath::greater(x1p,maxX1)))  return false;
+   else if( this->isParallelToX2Axis() && (UbMath::less(x2p,minX2) || UbMath::greater(x2p,maxX2)))  return false;
+   else if( this->isParallelToX3Axis() && (UbMath::less(x3p,minX3) || UbMath::greater(x3p,maxX3)))  return false;
+   else if( this->isNotParallelToAxis() ) throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Zylinder erlaubt... isPointInObject3D funzt sonst ned");
+
+   return UbMath::lessEqual(fabs(mLine->getDistance(x1p,x2p,x3p)),fabs(mRad));
+}
+/*==========================================================*/
+bool GbCylinder3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   //funzt derzeit nur bei achsparallelen cylindern
+   pointIsOnBoundary = false;
+
+   if     ( this->isParallelToX1Axis() && (UbMath::less(x1p,minX1) || UbMath::greater(x1p,maxX1)))  return false;
+   else if( this->isParallelToX2Axis() && (UbMath::less(x2p,minX2) || UbMath::greater(x2p,maxX2)))  return false;
+   else if( this->isParallelToX3Axis() && (UbMath::less(x3p,minX3) || UbMath::greater(x3p,maxX3)))  return false;
+   else if( this->isNotParallelToAxis() ) throw UbException(UB_EXARGS,"derzeit nur zu Achsen orthogonale Zylinder erlaubt... isPointInObject3D funzt sonst ned");
+
+   //true, wenn 'in Object' oder 'auf Boundary'!
+
+   double dis = mLine->getDistance(x1p,x2p,x3p);
+
+   if(UbMath::equal(dis,mRad)) pointIsOnBoundary = true;
+ 
+   if     (this->isParallelToX1Axis() && (UbMath::equal(x1p,minX1) || UbMath::equal(x1p,maxX1))) pointIsOnBoundary = true;
+   else if(this->isParallelToX2Axis() && (UbMath::equal(x2p,minX2) || UbMath::equal(x2p,maxX2))) pointIsOnBoundary = true;
+   else if(this->isParallelToX3Axis() && (UbMath::equal(x3p,minX3) || UbMath::equal(x3p,maxX3))) pointIsOnBoundary = true;
+
+   return UbMath::lessEqual(dis,mRad);
+}
+/*==========================================================*/
+string GbCylinder3D::toString()
+{
+	stringstream ss;
+	ss<<"GbCylinder3D[";
+	ss<<"line="<<this->mLine->toString();
+   ss<<", r="<<this->mRad;
+   ss<<"]";
+   return(ss.str());
+}
+/*=======================================================*/
+bool GbCylinder3D::isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   if(   this->isPointInGbObject3D(x1a, x2a, x3a)
+      && this->isPointInGbObject3D(x1b, x2a, x3a)
+      && this->isPointInGbObject3D(x1b, x2b, x3a)
+      && this->isPointInGbObject3D(x1a, x2b, x3a)
+      && this->isPointInGbObject3D(x1a, x2a, x3b)
+      && this->isPointInGbObject3D(x1b, x2a, x3b)
+      && this->isPointInGbObject3D(x1b, x2b, x3b)
+      && this->isPointInGbObject3D(x1a, x2b, x3b))
+   {
+      return true;
+   }
+   return false;
+}
+/*==========================================================*/
+bool GbCylinder3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der CuboidUmrandung
+//returns true:
+//  - cell cuts  cylinder3D
+//  - cell boxes cylinder3D
+//returns false:
+//  - cell completely inside cylinder3D ( = cylinder3D boxes cell)
+//  - cell und cylinder3D haben kein gemeinsames Volumen
+{
+   //erstmal wieder die dumm Loesung
+   if(   this->isCellInsideOrCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)
+      && !this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )
+   {
+      return true;
+   }
+
+   return false;
+}
+/*==========================================================*/
+bool GbCylinder3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//returns true:
+//  - cell completely inside cylinder3D ( = cylinder3D boxes cell)
+//  - cell cuts  cylinder3D
+//  - cell boxes cylinder3D
+//returns false:
+//  - cell und cylinder3D haben kein gemeinsames Volumen
+{
+   double dmin   = 0.0;
+
+   if(this->isParallelToX1Axis())
+   {
+      //check liegt Cell komplett !x1-ausserhalb"?
+      if(  UbMath::less   (x1a,minX1) && UbMath::less   (x1b,minX1) ) return false;
+      if(  UbMath::greater(x1a,maxX1) && UbMath::greater(x1b,maxX1) ) return false;
+
+      //mittelpunkt kreis-querschnitt
+      double& midX2 = mLine->getPoint1()->x2;
+      double& midX3 = mLine->getPoint1()->x3;
+      if     ( UbMath::less   ( midX2, x2a ) ) dmin += std::pow( midX2 - x2a, 2.0 ); 
+      else if( UbMath::greater( midX2, x2b ) ) dmin += std::pow( midX2 - x2b, 2.0 );     
+      if     ( UbMath::less   ( midX3, x3a ) ) dmin += std::pow( midX3 - x3a, 2.0 ); 
+      else if( UbMath::greater( midX3, x3b ) ) dmin += std::pow( midX3 - x3b, 2.0 );     
+      if( UbMath::lessEqual( dmin, mRad*mRad) ) return true;
+
+      return false;
+   }
+   else if(this->isParallelToX2Axis())
+   {
+      //check liegt Cell komplett !x2-ausserhalb"?
+      if(  UbMath::less   (x2a,minX2)   && UbMath::less   (x2b,minX2) ) return false;
+      if(  UbMath::greater(x2a,maxX2  ) && UbMath::greater(x2b,maxX2) ) return false;
+
+      //mittelpunkt kreis-querschnitt
+      double& midX1 = mLine->getPoint1()->x1;
+      double& midX3 = mLine->getPoint1()->x3;
+      if     ( UbMath::less   ( midX1, x1a ) ) dmin += std::pow( midX1 - x1a, 2.0 ); 
+      else if( UbMath::greater( midX1, x1b ) ) dmin += std::pow( midX1 - x1b, 2.0 );     
+      if     ( UbMath::less   ( midX3, x3a ) ) dmin += std::pow( midX3 - x3a, 2.0 ); 
+      else if( UbMath::greater( midX3, x3b ) ) dmin += std::pow( midX3 - x3b, 2.0 );     
+      if( UbMath::lessEqual( dmin, mRad*mRad ) ) return true;
+
+   }
+   else if(this->isParallelToX3Axis())
+   {
+      //check liegt Cell komplett !x3-ausserhalb"?
+      if(  UbMath::less   (x3a,minX3) && UbMath::less   (x3b,minX3) ) return false;
+      if(  UbMath::greater(x3a,maxX3) && UbMath::greater(x3b,maxX3) ) return false;
+
+      //mittelpunkt kreis-querschnitt
+      double& midX1 = mLine->getPoint1()->x1;
+      double& midX2 = mLine->getPoint1()->x2;
+      if     ( UbMath::less   ( midX1, x1a ) ) dmin += std::pow( midX1 - x1a, 2.0 ); 
+      else if( UbMath::greater( midX1, x1b ) ) dmin += std::pow( midX1 - x1b, 2.0 );     
+      if     ( UbMath::less   ( midX2, x2a ) ) dmin += std::pow( midX2 - x2a, 2.0 ); 
+      else if( UbMath::greater( midX2, x2b ) ) dmin += std::pow( midX2 - x2b, 2.0 );     
+      if( UbMath::lessEqual( dmin, mRad*mRad ) ) return true;
+   }
+
+   return false;
+}
+/*==========================================================*/
+GbLine3D* GbCylinder3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   //liefert immer "innere" linie, also der teil, der vom Zylinder "abgeschnitten" wurde!
+   //funktioniert derzeit nur mit achsenparallelen Zylindern!
+   vector<GbPoint3D*> schnittpunkte;
+
+   double xa,ya,za,xb,yb,zb,xm,ym,zStart,zEnd,t1,t2;
+
+   if(this->isParallelToX1Axis())
+   {
+      xa     = point1.getX2Coordinate();
+      ya     = point1.getX3Coordinate();
+      za     = point1.getX1Coordinate();
+      xb     = point2.getX2Coordinate();
+      yb     = point2.getX3Coordinate();
+      zb     = point2.getX1Coordinate();
+      xm     = mLine->getPoint1()->getX2Coordinate();
+      ym     = mLine->getPoint1()->getX3Coordinate();
+      zStart = mLine->getPoint1()->getX1Coordinate();
+      zEnd   = mLine->getPoint2()->getX1Coordinate();
+   }
+   else if(this->isParallelToX2Axis())
+   {
+      xa     = point1.getX1Coordinate();
+      ya     = point1.getX3Coordinate();
+      za     = point1.getX2Coordinate();
+      xb     = point2.getX1Coordinate();
+      yb     = point2.getX3Coordinate();
+      zb     = point2.getX2Coordinate();
+      xm     = mLine->getPoint1()->getX1Coordinate();
+      ym     = mLine->getPoint1()->getX3Coordinate();
+      zStart = mLine->getPoint1()->getX2Coordinate();
+      zEnd   = mLine->getPoint2()->getX2Coordinate();
+   }
+   else if(this->isParallelToX3Axis())
+   {
+      xa     = point1.getX1Coordinate();
+      ya     = point1.getX2Coordinate();
+      za     = point1.getX3Coordinate();
+      xb     = point2.getX1Coordinate();
+      yb     = point2.getX2Coordinate();
+      zb     = point2.getX3Coordinate();
+      xm     = mLine->getPoint1()->getX1Coordinate();
+      ym     = mLine->getPoint1()->getX2Coordinate();
+      zStart = mLine->getPoint1()->getX3Coordinate();
+      zEnd   = mLine->getPoint2()->getX3Coordinate();
+   }
+   else throw UbException(UB_EXARGS,"funktioniert derzeit nur mit achsenparallelen Zylindern");
+
+   //Bestimmung des Schnittpunktes mit unendlich ausgedehntem Zylinder
+   double r   = mRad;
+   double r2  = r*r;
+   double xa2 = xa*xa;
+   double xb2 = xb*xb;
+   double ya2 = ya*ya;
+   double yb2 = yb*yb;
+   double xm2 = xm*xm;
+   double ym2 = ym*ym;
+
+   double wurzel  = 2.0*xa*xm*yb2+2.0*ya*ym*xb2-2.0*xa*xb*r2+2.0*xa*xb*ym2-2.0*ya*yb*r2+2.0*xa2*yb*ym
+                   +2.0*xa*xm*ya*ym-2.0*xa*xm*yb*ym-2.0*ya*ym*xb*xm+2.0*xb*xm*yb*ym+2.0*ya*yb*xa*xb
+                   -2.0*ya*yb*xa*xm-2.0*ya*yb*xb*xm-2.0*xa*xb*ya*ym-2.0*xa*xb*yb*ym+2.0*xb*xm*ya2
+                   +2.0*ya*yb*xm2-xa2*yb2-xb2*ya2+xa2*r2-xa2*ym2+xb2*r2-xb2*ym2+ya2*r2-ya2*xm2+yb2*r2-yb2*xm2;
+   double nenner  = -2.0*(ya*yb+xa*xb)+xa2+xb2+ya2+yb2;
+   double zaehler =  2.0*(-xa*xm+xb*xm-ya*ym+yb*ym)+xa2-xb2+ya2-yb2;
+
+   if(UbMath::greaterEqual(wurzel,0.0) && !UbMath::zero(nenner) )//fabs(nenner)>1.E-13)
+   {
+      t1 = (zaehler+2.0*sqrt(wurzel))/nenner;
+      t2 = (zaehler-2.0*sqrt(wurzel))/nenner;
+
+      if(UbMath::inClosedInterval(t1, -1.0, 1.0)) //Schnittpunkt innerhalb der Strecke
+      {
+         double x = xa*(0.5-0.5*t1)+xb*(0.5+0.5*t1);
+         double y = ya*(0.5-0.5*t1)+yb*(0.5+0.5*t1);
+         double z = za*(0.5-0.5*t1)+zb*(0.5+0.5*t1);
+
+         if(UbMath::inClosedInterval(z,zStart,zEnd)) //zWert muss sich innerhal der cylinderlaenge befinden
+         {
+            if     (this->isParallelToX1Axis()) schnittpunkte.push_back(new GbPoint3D(z,x,y));
+            else if(this->isParallelToX2Axis()) schnittpunkte.push_back(new GbPoint3D(x,z,y));
+            else if(this->isParallelToX3Axis()) schnittpunkte.push_back(new GbPoint3D(x,y,z));
+         }
+      }
+      if(fabs(t2-t1)>1.E-13 && UbMath::inClosedInterval(t2, -1.0, 1.0)) //Schnittpunkt innerhalb der Strecke
+      {
+         double x = xa*(0.5-0.5*t2)+xb*(0.5+0.5*t2);
+         double y = ya*(0.5-0.5*t2)+yb*(0.5+0.5*t2);
+         double z = za*(0.5-0.5*t2)+zb*(0.5+0.5*t2);
+
+         if(UbMath::inClosedInterval(z,zStart,zEnd)) //zWert muss sich innerhal der cylinderlaenge befinden
+         {
+            if     (this->isParallelToX1Axis()) schnittpunkte.push_back(new GbPoint3D(z,x,y));
+            else if(this->isParallelToX2Axis()) schnittpunkte.push_back(new GbPoint3D(x,z,y));
+            else if(this->isParallelToX3Axis()) schnittpunkte.push_back(new GbPoint3D(x,y,z));
+         }
+      }
+   }
+   //wenn nenner==0 -> Strecke parallel zu Zylinder! Es muss noch auf Schnittpunkt mit "Deckeln" geprueft werden
+
+   //Schnittpunkt mit Seitenflaechen bestimmen
+   //hierzu wird der schnittpunkt der gegebnen strecke mit den seitenflaechenberechnet
+   //als erstes "schaut man seitlich auf den Zylinder" --> kreisflaechen wird als strecke darsgestellt
+   //mit diesen "strecken" berechnet man Schnittpunkte.
+   //anschliessend wird geprueft, ob der berechnete Schnittpunkt ueberhaupt im kreis liegt
+   //falls ja --> Schnittpunkt vorhanden
+
+   double x1a,y1a,z1a,x1b,y1b,z1b, //uebergebene Strecke
+          x2a,y2a,x2b,y2b,         //erste "Kreisstrecke"
+          x3a,y3a,x3b,y3b,         //zweite "Kreisstrecke"
+          y2m,z2m,y3m,z3m;
+   double nenner1ab;
+
+   if(this->isParallelToX1Axis())
+   {
+      x1a=point1.getX1Coordinate();
+      y1a=point1.getX2Coordinate();
+      z1a=point1.getX3Coordinate();
+      x1b=point2.getX1Coordinate();
+      y1b=point2.getX2Coordinate();
+      z1b=point2.getX3Coordinate();
+
+      x2a=mLine->getPoint1()->getX1Coordinate();
+      y2m=mLine->getPoint1()->getX2Coordinate();
+      z2m=mLine->getPoint1()->getX3Coordinate();
+      y2a=y2m+mRad;
+      x2b=mLine->getPoint1()->getX1Coordinate();
+      y2b=y2m-mRad;
+
+      x3a=mLine->getPoint2()->getX1Coordinate(); //
+      y3m=mLine->getPoint2()->getX2Coordinate();
+      z3m=mLine->getPoint2()->getX3Coordinate();
+      y3a=y3m+mRad;
+      x3b=mLine->getPoint2()->getX1Coordinate();
+      y3b=y3m-mRad;
+   }
+   else if(this->isParallelToX2Axis())
+   {
+      x1a=point1.getX2Coordinate();
+      y1a=point1.getX3Coordinate();
+      z1a=point1.getX1Coordinate();
+      x1b=point2.getX2Coordinate();
+      y1b=point2.getX3Coordinate();
+      z1b=point2.getX1Coordinate();
+
+      x2a=mLine->getPoint1()->getX2Coordinate();
+      y2m=mLine->getPoint1()->getX3Coordinate();
+      z2m=mLine->getPoint1()->getX1Coordinate();
+      y2a=y2m+mRad;
+      x2b=mLine->getPoint1()->getX2Coordinate();
+      y2b=y2m-mRad;
+
+      x3a=mLine->getPoint2()->getX2Coordinate(); //
+      y3m=mLine->getPoint2()->getX3Coordinate();
+      z3m=mLine->getPoint2()->getX1Coordinate();
+      y3a=y3m+mRad;
+      x3b=mLine->getPoint2()->getX2Coordinate();
+      y3b=y3m-mRad;
+   }
+   else if(this->isParallelToX3Axis())
+   {
+      x1a=point1.getX3Coordinate();
+      y1a=point1.getX2Coordinate();
+      z1a=point1.getX1Coordinate();
+      x1b=point2.getX3Coordinate();
+      y1b=point2.getX2Coordinate();
+      z1b=point2.getX1Coordinate();
+
+      x2a=mLine->getPoint1()->getX3Coordinate();
+      y2m=mLine->getPoint1()->getX2Coordinate();
+      z2m=mLine->getPoint1()->getX1Coordinate();
+      y2a=y2m+mRad;
+      x2b=mLine->getPoint1()->getX3Coordinate();
+      y2b=y2m-mRad;
+
+      x3a=mLine->getPoint2()->getX3Coordinate(); //
+      y3m=mLine->getPoint2()->getX2Coordinate();
+      z3m=mLine->getPoint2()->getX1Coordinate();
+      y3a=y3m+mRad;
+      x3b=mLine->getPoint2()->getX3Coordinate();
+      y3b=y3m-mRad;
+   }
+   else throw UbException(UB_EXARGS,"funktioniert derzeit nur mit achsenparallelen Zylindern");
+
+   nenner1ab = -y1a*x2a+y1a*x2b+y1b*x2a-y1b*x2b+x1a*y2a-x1a*y2b-x1b*y2a+x1b*y2b;
+   //double nenner2 = x1a*y2a-x1a*y2b-x1b*y2a+x1b*y2b-y1a*x2a+y1a*x2b+y1b*x2a-y1b*x2b;
+   if(fabs(nenner1ab)>1.E-13) //andernfalls sind die beiden Strecken parallel
+   {
+      //tStrecke ist fuer gegebene Strecke!
+      double t1ab = (-y1a*x2a+y1a*x2b-2.0*y2a*x2b+x1a*y2a-x1a*y2b-x1b*y2b+2.0*y2b*x2a+x1b*y2a-y1b*x2a+y1b*x2b)/nenner1ab;
+      //double tStrecke = -(-x1a*y2a+x1a*y2b+2.0*y2a*x2b+y1a*x2a-2.0*x2a*y2b-y1a*x2b+y1b*x2a-y1b*x2b-x1b*y2a+x1b*y2b)/nenner2;
+      //wenn -1 <= t2 <= +1 -> SP mit strecke
+      if(UbMath::inClosedInterval(t1ab, -1.0, 1.0)) //Schnittpunkt innerhalb der Strecke
+      {
+         double x,y,z,abstand_ist;
+         if     (this->isParallelToX1Axis())
+         {
+            x = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            y = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            z = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-y)*(y3m-y)+(z3m-z)*(z3m-z));
+         }
+         else if(this->isParallelToX2Axis())
+         {
+            y = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            z = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            x = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-z)*(y3m-z)+(z3m-x)*(z3m-x));
+         }
+         else if(this->isParallelToX3Axis())
+         {
+            z = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            y = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            x = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-y)*(y3m-y)+(z3m-x)*(z3m-x));
+         }
+         else throw UbException(UB_EXARGS,"funktioniert derzeit nur mit achsenparallelen Zylindern");
+         
+         //pruefen, ob Punkt Element von Kreisflaeche
+         //double abstand_ist=sqrt((y2m-y)*(y2m-y)+(z2m-z)*(z2m-z));
+         if(UbMath::lessEqual(abstand_ist,mRad))  //Punkt ist Schnittpunkt
+         {
+            bool exists = false;
+            for(int pos=0;pos<(int)schnittpunkte.size();++pos)
+            {
+               if(    fabs(schnittpunkte[pos]->getX1Coordinate()-x)<1.E-13
+                   && fabs(schnittpunkte[pos]->getX2Coordinate()-y)<1.E-13
+                   && fabs(schnittpunkte[pos]->getX3Coordinate()-z)<1.E-13 ) exists=true;
+            }
+
+            if(!exists) schnittpunkte.push_back(new GbPoint3D(x,y,z));
+         }
+      }
+   }
+
+   nenner1ab = -y1a*x3a+y1a*x3b+y1b*x3a-y1b*x3b+x1a*y3a-x1a*y3b-x1b*y3a+x1b*y3b;
+
+   if(fabs(nenner1ab)>1.E-13) //andernfalls sind die beiden Strecken parallel
+   {
+      //tStrecke ist fuer gegebene Strecke!
+      double t1ab = (-y1a*x3a+y1a*x3b-x1b*y3b-2.0*y3a*x3b-x1a*y3b+2.0*y3b*x3a+x1a*y3a+x1b*y3a-y1b*x3a+y1b*x3b)/nenner1ab;
+
+      if(UbMath::inClosedInterval(t1ab, -1.0, 1.0)) //Schnittpunkt innerhalb der Strecke
+      {
+         double x,y,z,abstand_ist;
+         if     (this->isParallelToX1Axis())
+         {
+            x = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            y = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            z = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-y)*(y3m-y)+(z3m-z)*(z3m-z));
+         }
+         else if(this->isParallelToX2Axis())
+         {
+            y = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            z = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            x = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-z)*(y3m-z)+(z3m-x)*(z3m-x));
+         }
+         else if(this->isParallelToX3Axis())
+         {
+            z = x1a*(0.5-0.5*t1ab)+x1b*(0.5+0.5*t1ab);
+            y = y1a*(0.5-0.5*t1ab)+y1b*(0.5+0.5*t1ab);
+            x = z1a*(0.5-0.5*t1ab)+z1b*(0.5+0.5*t1ab);
+            abstand_ist=sqrt((y3m-y)*(y3m-y)+(z3m-x)*(z3m-x));
+         }
+         else throw UbException(UB_EXARGS,"cylinder must be parallel to one axis");
+
+         //pruefen, ob Punkt Element von Kreisflaeche
+         //double abstand_ist=sqrt((y2m-y)*(y2m-y)+(z2m-z)*(z2m-z));
+
+         if(UbMath::lessEqual(abstand_ist,mRad))  //Punkt ist Schnittpunkt
+         {
+            bool exists = false;
+            for(int pos=0;pos<(int)schnittpunkte.size();++pos)
+            {
+               if(   fabs(schnittpunkte[pos]->getX1Coordinate()-x)<1.E-13
+                  && fabs(schnittpunkte[pos]->getX2Coordinate()-y)<1.E-13
+                  && fabs(schnittpunkte[pos]->getX3Coordinate()-z)<1.E-13 ) exists=true;
+            }
+
+            if(!exists) schnittpunkte.push_back(new GbPoint3D(x,y,z));
+         }
+      }
+   }
+
+   int nofSchnittpunkte = (int)schnittpunkte.size();
+   if     (nofSchnittpunkte==0) return NULL;
+   else if(nofSchnittpunkte >2) throw UbException(UB_EXARGS,"more than three intersection points - not possible");
+   else if(nofSchnittpunkte==2) return new GbLine3D(schnittpunkte[0],schnittpunkte[1]);
+   else if(nofSchnittpunkte==1)
+   {
+      if     (this->isPointInGbObject3D(&point1)) return new GbLine3D(schnittpunkte[0],new GbPoint3D(point1));
+      else if(this->isPointInGbObject3D(&point2)) return new GbLine3D(schnittpunkte[0],new GbPoint3D(point2));
+      else  return new GbLine3D(schnittpunkte[0],new GbPoint3D(*(schnittpunkte[0]))); //strecke beruehrt clippedLine reduziert sich auf einen Punkt!!!
+   }
+
+   return NULL;
+}
+/*==========================================================*/
+vector<GbTriangle3D*> GbCylinder3D::getSurfaceTriangleSet()
+{
+   double x1ma,x1mb,x2m,x3m;
+   if( this->isParallelToX1Axis() )
+   {
+      x1ma = this->getX1Minimum();
+      x1mb = this->getX1Maximum();
+      x2m  = this->getX2Centroid();
+      x3m  = this->getX3Centroid();
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      x1ma = this->getX2Minimum();
+      x1mb = this->getX2Maximum();
+      x2m  = this->getX1Centroid();
+      x3m  = this->getX3Centroid();
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      x1ma = this->getX3Minimum();
+      x1mb = this->getX3Maximum();
+      x2m  = this->getX2Centroid();
+      x3m  = this->getX1Centroid();
+   }
+   else throw UbException(UB_EXARGS,"cylinder not axis prallel");
+
+   vector<GbTriangle3D*> triangles;
+
+   int segmentsCircle  = 20;
+   double deltaPhi = UbMath::PI/(double)segmentsCircle;
+
+   double phiX1a,phiX1b;
+   double x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+
+   double dXCylinder =  fabs((x1mb-x1ma))/(double)segmentsCircle;
+   int segmentsCylinder = (int)(fabs(x1mb-x1ma)/dXCylinder);
+   for(int segCyl = 0; segCyl<segmentsCylinder; segCyl++)
+   {
+      x1a = x1d = x1ma+segCyl*dXCylinder;
+      x1b = x1c = x1a+dXCylinder;
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  x2m+mRad*std::sin(phiX1a);
+         x3a =  x3m+mRad*std::cos(phiX1a);
+         x2b =  x2m+mRad*std::sin(phiX1b);
+         x3b =  x3m+mRad*std::cos(phiX1b);
+
+         if( this->isParallelToX1Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1b,x2b,x3b),new GbPoint3D(x1b,x2a,x3a),new GbPoint3D(x1a,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1a,x2a,x3a),new GbPoint3D(x1a,x2b,x3b),new GbPoint3D(x1b,x2b,x3b)));
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2b,x1b,x3b),new GbPoint3D(x2a,x1b,x3a),new GbPoint3D(x2a,x1a,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2a,x1a,x3a),new GbPoint3D(x2b,x1a,x3b),new GbPoint3D(x2b,x1b,x3b)));
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3b,x2b,x1b),new GbPoint3D(x3a,x2a,x1b),new GbPoint3D(x3a,x2a,x1a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3a,x2a,x1a),new GbPoint3D(x3b,x2b,x1a),new GbPoint3D(x3b,x2b,x1b)));
+         }
+
+      }
+   }
+
+   int segmentsSide = (int)(mRad/dXCylinder);
+   double radius0, radius1;
+   for(int segCyl = 0; segCyl<segmentsSide; segCyl++)
+   {
+      radius0 = segCyl*dXCylinder;
+      radius1 = radius0+dXCylinder;
+      if(segCyl==segmentsSide-1) radius1=mRad;
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  x2m+radius0*std::sin(phiX1a);
+         x3a =  x3m+radius0*std::cos(phiX1a);
+         x2b =  x2m+radius0*std::sin(phiX1b);
+         x3b =  x3m+radius0*std::cos(phiX1b);
+         x2c =  x2m+radius1*std::sin(phiX1b);
+         x3c =  x3m+radius1*std::cos(phiX1b);
+         x2d =  x2m+radius1*std::sin(phiX1a);
+         x3d =  x3m+radius1*std::cos(phiX1a);
+
+         if( this->isParallelToX1Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1ma,x2a,x3a),new GbPoint3D(x1ma,x2b,x3b),new GbPoint3D(x1ma,x2c,x3c)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1ma,x2c,x3c),new GbPoint3D(x1ma,x2d,x3d),new GbPoint3D(x1ma,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1mb,x2c,x3c),new GbPoint3D(x1mb,x2b,x3b),new GbPoint3D(x1mb,x2a,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x1mb,x2a,x3a),new GbPoint3D(x1mb,x2d,x3d),new GbPoint3D(x1mb,x2c,x3c)));
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2a,x1ma,x3a),new GbPoint3D(x2b,x1ma,x3b),new GbPoint3D(x2c,x1ma,x3c)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2c,x1ma,x3c),new GbPoint3D(x2d,x1ma,x3d),new GbPoint3D(x2a,x1ma,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2c,x1mb,x3c),new GbPoint3D(x2b,x1mb,x3b),new GbPoint3D(x2a,x1mb,x3a)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x2a,x1mb,x3a),new GbPoint3D(x2d,x1mb,x3d),new GbPoint3D(x2c,x1mb,x3c)));
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3a,x2a,x1ma),new GbPoint3D(x3b,x2b,x1ma),new GbPoint3D(x3c,x2c,x1ma)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3c,x2c,x1ma),new GbPoint3D(x3d,x2d,x1ma),new GbPoint3D(x3a,x2a,x1ma)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3c,x2c,x1mb),new GbPoint3D(x3b,x2b,x1mb),new GbPoint3D(x3a,x2a,x1mb)));
+            triangles.push_back(new GbTriangle3D(new GbPoint3D(x3a,x2a,x1mb),new GbPoint3D(x3d,x2d,x1mb),new GbPoint3D(x3c,x2c,x1mb)));
+         }
+      }
+   }
+
+   return triangles;
+}
+/*==========================================================*/
+void GbCylinder3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+   float x1ma,x1mb,x2m,x3m;
+   if( this->isParallelToX1Axis() )
+   {
+      x1ma = (float)this->getX1Minimum();
+      x1mb = (float)this->getX1Maximum();
+      x2m  = (float)this->getX2Centroid();
+      x3m  = (float)this->getX3Centroid();
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      x1ma = (float)this->getX2Minimum();
+      x1mb = (float)this->getX2Maximum();
+      x2m  = (float)this->getX1Centroid();
+      x3m  = (float)this->getX3Centroid();
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      x1ma = (float)this->getX3Minimum();
+      x1mb = (float)this->getX3Maximum();
+      x2m  = (float)this->getX2Centroid();
+      x3m  = (float)this->getX1Centroid();
+   }
+   else throw UbException(UB_EXARGS,"cylinder not axis prallel");
+
+   int segmentsCircle  = 20;
+   double deltaPhi = UbMath::PI/(double)segmentsCircle;
+
+   double phiX1a,phiX1b;
+   float x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+
+   double dXCylinder =  fabs((x1mb-x1ma))/(double)segmentsCircle;
+   int segmentsCylinder = (int)(fabs(x1mb-x1ma)/dXCylinder);
+   int nodenr = 0;
+   for(int segCyl = 0; segCyl<segmentsCylinder; segCyl++)
+   {
+      x1a = x1d = (float)(x1ma+segCyl*dXCylinder);
+      x1b = x1c = (float)(x1a+dXCylinder);
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  (float)(x2m+mRad*std::sin(phiX1a));
+         x3a =  (float)(x3m+mRad*std::cos(phiX1a));
+         x2b =  (float)(x2m+mRad*std::sin(phiX1b));
+         x3b =  (float)(x3m+mRad*std::cos(phiX1b));
+
+         if( this->isParallelToX1Axis() )
+         {
+            nodes.push_back( makeUbTuple(x1b,x2b,x3b) ); nodes.push_back( makeUbTuple(x1b,x2a,x3a) ); nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1a,x2a,x3a) ); nodes.push_back( makeUbTuple(x1a,x2b,x3b) ); nodes.push_back( makeUbTuple(x1b,x2b,x3b) );
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            nodes.push_back( makeUbTuple(x2b,x1b,x3b) ); nodes.push_back( makeUbTuple(x2a,x1b,x3a) ); nodes.push_back( makeUbTuple(x2a,x1a,x3a) );
+            nodes.push_back( makeUbTuple(x2a,x1a,x3a) ); nodes.push_back( makeUbTuple(x2b,x1a,x3b) ); nodes.push_back( makeUbTuple(x2b,x1b,x3b) );
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            nodes.push_back( makeUbTuple(x3b,x2b,x1b) ); nodes.push_back( makeUbTuple(x3a,x2a,x1b) ); nodes.push_back( makeUbTuple(x3a,x2a,x1a) );
+            nodes.push_back( makeUbTuple(x3a,x2a,x1a) ); nodes.push_back( makeUbTuple(x3b,x2b,x1a) ); nodes.push_back( makeUbTuple(x3b,x2b,x1b) );
+         }
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+      }
+   }
+
+   int segmentsSide = (int)(mRad/dXCylinder);
+   double radius0, radius1;
+   for(int segCyl = 0; segCyl<segmentsSide; segCyl++)
+   {
+      radius0 = segCyl*dXCylinder;
+      radius1 = radius0+dXCylinder;
+      if(segCyl==segmentsSide-1) radius1=mRad;
+
+      for(phiX1a=2.0*UbMath::PI; phiX1a>0; phiX1a-=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a = x2m+(float)(radius0*std::sin(phiX1a));
+         x3a = x3m+(float)(radius0*std::cos(phiX1a));
+         x2b = x2m+(float)(radius0*std::sin(phiX1b));
+         x3b = x3m+(float)(radius0*std::cos(phiX1b));
+         x2c = x2m+(float)(radius1*std::sin(phiX1b));
+         x3c = x3m+(float)(radius1*std::cos(phiX1b));
+         x2d = x2m+(float)(radius1*std::sin(phiX1a));
+         x3d = x3m+(float)(radius1*std::cos(phiX1a));
+
+         if( this->isParallelToX1Axis() )
+         {
+            nodes.push_back( makeUbTuple(x1ma,x2a,x3a) ); nodes.push_back( makeUbTuple(x1ma,x2b,x3b) ); nodes.push_back( makeUbTuple(x1ma,x2c,x3c) );
+            nodes.push_back( makeUbTuple(x1ma,x2c,x3c) ); nodes.push_back( makeUbTuple(x1ma,x2d,x3d) ); nodes.push_back( makeUbTuple(x1ma,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1mb,x2c,x3c) ); nodes.push_back( makeUbTuple(x1mb,x2b,x3b) ); nodes.push_back( makeUbTuple(x1mb,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1mb,x2a,x3a) ); nodes.push_back( makeUbTuple(x1mb,x2d,x3d) ); nodes.push_back( makeUbTuple(x1mb,x2c,x3c) );
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            nodes.push_back( makeUbTuple(x2a,x1ma,x3a) ); nodes.push_back( makeUbTuple(x2b,x1ma,x3b) ); nodes.push_back( makeUbTuple(x2c,x1ma,x3c) );
+            nodes.push_back( makeUbTuple(x2c,x1ma,x3c) ); nodes.push_back( makeUbTuple(x2d,x1ma,x3d) ); nodes.push_back( makeUbTuple(x2a,x1ma,x3a) );
+            nodes.push_back( makeUbTuple(x2c,x1mb,x3c) ); nodes.push_back( makeUbTuple(x2b,x1mb,x3b) ); nodes.push_back( makeUbTuple(x2a,x1mb,x3a) );
+            nodes.push_back( makeUbTuple(x2a,x1mb,x3a) ); nodes.push_back( makeUbTuple(x2d,x1mb,x3d) ); nodes.push_back( makeUbTuple(x2c,x1mb,x3c) );
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            nodes.push_back( makeUbTuple(x3a,x2a,x1ma) ); nodes.push_back( makeUbTuple(x3b,x2b,x1ma) ); nodes.push_back( makeUbTuple(x3c,x2c,x1ma) );
+            nodes.push_back( makeUbTuple(x3c,x2c,x1ma) ); nodes.push_back( makeUbTuple(x3d,x2d,x1ma) ); nodes.push_back( makeUbTuple(x3a,x2a,x1ma) );
+            nodes.push_back( makeUbTuple(x3c,x2c,x1mb) ); nodes.push_back( makeUbTuple(x3b,x2b,x1mb) ); nodes.push_back( makeUbTuple(x3a,x2a,x1mb) );
+            nodes.push_back( makeUbTuple(x3a,x2a,x1mb) ); nodes.push_back( makeUbTuple(x3d,x2d,x1mb) ); nodes.push_back( makeUbTuple(x3c,x2c,x1mb) );
+         }
+
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+      }
+   }
+}
+/*==========================================================*/
+void GbCylinder3D::addSurfaceTriangleSetSegments(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles, int segmentsRound, int segmentsHeight )
+{
+   float x1ma,x1mb,x2m,x3m;
+   if( this->isParallelToX1Axis() )
+   {
+      x1ma = (float)this->getX1Minimum();
+      x1mb = (float)this->getX1Maximum();
+      x2m  = (float)this->getX2Centroid();
+      x3m  = (float)this->getX3Centroid();
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      x1ma = (float)this->getX2Minimum();
+      x1mb = (float)this->getX2Maximum();
+      x2m  = (float)this->getX1Centroid();
+      x3m  = (float)this->getX3Centroid();
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      x1ma = (float)this->getX3Minimum();
+      x1mb = (float)this->getX3Maximum();
+      x2m  = (float)this->getX2Centroid();
+      x3m  = (float)this->getX1Centroid();
+   }
+   else throw UbException(UB_EXARGS,"cylinder not axis prallel");
+
+   int segmentsCircle  = segmentsRound;
+   double deltaPhi = UbMath::PI/(double)segmentsCircle;
+
+   double phiX1a,phiX1b;
+   float x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+
+   double dXCylinder =  fabs((x1mb-x1ma))/(double)segmentsHeight; //hier evtl. segmentsheight
+   int segmentsCylinder = (int)(fabs(x1mb-x1ma)/dXCylinder);
+   int nodenr = 0;
+   for(int segCyl = 0; segCyl<segmentsCylinder; segCyl++)
+   {
+      x1a = x1d = (float)(x1ma+segCyl*dXCylinder);
+      x1b = x1c = (float)(x1a+dXCylinder);
+
+      //for(phiX1a=2.0*UbMath::PI; phiX1a>0.0; phiX1a-=deltaPhi)
+      for(phiX1a=0.0; phiX1a<2.0*UbMath::PI-0.5*deltaPhi; phiX1a+=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a =  (float)(x2m+mRad*std::sin(phiX1a));
+         x3a =  (float)(x3m+mRad*std::cos(phiX1a));
+         x2b =  (float)(x2m+mRad*std::sin(phiX1b));
+         x3b =  (float)(x3m+mRad*std::cos(phiX1b));
+
+         if( this->isParallelToX1Axis() )
+         {
+            nodes.push_back( makeUbTuple(x1b,x2b,x3b) ); nodes.push_back( makeUbTuple(x1b,x2a,x3a) ); nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1a,x2a,x3a) ); nodes.push_back( makeUbTuple(x1a,x2b,x3b) ); nodes.push_back( makeUbTuple(x1b,x2b,x3b) );
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            nodes.push_back( makeUbTuple(x2b,x1b,x3b) ); nodes.push_back( makeUbTuple(x2a,x1b,x3a) ); nodes.push_back( makeUbTuple(x2a,x1a,x3a) );
+            nodes.push_back( makeUbTuple(x2a,x1a,x3a) ); nodes.push_back( makeUbTuple(x2b,x1a,x3b) ); nodes.push_back( makeUbTuple(x2b,x1b,x3b) );
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            nodes.push_back( makeUbTuple(x3b,x2b,x1b) ); nodes.push_back( makeUbTuple(x3a,x2a,x1b) ); nodes.push_back( makeUbTuple(x3a,x2a,x1a) );
+            nodes.push_back( makeUbTuple(x3a,x2a,x1a) ); nodes.push_back( makeUbTuple(x3b,x2b,x1a) ); nodes.push_back( makeUbTuple(x3b,x2b,x1b) );
+         }
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+      }
+   }
+
+   int segmentsSide = (int)(mRad/dXCylinder);
+   double radius0, radius1;
+   for(int segCyl = 0; segCyl<segmentsSide; segCyl++)
+   {
+      radius0 = segCyl*dXCylinder;
+      radius1 = radius0+dXCylinder;
+      if(segCyl==segmentsSide-1) radius1=mRad;
+
+      //for(phiX1a=2.0*UbMath::PI; phiX1a>0.0; phiX1a-=deltaPhi)
+      for(phiX1a=0.0; phiX1a<2.0*UbMath::PI-0.5*deltaPhi; phiX1a+=deltaPhi)
+      {
+         phiX1b = phiX1a+deltaPhi;
+
+         x2a = x2m+(float)(radius0*std::sin(phiX1a));
+         x3a = x3m+(float)(radius0*std::cos(phiX1a));
+         x2b = x2m+(float)(radius0*std::sin(phiX1b));
+         x3b = x3m+(float)(radius0*std::cos(phiX1b));
+         x2c = x2m+(float)(radius1*std::sin(phiX1b));
+         x3c = x3m+(float)(radius1*std::cos(phiX1b));
+         x2d = x2m+(float)(radius1*std::sin(phiX1a));
+         x3d = x3m+(float)(radius1*std::cos(phiX1a));
+
+         if( this->isParallelToX1Axis() )
+         {
+            nodes.push_back( makeUbTuple(x1ma,x2a,x3a) ); nodes.push_back( makeUbTuple(x1ma,x2b,x3b) ); nodes.push_back( makeUbTuple(x1ma,x2c,x3c) );
+            nodes.push_back( makeUbTuple(x1ma,x2c,x3c) ); nodes.push_back( makeUbTuple(x1ma,x2d,x3d) ); nodes.push_back( makeUbTuple(x1ma,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1mb,x2c,x3c) ); nodes.push_back( makeUbTuple(x1mb,x2b,x3b) ); nodes.push_back( makeUbTuple(x1mb,x2a,x3a) );
+            nodes.push_back( makeUbTuple(x1mb,x2a,x3a) ); nodes.push_back( makeUbTuple(x1mb,x2d,x3d) ); nodes.push_back( makeUbTuple(x1mb,x2c,x3c) );
+         }
+         else if( this->isParallelToX2Axis() )
+         {
+            nodes.push_back( makeUbTuple(x2a,x1ma,x3a) ); nodes.push_back( makeUbTuple(x2b,x1ma,x3b) ); nodes.push_back( makeUbTuple(x2c,x1ma,x3c) );
+            nodes.push_back( makeUbTuple(x2c,x1ma,x3c) ); nodes.push_back( makeUbTuple(x2d,x1ma,x3d) ); nodes.push_back( makeUbTuple(x2a,x1ma,x3a) );
+            nodes.push_back( makeUbTuple(x2c,x1mb,x3c) ); nodes.push_back( makeUbTuple(x2b,x1mb,x3b) ); nodes.push_back( makeUbTuple(x2a,x1mb,x3a) );
+            nodes.push_back( makeUbTuple(x2a,x1mb,x3a) ); nodes.push_back( makeUbTuple(x2d,x1mb,x3d) ); nodes.push_back( makeUbTuple(x2c,x1mb,x3c) );
+         }
+         else if( this->isParallelToX3Axis() )
+         {
+            nodes.push_back( makeUbTuple(x3a,x2a,x1ma) ); nodes.push_back( makeUbTuple(x3b,x2b,x1ma) ); nodes.push_back( makeUbTuple(x3c,x2c,x1ma) );
+            nodes.push_back( makeUbTuple(x3c,x2c,x1ma) ); nodes.push_back( makeUbTuple(x3d,x2d,x1ma) ); nodes.push_back( makeUbTuple(x3a,x2a,x1ma) );
+            nodes.push_back( makeUbTuple(x3c,x2c,x1mb) ); nodes.push_back( makeUbTuple(x3b,x2b,x1mb) ); nodes.push_back( makeUbTuple(x3a,x2a,x1mb) );
+            nodes.push_back( makeUbTuple(x3a,x2a,x1mb) ); nodes.push_back( makeUbTuple(x3d,x2d,x1mb) ); nodes.push_back( makeUbTuple(x3c,x2c,x1mb) );
+         }
+
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+         triangles.push_back( makeUbTuple(nodenr  , nodenr+1, nodenr+2) );  nodenr+=3;
+      }
+   }
+}
+
+/*==========================================================*/
+void GbCylinder3D::objectChanged(UbObservable* changedObject)
+{
+   GbLine3D* line = dynamic_cast<GbLine3D*>(changedObject);
+   if(!line || this->mLine!=line) return;
+
+   this->notifyObserversObjectChanged();
+}
+/*==========================================================*/
+void GbCylinder3D::objectWillBeDeleted(UbObservable* objectForDeletion)
+{
+   if(this->mLine)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->mLine);
+      if(objectForDeletion == observedObj) { this->mLine = NULL; }
+   }
+}
+/*=======================================================*/
+void GbCylinder3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{
+   if( this->isParallelToX1Axis() )
+   {
+      if(!UbMath::equal(sx2,sx3)) throw UbException(UB_EXARGS,"|| to x1 -> different scaling sx2 and sx3 not possible");
+      this->mRad*=sx2;
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      if(!UbMath::equal(sx1,sx3)) throw UbException(UB_EXARGS,"|| to x2 -> different scaling sx1 and sx3 not possible");
+      this->mRad*=sx1;
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      if(!UbMath::equal(sx1,sx2)) throw UbException(UB_EXARGS,"|| to x3 -> different scaling sx1 and sx2 not possible");
+      this->mRad*=sx1;
+   }
+   else throw UbException(UB_EXARGS,"unknown direction");
+
+   this->mLine->scale(sx1,sx2,sx3);
+   //notify observer wird automatisch aufgerufen
+}
+/*==========================================================*/
+void GbCylinder3D::write(UbFileOutput* out)
+{
+   out->writeString(this->getCreator()->getTypeID());
+   mLine->write(out);
+   out->writeDouble(mRad);
+   out->writeInteger(cylinderType);
+}
+/*==========================================================*/
+void GbCylinder3D::read(UbFileInput* in)
+{
+   in->readString();
+   mLine = new GbLine3D;
+   mLine->read(in);
+   mRad         = in->readDouble();
+   cylinderType = in->readInteger();
+}
+/*==========================================================*/
+double GbCylinder3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   /*
+   Distance D of the intersection between a Ray((ox1,ox2,ox3),(dx1,dx2,dx3)) and a Plane P: ax+by+cz+d=0
+   dc = a*dx1 + b*dx2 + c*dx3
+   dw = a*ox1 + b*ox2 + c*ox3 + d
+   D =   - dw / dc
+   */
+   double px1, px2, px3;
+   double d = Ub::inf; // Distance to Min or Max Plane of the Zylinder
+                       // final distance should be less that d
+
+   if( this->isParallelToX1Axis() )
+   {
+      if     (UbMath::equal(x1 ,minX1) && UbMath::negative(rx1))    return -1.0;
+      else if(UbMath::equal(x1 ,maxX1) && UbMath::positive(rx1))    return -1.0;
+
+      //falls die Linie nicht parallel zu den Seitenflaechen ist
+      if( x1< minX1  ||  x1 > maxX1 ) //nur fuer punkte links und rechts des cylinders
+      {
+         px1 = (x1 < minX1 ? minX1 : maxX1);
+         //falls die Linie nicht parallel zu den Seitenflaechen ist
+         if( !UbMath::zero(rx1) )
+         {
+            // Plane a= 0, b= 1, c=0 d= -1*px2
+            d   = -1.0*(x1 - px1) / rx1;
+            px2 = x2 + d*rx2;
+            px3 = x3 + d*rx3;
+
+            if(UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad))
+            {
+               if     (x1 < minX1 && rx1>0.0 ) d = Ub::inf;  //punkt liegt "links" vom cylinder und strahl hat evtl weiteren SP auf oberflaeche
+               else if(x1 > maxX1 && rx1<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else
+      {
+         //if     (UbMath::negative(rx1)) d = -1.0 * (x1 - minX1) / rx1;
+         //else if(UbMath::positive(rx1)) d = -1.0 * (x1 - maxX1) / rx1;
+         if     (UbMath::negative(rx1)) d = -1.0 * (x1 - maxX1) / rx1;
+         else if(UbMath::positive(rx1)) d = -1.0 * (x1 - minX1) / rx1;
+      }
+   }
+   else if( this->isParallelToX2Axis() )
+   {
+      if     (UbMath::equal(x2 ,minX2) && UbMath::negative(rx2))    return -1;
+      else if(UbMath::equal(x2 ,maxX2) && UbMath::positive(rx2))    return -1;
+
+      if( minX2 > x2  ||  x2 > maxX2 )
+      {
+         px2 = (x2 < minX2 ? minX2 : maxX2);
+         //falls die Linie nicht parallel zu den Seitenflaechen ist
+         if( !UbMath::zero(rx2) )
+         {
+            // Plane a= 0, b= 1, c=0 d= -1*px2
+            d   = -1*(x2 - px2) / rx2;
+            px1 = x1 + d*rx1;
+            px3 = x3 + d*rx3;
+
+            if (UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad))
+            {
+               if     (x2 < minX2 && rx2>0.0 ) d = Ub::inf;  //punkt liegt "links oberhalb" vom cylinder und strahl mit pos x1 hat evtl weiteren SP auf oberflaeche
+               else if(x2 > maxX2 && rx2<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else
+      {
+         if     (UbMath::negative(rx2)) d = -1.0 * (x2 - minX2) / rx2;
+         else if(UbMath::positive(rx2)) d = -1.0 * (x2 - maxX2) / rx2;
+      }
+   }
+   else if( this->isParallelToX3Axis() )
+   {
+      if     (UbMath::equal(x3, minX3) && UbMath::negative(rx3)) return -1.0;
+      else if(UbMath::equal(x3, maxX3) && UbMath::positive(rx3)) return -1.0;
+
+      if(minX3 > x3  ||  x3 > maxX3 )
+      {
+         px3 = (x3 < minX3 ? minX3 : maxX3);
+         //falls die Linie nicht parallel zu den Seitenflaechen ist
+         if (!UbMath::zero(rx3))
+         {
+            // Plane a= 0, b= 0, c=1 d= -1*px3
+            d   = -1.0*(x3 - px3) / rx3;
+            px2 = x2 + d*rx2;
+            px1 = x1 + d*rx1;
+            if( UbMath::greater(mLine->getDistance(px1,px2,px3) , mRad) )
+            {
+               if     (x3 < minX3 && rx3>0.0 ) d = Ub::inf;
+               else if(x3 > maxX3 && rx3<0.0 ) d = Ub::inf;
+               else return -1.0;
+            }
+            else return d;
+         }
+         else return -1.0;
+      }
+      else
+      {
+         if     (UbMath::negative(rx3)) d = -1.0 * (x3 - minX3) / rx3;
+         else if(UbMath::positive(rx3)) d = -1.0 * (x3 - maxX3) / rx3;
+      }
+   }
+   else throw UbException(UB_EXARGS,"funzt nur bei achsen parallelem cylinder");
+   //////////////////////////////////////////////////////////////////////////
+   //Q berechnen fuer Infinity Zylinder
+   double axisX1 = mLine->getPoint2()->x1 - mLine->getPoint1()->x1;  /* Axis of the cylinder   */
+   double axisX2 = mLine->getPoint2()->x2 - mLine->getPoint1()->x2;  /* mit p1 als base of cylinder */
+   double axisX3 = mLine->getPoint2()->x3 - mLine->getPoint1()->x3;
+
+   //double dirlen = mLine->getLength();
+   //double abs, t, s;
+
+   double RCx1 = x1 - mLine->getPoint1()->x1;
+   double RCx2 = x2 - mLine->getPoint1()->x2;
+   double RCx3 = x3 - mLine->getPoint1()->x3;
+
+   //n = ray x axis
+   double nx1 = rx2*axisX3 - rx3*axisX2;
+   double nx2 = rx3*axisX1 - rx1*axisX3;
+   double nx3 = rx1*axisX2 - rx2*axisX1;
+   double nLength = nx1*nx1 + nx2*nx2 + nx3*nx3;
+
+   double abs;
+   if( UbMath::zero( nLength ) )
+   {  /* ray parallel to cyl  */
+      //abs = RC dot axis
+      double tmpabs = RCx1*axisX1 + RCx2*axisX2 + RCx3*axisX3;
+      double dx1 = RCx1 - tmpabs*axisX1;
+      double dx2 = RCx2 - tmpabs*axisX2;
+      double dx3 = RCx3 - tmpabs*axisX3;
+      if( UbMath::greater( dx1*dx1 + dx2*dx2 + dx3*dx3 , mRad*mRad) )
+         return -1.0;
+   }
+
+   //normalize "n"
+   nLength = std::sqrt(nLength);
+   double invnLength = 1.0/nLength;
+   nx1*=invnLength;
+   nx2*=invnLength;
+   nx3*=invnLength;
+
+   //shortest distance  = fabs( RC dot n )
+   abs = std::fabs( RCx1*nx1 + RCx2*nx2 + RCx3*nx3 );
+
+   if( UbMath::lessEqual(abs, mRad) )
+   {                    /* if ray hits cylinder */
+      //Ox1 = RC x axis
+      double Ox1 = RCx2*axisX3 - RCx3*axisX2;
+      double Ox2 = RCx3*axisX1 - RCx1*axisX3;
+      double Ox3 = RCx1*axisX2 - RCx2*axisX1;
+      //t = - O dot n / nLength;
+      double t = - (Ox1*nx1 + Ox2*nx2 + Ox3*nx3) / nLength;
+
+      //O = n x axis;
+      Ox1 = nx2*axisX3 - nx3*axisX2;
+      Ox2 = nx3*axisX1 - nx1*axisX3;
+      Ox3 = nx1*axisX2 - nx2*axisX1;
+
+      //normalize O
+      invnLength = 1.0/std::sqrt(Ox1*Ox1 + Ox2*Ox2 + Ox3*Ox3);
+      Ox1*=invnLength;
+      Ox2*=invnLength;
+      Ox3*=invnLength;
+
+      double s = std::fabs( sqrt(mRad*mRad - abs*abs) / (rx1*Ox1 + rx2*Ox2 + rx3*Ox3) );
+
+      //Wert a) t-s: entering distance
+      //     b) t+s: exiting  distance
+      //
+      // -> we only consider factors in ray-dir -> means positive values!
+      //    (s is always positive)
+
+      if(t>s)
+      {
+         return UbMath::min( t-s, d );
+      }
+      else if( (t+s) > 0 )
+      {
+         return UbMath::min( t+s, d );
+      }
+   }
+
+   return -1.0;
+}
+/*==========================================================*/
diff --git a/source/VirtualFluidsCore/Geometry/GbCylinder3D.h b/source/VirtualFluidsCore/Geometry/GbCylinder3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0e5425c9c77a6681f7b1321afa80299e0b9b931
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbCylinder3D.h
@@ -0,0 +1,153 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBCYLINDER3D_H
+#define GBCYLINDER3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <basics/utilities/UbObserver.h>
+
+class GbPoint3D;
+class GbLine3D;
+class GbTriangle3D;
+
+class GbObject3DCreator;
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbCylinder3D;
+typedef VFSharedPtr<GbCylinder3D> GbCylinder3DPtr;
+
+
+class GbCylinder3D : public GbObject3D , public UbObserver 
+{
+public:
+   GbCylinder3D();
+	GbCylinder3D(const double& x1a,const double& x2a, const double& x3a, const double& x1b,const double& x2b, const double& x3b, const double& radius);
+	GbCylinder3D(GbPoint3D* p1, GbPoint3D* p2, const double& radius);
+	GbCylinder3D(GbLine3D* line, const double& rad);
+	GbCylinder3D(GbCylinder3D* cylinder);
+	~GbCylinder3D();    
+
+	GbCylinder3D* clone() { return new GbCylinder3D(this); }
+	void finalize();
+
+	double     getRadius() { return this->mRad; };
+	GbLine3D*  getLine() {return mLine;}
+	GbPoint3D* getPoint1();
+	GbPoint3D* getPoint2();
+
+	void setRadius(const double& radius);
+	void setLine(GbLine3D* line);
+	void setPoint1(const double& x1, const double& x2, const double& x3);
+	void setPoint2(const double& x1, const double& x2, const double& x3);
+
+	bool isParallelToX1Axis() { return((this->cylinderType & X1PARALLEL        )    ==  X1PARALLEL        );}
+	bool isParallelToX2Axis() { return((this->cylinderType & X2PARALLEL        )    ==  X2PARALLEL        );}
+	bool isParallelToX3Axis() { return((this->cylinderType & X3PARALLEL        )    ==  X3PARALLEL        );}
+	bool isNotParallelToAxis(){ return((this->cylinderType & NOTPARALLELTOAXIS )    ==  NOTPARALLELTOAXIS );}
+
+	double getHeight(); 
+
+	void scale(const double& sx1, const double& sx2, const double& sx3);
+
+   void translate(const double& x1, const double& x2, const double& x3) 
+   {
+      this->mLine->translate( x1, x2, x3 );
+      this->calculateValues();
+      //this->notifyObserversObjectChanged();
+   }
+
+   double getX1Centroid() { return centerX1; }
+   double getX1Minimum()  { return minX1;    }
+	double getX1Maximum()  { return maxX1;    }
+	double getX2Centroid() { return centerX2; }
+	double getX2Minimum()  { return minX2;    }
+	double getX2Maximum()  { return maxX2;    }
+	double getX3Centroid() { return centerX3; }
+	double getX3Minimum()  { return minX3;    }
+	double getX3Maximum()  { return maxX3;    }
+
+	bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); 
+	bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary); 
+   bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+	GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+   
+   //SG ausdokumentieren, da der nur unendlcihe Zylinder macht ...
+   //bool hasRaytracing() { return true; }
+   bool hasRaytracing() { return false; }
+   bool raytracingSupportsPointsInside() { return true; }
+   
+   
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+	std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+   void addSurfaceTriangleSetSegments(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles, int segmentsRound, int segmentsHeight );
+
+	std::string toString();
+	ObObjectCreator* getCreator();
+	void write(UbFileOutput* out);
+	void read(UbFileInput* in);
+
+	//virtuelle Methoden von UbObserver
+	void objectChanged(UbObservable* changedObject);
+	void objectWillBeDeleted(UbObservable* objectForDeletion);
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & mLine;
+      ar & mRad;
+      ar & cylinderType;
+      
+      if( ArchiveTools::isReading(ar) )
+         this->calculateValues();
+   }
+#endif //CAB_RCF
+   
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+
+protected:
+   void calculateValues();
+
+   GbLine3D* mLine;
+	double    mRad;
+
+   double minX1, minX2, minX3;
+   double maxX1, maxX2, maxX3;
+   double centerX1, centerX2, centerX3;
+
+	int cylinderType;
+
+	//void berechneQuerschnittsWerte();
+   static const int NOTPARALLELTOAXIS  = (1<<0); //1
+   static const int X1PARALLEL         = (1<<1); //2
+   static const int X2PARALLEL         = (1<<2); //4
+   static const int X3PARALLEL         = (1<<3); //8
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbCylinder3D >("GbCylinder3D")           , SF_GbCylinder3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbCylinder3D >() ), SF_GbCylinder3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbCylinder3D>()  ), SF_GbCylinder3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif   
diff --git a/source/VirtualFluidsCore/Geometry/GbLine3D.cpp b/source/VirtualFluidsCore/Geometry/GbLine3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7cd729d8aca94749f3c92c49c5aec9a8e806f858
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbLine3D.cpp
@@ -0,0 +1,240 @@
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/creator/GbLine3DCreator.h>
+
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+using namespace std;
+
+ObObjectCreator* GbLine3D::getCreator()
+{
+   return GbLine3DCreator::getInstance();
+}
+/*=======================================================*/
+GbLine3D::GbLine3D()
+{
+   p1     = NULL;
+   p2     = NULL;                       
+   length = 0.0;
+}
+/*=======================================================*/
+GbLine3D::GbLine3D(GbPoint3D* point1, GbPoint3D* point2)
+{
+   this->p1 = point1;
+   this->p2 = point2;
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+   this->calculateValues();
+}
+/*=======================================================*/
+GbLine3D::GbLine3D(GbLine3D* line)
+{
+   this->p1 = line->p1->clone();            
+   this->p2 = line->p2->clone();
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+   this->calculateValues();
+}
+/*=======================================================*/
+GbLine3D::~GbLine3D() 
+{
+   if(this->p1) this->p1->removeObserver(this);
+   if(this->p2) this->p2->removeObserver(this);
+}
+/*=======================================================*/
+void GbLine3D::finalize() 
+{
+   if(this->p1) 
+   {
+      this->p1->removeObserver(this);
+      this->p1->finalize();
+      delete this->p1;
+      this->p1 = NULL;
+   }
+   if(this->p2)
+   {
+      this->p2->removeObserver(this);
+      this->p2->finalize();
+      delete this->p2;
+      this->p2 = NULL;
+   }
+}
+/*=======================================================*/
+vector<GbTriangle3D*> GbLine3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles;
+   GbPoint3D p1(getX1Minimum(),getX2Minimum(),getX3Minimum());
+   GbPoint3D p2(getX1Centroid(),getX2Centroid(),getX3Centroid());
+   GbPoint3D p3(getX1Maximum(),getX2Maximum(),getX3Maximum());
+ 
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p2),new GbPoint3D(p3)));
+   
+   return triangles;
+}
+/*=======================================================*/
+void GbLine3D::setPoint1(GbPoint3D* point1)
+{ 
+   if(this->p1) this->p1->removeObserver(this);
+   this->p1 = point1;  
+   this->p1->addObserver(this);
+
+   if(this->p1 && this->p2) this->calculateValues(); 
+}
+/*=======================================================*/
+void GbLine3D::setPoint2(GbPoint3D* point2)
+{ 
+   if(this->p2) this->p2->removeObserver(this);
+   this->p2 = point2;  
+   this->p2->addObserver(this);
+
+   if(this->p1 && this->p2) this->calculateValues(); 
+}
+/*=======================================================*/
+void GbLine3D::setPoints(GbPoint3D* point1, GbPoint3D* point2)
+{ 
+   if(this->p1) this->p1->removeObserver(this);
+   if(this->p2) this->p2->removeObserver(this);
+
+   this->p1 = point1; 
+   this->p2 = point2;
+
+   this->p1->addObserver(this);
+   this->p2->addObserver(this);
+
+   this->calculateValues(); 
+}
+/*=======================================================*/
+string GbLine3D::toString()
+{
+   stringstream ss;
+   ss<<"GbLine3D[p1=";
+   ss<<this->p1->toString()<<",p2="<<this->p2->toString()<<",l="<<this->getLength()<<"]";
+   return(ss.str());
+}
+/*=======================================================*/
+GbPoint3D* GbLine3D::calculateIntersectionPoint3D(GbLine3D* line)
+{
+   throw UbException(UB_EXARGS," not implemented");
+   //return(GbSystem::calculateIntersectionPoint3D(*this->p1, *this->p2, *line->p1, *line->p2));
+}
+/*======================================================================*/
+GbLine3D* GbLine3D::createClippedLine3D(GbCuboid3D* cuboid)
+{
+   return GbSystem3D::createClipLine3D(*this->p1, *this->p2, cuboid->getPoint1()->x1, cuboid->getPoint1()->x2, cuboid->getPoint1()->x3, cuboid->getPoint2()->x1, cuboid->getPoint2()->x2, cuboid->getPoint2()->x3);
+}                           
+/*======================================================================*/
+GbLine3D* GbLine3D::createClippedLine3D(GbPoint3D* pA, GbPoint3D* pE)
+{
+   return GbSystem3D::createClipLine3D(*this->p1, *this->p2, pA->x1, pA->x2, pA->x3, pE->x1, pE->x2, pE->x3);
+}
+/*======================================================================*/
+double GbLine3D::getDistance(const GbPoint3D& point)
+{
+   return this->getDistance(point.x1,point.x2,point.x3);
+}
+/*======================================================================*/
+double GbLine3D::getDistance(const double& x1,const double& x2,const double& x3)
+{
+   double dx1 = this->p2->x1 - this->p1->x1;
+   double dx2 = this->p2->x2 - this->p1->x2;
+   double dx3 = this->p2->x3 - this->p1->x3;
+
+   //double vec[3];
+   double a0 = x1 - p1->x1;
+   double a1 = x2 - p1->x2;
+   double a2 = x3 - p1->x3;
+
+   double kreuzProd0 = a1 * dx3 - a2 * dx2;
+   double kreuzProd1 = a2 * dx1 - a0 * dx3;
+   double kreuzProd2 = a0 * dx2 - a1 * dx1;
+
+   return (std::sqrt(kreuzProd0*kreuzProd0+kreuzProd1*kreuzProd1+kreuzProd2*kreuzProd2))/length;
+}
+/*=======================================================*/
+void GbLine3D::calculateValues()
+{
+   double dx1 = this->p2->x1 - this->p1->x1;
+   double dx2 = this->p2->x2 - this->p1->x2;
+   double dx3 = this->p2->x3 - this->p1->x3;
+   this->length = std::sqrt(dx1*dx1+dx2*dx2+dx3*dx3);
+}
+/*==========================================================*/
+void GbLine3D::objectChanged(UbObservable* changedObject)
+{
+   GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject);
+   if(!point || (this->p1!=point && this->p2!=point)) return;
+
+   this->calculateValues();
+}
+/*==========================================================*/
+void GbLine3D::objectWillBeDeleted(UbObservable* objectForDeletion)
+{
+   if(this->p1)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p1);
+      if(objectForDeletion == observedObj) { this->p1 = NULL; length = 0.0; }
+   }
+   if(this->p2)
+   {
+      UbObservable* observedObj = dynamic_cast<UbObservable*>(this->p2);
+      if(objectForDeletion == observedObj) { this->p2 = NULL; length = 0.0; }
+   }
+   //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo
+}
+/*==========================================================*/
+void GbLine3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   p1->write(out);
+   p2->write(out);
+}
+/*==========================================================*/
+void GbLine3D::read(UbFileInput* in) 
+{  
+   p1 = new GbPoint3D;
+   p2 = new GbPoint3D;
+   in->readString();                                    
+   p1->read(in);
+   p1->addObserver(this);
+   in->readString();                                    
+   p2->read(in);
+   p2->addObserver(this);
+   this->calculateValues();
+}
+/*==========================================================*/
+void GbLine3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{  
+   double p1X1 = this->p1->getX1Coordinate();
+   double p1X2 = this->p1->getX2Coordinate();
+   double p1X3 = this->p1->getX3Coordinate();
+
+   double p2X1 = this->p2->getX1Coordinate();
+   double p2X2 = this->p2->getX2Coordinate();
+   double p2X3 = this->p2->getX3Coordinate();
+
+   double lenX1 = fabs( p1X1 - p2X1 );
+   double lenX2 = fabs( p1X2 - p2X2 );
+   double lenX3 = fabs( p1X3 - p2X3 );
+
+   double deltaX1 = lenX1*sx1 - lenX1;
+   double deltaX2 = lenX2*sx2 - lenX2;
+   double deltaX3 = lenX3*sx3 - lenX3;
+
+   if(p1X1<p2X1) { p1X1 -=  0.5*deltaX1;   p2X1 +=  0.5*deltaX1; }
+   else          { p1X1 +=  0.5*deltaX1;   p2X1 -=  0.5*deltaX1; }
+   if(p1X2<p2X2) { p1X2 -=  0.5*deltaX2;   p2X2 +=  0.5*deltaX2; }
+   else          { p1X2 +=  0.5*deltaX2;   p2X2 -=  0.5*deltaX2; }
+   if(p1X3<p2X3) { p1X3 -=  0.5*deltaX3;   p2X3 +=  0.5*deltaX3; }
+   else          { p1X3 +=  0.5*deltaX3;   p2X3 -=  0.5*deltaX3; }
+
+   this->p1->setCoordinates(p1X1,p1X2,p1X3);
+   this->p2->setCoordinates(p2X1,p2X2,p2X3);
+}
+/*=======================================================*/
+void GbLine3D::translate(const double& tx1, const double& tx2, const double& tx3)
+{  
+   this->p1->translate(tx1, tx2, tx3);
+   this->p2->translate(tx1, tx2, tx3);
+   //this->notifyObserversObjectChanged();
+}
diff --git a/source/VirtualFluidsCore/Geometry/GbLine3D.h b/source/VirtualFluidsCore/Geometry/GbLine3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..9267666ce804cc800c92f0c08ec56b11e75f2bb8
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbLine3D.h
@@ -0,0 +1,138 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBLINE3D_H
+#define GBLINE3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <sstream>
+#include <cmath>
+          
+#include <basics/utilities/UbObserver.h>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+class GbCuboid3D;
+class GbObject3DCreator;
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbLine3D;
+typedef VFSharedPtr<GbLine3D> GbLine3DPtr;
+
+
+/*=========================================================================*/
+/* GbLine3D                                                                */
+/*                                                                         */
+/**
+ * This Class provides basic 3D line objects.
+ * The describing points are observed by 3D line objects.
+ * <BR><BR><HR>
+*/
+
+class GbLine3D	: public GbObject3D , public UbObserver
+{
+public:
+   GbLine3D();
+	GbLine3D(GbPoint3D* point1, GbPoint3D* point2);
+	GbLine3D(GbLine3D* line);
+   ~GbLine3D(); 
+
+   GbLine3D* clone() { return new GbLine3D(this); }
+   void finalize();
+
+   void setPoint1(GbPoint3D* point1);
+   void setPoint2(GbPoint3D* point2);
+   void setPoints(GbPoint3D* point1, GbPoint3D* point2);
+
+   void deletePoint1() { if(this->p1) {this->p1->removeObserver(this); delete this->p1; this->p1=NULL;} }
+   void deletePoint2() { if(this->p2) {this->p2->removeObserver(this); delete this->p2; this->p2=NULL;} }
+   void deletePoints() { this->deletePoint1(); this->deletePoint2(); }
+
+   GbPoint3D* getPoint1() { return this->p1; }
+   GbPoint3D* getPoint2() { return this->p2; }    
+   
+   double getLength()     { return(this->length); }
+	
+   double getX1Centroid() { return((this->p1->x1+this->p2->x1)*0.5);}
+   double getX2Centroid() { return((this->p1->x2+this->p2->x2)*0.5); };
+   double getX3Centroid() { return((this->p1->x3+this->p2->x3)*0.5); }
+   
+   double getX1Minimum()  { return(this->p1->x1 < this->p2->x1 ? this->p1->x1 : this->p2->x1); }
+   double getX2Minimum()  { return(this->p1->x2 < this->p2->x2 ? this->p1->x2 : this->p2->x2); }
+   double getX3Minimum()  { return(this->p1->x3 < this->p2->x3 ? this->p1->x3 : this->p2->x3); }
+   
+   double getX1Maximum()  { return(this->p1->x1 > this->p2->x1 ? this->p1->x1 : this->p2->x1); }
+   double getX2Maximum()  { return(this->p1->x2 > this->p2->x2 ? this->p1->x2 : this->p2->x2); }
+   double getX3Maximum()  { return(this->p1->x3 > this->p2->x3 ? this->p1->x3 : this->p2->x3); }
+	                                               
+   void scale(const double& sx1, const double& sx2, const double& sx3);
+   void translate(const double& tx1, const double& tx2, const double& tx3);
+
+   GbPoint3D* calculateIntersectionPoint3D(GbLine3D* line);
+   GbLine3D*  createClippedLine3D(GbCuboid3D* cuboid);
+   GbLine3D*  createClippedLine3D(GbPoint3D* pA, GbPoint3D* pE);
+   
+   double     getDistance(const GbPoint3D& point);
+   double     getDistance(const double& x1,const double& x2,const double& x3);
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+   {
+      throw UbException(UB_EXARGS,"not implemented");
+   }
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+   {
+      throw UbException(UB_EXARGS,"not implemented");
+   }
+   bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x32) { return false; }
+
+   GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2)
+   {
+      throw UbException(UB_EXARGS,"not implemented");
+   }
+
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject);
+   void objectWillBeDeleted(UbObservable* objectForDeletion);
+
+   std::string toString();
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & p1;
+      ar & p2;
+      ar & length;
+      if( ArchiveTools::isReading(ar) ) this->calculateValues();
+   }
+#endif //CAB_RCF
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+protected:
+   GbPoint3D* p1;
+	GbPoint3D* p2;
+	double     length;
+
+private:
+   void calculateValues();
+};
+
+#ifdef RCF_USE_SF_SERIALIZATION
+    UB_AUTO_RUN_NAMED(   SF::registerType<GbLine3D>("GbLine3D"), SF_GbLine3D  );
+    UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbLine3D >()), SF_GbLine3D_BD1 );
+    UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbLine3D>() ), SF_GbLine3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/GbObject3D.cpp b/source/VirtualFluidsCore/Geometry/GbObject3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..85f0332e1443d9c8cc593f78c9bf494f8b807af2
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbObject3D.cpp
@@ -0,0 +1,88 @@
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/creator/GbObject3DCreator.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <basics/utilities/UbMath.h>                 
+
+using namespace std;
+
+string GbObject3D::getTypeID()
+{
+      return this->getCreator()->getTypeID();
+}
+/*======================================================================*/
+bool GbObject3D::isPointInGbObject3D(GbPoint3D* p)
+{
+   return this->isPointInGbObject3D(p->getX1Centroid(),p->getX2Coordinate(),p->getX3Coordinate());
+} 
+/*======================================================================*/
+bool GbObject3D::isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) 
+{
+
+   if(   this->isPointInGbObject3D(x1a, x2a, x3a) 
+      && this->isPointInGbObject3D(x1b, x2a, x3a) 
+      && this->isPointInGbObject3D(x1b, x2b, x3a)
+      && this->isPointInGbObject3D(x1a, x2b, x3a) 
+      && this->isPointInGbObject3D(x1a, x2a, x3b)
+      && this->isPointInGbObject3D(x1b, x2a, x3b)
+      && this->isPointInGbObject3D(x1b, x2b, x3b)
+      && this->isPointInGbObject3D(x1a, x2b, x3b))
+   {
+      return true;
+   }
+
+   return false;
+}
+/*======================================================================*/
+bool GbObject3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b) 
+{
+   if(   this->isPointInGbObject3D(x1a, x2a, x3a)      
+      || this->isPointInGbObject3D(x1b, x2a, x3a)      
+      || this->isPointInGbObject3D(x1b, x2b, x3a)      
+      || this->isPointInGbObject3D(x1a, x2b, x3a)      
+      || this->isPointInGbObject3D(x1a, x2a, x3b)      
+      || this->isPointInGbObject3D(x1b, x2a, x3b)      
+      || this->isPointInGbObject3D(x1b, x2b, x3b)      
+      || this->isPointInGbObject3D(x1a, x2b, x3b) )    
+   {
+      if(   !this->isPointInGbObject3D(x1a, x2a, x3a) 
+         || !this->isPointInGbObject3D(x1b, x2a, x3a) 
+         || !this->isPointInGbObject3D(x1b, x2b, x3a) 
+         || !this->isPointInGbObject3D(x1a, x2b, x3a)
+         || !this->isPointInGbObject3D(x1a, x2a, x3b)
+         || !this->isPointInGbObject3D(x1b, x2a, x3b)
+         || !this->isPointInGbObject3D(x1b, x2b, x3b)
+         || !this->isPointInGbObject3D(x1a, x2b, x3b)) return true;
+   }
+   return false;
+}
+/*======================================================================*/
+bool GbObject3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   if(   this->isPointInGbObject3D(x1a, x2a, x3a)   
+      || this->isPointInGbObject3D(x1b, x2a, x3a)   
+      || this->isPointInGbObject3D(x1b, x2b, x3a)   
+      || this->isPointInGbObject3D(x1a, x2b, x3a)   
+      || this->isPointInGbObject3D(x1a, x2a, x3b)   
+      || this->isPointInGbObject3D(x1b, x2a, x3b)   
+      || this->isPointInGbObject3D(x1b, x2b, x3b)   
+      || this->isPointInGbObject3D(x1a, x2b, x3b))  
+   {
+      return true;
+   }
+
+   return false;
+}
+/*=======================================================*/
+bool GbObject3D::isInsideCell(const double& minX1,const double& minX2,const double& minX3,const double& maxX1,const double& maxX2,const double& maxX3)
+{
+   if(   UbMath::greaterEqual(this->getX1Minimum(),minX1)
+      && UbMath::greaterEqual(this->getX2Minimum(),minX2)
+      && UbMath::greaterEqual(this->getX3Minimum(),minX3)
+      && UbMath::lessEqual(this->getX1Maximum(),maxX1) 
+      && UbMath::lessEqual(this->getX2Maximum(),maxX2)   
+      && UbMath::lessEqual(this->getX2Maximum(),maxX3)     ) return true;
+
+   return false;
+}
+
+
diff --git a/source/VirtualFluidsCore/Geometry/GbObject3D.h b/source/VirtualFluidsCore/Geometry/GbObject3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..48cb40af7f284f988f991d7a87ad2dc6802ac8b0
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbObject3D.h
@@ -0,0 +1,173 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBOBJECT3D_H
+#define GBOBJECT3D_H
+
+#include <string>
+#include <vector>
+
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <basics/utilities/UbSystem.h>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+#include <basics/utilities/UbFileOutput.h>
+#include <basics/utilities/UbObservable.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/objects/ObObject.h>
+
+class GbPoint3D;
+class GbLine3D;
+class GbTriangle3D;
+class GbObject3DCreator;
+
+#ifdef CAB_CTL
+#include <ctl.h>
+#endif
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbObject3D;
+typedef VFSharedPtr<GbObject3D> GbObject3DPtr;
+
+
+/*=========================================================================*/
+/* GbObject3D                                                              */
+/*                                                                         */
+/**
+ * This Interface provides basic 3D geometry objects methods.
+ * <BR><BR><HR>
+ * @author <A HREF="mailto:geller@cab.bau.tu-bs.de">S. Geller</A>
+ * @author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+ * @version 1.0 - 02.02.05
+*/
+class GbObject3D : public ObObject
+{
+public:
+#ifdef CAB_CTL
+   virtual ctl::oStream &write(ctl::oStream &os) const
+   {
+      return os;
+   }
+   virtual ctl::iStream &read(ctl::iStream &is)
+   {
+      return is;
+   }
+#endif
+
+   virtual ~GbObject3D(){}
+
+   //ueberschriebene methode von ObObject
+   virtual std::string getTypeID();
+
+   //abstract Methods
+   virtual void finalize() =0 ; //detroys also all dynamic objects (e.g. GbPoints in GbLine)
+   virtual ObObjectCreator* getCreator()=0;
+
+   /**
+    * Returns the centroid x1 coordinate of this 3D object.
+    * @return the centroid x1 coordinate of this 3D object
+    */
+   virtual double getX1Centroid()=0;
+   /**
+    * Returns the minimum x1 coordinate of this 3D object.
+    * @return the minimum x1 coordinate of this 3D object
+    */
+   virtual double getX1Minimum()=0;
+   /**
+    * Returns the maximum x1 coordinate of this 3D object.
+    * @return the maximum x1 coordinate of this 3D object
+    */
+   virtual double getX1Maximum()=0;
+   /**
+    * Returns the centroid x2 coordinate of this 3D object.
+    * @return the centroid x2 coordinate of this 3D object
+    */
+   virtual double getX2Centroid()=0;
+   /**
+    * Returns the minimum x2 coordinate of this 3D object.
+    * @return the minimum x2 coordinate of this 3D object
+    */
+   virtual double getX2Minimum()=0;
+   /**
+    * Returns the maximum x2 coordinate of this 3D object.
+    * @return the maximum x2 coordinate of this 3D object
+    */
+   virtual double getX2Maximum()=0;
+
+	virtual double getX3Centroid()=0;
+   /**
+    * Returns the minimum x2 coordinate of this 3D object.
+    * @return the minimum x2 coordinate of this 3D object
+    */
+   virtual double getX3Minimum()=0;
+   /**
+    * Returns the maximum x2 coordinate of this 3D object.
+    * @return the maximum x2 coordinate of this 3D object
+    */
+   virtual double getX3Maximum()=0;
+
+   /*=======================================================*/
+   double getLengthX1() { return (getX1Maximum()-getX1Minimum()); }
+   double getLengthX2() { return (getX2Maximum()-getX2Minimum()); }
+   double getLengthX3() { return (getX3Maximum()-getX3Minimum()); }
+
+   virtual void setCenterX1Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void setCenterX2Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void setCenterX3Coordinate(const double& value) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void setCenterCoordinates(const double& x1, const double& x2, const double& x3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+
+   //Rotates the Point in relation to the origen.
+   //Parameters must be radian measure.
+   virtual void rotate(const double& rx1, const double& rx2, const double& rx3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void translate(const double& x1, const double& x2, const double& x3) { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+   virtual void scale(const double& sx1, const double& sx2, const double& sx3)  { throw UbException(UB_EXARGS,"not implemented for "+(std::string)typeid(*this).name() ); }
+
+   virtual void write(UbFileOutput* out)=0;
+   virtual void read(UbFileInput* in)=0;
+
+   virtual bool isPointInGbObject3D(GbPoint3D* p);
+   virtual bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)=0;
+   virtual bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)=0;
+
+   virtual bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   virtual bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   virtual bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   virtual double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b){ return -1.0;};
+
+   virtual bool isInsideCell(const double& minX1,const double& minX2,const double& minX3,const double& maxX1,const double& maxX2,const double& maxX3);
+
+   virtual GbLine3D* createClippedLine3D (GbPoint3D &point1, GbPoint3D &point2)=0;
+   virtual std::vector<GbTriangle3D*> getSurfaceTriangleSet()=0;
+
+   virtual void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles) { throw UbException("GbObject3D::addSurfaceTriangleSet - not implemented for "+(std::string)typeid(*this).name()); }
+
+   virtual bool hasRaytracing() { return false; }
+   virtual bool raytracingSupportsPointsInside() { return false; }
+   //|r| must be 1! einheitsvector!!
+   //return negativ value oder zero if no intersection
+   virtual double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3) { throw UbException("GbObject3D::getIntersectionRaytraceFactor - not implemented"); }
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<ObObject>(ar, *this);
+   }
+#endif //CAB_RCF
+};
+/*=========================================================================*/
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   SF_NO_CTOR(GbObject3D);
+   UB_AUTO_RUN_NAMED(SF::registerType<GbObject3D>("GbObject3D") , SF_GbObject3D);
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived<ObObject, GbObject3D >() ), SF_GbObject3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/GbObject3DManager.cpp b/source/VirtualFluidsCore/Geometry/GbObject3DManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..38fc910e8b5223295677abaf1e87c217f411da3d
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbObject3DManager.cpp
@@ -0,0 +1,285 @@
+#include <numerics/geometry3d/GbObject3DManager.h>      
+#include <numerics/geometry3d/GbObject3D.h>       
+#include <numerics/geometry3d/creator/GbObject3DFactory.h>
+
+using namespace std;
+
+GbObject3DEntry::GbObject3DEntry(GbObject3DManager *parent, GbObject3D *geoObject, bool active, string name):ObObjectEntry(parent, geoObject)
+{
+   //this->parent = parent;
+   //this->geoObject = geoObject;
+   this->active = active;
+   this->name = name;
+}
+
+/*======================================================*/
+/*==     nun halt der Manager                       ====*/
+/*======================================================*/
+
+GbObject3DManager::GbObject3DManager(): ObObjectManager()
+{
+   this->tableModel = new GbObject3DTableModel(this);
+}
+/*======================================================*/
+GbObject3DManager::~GbObject3DManager()
+{
+//   this->gbObject3DList.clear();
+}
+/*======================================================*/
+ObObjectFactory* GbObject3DManager::getObObjectFactory()
+{
+   return GbObject3DFactory::getInstance();
+}
+
+/*======================================================*/
+ObObjectEntry* GbObject3DManager::createNewObObjectEntry(ObObject *obj)
+{ 
+   GbObject3D *geoobject = dynamic_cast<GbObject3D*>(obj);
+   return new GbObject3DEntry(this, geoobject, true, geoobject->getTypeID()); 
+}
+
+/*======================================================*/
+//UbTableModel* GbObject3DManager::getTableModel()
+//{
+//   return this->tablemodel;
+//}
+
+/*======================================================*/
+//bool GbObject3DManager::addGbObject3D(GbObject3D *geoObject)
+//{
+//   return this->addGbObject3D(geoObject, true, "GeoObject");
+//}
+//
+///*======================================================*/
+bool GbObject3DManager::addGbObject3D(GbObject3D *geoObject, string name)
+{
+   GbObject3DEntry *entry = new GbObject3DEntry (this, geoObject, true, name);
+   return ObObjectManager::addObObjectEntry(entry);
+}
+//bool GbObject3DManager::addGbObject3D(GbObject3D *geoObject, bool active, string name)  
+//{
+//   GbObject3DEntry *entry = new GbObject3DEntry (this, geoObject, true, name);
+//   return ObObjectManager::addObObjectEntry(entry);
+//}
+//
+/*======================================================*/
+bool GbObject3DManager::removeGbObject3D(GbObject3D *geoObject)
+{
+   return ObObjectManager::removeObObject(geoObject);
+}
+/*======================================================*/
+bool GbObject3DManager::removeGbObject3D(int index)
+{
+   return ObObjectManager::removeObObject(index);
+}
+/*======================================================*/
+//void GbObject3DManager::removeAllGbObject3Ds() 
+//{  
+//    this->gbObject3DList.clear();
+//}
+/*======================================================*/
+int GbObject3DManager::getNumberOfGbObject3Ds()
+{ 
+   return GbObject3DManager::getNumberOfObObjects();
+}
+/*======================================================*/
+vector<GbObject3D*>* GbObject3DManager::getAllGbObject3Ds()  
+{ 
+   throw UbException(UB_EXARGS,"not implemented");
+   //vector<GbObject3D*> *geoVektor = new vector<GbObject3D*>;
+   //for(int u=0; u<(int)this->gbObject3DList.size();u++)
+   //{
+   //   GbObject3D* geoObject = dynamic_cast<GbObject3D*>((gbObject3DList)[u]->getObject());
+   //   geoVektor->push_back(geoObject);
+   //}
+   //return geoVektor;  
+}
+/*======================================================*/
+GbObject3D* GbObject3DManager::getGbObject3D(int index)
+{
+   if(index <  0)                            return NULL;
+   if(index >= this->getNumberOfObObjects()) return NULL;
+
+   GbObject3D* geoObject = dynamic_cast<GbObject3D*>(this->getObObject(index));
+   return(geoObject);
+}
+/*======================================================*/
+//GbObject3DEntry* GbObject3DManager::getGbObject3DEntry(int index)
+//{
+//   if(index <  0)                                 return NULL;
+//   if(index >= (int)this->gbObject3DList.size())  return NULL;
+//
+//   return((this->gbObject3DList)[index]);
+//}
+/*====================================================*/
+void GbObject3DManager::write(UbFileOutput *out) 
+{                    
+   int size = this->getNumberOfObObjects();
+   out->writeInteger(size);
+   out->writeString("// #GbObjects");
+
+   GbObject3D *geoObject;
+   for(int pos=0; pos<size; pos++)          
+   {
+      out->writeLine();
+      geoObject = dynamic_cast<GbObject3D*>(this->getObObject(pos));
+      cout<<pos<<".:"<<geoObject->toString()<<endl;
+      geoObject->write(out);
+   }
+}
+/*======================================================================*/
+void GbObject3DManager::read(UbFileInput *in) 
+{
+   this->removeAllObObjects();
+   
+   int n = in->readInteger();                          
+   
+   cout<<"GbObject3DManager::read "<<n<<" GbObject3Ds\n";
+   GbObject3D *geoObject;
+   for(int pos=1; pos<=n; pos++)
+   {
+      in->readLine();
+      cout<<" - GbObject3D "<<pos<<" ...";
+      geoObject = GbObject3DFactory::getInstance()->createGbObject3D(in);
+      
+      GbObject3DEntry *entry = new GbObject3DEntry(this, geoObject, true, "GeoObject");
+      this->addObObjectEntry(entry);
+      cout<<"done\n";
+   }
+}
+/*======================================================*/
+string GbObject3DManager::toString()
+{
+   stringstream ss; ss<<endl;
+   
+   int size = this->getNumberOfObObjects();
+   for(int pos=0; pos<size; pos++)          
+   {
+      ObObject* geoObject = this->getObObject(pos);
+      ss<<(pos+1)<<". "<<geoObject->toString()<<endl;
+   }
+   string back = ss.str();
+   return back;
+}
+
+/*======================================================*/
+/*======================================================*/
+/*======================================================*/
+
+GbObject3DTableModel::GbObject3DTableModel(GbObject3DManager* manager)
+{
+   this->objectManager = manager;
+}
+
+/*======================================================*/
+GbObject3DTableModel::~GbObject3DTableModel(void)
+{
+}
+
+/*======================================================*/
+//Gibt die Anzahl der Spalten zurueck.
+int GbObject3DTableModel::getColumnNumber()
+{
+   return 3;
+}
+
+/*======================================================*/
+std::string GbObject3DTableModel::getColumnLabel(int column)
+{
+   switch(column)
+   {
+   case COL_NAME: return "Name";
+   case COL_TYPE: return "Type";
+   case COL_ACTIVE: return "Active";
+   default: throw UbException(UB_EXARGS,"falscher Spaltenindex");
+   }
+}
+
+/*======================================================*/
+int GbObject3DTableModel::getRowNumber()
+{
+   return this->objectManager->getNumberOfGbObject3Ds();
+}
+/*======================================================*/
+int GbObject3DTableModel::getSelectedRowIndex()
+{
+   return 0;
+   //	return this->objectManager->getSelectedIndex();
+}
+
+/*======================================================*/
+int GbObject3DTableModel::getColumnType(int column)
+{
+   switch(column) {
+   case COL_NAME :
+      return UbTableModel::COL_TYPE_STRING;
+      break;
+   case COL_TYPE :
+      return UbTableModel::COL_TYPE_STRING;
+      break;
+   case COL_ACTIVE :
+      return UbTableModel::COL_TYPE_BOOL;
+      break;
+   }
+   return -1;
+}
+
+//Gibt den Eintag der Tabelle an der angegebenen Spalten- und 
+//Zeilenposition in Form eines String Werts zurueck.
+std::string GbObject3DTableModel::getStringValue(int row, int col)
+{
+   GbObject3DEntry* gbObjEntry = dynamic_cast<GbObject3DEntry*>(this->objectManager->getObObjectEntry(row));
+   switch(col) {
+   case COL_NAME:
+      return gbObjEntry->name;
+      break;
+   case COL_TYPE:
+      return gbObjEntry->getObject()->getTypeID();
+      break;
+   case COL_ACTIVE:
+      if ( gbObjEntry->active ) return "True";
+      return "False";
+      break;
+   }
+   return "Fehler";
+}
+
+/*======================================================*/
+//bool GbObject3DManager::selectGbObject3D(int index)
+//{
+//   cout<<"GbObject3DManager::selectGbObject3D(int index):"<<index<<endl;
+//   if (index > (int)this->gbObject3DList.size()-1 || index < 0) return false; 
+//   if ( this->selectedObject == this->getGbObject3D(index) ) return true;
+//   this->selectedObject = this->getGbObject3D(index);
+//   this->notifyObserversObjectChanged();
+//   return true;
+//}
+///*======================================================*/
+//bool GbObject3DManager::selectGbObject3D(GbObject3D* geoObject)
+//{
+//   for(int pos=0; pos<(int)this->gbObject3DList.size(); pos++)
+//   {
+//      if(this->gbObject3DList[pos]->geoObject==geoObject) 
+//      {
+//         return this->selectGbObject3D(pos);
+//      }
+//   }
+//   return false;
+//}
+///*======================================================*/
+//GbObject3D* GbObject3DManager::getSelectedGbObject3D()
+//{
+//   return this->selectedObject;
+//}
+///*======================================================*/
+//int GbObject3DManager::getSelectedIndex()
+//{
+//   for(int pos=0; pos<(int)this->gbObject3DList.size(); pos++)
+//   {
+//      if(this->gbObject3DList[pos]->geoObject==this->selectedObject) 
+//      {
+//         return pos;
+//      }
+//   }
+//   return -1;
+//}
diff --git a/source/VirtualFluidsCore/Geometry/GbObject3DManager.h b/source/VirtualFluidsCore/Geometry/GbObject3DManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..c842ddaff866fa615da8393d80d8c728290e3ffd
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbObject3DManager.h
@@ -0,0 +1,122 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBOBJECT3DMANAGER_H
+#define GBOBJECT3DMANAGER_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+#include <basics/utilities/UbFileOutput.h>
+#include <basics/utilities/UbTableModel.h>
+#include <basics/objects/ObObjectManager.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbObject3DManager;
+typedef VFSharedPtr<GbObject3DManager> GbObject3DManagerPtr;
+
+                                                  
+class GbObject3D;   
+class GbObject3DManager;
+class GbObject3DTableModel;
+
+class GbObject3DEntry  : public ObObjectEntry
+{
+   friend class GbObject3DManager;
+   friend class GbObject3DTableModel;
+public:
+   std::string getName() { return this->name;}
+private:
+   //GbObject3DManager *parent;
+   //GbObject3D        *geoObject;
+   bool        active;
+   std::string name;
+   
+
+   GbObject3DEntry(GbObject3DManager* parent, GbObject3D* geoObject, bool active, std::string name);
+ 
+};
+
+
+class GbObject3DManager  : public ObObjectManager 
+{                                           
+public:
+   GbObject3DManager();
+   ~GbObject3DManager();
+
+   ObObjectEntry* createNewObObjectEntry(ObObject *obj);
+   ObObjectFactory* getObObjectFactory();
+
+
+   //bool addGbObject3D(GbObject3D *geoObject3D);  
+   bool addGbObject3D(GbObject3D *geoObject3D, std::string name);   
+   //bool addGbObject3D(GbObject3D *geoObject3D, bool active, std::string name);   
+
+   bool removeGbObject3D(GbObject3D *geoObject3D);
+   bool removeGbObject3D(int index);
+
+   int getNumberOfGbObject3Ds();                 
+   std::vector<GbObject3D*>* getAllGbObject3Ds();
+   GbObject3D* getGbObject3D(int index);
+
+   //keine Definition dafuer da ...
+   //void writeValidationAVSFile(string filename);
+   //void writeSurfaceAVSFile(string filename);
+
+   //public final OctConstructionDescriptor[] getAllActiveConstructions()
+   //public final OctSpecificConstructionInstrument getSpecificConstructionInstrumentInstance(int index)
+   //public final boolean isConstructionActive(int index)
+   //public final boolean isConstructionVisible(int index)
+   //public final void activateConstruction(int index, boolean active)
+   //public final void visibleConstruction(int index, boolean visible)
+  // UbTableModel* getTableModel();
+   //void objectChanged(UbObservable* observable);
+   //void objectWillBeDeleted(UbObservable* observable);
+
+
+   void read(UbFileInput *in);
+   void write(UbFileOutput *out); 
+
+   std::string toString();
+
+private:
+   //GbObject3DTableModel* tablemodel;
+  // GbObject3D* selectedObject;
+   //vector<GbObject3DEntry*> gbObject3DList;
+};
+
+class GbObject3DTableModel : public UbTableModel
+{
+public:
+
+   static const int COL_NAME   = 0;
+   static const int COL_TYPE   = 1;
+   static const int COL_ACTIVE = 2;
+
+   GbObject3DTableModel(GbObject3DManager* manager);
+   ~GbObject3DTableModel(void);
+
+   //////////////////////////////////////////////////////////////////////////
+   //Geerbt von CabTable
+   int getColumnNumber(void);
+   int getRowNumber();
+
+   std::string getColumnLabel(int column);
+
+   int getColumnType(int);
+   std::string getStringValue(int row, int col);
+   int getSelectedRowIndex();
+   //bool GetBoolValue(int row, int col);
+   void setStringValue(int row, int col, std::string str) { throw UbException(UB_EXARGS,"not implemented"); }
+
+protected:
+   GbObject3DManager* objectManager;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/GbObjectGroup3D.cpp b/source/VirtualFluidsCore/Geometry/GbObjectGroup3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3e8c4087d537ae4c0bcf03155b032c459ade327f
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbObjectGroup3D.cpp
@@ -0,0 +1,146 @@
+#include <numerics/geometry3d/GbObjectGroup3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+using namespace std;
+
+/*=====================================================*/
+GbObjectGroup3D::GbObjectGroup3D()
+{
+   this->setName("ObjectGroup");
+}
+/*=====================================================*/
+GbObjectGroup3D::~GbObjectGroup3D()
+{
+}
+/*=====================================================*/
+void GbObjectGroup3D::finalize()
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=======================================================*/
+void GbObjectGroup3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+double GbObjectGroup3D::getDistance(GbPoint3D* p)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+
+void GbObjectGroup3D::setCenterX1Coordinate(const double& value)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+void GbObjectGroup3D::setCenterX2Coordinate(const double& value)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+void GbObjectGroup3D::setCenterX3Coordinate(const double& value)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+void GbObjectGroup3D::setRadius(const double& radius)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+double GbObjectGroup3D::getDistance(const double& x1p, const double& x2p, const double& x3p)
+{
+   throw UbException(UB_EXARGS,"not implemented.");
+}
+/*=====================================================*/
+//true, wenn 'in Object' oder 'auf Boundary'!
+bool GbObjectGroup3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   return false;
+}
+/*=====================================================*/
+//true, wenn 'in Object' oder 'auf Boundary'!
+bool GbObjectGroup3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   return false;
+}
+/*=====================================================*/
+string GbObjectGroup3D::toString()
+{
+	stringstream ss;
+	ss<< "GbObjectGroup3D[";
+	ss <<"mid="<<midPoint->toString()<<", r="<<radius<<"]";
+	return ss.str();
+}
+/*=====================================================*/
+GbLine3D* GbObjectGroup3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   return NULL;
+}
+/*=========================================================================*/
+vector<GbTriangle3D*> GbObjectGroup3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> allTriangles;
+
+   //loop ueber alle objekte in der group
+   for( std::list< GbObject3D* >::iterator iter = this->geoobjects.begin();
+                                          iter != this->geoobjects.end();
+                                          iter++ )
+   {
+      vector<GbTriangle3D*> triangles;
+      triangles = (*iter)->getSurfaceTriangleSet();
+
+      for( size_t i=0;i<triangles.size(); i++ )
+      {
+         //kopieren...
+         allTriangles.push_back( triangles[i] );
+      }
+   }
+   return allTriangles;
+}
+/*=======================================================*/
+void GbObjectGroup3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+}
+/*=======================================================*/
+void GbObjectGroup3D::write(UbFileOutput* out)
+{
+   out->writeString(this->getCreator()->getTypeID());
+   midPoint->write(out);
+   out->writeDouble(radius);
+   out->writeInteger((int)triangulationMode);
+}
+/*=======================================================*/
+void GbObjectGroup3D::read(UbFileInput* in)
+{
+}
+/*=======================================================*/
+bool GbObjectGroup3D::hasIntersectionWithDirectedLine(GbPoint3D origin, GbPoint3D direction)
+{
+   return false;
+}
+/*=======================================================*/
+bool GbObjectGroup3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   return false;
+}
+/*=======================================================*/
+bool GbObjectGroup3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   return false;
+}
+/*==========================================================*/
+double GbObjectGroup3D::getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+   return 0.0;
+}
+/*==========================================================*/
+double GbObjectGroup3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   return 0.0;
+}
+/*=======================================================*/
diff --git a/source/VirtualFluidsCore/Geometry/GbObjectGroup3D.h b/source/VirtualFluidsCore/Geometry/GbObjectGroup3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..52ffdcf7c6ec5e0261d41ff9b38337b193c1e423
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbObjectGroup3D.h
@@ -0,0 +1,162 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBOBJECTGROUP3D_H
+#define GBOBJECTGROUP3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+#ifdef CAB_CTL
+   #include <ctl.h>
+#endif //CAB_CTL
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <basics/utilities/UbObserver.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbObjectGroup3D;
+typedef VFSharedPtr<GbObjectGroup3D> GbObjectGroup3DPtr;
+
+
+class GbLine3D;
+class GbTriangle3D;
+class GbObject3DCreator;
+
+class GbObjectGroup3D : public GbObject3D, public UbObserver
+{                                              
+public:
+   enum TRIANGULATIONMODE { CUBOIDPROJECTION ,RAYPROJECTION };
+   
+   //////////////////////////////////////////////////////////////////////////
+   // Konstruktoren
+   GbObjectGroup3D(); 
+   GbObjectGroup3D(GbObjectGroup3D *group){}; 
+   ~GbObjectGroup3D();
+
+   GbObjectGroup3D* clone() {return new GbObjectGroup3D(this);}
+   void finalize();
+
+   void addGbObject(GbObject3D* object)
+   {
+      this->geoobjects.push_back(object);
+   }
+
+   double getRadius() const	{	return this->radius;	}
+
+   double getX1Centroid()  { return midPoint->getX1Coordinate();}
+   double getX1Minimum()   { return midPoint->getX1Coordinate()-radius;}
+   double getX1Maximum()   { return midPoint->getX1Coordinate()+radius;}
+   double getX2Centroid()  { return midPoint->getX2Coordinate();}
+   double getX2Minimum()   { return midPoint->getX2Coordinate()-radius;}
+   double getX2Maximum()   { return midPoint->getX2Coordinate()+radius;}
+   double getX3Centroid()  { return midPoint->getX3Coordinate();}
+   double getX3Minimum()   { return midPoint->getX3Coordinate()-radius;}
+   double getX3Maximum()   { return midPoint->getX3Coordinate()+radius;}
+
+   void setCenterX1Coordinate(const double& value);
+   void setCenterX2Coordinate(const double& value);
+   void setCenterX3Coordinate(const double& value);
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+   void setRadius(const double& radius);
+
+   GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+   double getDistance(GbPoint3D* p); 
+   double getDistance(const double& x1p, const double& x2p, const double& x3p);
+
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary);
+
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+                                
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+   bool hasIntersectionWithDirectedLine(GbPoint3D origin, GbPoint3D direction);
+
+	std::string toString();
+
+   ObObjectCreator* getCreator(){ return NULL; };
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);       
+
+   void translate(const double& x1, const double& x2, const double& x3) 
+   {
+      this->midPoint->translate(x1, x2, x3); 
+      this->notifyObserversObjectChanged();
+   }
+   void rotate(const double& rx1, const double& rx2, const double& rx3) {/* rotation makes no sense*/ }
+   void scale(const double& sx1, const double& sx2, const double& sx3) { this->radius *= sx1; }
+
+   TRIANGULATIONMODE getTriangulationMode() {return triangulationMode;}
+   void setTriangulationMode(TRIANGULATIONMODE mode) { this->triangulationMode = mode; }
+   
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject)
+   {
+      this->notifyObserversObjectChanged();
+      //std::cout<<"GbSphere:objectChanged() - toDo-);";
+   }
+   void objectWillBeDeleted(UbObservable* objectForDeletion)
+   {
+	   std::cout<<"throw UbException(-GbObjectGroup3D::finalize() - toDo-);";
+   }
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere, weil man eine
+
+   std::list< GbObject3D* > getGbObject3DList() { return this->geoobjects; }
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & midPoint;
+      ar & radius;
+      ar & triangulationMode;
+      ar & geoobjects;
+   }
+#endif //CAB_RCF
+#ifdef CAB_CTL
+   ctl::oStream &write(ctl::oStream &os) const
+   { 
+      midPoint->write(os);
+      return os<<radius; 
+   }
+   ctl::iStream &read(ctl::iStream &is) 
+   { 
+      midPoint->read(is);
+      return is>>radius;
+   }
+#endif //CAB_CTL
+
+private:
+   GbPoint3D* midPoint;
+   double radius;  // Radius des Kreises
+   TRIANGULATIONMODE triangulationMode;
+
+   std::list< GbObject3D* > geoobjects;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   #if defined(RCF_USE_SF_SERIALIZATION) && (CAB_RCF <= 903) 
+      SF_SERIALIZE_ENUM(GbObjectGroup3D::TRIANGULATIONMODE) //bei klassen ausserhalb der klasse;-)
+   #endif
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbObjectGroup3D>("GbObjectGroup3D")        , SF_GbObjectGroup3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbObjectGroup3D >()), SF_GbObjectGroup3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //GbObjectGroup3D_H
diff --git a/source/VirtualFluidsCore/Geometry/GbPoint3D.cpp b/source/VirtualFluidsCore/Geometry/GbPoint3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..980fcf386f20cb0e64c56e0301bbc23995b269e4
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbPoint3D.cpp
@@ -0,0 +1,146 @@
+#include <numerics/geometry3d/GbPoint3D.h>
+//#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/creator/GbPoint3DCreator.h>
+
+using namespace std;
+
+/*=======================================================*/
+ObObjectCreator* GbPoint3D::getCreator()
+{
+   return GbPoint3DCreator::getInstance();
+}
+/*=======================================================*/
+GbPoint3D::GbPoint3D()
+{ 
+   this->x1=0.0; 
+   this->x2=0.0; 
+   this->x3=0.0;
+}                                             
+/*=======================================================*/
+GbPoint3D::GbPoint3D(const double& x1, const double& x2, const double& x3)
+{ 
+   this->x1=x1; 
+   this->x2=x2; 
+   this->x3=x3;
+}
+/*=======================================================*/
+GbPoint3D::GbPoint3D(GbPoint3D* point)
+{
+   this->x1 = point->x1;                                             
+   this->x2 = point->x2;
+   this->x3 = point->x3;
+} 
+/*=======================================================*/
+double GbPoint3D::getDistance(GbPoint3D* p)
+{
+   double dx1 = this->x1 - p->x1;
+   double dx2 = this->x2 - p->x2;
+   double dx3 = this->x3 - p->x3;
+   return std::sqrt(dx1*dx1 + dx2*dx2 + dx3*dx3);
+}
+/*=======================================================*/
+bool GbPoint3D::equals(const GbPoint3D* point) const
+{
+   if(fabs(this->x1-point->x1)>1.E-10) return false;
+   if(fabs(this->x2-point->x2)>1.E-10) return false;
+   if(fabs(this->x3-point->x3)>1.E-10) return false;
+
+   return true;
+}
+/*=======================================================*/
+void GbPoint3D::transform(const double matrix[4][4])
+{
+   double tempX1 = x1;
+   double tempX2 = x2;
+   double tempX3 = x3;
+   x1 = matrix[0][0] * tempX1 + matrix[0][1] * tempX2 + matrix[0][2] * tempX3 + matrix[0][3] * 1.;
+   x2 = matrix[1][0] * tempX1 + matrix[1][1] * tempX2 + matrix[1][2] * tempX3 + matrix[1][3] * 1.;
+   x3 = matrix[2][0] * tempX1 + matrix[2][1] * tempX2 + matrix[2][2] * tempX3 + matrix[2][3] * 1.;
+}
+/*=======================================================*/
+bool GbPoint3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+{
+   return (fabs(x1)<1.E-13 && fabs(x2)<1.E-13 && fabs(x3)<1.E-13 );
+}
+/*=======================================================*/
+bool GbPoint3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+{
+   pointIsOnBoundary = (fabs(x1)<1.E-13 && fabs(x2)<1.E-13 && fabs(x3)<1.E-13 );
+   return pointIsOnBoundary;
+}
+/*=======================================================*/
+vector<GbTriangle3D*> GbPoint3D::getSurfaceTriangleSet()
+{            
+   cout<<"GbPoint3D::getSurfaceTriangleSet() - test ... if no exception occurs, everything is fine\n";
+   vector<GbTriangle3D*> triangles;
+   return triangles; //<-empty vector! is okay!
+   
+   //old:
+   //to avoid unnecessary exceptions a point will generate a triangle with
+   //three point with same coordinates
+   //vector<GbTriangle3D*> triangles;
+   //GbPoint3D p1(getX1Coordinate(),getX2Coordinate(),getX3Coordinate());
+   //triangles.push_back(new GbTriangle3D(new GbPoint3D(p1),new GbPoint3D(p1),new GbPoint3D(p1)));
+}
+/*=======================================================*/
+GbLine3D* GbPoint3D::createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"not implemented");
+} 
+/*=======================================================*/
+string GbPoint3D::toString()
+{
+   stringstream ss;
+   ss<<"GbPoint3D["<<this->x1<<","<<this->x2<<","<<this->x3<<"]";
+   return((ss.str()).c_str());
+}
+/*=======================================================*/
+void GbPoint3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   out->writeDouble(x1);
+   out->writeDouble(x2);
+   out->writeDouble(x3);
+}
+/*=======================================================*/
+void GbPoint3D::read(UbFileInput* in) 
+{  
+   x1=in->readDouble();
+   x2=in->readDouble();
+   x3=in->readDouble();
+}
+/*=======================================================*/
+void GbPoint3D::translate(const double& dx1, const double& dx2, const double& dx3)
+{  
+   this->x1 += dx1;
+   this->x2 += dx2;
+   this->x3 += dx3;
+  // wenn Notify hier dann nicht im Cuboid oder spher translate ?!
+   //sollte eigentlich!
+   //--> hier muss notify aufgerufen werden udn rekuriv dann z.B. Cuboid, etc 
+   
+   //aber da ist halt einfach daemlich, ich asse es auf gellers way... (erstmal)
+   this->notifyObserversObjectChanged(); 
+}
+/*=======================================================*/
+void GbPoint3D::rotate(const double& rx1, const double& rx2, const double& rx3)
+{  
+   double newX1 = cos(rx3)*cos(rx2)*x1-x2*sin(rx3)*cos(rx1)+x2*cos(rx3)*sin(rx2)*sin(rx1)+x3*sin(rx3)*sin(rx1)+x3*cos(rx3)*sin(rx2)*cos(rx1);
+   double newX2 =  sin(rx3)*cos(rx2)*x1+x2*cos(rx3)*cos(rx1)+x2*sin(rx3)*sin(rx2)*sin(rx1)-x3*cos(rx3)*sin(rx1)+x3*sin(rx3)*sin(rx2)*cos(rx1);
+   double newX3 = -sin(rx2)*x1+cos(rx2)*sin(rx1)*x2+cos(rx2)*cos(rx1)*x3;
+
+   this->x1 = newX1;
+   this->x2 = newX2;
+   this->x3 = newX3;
+   this->notifyObserversObjectChanged(); 
+}
+/*=======================================================*/
+void GbPoint3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{  
+   this->x1 *= sx1;
+   this->x2 *= sx2;
+   this->x3 *= sx3;
+   this->notifyObserversObjectChanged(); 
+}
+/*=======================================================*/
+
diff --git a/source/VirtualFluidsCore/Geometry/GbPoint3D.h b/source/VirtualFluidsCore/Geometry/GbPoint3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..5cccbc1718b10321867742def359e18109afeb8d
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbPoint3D.h
@@ -0,0 +1,123 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBPOINT3D_H
+#define GBPOINT3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <string>
+#include <sstream>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbPoint3D;
+typedef VFSharedPtr<GbPoint3D> GbPoint3DPtr;
+
+
+class GbTriangle3D;
+class GbObject3DCreator;
+
+#ifdef CAB_CTL
+   #include <ctl.h>
+#endif
+
+class GbPoint3D : public GbObject3D
+{
+public:
+   GbPoint3D();
+   GbPoint3D(const double& x1, const double& x2, const double& x3);
+   GbPoint3D(GbPoint3D *point);                
+   ~GbPoint3D() {}
+
+   GbPoint3D* clone() {return new GbPoint3D(this);}
+   void finalize() {}
+
+   void setCoordinates(const double& x1, const double& x2, const double& x3)
+   {
+       this->x1=x1;
+       this->x2=x2;
+       this->x3=x3;
+       this->notifyObserversObjectChanged();
+   }
+   void setX1(const double& x1) { this->x1=x1; this->notifyObserversObjectChanged(); }
+   void setX2(const double& x2) { this->x2=x2; this->notifyObserversObjectChanged(); }
+   void setX3(const double& x3) { this->x3=x3; this->notifyObserversObjectChanged(); }
+
+   double getX1Coordinate() const  { return this->x1; }
+   double getX2Coordinate() const  { return this->x2; }
+   double getX3Coordinate() const  { return this->x3; }
+
+   void transform(const double matrix[4][4]);
+ 
+   double getX1Centroid()  { return this->x1; }
+   double getX1Minimum()   { return this->x1; }
+   double getX1Maximum()   { return this->x1; }
+   double getX2Centroid()  { return this->x2; }
+   double getX2Minimum()   { return this->x2; }
+   double getX2Maximum()   { return this->x2; }
+   double getX3Centroid()  { return this->x3; }
+   double getX3Minimum()   { return this->x3; }
+   double getX3Maximum()   { return this->x3; }        
+ 
+   void translate(const double& x1, const double& x2, const double& x3);
+   void rotate(const double& rx1, const double& rx2, const double& rx3);
+   void scale(const double& sx1, const double& sx2, const double& sx3);
+
+   double getDistance(GbPoint3D *p);
+   bool equals(const GbPoint3D* point) const;
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary);
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x23) { return false; }
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   GbLine3D* createClippedLine3D(GbPoint3D &point1, GbPoint3D &point2);
+   virtual std::string toString();
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren
+                                          //, welche sonst hier "ueberdeckt" waere,da es dieselbe methode mit anderen args gibt!
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & x1; 
+      ar & x2; 
+      ar & x3;
+   }
+#endif //CAB_RCF
+
+#ifdef CAB_CTL
+   ctl::oStream &write(ctl::oStream &os) const
+   { 
+      return os<<x1<<x2<<x3; 
+   }
+   ctl::iStream &read(ctl::iStream &is) 
+   { 
+      return is>>x1>>x2>>x3;
+   }
+#endif
+
+   //member
+   double x1;
+   double x2;
+   double x3;      
+};
+
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbPoint3D>("GbPoint3D")              , SF_GbPoint3D      );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbPoint3D >()), SF_GbPoint3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/GbPolygon3D.cpp b/source/VirtualFluidsCore/Geometry/GbPolygon3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..879c6a9af274e551d306ccb99eb6a1998a7cd723
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbPolygon3D.cpp
@@ -0,0 +1,686 @@
+#include <numerics/geometry3d/GbPolygon3D.h>
+#include <numerics/geometry3d/creator/GbPolygon3DCreator.h>
+
+using namespace std;
+
+ObObjectCreator* GbPolygon3D::getCreator()
+{
+   return GbPolygon3DCreator::getInstance();
+}
+
+int GbPolygon3D::counter = 0;
+
+GbPolygon3D::GbPolygon3D()
+{
+   init();
+   counter++;
+   this->ps = new GbSystem3D::PointSet3(0);
+}
+void GbPolygon3D::init()
+{
+   x1s        = 0.0;
+   x2s        = 0.0;
+   x1min      = 0.0;
+   x1max      = 0.0;
+   x2min      = 0.0;
+   x2max      = 0.0;
+   //		points   = NULL;
+   consistent = false;
+   ps         = NULL;
+}
+
+/**
+* Creates an empty 3D polygon with the specified capacity.
+* @param capacity the initial capacity
+*/
+GbPolygon3D::GbPolygon3D(int capacity)
+{
+   init();
+   counter++;
+   this->ps = new GbSystem3D::PointSet3(capacity);
+   //     this.po = new PointObserver(this);
+}
+/**
+* Creates a 3D polygon with the specified points.
+* @param points the initial points of the polygon
+*/
+GbPolygon3D::GbPolygon3D(vector<GbPoint3D>& points)
+{
+   init();
+   counter++;
+   this->ps = new GbSystem3D::PointSet3((int)points.size());
+   this->addPoints(points);
+}
+/**
+* Creates a 3D polygon as clone of the specified 3D polygon.
+* @param polygon the 3D polygon to be cloned
+*/
+GbPolygon3D::GbPolygon3D(GbPolygon3D* polygon)
+{
+   this->init();
+   counter++;
+   this->ps = new GbSystem3D::PointSet3((int)polygon->size());
+   vector<GbPoint3D> temp = polygon->getPoints();
+   this->addPoints( temp  );
+}
+
+GbPolygon3D::~GbPolygon3D()
+{
+   counter--;
+   //if(points)
+   //for(unsigned u=0; u<points->size(); u++)
+   //{
+   //	delete (*points)[u];
+   //}
+   //		delete this->points;
+   delete this->ps;
+}
+
+/*======================================================================*/
+/**
+* Returns the number of points.
+* @return the number of points
+*/
+int GbPolygon3D::size()
+{
+   return(this->ps->size());
+}
+/**
+* Returns the number of times this 3D polygon contains the specified point.
+* @param point the point
+* @return the number of times this 3D polygon contains the specified point
+*/
+int GbPolygon3D::contains(GbPoint3D* point)
+{
+   return(this->ps->contains(point));
+}
+/**
+* Returns the number of times this 3D polygon contains a point equal to the specified point.
+* @param point the point
+* @return the number of times this 3D polygon contains a point equal to the specified point
+*/
+int GbPolygon3D::containsEqual(GbPoint3D* point)
+{
+   return(this->ps->containsEqual(point));
+}
+/**
+* Returns true, if this 3D polygon contains the specified line.
+* @param point1 the first point
+* @param point2 the second point
+* @return true, if this 3D polygon contains the specified line
+*/
+bool GbPolygon3D::containsLine(GbPoint3D* point1, GbPoint3D* point2)
+{
+   return(this->ps->containsLine(point1, point2));
+}
+/**
+* Returns true, if this 3D polygon contains the specified line.
+* @param line the line
+* @return true, if this 3D polygon contains the specified line
+*/
+bool GbPolygon3D::containsLine(GbLine3D* line)
+{
+   return(this->ps->containsLine(line->getPoint1(), line->getPoint2()));
+}
+/**
+* Returns the first point.
+* @return the first point
+*/
+GbPoint3D* GbPolygon3D::getFirstPoint()
+{
+   return(this->ps->getFirstPoint());
+}
+/**
+* Returns the last point.
+* @return the last point
+*/
+GbPoint3D* GbPolygon3D::getLastPoint()
+{
+   return(this->ps->getLastPoint());
+}
+/**
+* Returns the specified point.
+* @param index the index
+* @return the specified point
+* @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+*/
+GbPoint3D* GbPolygon3D::getPoint(const int& index) 
+{
+   if(index < 0 || index > this->ps->size()) throw UbException(UB_EXARGS,"ArrayIndexOutOfBoundsException-GbPolygon3D.getPoint()");
+   return(this->ps->getPoint(index));
+}
+/**
+* Returns the points.
+* @return the points
+*/
+vector<GbPoint3D> GbPolygon3D::getPoints()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->points);
+}
+/**
+* Returns the points within the specified rectangle.
+* @param p1 the 1st point of the rectangle
+* @param p2 the 2nd point of the rectangle
+* @return the points within the specified rectangle
+*/
+vector<GbPoint3D> GbPolygon3D::getPoints(GbPoint3D* p1, GbPoint3D* p2)
+{
+   return(this->getPoints(p1->x1, p1->x2, p1->x3, p2->x1, p2->x2, p2->x3));
+}
+/**
+* Returns the points within the specified rectangle.
+* @param p1x1 the 1st x1 coordinate of the rectangle
+* @param p1x2 the 1st x2 coordinate of the rectangle
+* @param p1x3 the 1st x3 coordinate of the rectangle
+* @param p2x1 the 2nd x1 coordinate of the rectangle
+* @param p2x2 the 2nd x2 coordinate of the rectangle
+* @param p2x3 the 2nd x3 coordinate of the rectangle
+* @return the points within the specified rectangle
+*/
+vector<GbPoint3D> GbPolygon3D::getPoints(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3)
+{
+   double x1min, x1max, x2min, x2max, x3min, x3max;
+
+   if(UbMath::less(p1x1, p2x1)) { x1min = p1x1; x1max = p2x1; }
+   else                           { x1min = p2x1; x1max = p1x1; }
+   if(UbMath::less(p1x2, p2x2)) { x2min = p1x2; x2max = p2x2; }
+   else                           { x2min = p2x2; x2max = p1x2; }
+   if(UbMath::less(p1x3, p2x3)) { x3min = p1x3; x3max = p2x3; }
+   else                           { x3min = p2x3; x3max = p1x3; }
+
+   GbSystem3D::PointSet3 *pts = new GbSystem3D::PointSet3(1);
+
+   if(!this->consistent) this->calculateValues();
+   for(int i=this->size()-1; i>=0; i--)
+   {
+      if(UbMath::lessEqual(x1min, (this->points)[i].x1) && UbMath::greaterEqual(x1max, (this->points)[i].x1) &&
+         UbMath::lessEqual(x2min, (this->points)[i].x2) && UbMath::greaterEqual(x2max, (this->points)[i].x2) &&
+         UbMath::lessEqual(x3min, (this->points)[i].x3) && UbMath::greaterEqual(x3max, (this->points)[i].x3))     pts->add((this->points)[i]);
+   }
+   return(pts->getPoints());
+}
+/**
+* Returns the area of this polygon.
+* The area is positive for positive ordered points, otherwise negative.
+* @return the area of this polygon
+*/
+//double getArea()
+//{
+//   if(!this.consistent) this.calculateValues();
+//   return(this.area);
+//}
+double GbPolygon3D::getX1Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1s);
+}
+double GbPolygon3D::getX1Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1min);
+}
+double GbPolygon3D::getX1Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1max);
+}
+double GbPolygon3D::getX2Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2s);
+}
+double GbPolygon3D::getX2Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2min);
+}
+double GbPolygon3D::getX2Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2max);
+}
+double GbPolygon3D::getX3Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3s);
+}
+double GbPolygon3D::getX3Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3min);
+}
+double GbPolygon3D::getX3Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3max);
+}
+
+/**
+* Adds a point to the end of this polygon. Notifies the observers of this 3D polygon.
+* @param point the point
+*/
+void GbPolygon3D::addPoint(GbPoint3D* point)
+{
+   //if((this instanceof GbPolygon3D) && !(point instanceof GbPoint3D)) throw new IllegalArgumentException("GbPolygon3D.addPoint(): points of 3D polygons have to be 3D points!");
+
+   this->ps->add(point);
+   //point.addObserver(this.po);
+   this->consistent = false;
+   //super.notifyObservers();
+}
+/**
+* Adds a number of points to the end of this polygon. Notifies the observers of this 3D polygon.
+* @param points the points
+*/
+void GbPolygon3D::addPoints(vector<GbPoint3D>& points)
+{
+   //if((this instanceof GbPolygon3D) && (points.getClass().getComponentType() != GbPoint3D.class)) throw new IllegalArgumentException("GbPolygon3D.addPoints(): points of 3D polygons have to be 3D points!");
+
+   this->ps->add(points);
+   //for(int i=0; i<points.length; i++) points[i].addObserver(this.po);
+   this->consistent = false;
+   //super.notifyObservers();
+}
+/**
+* Inserts a point at the specified position within this polygon. Notifies the observers of this 3D polygon.
+* @param point the point
+* @param index the index
+* @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+*/
+//public void insertPoint(GbPoint3D point, int index) throws ArrayIndexOutOfBoundsException
+//{
+//   if((this instanceof GbPolygon3D) && !(point instanceof GbPoint3D)) throw new IllegalArgumentException("GbPolygon3D.insertPoint(): points of 3D polygons have to be 3D points!");
+//   if(index < 0 || index > this.ps.size()) throw new ArrayIndexOutOfBoundsException("GbPolygon3D.insert(): invalid index specified: "+index);
+
+//   this.ps.insert(point, index);
+//   point.addObserver(this.po);
+//   this.consistent = false;
+//   super.notifyObservers();
+//}
+/**
+* Removes all points from this polygon identical to the specified one. Notifies the observers of this 3D polygon.
+* @param point the point
+*/
+//public void deletePoint(GbPoint3D point)
+//{
+//   this.ps.delete(point);
+//   point.removeObserver(this.po);
+//   this.consistent = false;
+//   super.notifyObservers();
+//}
+/**
+* Removes all points from this polygon equal to the specified one. Notifies the observers of this 3D polygon.
+* @param point the point
+*/
+//public void deleteEqualPoint(GbPoint3D point)
+//{
+//   this.ps.deleteEqual(point);
+//   point.removeObserver(this.po);
+//   this.consistent = false;
+//   super.notifyObservers();
+//}
+/**
+* Removes all points from this polygon. Notifies the observers of this 3D polygon.
+*/
+void GbPolygon3D::clear()
+{
+   //		delete this->points;
+   this->ps->clearAndTrim();
+   delete this->ps;
+
+   //for(int i=points.length-1; i>=0; i--) points[i].removeObserver(this.po);
+   this->consistent = false;
+   //super.notifyObservers();
+}
+
+/**
+* Returns true if this 3D polygon equals the specified object.
+* Two polygon are equal, if their points are equal.
+* <BR>Note that the order of points is recognized!
+* @return true if this 3D polygon equals the specified object
+* @see GbPoint3D#equals(java.lang.Object)
+*/
+// bool equals(Object object)
+// {
+//    try
+//    {
+//	GbPolygon2D polygon = (GbPolygon3D) object;
+//int         n       = this.size();
+
+//if(n != polygon.size()) return(false);
+//for(int i=0; i<n; i++) if(!this.getPoint(i).equals(polygon.getPoint(i))) return(false);
+//return(true);
+//    }
+//    catch(Exception e){ return(false); }
+// }
+/**
+* Returns a string representation of this 3D polygon.
+* @return a string representation of this 3D polygon
+*/
+string GbPolygon3D::toString()
+{
+   stringstream ss;
+   ss<<"GbPolygon3D[";
+   ss<<this->size()<<" points";
+
+   //    ss<<", x1s="<<this->x1s;
+   //    ss<<", x2s="<<this->x2s;
+   //ss<<", x3s="<<this->x3s;
+   //    ss<<", x1min="<<this->x1min;
+   //    ss<<", x1max="<<this->x1max;
+   //    ss<<", x2min="<<this->x2min;
+   //    ss<<", x2max="<<this->x2max;
+   //ss<<", x3min="<<this->x3min;
+   //    ss<<", x3max="<<this->x3max;
+   ss<<"]"<<endl;
+   for(int u=0; u<this->size(); u++)
+      ss<<this->ps->getPoint(u)->toString()<<endl;
+
+   return(ss.str());
+}
+/*======================================================================*/
+
+
+/*======================================================================*/
+/*  Calculation                                                         */
+/*                                                                      */
+/*
+* Returns the intersection points of this 3D polygon and the specified 3D line.
+* @param line the 3D line to intersect
+* @return the intersection points of this 3D polygon and the specified 3D line
+*/
+// public GbPoint3D[] calculateIntersectionPoints3D(GbLine3D line)
+// {
+//    GbSystem.PointSet pointSet = new GbSystem.PointSet(0);
+//    GbPoint3D         points[] = this.getPoints();
+//    GbPoint3D         pCrossed = null;
+//    int               n        = points.length;
+//    if(n < 2)         return(pointSet.getPoints());
+
+//    for(int i=1; i<n; i++)
+//    {
+//pCrossed = GbSystem.calculateIntersectionPoint3D(points[i-1], points[i], line.p1, line.p2);
+//if(pCrossed != null) pointSet.add(pCrossed);
+//    }
+//    pCrossed = GbSystem.calculateIntersectionPoint3D(points[n-1], points[0], line.p1, line.p2);
+//    if(pCrossed != null) pointSet.add(pCrossed);
+
+//    return(pointSet.getPoints());
+// }
+
+/*
+* Returns true if the specified 3D point lies within (or on the border of) this 3D polygon.
+* @param point the 3D point to check
+* @return true if the specified 3D point lies within (or on the border of) this 3D polygon
+*/
+// public boolean enclosesPoint3D(GbPoint3D point)
+// {
+//    if(GbSystem.less(point.x1, this.x1min))    return(false);
+//    if(GbSystem.less(point.x2, this.x2min))    return(false);
+//    if(GbSystem.greater(point.x1, this.x1max)) return(false);
+//    if(GbSystem.greater(point.x2, this.x2max)) return(false);
+//    if(this.containsEqual(point) > 0)          return(true);
+
+//    QbList    ltest    = new QbList(GbPoint2D.class, QbList.NOEQUALOBJECTS);
+//    GbPoint3D points[] = this.getPoints();
+//    GbPoint3D ptest;
+//    int       n        = points.length;
+//    if(n < 2) return(false);
+
+//    if(GbSystem.equal(point.x2, this.x2min)) ptest = new GbPoint3D(point.x1, this.x2min-1.0);
+//    else                                     ptest = new GbPoint3D(point.x1, this.x2max+1.0);
+
+//    for(int i=1; i<n; i++)
+//    {
+//try { ltest.append(GbSystem.calculateIntersectionPoint2D(points[i-1], points[i], point, ptest)); }
+//catch(Exception e){}
+//    }
+//    try { ltest.append(GbSystem.calculateIntersectionPoint3D(points[n-1], points[0], point, ptest)); }
+//    catch(Exception e){}
+//    return((ltest.size()%2)==1);
+// }
+
+/*
+* Returns a new 3D polygon clipped by the specified 3D rectangle (result may be null!).
+* @param rectangle the 3D rectangle
+* @return a new 3D polygon clipped by the specified 3D rectangle
+*/
+// GbPolygon3D *createClippedPolygon3D(GbCuboid3D *cube)
+// {
+//return(GbSystem::clipPolygon3D(this->getPoints(), cube->p1->x1, cube->p1->x2, cube->p1->x3, , cube->p2->x1, cube->p2->x2, cube->p2->x3));
+// }
+/*                                          
+* Returns a new 3D polygon clipped by the specified 3D rectangle (result may be null!).
+* @param p1 the 1st point of the rectangle
+* @param p2 the 2nd point of the rectangle
+* @return a new 3D polygon clipped by the specified 3D rectangle
+*/
+// GbPolygon3D *createClippedPolygon3D(GbPoint3D *p1, GbPoint3D *p2)
+// {
+//return(GbSystem::clipPolygon3D(this->getPoints(), p1->x1, p1->x2, p1->x3, p2->x1, p2->x2, p2->x3));
+// }
+/*
+* Returns a new 3D polygon clipped by the specified 3D rectangle (result may be null!).
+* @param p1x1 the 1st x1 coordinate of the rectangle
+* @param p1x2 the 1st x2 coordinate of the rectangle
+* @param p2x1 the 2nd x1 coordinate of the rectangle
+* @param p2x2 the 2nd x2 coordinate of the rectangle
+* @return a new 3D polygon clipped by the specified 3D rectangle
+*/
+// GbPolygon3D *createClippedPolygon3D(double p1x1, double p1x2, double p1x3, double p2x1, double p2x2, double p2x3)
+// {
+//return(GbSystem::clipPolygon3D(this.getPoints(), p1x1, p1x2, p1x3, p2x1, p2x2. p2x3));
+// }
+
+/*
+* Returns true if the specified 3D rectangle lies completely within this 3D polygon.
+* @param rectangle the 3D rectangle to check
+* @return true if the specified 3D rectangle lies completely within this 3D polygon
+*/
+//public boolean enclosesRectangle3D(GbRectangle3D rectangle)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), rectangle.getArea()));
+//}
+/*
+* Returns true if the specified 3D rectangle lies completely within this 3D polygon.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 3D rectangle lies completely within this 3D polygon
+*/
+//public boolean enclosesRectangle3D(GbPoint3D p1, GbPoint3D p2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+//}
+/*
+* Returns true if the specified 3D rectangle lies completely within this 3D polygon.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 3D rectangle lies completely within this 3D polygon
+*/
+//public boolean enclosesRectangle3D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+//}
+
+/*
+* Returns true if the specified 3D rectangle is crossed by this 3D polygon.
+* @param rectangle the 3D rectangle to check
+* @return true if the specified 3D rectangle is crossed by this 3D polygon
+*/
+//public boolean crossesRectangle3D(GbRectangle3D rectangle)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, rectangle.getArea()));
+//}
+/*
+* Returns true if the specified 3D rectangle is crossed by this 3D polygon.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 3D rectangle is crossed by this 3D polygon
+*/
+//public boolean crossesRectangle3D(GbPoint3D p1, GbPoint3D p2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+//}
+/*
+* Returns true if the specified 3D rectangle is crossed by this 3D polygon.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 3D rectangle is crossed by this 3D polygon
+*/
+//public boolean crossesRectangle3D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+//}
+
+/*
+* Returns true if the specified 3D rectangle lies (at least partly) within this 3D polygon.
+* @param rectangle the 3D rectangle to check
+* @return true if the specified 3D rectangle lies (at least partly) within this 3D polygon
+*/
+//public boolean enclosesOrCrossesRectangle3D(GbRectangle3D rectangle)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*
+* Returns true if the specified 3D rectangle lies (at least partly) within this 3D polygon.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 3D rectangle lies (at least partly) within this 3D polygon
+*/
+//public boolean enclosesOrCrossesRectangle3D(GbPoint3D p1, GbPoint3D p2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*
+* Returns true if the specified 3D rectangle lies (at least partly) within this 3D polygon.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 3D rectangle lies (at least partly) within this 3D polygon
+*/
+//public boolean enclosesOrCrossesRectangle3D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon3D p = GbSystem.clipPolygon3D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*======================================================================*/
+
+void GbPolygon3D::calculateValues()
+{
+   this->x1s        = 0.0;
+   this->x2s        = 0.0;
+   this->x3s        = 0.0;
+   this->x1min      = 0.0;
+   this->x1max      = 0.0;
+   this->x2min      = 0.0;
+   this->x2max      = 0.0;
+   this->x3min      = 0.0;
+   this->x3max      = 0.0;
+   throw UbException(UB_EXARGS,"should be implemented");
+
+   //this->consistent = true;
+
+   //this->points = this->ps->getPoints();
+
+   //int       n     = (int)this->points.size();
+   //if(n < 1) return;
+
+   //GbPoint3D p1 = (this->points)[0];
+   //GbPoint3D p2 = NULL;
+   //double    h1 = 0.0;
+   //double    h2 = 0.0;
+   //double    f=0.0;
+
+   //this->x1s   = p1.x1;
+   //this->x1min = p1.x1;
+   //this->x1max = p1.x1;
+   //this->x2s   = p1.x2;
+   //this->x2min = p1.x2;
+   //this->x2max = p1.x2;
+   //this->x3s   = p1.x2;
+   //this->x3min = p1.x2;
+   //this->x3max = p1.x2;
+
+   //std::cout<<"Should be implemented "<<endl;
+
+   //for(int i=1; i<n; i++)
+   //{
+   //  p2         = (this->points)[i];
+   //  f          = p1.x1*p2.x2 - p1.x2*p2.x1;
+   //  this->area += f;
+   //  h1        += f*(p1.x2 + p2.x2);
+   //  h2        += f*(p1.x1 + p2.x1);
+   //  p1         = p2;
+
+   //  if(p1.x1 < this->x1min) this->x1min = p1.x1;
+   //  if(p1.x1 > this->x1max) this->x1max = p1.x1;
+   //  if(p1.x2 < this->x2min) this->x2min = p1.x2;
+   //  if(p1.x2 > this->x2max) this->x2max = p1.x2;
+   //}
+   //p2         = (this->points)[0];
+   //f          = p1.x1*p2.x2 - p1.x2*p2.x1;
+   //this->area += f;
+   //h1        += f*(p1.x2 + p2.x2);
+   //h2        += f*(p1.x1 + p2.x1);
+
+   //this->area *= 0.5;
+   //h1        /= 6.0;
+   //h2        /= 6.0;
+
+   //if(n > 2)
+   //{
+   //   this->x1s = h2/this->area;
+   //   this->x2s = h1/this->area;
+   //}
+
+   //if(n < 3 || !GbSystem::inClosedInterval(this->x1s, this->x1min, this->x1max)) this->x1s = 0.5*(this->x1min+this->x1max);
+   //if(n < 3 || !GbSystem::inClosedInterval(this->x2s, this->x2min, this->x2max)) this->x2s = 0.5*(this->x2min+this->x2max);
+}
+/*======================================================================*/
+
+
+/*======================================================================*/
+// private class PointObserver implements TiObserver
+// {
+//    GbPolygon3D polygon = null;
+
+//    PointObserver(GbPolygon3D polygon)
+//    {
+//this.polygon = polygon;
+//    }
+
+//    public void objectChanged(Object object)
+//    {
+//if((object instanceof GbPoint3D) && this.polygon.contains((GbPoint3D)object)>0)
+//{
+//   this.polygon.consistent = false;
+//   this.polygon.notifyObservers();
+//}
+//    }
+// }
+/*=======================================================*/
+void GbPolygon3D::write(UbFileOutput* out) 
+{                                      
+   throw UbException(UB_EXARGS,"not implemented");
+}
+/*=======================================================*/
+void GbPolygon3D::read(UbFileInput* in) 
+{  
+   throw UbException(UB_EXARGS,"not implemented");
+}
+/*=======================================================*/
+
diff --git a/source/VirtualFluidsCore/Geometry/GbPolygon3D.h b/source/VirtualFluidsCore/Geometry/GbPolygon3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..da383fb05530409a9626ae1a39062f9636d9951a
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbPolygon3D.h
@@ -0,0 +1,536 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBPOLYGON3D_H
+#define GBPOLYGON3D_H
+
+#include <sstream>
+#include <iostream>
+
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbPolygon3D;
+typedef VFSharedPtr<GbPolygon3D> GbPolygon3DPtr;
+
+
+class GbObject3DCreator;
+
+/*=========================================================================*/
+/* GbPolygon2D                                                             */
+/*                                                                         */
+/*
+* This Class provides basic 3D polygon objects.
+*/
+class GbPolygon3D : public GbObject3D
+{
+public:
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+private:
+   /*======================================================================*/
+   double            x1s  ;
+   double            x2s  ;
+   double            x3s  ;
+   double            x1min;
+   double            x1max;
+   double            x2min;
+   double            x2max;
+   double            x3min;
+   double            x3max;
+
+   std::vector<GbPoint3D> points;
+   bool                   consistent;
+
+   GbSystem3D::PointSet3 *ps;
+   //private PointObserver     po         = null;
+
+   void init();
+
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   /*  Konstruktoren                                                       */
+   /*                                                                      */
+   /*
+   * Creates an empty 2D polygon.
+   */
+public:
+   static int counter;
+   GbPolygon3D();
+   /*
+   * Creates an empty 2D polygon with the specified capacity.
+   * @param capacity the initial capacity
+   */
+   GbPolygon3D(int capacity);
+   /*
+   * Creates a 2D polygon with the specified points.
+   * @param points the initial points of the polygon
+   */
+   GbPolygon3D(std::vector<GbPoint3D> &points);
+   /*
+   * Creates a 2D polygon as clone of the specified 2D polygon.
+   * @param polygon the 2D polygon to be cloned
+   */
+   GbPolygon3D(GbPolygon3D *polygon);
+
+   ~GbPolygon3D();
+
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   /*  Methoden                                                            */
+   /*                                                                      */
+   /*
+   * Creates a 2D polygon as clone of this 2D polygon.
+   */
+   GbPolygon3D* clone() {   return(new GbPolygon3D(this)); }
+   void finalize()
+   {
+      throw UbException(UB_EXARGS,"toDo");
+   }
+
+   /*
+   * Returns the number of points.
+   * @return the number of points
+   */
+   int size();
+   /*
+   * Returns the number of times this 2D polygon contains the specified point.
+   * @param point the point
+   * @return the number of times this 2D polygon contains the specified point
+   */
+   int contains(GbPoint3D *point);
+   /*
+   * Returns the number of times this 2D polygon contains a point equal to the specified point.
+   * @param point the point
+   * @return the number of times this 2D polygon contains a point equal to the specified point
+   */
+   int containsEqual(GbPoint3D* point);
+   /*
+   * Returns true, if this 2D polygon contains the specified line.
+   * @param point1 the first point
+   * @param point2 the second point
+   * @return true, if this 2D polygon contains the specified line
+   */
+   bool containsLine(GbPoint3D* point1, GbPoint3D* point2);
+   /*
+   * Returns true, if this 2D polygon contains the specified line.
+   * @param line the line
+   * @return true, if this 2D polygon contains the specified line
+   */
+   bool containsLine(GbLine3D* line);
+   /*
+   * Returns the first point.
+   * @return the first point
+   */
+   GbPoint3D* getFirstPoint();
+   /*
+   * Returns the last point.
+   * @return the last point
+   */
+   GbPoint3D* getLastPoint();
+   /*
+   * Returns the specified point.
+   * @param index the index
+   * @return the specified point
+   * @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+   */
+   GbPoint3D* getPoint(const int& index);
+   /*
+   * Returns the points.
+   * @return the points
+   */
+   std::vector<GbPoint3D> getPoints();
+   /*
+   * Returns the points within the specified rectangle.
+   * @param rectangle the 2D rectangle
+   * @return the points within the specified rectangle
+   */
+   //public GbPoint2D[] getPoints(GbRectangle2D rectangle)
+   //{
+   //   return(this.getPoints(rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2));
+   //}
+   /*
+   * Returns the points within the specified rectangle.
+   * @param p1 the 1st point of the rectangle
+   * @param p2 the 2nd point of the rectangle
+   * @return the points within the specified rectangle
+   */
+   std::vector<GbPoint3D> getPoints(GbPoint3D* p1, GbPoint3D* p2);
+   /*
+   * Returns the points within the specified rectangle.
+   * @param p1x1 the 1st x1 coordinate of the rectangle
+   * @param p1x2 the 1st x2 coordinate of the rectangle
+   * @param p2x1 the 2nd x1 coordinate of the rectangle
+   * @param p2x2 the 2nd x2 coordinate of the rectangle
+   * @return the points within the specified rectangle
+   */
+   std::vector<GbPoint3D> getPoints(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3);
+   /*
+   * Returns the area of this polygon.
+   * The area is positive for positive ordered points, otherwise negative.
+   * @return the area of this polygon
+   */
+   //double getArea()
+   //{
+   //   if(!this.consistent) this.calculateValues();
+   //   return(this.area);
+   //}
+   double getX1Centroid();
+   double getX1Minimum();
+   double getX1Maximum();
+   double getX2Centroid();
+   double getX2Minimum();
+   double getX2Maximum();
+   double getX3Centroid();
+   double getX3Minimum();
+   double getX3Maximum();
+
+   /*
+   * Adds a point to the end of this polygon. Notifies the observers of this 2D polygon.
+   * @param point the point
+   */
+   void addPoint(GbPoint3D* point);
+   /*
+   * Adds a number of points to the end of this polygon. Notifies the observers of this 2D polygon.
+   * @param points the points
+   */
+   void addPoints(std::vector<GbPoint3D>& points);
+   /*
+   * Inserts a point at the specified position within this polygon. Notifies the observers of this 2D polygon.
+   * @param point the point
+   * @param index the index
+   * @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+   */
+   //public void insertPoint(GbPoint2D point, int index) throws ArrayIndexOutOfBoundsException
+   //{
+   //   if((this instanceof GbPolygon3D) && !(point instanceof GbPoint3D)) throw new IllegalArgumentException("GbPolygon2D.insertPoint(): points of 3D polygons have to be 3D points!");
+   //   if(index < 0 || index > this.ps.size()) throw new ArrayIndexOutOfBoundsException("GbPolygon2D.insert(): invalid index specified: "+index);
+
+   //   this.ps.insert(point, index);
+   //   point.addObserver(this.po);
+   //   this.consistent = false;
+   //   super.notifyObservers();
+   //}
+   /*
+   * Removes all points from this polygon identical to the specified one. Notifies the observers of this 2D polygon.
+   * @param point the point
+   */
+   //public void deletePoint(GbPoint2D point)
+   //{
+   //   this.ps.delete(point);
+   //   point.removeObserver(this.po);
+   //   this.consistent = false;
+   //   super.notifyObservers();
+   //}
+   /*
+   * Removes all points from this polygon equal to the specified one. Notifies the observers of this 2D polygon.
+   * @param point the point
+   */
+   //public void deleteEqualPoint(GbPoint2D point)
+   //{
+   //   this.ps.deleteEqual(point);
+   //   point.removeObserver(this.po);
+   //   this.consistent = false;
+   //   super.notifyObservers();
+   //}
+   /*
+   * Removes all points from this polygon. Notifies the observers of this 2D polygon.
+   */
+   void clear();
+
+   /*
+   * Returns true if this 2D polygon equals the specified object.
+   * Two polygon are equal, if their points are equal.
+   * <BR>Note that the order of points is recognized!
+   * @return true if this 2D polygon equals the specified object
+   * @see GbPoint2D#equals(java.lang.Object)
+   * @see GbPoint3D#equals(java.lang.Object)
+   */
+   // bool equals(Object object)
+   // {
+   //    try
+   //    {
+   //	GbPolygon2D polygon = (GbPolygon2D) object;
+   //int         n       = this.size();
+
+   //if(n != polygon.size()) return(false);
+   //for(int i=0; i<n; i++) if(!this.getPoint(i).equals(polygon.getPoint(i))) return(false);
+   //return(true);
+   //    }
+   //    catch(Exception e){ return(false); }
+   // }
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet()
+   {
+      std::cout<<"GbPolygon3D::getSurfaceTriangleSet() - not implemented\n";
+      std::vector<GbTriangle3D*> tmp;
+      return tmp;
+   }
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+   {
+      throw UbException(__FILE__, __LINE__, "GbPolygon3D::isPointInObject3D- not implemented");
+   }
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+   {
+      throw UbException(__FILE__, __LINE__, "GbPolygon3D::isPointInObject3D- not implemented");
+   }
+   bool isCellInsideGbObject3D(double x11,double x21,double x31,double x12,double x22,double x32) { return false; }
+
+   GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D &point2)
+   {
+      throw UbException(__FILE__, __LINE__, "GbPolygon3D::createClippedLine3D - not implemented");
+   }                        
+/*
+   * Returns a string representation of this 2D polygon.
+   * @return a string representation of this 2D polygon
+   */
+   std::string toString();
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   /*  Calculation                                                         */
+   /*                                                                      */
+   /*
+   * Returns the intersection points of this 2D polygon and the specified 2D line.
+   * @param line the 2D line to intersect
+   * @return the intersection points of this 2D polygon and the specified 2D line
+   */
+   // public GbPoint2D[] calculateIntersectionPoints2D(GbLine2D line)
+   // {
+   //    GbSystem.PointSet pointSet = new GbSystem.PointSet(0);
+   //    GbPoint2D         points[] = this.getPoints();
+   //    GbPoint2D         pCrossed = null;
+   //    int               n        = points.length;
+   //    if(n < 2)         return(pointSet.getPoints());
+
+   //    for(int i=1; i<n; i++)
+   //    {
+   //pCrossed = GbSystem.calculateIntersectionPoint2D(points[i-1], points[i], line.p1, line.p2);
+   //if(pCrossed != null) pointSet.add(pCrossed);
+   //    }
+   //    pCrossed = GbSystem.calculateIntersectionPoint2D(points[n-1], points[0], line.p1, line.p2);
+   //    if(pCrossed != null) pointSet.add(pCrossed);
+
+   //    return(pointSet.getPoints());
+   // }
+
+   /*
+   * Returns true if the specified 2D point lies within (or on the border of) this 2D polygon.
+   * @param point the 2D point to check
+   * @return true if the specified 2D point lies within (or on the border of) this 2D polygon
+   */
+   // public boolean enclosesPoint2D(GbPoint2D point)
+   // {
+   //    if(GbSystem.less(point.x1, this.x1min))    return(false);
+   //    if(GbSystem.less(point.x2, this.x2min))    return(false);
+   //    if(GbSystem.greater(point.x1, this.x1max)) return(false);
+   //    if(GbSystem.greater(point.x2, this.x2max)) return(false);
+   //    if(this.containsEqual(point) > 0)          return(true);
+
+   //    QbList    ltest    = new QbList(GbPoint2D.class, QbList.NOEQUALOBJECTS);
+   //    GbPoint2D points[] = this.getPoints();
+   //    GbPoint2D ptest;
+   //    int       n        = points.length;
+   //    if(n < 2) return(false);
+
+   //    if(GbSystem.equal(point.x2, this.x2min)) ptest = new GbPoint2D(point.x1, this.x2min-1.0);
+   //    else                                     ptest = new GbPoint2D(point.x1, this.x2max+1.0);
+
+   //    for(int i=1; i<n; i++)
+   //    {
+   //try { ltest.append(GbSystem.calculateIntersectionPoint2D(points[i-1], points[i], point, ptest)); }
+   //catch(Exception e){}
+   //    }
+   //    try { ltest.append(GbSystem.calculateIntersectionPoint2D(points[n-1], points[0], point, ptest)); }
+   //    catch(Exception e){}
+   //    return((ltest.size()%2)==1);
+   // }
+
+   /*
+   * Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+   * @param rectangle the 2D rectangle
+   * @return a new 2D polygon clipped by the specified 2D rectangle
+   */
+   // GbPolygon3D *createClippedPolygon3D(GbCuboid3D *cube)
+   // {
+   //return(GbSystem::clipPolygon3D(this->getPoints(), cube->p1->x1, cube->p1->x2, cube->p1->x3, , cube->p2->x1, cube->p2->x2, cube->p2->x3));
+   // };
+   /*
+   * Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+   * @param p1 the 1st point of the rectangle
+   * @param p2 the 2nd point of the rectangle
+   * @return a new 2D polygon clipped by the specified 2D rectangle
+   */
+   // GbPolygon3D *createClippedPolygon2D(GbPoint3D *p1, GbPoint3D *p2)
+   // {
+   //return(GbSystem::clipPolygon3D(this->getPoints(), p1->x1, p1->x2, p1->x3, p2->x1, p2->x2, p2->x3));
+   // };
+   /*
+   * Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+   * @param p1x1 the 1st x1 coordinate of the rectangle
+   * @param p1x2 the 1st x2 coordinate of the rectangle
+   * @param p2x1 the 2nd x1 coordinate of the rectangle
+   * @param p2x2 the 2nd x2 coordinate of the rectangle
+   * @return a new 2D polygon clipped by the specified 2D rectangle
+   */
+   // GbPolygon3D *createClippedPolygon3D(double p1x1, double p1x2, double p1x3, double p2x1, double p2x2, double p2x3)
+   // {
+   //return(GbSystem::clipPolygon3D(this.getPoints(), p1x1, p1x2, p1x3, p2x1, p2x2. p2x3));
+   // };
+
+   /*
+   * Returns true if the specified 2D rectangle lies completely within this 2D polygon.
+   * @param rectangle the 2D rectangle to check
+   * @return true if the specified 2D rectangle lies completely within this 2D polygon
+   */
+   //public boolean enclosesRectangle2D(GbRectangle2D rectangle)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+   //   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), rectangle.getArea()));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle lies completely within this 2D polygon.
+   * @param p1 the 1st point of the rectangle to check
+   * @param p2 the 2nd point of the rectangle to check
+   * @return true if the specified 2D rectangle lies completely within this 2D polygon
+   */
+   //public boolean enclosesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+   //   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle lies completely within this 2D polygon.
+   * @param p1x1 the 1st x1 coordinate of the rectangle to check
+   * @param p1x2 the 1st x2 coordinate of the rectangle to check
+   * @param p2x1 the 2nd x1 coordinate of the rectangle to check
+   * @param p2x2 the 2nd x2 coordinate of the rectangle to check
+   * @return true if the specified 2D rectangle lies completely within this 2D polygon
+   */
+   //public boolean enclosesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+   //   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+   //}
+
+   /*
+   * Returns true if the specified 2D rectangle is crossed by this 2D polygon.
+   * @param rectangle the 2D rectangle to check
+   * @return true if the specified 2D rectangle is crossed by this 2D polygon
+   */
+   //public boolean crossesRectangle2D(GbRectangle2D rectangle)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+   //   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, rectangle.getArea()));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle is crossed by this 2D polygon.
+   * @param p1 the 1st point of the rectangle to check
+   * @param p2 the 2nd point of the rectangle to check
+   * @return true if the specified 2D rectangle is crossed by this 2D polygon
+   */
+   //public boolean crossesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+   //   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle is crossed by this 2D polygon.
+   * @param p1x1 the 1st x1 coordinate of the rectangle to check
+   * @param p1x2 the 1st x2 coordinate of the rectangle to check
+   * @param p2x1 the 2nd x1 coordinate of the rectangle to check
+   * @param p2x2 the 2nd x2 coordinate of the rectangle to check
+   * @return true if the specified 2D rectangle is crossed by this 2D polygon
+   */
+   //public boolean crossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+   //   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+   //}
+
+   /*
+   * Returns true if the specified 2D rectangle lies (at least partly) within this 2D polygon.
+   * @param rectangle the 2D rectangle to check
+   * @return true if the specified 2D rectangle lies (at least partly) within this 2D polygon
+   */
+   //public boolean enclosesOrCrossesRectangle2D(GbRectangle2D rectangle)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+   //   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle lies (at least partly) within this 2D polygon.
+   * @param p1 the 1st point of the rectangle to check
+   * @param p2 the 2nd point of the rectangle to check
+   * @return true if the specified 2D rectangle lies (at least partly) within this 2D polygon
+   */
+   //public boolean enclosesOrCrossesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1.x1, p1.x2, p2.x1, p2.x2);
+   //   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+   //}
+   /*
+   * Returns true if the specified 2D rectangle lies (at least partly) within this 2D polygon.
+   * @param p1x1 the 1st x1 coordinate of the rectangle to check
+   * @param p1x2 the 1st x2 coordinate of the rectangle to check
+   * @param p2x1 the 2nd x1 coordinate of the rectangle to check
+   * @param p2x2 the 2nd x2 coordinate of the rectangle to check
+   * @return true if the specified 2D rectangle lies (at least partly) within this 2D polygon
+   */
+   //public boolean enclosesOrCrossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+   //{
+   //   GbPolygon2D p = GbSystem.clipPolygon2D(this.getPoints(), p1x1, p1x2, p2x1, p2x2);
+   //   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+   //}
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   /*  Private Methoden                                                    */
+   /*                                                                      */
+   void calculateValues();
+   /*======================================================================*/
+
+
+   /*======================================================================*/
+   // private class PointObserver implements TiObserver
+   // {
+   //    GbPolygon2D polygon = null;
+
+   //    PointObserver(GbPolygon2D polygon)
+   //    {
+   //this.polygon = polygon;
+   //    }
+
+   //    public void objectChanged(Object object)
+   //    {
+   //if((object instanceof GbPoint2D) && this.polygon.contains((GbPoint2D)object)>0)
+   //{
+   //   this.polygon.consistent = false;
+   //   this.polygon.notifyObservers();
+   //}
+   //    }
+   // }
+   /*======================================================================*/
+};
+/*=========================================================================*/
+#endif
+
+
+
+
+
+
diff --git a/source/VirtualFluidsCore/Geometry/GbSphere3D.cpp b/source/VirtualFluidsCore/Geometry/GbSphere3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..064cc0cff91d812162489a34149a870e8fc23b75
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbSphere3D.cpp
@@ -0,0 +1,911 @@
+#include <numerics/geometry3d/GbSphere3D.h>
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+
+#include <numerics/geometry3d/creator/GbSphere3DCreator.h>
+
+using namespace std;
+
+ObObjectCreator* GbSphere3D::getCreator()
+{
+   return GbSphere3DCreator::getInstance();
+}
+/*=====================================================*/
+GbSphere3D::GbSphere3D()
+  : GbObject3D(), UbObserver()
+{
+   this->setName("sphere");
+   radius=0;
+   midPoint=new GbPoint3D(0,0,0);
+}
+/*=====================================================*/
+GbSphere3D::GbSphere3D(const double& x1,const double& x2, const double& x3, const double& radius)
+  : GbObject3D(), UbObserver()
+{
+   this->setName("sphere");
+   midPoint = new GbPoint3D(x1,x2,x3);
+   midPoint->addObserver(this);
+
+   this->radius   = radius;
+   triangulationMode = RAYPROJECTION;
+   //triangulationMode = CUBOIDPROJECTION;
+}
+/*=====================================================*/
+GbSphere3D::GbSphere3D(const GbSphere3D& sphere)
+  : GbObject3D(), UbObserver()
+{
+   this->setName("sphere");
+
+   this->midPoint    = sphere.midPoint->clone();
+   this->radius      = sphere.radius;
+   triangulationMode = RAYPROJECTION;
+
+   this->midPoint->addObserver(this);
+}
+/*=====================================================*/
+GbSphere3D::GbSphere3D(GbSphere3D* sphere)
+   : GbObject3D(), UbObserver()
+{
+   this->setName(sphere->getName());
+   midPoint = sphere->midPoint->clone();
+   midPoint->addObserver(this);
+
+   this->radius   = sphere->getRadius();
+   triangulationMode = RAYPROJECTION;
+}
+/*=====================================================*/
+GbSphere3D::~GbSphere3D()
+{
+   if(this->midPoint) this->midPoint->removeObserver(this);
+}
+/*=====================================================*/
+void GbSphere3D::finalize()
+{
+   if(this->midPoint)
+   {
+      this->midPoint->removeObserver(this);
+      this->midPoint->finalize();
+      delete this->midPoint;
+      this->midPoint = NULL;
+   }
+
+   if(this->midPoint) this->midPoint->removeObserver(this);
+}
+/*=======================================================*/
+void GbSphere3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3)
+{
+   this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() );
+}
+/*=====================================================*/
+double GbSphere3D::getDistance(GbPoint3D* p)
+{
+   return this->getDistance(p->getX1Centroid(),p->getX2Coordinate(),p->getX3Coordinate());
+}
+/*=====================================================*/
+void GbSphere3D::setCenterX1Coordinate(const double& value)
+{
+   if(this->midPoint) this->midPoint->setX1(value);
+   else throw UbException(UB_EXARGS,"Sphere has no midPoint");
+   //kein notifyObserver(), da der knoten notifyObserver() ausfuehrt und die GbSphere dieses event
+   //abfaengt und dann selbst notifyObservers ausfuehrt ;-)
+}
+/*=====================================================*/
+void GbSphere3D::setCenterX2Coordinate(const double& value)
+{
+   if(this->midPoint) this->midPoint->setX2(value);
+   else  throw UbException(UB_EXARGS,"Sphere has no midPoint");
+   //kein notifyObserver(), da der knoten notifyObserver() ausfuehrt und die GbSphere dieses event
+   //abfaengt und dann selbst notifyObservers ausfuehrt ;-)
+}
+/*=====================================================*/
+void GbSphere3D::setCenterX3Coordinate(const double& value)
+{
+   if(this->midPoint) this->midPoint->setX3(value);
+   else  throw UbException(UB_EXARGS,"sphere has no midPoint");
+   //kein notifyObserver(), da der knoten notifyObserver() ausfuehrt und die GbSphere dieses event
+   //abfaengt und dann selbst notifyObservers ausfuehrt ;-)
+}
+/*=====================================================*/
+void GbSphere3D::setRadius(const double& radius)
+{
+   if (radius != this->radius)
+   {
+   this->radius=radius;
+   this->notifyObserversObjectChanged();
+}
+}
+/*=====================================================*/
+double GbSphere3D::getDistance(const double& x1p, const double& x2p, const double& x3p)
+{
+   double deltaX1 = x1p - midPoint->getX1Coordinate();
+   double deltaX2 = x2p - midPoint->getX2Coordinate();
+   double deltaX3 = x3p - midPoint->getX3Coordinate();
+   return sqrt(deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3)-this->radius;
+}
+/*=====================================================*/
+//true, wenn 'in Object' oder 'auf Boundary'!
+bool GbSphere3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   double deltaX1 = x1p - midPoint->getX1Coordinate();
+   double deltaX2 = x2p - midPoint->getX2Coordinate();
+   double deltaX3 = x3p - midPoint->getX3Coordinate();
+
+   return UbMath::lessEqual(deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3, this->radius*this->radius);
+}
+/*=====================================================*/
+//true, wenn 'in Object' oder 'auf Boundary'!
+bool GbSphere3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   double deltaX1 = x1p - midPoint->getX1Coordinate();
+   double deltaX2 = x2p - midPoint->getX2Coordinate();
+   double deltaX3 = x3p - midPoint->getX3Coordinate();
+
+   double distanceSquare = deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3;
+   double radiusSquare   = this->radius*this->radius;
+
+   pointIsOnBoundary = UbMath::equal(distanceSquare,radiusSquare);
+
+   return UbMath::lessEqual(distanceSquare,radiusSquare);
+}
+/*=====================================================*/
+//bool GbSphere3D::crossCellCrossSection(double x11,double x21,double x12,double x22, double ra)
+//{
+//   if(this->isPointInCrossection(x11, x12) || this->isPointInCrossection(x21, x22) || this->isPointInCrossection(x11, x22) || this->isPointInCrossection(x21, x12))
+//   {
+//		if(!this->isPointInCrossection(x11, x12) || !this->isPointInCrossection(x21, x22) || !this->isPointInCrossection(x11, x22) || !this->isPointInCrossection(x21, x12)) return true;
+//   }
+//   return false;
+//}
+//
+///*=====================================================*/
+//bool GbSphere3D::cellCrossAndInsideCrossSection(double x11,double x21,double x12,double x22, double ra)
+//{
+//   if(this->isPointInCrossection(x11, x12) || this->isPointInCrossection(x21, x22) || this->isPointInCrossection(x11, x22) || this->isPointInCrossection(x21, x12))  return true;
+//   return false;
+//}
+/*=====================================================*/
+string GbSphere3D::toString()
+{
+	stringstream ss;
+	ss<< "GbSphere3D[";
+	ss <<"mid="<<midPoint->toString()<<", r="<<radius<<"]";
+	return ss.str();
+}
+/*=====================================================*/
+GbLine3D* GbSphere3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   double factor = 100.0; //um rundungsfehler beim wurzelterm zu minimieren
+   double xa = factor*point1.getX1Coordinate();
+   double ya = factor*point1.getX2Coordinate();
+   double za = factor*point1.getX3Coordinate();
+   double xb = factor*point2.getX1Coordinate();
+   double yb = factor*point2.getX2Coordinate();
+   double zb = factor*point2.getX3Coordinate();
+   double xm = factor*this->midPoint->getX1Coordinate();
+   double ym = factor*this->midPoint->getX2Coordinate();
+   double zm = factor*this->midPoint->getX3Coordinate();
+   double r  = factor*this->radius;
+
+   double xa2 = xa*xa;
+   double ya2 = ya*ya;
+   double za2 = za*za;
+   double xb2 = xb*xb;
+   double yb2 = yb*yb;
+   double zb2 = zb*zb;
+   double xm2 = xm*xm;
+   double ym2 = ym*ym;
+   double zm2 = zm*zm;
+   double r2  = r*r;
+
+   double wurzel =   2.0*xa*xb*ym2-2.0*ya*yb*r2+2.0*ya*ym*xb2+2.0*yb*ym*za2
+                    +2.0*ya*ym*zb2+2.0*xb*xm*za2+2.0*za*zb*ym2+2.0*xb*xm*ya2+2.0*xa*xm*yb2
+                    +2.0*yb*ym*xa2+2.0*zb*zm*ya2+2.0*xa*xm*zb2+2.0*za*zm*xb2+2.0*za*zm*yb2
+                    +2.0*xa*xb*zm2-2.0*xa*xb*r2-2.0*za*zb*r2+2.0*za*zb*xm2-2.0*ya*yb*xa*xm
+                    +2.0*ya*yb*xa*xb+2.0*zb*zm*xa2-2.0*ya*yb*xb*xm+2.0*ya*yb*xm2-2.0*ya*yb*zb*zm
+                    +2.0*ya*yb*zm2+2.0*zb*zm*yb*ym-2.0*zb*zm*ya*ym+2.0*zb*zm*xb*xm-2.0*xa*xm*yb*ym
+                    +2.0*xa*xm*za*zm+2.0*xa*xm*ya*ym-2.0*yb*ym*za*zm+2.0*yb*ym*xb*xm+2.0*za*zm*ya*ym
+                    -2.0*za*zm*xb*xm-2.0*ya*ym*xb*xm+2.0*za*zb*xa*xb-2.0*za*zb*xa*xm-2.0*za*zb*xb*xm
+                    +2.0*za*zb*ya*yb-2.0*za*zb*ya*ym-2.0*za*zb*yb*ym-2.0*ya*yb*za*zm-xa2*zb2
+                    -xa2*yb2-zb2*ya2-za2*xb2-za2*yb2-xb2*ya2-2.0*zb*zm*xa*xm
+                    -2.0*xa*xb*za*zm-2.0*xa*xb*zb*zm-2.0*xa*xb*ya*ym-2.0*xa*xb*yb*ym+za2*r2
+                    -za2*xm2-za2*ym2+zb2*r2-zb2*xm2-zb2*ym2+xa2*r2-xa2*zm2
+                    -xa2*ym2+xb2*r2-xb2*zm2-xb2*ym2+ya2*r2-ya2*zm2-ya2*xm2
+                    +yb2*r2-yb2*zm2-yb2*xm2;
+   double nenner  = -2.0*za*zb-2.0*ya*yb-2.0*xa*xb+za2+zb2+xa2+xb2+ya2+yb2;
+   double zaehler =  2.0*zb*zm-2.0*xa*xm+2.0*yb*ym-2.0*za*zm+xa2-2.0*ya*ym
+                    +2.0*xb*xm-zb2+za2-xb2+ya2-yb2;
+
+   vector<GbPoint3D*> schnittpunkte;
+
+   if(fabs(nenner)>1.E-13 && UbMath::greaterEqual(wurzel,0.0))
+   {
+      double t1 = (zaehler+2.0*sqrt(wurzel))/nenner;
+      double t2 = (zaehler-2.0*sqrt(wurzel))/nenner;
+
+      if(UbMath::inClosedInterval(t1,-1.0,1.0))
+      {
+         double x = ( xa*(0.5-0.5*t1)+xb*(0.5+0.5*t1) )/factor;
+         double y = ( ya*(0.5-0.5*t1)+yb*(0.5+0.5*t1) )/factor;
+         double z = ( za*(0.5-0.5*t1)+zb*(0.5+0.5*t1) )/factor;
+
+         schnittpunkte.push_back(new GbPoint3D(x,y,z));
+      }
+      if(fabs(t2-t1)>1.E-13 && UbMath::inClosedInterval(t2,-1.0,1.0))
+      {
+         double x = ( xa*(0.5-0.5*t2)+xb*(0.5+0.5*t2) )/factor;
+         double y = ( ya*(0.5-0.5*t2)+yb*(0.5+0.5*t2) )/factor;
+         double z = ( za*(0.5-0.5*t2)+zb*(0.5+0.5*t2) )/factor;
+
+         schnittpunkte.push_back(new GbPoint3D(x,y,z));
+      }
+   }
+
+   int nofSchnittpunkte = (int)schnittpunkte.size();
+   if(nofSchnittpunkte==1)
+   {
+      if     (this->isPointInGbObject3D(&point1)) return new GbLine3D(schnittpunkte[0],new GbPoint3D(point1));
+      else if(this->isPointInGbObject3D(&point2)) return new GbLine3D(schnittpunkte[0],new GbPoint3D(point2));
+      else //line beruehrt kugel! -> clippedLine reduziert sich zu einem Punkt!
+      {
+         if(std::fabs(this->getDistance(schnittpunkte[0])-this->radius)<1.E-13)
+            throw UbException(UB_EXARGS,"Beide LinenPunkte ausserhalb des Kreises, der berechnete Punkt ist jedoch KEIN Beruhrungspunkt der Sphere...");
+         return new GbLine3D(schnittpunkte[0],new GbPoint3D(*(schnittpunkte[0])));
+      }
+   }
+   else if(nofSchnittpunkte==2) return new GbLine3D(schnittpunkte[0],schnittpunkte[1]);
+
+   return NULL;
+}
+/*=========================================================================*/
+vector<GbTriangle3D*> GbSphere3D::getSurfaceTriangleSet()
+{
+   if(triangulationMode==RAYPROJECTION)
+   {
+      double x1m = midPoint->getX1Coordinate();
+      double x2m = midPoint->getX2Coordinate();
+      double x3m = midPoint->getX3Coordinate();
+
+      vector<GbTriangle3D*> triangles;
+
+      int segments =30;
+      double deltaPhi = UbMath::PI/(double)segments;
+      double phiX1a,phiX1b,phiX3a,phiX3b;
+      double x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+
+      for(phiX3a=0.5*UbMath::PI; phiX3a>-1.5*UbMath::PI; phiX3a-=deltaPhi)
+      {
+         for(phiX1a=0.0; phiX1a<UbMath::PI; phiX1a+=deltaPhi)
+         {
+            phiX1b = phiX1a+deltaPhi;
+            phiX3b = phiX3a+deltaPhi;
+
+            x1a =  x1m+radius*cos(phiX3a)*std::cos(phiX1a);
+            x2a =  x2m+radius*cos(phiX3a)*std::sin(phiX1a);
+            x3a =  x3m+radius*sin(phiX3a);
+            x1b =  x1m+radius*cos(phiX3a)*std::cos(phiX1b);
+            x2b =  x2m+radius*cos(phiX3a)*std::sin(phiX1b);
+            x3b =  x3m+radius*sin(phiX3a);
+            x1c =  x1m+radius*cos(phiX3b)*std::cos(phiX1b);
+            x2c =  x2m+radius*cos(phiX3b)*std::sin(phiX1b);
+            x3c =  x3m+radius*sin(phiX3b);
+            x1d =  x1m+radius*cos(phiX3b)*std::cos(phiX1a);
+            x2d =  x2m+radius*cos(phiX3b)*std::sin(phiX1a);
+            x3d =  x3m+radius*sin(phiX3b);
+
+            if(UbMath::greater(phiX3b,-0.5*UbMath::PI)  && UbMath::less(phiX3a,0.5*UbMath::PI))
+            {
+               triangles.push_back(new GbTriangle3D(new GbPoint3D(x1a,x2a,x3a),new GbPoint3D(x1b,x2b,x3b),new GbPoint3D(x1c,x2c,x3c)));
+               triangles.push_back(new GbTriangle3D(new GbPoint3D(x1a,x2a,x3a),new GbPoint3D(x1c,x2c,x3c),new GbPoint3D(x1d,x2d,x3d)));
+            }
+            else
+            {
+               triangles.push_back(new GbTriangle3D(new GbPoint3D(x1d,x2d,x3d),new GbPoint3D(x1c,x2c,x3c),new GbPoint3D(x1a,x2a,x3a)));
+               triangles.push_back(new GbTriangle3D(new GbPoint3D(x1c,x2c,x3c),new GbPoint3D(x1b,x2b,x3b),new GbPoint3D(x1a,x2a,x3a)));
+            }
+         }
+      }
+      return triangles;
+   }
+   else if(triangulationMode==CUBOIDPROJECTION)
+   {
+      vector<GbTriangle3D*> triangles;
+      vector<GbPoint3D*>   points;
+      double x1min = this->getX1Minimum();
+      double x2min = this->getX2Minimum();
+      double x3min = this->getX3Minimum();
+      double x1max = this->getX1Maximum();
+      double x2max = this->getX2Maximum();
+      double x3max = this->getX3Maximum();
+      double ax1 = x1min;    double bx2 = x2min;   double cx1 = x1min;
+      double ax2 = x2min;    double bx3 = x3min;   double cx3 = x3min;
+
+      int anzahl = 20;
+      double dx1 = (x1max-x1min)/(double)(anzahl-1);
+      double dx2 = (x2max-x2min)/(double)(anzahl-1);
+      double dx3 = (x3max-x3min)/(double)(anzahl-1);
+
+      for (int u=0; u<anzahl; u++)
+      {
+         ax2 = x2min;
+         bx2 = x2min;
+         cx3 = x3min;
+         for (int v=0; v<anzahl; v++)
+         {
+            GbPoint3D p1 = GbPoint3D(ax1, ax2, x3max);
+            GbPoint3D p2 = GbPoint3D(ax1, ax2, x3min);
+            GbPoint3D p3 = GbPoint3D(cx1, x2min, cx3);
+            GbPoint3D p4 = GbPoint3D(cx1, x2max, cx3);
+            GbPoint3D p5 = GbPoint3D(x1min, bx2, bx3);
+            GbPoint3D p6 = GbPoint3D(x1max, bx2, bx3);
+
+            GbLine3D* clippedline1 = this->createClippedLine3D(*this->midPoint, p1);
+            GbLine3D* clippedline2 = this->createClippedLine3D(*this->midPoint, p2);
+            GbLine3D* clippedline3 = this->createClippedLine3D(*this->midPoint, p3);
+            GbLine3D* clippedline4 = this->createClippedLine3D(*this->midPoint, p4);
+            GbLine3D* clippedline5 = this->createClippedLine3D(*this->midPoint, p5);
+            GbLine3D* clippedline6 = this->createClippedLine3D(*this->midPoint, p6);
+            points.push_back(new GbPoint3D(clippedline1->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline2->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline3->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline4->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline5->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline6->getPoint1()));
+            clippedline1->deletePoints();    delete clippedline1;
+            clippedline2->deletePoints();    delete clippedline2;
+            clippedline3->deletePoints();    delete clippedline3;
+            clippedline4->deletePoints();    delete clippedline4;
+            clippedline5->deletePoints();    delete clippedline5;
+            clippedline6->deletePoints();    delete clippedline6;
+            ax2 +=dx2;
+            cx3 +=dx3;
+            bx2 +=dx2;
+         }
+         ax1 +=dx1;
+         cx1 +=dx1;
+         bx3 +=dx3;
+      }
+
+      int anz = anzahl*anzahl*6;
+      GbPoint3D* point1 = NULL;
+      GbPoint3D* point2 = NULL;
+      GbPoint3D* point3 = NULL;
+      int anzahl2 = anzahl*6;
+      int anzahl3 = anzahl2+6;
+      for (int u=0; u<anz-anzahl3; u++)
+      {
+         point1 = new GbPoint3D(points[u+6]);
+         point2 = new GbPoint3D(points[u]);
+         point3 = new GbPoint3D(points[u+anzahl2]);
+         if(u%2 == 0) triangles.push_back(new GbTriangle3D(point1, point2, point3));
+         else         triangles.push_back(new GbTriangle3D(point2, point1, point3));
+
+         point1 = new GbPoint3D(points[u+6]);
+         point2 = new GbPoint3D(points[u+anzahl2]);
+         point3 = new GbPoint3D(points[u+anzahl3]);
+         if(u%2 == 0) triangles.push_back(new GbTriangle3D(point1, point2, point3));
+         else         triangles.push_back(new GbTriangle3D(point2, point1, point3));
+      }
+      for (int u=0; u<anz; u++) delete points[u];
+
+      return triangles;
+   }
+   else throw UbException(UB_EXARGS,"undefined triangulationmode");
+}
+/*=======================================================*/
+void GbSphere3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+   //wenn ich viele Kugeln bei der PE rausschreibe sollten die vektoren nicht geresized werden
+   //nodes.resize(0);
+   //triangles.resize(0);
+
+   if(triangulationMode==RAYPROJECTION)
+   {
+      float x1m = (float)midPoint->getX1Coordinate();
+      float x2m = (float)midPoint->getX2Coordinate();
+      float x3m = (float)midPoint->getX3Coordinate();
+
+      int segments =30;
+      float deltaPhi = (float)UbMath::PI/(float)segments;
+      float phiX1a,phiX1b,phiX3a,phiX3b;
+      float x1a,x2a,x3a,x1b,x2b,x3b,x1c,x2c,x3c,x1d,x2d,x3d;
+      int nodeNr = 0;
+      for(phiX3a=(float)(0.5*UbMath::PI); phiX3a > (float)(-1.5*UbMath::PI); phiX3a-=deltaPhi)
+      {
+         for(phiX1a=0.0; phiX1a<UbMath::PI; phiX1a+=deltaPhi)
+         {
+            phiX1b = phiX1a+deltaPhi;
+            phiX3b = phiX3a+deltaPhi;
+
+            x1a =  x1m+(float)(radius*cos(phiX3a)*std::cos(phiX1a));
+            x2a =  x2m+(float)(radius*cos(phiX3a)*std::sin(phiX1a));
+            x3a =  x3m+(float)(radius*sin(phiX3a));
+            x1b =  x1m+(float)(radius*cos(phiX3a)*std::cos(phiX1b));
+            x2b =  x2m+(float)(radius*cos(phiX3a)*std::sin(phiX1b));
+            x3b =  x3m+(float)(radius*sin(phiX3a));
+            x1c =  x1m+(float)(radius*cos(phiX3b)*std::cos(phiX1b));
+            x2c =  x2m+(float)(radius*cos(phiX3b)*std::sin(phiX1b));
+            x3c =  x3m+(float)(radius*sin(phiX3b));
+            x1d =  x1m+(float)(radius*cos(phiX3b)*std::cos(phiX1a));
+            x2d =  x2m+(float)(radius*cos(phiX3b)*std::sin(phiX1a));
+            x3d =  x3m+(float)(radius*sin(phiX3b));
+
+            if(UbMath::greater(phiX3b,-0.5*UbMath::PI) && UbMath::less(phiX3a,0.5*UbMath::PI))
+            {
+               nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+               nodes.push_back( makeUbTuple(x1b,x2b,x3b) );
+               nodes.push_back( makeUbTuple(x1c,x2c,x3c) );
+
+               nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+               nodes.push_back( makeUbTuple(x1c,x2c,x3c) );
+               nodes.push_back( makeUbTuple(x1d,x2d,x3d) );
+            }
+            else
+            {
+               nodes.push_back( makeUbTuple(x1d,x2d,x3d) );
+               nodes.push_back( makeUbTuple(x1c,x2c,x3c) );
+               nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+
+               nodes.push_back( makeUbTuple(x1c,x2c,x3c) );
+               nodes.push_back( makeUbTuple(x1b,x2b,x3b) );
+               nodes.push_back( makeUbTuple(x1a,x2a,x3a) );
+            }
+            triangles.push_back( makeUbTuple(nodeNr, nodeNr+1, nodeNr+2) );
+            triangles.push_back( makeUbTuple(nodeNr+3, nodeNr+4, nodeNr+5) );
+            nodeNr+=6;
+         }
+      }
+   }
+   else if(triangulationMode==CUBOIDPROJECTION)
+   {
+      vector<GbPoint3D*>   points;
+      double x1min = this->getX1Minimum();
+      double x2min = this->getX2Minimum();
+      double x3min = this->getX3Minimum();
+      double x1max = this->getX1Maximum();
+      double x2max = this->getX2Maximum();
+      double x3max = this->getX3Maximum();
+      double ax1 = x1min;    double bx2 = x2min;   double cx1 = x1min;
+      double ax2 = x2min;    double bx3 = x3min;   double cx3 = x3min;
+
+      int anzahl = 20;
+      double dx1 = (x1max-x1min)/(double)(anzahl-1);
+      double dx2 = (x2max-x2min)/(double)(anzahl-1);
+      double dx3 = (x3max-x3min)/(double)(anzahl-1);
+
+      for (int u=0; u<anzahl; u++)
+      {
+         ax2 = x2min;
+         bx2 = x2min;
+         cx3 = x3min;
+         for (int v=0; v<anzahl; v++)
+         {
+            GbPoint3D p1 = GbPoint3D(ax1, ax2, x3max);
+            GbPoint3D p2 = GbPoint3D(ax1, ax2, x3min);
+            GbPoint3D p3 = GbPoint3D(cx1, x2min, cx3);
+            GbPoint3D p4 = GbPoint3D(cx1, x2max, cx3);
+            GbPoint3D p5 = GbPoint3D(x1min, bx2, bx3);
+            GbPoint3D p6 = GbPoint3D(x1max, bx2, bx3);
+
+            GbLine3D* clippedline1 = this->createClippedLine3D(*this->midPoint, p1);
+            GbLine3D* clippedline2 = this->createClippedLine3D(*this->midPoint, p2);
+            GbLine3D* clippedline3 = this->createClippedLine3D(*this->midPoint, p3);
+            GbLine3D* clippedline4 = this->createClippedLine3D(*this->midPoint, p4);
+            GbLine3D* clippedline5 = this->createClippedLine3D(*this->midPoint, p5);
+            GbLine3D* clippedline6 = this->createClippedLine3D(*this->midPoint, p6);
+            points.push_back(new GbPoint3D(clippedline1->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline2->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline3->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline4->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline5->getPoint1()));
+            points.push_back(new GbPoint3D(clippedline6->getPoint1()));
+            clippedline1->deletePoints();    delete clippedline1;
+            clippedline2->deletePoints();    delete clippedline2;
+            clippedline3->deletePoints();    delete clippedline3;
+            clippedline4->deletePoints();    delete clippedline4;
+            clippedline5->deletePoints();    delete clippedline5;
+            clippedline6->deletePoints();    delete clippedline6;
+            ax2 +=dx2;
+            cx3 +=dx3;
+            bx2 +=dx2;
+         }
+         ax1 +=dx1;
+         cx1 +=dx1;
+         bx3 +=dx3;
+      }
+
+      int anz = anzahl*anzahl*6;
+      int anzahl2 = anzahl*6;
+      int anzahl3 = anzahl2+6;
+      int nodeNr = 0;
+      for (int u=0; u<anz-anzahl3; u++)
+      {
+         nodes.push_back( makeUbTuple((float)points[u+6]->x1      , (float)points[u+6]->x2      , (float)points[u+6]->x3) );
+         nodes.push_back( makeUbTuple((float)points[u]->x1        , (float)points[u]->x2        , (float)points[u]->x3) );
+         nodes.push_back( makeUbTuple((float)points[u+anzahl2]->x1, (float)points[u+anzahl2]->x2, (float)points[u+anzahl2]->x3) );
+
+         if(u%2 == 0) triangles.push_back( makeUbTuple(nodeNr  , nodeNr+1, nodeNr+2) );
+         else         triangles.push_back( makeUbTuple(nodeNr  , nodeNr+1, nodeNr+2) );
+
+         nodes.push_back( makeUbTuple((float)points[u+6]->x1      , (float)points[u+6]->x2      , (float)points[u+6]->x3) );
+         nodes.push_back( makeUbTuple((float)points[u+anzahl2]->x1, (float)points[u+anzahl2]->x2, (float)points[u+anzahl2]->x3) );
+         nodes.push_back( makeUbTuple((float)points[u+anzahl3]->x1, (float)points[u+anzahl3]->x2, (float)points[u+anzahl3]->x3) );
+         if(u%2 == 0) triangles.push_back( makeUbTuple(nodeNr+3, nodeNr+4, nodeNr+5) );
+         else         triangles.push_back( makeUbTuple(nodeNr+3, nodeNr+4, nodeNr+5) );
+
+         nodeNr+=6;
+      }
+      for(int u=0; u<anz; u++) delete points[u];
+   }
+   else throw UbException(UB_EXARGS,"undefined triangulationmode");
+}
+/*=======================================================*/
+void GbSphere3D::transform(const double matrix[4][4])
+{
+   midPoint->transform(matrix);
+   this->setRadius(this->getRadius()*matrix[0][0]);
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbSphere3D::write(UbFileOutput* out)
+{
+   out->writeString(this->getCreator()->getTypeID());
+   midPoint->write(out);
+   out->writeDouble(radius);
+   out->writeInteger((int)triangulationMode);
+}
+/*=======================================================*/
+void GbSphere3D::read(UbFileInput* in)
+{
+   if(midPoint)
+   {
+      midPoint->removeObserver(this);
+      midPoint->finalize();
+      delete midPoint;
+   }
+   midPoint = new GbPoint3D;
+   in->readString();
+   midPoint->read(in);
+   midPoint->addObserver(this);
+   radius = in->readDouble();
+   triangulationMode = (TRIANGULATIONMODE)in->readInteger();
+}
+/*=======================================================*/
+bool GbSphere3D::hasIntersectionWithDirectedLine(GbPoint3D origin, GbPoint3D direction)
+{
+	GbVector3D vecOrigin(origin.getX1Coordinate(),origin.getX2Coordinate(), origin.getX3Coordinate()) ;
+	GbVector3D vecDirection(direction.getX1Coordinate(),direction.getX2Coordinate(), direction.getX3Coordinate());
+	GbVector3D vecSfereCenter(getX1Centroid(), getX2Centroid(), getX3Centroid());
+	GbVector3D diff = vecOrigin - vecSfereCenter;
+   float a = (float)(vecDirection.Dot(vecDirection));
+   float b = (float)(2.0 * vecDirection.Dot(diff));
+   float c = (float)(diff.Dot(diff) - this->getRadius()*this->getRadius());
+
+	// use 'abc'-formula for finding root t_1,2 = (-b +/- sqrt(b^2-4ac))/(2a)
+	float inRoot = (float)(b*b - 4.0*a*c);
+	if (inRoot < 0) return false;
+	float root = sqrt(inRoot);
+
+	float dist = (float)((-b - root)/(2.0*a));
+
+	double infinity = DBL_MAX;
+	double eps = 1E-4;
+
+   if (dist > infinity)
+		return false;
+
+	if (dist < eps)
+	{
+		dist = (float)((-b + root)/(2.0*a));
+		if (dist < eps || dist > infinity)
+			return false;
+	}
+	return true;
+}
+/*=======================================================*/
+bool GbSphere3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der SphereUmrandung
+//returns true:
+//  - cell cuts  sphere3D
+//  - cell boxes sphere3D
+//returns false:
+//  - cell completely inside sphere3D ( = sphere3D boxes cell)
+//  - cell und sphere3D haben kein gemeinsames Volumen
+{
+   double midX[] = {  this->getX1Centroid()
+                    , this->getX2Centroid()
+                    , this->getX3Centroid() };
+
+   double Bmin[] = {  UbMath::min(x1a, x1b)
+                    , UbMath::min(x2a, x2b)
+                    , UbMath::min(x3a, x3b) };
+
+   double Bmax[] = {  UbMath::max(x1a, x1b)
+                    , UbMath::max(x2a, x2b)
+                    , UbMath::max(x3a, x3b) };
+
+   /* Solid Box - Hollow Sphere */
+   double dmin = 0.0;
+   double dmax = 0.0;
+   double r2   = radius*radius;
+
+   for( int i=0; i<3; i++ )
+   {
+      double a = pow( midX[i] - Bmin[i], 2.0 );
+      double b = pow( midX[i] - Bmax[i], 2.0 );
+      dmax += UbMath::max( a, b );
+      if     ( UbMath::less   ( midX[i], Bmin[i] ) ) dmin += a;
+      else if( UbMath::greater( midX[i], Bmax[i] ) ) dmin += b;
+   }
+   if(   UbMath::lessEqual(dmin, r2   )
+      && UbMath::lessEqual(r2  , dmax ) )
+   {
+      return true;
+   }
+   return false;
+}
+/*=======================================================*/
+bool GbSphere3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//returns true:
+//  - cell completely inside sphere3D ( = sphere3D boxes cell)
+//  - cell cuts  sphere3D
+//  - cell boxes sphere3D
+//returns false:
+//  - cell und sphere3D haben kein gemeinsames Volumen
+{
+   //URL: http://tog.acm.org/GraphicsGems/gems/BoxSphere.c (mode=4, beides solids!!!)
+   // solid - solid
+   //this routine tests for intersection between an 3-dimensional
+   //axis-aligned box and an 3-dimensional sphere.
+
+   //true:
+   //  - wenn Schnitt
+   //  - Cell komplett innerhalb GbSphere3D
+   //  - Cell umhuellt GbSphere3D
+
+
+   double midX1 = this->getX1Centroid();
+   double midX2 = this->getX2Centroid();
+   double midX3 = this->getX3Centroid();
+
+   double dmin  = 0.0;
+
+   if     ( UbMath::less   ( midX1, x1a ) ) dmin += std::pow( midX1 - x1a, 2.0 );
+   else if( UbMath::greater( midX1, x1b ) ) dmin += std::pow( midX1 - x1b, 2.0 );
+
+   if     ( UbMath::less   ( midX2, x2a ) ) dmin += std::pow( midX2 - x2a, 2.0 );
+   else if( UbMath::greater( midX2, x2b ) ) dmin += std::pow( midX2 - x2b, 2.0 );
+
+   if     ( UbMath::less   ( midX3, x3a ) ) dmin += std::pow( midX3 - x3a, 2.0 );
+   else if( UbMath::greater( midX3, x3b ) ) dmin += std::pow( midX3 - x3b, 2.0 );
+
+   if( UbMath::lessEqual( dmin, radius*radius ) )
+   {
+      return true;
+   }
+
+   return false;
+}
+/*==========================================================*/
+double GbSphere3D::getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+	double deltaX1 = (x1b-x1a);
+	double deltaX2 = (x2b-x2a);
+	double deltaX3 = (x3b-x3a);
+	  
+	if( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )       return 1.0*deltaX1*deltaX2*deltaX3; 
+	if( !(this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)) )   return 0.0;
+
+	double tempResult = 0.0;
+
+	int iMax = 10;
+	int jMax = 10;
+	int kMax = 10;
+
+	for(         int i=0; i<iMax; i++){
+		for(     int j=0; j<jMax; j++){
+			for( int k=0; k<kMax; k++){
+				
+				tempResult += getCellVolumeInsideGbObject3DHelperFunction(
+					x1a+((double) i   )*deltaX1/((double)iMax), x2a+((double) j   )*deltaX2/((double)jMax), x3a+((double) k   )*deltaX3/((double)kMax),
+					x1a+((double)(i+1))*deltaX1/((double)iMax), x2a+((double)(j+1))*deltaX2/((double)jMax), x3a+((double)(k+1))*deltaX3/((double)kMax) );
+			}
+		}
+	}
+
+
+	double resultWithOneCell = getCellVolumeInsideGbObject3DHelperFunction( x1a, x2a, x3a, x1b, x2b, x3b );
+
+	//cout << tempResult << " vs. " << resultWithOneCell << endl;
+
+	return tempResult;
+
+}
+/*==========================================================*/
+double GbSphere3D::getCellVolumeInsideGbObject3DHelperFunction(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+{
+
+	double deltaX1 = x1b-x1a;
+   double deltaX2 = x2b-x2a;
+   double deltaX3 = x3b-x3a;
+
+   if(   this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )     return 1.0*deltaX1*deltaX2*deltaX3;
+   if( !(this->isCellCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b)) )   return 0.0;
+
+   double alpha=0.0;
+   double internX1,internX2,internX3;
+
+   for(int x1vers=0;x1vers<2;x1vers++){
+      for(int x2vers=0;x2vers<2;x2vers++){
+         for(int x3vers=0;x3vers<2;x3vers++){
+            internX1 = x1a + (x1b-x1a)*x1vers;
+            internX2 = x2a + (x2b-x2a)*x2vers;
+            internX3 = x3a + (x3b-x3a)*x3vers;
+
+            if( UbMath::lessEqual(this->getDistance(internX1,internX2,internX3),alpha) )
+               alpha = this->getDistance(internX1,internX2,internX3);
+            //cout<<zelltyp<<" "<<kugel->getDistance(internX1,internX2,internX3)<<" "<<alpha<<endl;
+         }//end first for
+      }//end second for
+   }//end third for
+
+   alpha = (-1)*alpha;
+
+
+
+   double n[3];
+   n[0] = 0.5*(x1b+x1a) - this->getX1Centroid();
+   n[1] = 0.5*(x2b+x2a) - this->getX2Centroid();
+   n[2] = 0.5*(x3b+x3a) - this->getX3Centroid();
+
+   //cout << "Koordinaten:  "<<x1<<" "<<x2<<" "<<x3<<endl;
+   //cout << "Deltas:       "<<deltaX1<<" "<<deltaX2<<" "<<deltaX3<<endl;
+   //cout << "Halbe Zelle:  "<<halfcelldelta<<endl;
+
+   //cout<<"Centroid:  "<<kugel->getX1Centroid()<<" "<<kugel->getX2Centroid()<<" "<<kugel->getX3Centroid()<<endl;
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double normLength;
+   normLength = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
+   n[0] /= normLength;
+   n[1] /= normLength;
+   n[2] /= normLength;
+
+   if( UbMath::less(n[0],0.0) ) n[0] = -n[0];
+   if( UbMath::less(n[1],0.0) ) n[1] = -n[1];
+   if( UbMath::less(n[2],0.0) ) n[2] = -n[2];
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double dummy;
+   if( UbMath::greater(n[0],n[1])) {dummy=n[1]; n[1]=n[0]; n[0]=dummy;}
+   if( UbMath::greater(n[1],n[2])) {dummy=n[2]; n[2]=n[1]; n[1]=dummy;}
+   if( UbMath::greater(n[0],n[1])) {dummy=n[1]; n[1]=n[0]; n[0]=dummy;}
+
+   //cout<<"Normals: "<<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;
+
+   double n1,n2,n3;
+   n1=n[0];
+   n2=n[1];
+   n3=n[2];
+
+	double maxVol =  deltaX1*deltaX2*deltaX3;
+
+	double result = 0.0, preresult = 0.0;
+
+   if( UbMath::lessEqual( maxVol, 0.000001 ) )
+      return 0.0;
+
+   // 1D Check
+   if ( UbMath::lessEqual(n1,0.001)&&UbMath::lessEqual(n2,0.001) )
+	{
+		result = alpha*deltaX1*deltaX2;
+   }
+   // 2D Check
+   else if ( UbMath::lessEqual(n1,0.001) )
+	{
+		preresult = (2*n2*n3);
+		result = (alpha*alpha)/preresult;
+		
+		if( UbMath::greater(alpha,n2*deltaX2) )
+		{
+			result += -(alpha-n2*deltaX2)*(alpha-n2*deltaX2)/preresult;
+		}
+		if( UbMath::greater(alpha,n3*deltaX3) )
+		{
+			result += -(alpha-n3*deltaX3)*(alpha-n3*deltaX3)/preresult;
+		}
+		if( UbMath::greater(alpha,n2*deltaX2+n3*deltaX3) )
+		{
+			result +=  (alpha-n2*deltaX2-n3*deltaX3)*(alpha-n2*deltaX2-n3*deltaX3)/preresult;
+		}
+
+		// tiefenrichtung mit einmultiplizieren...
+		result *= deltaX1;
+	}	
+   // 3D Check
+   else	
+	{ 	
+		preresult =6*n1*n2*n3;
+
+		result = alpha*alpha*alpha;
+
+		if ( UbMath::greaterEqual(alpha,n1*deltaX1))
+		{
+			result+=-((alpha-n1*deltaX1)*(alpha-n1*deltaX1)*(alpha-n1*deltaX1));
+		}
+		if (UbMath::greaterEqual(alpha,n2*deltaX2))
+		{
+			result+=-((alpha-n2*deltaX2)*(alpha-n2*deltaX2)*(alpha-n2*deltaX2));
+		}
+		if (UbMath::greaterEqual(alpha,n3*deltaX3))
+		{
+			result+=-((alpha-n3*deltaX3)*(alpha-n3*deltaX3)*(alpha-n3*deltaX3));
+		}
+		if (UbMath::greaterEqual(alpha,(n1*deltaX1+n2*deltaX2)))
+		{
+			result+=((alpha-(n1*deltaX1+n2*deltaX2))*(alpha-(n1*deltaX1+n2*deltaX2))*(alpha-(n1*deltaX1+n2*deltaX2)));
+		}
+		if (UbMath::greaterEqual(alpha,(n1*deltaX1+n3*deltaX3)))
+		{
+			result+=((alpha-(n1*deltaX1+n3*deltaX3))*(alpha-(n1*deltaX1+n3*deltaX3))*(alpha-(n1*deltaX1+n3*deltaX3)));
+		}
+		if (UbMath::greaterEqual(alpha,(n2*deltaX2+n3*deltaX3)))
+		{
+			result+=((alpha-(n2*deltaX2+n3*deltaX3))*(alpha-(n2*deltaX2+n3*deltaX3))*(alpha-(n2*deltaX2+n3*deltaX3)));
+		}
+
+		//NEW
+		if (UbMath::greaterEqual(alpha,(n1*deltaX1+n2*deltaX2+n3*deltaX3)))
+		{
+			result+= -((alpha-(n1*deltaX1+n2*deltaX2+n3*deltaX3))*(alpha-(n1*deltaX1+n2*deltaX2+n3*deltaX3))*(alpha-(n1*deltaX1+n2*deltaX2+n3*deltaX3)));
+		}
+
+		result = result / preresult;
+
+   }
+   return(result) ;
+
+   //cout << "alpha ist " << alpha << endl;
+   //cout << "fillLevel ist " << eps << endl;
+}
+/*==========================================================*/
+double GbSphere3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   double lx1  = midPoint->x1 - x1;
+   double lx2  = midPoint->x2 - x2;
+   double lx3  = midPoint->x3 - x3;
+   double l_sq = lx1*lx1 + lx2*lx2 + lx3*lx3;  //l = abstand Punkt(x1,x2,x3)<->kreismittelpunkt
+
+   double s    = lx1*rx1 + lx2*rx2 + lx3*rx3;  //s= l*ray_dir)
+   double r_sq = this->radius * this->radius;  // r² =r*r
+   //if (d<0 (fuer die Richtung falls sie gegen das Kreis dann haben wir ein negativer Zahl)
+   //     && l² > r² (point outside ))
+   //wenn s<0->Punkt liegt rechts vom mittelpunkt, wenn nun punkt ausserhalb des kreises liegt, kann es keinen SP mehr geben
+   if( s<-1.E-10 && l_sq>r_sq+1.E-10 )
+      return -1.0;
+   //Pythagor on Triangle Rectangle (point, center of the cercle, intersection of the direction on point and m)
+   // l² = m² + d²
+   double m_sq = l_sq - s*s;
+   // if (m² > r² (dann gibt es kein schnittpunt zwischen direction und circle))
+   if( m_sq > r_sq+1.E-10 )  return -1.0;
+   // Pythagoras on Triangle Rectangle in cercle (direction , m, r)
+   // r² = m² + h²
+
+   //patch: rundungsfehler bei kleinen delta!!!
+   //-> wenn wurzel minimal null->
+   double wurzelTerm = r_sq - m_sq;
+   if(wurzelTerm<0.0)
+   {
+      if(wurzelTerm<-1E-10) return -1.0; //definitiv kein SP
+      else                  return s;   //im rundungsfehler-bereich. SP liegt dierkt auf sphere umrandung
+   }
+
+   //if point outside of the circle
+   if(l_sq>r_sq) return s-sqrt(wurzelTerm);
+
+   return s+sqrt(wurzelTerm);
+}
+/*=======================================================*/
diff --git a/source/VirtualFluidsCore/Geometry/GbSphere3D.h b/source/VirtualFluidsCore/Geometry/GbSphere3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9d4d86ea7fabe544e768f90e7ba2aefc2cabec6
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbSphere3D.h
@@ -0,0 +1,163 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBSPHERE3D_H
+#define GBSPHERE3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+#ifdef CAB_CTL
+   #include <ctl.h>
+#endif //CAB_CTL
+
+#include <vector>
+#include <cmath>
+
+#include <basics/utilities/UbObserver.h>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbSphere3D;
+typedef VFSharedPtr<GbSphere3D> GbSphere3DPtr;
+
+
+class GbLine3D;
+class GbTriangle3D;
+class GbObject3DCreator;
+
+class GbSphere3D : public GbObject3D, public UbObserver
+{                                              
+public:
+   enum TRIANGULATIONMODE { CUBOIDPROJECTION ,RAYPROJECTION };
+   
+   //////////////////////////////////////////////////////////////////////////
+   // Konstruktoren
+   GbSphere3D(); 
+   GbSphere3D(const double& x1,const double& x2, const double& x3, const double& radius);            
+   GbSphere3D(const GbSphere3D& sphere);            
+   GbSphere3D(GbSphere3D* sphere); //<-unschoen!
+   
+   ~GbSphere3D();
+
+   GbSphere3D* clone() { return new GbSphere3D(*this);}
+   void finalize();
+
+   double getRadius() const	{	return this->radius;	}
+
+   double getX1Centroid()  { return midPoint->getX1Coordinate();}
+   double getX1Minimum()   { return midPoint->getX1Coordinate()-radius;}
+   double getX1Maximum()   { return midPoint->getX1Coordinate()+radius;}
+   double getX2Centroid()  { return midPoint->getX2Coordinate();}
+   double getX2Minimum()   { return midPoint->getX2Coordinate()-radius;}
+   double getX2Maximum()   { return midPoint->getX2Coordinate()+radius;}
+   double getX3Centroid()  { return midPoint->getX3Coordinate();}
+   double getX3Minimum()   { return midPoint->getX3Coordinate()-radius;}
+   double getX3Maximum()   { return midPoint->getX3Coordinate()+radius;}
+
+   void setCenterX1Coordinate(const double& value);
+   void setCenterX2Coordinate(const double& value);
+   void setCenterX3Coordinate(const double& value);
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+   void setRadius(const double& radius);
+
+   GbLine3D* createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2);
+   double getDistance(GbPoint3D* p); 
+   double getDistance(const double& x1p, const double& x2p, const double& x3p);
+
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary);
+
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   double getCellVolumeInsideGbObject3DHelperFunction(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+   bool hasIntersectionWithDirectedLine(GbPoint3D origin, GbPoint3D direction);
+
+	std::string toString();
+
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);       
+
+   void translate(const double& x1, const double& x2, const double& x3) 
+   {
+      this->midPoint->translate(x1, x2, x3); 
+      this->notifyObserversObjectChanged();
+   }
+   void rotate(const double& rx1, const double& rx2, const double& rx3) {/* rotation makes no sense*/ }
+   void scale(const double& sx1, const double& sx2, const double& sx3) 
+   { 
+      this->radius *= sx1; 
+      this->notifyObserversObjectChanged();
+   }
+
+   void transform(const double matrix[4][4]);
+
+   TRIANGULATIONMODE getTriangulationMode() {return triangulationMode;}
+   void setTriangulationMode(TRIANGULATIONMODE mode) { this->triangulationMode = mode; }
+   
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject)
+   {
+      this->notifyObserversObjectChanged();
+      //std::cout<<"GbSphere:objectChanged() - toDo-);";
+   }
+   void objectWillBeDeleted(UbObservable* objectForDeletion)
+   {
+	   throw UbException(UB_EXARGS,"not implemented");
+   }
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere, weil man eine
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & midPoint;
+      ar & radius;
+      ar & triangulationMode;
+   }
+#endif //CAB_RCF
+#ifdef CAB_CTL
+   ctl::oStream &write(ctl::oStream &os) const
+   { 
+      midPoint->write(os);
+      return os<<radius; 
+   }
+   ctl::iStream &read(ctl::iStream &is) 
+   { 
+      midPoint->read(is);
+      return is>>radius;
+   }
+#endif //CAB_CTL
+
+private:
+   GbPoint3D* midPoint;
+   double radius;  // Radius des Kreises
+   TRIANGULATIONMODE triangulationMode;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   #if CAB_RCF <= 903 
+      SF_SERIALIZE_ENUM(GbSphere3D::TRIANGULATIONMODE) //bei klassen ausserhalb der klasse;-)
+   #endif
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbSphere3D>("GbSphere3D")             , SF_GbSphere3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbSphere3D >()), SF_GbSphere3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //GBSPHERE3D_H
diff --git a/source/VirtualFluidsCore/Geometry/GbSystem3D.cpp b/source/VirtualFluidsCore/Geometry/GbSystem3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..529d3222c8b643631e6e33fe2499c5df873313e2
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbSystem3D.cpp
@@ -0,0 +1,1187 @@
+#include <numerics/geometry3d/GbSystem3D.h>
+
+#include <numerics/geometry3d/GbPolygon3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+
+using namespace std;
+
+double GbSystem3D::getDistance(const GbPoint3D& p11, const GbPoint3D& p12)
+{
+   double dx1 = p11.x1 - p12.x1;
+   double dx2 = p11.x2 - p12.x2;
+   double dx3 = p11.x3 - p12.x3;
+   return std::sqrt(dx1*dx1+dx2*dx2+dx3*dx3);
+}
+
+GbPoint3D* GbSystem3D::calculateIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22)
+{
+   if(UbMath::less2(p11.x1, p12.x1, p21.x1, p22.x1))    return NULL;
+   if(UbMath::less2(p11.x2, p12.x2, p21.x2, p22.x2))    return NULL;
+   if(UbMath::less2(p11.x3, p12.x3, p21.x3, p22.x3))    return NULL;
+   if(UbMath::greater2(p11.x1, p12.x1, p21.x1, p22.x1)) return NULL;
+   if(UbMath::greater2(p11.x2, p12.x2, p21.x2, p22.x2)) return NULL;
+   if(UbMath::greater2(p11.x3, p12.x3, p21.x3, p22.x3)) return NULL;
+
+   double a11 = p12.x1 - p11.x1;                       //..HOW PARAMETERS ARE USED.........
+   double a12 = p12.x2 - p11.x2;                       //
+   double a13 = p12.x3 - p11.x3;                       //  p11 and p12 represent line 1
+   double a21 = p21.x1 - p22.x1;                       //  p21 and p22 represent line 2
+   double a22 = p21.x2 - p22.x2;                       //
+   double a23 = p21.x3 - p22.x3;                       //..................................
+   double b1  = p21.x1 - p11.x1;
+   double b2  = p21.x2 - p11.x2;
+   double b3  = p21.x3 - p11.x3;
+   double d1  = a11*a22 - a12*a21;
+   double d2  = a11*a23 - a13*a21;
+   double d3  = a12*a23 - a13*a22;
+   double t;
+
+   if(UbMath::zero(d1) && UbMath::zero(d2) && UbMath::zero(d3)) return NULL;
+   if(UbMath::zero(d1))
+   {
+   	if(!UbMath::zero(d2)) t = (a23*b1-a21*b3)/d2;
+      else          t = (a23*b2-a22*b3)/d3;
+   }
+   else if(UbMath::zero(d2))
+   {
+   	if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1;
+      else          t = (a23*b2-a22*b3)/d3;
+   }
+   else if(UbMath::zero(d3))
+   {
+   	if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1;
+      else          t = (a23*b1-a21*b3)/d2;
+   }
+   else return NULL;
+
+   double x1 = p11.x1 + t*a11;
+   double x2 = p11.x2 + t*a12;
+   double x3 = p11.x3 + t*a13;
+
+   if(UbMath::inClosedInterval(x1, p11.x1, p12.x1) && UbMath::inClosedInterval(x1, p21.x1, p22.x1) &&
+      UbMath::inClosedInterval(x2, p11.x2, p12.x2) && UbMath::inClosedInterval(x2, p21.x2, p22.x2) &&
+      UbMath::inClosedInterval(x3, p11.x3, p12.x3) && UbMath::inClosedInterval(x3, p21.x3, p22.x3)    ) return new GbPoint3D(x1, x2, x3);
+
+   return NULL;
+}
+/*=================================================================*/
+//Line1: p11 -> p12 and Line2: p21 -> p22
+bool GbSystem3D::hasIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22)
+{
+   if(UbMath::less2(p11.x1, p12.x1, p21.x1, p22.x1))    return false; 
+   if(UbMath::less2(p11.x2, p12.x2, p21.x2, p22.x2))    return false; 
+   if(UbMath::less2(p11.x3, p12.x3, p21.x3, p22.x3))    return false; 
+   if(UbMath::greater2(p11.x1, p12.x1, p21.x1, p22.x1)) return false; 
+   if(UbMath::greater2(p11.x2, p12.x2, p21.x2, p22.x2)) return false; 
+   if(UbMath::greater2(p11.x3, p12.x3, p21.x3, p22.x3)) return false; 
+
+   double a11 = p12.x1 - p11.x1;                       //..HOW PARAMETERS ARE USED.........
+   double a12 = p12.x2 - p11.x2;                       //
+   double a13 = p12.x3 - p11.x3;                       //  p11 and p12 represent line 1
+   double a21 = p21.x1 - p22.x1;                       //  p21 and p22 represent line 2
+   double a22 = p21.x2 - p22.x2;                       //
+   double a23 = p21.x3 - p22.x3;                       //..................................
+   double b1  = p21.x1 - p11.x1;
+   double b2  = p21.x2 - p11.x2;
+   double b3  = p21.x3 - p11.x3;
+   double d1  = a11*a22 - a12*a21;
+   double d2  = a11*a23 - a13*a21;
+   double d3  = a12*a23 - a13*a22;
+   double t;
+
+   if(UbMath::zero(d1) && UbMath::zero(d2) && UbMath::zero(d3)) return false; 
+   if(UbMath::zero(d1))
+   {
+      if(!UbMath::zero(d2)) t = (a23*b1-a21*b3)/d2;
+      else          t = (a23*b2-a22*b3)/d3;
+   }
+   else if(UbMath::zero(d2))
+   {
+      if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1;
+	   else          t = (a23*b2-a22*b3)/d3;
+   }
+   else if(UbMath::zero(d3))
+   {
+      if(!UbMath::zero(d1)) t = (a22*b1-a21*b2)/d1;
+      else          t = (a23*b1-a21*b3)/d2;
+   }
+   else return false; 
+
+   double x1 = p11.x1 + t*a11;
+   double x2 = p11.x2 + t*a12;
+   double x3 = p11.x3 + t*a13;
+
+   if(UbMath::inClosedInterval(x1, p11.x1, p12.x1) && UbMath::inClosedInterval(x1, p21.x1, p22.x1) &&
+	   UbMath::inClosedInterval(x2, p11.x2, p12.x2) && UbMath::inClosedInterval(x2, p21.x2, p22.x2) &&
+	   UbMath::inClosedInterval(x3, p11.x3, p12.x3) && UbMath::inClosedInterval(x3, p21.x3, p22.x3)) return true; 
+   return false; 
+}
+ /*======================================================================*/
+//
+//
+//   /*======================================================================*/
+//   /*  Private Methoden (Parallelism)                                      */
+//   /*                                                                      */
+bool GbSystem3D::isParallelIn3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22)
+{
+   double a11 = p12.x1 - p11.x1;                       //..HOW PARAMETERS ARE USED.........
+   double a12 = p12.x2 - p11.x2;                       //
+   double a13 = p12.x3 - p11.x3;                       //  p11 and p12 represent line 1
+   double a21 = p21.x1 - p22.x1;                       //  p21 and p22 represent line 2
+   double a22 = p21.x2 - p22.x2;                       //
+   double a23 = p21.x3 - p22.x3;                       //..................................
+
+   return (UbMath::zero(a11*a22 - a12*a21) && UbMath::zero(a11*a23 - a13*a21) && UbMath::zero(a12*a23 - a13*a22));
+}
+/*======================================================================*/
+
+
+/*======================================================================*/
+/*  General Clipping Methods                                            */
+//......................................................................*/
+//
+//  Method       Parameters                                       Result      Remarks
+//  ---------    ---------------------------------------------    ---------   -------------------
+//  clip###2D   (2D objects to be clipped, 2+2 clipping values)   2D object   clipping x1, x2
+//  clip###3D   (3D objects to be clipped, 2+2 clipping values)   3D object   clipping x1, x2
+//  clip###3D   (3D objects to be clipped, 3+3 clipping values)   3D object   clipping x1, x2, x3
+//  clip###3D   (3D objects to be clipped, 1+1 clipping values)   3D object   clipping x3
+//
+/*======================================================================*/
+/*  Private Methoden (Clipping Lines)                                   */
+/*                                                                      */
+GbLine3D* GbSystem3D::createClipLine3D(GbPoint3D &pA, GbPoint3D &pB, double x1a, double x2a, double x3a, double x1b, double x2b, double x3b)
+{
+   GbPoint3D *p1 = new GbPoint3D(pA);
+   GbPoint3D *p2 = new GbPoint3D(pB);
+
+   if(UbMath::greater(x1a, x1b)) { double x1 = x1a; x1a = x1b; x1b = x1; }
+   if(UbMath::greater(x2a, x2b)) { double x2 = x2a; x2a = x2b; x2b = x2; }
+   if(UbMath::greater(x3a, x3b)) { double x3 = x3a; x3a = x3b; x3b = x3; }
+
+   double f;
+
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an vorderer Kante                                      */
+   /*                                                                   */
+   if(UbMath::less(p1->x3, x3a))
+   {
+      if(UbMath::less(p2->x3, x3a)) { delete p1; delete p2; return NULL; }
+
+      f       = (x3a-p1->x3)/(p1->x3-p2->x3);
+      p1->x1 += (p1->x1-p2->x1)*f;
+      p1->x2 += (p1->x2-p2->x2)*f;
+      p1->x3  = x3a;
+   }
+   else if(UbMath::less(p2->x3, x3a))
+   {
+      f      = (x3a-p2->x3)/(p2->x3-p1->x3);
+      p2->x1 += (p2->x1-p1->x1)*f;
+      p2->x2 += (p2->x2-p1->x2)*f;
+      p2->x3  = x3a;
+   }     
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an unterer Kante                                       */
+   /*                                                                   */
+   if(UbMath::less(p1->x2, x2a))
+   {
+      if(UbMath::less(p2->x2, x2a)) { delete p1; delete p2; return NULL;
+      }
+
+      f      = (x2a-p1->x2)/(p1->x2-p2->x2);
+      p1->x1 += (p1->x1-p2->x1)*f;
+      p1->x3 += (p1->x3-p2->x3)*f;
+      p1->x2  = x2a;
+   }
+   else if(UbMath::less(p2->x2, x2a))
+   {
+      f      = (x2a-p2->x2)/(p2->x2-p1->x2);
+      p2->x1 += (p2->x1-p1->x1)*f;
+      p2->x3 += (p2->x3-p1->x3)*f;
+      p2->x2  = x2a;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an rechter Kante                                       */
+   /*                                                                   */
+   if(UbMath::greater(p1->x1, x1b))
+   {
+      if(UbMath::greater(p2->x1, x1b))  { delete p1;delete p2; return NULL;}
+
+      f      = (x1b-p1->x1)/(p1->x1-p2->x1);
+      p1->x2 += (p1->x2-p2->x2)*f;
+      p1->x3 += (p1->x3-p2->x3)*f;
+      p1->x1  = x1b;
+   }
+   else if(UbMath::greater(p2->x1, x1b))
+   {
+      f      = (x1b-p2->x1)/(p2->x1-p1->x1);
+      p2->x2 += (p2->x2-p1->x2)*f;
+      p2->x3 += (p2->x3-p1->x3)*f;
+      p2->x1  = x1b;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an hinterer Kante                                      */
+   /*                                                                   */
+   if(UbMath::greater(p1->x3, x3b))
+   {
+      if(UbMath::greater(p2->x3, x3b))  { delete p1;delete p2; return NULL;}
+
+      f      = (x3b-p1->x3)/(p1->x3-p2->x3);
+      p1->x1 += (p1->x1-p2->x1)*f;
+      p1->x2 += (p1->x2-p2->x2)*f;
+      p1->x3  = x3b;
+   }
+   else if(UbMath::greater(p2->x3, x3b))
+   {
+      f      = (x3b-p2->x3)/(p2->x3-p1->x3);
+      p2->x1 += (p2->x1-p1->x1)*f;
+      p2->x2 += (p2->x2-p1->x2)*f;
+      p2->x3  = x3b;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an oberer Kante                                        */
+   /*                                                                   */
+   if(UbMath::greater(p1->x2, x2b))
+   {
+      if(UbMath::greater(p2->x2, x2b))  { delete p1;delete p2; return NULL;}
+
+      f      = (x2b-p1->x2)/(p1->x2-p2->x2);
+      p1->x1 += (p1->x1-p2->x1)*f;
+      p1->x3 += (p1->x3-p2->x3)*f;
+      p1->x2  = x2b;
+   }
+   else if(UbMath::greater(p2->x2, x2b))
+   {
+      f      = (x2b-p2->x2)/(p2->x2-p1->x2);
+      p2->x1 += (p2->x1-p1->x1)*f;
+      p2->x3 += (p2->x3-p1->x3)*f;
+      p2->x2  = x2b;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an linker Kante                                        */
+   /*                                                                   */
+   if(UbMath::less(p1->x1, x1a))
+   {
+      if(UbMath::less(p2->x1, x1a))  { delete p1;delete p2; return NULL;}
+
+      f      = (x1a-p1->x1)/(p1->x1-p2->x1);
+      p1->x2 += (p1->x2-p2->x2)*f;
+      p1->x3 += (p1->x3-p2->x3)*f;
+      p1->x1  = x1a;
+   }
+   else if(UbMath::less(p2->x1, x1a))
+   {
+      f      = (x1a-p2->x1)/(p2->x1-p1->x1);
+      p2->x2 += (p2->x2-p1->x2)*f;
+      p2->x3 += (p2->x3-p1->x3)*f;
+      p2->x1  = x1a;
+   }
+   /*-------------------------------------------------------------------*/
+   return new GbLine3D(p1, p2);
+}
+//   /*======================================================================*/
+//   /*  Private Methoden (Clipping Rectangles)                              */
+//   /*                                                                      */
+//   final static GbPolygon3D clipPolygon3D(GbPoint3D points[], double x11, double x12, double x21, double x22)
+//   {
+//      GbPoint3D last = null;
+//      PointSet3 ps   = new PointSet3(points);
+//      boolean   flag = false;
+//      int       n    = points.length;
+//      int       i;
+//      double    f;
+//
+//      if(n == 0)              return(null);
+//      if(greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; }
+//      if(greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; }
+//
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an unterer Kante                                       */
+//      /*                                                                   */
+//      if(less(ps.getX2Minimum(), x12))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(less((*points)[0]->x2, x12)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(less((*points)[i]->x2, x12))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x12-(*points)[i]->x2)/((*points)[i]->x2-last->x2);
+//	          ps.add(new GbPoint3D((*points)[i]->x1 + ((*points)[i]->x1-last->x1)*f, x12, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x12-(*points)[i]->x2)/((*points)[i]->x2-last->x2);
+//	          ps.add(new GbPoint3D((*points)[i]->x1 + ((*points)[i]->x1-last->x1)*f, x12, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f));
+//	       }
+//	       ps.add((*points)[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((less(points[0].x2, x12)) ^ flag))
+//	 {
+//	    f = (x12-points[0].x2)/(points[0].x2-last->x2);
+//	    ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last->x1)*f, x12, points[0].x3 + (points[0].x3-last->x3)*f));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an rechter Kante                                       */
+//      /*                                                                   */
+//      if(greater(ps.getX1Maximum(), x21))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(greater(points[0].x1, x21)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(greater((*points)[i]->x1, x21))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x21-(*points)[i]->x1)/((*points)[i]->x1-last->x1);
+//	          ps.add(new GbPoint3D(x21, (*points)[i]->x2 + ((*points)[i]->x2-last->x2)*f, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x21-(*points)[i]->x1)/((*points)[i]->x1-last->x1);
+//	          ps.add(new GbPoint3D(x21, (*points)[i]->x2 + ((*points)[i]->x2-last->x2)*f, (*points)[i]->x3 + ((*points)[i]->x3-last->x3)*f));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((greater(points[0].x1, x21)) ^ flag))
+//	 {
+//	    f = (x21-points[0].x1)/(points[0].x1-last.x1);
+//	    ps.add(new GbPoint3D(x21, points[0].x2 + (points[0].x2-last.x2)*f, points[0].x3 + (points[0].x3-last.x3)*f));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an oberer Kante                                        */
+//      /*                                                                   */
+//      if(greater(ps.getX2Maximum(), x22))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(greater(points[0].x2, x22)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(greater((*points)[i]->x2, x22))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x22-(*points)[i]->x2)/(points[i].x2-last.x2);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, x22, points[i].x3 + (points[i].x3-last.x3)*f));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x22-points[i].x2)/(points[i].x2-last.x2);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, x22, points[i].x3 + (points[i].x3-last.x3)*f));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((greater(points[0].x2, x22)) ^ flag))
+//	 {
+//	    f = (x22-points[0].x2)/(points[0].x2-last.x2);
+//	    ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, x22, points[0].x3 + (points[0].x3-last.x3)*f));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an linker Kante                                        */
+//      /*                                                                   */
+//      if(less(ps.getX1Minimum(), x11))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(less(points[0].x1, x11)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(less(points[i].x1, x11))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x11-points[i].x1)/(points[i].x1-last.x1);
+//	          ps.add(new GbPoint3D(x11, points[i].x2 + (points[i].x2-last.x2)*f, points[i].x3 + (points[i].x3-last.x3)*f));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x11-points[i].x1)/(points[i].x1-last.x1);
+//	          ps.add(new GbPoint3D(x11, points[i].x2 + (points[i].x2-last.x2)*f, points[i].x3 + (points[i].x3-last.x3)*f));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((less(points[0].x1, x11)) ^ flag))
+//	 {
+//	    f = (x11-points[0].x1)/(points[0].x1-last.x1);
+//	    ps.add(new GbPoint3D(x11, points[0].x2 + (points[0].x2-last.x2)*f, points[0].x3 + (points[0].x3-last.x3)*f));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      GbPolygon3D polygon = new GbPolygon3D(points);
+//
+//      if(n > 2)
+//      {
+//	 for(i=2; i<n; i++) if(zero(i_TA(points[i-2], points[i-1], points[i]))) polygon.deletePoint(points[i-1]);
+//	 if(zero(i_TA(points[n-2], points[n-1], points[0]))) polygon.deletePoint(points[n-1]);
+//	 if(zero(i_TA(points[n-1], points[0],   points[1]))) polygon.deletePoint(points[0]);
+//      }
+//      return(polygon);
+//   }
+//   final static GbPolygon3D clipPolygon3D(GbPoint3D points[], double x13, double x23)
+//   {
+//      GbPoint3D last = null;
+//      PointSet3 ps   = new PointSet3(points);
+//      boolean   flag = false;
+//      int       n    = points.length;
+//      int       i;
+//      double    f;
+//
+//      if(n == 0)              return(null);
+//      if(greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; }
+//
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an vorderer Kante                                      */
+//      /*                                                                   */
+//      if(less(ps.getX3Minimum(), x13))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(less(points[0].x3, x13)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(less(points[i].x3, x13))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x13-points[i].x3)/(points[i].x3-last.x3);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x13));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x13-points[i].x3)/(points[i].x3-last.x3);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x13));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((less(points[0].x3, x13)) ^ flag))
+//	 {
+//	    f = (x13-points[0].x3)/(points[0].x3-last.x3);
+//	    ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, points[0].x2 + (points[0].x2-last.x2)*f, x13));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      /*  Schneiden an hinterer Kante                                      */
+//      /*                                                                   */
+//      if(greater(ps.getX3Maximum(), x23))
+//      {
+//	 ps.clear();
+//	 last = points[0];
+//	 if(greater(points[0].x3, x23)) flag = false;
+//	 else
+//	 {
+//	    ps.add(points[0]);
+//	    flag = true;
+//	 }
+//	 for(i=1; i<n; i++)
+//	 {
+//	    if(greater(points[i].x3, x23))
+//	    {
+//	       if(flag)
+//	       {
+//	          f = (x23-points[i].x3)/(points[i].x3-last.x3);
+//	          ps.add(new GbPoint3D(points[i].x1 + (points[i].x1-last.x1)*f, points[i].x2 + (points[i].x2-last.x2)*f, x23));
+//	       }
+//	       flag = false;
+//	    }
+//	    else
+//	    {
+//	       if(!flag)
+//	       {
+//	          f = (x23-points[i].x3)/(points[i].x3-last.x3);
+//	          ps.add(new GbPoint3D(points[i].x1 + ((*points)[i]->x1-last.x1)*f, (*points)[i]->x2 + ((*points)[i]->x2-last.x2)*f, x23));
+//	       }
+//	       ps.add(points[i]);
+//	       flag = true;
+//	    }
+//	    last = points[i];
+//	 }
+//	 if(!((greater(points[0].x3, x23)) ^ flag))
+//	 {
+//	    f = (x23-points[0].x3)/(points[0].x3-last.x3);
+//	    ps.add(new GbPoint3D(points[0].x1 + (points[0].x1-last.x1)*f, points[0].x2 + (points[0].x2-last.x2)*f, x23));
+//	 }
+//
+//	 points = ps.getPoints();
+//	 n      = points.length;
+//
+//	 if(n == 0) return(null);
+//      }
+//      /*-------------------------------------------------------------------*/
+//      GbPolygon3D polygon = new GbPolygon3D(points);
+//
+//      return(polygon);
+//   }
+GbPolygon3D* GbSystem3D::clipPolygon3D(vector<GbPoint3D> points, double x11, double x12, double x13, double x21, double x22, double x23)
+{
+   GbPoint3D last;
+   PointSet3 ps(points);
+   bool   flag = false;
+   int    n    = (int)points.size();
+	int       i;
+   double    f;
+
+   if(n == 0)              return NULL;
+   if(UbMath::greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; }
+   if(UbMath::greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; }
+   if(UbMath::greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; }
+
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an vorderer Kante                                      */
+   /*                                                                   */
+   if(UbMath::less(ps.getX3Minimum(), x13))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::less((points)[0].x3, x13)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::less((points)[i].x3, x13))
+			{
+				if(flag)
+				{
+					f = (x13-(points)[i].x3)/((points)[i].x3-last.x3);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x13));
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x13-(points)[i].x3)/((points)[i].x3-last.x3);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x13));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::less((points)[0].x3, x13)) ^ flag))
+		{
+			f = (x13-(points)[0].x3)/((points)[0].x3-last.x3);
+			ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, (points)[0].x2 + ((points)[0].x2-last.x2)*f, x13));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+   }
+	
+	/*-------------------------------------------------------------------*/
+   /*  Schneiden an unterer Kante                                       */
+   /*                                                                   */
+   if(UbMath::less(ps.getX2Minimum(), x12))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::less((points)[0].x2, x12)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::less((points)[i].x2, x12))
+			{
+				if(flag)
+				{
+					f = (x12-(points)[i].x2)/((points)[i].x2-last.x2);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x12, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				flag = false;
+			}
+		   else
+			{
+				if(!flag)
+				{
+					f = (x12-(points)[i].x2)/((points)[i].x2-last.x2);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x12, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::less((points)[0].x2, x12)) ^ flag))
+		{
+			f = (x12-(points)[0].x2)/((points)[0].x2-last.x2);
+			ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, x12, (points)[0].x3 + ((points)[0].x3-last.x3)*f));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an rechter Kante                                       */
+   /*                                                                   */
+	
+	if(UbMath::greater(ps.getX1Maximum(), x21))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::greater((points)[0].x1, x21)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::greater((points)[i].x1, x21))
+			{
+				if(flag)
+				{
+					f = (x21-(points)[i].x1)/((points)[i].x1-last.x1);
+					ps.add(GbPoint3D(x21, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x21-(points)[i].x1)/((points)[i].x1-last.x1);
+					ps.add(GbPoint3D(x21, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::greater((points)[0].x1, x21)) ^ flag))
+		{
+			f = (x21-(points)[0].x1)/((points)[0].x1-last.x1);
+			ps.add(GbPoint3D(x21, (points)[0].x2 + ((points)[0].x2-last.x2)*f, (points)[0].x3 + ((points)[0].x3-last.x3)*f));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an hinterer Kante                                      */
+   /*                                                                   */
+   if(UbMath::greater(ps.getX3Maximum(), x23))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::greater((points)[0].x3, x23)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::greater((points)[i].x3, x23))
+			{
+				if(flag)
+				{
+					f = (x23-(points)[i].x3)/((points)[i].x3-last.x3);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x23));
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x23-(points)[i].x3)/((points)[i].x3-last.x3);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, (points)[i].x2 + ((points)[i].x2-last.x2)*f, x23));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::greater((points)[0].x3, x23)) ^ flag))
+		{
+			f = (x23-(points)[0].x3)/((points)[0].x3-last.x3);
+			ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, (points)[0].x2 + ((points)[0].x2-last.x2)*f, x23));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+	}
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an oberer Kante                                        */
+   /*                                                                   */
+
+	if(UbMath::greater(ps.getX2Maximum(), x22))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::greater((points)[0].x2, x22)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::greater((points)[i].x2, x22))
+			{
+				if(flag)
+				{
+					f = (x22-(points)[i].x2)/((points)[i].x2-last.x2);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x22, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x22-(points)[i].x2)/((points)[i].x2-last.x2);
+					ps.add(GbPoint3D((points)[i].x1 + ((points)[i].x1-last.x1)*f, x22, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::greater((points)[0].x2, x22)) ^ flag))
+		{
+			f = (x22-(points)[0].x2)/((points)[0].x2-last.x2);
+			ps.add(GbPoint3D((points)[0].x1 + ((points)[0].x1-last.x1)*f, x22, (points)[0].x3 + ((points)[0].x3-last.x3)*f));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+
+		if(n == 0) return NULL;
+   }
+   /*-------------------------------------------------------------------*/
+   /*  Schneiden an linker Kante                                        */
+   /*                                                                   */
+	if(UbMath::less(ps.getX1Minimum(), x11))
+   {
+		ps.clear();
+		last = (points)[0];
+		if(UbMath::less((points)[0].x1, x11)) flag = false;
+		else
+		{
+			ps.add((points)[0]);
+			flag = true;
+		}
+		for(i=1; i<n; i++)
+		{
+			if(UbMath::less((points)[i].x1, x11))
+			{
+				if(flag)
+				{
+					f = (x11-(points)[i].x1)/((points)[i].x1-last.x1);
+					ps.add(GbPoint3D(x11, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+
+				}
+				flag = false;
+			}
+			else
+			{
+				if(!flag)
+				{
+					f = (x11-(points)[i].x1)/((points)[i].x1-last.x1);
+					ps.add(GbPoint3D(x11, (points)[i].x2 + ((points)[i].x2-last.x2)*f, (points)[i].x3 + ((points)[i].x3-last.x3)*f));
+				}
+				ps.add((points)[i]);
+				flag = true;
+			}
+			last = (points)[i];
+		}
+		if(!((UbMath::less((points)[0].x1, x11)) ^ flag))
+		{
+			f = (x11-(points)[0].x1)/((points)[0].x1-last.x1);
+			ps.add(GbPoint3D(x11, (points)[0].x2 + ((points)[0].x2-last.x2)*f, (points)[0].x3 + ((points)[0].x3-last.x3)*f));
+		}
+
+		points = ps.getPoints();
+		n      = (int)points.size();
+		
+		if(n == 0) return NULL;
+   }
+   /*-------------------------------------------------------------------*/
+	return new GbPolygon3D(points);
+}
+/*=========================================================================*/
+GbCuboid3D* GbSystem3D::clipRectangle3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23)
+{
+   double r11 = p1.x1;
+   double r12 = p1.x2;
+   double r13 = p1.x3;
+   double r21 = p2.x1;
+   double r22 = p2.x2;
+   double r23 = p2.x3;
+
+   if(UbMath::greater(x11, x21)) { double ax = x11; x11 = x21; x21 = ax; }
+   if(UbMath::greater(x12, x22)) { double ay = x12; x12 = x22; x22 = ay; }
+   if(UbMath::greater(x13, x23)) { double az = x13; x13 = x23; x23 = az; }
+   if(UbMath::greater(r11, r21)) { double bx = r11; r11 = r21; r21 = bx; }
+   if(UbMath::greater(r12, r22)) { double by = r12; r12 = r22; r22 = by; }
+   if(UbMath::greater(r13, r23)) { double bz = r13; r13 = r23; r23 = bz; }
+
+   double m11 = UbMath::greater(x11, r11) ? x11 : r11;
+   double m12 = UbMath::greater(x12, r12) ? x12 : r12;
+   double m13 = UbMath::greater(x13, r13) ? x13 : r13;
+   double m21 = UbMath::greater(x21, r21) ? r21 : x21;
+   double m22 = UbMath::greater(x22, r22) ? r22 : x22;
+   double m23 = UbMath::greater(x23, r23) ? r23 : x23;
+
+   if(UbMath::lessEqual(m11, m21) && UbMath::lessEqual(m12, m22) && UbMath::lessEqual(m13, m23)) 
+      return(new GbCuboid3D(new GbPoint3D(m11, m12, m13), new GbPoint3D(m21, m22, m23)));
+   else  
+      return(NULL);
+}
+
+/*=========================================================================*/
+/*=========================================================================*/
+/*=========================================================================*/
+
+
+GbSystem3D::PointSet3::PointSet3(int n)
+{
+   this->init();
+   this->points.reserve(n); //reserves n elements! but the size of the vector ist still "0"
+}
+/*=======================================================*/
+GbSystem3D::PointSet3::PointSet3(const vector<GbPoint3D>& points)
+{
+   this->init();
+   this->add(points);
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::add(const GbPoint3D& point)
+{
+   //is point equal to last point in points then return
+   if(!this->points.empty() && point.equals(&this->points.back())) return;    //WHY???
+
+   //push point to vector
+   this->points.push_back(point);
+
+   this->consistent = false;
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::addUnequal(const GbPoint3D& point)
+{
+   if(this->containsEqual(point) > 0) return;
+   
+   this->points.push_back(point);
+   this->consistent = false;
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::add(const vector<GbPoint3D>& pointVector)
+{
+   for(int pos=0; pos<(int)pointVector.size(); pos++ )
+      this->points.push_back(pointVector[pos]);
+
+   this->consistent = false;
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::insert(const GbPoint3D& point, int index)
+{
+   if(index<0 || index>=(int)this->points.size()) 
+      throw UbException(UB_EXARGS,"index out of range");
+
+   //get iterator for index-position
+   vector<GbPoint3D>::iterator pos=this->points.begin();
+   for(int i=1; i<=index; i++) ++pos;
+
+   //insert point
+   this->points.insert(pos,point);
+
+   this->consistent    = false;
+}
+/*=======================================================*/
+//void delete(GbPoint3D point)
+//{
+//   for(int i=this.size-1; i>=0; i--) if(this.points[i] == point) this.delete(i);
+//}
+/*=======================================================*/
+//void delete(int index)
+//{
+//   int j = this.size - index - 1;
+//   if(j > 0) System.arraycopy(this.points, index + 1, this.points, index, j);
+//   this.consistent = false;
+//   this.size--;
+//}
+/*=======================================================*/
+void GbSystem3D::PointSet3::clear()
+{
+   //clears points (size==0 but capacity is the old one)
+   this->points.clear();
+   this->consistent = false;
+}
+/*=======================================================*/
+void GbSystem3D::PointSet3::clearAndTrim()
+{
+   //clears points (size==0 AND capacity==0)
+   this->points.resize(0);
+   this->consistent = false;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX1Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x1min;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX1Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x1max;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX2Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x2min;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX2Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x2max;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX3Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x3min;
+}
+/*=======================================================*/
+double GbSystem3D::PointSet3::getX3Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return this->x3max;
+}
+/*=======================================================*/
+int GbSystem3D::PointSet3::contains(GbPoint3D* point)
+{
+   //returns number of points which has the same adress (this should be 0 or 1!!!)
+   int n=0;
+
+   for(int pos=(int)this->points.size()-1; pos>=0; pos--) 
+      if(&this->points[pos]==point) n++;
+
+   return n;
+}
+/*=======================================================*/
+int GbSystem3D::PointSet3::containsEqual(const GbPoint3D& point)
+{
+   //returns number of points which have the same coordinates with point (could be 0,1 or even more)
+   int n=0;
+
+   for(int pos=(int)this->points.size()-1; pos>=0; pos--) 
+      if(this->points[pos].equals(&point)) n++;
+
+   return n;
+}
+/*=======================================================*/
+bool GbSystem3D::PointSet3::containsLine(GbPoint3D *point1, GbPoint3D *point2)
+{
+   //returns true if pointset has two in "this->points"vector  neighboured points 
+   //wich have the same adress as point1 or point2
+   vector<GbPoint3D>::iterator pos1=this->points.begin();
+   vector<GbPoint3D>::iterator pos2;
+
+   for(pos2=pos1++; pos2!=this->points.end(); ++pos2) 
+   {
+      if     (&(*pos1)==point1 && &(*pos2)==point2) return true;
+      else if(&(*pos1)==point2 && &(*pos2)==point1) return true;
+
+      pos1=pos2;
+   }
+
+   return false;
+}
+/*=======================================================*/
+bool GbSystem3D::PointSet3::containsEqualLine(const GbPoint3D& point1, const GbPoint3D& point2)
+{
+   //returns true if pointset has two in "this->points"vector  neighboured points 
+   //wich have the same coordinates as point1 or point2
+   vector<GbPoint3D>::iterator pos1=this->points.begin();
+   vector<GbPoint3D>::iterator pos2;
+
+   for(pos2=pos1++; pos2!=this->points.end(); ++pos2) 
+   {
+      if     ((*pos1).equals(&point1) && (*pos2).equals(&point2)) return true;
+      else if((*pos1).equals(&point2) && (*pos2).equals(&point1)) return true;
+
+      pos1=pos2;
+   }
+
+   return false;
+}
+/*=======================================================*/
+GbPoint3D* GbSystem3D::PointSet3::getPoint(int index)
+{
+   if(index<0 || index>=(int)this->points.size()) throw UbException(UB_EXARGS,"index out of range");
+   return &(this->points)[index];
+}
+/*=======================================================*/
+GbPoint3D* GbSystem3D::PointSet3::getFirstPoint()
+{
+   return &(this->points.front());
+}
+/*=======================================================*/
+GbPoint3D* GbSystem3D::PointSet3::getLastPoint() 
+{ 
+   return &(this->points.back()); 
+}
+/*=======================================================*/
+int GbSystem3D::PointSet3::size()
+{ 
+   return (int)this->points.size();      
+}
+/*=======================================================*/
+vector<GbPoint3D> GbSystem3D::PointSet3::getPoints()
+{
+   //is this right? it's another effect as at GbPoint3D* getNode(index)!!!
+   //or do we want to have the next uncommented getPoints() funktion
+   return this->points;
+}
+///*=======================================================*/
+//vector<GbPoint3D*> GbSystem3D::PointSet3::getPoints()
+//{
+//   vector<GbPoint3D*> tmp;
+//   for(int pos=0; pos<(int)this->points.size();pos++) tmp.push_back(&this->points[pos]);
+//   
+//   return tmp;
+//}
+/*=======================================================*/
+void GbSystem3D::PointSet3::calculateValues()
+{
+   if(this->points.empty()) 
+   {
+      this->x1min = this->x2min = this->x3min = 0.0;
+      this->x1max = this->x2max = this->x3max = 0.0;
+   }
+   else
+   {
+      this->x1min = (this->points)[0].x1;
+      this->x1max = (this->points)[0].x1;
+      this->x2min = (this->points)[0].x2;
+      this->x2max = (this->points)[0].x2;
+      this->x3min = (this->points)[0].x3;
+      this->x3max = (this->points)[0].x3;
+
+      for(int i=(int)this->points.size()-1; i>0; --i)
+      {
+         if((this->points)[i].x1 < this->x1min) this->x1min = (this->points)[i].x1;
+         if((this->points)[i].x1 > this->x1max) this->x1max = (this->points)[i].x1;
+         if((this->points)[i].x2 < this->x2min) this->x2min = (this->points)[i].x2;
+         if((this->points)[i].x2 > this->x2max) this->x2max = (this->points)[i].x2;
+         if((this->points)[i].x3 < this->x3min) this->x3min = (this->points)[i].x3;
+         if((this->points)[i].x3 > this->x3max) this->x3max = (this->points)[i].x3;
+      }
+   }
+   this->consistent = true;
+}
+
+
+
diff --git a/source/VirtualFluidsCore/Geometry/GbSystem3D.h b/source/VirtualFluidsCore/Geometry/GbSystem3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3f579b282f16b5c74b4958688305081c09b7c29
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbSystem3D.h
@@ -0,0 +1,396 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBSYSTEM3D_H
+#define GBSYSTEM3D_H
+
+#include <iostream>
+#include <cmath>
+#include <vector>
+
+#include <basics/utilities/UbMath.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+#include <numerics/geometry3d/GbObject3D.h>
+#include <basics/writer/WbWriter.h>
+
+class GbPolygon3D;
+class GbCuboid3D;
+class GbLine3D;
+
+namespace GbSystem3D
+{
+   extern double       getDistance(const GbPoint3D& p11, const GbPoint3D& p12);
+   extern GbPoint3D*   calculateIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22);
+   extern GbPolygon3D* clipPolygon3D(std::vector<GbPoint3D> points, double x11, double x12, double x13, double x21, double x22, double x23);
+   extern GbLine3D*    createClipLine3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23);
+   extern bool         hasIntersectionPoint3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22);
+   extern bool         isParallelIn3D(GbPoint3D& p11, GbPoint3D& p12, GbPoint3D& p21, GbPoint3D& p22);
+   extern GbCuboid3D*  clipRectangle3D(GbPoint3D& p1, GbPoint3D& p2, double x11, double x12, double x13, double x21, double x22, double x23);
+
+   /*========================================================================================*/
+   inline static std::string writeGeoObject(GbObject3D* gbobject, const std::string& filename, WbWriter* writer)
+   {
+      std::vector<UbTupleFloat3> nodes;
+      std::vector<UbTupleInt3>   triangles;
+      gbobject->addSurfaceTriangleSet(nodes, triangles);
+
+      std::string outFilename = writer->writeTriangles(filename,nodes,triangles);
+      return outFilename;
+   }
+   //the same as before
+   /*========================================================================================*/
+   inline static std::string writeGeoObject(GbObject3DPtr gbobject, const std::string& filename, WbWriter* writer)
+   {
+      std::vector<UbTupleFloat3> nodes;
+      std::vector<UbTupleInt3>   triangles;
+      gbobject->addSurfaceTriangleSet(nodes, triangles);
+
+      std::string outFilename = writer->writeTriangles(filename,nodes,triangles);
+      return outFilename;
+   }
+   /*========================================================================================*/
+   inline static std::vector< std::string > writeGeoObject(GbObject3D*  gbobject, const std::string& filename, std::vector< WbWriter* > writer )
+   {
+      std::vector<UbTupleFloat3> nodes;
+      std::vector<UbTupleInt3>   triangles;
+      gbobject->addSurfaceTriangleSet(nodes, triangles);
+
+      std::vector< std::string > outFilenames;
+      for(std::size_t i=0; i<writer.size(); ++i)
+         outFilenames.push_back( writer[i]->writeTriangles(filename,nodes,triangles) );
+      return outFilenames;
+   }
+   /*========================================================================================*/
+   inline static std::string writeGeoObjects(std::vector< GbObject3D* > gbobjects, const std::string& filename, WbWriter* writer)
+   {
+      std::vector<UbTupleFloat3> nodes;
+      std::vector<UbTupleInt3>   triangles;
+
+      for(std::size_t i=0; i<gbobjects.size(); ++i)
+      {
+         //std::cout<<i<<", "<<gbobjects[i]<<std::endl;
+         gbobjects[i]->addSurfaceTriangleSet(nodes, triangles);
+      }
+
+      std::string outFilename = writer->writeTriangles(filename,nodes,triangles);
+      return outFilename;
+   }
+   /*========================================================================================*/
+
+   //////////////////////////////////////////////////////////////////////////
+   class PointSet3
+   {
+   public:
+      PointSet3(int n);
+      PointSet3(const std::vector<GbPoint3D>& points);
+      ~PointSet3(){}
+      void   add(const GbPoint3D& point);
+      void   addUnequal(const GbPoint3D& point);
+      void   add(const std::vector<GbPoint3D>& p);
+      int    contains(GbPoint3D* point);
+      void   insert(const GbPoint3D& point, int index);
+      void   clear();
+      void   clearAndTrim();
+      int    containsEqual(const GbPoint3D& point);
+      bool   containsLine(GbPoint3D* point1, GbPoint3D* point2);
+      bool   containsEqualLine(const GbPoint3D& point1, const GbPoint3D& point2);
+      double getX1Minimum();
+      double getX1Maximum();
+      double getX2Minimum();
+      double getX2Maximum();
+      double getX3Minimum();
+      double getX3Maximum();
+      void   calculateValues();
+      int    size();
+      GbPoint3D* getPoint(int index);
+      GbPoint3D* getFirstPoint();
+      GbPoint3D* getLastPoint() ;
+      std::vector<GbPoint3D> getPoints();
+
+   private:
+      double    x1min;
+      double    x1max;
+      double    x2min;
+      double    x2max;
+      double    x3min;
+      double    x3max;
+      bool      consistent;
+      std::vector<GbPoint3D> points;
+
+      void init()
+      {
+         consistent = false;
+         x1min = x2min = x3min = 0.0;
+         x1max = x2max = x3max = 0.0;
+      }
+   };
+   /*=================================================================*/
+   class OldPointSet3
+   {
+   private:
+      int       sizet;
+      double    x1min;
+      double    x1max;
+      double    x2min;
+      double    x2max;
+      double    x3min;
+      double    x3max;
+      bool      consistent;
+      std::vector<GbPoint3D> points;
+
+      void init()
+      {
+         sizet      = 0;
+         x1min      = 0.0;
+         x1max      = 0.0;
+         x2min      = 0.0;
+         x2max      = 0.0;
+         x3min		  = 0.0;
+         x3max      = 0.0;
+         consistent = false;
+         //points   = NULL;
+      };
+
+   public:
+      OldPointSet3(int n)
+      {
+         this->init();
+         this->points.resize(n);
+      }
+      OldPointSet3(std::vector<GbPoint3D> &points)
+      {
+         this->init();
+         this->points.resize(0);//, NULL);
+         this->add(points);
+      };
+      ~OldPointSet3()
+      {
+         //			delete points;
+      };
+      void add(GbPoint3D point)
+         {
+            if(this->sizet>0 && point.equals(&(this->points)[this->sizet-1])) return;
+            if(this->sizet == (int)this->points.size())
+            {
+               std::vector<GbPoint3D> a;
+               a.resize(1+(this->sizet<<1));
+               for(int u=0; u<this->sizet; u++)  { (a)[u] = (points)[u];	}
+               this->points = a;
+            }
+            (this->points)[this->sizet] = point;
+            this->consistent				= false;
+            this->sizet++;
+         }
+         void addUnequal(GbPoint3D *point)
+         {
+            if(this->containsEqual(point) > 0) return;
+            if(this->sizet == (int)this->points.size())
+            {
+               std::vector<GbPoint3D> a;
+               a.resize(1+(this->sizet<<1));
+               for(int u=0; u<this->sizet; u++)  { (a)[u] = (points)[u];	}
+               this->points = a;
+            }
+            (this->points)[this->sizet] = point;
+            this->consistent        = false;
+            this->sizet++;
+         }
+         void add(std::vector<GbPoint3D> &p)
+         {
+            if(this->sizet+p.size() >= this->points.size())
+            {
+               std::vector<GbPoint3D> a;
+               a.resize(this->sizet+p.size());
+               for(int u=0; u<(int)this->points.size(); u++)  { (a)[u] = (this->points)[u];	}
+               this->points = a;
+            }
+            int u = this->sizet;// (int)this->points->size();
+            for(int b=0; b<(int)p.size(); b++)			(this->points)[u++] = (p)[b];
+            //u = this->sizet;
+            //for(int b=0; b<(int)p->size(); b++)
+            //	cout<<(this->points)[u++].toString()<<endl;
+            this->consistent  = false;
+            this->sizet      += (int)p.size();
+         };
+         //		void insert(GbPoint3D *point, int index)
+         //      {
+         //	 if(this.size == this.points.length)
+         //	 {
+         //	    GbPoint3D a[] = new GbPoint3D[1+(this.size<<1)];
+         //	    System.arraycopy(this.points, 0, a, 0, this.size);
+         //	    this.points = a;
+         //	 }
+         //	 System.arraycopy(this.points, index, this.points, index+1, this.size-index);
+         //	 this.points[index] = point;
+         //	 this.consistent    = false;
+         //	 this.size++;
+         //      }
+         //      void delete(GbPoint3D point)
+         //      {
+         //	 for(int i=this.size-1; i>=0; i--) if(this.points[i] == point) this.delete(i);
+         //      }
+         //      void delete(int index)
+         //      {
+         //	 int j = this.size - index - 1;
+         //	 if(j > 0) System.arraycopy(this.points, index + 1, this.points, index, j);
+         //	 this.consistent = false;
+         //	 this.size--;
+         //      }
+         void clear()
+         {
+            this->sizet    = 0;
+            this->consistent = false;
+         }
+         void clearAndTrim()
+         {
+            this->sizet       = 0;
+            this->points.resize(0);
+            this->consistent = false;
+         }
+
+         double getX1Minimum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x1min);
+         }
+         double getX1Maximum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x1max);
+         }
+         double getX2Minimum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x2min);
+         }
+         double getX2Maximum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x2max);
+         }
+         double getX3Minimum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x3min);
+         }
+         double getX3Maximum()
+         {
+            if(!this->consistent) this->calculateValues();
+            return(this->x3max);
+         }
+         void calculateValues()
+         {
+            this->x1min      = 0.0;
+            this->x1max      = 0.0;
+            this->x2min      = 0.0;
+            this->x2max      = 0.0;
+            this->x3min      = 0.0;
+            this->x3max      = 0.0;
+            this->consistent = true;
+
+            if(this->sizet == 0) return;
+
+            this->x1min = (this->points)[0].x1;
+            this->x1max = (this->points)[0].x1;
+            this->x2min = (this->points)[0].x2;
+            this->x2max = (this->points)[0].x2;
+            this->x3min = (this->points)[0].x3;
+            this->x3max = (this->points)[0].x3;
+
+            for(int i=this->sizet-1; i>0; i--)
+            {
+               if((this->points)[i].x1 < this->x1min) this->x1min = (this->points)[i].x1;
+               if((this->points)[i].x1 > this->x1max) this->x1max = (this->points)[i].x1;
+               if((this->points)[i].x2 < this->x2min) this->x2min = (this->points)[i].x2;
+               if((this->points)[i].x2 > this->x2max) this->x2max = (this->points)[i].x2;
+               if((this->points)[i].x3 < this->x3min) this->x3min = (this->points)[i].x3;
+               if((this->points)[i].x3 > this->x3max) this->x3max = (this->points)[i].x3;
+            }
+         };
+
+         int contains(GbPoint3D *point)
+         {
+            int n = 0;
+            for(int i=this->sizet-1; i>=0; i--) if(&(this->points)[i] == point) n++;
+            return(n);
+         };
+         int containsEqual(GbPoint3D *point)
+         {
+            int n = 0;
+            for(int i=this->sizet-1; i>=0; i--) if((this->points)[i].equals(point)) n++;
+            return(n);
+         }
+         bool containsLine(GbPoint3D *point1, GbPoint3D *point2)
+         {
+            for(int i=this->sizet-1; i>=0; i--) if(&(this->points)[i] == point1)
+            {
+               if(i == 0)
+               {
+                  if(&(this->points)[i+1]           == point2) return(true);
+                  if(&(this->points)[this->sizet-1] == point2) return(true);
+               }
+               else if(i == this->sizet-1)
+               {
+                  if(&(this->points)[0]   == point2) return(true);
+                  if(&(this->points)[i-1] == point2) return(true);
+               }
+               else
+               {
+                  if(&(this->points)[i+1] == point2) return(true);
+                  if(&(this->points)[i-1] == point2) return(true);
+               }
+            }
+            return(false);
+         };
+         //      boolean containsEqualLine(GbPoint2D point1, GbPoint2D point2)
+         //      {
+         //	 for(int i=this.size-1; i>=0; i--) if(this.points[i].equals(point1))
+         //	 {
+         //	    if(i == 0)
+         //	    {
+         //	       if(this.points[i+1].equals(point2))         return(true);
+         //	       if(this.points[this.size-1].equals(point2)) return(true);
+         //	    }
+         //	    else if(i == this.size-1)
+         //	    {
+         //	       if(this.points[0].equals(point2))   return(true);
+         //	       if(this.points[i-1].equals(point2)) return(true);
+         //	    }
+         //	    else
+         //	    {
+         //	       if(this.points[i+1].equals(point2)) return(true);
+         //	       if(this.points[i-1].equals(point2)) return(true);
+         //	    }
+         //	 }
+         //	 return(false);
+         //      }
+         GbPoint3D *getPoint(int index)
+         {
+            return(&(this->points)[index]);
+         }
+         GbPoint3D *getFirstPoint()
+         {
+            return(&(this->points)[0]);
+         }
+         GbPoint3D *getLastPoint() { return(&(this->points)[this->sizet-1]); }
+         int size()                { return(this->sizet);      }
+         std::vector<GbPoint3D> getPoints()
+         {
+            points.resize(sizet);
+            return points;
+            //int l = this->sizet;
+            //if(l > 1 && (this->points)[0].equals(&(this->points)[l-1])) l--;
+
+            //vector<GbPoint3D*> *a = new vector<GbPoint3D*>;
+            //a->resize(l, NULL);
+            //for(int u=0; u<l; u++)  { (*a)[u] = &((points)[u]);	}
+            //return(a);
+         }
+      };
+      /*=================================================================*/
+}
+
+#endif //GBSYSTEM3D_H
diff --git a/source/VirtualFluidsCore/Geometry/GbTriFaceMesh3D.cpp b/source/VirtualFluidsCore/Geometry/GbTriFaceMesh3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..70cc36cfd640cd6fe3f93fdfb05e7fd3ec81c58d
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbTriFaceMesh3D.cpp
@@ -0,0 +1,1146 @@
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+#include <numerics/geometry3d/CoordinateTransformation3D.h>
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+#include <basics/utilities/UbRandom.h>
+#include <basics/utilities/UbTiming.h>
+#include <basics/utilities/UbLogger.h>
+
+#include <numerics/geometry3d/KdTree/KdTree.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h>
+
+using namespace std;
+
+GbTriFaceMesh3D::GbTriFaceMesh3D() 
+   :   GbObject3D()
+     , buildVertTriRelationMap(false)
+     , kdTree(NULL)
+     , transX1(0.0)
+     , transX2(0.0)
+     , transX3(0.0)
+     , transferViaFilename(false)
+
+{
+   this->setName("CAB_GbTriFaceMesh3D");
+   this->nodes          = new vector<Vertex>;
+   this->triangles      = new vector<TriFace>;
+   this->consistent     = false;
+   this->kdtreeSplitAlg = KDTREE_SAHPLIT;
+}
+/*=======================================================================*/
+GbTriFaceMesh3D::GbTriFaceMesh3D(string name, vector<Vertex>* nodes, vector<TriFace>* triangles, KDTREE_SPLITAGORITHM splitAlg, bool removeRedundantNodes)
+   :  GbObject3D()
+    , nodes(nodes)
+    , triangles(triangles)
+    , buildVertTriRelationMap(false)
+    , consistent(false)
+    , kdTree(NULL)
+    , kdtreeSplitAlg(splitAlg)
+    , transX1(0.0)
+    , transX2(0.0)
+    , transX3(0.0)
+    , transferViaFilename(false)
+{
+   if( name.empty() ) throw UbException(UB_EXARGS,"no name specified");
+   if( !nodes       ) throw UbException(UB_EXARGS,"no nodes specified");
+   if( !triangles   ) throw UbException(UB_EXARGS,"no triangles specified");
+
+   this->setName(name);
+
+   if(removeRedundantNodes)
+   {
+      this->deleteRedundantNodes(); //dort wird autoamtisch calculateValues() aufgerufen
+   }
+   else
+   {
+      this->calculateValues();
+   }
+}
+/*=======================================================================*/
+GbTriFaceMesh3D::~GbTriFaceMesh3D()
+{
+   if( nodes     ) { delete nodes;     nodes     = NULL; }
+   if( triangles ) { delete triangles; triangles = NULL; }
+   if( kdTree    ) { delete kdTree;    kdTree    = NULL; }
+}
+/*======================================================================*/
+ObObjectCreator* GbTriFaceMesh3D::getCreator()
+{
+   return GbTriFaceMesh3DCreator::getInstance();
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::init()
+{
+   nodes      = NULL;
+   triangles  = NULL;
+   x1min      = 0.0;
+   x1max      = 0.0;
+   x1center   = 0.0;
+   x2min      = 0.0;
+   x2max      = 0.0;
+   x2center   = 0.0;
+   x3min      = 0.0;
+   x3max      = 0.0;
+   x3center   = 0.0;
+   consistent = false;
+}
+/*======================================================================*/
+GbTriFaceMesh3D* GbTriFaceMesh3D::clone()
+{
+   vector<GbTriFaceMesh3D::Vertex>    *newNodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   vector<GbTriFaceMesh3D::TriFace>   *newTriangles = new vector<GbTriFaceMesh3D::TriFace>;
+
+   int numberNodes = (int)this->nodes->size();
+
+   double x,y,z;
+   for(int u=0;u<numberNodes;u++)
+   {
+      x=(*nodes)[u].x;
+      y=(*nodes)[u].y;
+      z=(*nodes)[u].z;
+      newNodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+   }
+   int numberTris  = (int)this->triangles->size();
+   UBLOG(logDEBUG1,"numberTris:"<<numberTris);
+
+   int id1,id2,id3;
+   for(int u=0;u<numberTris;u++)
+   {
+      id1 = (*this->triangles)[u].v1;
+      id2 = (*this->triangles)[u].v2;
+      id3 = (*this->triangles)[u].v3;
+      newTriangles->push_back(GbTriFaceMesh3D::TriFace(id1,id2,id3));
+      //cout<<u<<" - id1,id2,id3:"<<id1<<","<<id2<<","<<id3<<endl;
+   }
+   UBLOG(logDEBUG1,"Tris gelesen");
+
+   GbTriFaceMesh3D* mesh = new GbTriFaceMesh3D("no name", newNodes, newTriangles);
+   UBLOG(logDEBUG1,"mesh cloned ...");
+
+   return mesh;
+}
+
+/*======================================================================*/
+//checks for doppelt nodes und fixed Dreicke die zweimal denselben Knoten haben
+void GbTriFaceMesh3D::deleteRedundantNodes()
+{
+    UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - Nodes before deleting redundant: "<<this->nodes->size());
+
+    map<Vertex,size_t/*new vecIndex*/> vertexMap;
+    map<Vertex,size_t/*new vecIndex*/>::iterator pos;
+    map<Vertex,size_t/*new vecIndex*/>::iterator it;
+    
+    vector<TriFace>& tris     = *this->triangles;
+    vector<Vertex>&  oldNodes = *this->nodes;
+    vector<Vertex>   newNodes;
+
+    for(size_t t=0; t<tris.size(); t++)
+    {
+       if(t%100==0) UBLOG(logDEBUG5,"GbTriFaceMesh3D::deleteRedundantNodes - tri: "<<(t)<<" von "<<tris.size());
+       TriFace& tri = tris[t];
+       //Knoten bereits in neuem node vector?
+       for(int v=0; v<=2; v++)
+       {
+          Vertex& vert = tri.getNode(v,oldNodes);
+          //pos=vertexMap.find( vert );
+          //if( pos==vertexMap.end() )
+          {
+             for(pos=vertexMap.begin();pos!=vertexMap.end();pos++)
+             {
+               Vertex rhs = pos->first;
+             //if(UbMath::inClosedInterval(vert.z,0.01999, 0.02001))
+               if ( fabs(vert.x-rhs.x)<1.E-5 && fabs(vert.y-rhs.y)<1.E-5 && fabs(vert.z-rhs.z)<1.E-5 )
+               {
+                  break;
+               }
+             }
+          }
+          if( pos!=vertexMap.end() ) tri.setNode(v, (int)pos->second);
+          else
+          {
+             newNodes.push_back(vert);
+             int index = (int)newNodes.size()-1;
+             vertexMap[vert] = index;                       
+             tri.setNode(v,index);
+          }
+       }
+    }
+
+    std::swap(*nodes,newNodes);
+
+    UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - Nodes after deleting redundant:"<<this->nodes->size());
+    //
+    //Das geht irgendwie nicht ...
+    //
+    //UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - checking for double triangles !!!");
+    //UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - Triangles before deleting redundant: "<<this->triangles->size());
+    //vector<TriFace> newSingleTris;
+    //newSingleTris.reserve( this->triangles->size() );
+    //for(size_t t=0; t<tris.size(); t++)
+    //{
+    //   Vertex& v1 = tris[t].getNode(0,*nodes); 
+    //   Vertex& v2 = tris[t].getNode(1,*nodes); 
+    //   Vertex& v3 = tris[t].getNode(2,*nodes); 
+
+    //   if(UbMath::greater(std::fabs(v1.x), 0.0634) && UbMath::inClosedInterval(v1.z, 0.01999, 0.02001))
+    //   {
+    //      UBLOG2(logINFO,std::cout, "V1:"<<v1.x<<" "<<v1.y<<" "<<v1.z);
+    //   }
+    //   if(UbMath::greater(std::fabs(v2.x), 0.0634) && UbMath::inClosedInterval(v2.z, 0.01999, 0.02001))
+    //   {
+    //      UBLOG2(logINFO,std::cout, "V2:"<<v2.x<<" "<<v2.y<<" "<<v2.z);
+    //   }
+    //   if(UbMath::greater(std::fabs(v3.x), 0.0634) && UbMath::inClosedInterval(v3.z, 0.01999, 0.02001))
+    //   {
+    //      UBLOG2(logINFO,std::cout, "V3:"<<v3.x<<" "<<v3.y<<" "<<v3.z);
+    //   }
+
+    //   bool inList = false;
+    //   for(size_t u=0; u<newSingleTris.size(); u++)
+    //   {
+    //      Vertex& vn1 = newSingleTris[t].getNode(0,*nodes); 
+    //      Vertex& vn2 = newSingleTris[t].getNode(1,*nodes); 
+    //      Vertex& vn3 = newSingleTris[t].getNode(2,*nodes); 
+
+    //      if(v1==vn1 && v2==vn2 && v3==vn3)      inList = true;
+    //      else if(v1==vn1 && v2==vn3 && v3==vn2) inList = true;
+    //      else if(v1==vn2 && v2==vn3 && v3==vn1) inList = true;
+    //      else if(v1==vn2 && v2==vn1 && v3==vn3) inList = true;
+    //      else if(v1==vn3 && v2==vn1 && v3==vn2) inList = true;
+    //      else if(v1==vn3 && v2==vn2 && v3==vn1) inList = true;
+    //   }
+    //   if(!inList) newSingleTris.push_back(tris[t]);
+    //   else 
+    //      UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - inList !!!!");
+    
+    //}
+    //swap(tris,newSingleTris);
+
+    //UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - Triangles after deleting redundant:"<<this->triangles->size());
+    UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - checking for triangles that have same node several times or are lines!!!");
+    int counter1 = 0;
+    int counter2 = 0;
+    vector<TriFace> newTris;
+    newTris.reserve( this->triangles->size() );
+    for(size_t t=0; t<tris.size(); t++)
+    {
+       Vertex& v1 = tris[t].getNode(0,*nodes); 
+       Vertex& v2 = tris[t].getNode(1,*nodes); 
+       Vertex& v3 = tris[t].getNode(2,*nodes); 
+       if( v1==v2 || v1==v3 || v2==v3 )
+       {
+          counter1++;
+       }
+       else if( tris[t].getArea(*nodes)<1.0E-8 )
+       {
+          counter2++;
+       }
+       else newTris.push_back(tris[t]);
+    }
+    if(counter1)
+    {
+       UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - ### Warning ###: found and removed  "<<counter1<<" triangle with double nodes!");
+    }
+    if(counter2)
+    {
+       UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - ### Warning ###: found and removed  "<<counter2<<" triangle that are lines!") ;
+    }
+    if(!counter1 && !counter2) { UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - alles gut... nix doppelt"); }
+    else swap(tris,newTris);
+    
+    UBLOG(logDEBUG1,"GbTriFaceMesh3D::deleteRedundantNodes - done" );
+    this->calculateValues();
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::setKdTreeSplitAlgorithm(KDTREE_SPLITAGORITHM mode) 
+{ 
+   if(kdTree && mode != this->kdtreeSplitAlg) { delete kdTree; kdTree = NULL; }
+   this->kdtreeSplitAlg = mode; 
+}
+/*======================================================================*/
+   /**
+    * Returns a string representation of this triangular mesh.
+    * @return a string representation of this triangular mesh
+    */
+string GbTriFaceMesh3D::toString()
+{
+	stringstream ss;
+	ss<<"GbTriFaceMesh3D[";
+	ss<<(int)this->triangles->size()<<"-Triangles, "<<(int)this->nodes->size()<<"-Nodes, "<<endl;
+   ss<<"]";
+   return(ss.str());
+}
+/**
+ * Returns the nodes of this triangular mesh.
+ * @return the nodes of this triangular mesh
+ */
+vector<GbTriFaceMesh3D::Vertex>* GbTriFaceMesh3D::getNodes()       {  return this->nodes;   }
+/**
+ * Returns the triangles of this triangular mesh.
+ * @return the triangles of this triangular mesh
+ */
+vector<GbTriFaceMesh3D::TriFace>* GbTriFaceMesh3D::getTriangles()  { return this->triangles;  }
+/**
+ * Returns the center x1 coordinate of this triangular mesh.
+ * @return the center x1 coordinate of this triangular mesh
+ */
+double GbTriFaceMesh3D::getVolume()
+{
+   vector<Vertex>&  vertices = *nodes;
+   vector<TriFace>& tris     = *triangles;
+
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3, G3i;
+   //double rSP1 = 0.0;double rSP2 = 0.0;double rSP3 = 0.0;
+   double volume = 0.0;
+   for(size_t t=0; t<tris.size(); t++)
+   {
+      TriFace& triangle = tris[t];
+      x1     = triangle.getV1x(vertices); y1 = triangle.getV1y(vertices); z1 = triangle.getV1z(vertices);
+      x2     = triangle.getV2x(vertices); y2 = triangle.getV2y(vertices); z2 = triangle.getV2z(vertices);
+      x3     = triangle.getV3x(vertices); y3 = triangle.getV3y(vertices); z3 = triangle.getV3z(vertices);
+      G3i    = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+   }
+   return volume;
+}
+/*===============================================*/
+UbTupleDouble3 GbTriFaceMesh3D::calculateCenterOfGravity()
+{
+   vector<Vertex>&  vertices = *nodes;
+   vector<TriFace>& tris     = *triangles;
+   
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3;
+   double G3i;
+   double rSP1 = 0.0, rSP2 = 0.0, rSP3 = 0.0, volume = 0.0;
+   
+   for(size_t t=0; t<tris.size(); t++)
+   {
+      TriFace& triangle = tris[t];
+      x1     = triangle.getV1x(vertices); y1 = triangle.getV1y(vertices); z1 = triangle.getV1z(vertices);
+      x2     = triangle.getV2x(vertices); y2 = triangle.getV2y(vertices); z2 = triangle.getV2z(vertices);
+      x3     = triangle.getV3x(vertices); y3 = triangle.getV3y(vertices); z3 = triangle.getV3z(vertices);
+      G3i    = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+      rSP1   = rSP1+G3i*(x1+x2+x3);
+      rSP2   = rSP2+G3i*(y1+y2+y3);
+      rSP3   = rSP3+G3i*(z1+z2+z3);
+   }
+   rSP1 = rSP1/(24.0*volume);
+   rSP2 = rSP2/(24.0*volume);
+   rSP3 = rSP3/(24.0*volume);
+
+   return UbTupleDouble3(rSP1, rSP2, rSP3);
+}
+/*===============================================*/
+UbTupleDouble6 GbTriFaceMesh3D::calculateMomentOfInertia(double rhoP)
+{
+   vector<Vertex>& vertices = *nodes;
+
+   double x1,x2,x3,y1,y2,y3,z1,z2,z3;
+   double G3i;
+   double xx,yy,zz,xy,yz,zx;
+   double rSP1 = 0.0;double rSP2 = 0.0;double rSP3 = 0.0;
+   double volume = 0.0;
+   double top11 = 0.0;double top22 = 0.0;double top33 = 0.0;
+   double top12 = 0.0;double top23 = 0.0;double top13 = 0.0;
+   int size = (int)this->triangles->size();
+   for(int u=0; u<size;u++)
+   {
+      TriFace& triangle = (*this->triangles)[u];
+      x1 = triangle.getV1x(vertices); y1 = triangle.getV1y(vertices); z1 = triangle.getV1z(vertices);
+      x2 = triangle.getV2x(vertices); y2 = triangle.getV2y(vertices); z2 = triangle.getV2z(vertices);
+      x3 = triangle.getV3x(vertices); y3 = triangle.getV3y(vertices); z3 = triangle.getV3z(vertices);
+      G3i = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      volume = volume+G3i/6.0;
+      rSP1 = rSP1+G3i*(x1+x2+x3);
+      rSP2 = rSP2+G3i*(y1+y2+y3);
+      rSP3 = rSP3+G3i*(z1+z2+z3);
+   }
+   rSP1 = rSP1/(24.0*volume);
+   rSP2 = rSP2/(24.0*volume);
+   rSP3 = rSP3/(24.0*volume);
+
+   double x1s = 0.0;//rSP1;//0.0;//
+   double x2s = 0.0;//rSP2;//0.0;//
+   double x3s = 0.0;//rSP3;//0.0;//
+
+   for(int u=0; u<size;u++)
+   {
+      TriFace& triangle = (*this->triangles)[u];
+      x1 = triangle.getV1x(vertices)-x1s;
+      y1 = triangle.getV1y(vertices)-x2s;
+      z1 = triangle.getV1z(vertices)-x3s;
+      x2 = triangle.getV2x(vertices)-x1s;
+      y2 = triangle.getV2y(vertices)-x2s;
+      z2 = triangle.getV2z(vertices)-x3s;
+      x3 = triangle.getV3x(vertices)-x1s;
+      y3 = triangle.getV3y(vertices)-x2s;
+      z3 = triangle.getV3z(vertices)-x3s;
+      G3i = x1*(y2*z3-z2*y3)+y1*(z2*x3-x2*z3)+z1*(x2*y3-y2*x3);
+      //rSP1 = rSP1+G3i*(x1+x2+x3)/(24.0*volume);
+      //rSP2 = rSP2+G3i*(y1+y2+y3)/(24.0*volume);
+      //rSP3 = rSP3+G3i*(z1+z2+z3)/(24.0*volume);
+      xx = x1*x1+x2*x2+x3*x3+x1*x2+x2*x3+x3*x1;
+      yy = y1*y1+y2*y2+y3*y3+y1*y2+y2*y3+y3*y1;
+      zz = z1*z1+z2*z2+z3*z3+z1*z2+z2*z3+z3*z1;
+      top11 = top11+(yy+zz)*rhoP*G3i/60.;
+      top22 = top22+(xx+zz)*rhoP*G3i/60.;
+      top33 = top33+(yy+xx)*rhoP*G3i/60.;
+      xy = 2.0*(x1*y1+x2*y2+x3*y3)+x2*y3+x3*y1+x1*y2+x3*y2+x1*y3+x2*y1;
+      yz = 2.0*(y1*z1+y2*z2+y3*z3)+y2*z3+y3*z1+y1*z2+y3*z2+y1*z3+y2*z1;
+      zx = 2.0*(z1*x1+z2*x2+z3*x3)+z2*x3+z3*x1+z1*x2+z3*x2+z1*x3+z2*x1;
+      top12 = top12-xy*rhoP*G3i/120.;
+      top23 = top23-yz*rhoP*G3i/120.;
+      top13 = top13-zx*rhoP*G3i/120.;
+   }
+   //Satz von Steiner ...
+   top11 = top11-rhoP*volume*(rSP2*rSP2+rSP3+rSP3);
+   top22 = top22-rhoP*volume*(rSP3*rSP3+rSP1*rSP1);
+   top33 = top33-rhoP*volume*(rSP1*rSP1+rSP2*rSP2);
+   top12 = top12+rhoP*volume*rSP1*rSP2;
+   top23 = top23+rhoP*volume*rSP2*rSP3;
+   top13 = top13+rhoP*volume*rSP3*rSP1;
+
+   cout<<"Volume:"<<volume<<"\n Traegheitsmomente:\n";
+   cout<<" top11:"<<top11<<" top22:"<<top22<<" top33:"<<top33<<endl;
+   cout<<" top12:"<<top12<<" top23:"<<top23<<" top13:"<<top13<<endl;
+
+   return UbTupleDouble6(top11,top22,top33,top12,top23,top13);
+}
+/*==============================================================*/
+void GbTriFaceMesh3D::calculateValues()
+{
+   relationVertTris.clear();
+
+   if( nodes->empty() )
+   {
+      x1min = x1max = x2min = x2max = x3min = x3max = 0.0;
+   }
+   else
+   {
+      Vertex& v = (*nodes)[0];
+      x1min = x1max = v.x;
+      x2min = x2max = v.y;
+      x3min = x3max = v.z;
+
+      for(size_t i=1; i<this->nodes->size(); i++)
+      {
+         Vertex& v1 = (*nodes)[i];
+         
+         x1min = UbMath::min<double>(x1min,v1.x);
+         x2min = UbMath::min<double>(x2min,v1.y);
+         x3min = UbMath::min<double>(x3min,v1.z);
+         
+         x1max = UbMath::max<double>(x1max,v1.x);
+         x2max = UbMath::max<double>(x2max,v1.y);
+         x3max = UbMath::max<double>(x3max,v1.z);
+      }
+      x1center = 0.5 * (x1min + x1max );
+      x2center = 0.5 * (x2min + x2max );
+      x3center = 0.5 * (x3min + x3max );
+      
+      vector<TriFace>& tris  = *this->triangles;
+      vector<Vertex>&  verts = *this->nodes;
+      for(size_t i=0; i<this->triangles->size(); i++)
+      {
+         tris[i].calculateNormal(verts);
+      }
+      //relation Vertex <-> Triangle ermitteln
+      if(buildVertTriRelationMap)
+      {
+         for(size_t t=0; t<tris.size(); t++)
+         {
+            TriFace& tri = tris[t];
+            relationVertTris.insert( make_pair( &verts[tri.v1], &tri) );
+            relationVertTris.insert( make_pair( &verts[tri.v2], &tri) );
+            relationVertTris.insert( make_pair( &verts[tri.v3], &tri) );
+         }
+      }
+   }
+   if(kdTree)
+   { 
+      delete kdTree; 
+      kdTree=NULL; 
+   }
+   
+   this->consistent = true;
+}
+/*=========================================================================*/
+std::vector<GbTriFaceMesh3D::TriFace*> GbTriFaceMesh3D::getTrianglesForVertex(Vertex* vertex)
+{
+   if(!buildVertTriRelationMap) { buildVertTriRelationMap=true; consistent = false;}
+   if(!consistent) this->calculateValues();
+
+   typedef std::multimap<Vertex*,TriFace*>::iterator Iterator;
+   pair<Iterator,Iterator> objRange = relationVertTris.equal_range(vertex);
+
+   std::vector<TriFace*> tmpTris;
+   for(Iterator pos=objRange.first; pos!=objRange.second; ++pos) 
+      tmpTris.push_back( pos->second );
+
+   return tmpTris;
+}
+/*=======================================================*/
+void GbTriFaceMesh3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3) 
+{
+   this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() );
+}
+
+/*======================================================================*/
+void GbTriFaceMesh3D::scale(const double& sx1, const double& sx2, const double& sx3)
+{
+   CoordinateTransformation3D trafoForw(this->getX1Centroid(), this->getX2Centroid(), this->getX3Centroid(), 1.0, 1.0, 1.0, 0.0, 0.0, 0.0);
+   CoordinateTransformation3D trafoBack(this->getX1Centroid(), this->getX2Centroid(), this->getX3Centroid(), sx1, sx2, sx3, 0, 0, 0);
+
+   vector<Vertex>& vertices = *nodes;
+   for(size_t i=0; i<vertices.size(); i++)
+   {
+      Vertex& v = vertices[i];
+      double p1x1 = trafoForw.transformForwardToX1Coordinate(v.x, v.y, v.z);
+      double p1x2 = trafoForw.transformForwardToX2Coordinate(v.x, v.y, v.z);
+      double p1x3 = trafoForw.transformForwardToX3Coordinate(v.x, v.y, v.z);
+      v.x = (float)trafoBack.transformBackwardToX1Coordinate(p1x1, p1x2, p1x3);
+      v.y = (float)trafoBack.transformBackwardToX2Coordinate(p1x1, p1x2, p1x3);
+      v.z = (float)trafoBack.transformBackwardToX3Coordinate(p1x1, p1x2, p1x3);
+   }
+   this->calculateValues();
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::rotate(const double& alpha, const double& beta, const double& gamma)
+{
+   CoordinateTransformation3D trafoForw(this->getX1Centroid(), this->getX2Centroid(), this->getX3Centroid(), 1.0, 1.0, 1.0, 0.0, 0.0, 0.0);
+   CoordinateTransformation3D trafoBack(this->getX1Centroid(), this->getX2Centroid(), this->getX3Centroid(), 1.0, 1.0, 1.0, alpha, beta, gamma);
+
+   vector<Vertex>& vertices = *nodes;
+   for(size_t i=0; i<vertices.size(); i++)
+   {
+      Vertex& v = vertices[i];
+      double p1x1 = trafoForw.transformForwardToX1Coordinate(v.x, v.y, v.z);
+      double p1x2 = trafoForw.transformForwardToX2Coordinate(v.x, v.y, v.z);
+      double p1x3 = trafoForw.transformForwardToX3Coordinate(v.x, v.y, v.z);
+      v.x = (float)trafoBack.transformBackwardToX1Coordinate(p1x1, p1x2, p1x3);
+      v.y = (float)trafoBack.transformBackwardToX2Coordinate(p1x1, p1x2, p1x3);
+      v.z = (float)trafoBack.transformBackwardToX3Coordinate(p1x1, p1x2, p1x3);
+   }
+   this->calculateValues();
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::rotateAroundPoint(const double& px1, const double& px2, const double& px3, const double& alpha, const double& beta, const double& gamma)
+{
+   CoordinateTransformation3D trafoForw(px1, px2, px3, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0);
+   CoordinateTransformation3D trafoBack(px1, px2, px3, 1.0, 1.0, 1.0, alpha, beta, gamma);
+
+   vector<Vertex>& vertices = *nodes;
+   for(size_t i=0; i<vertices.size(); i++)
+   {
+      Vertex& v = vertices[i];
+      double p1x1 = trafoForw.transformForwardToX1Coordinate(v.x, v.y, v.z);
+      double p1x2 = trafoForw.transformForwardToX2Coordinate(v.x, v.y, v.z);
+      double p1x3 = trafoForw.transformForwardToX3Coordinate(v.x, v.y, v.z);
+      v.x = (float)trafoBack.transformBackwardToX1Coordinate(p1x1, p1x2, p1x3);
+      v.y = (float)trafoBack.transformBackwardToX2Coordinate(p1x1, p1x2, p1x3);
+      v.z = (float)trafoBack.transformBackwardToX3Coordinate(p1x1, p1x2, p1x3);
+   }
+   this->calculateValues();
+}
+
+
+/*======================================================================*/
+void GbTriFaceMesh3D::translate(const double& x1, const double& x2, const double& x3)
+{
+   vector<Vertex>& vertices = *nodes;
+   for(size_t i=0; i<vertices.size(); i++)
+   {
+      Vertex& v = vertices[i];
+      v.x += static_cast<float>(x1);
+      v.y += static_cast<float>(x2);
+      v.z += static_cast<float>(x3);
+   }
+   this->calculateValues();
+}
+/*======================================================================*/
+vector<GbTriangle3D*> GbTriFaceMesh3D::getSurfaceTriangleSet()
+{
+   //SirAnn: eine miese Speicherlochmethode
+   //        hier werden dynmamische Objekte angelegt 
+   //        mit sowas rechnet von aussen kein Mensch!!!
+   vector<GbTriangle3D*> tris( triangles->size() );
+
+   for(size_t i=0; i<this->triangles->size(); i++)
+   {
+      Vertex& v1 = (*nodes)[(*triangles)[i].v1];
+      Vertex& v2 = (*nodes)[(*triangles)[i].v2];
+      Vertex& v3 = (*nodes)[(*triangles)[i].v3];
+
+      tris[i] = new GbTriangle3D(  new GbPoint3D(v1.x,v1.y,v1.z)
+                                 , new GbPoint3D(v2.x,v2.y,v2.z)
+                                 , new GbPoint3D(v3.x,v3.y,v3.z) );
+   }
+   return tris;
+}
+/*=======================================================*/
+void GbTriFaceMesh3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& pts, vector<UbTupleInt3>& tris)
+{
+   for(int i=0; i<(int)this->triangles->size(); i++)
+   {
+      Vertex& v1 = (*nodes)[(*triangles)[i].v1];
+      Vertex& v2 = (*nodes)[(*triangles)[i].v2];
+      Vertex& v3 = (*nodes)[(*triangles)[i].v3];
+      pts.push_back( makeUbTuple(v1.x,v1.y,v1.z));
+      pts.push_back( makeUbTuple(v2.x,v2.y,v2.z));
+      pts.push_back( makeUbTuple(v3.x,v3.y,v3.z));
+
+      tris.push_back( makeUbTuple( 3*i, 3*i+1, 3*i+2) );
+   }
+}
+/*======================================================================*/
+//bool GbTriFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, int counter)
+//{
+//
+//
+//   if( !nodes->empty() )
+//   {
+//      //Baum erstellen, wen noch keiner vorhanden
+//      if( !kdTree)
+//      {
+//         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
+//         UbTimer timer; timer.start();
+//         if(kdtreeSplitAlg == KDTREE_SAHPLIT     ) 
+//         {
+//            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
+//            this->kdTree = new Kd::Tree<double>( *this, Kd::SAHSplit<double>()            );
+//         }
+//         else if(kdtreeSplitAlg == KDTREE_SPATIALSPLIT)
+//         {
+//            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SpatialMedianSplit");
+//            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() ); 
+//         }
+//         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
+//         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+//      }
+//
+//      //eigentlicher PIO-Test
+//      //int iSec;
+//      //for(int i=0; i<100; i++)
+//      //{
+//      //   Kd::Ray<double> ray(  x1, x2, x3  //, 1, 0 ,0 );
+//      //                        , ( x1 < x1center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+//      //                        , ( x2 < x2center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+//      //                        , ( x3 < x3center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) );
+//      //                        
+//      //   iSec = kdTree->intersectRay( ray, Kd::CountRayIntersectionHandler<double>() );
+//      //     
+//      //   if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+//      //   {
+//      //      if(iSec == Kd::Intersection::ON_BOUNDARY )
+//      //      {
+//      //         return true;
+//      //      }
+//      //      return (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+//      //   }
+//      //   UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+//      //}
+//      //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+//      int iSec1,iSec2;
+//         
+//      Kd::Ray<double> ray1(  x1, x2, x3, 1.0, 0.0 ,0.0 );
+//      iSec1 = kdTree->intersectRay( ray1, Kd::CountRayIntersectionHandler<double>() );
+//      Kd::Ray<double> ray2(  x1, x2, x3, -1.0, 0.0 ,0.0 );
+//      iSec2 = kdTree->intersectRay( ray2, Kd::CountRayIntersectionHandler<double>() );
+//
+//      if(iSec1 == Kd::Intersection::ON_BOUNDARY || iSec2 == Kd::Intersection::ON_BOUNDARY)
+//      {
+//         return true;
+//      }
+//      if( iSec1 == Kd::Intersection::INTERSECT_EDGE && iSec2 == Kd::Intersection::INTERSECT_EDGE) 
+//      {
+//         UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.INTERSECT_EDGE");
+//         double eps = UbMath::getEqualityEpsilon<float>()*1000.0;
+//         if (counter>100) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+//         return this->isPointInGbObject3D(x1+eps, x2+eps, x3+eps,(counter+1)); 
+//      }
+//      else if( iSec1 == Kd::Intersection::INTERSECT_EDGE)
+//      {
+//         return (iSec2&1);  
+//      }
+//      else if( iSec2 == Kd::Intersection::INTERSECT_EDGE)
+//      {
+//         return (iSec1&1);  
+//      }
+//      else
+//      {
+//         if((iSec1&1) != (iSec2&1))
+//         {
+//            UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.iSec1&1 != iSec2&1");
+//            double eps = UbMath::getEqualityEpsilon<float>()*1000.0;
+//            if (counter>100) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+//            return this->isPointInGbObject3D(x1+eps, x2+eps, x3+eps,(counter+1));
+//         }
+//         return iSec1&1;
+//      }
+//      //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+//
+//   }
+//   return false;
+//}
+bool GbTriFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, int counter)
+{
+
+
+   if( !nodes->empty() )
+   {
+      //Baum erstellen, wen noch keiner vorhanden
+      if( !kdTree)
+      {
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
+         UbTimer timer; timer.start();
+         if(kdtreeSplitAlg == KDTREE_SAHPLIT     ) 
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SAHSplit<double>()            );
+         }
+         else if(kdtreeSplitAlg == KDTREE_SPATIALSPLIT)
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SpatialMedianSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() ); 
+         }
+         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+      }
+
+      //eigentlicher PIO-Test
+      //int iSec;
+      //for(int i=0; i<100; i++)
+      //{
+      //   Kd::Ray<double> ray(  x1, x2, x3  //, 1, 0 ,0 );
+      //                        , ( x1 < x1center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+      //                        , ( x2 < x2center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+      //                        , ( x3 < x3center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) );
+      //                        
+      //   iSec = kdTree->intersectRay( ray, Kd::CountRayIntersectionHandler<double>() );
+      //     
+      //   if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+      //   {
+      //      if(iSec == Kd::Intersection::ON_BOUNDARY )
+      //      {
+      //         return true;
+      //      }
+      //      return (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+      //   }
+      //   UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+      //}
+      //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+      int iSec1,iSec2;
+      double eps = 0.05;        
+      Kd::Ray<double> ray1(  x1, x2, x3, 1.0+eps*((double)counter), eps*((double)counter) ,eps*((double)counter) );
+      iSec1 = kdTree->intersectRay( ray1, Kd::CountRayIntersectionHandler<double>() );
+      Kd::Ray<double> ray2(  x1, x2, x3, -1.0-eps*((double)counter), -eps*((double)counter) ,-eps*((double)counter) );
+ 
+      iSec2 = kdTree->intersectRay( ray2, Kd::CountRayIntersectionHandler<double>() );
+
+      if(iSec1 == Kd::Intersection::ON_BOUNDARY || iSec2 == Kd::Intersection::ON_BOUNDARY)
+      {
+         return true;
+      }
+      if( iSec1 == Kd::Intersection::INTERSECT_EDGE && iSec2 == Kd::Intersection::INTERSECT_EDGE) 
+      {
+         //UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.INTERSECT_EDGE");
+
+         if (counter>20) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+         return this->isPointInGbObject3D(x1, x2, x3,(counter+1)); 
+      }
+      else if( iSec1 == Kd::Intersection::INTERSECT_EDGE)
+      {
+         return (iSec2&1);  
+      }
+      else if( iSec2 == Kd::Intersection::INTERSECT_EDGE)
+      {
+         return (iSec1&1);  
+      }
+      else
+      {
+         if((iSec1&1) != (iSec2&1))
+         {
+            //UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.iSec1&1 != iSec2&1");
+
+            if (counter>20) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+            return this->isPointInGbObject3D(x1, x2, x3,(counter+1));
+         }
+         return iSec1&1;
+      }
+      //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+
+   }
+   return false;
+}
+/*======================================================================*/
+bool GbTriFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3)
+{
+  int counter=0;
+
+   if( !nodes->empty() )
+   {
+      //Baum erstellen, wen noch keiner vorhanden
+      if( !kdTree)
+      {
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
+         UbTimer timer; timer.start();
+         if(kdtreeSplitAlg == KDTREE_SAHPLIT     ) 
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SAHSplit<double>()            );
+         }
+         else if(kdtreeSplitAlg == KDTREE_SPATIALSPLIT)
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SpatialMedianSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() ); 
+         }
+         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+      }
+
+      //eigentlicher PIO-Test
+      int iSec;
+      for(int i=0; i<100; i++)
+      {
+         Kd::Ray<double> ray(  x1, x2, x3  //, 1, 0 ,0 );
+                              , ( x1 < x1center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+                              , ( x2 < x2center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) )
+                              , ( x3 < x3center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) );
+                              
+         iSec = kdTree->intersectRay( ray, Kd::CountRayIntersectionHandler<double>() );
+           
+         if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+         {
+            if(iSec == Kd::Intersection::ON_BOUNDARY )
+            {
+               return true;
+            }
+            return (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+         }
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+      }
+      throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+
+   //   int iSec1,iSec2;
+   //      
+   //   Kd::Ray<double> ray1(  x1, x2, x3, 1.0, 0.0 ,0.0 );
+   //   iSec1 = kdTree->intersectRay( ray1, Kd::CountRayIntersectionHandler<double>() );
+   //   Kd::Ray<double> ray2(  x1, x2, x3, -1.0, 0.0 ,0.0 );
+   //   iSec2 = kdTree->intersectRay( ray2, Kd::CountRayIntersectionHandler<double>() );
+
+   //   if(iSec1 == Kd::Intersection::ON_BOUNDARY || iSec2 == Kd::Intersection::ON_BOUNDARY)
+   //   {
+   //      return true;
+   //   }
+   //   if( iSec1 == Kd::Intersection::INTERSECT_EDGE && iSec2 == Kd::Intersection::INTERSECT_EDGE) 
+   //   {
+   //      //UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.INTERSECT_EDGE");
+   //      double eps = UbMath::getEqualityEpsilon<double>();
+   //      if (counter>100) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+   //      return this->isPointInGbObject3D(x1+eps, x2+eps, x3+eps,(counter+1)); 
+   //   }
+   //   else if( iSec1 == Kd::Intersection::INTERSECT_EDGE)
+   //   {
+   //      return (iSec2&1);  
+   //   }
+   //   else if( iSec2 == Kd::Intersection::INTERSECT_EDGE)
+   //   {
+   //      return (iSec1&1);  
+   //   }
+   //   else
+   //   {
+   //      if((iSec1&1) != (iSec2&1))
+   //      {
+   //         UBLOG(logINFO, "GbTriFaceMesh3D.isPointInGbObject3D.iSec1&1 != iSec2&1");
+   //         double eps = UbMath::getEqualityEpsilon<double>();
+   //         if (counter>100) {return(iSec1&1);  UBLOG(logINFO, "NACH 100 Iterationen Eps umsetzen aufgegeben!");}
+   //         return this->isPointInGbObject3D(x1+eps, x2+eps, x3+eps,(counter+1));
+   //      }
+   //      return iSec1&1;
+   //   }
+   //   //throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+
+   }
+   return false;
+}
+/*======================================================================*/
+bool GbTriFaceMesh3D::isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)
+{
+   if( !nodes->empty() )
+   {
+      //Baum erstellen, wen noch keiner vorhanden
+      if( !kdTree)
+      {
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
+         UbTimer timer; timer.start();
+         if(kdtreeSplitAlg == KDTREE_SAHPLIT     ) 
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SAHSplit<double>()            );
+         }
+         else if(kdtreeSplitAlg == KDTREE_SPATIALSPLIT)
+         {
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SpatialMedianSplit");
+            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() ); 
+         }
+         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
+         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+      }
+
+      //eigentlicher PIO-Test
+      int iSec;
+      for(int i=0; i<100; i++)
+      {
+         Kd::Ray<double> ray(  x1, x2, x3 
+                            , float( ( x1 < x1center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) )
+                            , float( ( x2 < x2center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) )
+                            , float( ( x3 < x3center ? UbRandom::rand(-1.0,-0.001, 10) : UbRandom::rand(0.001, 1.0, 10) ) ) );
+
+         iSec = kdTree->intersectRay( ray, Kd::CountRayIntersectionHandler<double>()    );
+
+         if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+         {
+            if(iSec == Kd::Intersection::ON_BOUNDARY )
+            {
+               pointIsOnBoundary = true;
+               return true;
+            }
+            pointIsOnBoundary = false;
+            return (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+         }
+      }
+
+      throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+   }
+   
+   return false;
+}
+/*======================================================================*/
+GbLine3D* GbTriFaceMesh3D::createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2)
+{
+   throw UbException(UB_EXARGS,"not implemented");
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::write(UbFileOutput* out)
+{
+   out->writeString(this->getCreator()->getTypeID());
+   out->writeInteger((int)kdtreeSplitAlg);
+   out->writeBool(transferViaFilename);
+
+   if(!transferViaFilename)
+   {
+      //nodes
+      vector<Vertex>& vertices = *nodes;
+      out->writeSize_t( nodes->size() );
+      out->writeLine();
+      for(size_t i=0; i<vertices.size(); i++)
+      {
+         Vertex& v = vertices[i];
+         out->writeFloat(v.x);
+         out->writeFloat(v.y);
+         out->writeFloat(v.z);
+         out->writeLine();
+      }
+      
+      //triangles
+      vector<TriFace>& tris = *triangles;
+      out->writeSize_t( tris.size() );
+      out->writeLine();
+      for(size_t i=0; i<tris.size(); i++)
+      {
+         TriFace& t = tris[i];
+         out->writeInteger(t.v1);
+         out->writeInteger(t.v2);
+         out->writeInteger(t.v3);
+         out->writeLine();
+      }
+   }
+   else
+   {
+      out->writeString(filename);
+      out->writeLine();
+      out->writeDouble(transX1);
+      out->writeDouble(transX2);
+      out->writeDouble(transX3);
+
+   }
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::read(UbFileInput* in)
+{
+   kdtreeSplitAlg =  (KDTREE_SPLITAGORITHM)in->readInteger();
+   transferViaFilename = in->readBool();
+
+   if(!transferViaFilename)
+   {
+      if(!nodes) nodes = new vector<Vertex>;
+      //nodes
+      vector<Vertex>& vertices = *nodes;
+      vertices.resize( in->readSize_t( ) );
+      in->readLine();
+      for(size_t i=0; i<vertices.size(); i++)
+      {
+         Vertex& v = vertices[i];
+         v.x = in->readFloat();
+         v.y = in->readFloat();
+         v.z = in->readFloat();
+         in->readLine();
+      }
+
+      //triangles
+      if(!triangles) triangles = new vector<TriFace>;
+      vector<TriFace>& tris = *triangles;
+      tris.resize( in->readSize_t( ) );
+      in->readLine();
+      for(size_t i=0; i<tris.size(); i++)
+      {
+         TriFace& t = tris[i];
+         t.v1 = in->readInteger();
+         t.v2 = in->readInteger();
+         t.v3 = in->readInteger();
+         in->readLine();
+      }
+
+      this->calculateValues();
+   }
+   else
+   {
+      filename = in->readString();
+      in->readLine();
+      transX1 = in->readDouble();
+      transX2 = in->readDouble();
+      transX3 = in->readDouble();
+
+      this->readMeshFromSTLFile(filename, true);
+      this->translate(transX1,transX2,transX3);
+   }
+}
+/*======================================================================*/
+UbTuple<string, string> GbTriFaceMesh3D::writeMesh(string filename, WbWriter* writer, bool writeNormals, vector< string >* datanames, std::vector< std::vector < double > >* nodedata )
+{
+   UBLOG(logINFO, "GbTriFaceMesh3D::writeMesh ");
+
+   vector<UbTupleFloat3 > triNodes(nodes->size());
+   vector<UbTupleInt3 >   tris(triangles->size());
+
+   for(size_t i=0; i<nodes->size(); i++)
+      triNodes[i] = makeUbTuple( (*nodes)[i].x, (*nodes)[i].y, (*nodes)[i].z );
+
+   for(size_t i=0; i<triangles->size(); i++)
+      tris[i] = makeUbTuple( (*triangles)[i].v1, (*triangles)[i].v2, (*triangles)[i].v3 ) ;
+
+   UbTuple<string, string> filenames("","");
+
+   if( !datanames || datanames->empty() || !nodedata  )
+   {
+      val<1>(filenames) = writer->writeTriangles(filename,triNodes,tris);
+   }
+   else
+   {
+      val<1>(filenames) = writer->writeTrianglesWithNodeData(filename,triNodes,tris,*datanames,*nodedata);
+   }
+
+   if(writeNormals)
+   {
+      vector<UbTupleFloat3 > lineNodes(triangles->size()*2);
+      vector<UbTupleInt2 >   lines(triangles->size());
+      for(size_t i=0; i<triangles->size(); i++)
+      {
+         TriFace& triangle = (*triangles)[i];
+         lineNodes[i*2  ] = makeUbTuple( triangle.getX1Centroid(*nodes)
+                                        ,triangle.getX2Centroid(*nodes)
+                                        ,triangle.getX3Centroid(*nodes));
+
+         lineNodes[i*2+1] = makeUbTuple( (float)(triangle.getX1Centroid(*nodes)+1.0*triangle.nx)
+                                        ,(float)(triangle.getX2Centroid(*nodes)+1.0*triangle.ny)
+                                        ,(float)(triangle.getX3Centroid(*nodes)+1.0*triangle.nz));
+
+         lines[i] = makeUbTuple((int)i*2,(int)i*2+1);
+      }
+      val<2>(filenames) = writer->writeLines(filename+"_normals",lineNodes,lines);
+   }
+
+   return filenames;
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::writeMeshPly( const std::string& filename)
+{
+   ofstream out(filename.c_str() );
+   if( !out )
+      throw UbException(UB_EXARGS, "couldn't open " + filename);
+
+   out << "ply" << endl;
+   out << "format ascii 1.0" << endl;
+   out << "element vertex " << (int)nodes->size() << endl;
+   out << "property float x" << endl;
+   out << "property float y" << endl;
+   out << "property float z" << endl;
+   out << "element face " << (int)triangles->size() << endl;
+   out << "property list uchar int vertex_indices" << endl;
+   out << "end_header" << endl;
+
+   for(size_t i=0; i<nodes->size(); i++)
+      out << (*nodes)[i].x << " " << (*nodes)[i].y << " " << (*nodes)[i].z << endl;
+
+   for(size_t i=0; i<triangles->size(); i++)
+      out << "3 " << (*triangles)[i].v1 << " " << (*triangles)[i].v2 << " " << (*triangles)[i].v3 << endl;
+}
+/*======================================================================*/
+void GbTriFaceMesh3D::readMeshFromSTLFile(string filename, bool removeRedundantNodes)
+{
+   UBLOG(logDEBUG1,"GbTriFaceMesh3DCreator::readMeshFromSTLFile !!! Dieses Format hat leider redundante Knoten ...");
+
+   UbFileInputASCII in(filename);
+   //this->nodes     = new vector<GbTriFaceMesh3D::Vertex>;
+   //this->triangles = new vector<GbTriFaceMesh3D::TriFace>;
+   string dummy;
+
+   double x, y, z;
+   int nr=0;
+
+   in.readLine();
+   while(dummy!="endsolid")
+   {
+      in.readLine();
+      in.readLine();
+      dummy = in.readString();
+      if(dummy!="vertex") throw UbException(UB_EXARGS,"no vertex format");
+      x=in.readDouble();
+      y=in.readDouble();
+      z=in.readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in.readLine();
+      in.readString();
+      x=in.readDouble();
+      y=in.readDouble();
+      z=in.readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      in.readLine();
+      in.readString();
+      x=in.readDouble();
+      y=in.readDouble();
+      z=in.readDouble();
+      nodes->push_back(GbTriFaceMesh3D::Vertex((float)x,(float)y,(float)z));
+      triangles->push_back(GbTriFaceMesh3D::TriFace(nr,nr+1,nr+2));
+      in.readLine();
+      in.readLine();
+      in.readLine();
+      dummy = in.readString();
+      nr+=3;
+   }
+   if(removeRedundantNodes)
+   {
+      this->deleteRedundantNodes(); //dort wird autoamtisch calculateValues() aufgerufen
+   }
+   else
+   {
+      this->calculateValues();
+   }
+}
diff --git a/source/VirtualFluidsCore/Geometry/GbTriFaceMesh3D.h b/source/VirtualFluidsCore/Geometry/GbTriFaceMesh3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..05c3635e95a5d983119a84c77e02eed2fc35856d
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbTriFaceMesh3D.h
@@ -0,0 +1,384 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBTRIFACEMESH3D_H
+#define GBTRIFACEMESH3D_H
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/writer/WbWriter.h>
+
+#include <basics/memory/MbSmartPtr.h>
+
+#include <numerics/geometry3d/GbPoint3D.h> 
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbTriFaceMesh3D;
+typedef VFSharedPtr<GbTriFaceMesh3D> GbTriFaceMesh3DPtr;
+
+
+namespace Kd 
+{ 
+   template< typename T>  class Tree; 
+   template< typename T > class SplitAlgorithm;
+   template< typename T > class RayIntersectionHandler;
+}
+
+
+/*=========================================================================*/
+/* GbTriFaceMesh3D                                                                  */
+/*                                                                         */
+/**
+ * This Class provides the triangular meshes.
+ * Note, that up to now no methods for checking consistency are included.
+ * in this context this class describes facettes from an 3D-object !!!
+*/
+class GbTriFaceMesh3D : public GbObject3D
+{
+public:
+  // nested class start
+   class Vertex
+   {
+   public:
+      Vertex() : x(0.0), y(0.0), z(0.0) { }
+      Vertex(const float& x, const float& y, const float& z) : x(x), y(y),z(z) { }
+      Vertex(Vertex* vert)
+      {
+         this->x = vert->x;
+         this->y = vert->y;
+         this->z = vert->z;
+      }
+      float operator[] (const int&i) const
+      {
+         if     (i==0) return x;
+         else if(i==1) return y;
+         else if(i==2) return z;
+
+         throw UbException(UB_EXARGS,"i not in [0;2]");
+      }
+      float& operator[] (const int& i)
+      {
+         if     (i==0) return x;
+         else if(i==1) return y;
+         else if(i==2) return z;
+
+         throw UbException(UB_EXARGS,"not in [0;2]");
+      }
+      bool operator== (const Vertex& rhs)
+      {
+         return ( fabs(x-rhs.x)<1.E-8 && fabs(y-rhs.y)<1.E-8 && fabs(z-rhs.z)<1.E-8 );
+      }
+      friend inline bool operator<(const Vertex & lhsVert,const Vertex & rhsVert)
+      {
+         if( lhsVert.x < rhsVert.x ) return true;
+         if( lhsVert.x > rhsVert.x ) return false;
+         if( lhsVert.y < rhsVert.y ) return true;
+         if( lhsVert.y > rhsVert.y ) return false;
+         if( lhsVert.z < rhsVert.z ) return true;
+
+         return false;
+      }
+      friend std::ostream& operator<<( std::ostream& os, const Vertex& node )
+      {
+         return os<<node.x<<","<<node.y<<","<<node.z;
+      }
+      Vertex* clone()
+      {
+         return(new Vertex(this));
+      }
+
+#ifdef CAB_RCF
+      template<class Archive>
+      void SF_SERIALIZE(Archive & ar)
+      {
+         ar & x; ar & y; ar & z;
+      }
+#endif //CAB_RCF
+
+   public:
+      float x, y, z;
+   };
+   //////////////////////////////////////////////////////////////////////////
+   class TriFace
+   {
+   public:
+      TriFace()
+         : v1(-1), v2(-1), v3(-1), nx(0.0), ny(0.0), nz(0.0)
+      {
+
+      }
+      TriFace(const int& v1, const int& v2, const int& v3)
+         : v1(v1), v2(v2), v3(v3), nx(0.0), ny(0.0), nz(0.0)
+      {
+      }
+
+      const int& getIndexVertex1() const { return v1; }
+      const int& getIndexVertex2() const { return v2; }
+      const int& getIndexVertex3() const { return v3; }
+
+      Vertex& getNode(const int& i, std::vector<Vertex>& nodes)
+      {
+         if(i==0) return nodes[v1];
+         if(i==1) return nodes[v2];
+         if(i==2) return nodes[v3];
+         throw UbException(UB_EXARGS,"invalid i - not in range [0;2]");
+      }
+      void setNode(const int& i, const int& index)
+      {
+         if     (i==0) v1=index;
+         else if(i==1) v2=index;
+         else if(i==2) v3=index;
+         else throw UbException(UB_EXARGS,"invalid i - not in range [0;2]");
+      }
+
+      int operator[] (int index)
+      { 
+         if(index==0) return v1;
+         if(index==1) return v2;
+         if(index==2) return v3;
+         throw UbException(UB_EXARGS,"invalid i - not in range [0;2]");
+      }
+
+      float& getV1x(std::vector<Vertex>& nodes) { return nodes[v1].x; }
+      float& getV1y(std::vector<Vertex>& nodes) { return nodes[v1].y; }
+      float& getV1z(std::vector<Vertex>& nodes) { return nodes[v1].z; }
+
+      float& getV2x(std::vector<Vertex>& nodes) { return nodes[v2].x; }
+      float& getV2y(std::vector<Vertex>& nodes) { return nodes[v2].y; }
+      float& getV2z(std::vector<Vertex>& nodes) { return nodes[v2].z; }
+
+      float& getV3x(std::vector<Vertex>& nodes) { return nodes[v3].x; }
+      float& getV3y(std::vector<Vertex>& nodes) { return nodes[v3].y; }
+      float& getV3z(std::vector<Vertex>& nodes) { return nodes[v3].z; }
+
+      float getMinX(std::vector<Vertex>& nodes) { return (float)UbMath::min(nodes[v1].x,nodes[v2].x,nodes[v3].x); }
+      float getMinY(std::vector<Vertex>& nodes) { return (float)UbMath::min(nodes[v1].y,nodes[v2].y,nodes[v3].y); }
+      float getMinZ(std::vector<Vertex>& nodes) { return (float)UbMath::min(nodes[v1].z,nodes[v2].z,nodes[v3].z); }
+
+      float getMaxX(std::vector<Vertex>& nodes) { return (float)UbMath::max(nodes[v1].x,nodes[v2].x,nodes[v3].x); }
+      float getMaxY(std::vector<Vertex>& nodes) { return (float)UbMath::max(nodes[v1].y,nodes[v2].y,nodes[v3].y); }
+      float getMaxZ(std::vector<Vertex>& nodes) { return (float)UbMath::max(nodes[v1].z,nodes[v2].z,nodes[v3].z); }
+
+      float getX1Centroid(std::vector<Vertex>& nodes) {return (float)UbMath::c1o3 * (getV1x(nodes)+getV2x(nodes)+getV3x(nodes)); }
+      float getX2Centroid(std::vector<Vertex>& nodes) {return (float)UbMath::c1o3 * (getV1y(nodes)+getV2y(nodes)+getV3y(nodes)); }
+      float getX3Centroid(std::vector<Vertex>& nodes) {return (float)UbMath::c1o3 * (getV1z(nodes)+getV2z(nodes)+getV3z(nodes)); }
+
+      double calculateDistanceToPoint3D(const double& x1, const double& x2, const double& x3, std::vector<Vertex>& nodes);
+
+      double getArea(std::vector<Vertex>& nodes)
+      {
+         //GbVector3D A(nodes[v1].x, nodes[v1].y, nodes[v1].z);
+         //GbVector3D B(nodes[v2].x, nodes[v2].y, nodes[v2].z);
+         //GbVector3D C(nodes[v3].x, nodes[v3].y, nodes[v3].z);
+         //GbVector3D AB = B-A;
+         //GbVector3D AC = C-A;
+         //GbVector3D N = AB.Cross(AC);
+         //return 0.5*N.Length();
+         UbMath::Vector3D A(nodes[v1].x, nodes[v1].y, nodes[v1].z);
+         UbMath::Vector3D B(nodes[v2].x, nodes[v2].y, nodes[v2].z);
+         UbMath::Vector3D C(nodes[v3].x, nodes[v3].y, nodes[v3].z);
+         UbMath::Vector3D AB = B-A;
+         UbMath::Vector3D AC = C-A;
+         UbMath::Vector3D N = AB.Cross(AC);
+         return 0.5*N.Length();
+      }
+      void calculateNormal(std::vector<Vertex>& nodes)
+      {
+         const float& v1x = nodes[v1].x; const float& v1y = nodes[v1].y; const float& v1z = nodes[v1].z;
+         const float& v2x = nodes[v2].x; const float& v2y = nodes[v2].y; const float& v2z = nodes[v2].z;
+         const float& v3x = nodes[v3].x; const float& v3y = nodes[v3].y; const float& v3z = nodes[v3].z;
+
+         nx = ( v3z - v1z) * ( v2y - v1y ) - ( v2z - v1z) * ( v3y - v1y );
+         ny = ( v2z - v1z) * ( v3x - v1x ) - ( v2x - v1x) * ( v3z - v1z );
+         nz = ( v2x - v1x) * ( v3y - v1y ) - ( v2y - v1y) * ( v3x - v1x );
+
+         float length = std::sqrt( nx*nx + ny*ny + nz*nz );
+         if(length>1.E-10)
+         {
+            length = 1.0f/length;
+            nx *= length;
+            ny *= length;
+            nz *= length;
+         }
+         else 
+         {
+            std::cerr<<"GbTriFaceMesh3D::TriFace - calculateNormal: nx=ny=nz=0 -> kann nich sein "
+                     <<"(dreieck hat evtl knoten doppelt oder ist ne Linie)"
+                     <<"->removeRedunantNodes"<<std::endl;
+         }
+      }
+   #ifdef CAB_RCF
+      template<class Archive>
+      void SF_SERIALIZE(Archive & ar)
+      {
+         ar & v1; ar & v2; ar & v3;
+      }
+   #endif //CAB_RCF
+
+   public:
+      int   v1, v2, v3;
+      float nx, ny, nz;
+   };
+
+public:
+  enum KDTREE_SPLITAGORITHM { KDTREE_SAHPLIT, KDTREE_SPATIALSPLIT };
+
+public:
+   GbTriFaceMesh3D();
+   GbTriFaceMesh3D(std::string name, std::vector<Vertex>* nodes, std::vector<TriFace>* triangles, KDTREE_SPLITAGORITHM splitAlg = KDTREE_SAHPLIT, bool removeRedundantNodes=true);
+	~GbTriFaceMesh3D();
+
+   GbTriFaceMesh3D* clone();// { throw UbException(UB_EXARGS,"not implemented"); }
+   void finalize() {}
+
+   //void setRegardPointInPolyhedronTest(bool value) { this->regardPiO=value; }
+
+   std::string toString();
+
+   //std::string getName();
+   std::vector<Vertex>*  getNodes();
+   std::vector<TriFace>* getTriangles();
+   
+   void setTransferViaFilename(bool transferViaFilename, std::string filename, double transX1, double transX2, double transX3)
+   {
+      this->filename = filename;
+      this->transferViaFilename = transferViaFilename;
+      this->transX1 = transX1;
+      this->transX2 = transX2;
+      this->transX3 = transX3;
+   }
+   void readMeshFromSTLFile(std::string filename, bool removeRedundantNodes);
+
+   double getX1Minimum()  { if(!this->consistent) this->calculateValues(); return this->x1min;    }
+   double getX1Maximum()  { if(!this->consistent) this->calculateValues(); return this->x1max;    }
+   double getX1Centroid() { if(!this->consistent) this->calculateValues(); return this->x1center; }
+
+   double getX2Minimum()  { if(!this->consistent) this->calculateValues(); return this->x2min;    }
+   double getX2Maximum()  { if(!this->consistent) this->calculateValues(); return this->x2max;    }
+   double getX2Centroid() { if(!this->consistent) this->calculateValues(); return this->x2center; }
+   
+   double getX3Minimum()  { if(!this->consistent) this->calculateValues(); return this->x3min;    }
+   double getX3Centroid() { if(!this->consistent) this->calculateValues(); return this->x3center; }
+   double getX3Maximum()  { if(!this->consistent) this->calculateValues(); return this->x3max;    }
+
+   void   calculateValues();
+
+   double getVolume();
+   void   deleteRedundantNodes();
+
+   UbTupleDouble6 calculateMomentOfInertia(double rhoP);
+   UbTupleDouble3 calculateCenterOfGravity();
+
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+
+
+   void scale(const double& sx1, const double& sx2, const double& sx3);
+   void rotate(const double& alpha, const double& beta, const double& gamma);
+   void rotateAroundPoint(const double& px1, const double& px2, const double& px3, const double& alpha, const double& beta, const double& gamma);
+   void translate(const double& x1, const double& x2, const double& x3);
+   void reflectAcrossXYLine(const double& alpha);
+
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3);
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, int counter);
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary);
+
+   virtual GbLine3D* createClippedLine3D (GbPoint3D &point1,GbPoint3D &point2);
+
+   virtual std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+
+   std::vector<GbTriFaceMesh3D::TriFace*> getTrianglesForVertex(Vertex* vertex);
+
+   void setKdTreeSplitAlgorithm(KDTREE_SPLITAGORITHM mode); 
+   KDTREE_SPLITAGORITHM getKdTreeSplitAlgorithm() { return this->kdtreeSplitAlg; }
+   Kd::Tree<double>* getKdTree() { return this->kdTree; }
+
+   virtual ObObjectCreator* getCreator();
+
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);  
+
+   virtual UbTuple<std::string, std::string> writeMesh(std::string filename, WbWriter* writer, bool writeNormals=false, std::vector< std::string >* datanames=NULL, std::vector< std::vector < double > >* nodedata=NULL );
+   void writeMeshPly( const std::string& filename);
+
+   /*======================================================================*/
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & kdtreeSplitAlg;
+      ar & transferViaFilename;
+      if(!transferViaFilename)
+      {
+         ar & nodes;
+         ar & triangles;
+      }
+      else
+      {
+         ar & filename;
+         ar & transX1;
+         ar & transX2;
+         ar & transX3;
+         if(ArchiveTools::isReading(ar) ) 
+         {
+            this->readMeshFromSTLFile(filename, true);
+            this->translate(transX1,transX2,transX3);
+         }
+      }
+      
+      if(ArchiveTools::isReading(ar)) this->calculateValues();
+   }
+#endif //CAB_RCF
+
+protected:
+   KDTREE_SPLITAGORITHM kdtreeSplitAlg;
+   void init();
+
+   std::vector<Vertex>*  nodes;
+   std::vector<TriFace>* triangles;
+   //for transfer
+   std::string filename;
+   bool transferViaFilename;
+   double transX1;
+   double transX2;
+   double transX3;
+
+   double x1min;
+   double x1max;
+   double x2min;
+   double x2max;
+   double x3min;
+   double x3max;
+   double x1center;
+   double x2center;
+   double x3center;
+
+   bool   consistent;
+
+   bool buildVertTriRelationMap;
+   std::multimap<Vertex*,TriFace*> relationVertTris;
+
+   Kd::Tree< double >* kdTree;
+};
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbTriFaceMesh3D  >("GbTriFaceMesh3D  ")     , SF_GbTriFaceMesh3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbTriFaceMesh3D >() ), SF_GbTriFaceMesh3D_BD1 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif //GBTRIFACEMESH3D_H
diff --git a/source/VirtualFluidsCore/Geometry/GbTriangle3D.cpp b/source/VirtualFluidsCore/Geometry/GbTriangle3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f3edda2240522d65a212729acaf258da4fcc94e6
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbTriangle3D.cpp
@@ -0,0 +1,1229 @@
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <numerics/geometry3d/creator/GbTriangle3DCreator.h>
+
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+//#include <numerics/geometry3d/GbPolygon3D.h>                                  
+
+using namespace std;
+
+ObObjectCreator* GbTriangle3D::getCreator()
+{
+   return GbTriangle3DCreator::getInstance();
+}
+
+/*=========================================================================*/
+/* GbTriangle3D                                                            */
+/*                                                                         */
+/*
+* This Class provides basic 3D triangle objects.
+* The describing points are observed by 2D triangle objects.
+* <BR><BR><HR>
+* @version 1.0 - 24.01.05
+*/                                                                  
+
+GbTriangle3D::GbTriangle3D()
+{
+   this->init();
+   this->consistent = false;
+}
+/*======================================================================*/
+/*
+* Creates an empty 2D triangle with the specified points.
+* @param point1 the 1st point
+* @param point2 the 2nd point
+* @param point3 the 3nd point
+*/
+GbTriangle3D::GbTriangle3D(GbPoint3D* point1, GbPoint3D* point2, GbPoint3D* point3)
+{
+   this->init();
+   this->points[0] = point1;
+   this->points[1] = point2;
+   this->points[2] = point3;
+
+   this->calculateNormal();
+   this->consistent = false;
+
+   this->points[0]->addObserver(this);
+   this->points[1]->addObserver(this);
+   this->points[2]->addObserver(this);
+   
+   //this.po        = new PointObserver(this);
+   //this.points[0].addObserver(this.po);
+   //this.points[1].addObserver(this.po);
+   //this.points[2].addObserver(this.po);
+}
+/*======================================================================*/
+/*
+* Creates a 3D triangle as clone of the specified 2D triangle.
+* @param triangle the 3D triangle to be cloned
+*/
+GbTriangle3D::GbTriangle3D(GbTriangle3D* triangle)
+{
+   this->init();
+   this->points[0] = triangle->points[0]->clone();
+   this->points[1] = triangle->points[1]->clone();
+   this->points[2] = triangle->points[2]->clone();
+
+   this->consistent = false;
+   this->calculateNormal();
+   this->calculateValues();
+}
+/*======================================================================*/
+GbTriangle3D::~GbTriangle3D()
+{
+   if(this->points[0]) this->points[0]->removeObserver(this);
+   if(this->points[1]) this->points[1]->removeObserver(this);
+   if(this->points[2]) this->points[2]->removeObserver(this);
+}
+/*======================================================================*/
+void GbTriangle3D::deletePoints()
+{ 
+   if(points[0]) { delete points[0]; points[0]=NULL;}
+   if(points[1]) { delete points[1]; points[1]=NULL;}
+   if(points[2]) { delete points[2]; points[2]=NULL;}
+}
+
+/*======================================================================*/
+/*  Methoden                                                            */
+/*                                                                      */
+/*
+* Creates a 3D triangle as clone of this 3D triangle.
+*/
+GbTriangle3D* GbTriangle3D::clone()
+{
+   return(new GbTriangle3D(this));
+}
+/*======================================================================*/
+/*
+* Returns the number of times this 2D triangle contains the specified point.
+* @param point the point
+* @return the number of times this 2D triangle contains the specified point
+*/
+int GbTriangle3D::contains(GbPoint3D* point)
+{
+   int n = 0;
+   for(int i=0; i<3; i++) if(this->points[i]->equals(point)) n++;
+   return(n);
+}
+/*======================================================================*/
+/*
+* Returns the number of times this 2D triangle contains a point equal to the specified point.
+* @param point the point
+* @return the number of times this 2D triangle contains a point equal to the specified point
+*/
+int GbTriangle3D::containsEqual(GbPoint3D* point)
+{
+   int n = 0;
+   for(int i=0; i<3; i++) if(this->points[i]->equals(point)) n++;
+   return(n);
+}
+/*======================================================================*/
+/*
+* Returns the specified point.
+* @param index the index (must be 0, 1, or 2)
+* @return the specified point
+* @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+*/
+GbPoint3D* GbTriangle3D::getPoint(const int& index) 
+{
+   if(index < 0 || index > 2) throw UbException(UB_EXARGS,"invalid index specified: ");
+   return((this->points[index]));
+}
+/*======================================================================*/
+vector<GbPoint3D> GbTriangle3D::getPoints() 
+{
+   vector<GbPoint3D> p(3);
+   p[0] = *(points[0]);
+   p[1] = *(points[1]);
+   p[2] = *(points[2]);
+   return p;
+   //
+   //vector<GbPoint3D> p(3);// = new vector<GbPoint3D*>;
+   //p.resize(3);//, NULL);
+   //p[0] = this->points[0];
+   //p[1] = this->points[1];
+   //p[2] = this->points[2];
+   //return(p);
+}
+/*======================================================================*/
+/*
+* Returns the area of this triangle.
+* The area is positive for positive ordered points, otherwise negative.
+* @return the area of this triangle
+*/
+double GbTriangle3D::getArea()
+{
+   if(!this->consistent) this->calculateValues();
+   // throw UbException(UB_EXARGS,"not correct calculated ...");
+   return(this->area);
+}
+/*
+* Returns the centroid x1 coordinate of this triangle.
+* @return the centroid x1 coordinate of this triangle
+*/
+double GbTriangle3D::getX1Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1s);
+}
+/*
+* Returns the minimum x1 coordinate of this triangle.
+* @return the minimum x1 coordinate of this triangle
+*/
+double GbTriangle3D::getX1Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1min);
+}
+/*
+* Returns the maximum x1 coordinate of this triangle.
+* @return the maximum x1 coordinate of this triangle
+*/
+double GbTriangle3D::getX1Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x1max);
+}
+/*
+* Returns the centroid x2 coordinate of this triangle.
+* @return the centroid x2 coordinate of this triangle
+*/
+double GbTriangle3D::getX2Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2s);
+}
+/*                                                         
+* Returns the minimum x2 coordinate of this triangle.
+* @return the minimum x2 coordinate of this triangle
+*/
+double GbTriangle3D::getX2Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2min);
+}
+/*
+* Returns the maximum x2 coordinate of this triangle.
+* @return the maximum x2 coordinate of this triangle
+*/
+double GbTriangle3D::getX2Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x2max);
+}
+double GbTriangle3D::getX3Centroid()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3s);
+}
+double GbTriangle3D::getX3Minimum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3min);
+}
+double GbTriangle3D::getX3Maximum()
+{
+   if(!this->consistent) this->calculateValues();
+   return(this->x3max);
+}
+
+/*
+* Sets the specified point.
+* @param point the point
+* @param index the index (must be 0, 1, or 2)
+* @exception ArrayIndexOutOfBoundsException if the specified index is not valid
+*/
+void GbTriangle3D::setPoint(GbPoint3D* point, int index) 
+{
+   if(index < 0 || index > 2) throw UbException(UB_EXARGS,"invalid index specified: ");
+   this->points[index] = point;
+   this->consistent    = false;
+   this->calculateNormal();
+}
+
+/*
+* Returns true if this 2D triangle equals the specified object.
+* Two triangle are equal, if their points are equal.
+* <BR>Note that the order of points is not recognized!
+* @return true if this 2D triangle equals the specified object
+* @see GbPoint2D#equals(java.lang.Object)
+* @see GbPoint3D#equals(java.lang.Object)
+*/
+//bool equals(GbObject3D *object)
+//{
+//   try
+//   {
+//      GbTriangle3D *triangle = (GbTriangle3D*) object;
+
+//if(this.points[0].equals(triangle.points[0]))
+//{
+//   if(this.points[1].equals(triangle.points[1]) && this.points[2].equals(triangle.points[2])) return(true);
+//   if(this.points[1].equals(triangle.points[2]) && this.points[2].equals(triangle.points[1])) return(true);
+//   return(false);
+//}
+//else if(this.points[0].equals(triangle.points[1]))
+//{
+//   if(this.points[1].equals(triangle.points[0]) && this.points[2].equals(triangle.points[2])) return(true);
+//   if(this.points[1].equals(triangle.points[2]) && this.points[2].equals(triangle.points[0])) return(true);
+//   return(false);
+//}
+//else if(this.points[0].equals(triangle.points[2]))
+//{
+//   if(this.points[1].equals(triangle.points[0]) && this.points[2].equals(triangle.points[1])) return(true);
+//   if(this.points[1].equals(triangle.points[1]) && this.points[2].equals(triangle.points[0])) return(true);
+//   return(false);
+//}
+//return(false);
+//    }
+//    catch(Exception e){ return(false); }
+// }
+/*
+* Returns the surface triangle set with new nodes !!!
+* @returns the surface triangle set with new nodes !!!
+*/
+vector<GbTriangle3D*> GbTriangle3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles;
+   
+   triangles.push_back(new GbTriangle3D(new GbPoint3D(getPoint1()),new GbPoint3D(getPoint2()),new GbPoint3D(getPoint3())));
+
+   return triangles;
+}
+
+
+/*
+* Returns the string representation of the triangle
+* @returns the string representation of the triangle
+*/
+
+string GbTriangle3D::toString()
+{
+   stringstream ss;
+   ss<<"GbTriangle3D[area=";
+   ss<<this->getArea();
+
+   ss<<", x1s="<<this->x1s;
+   ss<<", x2s="<<this->x2s;
+   ss<<", x3s="<<this->x3s;
+   ss<<", x1min="<<this->x1min;
+   ss<<", x1max="<<this->x1max;
+   ss<<", x2min="<<this->x2min;
+   ss<<", x2max="<<this->x2max;
+   ss<<", x3min="<<this->x3min;
+   ss<<", x3max="<<this->x3max;
+   ss<<", points1="<<this->points[0]->toString();
+   ss<<", points2="<<this->points[1]->toString();
+   ss<<", points3="<<this->points[2]->toString();
+   ss<<"]";
+   return((ss.str()).c_str());
+}
+/*======================================================================*/
+double GbTriangle3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   //e1 = v1 - v0
+   double e1x1 = this->points[1]->x1-this->points[0]->x1;
+   double e1x2 = this->points[1]->x2-this->points[0]->x2;
+   double e1x3 = this->points[1]->x3-this->points[0]->x3;  
+
+   //e2 = v2 - v0
+   double e2x1 = this->points[2]->x1-this->points[0]->x1;
+   double e2x2 = this->points[2]->x2-this->points[0]->x2;
+   double e2x3 = this->points[2]->x3-this->points[0]->x3;  
+
+   //p = d x e2
+   double px1 = rx2*e2x3 - rx3*e2x2;
+   double px2 = rx3*e2x1 - rx1*e2x3;
+   double px3 = rx1*e2x2 - rx2*e2x1;
+
+   //a = e1 dot p
+   double a = e1x1*px1 + e1x2*px2 + e1x3*px3;
+   if(fabs(a)<1.E-10) return -1.0;
+   double f = 1.0/a;
+
+   //s = o - v0
+   double sx1 = x1 - this->points[0]->x1;
+   double sx2 = x2 - this->points[0]->x2;
+   double sx3 = x3 - this->points[0]->x3;
+
+   //u = f * ( s dot p)
+   double u = f * ( sx1*px1 + sx2*px2 + sx3*px3 );
+   if(u<-1.E-10 || u>1.0+1.E-10) return -1.0;
+
+   //q = s x e1
+   double qx1 = sx2*e1x3 - sx3*e1x2;
+   double qx2 = sx3*e1x1 - sx1*e1x3;
+   double qx3 = sx1*e1x2 - sx2*e1x1;
+
+   //v = f*(e2 dot q)
+   double v = f * (rx1*qx1 + rx2*qx2 + rx3*qx3);
+   if(v<-1.E-10 || (u+v)>1.0+1.E-10) return -1.0;
+
+   //t = f * (e2 dot q)
+   return f * (e2x1*qx1 + e2x2*qx2 + e2x3*qx3);
+}
+
+/*======================================================================*/
+/*  Calculation                                                         */
+/*                                                                      */
+/*
+* Returns the intersection points of this 2D triangle and the specified 2D line.
+* @param line the 2D line to intersect
+* @return the intersection points of this 2D triangle and the specified 2D line
+*/
+/*
+vector<GbPoint3D> GbTriangle3D::calculateIntersectionPoints3D(GbLine3D *line)
+{
+//throw UbException(UB_EXARGS,"not yet implemented");	
+
+GbSystem::PointSet3 pointSet(0);
+GbPoint3D          *pCrossed = NULL;
+
+pCrossed = GbSystem::calculateIntersectionPoint3D(*this->points[0], *this->points[1], *line->getPoint1(), *line->getPoint2());
+if(pCrossed != NULL) pointSet.addUnequal(pCrossed);
+pCrossed = GbSystem::calculateIntersectionPoint3D(*this->points[1], *this->points[2], *line->getPoint1(), *line->getPoint2());
+if(pCrossed != NULL) pointSet.addUnequal(pCrossed);
+pCrossed = GbSystem::calculateIntersectionPoint3D(*this->points[2], *this->points[0], *line->getPoint1(), *line->getPoint2());
+if(pCrossed != NULL) pointSet.addUnequal(pCrossed);
+//vector<GbPoint3D> points = pointSet->getPoints();
+return(pointSet.getPoints());
+}
+*/
+/*===========================================================*/
+
+GbLine3D* GbTriangle3D::createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2)
+{
+   GbPoint3D *result = this->calculateIntersectionPoints3D(&point1, &point2);
+   if(!result) return NULL;
+
+   return new GbLine3D(result, new GbPoint3D(point2));
+
+   //return GbSystem::createClipLine3D(point1, point2,
+      //p1->getX1Coordinate(),p1->getX2Coordinate(),p1->getX3Coordinate(),
+      //p2->getX1Coordinate(),p2->getX2Coordinate(),p2->getX3Coordinate() );
+}
+
+//von Navodit ...
+/*===========================================================*/
+GbPoint3D* GbTriangle3D::calculateIntersectionPoints3D(GbLine3D* line)
+{
+   return this->calculateIntersectionPoints3D(line->getPoint1(), line->getPoint2());
+}
+/*===========================================================*/
+GbPoint3D* GbTriangle3D::calculateIntersectionPoints3D(GbPoint3D* linePoint1, GbPoint3D* linePoint2)
+{
+   GbVector3D Point1(linePoint1->x1, linePoint1->x2, linePoint1->x3);
+   GbVector3D Point2(linePoint2->x1, linePoint2->x2, linePoint2->x3);
+   GbVector3D direction = Point2-Point1;
+   GbVector3D GbPoint3D1(this->getPoint1()->x1,this->getPoint1()->x2,this->getPoint1()->x3);
+   GbVector3D GbPoint3D2(this->getPoint2()->x1,this->getPoint2()->x2,this->getPoint2()->x3);
+   GbVector3D GbPoint3D3(this->getPoint3()->x1,this->getPoint3()->x2,this->getPoint3()->x3);
+   GbVector3D V2V1 = GbPoint3D2-GbPoint3D1;
+   GbVector3D V3V1 = GbPoint3D3-GbPoint3D1;
+   GbVector3D V2V1V3V1 = V2V1.Cross(V3V1);
+   V2V1V3V1.Normalize();
+   GbVector3D Normal = V2V1V3V1;
+
+   double d = -Normal.Dot(GbPoint3D1);            
+   double denom = Normal.Dot(direction);       
+
+   if (UbMath::zero(denom)) return NULL;   //line does not intersect the plane of the triangle !
+   else
+   {
+      double mu = -1.*(d + Point1.Dot(Normal))/denom;            //mu = -(d+ Normal.Point1)/denom
+
+      //   GbVector3D p1 = Point2-Point1;
+      //   GbVector3D p2 = p1*mu;
+      //   GbVector3D p3 = Point1+p2;
+      GbVector3D point = Point1 + mu*(Point2 -Point1);
+
+      if (mu<0.0 || mu>1.0)    return NULL;     // Point of intersection of line and plane does not lie on the triangle   
+      else
+      {
+         //Test whether Point lies inside the triangle or not
+         bool test=true;
+         GbVector3D a = GbPoint3D1-point;
+         GbVector3D b = GbPoint3D2-point;
+         GbVector3D c = GbPoint3D3-point;
+         GbVector3D ab = a.Cross(b);
+         GbVector3D bc = b.Cross(c);
+         GbVector3D ca = c.Cross(a);
+         GbVector3D Q1 = ab*0.5;
+         GbVector3D Q2 = bc*0.5;
+         GbVector3D Q3 = ca*0.5;
+         GbVector3D Q1Q2 = Q1+Q2;
+         GbVector3D Q = Q1Q2+Q3;
+
+         if (UbMath::less(Q.Dot(Q1), 0.0)) test = false; 
+         if (UbMath::less(Q.Dot(Q2), 0.0)) test = false; 
+         if (UbMath::less(Q.Dot(Q3), 0.0)) test = false; 
+
+         if (test == true) return (new GbPoint3D(point.X1(), point.X2(), point.X3()));
+         else          return NULL;
+      }
+   }
+}
+
+/**
+* Returns the distance between the 3D triangle and the specified 3D Point                                                                      
+* @param point the 3D point from whom the distance is to be calculated
+* @return the distance of the specified point from the triangle
+*/
+double GbTriangle3D::calculateDistanceToPoint3D(GbPoint3D *point) 
+{
+   return this->calculateDistanceToPoint3D(point->x1, point->x2, point->x3);
+}
+/*=======================================================================*/
+double GbTriangle3D::calculateDistanceToPoint3D(const double& x1, const double& x2, const double& x3) 
+{
+   //
+   //throw UbException(UB_EXARGS,"Ich glaub GbTriangle3D::calculateDistanceToPoint3D(...) kann man so nicht nehmen,jedenfalls nicht fuer die q's");
+   cout<<"??? ch glaub GbTriangle3D::calculateDistanceToPoint3D(...) kann man so nicht nehmen,jedenfalls nicht fuer die q's"<<endl;
+   GbVector3D P0(x1, x2, x3);
+   GbVector3D P1(this->points[0]->x1, this->points[0]->x2, this->points[0]->x3);
+   GbVector3D P2(this->points[1]->x1, this->points[1]->x2, this->points[1]->x3);
+   GbVector3D P3(this->points[2]->x1, this->points[2]->x2, this->points[2]->x3);
+
+   //Determine normal to triangle
+   GbVector3D Normal = (P1-P2).Cross(P1-P3);
+   double alpha = UbMath::ACos((P1-P0).Dot(Normal)/((P1-P0).Length()*Normal.Length()));
+
+   double P0P0dash = (P0-P1).Length()*cos(alpha);
+   Normal.Normalize();
+   GbVector3D Projection = Normal*(-P0P0dash);
+
+   GbVector3D P0dash = P0+Projection;
+
+   //Check if point P0dash lies within the triangle P1P2P3.
+   bool test = false;
+   if ( ((P1-P0).Cross(P2-P0)).Dot(Normal) > 0 ) test = true;
+   if ( ((P2-P0).Cross(P3-P0)).Dot(Normal) > 0 ) test = true;
+   if ( ((P3-P0).Cross(P1-P0)).Dot(Normal) > 0 ) test = true;
+
+   if (test == true) return (P0-P0dash).Length();
+   else
+   // Determine the distance of point P0 from all edges and vertices and return the minimum distance
+   {
+      double dP0P1 = (P0-P1).Length(); //Distance of Point P0 from Point P1
+      double dP0P2 = (P0-P2).Length(); //Distance of Point P0 from Point P2
+      double dP0P3 = (P0-P3).Length(); //Distance of Point P0 from Point P3
+
+      GbVector3D MP1P2 = P2-P1;        //Direction vector for line P1P2
+      GbVector3D MP2P3 = P3-P2;        //Direction vector for line P2P3
+      GbVector3D MP3P1 = P1-P3;        //Direction vector for line P3P1
+
+      double tP1P2 = MP1P2.Dot(P0-P1) / MP1P2.Dot(MP1P2);
+      double tP2P3 = MP2P3.Dot(P0-P2) / MP2P3.Dot(MP2P3);
+      double tP3P1 = MP3P1.Dot(P0-P3) / MP3P1.Dot(MP3P1);
+
+      double dP1P2 = (P0-(P1+(MP1P2*tP1P2))).Length(); //Distance of Point P0 from line P1P2
+      double dP2P3 = (P0-(P2+(MP2P3*tP2P3))).Length(); //Distance of Point P0 from line P2P3
+      double dP3P1 = (P0-(P3+(MP3P1*tP3P1))).Length(); //Distance of Point P0 from line P3P1
+
+      double distanceP0[6]; //Array to store all the distances from Point P0
+      distanceP0[0] = dP0P1; 
+      distanceP0[1] = dP0P2; 
+      distanceP0[2] = dP0P3; 
+      distanceP0[3] = dP1P2; 
+      distanceP0[4] = dP2P3; 
+      distanceP0[5] = dP3P1; 
+
+      double d = 0.0;
+      //Find the minimum distance from Point P0
+      for (int i=0; i<6; i++)
+      {
+         if(distanceP0[i]<d) d = distanceP0[i];
+      }
+      return d;
+   }
+}
+/**
+* Returns the normalized distance between the 3D triangle and the specified 3D Point
+* copied from Benjamin A.
+* @param point the 3D point from whom the distance is to be calculated
+* @return the distance of the specified point from the triangle
+*/
+double GbTriangle3D::calculateNormalizedDistanceToPoint3D(const double& x1, const double& y1, const double& z1, 
+                                                          const double& x2, const double& y2, const double& z2)
+{
+    //face* pf
+    double xa, xb, xc, ya, yb, yc, za, zb, zc;
+    //double xp, yp, zp;
+    double tt=0, xi=0, eta=0;
+    double zaehler, nenner;
+    double wurzel3 = sqrt(3.);
+
+    //Weltkoordinaten der Dreiecke
+    xa = this->points[0]->x1;
+    xb = this->points[1]->x1;
+    xc = this->points[2]->x1;
+         
+    ya = this->points[0]->x2;
+    yb = this->points[1]->x2;
+    yc = this->points[2]->x2;
+
+    za = this->points[0]->x3;
+    zb = this->points[1]->x3;
+    zc = this->points[2]->x3;
+
+    //Shape-Funktionen zum Berechnen der Schnittpunkte
+    zaehler =
+       static_cast<double>(((-1.0*zc+zb)*ya+(yc-1.0*yb)*za+zc*yb-1.0*zb*yc)*x1
+       +((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y1+((-1.0*yc+yb)*xa
+       +(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z1+((-1.0*zc+zb)*ya+(yc-1.0*yb)*za
+       +zc*yb-1.0*zb*yc)*x2+((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2
+       +((-1.0*yc+yb)*xa+(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z2+(2.0*zb*yc-2.0*zc*yb)*xa
+       +(2.0*xb*zc-2.0*xc*zb)*ya+(-2.0*xb*yc+2.0*xc*yb)*za);
+    nenner  =
+       static_cast<double>((((-1.0*zc+zb)*ya+(yc-1.0*yb)*za+zc*yb-1.0*zb*yc)*x1
+       +((-1.0*zb+zc)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y1+((-1.0*yc+yb)*xa
+       +(-1.0*xb+xc)*ya-1.0*xc*yb+xb*yc)*z1+((-1.0*zb+zc)*ya+(-1.0*yc+yb)*za-1.0*zc*yb+zb*yc)
+       *x2+((-1.0*zc+zb)*xa+(-1.0*xb+xc)*za+xb*zc-1.0*xc*zb)*y2+((yc-1.0*yb)*xa+(xb
+       -1.0*xc)*ya+xc*yb-1.0*xb*yc)*z2));
+    if( UbMath::greater(nenner, 0.0) ) tt = zaehler/nenner;
+    else tt=-999.;
+
+    zaehler =
+       static_cast<double>(((-2.0*zc+za+zb)*y2+(-1.0*yb-1.0*ya+2.0*yc)*z2+zc*ya
+       -1.0*zb*yc+zc*yb-1.0*za*yc)*x1+((-1.0*za+2.0*zc-1.0*zb)*x2+(xa-2.0*xc+xb)*z2
+       -1.0*xa*zc-1.0*xb*zc+xc*za+xc*zb)*y1+((-2.0*yc+ya+yb)*x2+(-1.0*xa-1.0*xb+2.0*xc)
+       *y2-1.0*xc*yb+xa*yc+xb*yc-1.0*xc*ya)*z1+(zb*yc-1.0*zc*ya-1.0*zc*yb+za*yc)
+       *x2+(-1.0*xc*za+xb*zc+xa*zc-1.0*xc*zb)*y2+(xc*yb-1.0*xa*yc-1.0*xb*yc+xc*ya)*z2);
+    nenner  =
+       static_cast<double>((((zc-1.0*zb)*ya+(yb-1.0*yc)*za+zb*yc-1.0*zc*yb)*x1
+       +((zb-1.0*zc)*xa+(xc-1.0*xb)*za-1.0*xc*zb+xb*zc)*y1+((-1.0*yb+yc)*xa+(xb-1.0*xc)
+       *ya-1.0*xb*yc+xc*yb)*z1+((zb-1.0*zc)*ya+(-1.0*yb+yc)*za+zc*yb-1.0*zb*yc)*x2
+       +((zc-1.0*zb)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2+((yb-1.0*yc)*xa
+       +(xc-1.0*xb)*ya+xb*yc-1.0*xc*yb)*z2));
+    if( UbMath::greater(nenner, 0.0) ) xi = zaehler/nenner;
+    else xi=-999.;
+
+    zaehler =
+       static_cast<double>(((za-1.0*zb)*y2+(-1.0*ya+yb)*z2-1.0*za*yb+zb*ya)*x1+
+       ((-1.0*za+zb)*x2+(xa-1.0*xb)*z2-1.0*xa*zb+xb*za)*y1+((ya-1.0*yb)*x2+(xb-1.0*xa)
+       *y2+xa*yb-1.0*xb*ya)*z1+(-1.0*zb*ya+za*yb)*x2+(-1.0*xb*za+xa*zb)*y2
+       +(-1.0*xa*yb+xb*ya)*z2);
+    nenner  =
+       static_cast<double>((((zc-1.0*zb)*ya+(yb-1.0*yc)*za+zb*yc-1.0*zc*yb)*x1
+       +((zb-1.0*zc)*xa+(xc-1.0*xb)*za-1.0*xc*zb+xb*zc)*y1+((-1.0*yb+yc)*xa+(xb-1.0*xc)
+       *ya-1.0*xb*yc+xc*yb)*z1+((zb-1.0*zc)*ya+(-1.0*yb+yc)*za+zc*yb-1.0*zb*yc)*x2
+       +((zc-1.0*zb)*xa+(xb-1.0*xc)*za-1.0*xb*zc+xc*zb)*y2+((yb-1.0*yc)*xa+(xc-1.0*xb)
+       *ya+xb*yc-1.0*xc*yb)*z2));
+    if ( UbMath::greater(nenner, 0.0) ) eta = static_cast<double>((zaehler/nenner)*wurzel3*-1.);
+    else eta=-999.;
+
+    if (tt >= -1.0-UbMath::Epsilon<double>::val() && tt <= 1.0){
+       if(xi >= -1.0+eta/wurzel3-UbMath::Epsilon<double>::val() && xi <=
+          1.0-eta/wurzel3+UbMath::Epsilon<double>::val()){
+             if (eta >= 0-UbMath::Epsilon<double>::val() && eta <= wurzel3+UbMath::Epsilon<double>::val()){
+                /*xp = x1*(0.5-tt/2)+x2*(0.5+tt/2);
+                yp = y1*(0.5-tt/2)+y2*(0.5+tt/2);
+                zp = z1*(0.5-tt/2)+z2*(0.5+tt/2);*/
+                return
+                   static_cast<double>((sqrt(pow((x1*(0.5-tt/2)+x2*(0.5+tt/2))-x1,2)
+                   +pow((y1*(0.5-tt/2)+y2*(0.5+tt/2))-y1,2)+pow((z1*(0.5-tt/2)+z2*(0.5+tt/2))-z1,2))));
+             }
+          }
+    }
+    return (-999.);
+}
+/*
+* Returns true if the specified 2D point lies within (or on the border of) this 2D triangle.
+* @param point the 2D point to check
+* @return true if the specified 2D point lies within (or on the border of) this 2D triangle
+*/
+ bool GbTriangle3D::enclosesPoint2D(double x1, double x2)
+ {
+	 int i=0;
+	 //Punkt(x1,x2) liegt auf einem der Eckpunkte
+    if(x1==this->getPoint(0)->getX1Coordinate() && x2 == this->getPoint(0)->getX2Coordinate())	return true;
+	 if(x1==this->getPoint(1)->getX1Coordinate() && x2 == this->getPoint(1)->getX2Coordinate())	return true;
+	 if(x1==this->getPoint(2)->getX1Coordinate() && x2 == this->getPoint(2)->getX2Coordinate())  return true;
+
+	 //Erste Grade aus dem zu pruefenden Punkt(x,y) und einem zweiten Punkt(x+0.333,y+2.333)
+	 GbPoint3D p1;		p1.setX1(x1);			p1.setX2(x2);			p1.setX3(0.0);
+	 GbPoint3D p2;		p2.setX1(x1+0.333);	p2.setX2(x2+3.333);	p2.setX3(0.0);
+	 //Punkte des Dreiecks auf 2D reduziert
+	 GbPoint3D dp1;	dp1.setX1(this->getPoint(0)->getX1Coordinate());	dp1.setX2(this->getPoint(0)->getX2Coordinate());	dp1.setX3(0.0);
+	 GbPoint3D dp2;	dp2.setX1(this->getPoint(1)->getX1Coordinate());	dp2.setX2(this->getPoint(1)->getX2Coordinate());	dp2.setX3(0.0);
+	 GbPoint3D dp3;	dp3.setX1(this->getPoint(2)->getX1Coordinate());	dp3.setX2(this->getPoint(2)->getX2Coordinate());	dp3.setX3(0.0);
+	 //ueberpruefen, ob der Punkt(x,y) innerhalt der Boundingbox des Dreiecks liegt
+	 if(	 x1<this->getX1Maximum() && x1>getX1Minimum()
+		 && x2<this->getX2Maximum() && x2>getX2Minimum())
+	 {
+		 GbPoint3D* dummy = NULL;
+		 //ueberpruefen, ob der Punkt innerhalb des Dreiecks liegt
+		 dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp1,dp2);
+		 if(dummy!=NULL)
+       {
+          if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate())	
+          {
+             delete dummy;
+             return true;
+          }
+			 else if(dummy->getX1Coordinate()>p1.getX1Coordinate())
+          {
+             i++;
+          }
+			 else
+          {
+             i--;
+          }
+       }
+       if(dummy)  delete dummy;
+
+       dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp2,dp3);
+		 if(dummy!=NULL)
+       {
+          if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate())
+          {
+             if(dummy)  delete dummy;
+             return true;
+          }
+			 else if(dummy->getX1Coordinate()>p1.getX1Coordinate())
+          {
+             i++;
+          }
+			 else
+          {
+             i--;
+          }
+       }
+       if(dummy)  delete dummy;
+
+		 dummy = GbSystem3D::calculateIntersectionPoint3D(p1,p2,dp3,dp1);
+		 if(dummy!=NULL)
+       {
+          if(dummy->getX1Coordinate()==p1.getX1Coordinate() && dummy->getX2Coordinate()==p1.getX2Coordinate())
+          {
+             if(dummy)  delete dummy;
+             return true;
+          }
+			 else if(dummy->getX1Coordinate()>p1.getX1Coordinate())
+          {
+             i++;
+          }
+          else
+          {
+             i--;
+          }
+       }
+       if(dummy)  delete dummy;
+	 }
+	 if(i==-1) return true;
+	 if(i==1 ) return true;
+	
+    return false;
+ }
+
+///*
+//* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+//* @param rectangle the 2D rectangle
+//* @return a new 2D polygon clipped by the specified 2D rectangle
+//*/
+GbPolygon3D* GbTriangle3D::createClippedPolygon3D(GbCuboid3D* cube)
+{
+   return(GbSystem3D::clipPolygon3D(this->getPoints(), cube->getPoint1()->getX1Coordinate(), cube->getPoint1()->getX2Coordinate(), cube->getPoint1()->getX3Coordinate(), cube->getPoint2()->getX1Coordinate(), cube->getPoint2()->getX2Coordinate(), cube->getPoint2()->getX3Coordinate()));
+}
+///*
+//* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+//* @param p1 the 1st point of the rectangle
+//* @param p2 the 2nd point of the rectangle
+//* @return a new 2D polygon clipped by the specified 2D rectangle
+//*/
+//public GbPolygon2D createClippedPolygon2D(GbPoint2D p1, GbPoint2D p2)
+//{
+//   return(GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2));
+//}
+/*
+* Returns a new 2D polygon clipped by the specified 2D rectangle (result may be null!).
+* @param p1x1 the 1st x1 coordinate of the rectangle
+* @param p1x2 the 1st x2 coordinate of the rectangle
+* @param p2x1 the 2nd x1 coordinate of the rectangle
+* @param p2x2 the 2nd x2 coordinate of the rectangle
+* @return a new 2D polygon clipped by the specified 2D rectangle
+*/
+GbPolygon3D* GbTriangle3D::createClippedPolygon3D(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3)
+{
+   return(GbSystem3D::clipPolygon3D(this->getPoints(), p1x1, p1x2, p1x3, p2x1, p2x2, p2x3));
+}
+
+/*
+* Returns true if the specified 2D rectangle lies completely within this 2D triangle.
+* @param rectangle the 2D rectangle to check
+* @return true if the specified 2D rectangle lies completely within this 2D triangle
+*/
+//bool enclosesRectangle2D(GbRectangle2D *rectangle)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), rectangle.getArea()));
+//}
+/*
+* Returns true if the specified 2D rectangle lies completely within this 2D triangle.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check                         triangle
+* @return true if the specified 2D rectangle lies completely within this 2D
+*/
+//public boolean enclosesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+//}
+/*
+* Returns true if the specified 2D rectangle lies completely within this 2D triangle.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 2D rectangle lies completely within this 2D triangle
+*/
+//public boolean enclosesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.equal(Math.abs(p.getArea()), Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+//}
+
+/*
+* Returns true if the specified 2D rectangle is crossed by this 2D triangle.
+* @param rectangle the 2D rectangle to check
+* @return true if the specified 2D rectangle is crossed by this 2D triangle
+*/
+//public boolean crossesRectangle2D(GbRectangle2D rectangle)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, rectangle.getArea()));
+//}
+/*
+* Returns true if the specified 2D rectangle is crossed by this 2D triangle.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 2D rectangle is crossed by this 2D triangle
+*/
+//public boolean crossesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1.x1-p2.x1)*(p1.x2-p2.x2))));
+//}
+/*
+* Returns true if the specified 2D rectangle is crossed by this 2D triangle.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 2D rectangle is crossed by this 2D triangle
+*/
+//public boolean crossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.inOpenInterval(Math.abs(p.getArea()), 0.0, Math.abs((p1x1-p2x1)*(p1x2-p2x2))));
+//}
+
+/*
+* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle.
+* @param rectangle the 2D rectangle to check
+* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle
+*/
+//public boolean enclosesOrCrossesRectangle2D(GbRectangle2D rectangle)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, rectangle.p1.x1, rectangle.p1.x2, rectangle.p2.x1, rectangle.p2.x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*
+* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle.
+* @param p1 the 1st point of the rectangle to check
+* @param p2 the 2nd point of the rectangle to check
+* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle
+*/
+//public boolean enclosesOrCrossesRectangle2D(GbPoint2D p1, GbPoint2D p2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1.x1, p1.x2, p2.x1, p2.x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*
+* Returns true if the specified 2D rectangle lies (at least partly) within this 2D triangle.
+* @param p1x1 the 1st x1 coordinate of the rectangle to check
+* @param p1x2 the 1st x2 coordinate of the rectangle to check
+* @param p2x1 the 2nd x1 coordinate of the rectangle to check
+* @param p2x2 the 2nd x2 coordinate of the rectangle to check
+* @return true if the specified 2D rectangle lies (at least partly) within this 2D triangle
+*/
+//public boolean enclosesOrCrossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2)
+//{
+//   GbPolygon2D p = GbSystem.clipPolygon2D(this.points, p1x1, p1x2, p2x1, p2x2);
+//   return(p!=null && GbSystem.greater(Math.abs(p.getArea()), 0.0));
+//}
+/*======================================================================*/
+
+
+/*======================================================================*/
+/*  Private Methoden                                                    */
+/*                                                                      */
+void GbTriangle3D::calculateValues()
+{
+   this->x1min = this->points[0]->x1;
+   this->x1max = this->points[0]->x1;
+   this->x2min = this->points[0]->x2;
+   this->x2max = this->points[0]->x2;
+   this->x3min = this->points[0]->x3;
+   this->x3max = this->points[0]->x3;
+
+   if(this->points[1]->x1 < this->x1min) this->x1min = this->points[1]->x1;
+   if(this->points[1]->x1 > this->x1max) this->x1max = this->points[1]->x1;
+   if(this->points[1]->x2 < this->x2min) this->x2min = this->points[1]->x2;
+   if(this->points[1]->x2 > this->x2max) this->x2max = this->points[1]->x2;
+   if(this->points[1]->x3 < this->x3min) this->x3min = this->points[1]->x3;
+   if(this->points[1]->x3 > this->x3max) this->x3max = this->points[1]->x3;
+
+   if(this->points[2]->x1 < this->x1min) this->x1min = this->points[2]->x1;
+   if(this->points[2]->x1 > this->x1max) this->x1max = this->points[2]->x1;
+   if(this->points[2]->x2 < this->x2min) this->x2min = this->points[2]->x2;
+   if(this->points[2]->x2 > this->x2max) this->x2max = this->points[2]->x2;
+   if(this->points[2]->x3 < this->x3min) this->x3min = this->points[2]->x3;
+   if(this->points[2]->x3 > this->x3max) this->x3max = this->points[2]->x3;
+
+   this->x1s   = (this->points[0]->x1+this->points[1]->x1+this->points[2]->x1)/3.0;
+   this->x2s   = (this->points[0]->x2+this->points[1]->x2+this->points[2]->x2)/3.0;
+   this->x3s   = (this->points[0]->x3+this->points[1]->x3+this->points[2]->x3)/3.0;
+
+   GbVector3D A(points[0]->x1,points[0]->x2,points[0]->x3);
+   GbVector3D B(points[1]->x1,points[1]->x2,points[1]->x3);
+   GbVector3D C(points[2]->x1,points[2]->x2,points[2]->x3);
+   GbVector3D AB = B-A;
+   GbVector3D AC = C-A;
+   GbVector3D N = AB.Cross(AC);
+   this->area = 0.5*N.Length();
+   this->consistent = true;
+}
+/*======================================================================*/
+
+
+/*======================================================================*/
+//class PointObserver : public UbObserver
+//{
+//    GbTriangle3D *triangle;
+
+//    PointObserver(GbTriangle3D *triangle)
+//    {
+//      this->triangle = triangle;
+//    }
+
+//public:
+//   void objectChanged(GbObject3D *object)
+//    {
+//      if(object == this->triangle->points[0] || object == this->triangle->points[1]  || object == this->triangle->points[2])
+//      {
+//         this->triangle->consistent = false;
+//         this->triangle->notifyObservers();
+//      }
+//    }
+//};
+//bool GbTriangle3D::isPointOnEdge(GbVector3D& q)
+//{
+////cout<<"muss einer machen ...\n";
+//   return false;
+//}
+/*======================================================================*/
+GbVector3D GbTriangle3D::getNormal()
+{
+   this->calculateNormal();
+   return normal; 
+}
+/*======================================================================*/
+void GbTriangle3D::init()
+{
+   x1s        = 0.0;
+   x2s        = 0.0;
+   x3s        = 0.0;
+   x1min      = 0.0;
+   x1max      = 0.0;
+   x2min      = 0.0;
+   x2max      = 0.0;
+   area       = 0.0;
+   consistent = false;
+   points.resize(3,NULL);
+}
+/*=======================================================*/
+void GbTriangle3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   if(points[0]) points[0]->write(out);
+   else {GbPoint3D tmp; tmp.write(out);}
+   if(points[1]) points[1]->write(out);
+   else {GbPoint3D tmp; tmp.write(out);}
+   if(points[2]) points[2]->write(out);
+   else {GbPoint3D tmp; tmp.write(out);}
+}
+/*=======================================================*/
+void GbTriangle3D::read(UbFileInput* in) 
+{  
+   this->deletePoints();
+   points[0] = new GbPoint3D;
+   points[1] = new GbPoint3D;
+   points[2] = new GbPoint3D;
+   in->readString();                                    
+   points[0]->read(in);
+   in->readString();                                    
+   points[1]->read(in);
+   in->readString();                                    
+   points[2]->read(in);
+   consistent = false;
+}
+/*=======================================================*/
+void GbTriangle3D::calculateNormal()
+{
+   GbPoint3D*& a = points[0]; 
+   GbPoint3D*& b = points[1];
+   GbPoint3D*& c = points[2];
+   normal[0] = ( c->getX3Coordinate() - a->getX3Coordinate()) * ( b->getX2Coordinate() - a->getX2Coordinate() ) -
+               ( b->getX3Coordinate() - a->getX3Coordinate()) * ( c->getX2Coordinate() - a->getX2Coordinate() );
+   normal[1] = ( b->getX3Coordinate() - a->getX3Coordinate()) * ( c->getX1Coordinate() - a->getX1Coordinate() ) -
+               ( b->getX1Coordinate() - a->getX1Coordinate()) * ( c->getX3Coordinate() - a->getX3Coordinate() );
+   normal[2] = ( b->getX1Coordinate() - a->getX1Coordinate()) * ( c->getX2Coordinate() - a->getX2Coordinate() ) -
+               ( b->getX2Coordinate() - a->getX2Coordinate()) * ( c->getX1Coordinate() - a->getX1Coordinate() );
+   normal.Normalize();
+}
+/*=======================================================*/
+//toDo: 
+double GbTriangle3D::getDistanceFromPoint(GbVector3D punct)
+{
+	GbVector3D Point1(this->getPoint1()->getX1Coordinate(), this->getPoint1()->getX2Coordinate(), this->getPoint1()->getX3Coordinate());
+	GbVector3D Point2(this->getPoint2()->getX1Coordinate(), this->getPoint2()->getX2Coordinate(), this->getPoint2()->getX3Coordinate());
+	GbVector3D Point3(this->getPoint3()->getX1Coordinate(), this->getPoint3()->getX2Coordinate(), this->getPoint3()->getX3Coordinate());
+
+	GbVector3D kDiff = Point1 - punct;
+	GbVector3D kEdge0 = Point2 - Point1;
+	GbVector3D kEdge1 = Point3 - Point1;
+	double fA00 = kEdge0.SquaredLength();
+	double fA01 = kEdge0.Dot(kEdge1);
+	double fA11 = kEdge1.SquaredLength();
+	double fB0 = kDiff.Dot(kEdge0);
+	double fB1 = kDiff.Dot(kEdge1);
+	double fC = kDiff.SquaredLength();
+	double fDet = fabs(fA00*fA11-fA01*fA01);
+	double fS = fA01*fB1-fA11*fB0;
+	double fT = fA01*fB0-fA00*fB1;
+	double fSqrDistance;
+
+	if (fS + fT <= fDet)
+	{
+		if (fS < (double)0.0)
+		{
+			if (fT < (double)0.0)  // region 4
+			{
+				if (fB0 < (double)0.0)
+				{
+					fT = (double)0.0;
+					if (-fB0 >= fA00)
+					{
+						fS = (double)1.0;
+						fSqrDistance = fA00+((double)2.0)*fB0+fC;
+					}
+					else
+					{
+						fS = -fB0/fA00;
+						fSqrDistance = fB0*fS+fC;
+					}
+				}
+				else
+				{
+					fS = (double)0.0;
+					if (fB1 >= (double)0.0)
+					{
+						fT = (double)0.0;
+						fSqrDistance = fC;
+					}
+					else if (-fB1 >= fA11)
+					{
+						fT = (double)1.0;
+						fSqrDistance = fA11+((double)2.0)*fB1+fC;
+					}
+					else
+					{
+						fT = -fB1/fA11;
+						fSqrDistance = fB1*fT+fC;
+					}
+				}
+			}
+			else  // region 3
+			{
+				fS = (double)0.0;
+				if (fB1 >= (double)0.0)
+				{
+					fT = (double)0.0;
+					fSqrDistance = fC;
+				}
+				else if (-fB1 >= fA11)
+				{
+					fT = (double)1.0;
+					fSqrDistance = fA11+((double)2.0)*fB1+fC;
+				}
+				else
+				{
+					fT = -fB1/fA11;
+					fSqrDistance = fB1*fT+fC;
+				}
+			}
+		}
+		else if (fT < (double)0.0)  // region 5
+		{
+			fT = (double)0.0;
+			if (fB0 >= (double)0.0)
+			{
+				fS = (double)0.0;
+				fSqrDistance = fC;
+			}
+			else if (-fB0 >= fA00)
+			{
+				fS = (double)1.0;
+				fSqrDistance = fA00+((double)2.0)*fB0+fC;
+			}
+			else
+			{
+				fS = -fB0/fA00;
+				fSqrDistance = fB0*fS+fC;
+			}
+		}
+		else  // region 0
+		{
+			// minimum at interior point
+			double fInvDet = ((double)1.0)/fDet;
+			fS *= fInvDet;
+			fT *= fInvDet;
+			fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) +
+				fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC;
+		}
+	}
+	else
+	{
+		double fTmp0, fTmp1, fNumer, fDenom;
+
+		if (fS < (double)0.0)  // region 2
+		{
+			fTmp0 = fA01 + fB0;
+			fTmp1 = fA11 + fB1;
+			if (fTmp1 > fTmp0)
+			{
+				fNumer = fTmp1 - fTmp0;
+				fDenom = fA00-2.0f*fA01+fA11;
+				if (fNumer >= fDenom)
+				{
+					fS = (double)1.0;
+					fT = (double)0.0;
+					fSqrDistance = fA00+((double)2.0)*fB0+fC;
+				}
+				else
+				{
+					fS = fNumer/fDenom;
+					fT = (double)1.0 - fS;
+					fSqrDistance = fS*(fA00*fS+fA01*fT+2.0f*fB0) +
+						fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC;
+				}
+			}
+			else
+			{
+				fS = (double)0.0;
+				if (fTmp1 <= (double)0.0)
+				{
+					fT = (double)1.0;
+					fSqrDistance = fA11+((double)2.0)*fB1+fC;
+				}
+				else if (fB1 >= (double)0.0)
+				{
+					fT = (double)0.0;
+					fSqrDistance = fC;
+				}
+				else
+				{
+					fT = -fB1/fA11;
+					fSqrDistance = fB1*fT+fC;
+				}
+			}
+		}
+		else if (fT < (double)0.0)  // region 6
+		{
+			fTmp0 = fA01 + fB1;
+			fTmp1 = fA00 + fB0;
+			if (fTmp1 > fTmp0)
+			{
+				fNumer = fTmp1 - fTmp0;
+				fDenom = fA00-((double)2.0)*fA01+fA11;
+				if (fNumer >= fDenom)
+				{
+					fT = (double)1.0;
+					fS = (double)0.0;
+					fSqrDistance = fA11+((double)2.0)*fB1+fC;
+				}
+				else
+				{
+					fT = fNumer/fDenom;
+					fS = (double)1.0 - fT;
+					fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) +
+						fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC;
+				}
+			}
+			else
+			{
+				fT = (double)0.0;
+				if (fTmp1 <= (double)0.0)
+				{
+					fS = (double)1.0;
+					fSqrDistance = fA00+((double)2.0)*fB0+fC;
+				}
+				else if (fB0 >= (double)0.0)
+				{
+					fS = (double)0.0;
+					fSqrDistance = fC;
+				}
+				else
+				{
+					fS = -fB0/fA00;
+					fSqrDistance = fB0*fS+fC;
+				}
+			}
+		}
+		else  // region 1
+		{
+			fNumer = fA11 + fB1 - fA01 - fB0;
+			if (fNumer <= (double)0.0)
+			{
+				fS = (double)0.0;
+				fT = (double)1.0;
+				fSqrDistance = fA11+((double)2.0)*fB1+fC;
+			}
+			else
+			{
+				fDenom = fA00-2.0f*fA01+fA11;
+				if (fNumer >= fDenom)
+				{
+					fS = (double)1.0;
+					fT = (double)0.0;
+					fSqrDistance = fA00+((double)2.0)*fB0+fC;
+				}
+				else
+				{
+					fS = fNumer/fDenom;
+					fT = (double)1.0 - fS;
+					fSqrDistance = fS*(fA00*fS+fA01*fT+((double)2.0)*fB0) +
+						fT*(fA01*fS+fA11*fT+((double)2.0)*fB1)+fC;
+				}
+			}
+		}
+	}
+
+	// account for numerical round-off error
+	if (fSqrDistance < (double)0.0)
+	{
+		fSqrDistance = (double)0.0;
+	}
+/*
+	m_kClosestPoint0 = punct;
+	m_kClosestPoint1 = m_rkTriangle.V[0] + fS*kEdge0 + fT*kEdge1;
+	m_afTriangleBary[1] = fS;
+	m_afTriangleBary[2] = fT;
+	m_afTriangleBary[0] = (double)1.0 - fS - fT;
+*/
+	return sqrt(fSqrDistance);
+}
diff --git a/source/VirtualFluidsCore/Geometry/GbTriangle3D.h b/source/VirtualFluidsCore/Geometry/GbTriangle3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..42072eb2d153ff473e634818add9da8f7194f133
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbTriangle3D.h
@@ -0,0 +1,248 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBTRIANGLE3D_H
+#define GBTRIANGLE3D_H
+
+#include <sstream>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <numerics/geometry3d/GbVector3D.h>
+#include <numerics/geometry3d/GbPoint3D.h>
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbTriangle3D;
+typedef VFSharedPtr<GbTriangle3D> GbTriangle3DPtr;
+
+
+class GbCuboid3D;
+class GbPolygon3D;
+class GbObject3DCreator;
+
+/*=========================================================================*/
+/* GbTriangle3D                                                            */
+/*                                                                         */
+/*                                                               
+* This Class provides basic 3D triangle objects.
+*/
+//class GbLine2D;
+
+class GbTriangle3D : public GbObject3D , public UbObserver
+{
+public:
+   /*======================================================================*/
+   /*  Konstruktoren                                                       */
+   /*                                                                      */
+   GbTriangle3D();
+   GbTriangle3D(GbPoint3D* point1, GbPoint3D* point2, GbPoint3D* point3);
+   GbTriangle3D(GbTriangle3D* triangle);
+   ~GbTriangle3D();
+   /*======================================================================*/
+   /*  Methoden                                                            */
+   /*                                                                      */
+   GbTriangle3D* clone();
+   void finalize()
+   {
+      this->deletePoints();
+   }
+
+   GbPoint3D* getPoint1()   { return this->points[0]; }
+   GbPoint3D* getPoint2()   { return this->points[1]; }
+   GbPoint3D* getPoint3()   { return this->points[2]; }
+
+   GbVector3D getNormal();
+   void       calculateNormal();
+
+   void deletePoints();
+
+   int contains(GbPoint3D* point);
+   int containsEqual(GbPoint3D* point);
+   GbPoint3D* getPoint(const int& index);
+   std::vector<GbPoint3D> getPoints();
+   double getArea();
+   double getX1Centroid();
+   double getX1Minimum();
+   double getX1Maximum();           
+   double getX2Centroid();
+   double getX2Minimum();
+   double getX2Maximum();
+   double getX3Centroid();
+   double getX3Minimum();
+   double getX3Maximum();
+
+   void setInconsistent() { this->consistent = false;}
+
+   void setPoint(GbPoint3D *point, int index);
+
+   //bool equals(GbObject3D *object)
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3)   
+   {
+      //der einfachheit halber ... 
+      return false;
+      //throw UbException(__FILE__, __LINE__, "GbTriangle3D::isPointInObject3D- not implemented");
+   }
+   bool isPointInGbObject3D(const double& x1, const double& x2, const double& x3, bool& pointIsOnBoundary)   
+   {
+      //der einfachheit halber ... 
+      pointIsOnBoundary = false;
+      return false;
+      //throw UbException(__FILE__, __LINE__, "GbTriangle3D::isPointInObject3D- not implemented");
+   }
+   bool isCellInsideGbObject3D(const double& x11,const double& x21,const double& x31,const double& x12,const double& x22,const double& x23) { return false; }
+
+
+   // get distance from a point to the triangle
+   //todo CHANGE...
+   double getDistanceFromPoint(GbVector3D punct);
+
+   std::string toString();
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+   /*======================================================================*/
+   /*  Calculation                                                         */
+   /*                                                                      */
+//   std::vector<GbPoint3D> calculateIntersectionPoints3D(GbLine3D *line);
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+//   bool isPointOnEdge(GbVector3D& q);
+   
+   GbPoint3D* calculateIntersectionPoints3D(GbLine3D* line);
+   GbPoint3D* calculateIntersectionPoints3D(GbPoint3D* linePoint1, GbPoint3D* linePoint2);
+   double calculateDistanceToPoint3D(GbPoint3D *point);
+   double calculateDistanceToPoint3D(const double& x1, const double& x2, const double& x3);      
+   double calculateNormalizedDistanceToPoint3D(const double& x1, const double& y1, const double& z1, const double& x2, const double& y2, const double& z2);
+
+   bool enclosesPoint2D(double x1, double x2);
+   GbPolygon3D* createClippedPolygon3D(GbCuboid3D* cube);   
+   GbLine3D* createClippedLine3D (GbPoint3D& point1, GbPoint3D& point2);
+   //public GbPolygon2D createClippedPolygon2D(GbPoint2D p1, GbPoint2D p2);
+   GbPolygon3D* createClippedPolygon3D(const double& p1x1, const double& p1x2, const double& p1x3, const double& p2x1, const double& p2x2, const double& p2x3);
+   //bool enclosesRectangle2D(GbRectangle2D *rectangle);
+   //public boolean enclosesRectangle2D(GbPoint2D p1, GbPoint2D p2);
+   //public boolean enclosesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2);
+   //public boolean crossesRectangle2D(GbRectangle2D rectangle);
+   //public boolean crossesRectangle2D(GbPoint2D p1, GbPoint2D p2);
+   //public boolean crossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2);
+   //public boolean enclosesOrCrossesRectangle2D(GbRectangle2D rectangle);
+   //public boolean enclosesOrCrossesRectangle2D(GbPoint2D p1, GbPoint2D p2);
+   //public boolean enclosesOrCrossesRectangle2D(double p1x1, double p1x2, double p2x1, double p2x2);
+   /*======================================================================*/
+   /*======================================================================*/
+   /*  Private Methoden                                                    */
+   /*                                                                      */
+   virtual void calculateValues();
+
+   /*======================================================================*/
+   //class PointObserver : public UbObserver
+   //{
+   //    GbTriangle3D *triangle;
+
+   //    PointObserver(GbTriangle3D *triangle)
+   //    {
+   //      this->triangle = triangle;
+   //    }
+
+   //public:
+   //   void objectChanged(GbObject3D *object)
+   //    {
+   //      if(object == this->triangle->points[0] || object == this->triangle->points[1]  || object == this->triangle->points[2])
+   //      {
+   //         this->triangle->consistent = false;
+   //         this->triangle->notifyObservers();
+   //      }
+   //    }
+   //};
+   /*======================================================================*/
+
+   //virtuelle Methoden von UbObserver
+   //!! quick and dirty von sirann !!
+   void objectChanged(UbObservable* changedObject)
+   {
+      GbPoint3D* point = dynamic_cast<GbPoint3D*>(changedObject);
+      if(!point || (  this->points[0]!=point && this->points[1]!=point && this->points[2]!=point) ) 
+         return;
+      
+      this->consistent = false;
+   }
+   void objectWillBeDeleted(UbObservable* objectForDeletion)
+   {
+      if(this->points[0])
+      {
+         UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[0]);
+         if(objectForDeletion == observedObj) { this->points[0] = NULL; }
+      }
+      if(this->points[1])
+      {
+         UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[1]);
+         if(objectForDeletion == observedObj) { this->points[1] = NULL; }
+      }
+      if(this->points[2])
+      {
+         UbObservable* observedObj = dynamic_cast<UbObservable*>(this->points[2]);
+         if(objectForDeletion == observedObj) { this->points[2] = NULL; }
+      }
+      //ACHTUNG: eigentlich muessten in allen methoden von GbLine if abfragen fuer NULL pointer hin... toDo
+   }
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & points;
+      ar & normal;
+      ar & x1s;
+      ar & x2s;
+      ar & x3s;
+      ar & x1min;
+      ar & x1max;
+      ar & x2min;
+      ar & x2max;
+      ar & x3min;
+      ar & x3max;
+      ar & area;
+      ar & consistent;
+      if( ArchiveTools::isReading(ar) ) this->calculateNormal();
+   }
+#endif //CAB_RCF
+
+protected:
+   bool   consistent;
+   double x1s;
+   double x2s;
+   double x3s;
+   double x1min;
+   double x1max;
+   double x2min;
+   double x2max;
+   double x3min;
+   double x3max;
+   double area;
+   
+   GbVector3D normal;
+   std::vector<GbPoint3D*> points;
+   
+private:
+   void init();
+};
+/*=========================================================================*/
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbTriangle3D  >("GbTriangle3D  ")        , SF_GbTriangle3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbTriangle3D >() ), SF_GbTriangle3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbTriangle3D>()  ), SF_GbTriangle3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+#endif
diff --git a/source/VirtualFluidsCore/Geometry/GbVoxelMatrix3D.cpp b/source/VirtualFluidsCore/Geometry/GbVoxelMatrix3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..93fe1064aa945c3f5491c7fff9442a9efec62f86
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbVoxelMatrix3D.cpp
@@ -0,0 +1,1027 @@
+#include <numerics/geometry3d/GbVoxelMatrix3D.h>
+
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbFileInputASCII.h>
+#include <numerics/geometry3d/creator/GbVoxelMatrix3DCreator.h>
+#include <numerics/geometry3d/GbTriangle3D.h>
+#include <basics/utilities/UbFileOutputASCII.h>
+#include <numerics/geometry3d/CoordinateTransformation3D.h>
+
+#include <basics/utilities/UbSystem.h>
+
+#ifdef MC_CUBES
+   #include <3rdParty/MarchingCubes/MarchingCubes.h>
+#endif // MC_CUBES
+
+using namespace std;
+
+const float GbVoxelMatrix3D::SOLID = 1.0f;
+const float GbVoxelMatrix3D::FLUID = 0.0f;
+
+
+/*=======================================================*/
+ObObjectCreator* GbVoxelMatrix3D::getCreator()
+{
+   return GbVoxelMatrix3DCreator::getInstance();
+}
+/*=======================================================*/
+// Konstruktor
+GbVoxelMatrix3D::GbVoxelMatrix3D(int nx1, int nx2, int nx3, float initVal, double lowerThreshold, double upperThreshold)
+   : GbObject3D()
+   , minX1(0.0)
+   , minX2(0.0)
+   , minX3(0.0)
+   , lowerThreshold(lowerThreshold)
+   , upperThreshold(upperThreshold)
+   , nodesX1(nx1)
+   , nodesX2(nx2)
+   , nodesX3(nx3)
+   , deltaX1(1.0)
+   , deltaX2(1.0)
+   , deltaX3(1.0)
+   , transferViaFilename(false)
+   , addSurfaceTriangleSetFlag(true)
+   , voxelMatrix(Matrix3D(nx1, nx2, nx3, initVal))
+{
+   this->setName("VoxelMatrix3D");
+}
+/*=======================================================*/
+GbVoxelMatrix3D::GbVoxelMatrix3D() 
+  :   GbObject3D()
+    , minX1(0.0)
+    , minX2(0.0)
+    , minX3(0.0)
+    , nodesX1(0)
+    , nodesX2(0)
+    , nodesX3(0)
+    , lowerThreshold(0.0)
+    , upperThreshold(0.0)
+    , deltaX1(1.0)
+    , deltaX2(1.0)
+    , deltaX3(1.0)
+    , transferViaFilename(false)
+    , addSurfaceTriangleSetFlag(true)
+{
+   this->setName("VoxelMatrix3D");
+}
+/*=======================================================*/
+GbVoxelMatrix3D::GbVoxelMatrix3D(const Matrix3D& voxelMatrix, double lowerThreshold, double upperThreshold)
+  :   GbObject3D()
+    , minX1(0.0)
+    , minX2(0.0)
+    , minX3(0.0)
+    , nodesX1((int)voxelMatrix.getNX1())
+    , nodesX2((int)voxelMatrix.getNX2())
+    , nodesX3((int)voxelMatrix.getNX3())
+    , lowerThreshold(lowerThreshold)
+    , upperThreshold(upperThreshold)
+    , deltaX1(1.0)
+    , deltaX2(1.0)
+    , deltaX3(1.0)
+    , transferViaFilename(false)
+    , addSurfaceTriangleSetFlag(true)
+    , voxelMatrix(voxelMatrix)
+{
+   this->setName("VoxelMatrix3D");
+}
+/*=======================================================*/
+GbVoxelMatrix3D*  GbVoxelMatrix3D::clone()
+{
+   GbVoxelMatrix3D* vm = new GbVoxelMatrix3D(this->voxelMatrix, lowerThreshold, upperThreshold);
+   vm->setVoxelMatrixMininum(minX1, minX2, minX3);
+   vm->setVoxelMatrixDelta(deltaX1, deltaX2, deltaX3);
+   return  vm;
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::setCenterCoordinates(const double& x1, const double& x2, const double& x3) 
+{
+   this->translate(x1-getX1Centroid(), x2-getX2Centroid(), x3-getX3Centroid() );
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::translate(const double& tx1, const double& tx2, const double& tx3)
+{  
+   this->minX1 += tx1;
+   this->minX2 += tx2;
+   this->minX3 += tx3;
+   this->notifyObserversObjectChanged();
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::setClosedVoidSpaceToSolid()
+{
+   voxelMatrixTemp = Matrix3D(nodesX1, nodesX2, nodesX3, SOLID);
+   flagMatrix = CbArray3D<char>(nodesX1, nodesX2, nodesX3, 0);
+
+   for (int x3 = 0; x3<nodesX3; x3++)
+   {
+      for (int x2 = 0; x2<nodesX2; x2++)
+      {
+         for (int x1 = 0; x1<nodesX1; x1++)
+         {
+            if (voxelMatrix(x1, x2, x3)==FLUID)
+            {
+               UBLOG(logINFO, "setClosedVoidSpaceToSolid:start");
+               x1Nbr.push_back(x1);
+               x2Nbr.push_back(x2);
+               x3Nbr.push_back(x3);
+               int size = (int)x1Nbr.size();
+               while (size > 0)
+               {
+                  for (int i = 0; i < size; i++)
+                  {
+                     findFluidNeighbor(x1Nbr[i], x2Nbr[i], x3Nbr[i]);
+                  }
+
+                  swap(x1Nbr, x1NbrTemp);
+                  swap(x2Nbr, x2NbrTemp);
+                  swap(x3Nbr, x3NbrTemp);
+
+                  x1NbrTemp.clear();
+                  x2NbrTemp.clear();
+                  x3NbrTemp.clear();
+                  size = x1Nbr.size();
+               }
+               UBLOG(logINFO, "setClosedVoidSpaceToSolid:end");
+               voxelMatrix = voxelMatrixTemp;
+               return;
+            }
+
+         }
+      }
+   }
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::findFluidNeighbor(int x1, int x2, int x3)
+{
+   for (int k3 = -1; k3<=1; k3++)
+   {
+      for (int k2 = -1; k2<=1; k2++)
+      {
+         for (int k1 = -1; k1<=1; k1++)
+         {
+            int j1 = x1+k1;
+            int j2 = x2+k2;
+            int j3 = x3+k3;
+            if (j1>=0 && j1<nodesX1 && j2>=0 && j2<nodesX2 && j3>=0 && j3<nodesX3)
+            {
+               if (voxelMatrix(j1, j2, j3)==FLUID)
+               {
+                  if (flagMatrix(j1, j2, j3) == 0)
+                  {
+                     voxelMatrixTemp(j1, j2, j3) = FLUID;
+                     flagMatrix(j1, j2, j3) = 1;
+                     x1NbrTemp.push_back(j1);
+                     x2NbrTemp.push_back(j2);
+                     x3NbrTemp.push_back(j3);
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::calculateNumberOfSolidAndFluid()
+{
+   numberOfSolid = 0;
+
+   for (int x3 = 0; x3<nodesX3; x3++)
+      for (int x2 = 0; x2<nodesX2; x2++)
+         for (int x1 = 0; x1<nodesX1; x1++)
+         {
+            if (voxelMatrix(x1, x2, x3) == GbVoxelMatrix3D::SOLID)
+            {
+               numberOfSolid++;
+            }
+         }
+
+   numberOfFluid = (long)nodesX1*(long)nodesX2*(long)nodesX3 - numberOfSolid;
+}
+/*=======================================================*/
+long GbVoxelMatrix3D::getNumberOfSolid()
+{
+   return numberOfSolid;
+}
+/*=======================================================*/
+long GbVoxelMatrix3D::getNumberOfFluid()
+{
+   return numberOfFluid;
+}
+/*=======================================================*/
+double GbVoxelMatrix3D::getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3)
+{
+   if( !(    (UbMath::equal(rx1,0.0) || UbMath::equal(fabs(rx1),1.0) || UbMath::equal(fabs(rx1),UbMath::one_over_sqrt2) )
+          && (UbMath::equal(rx2,0.0) || UbMath::equal(fabs(rx2),1.0) || UbMath::equal(fabs(rx2),UbMath::one_over_sqrt2) )
+          && (UbMath::equal(rx3,0.0) || UbMath::equal(fabs(rx3),1.0) || UbMath::equal(fabs(rx3),UbMath::one_over_sqrt2) ) ) )
+   {
+      throw UbException(UB_EXARGS,"nur fuer diskrete Boltzmannrichungen implementiert!!!");
+   }
+
+   //nachbarindex ermitteln
+   int ndx1 = 0, ndx2 = 0, ndx3 = 0;
+   if (UbMath::greater(rx1, 0.0)) ndx1 = 1;
+   else if (UbMath::less(rx1, 0.0)) ndx1 = -1;
+   if (UbMath::greater(rx2, 0.0)) ndx2 = 1;
+   else if (UbMath::less(rx2, 0.0)) ndx2 = -1;
+   if (UbMath::greater(rx3, 0.0)) ndx3 = 1;
+   else if (UbMath::less(rx3, 0.0)) ndx3 = -1;
+
+   int nix1 = UbMath::integerRounding( (x1-minX1)/deltaX1 )+ndx1;
+   int nix2 = UbMath::integerRounding( (x2-minX2)/deltaX2 )+ndx2;
+   int nix3 = UbMath::integerRounding( (x3-minX3)/deltaX3 )+ndx3;
+
+   //test ob nachbar solid
+   if(    nix1>=0 
+       && nix2>=0 
+       && nix3>=0 
+       && nix1<voxelMatrix.getNX1()
+       && nix2<voxelMatrix.getNX2()
+       && nix3<voxelMatrix.getNX3() )
+   {
+      if( UbMath::equal(voxelMatrix(nix1,nix2,nix3), SOLID) )
+      {
+         //return halber abstand der beiden knoten
+         return 0.5*sqrt(  (ndx1*deltaX1)*(ndx1*deltaX1) 
+                         + (ndx2*deltaX2)*(ndx2*deltaX2)
+                         + (ndx3*deltaX3)*(ndx3*deltaX3) );
+      }
+   }
+
+   return 0.0;
+}	
+/*=======================================================*/
+bool GbVoxelMatrix3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p)
+{
+   //index ermitteln
+   int ix1 = UbMath::integerRounding( (x1p-minX1)/deltaX1 );
+   int ix2 = UbMath::integerRounding( (x2p-minX2)/deltaX2 );
+   int ix3 = UbMath::integerRounding( (x3p-minX3)/deltaX3 );
+
+   if(    ix1>=0 
+       && ix2>=0 
+       && ix3>=0 
+       && ix1<voxelMatrix.getNX1() 
+       && ix2<voxelMatrix.getNX2()
+       && ix3<voxelMatrix.getNX3() )
+   {
+      if (UbMath::equal(voxelMatrix(ix1, ix2, ix3), SOLID)) return true;
+   }
+
+   return false;
+}
+/*=======================================================*/
+bool GbVoxelMatrix3D::isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary)
+{
+   pointIsOnBoundary = false;
+   
+   return isPointInGbObject3D(x1p,x2p,x3p);
+}
+/*=======================================================*/
+bool GbVoxelMatrix3D::isCellInsideGbObject3D(const double& x1p1,const double& x2p1,const double& x3p1,const double& x1p2,const double& x2p2,const double& x3p2)
+{
+   return false;
+//dass hängt von der Konfigration ab, aber meist ist der Block grösser wie etliche Poren ...
+
+   //indizes ermitteln
+   int startix1 = (int)std::floor( (x1p1-minX1)/deltaX1+1E-13 );
+   int startix2 = (int)std::floor( (x2p1-minX2)/deltaX2+1E-13 );
+   int startix3 = (int)std::floor( (x3p1-minX3)/deltaX3+1E-13 );
+
+   if(startix1<0 ) return false;
+   if(startix2<0 ) return false;
+   if(startix3<0 ) return false;
+
+   int maxiX1 = (int)voxelMatrix.getNX1()-1;
+   int maxiX2 = (int)voxelMatrix.getNX2()-1;
+   int maxiX3 = (int)voxelMatrix.getNX3()-1;
+
+   int endix1 = (int)std::ceil( (x1p2-minX1)/deltaX1-1E-13 );
+   int endix2 = (int)std::ceil( (x2p2-minX2)/deltaX2-1E-13 );
+   int endix3 = (int)std::ceil( (x3p2-minX3)/deltaX3-1E-13 );
+
+   if(endix1>maxiX1 ) return false;
+   if(endix2>maxiX2 ) return false;
+   if(endix3>maxiX3 ) return false;
+
+   for(int ix3=startix3; ix3<=endix3; ix3++)
+      for(int ix2=startix2; ix2<=endix2; ix2++)
+         for(int ix1=startix1; ix1<=endix1; ix1++)
+            if( UbMath::equal(voxelMatrix(ix1,ix2,ix3), FLUID ) ) 
+               return false;
+   return true;
+}
+/*=======================================================*/
+bool GbVoxelMatrix3D::isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//Merksatz: cell oder deren Volumen schneidet oder beinhaltet komplette oder Teile der CuboidUmrandung
+//returns true:
+//  - cell cuts  GbVoxelMatrix3D
+//  - cell boxes GbVoxelMatrix3D
+//returns false:
+//  - cell completely inside GbVoxelMatrix3D 
+//  - cell und cuboid3D haben kein gemeinsames Volumen
+{
+   //erstmal die dumm Loesung
+   if(  !( this->isCellInsideGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )   
+      &&   this->isCellInsideOrCuttingGbObject3D(x1a,x2a,x3a,x1b,x2b,x3b) )
+   {
+      return true;
+   }
+
+   return false;
+}
+/*=======================================================*/
+bool GbVoxelMatrix3D::isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b)
+//returns true:
+//  - cell completely inside cuboid3D ( = cuboid3D boxes cell)
+//  - cell cuts  cuboid3D
+//  - cell boxes cuboid3D
+//returns false:
+//  - cell und cuboid3D haben kein gemeinsames Volumen
+{
+    //simpler check, da unser GbCuboid3D ein AABB is:
+   //  anfA        midA         endA             anfB    midB    endB
+   //   |            x<-- dxA -->|                 |<-dxB->x       |
+   //                |<----------------- T --------------->|
+   //ist |T| <= dxA + dxB -> overlap!
+
+   if(     UbMath::lessEqual(  std::fabs( this->getX1Centroid() - 0.5*(x1b+x1a)      /*Tx1*/      )
+                             , 0.5*( this->getLengthX1()        + std::fabs(x1b-x1a) /*dx1A+dx1B*/) )
+
+        && UbMath::lessEqual(  std::fabs( this->getX2Centroid() - 0.5*(x2b+x2a)      /*Tx2*/      )
+                             , 0.5*( this->getLengthX2()        + std::fabs(x2b-x2a) /*dx2A+dx2B*/) )
+
+        && UbMath::lessEqual(  std::fabs( this->getX3Centroid() - 0.5*(x3b+x3a)      /*Tx3*/      )
+                             , 0.5*( this->getLengthX3()        + std::fabs(x3b-x3a) /*dx3A+dx3B*/) ) )
+    {
+       return true;
+    }
+
+    return false;
+}
+/*=======================================================*/
+vector<GbTriangle3D*> GbVoxelMatrix3D::getSurfaceTriangleSet()
+{
+   vector<GbTriangle3D*> triangles;
+   
+   #ifdef MC_CUBES
+      //MC
+      typedef McCubes::Matrix3DWrapper< Matrix3D >                McMatrixWrapper;
+      typedef McCubes::MarchingCubes< McMatrixWrapper >           McMarchingCubesGenerator;
+      typedef McMarchingCubesGenerator::Vertex                    McVertex;
+      typedef McMarchingCubesGenerator::Triangle                  McTriangle;
+
+      McMatrixWrapper wrapper(&voxelMatrix);//,0,0,0,voxelMatrix.getNX1()-1,voxelMatrix.getNX2()-1,voxelMatrix.getNX3()-1);
+      McMarchingCubesGenerator mc(wrapper);
+
+      mc.init_all();
+      mc.run(0.5);
+
+      //const int   nofVertices  = mc.nverts();
+      const int   nofTriangles = mc.ntrigs();
+
+      McVertex*   mcvertices   = mc.vertices();
+      McTriangle* mctriangles  = mc.triangles();
+
+      for(int t=0; t<nofTriangles; t++)
+      {
+         triangles.push_back(new GbTriangle3D( new GbPoint3D(  minX1 + deltaX1 * (mcvertices[mctriangles[t].v1].x /*-1*/)
+                                                             , minX2 + deltaX2 * (mcvertices[mctriangles[t].v1].y /*-1*/)
+                                                             , minX3 + deltaX3 * (mcvertices[mctriangles[t].v1].z /*-1*/) )
+                                              ,new GbPoint3D(  minX1 + deltaX1 * (mcvertices[mctriangles[t].v2].x /*-1*/)
+                                                             , minX2 + deltaX2 * (mcvertices[mctriangles[t].v2].y /*-1*/)
+                                                             , minX3 + deltaX3 * (mcvertices[mctriangles[t].v2].z /*-1*/) )
+                                              ,new GbPoint3D(  minX1 + deltaX1 * (mcvertices[mctriangles[t].v3].x /*-1*/)
+                                                             , minX2 + deltaX2 * (mcvertices[mctriangles[t].v3].y /*-1*/)
+                                                             , minX3 + deltaX3 * (mcvertices[mctriangles[t].v3].z /*-1*/) ) ) );
+      }
+   #else
+     cerr<<"vector<GbTriangle3D*> GbVoxelMatrix3D::getSurfaceTriangleSet() - benoetigt MARCHING_CUBE paket aus 3rdParty"<<endl;
+   #endif // MC_CUBES
+
+   return triangles;
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::addSurfaceTriangleSet(vector<UbTupleFloat3>& nodes, vector<UbTupleInt3>& triangles)
+{
+   UBLOG(logINFO," GbVoxelMatrix3D addSurfaceTriangleSet start")
+   if(!this->addSurfaceTriangleSetFlag)
+   {
+      UBLOG(logINFO," GbVoxelMatrix3D addSurfaceTriangleSet end without TriangleSetCreation")
+      return;
+   }
+   #ifdef MC_CUBES
+      UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet MC defined")
+
+      typedef McCubes::Matrix3DWrapper< Matrix3D >                McMatrixWrapper;
+      typedef McCubes::MarchingCubes< McMatrixWrapper >           McMarchingCubesGenerator;
+      typedef McMarchingCubesGenerator::Vertex                    McVertex;
+      typedef McMarchingCubesGenerator::Triangle                  McTriangle;
+    
+      //MC
+      {  //standard( fuer voxelmatrix)
+         McMatrixWrapper wrapper(&voxelMatrix);
+         McMarchingCubesGenerator mc(wrapper);
+
+         UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet McMarchingCubesGenerator")
+
+         UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet mc.init")
+         mc.init_all();
+         UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet mc.run")
+         mc.run(0.5);
+         UBLOG(logDEBUG1," GbVoxelMatrix3D addSurfaceTriangleSet mc.run done")
+
+         const int   nofVertices  = mc.nverts();
+         const int   nofTriangles = mc.ntrigs();
+
+         McVertex*   mcvertices   = mc.vertices();
+         McTriangle* mctriangles  = mc.triangles();
+
+UBLOG(logDEBUG1," GbVoxelMatrix3D node tuple")
+         for(int n=0; n<nofVertices; n++)
+            nodes.push_back( makeUbTuple( (float)(minX1 + deltaX1 * (mcvertices[n].x /*-1*/)),   //Anm: kein -1, da man durch manipulation der indices die dreiecke um eins versetzt bekommt
+                                          (float)(minX2 + deltaX2 * (mcvertices[n].y /*-1*/)),
+                                          (float)(minX3 + deltaX3 * (mcvertices[n].z /*-1*/)) ) );
+UBLOG(logDEBUG1," GbVoxelMatrix3D triangles tuple")
+         for(int t=0; t<nofTriangles; t++)
+            triangles.push_back( makeUbTuple( mctriangles[t].v1, mctriangles[t].v2, mctriangles[t].v3 ) );
+UBLOG(logDEBUG1," GbVoxelMatrix3D triangles tuple done")
+      }
+      
+      //false - das scheint probleme bei der asphaltprobe zu machen 1500x600x100
+      // da lief es bis C - evtl. memory voll
+      if(false)  //extension... um die raender koerrekt abzubilden muesste man eine dummy FLUID reihe um 
+      {         //die matrix legen( lsg1: temp matrix mit 2 reihen pro richtung mehr -> zuviel speicher, 500^3 = 500MB
+                // lsg2: fuer jede flaeche eine dummy matrix -> wie folgt:
+         int nx1 = (int)voxelMatrix.getNX1();
+         int nx2 = (int)voxelMatrix.getNX2();
+         int nx3 = (int)voxelMatrix.getNX3();
+UBLOG(logINFO," A ")
+         Matrix3D tmpX1Min( 2, nx2+2, nx3+2, FLUID );
+         Matrix3D tmpX1Max( 2, nx2+2, nx3+2, FLUID );
+         for(int x3=0; x3<nx3; x3++ )
+            for(int x2=0; x2<nx2; x2++ )
+            {
+               tmpX1Min(1, x2+1, x3+1) = voxelMatrix(0    , x2, x3);
+               tmpX1Max(0, x2+1, x3+1) = voxelMatrix(nx1-1, x2, x3);
+            }
+UBLOG(logINFO," B")
+         Matrix3D tmpX2Min(nx1+2, 2, nx3+2, FLUID );
+         Matrix3D tmpX2Max(nx1+2, 2, nx3+2, FLUID );
+         for(int x3=0; x3<nx3; x3++ )
+            for(int x1=0; x1<nx1; x1++ )
+            {
+               tmpX2Min(x1+1, 1, x3+1) = voxelMatrix(x1, 0    , x3);
+               tmpX2Max(x1+1, 0, x3+1) = voxelMatrix(x1, nx2-1, x3);
+            }
+UBLOG(logINFO," C ")
+         Matrix3D tmpX3Min(nx1+2, nx3+2, 2, FLUID );
+         Matrix3D tmpX3Max(nx1+2, nx3+2, 2, FLUID );
+         for(int x2=0; x2<nx2; x2++ )
+            for(int x1=0; x1<nx1; x1++ )
+            {
+               tmpX3Min(x1+1, x2+1, 1) = voxelMatrix(x1, x2, 0    );
+               tmpX3Max(x1+1, x2+1, 0) = voxelMatrix(x1, x2, nx3-1);
+            }
+UBLOG(logINFO," D")
+         Matrix3D* matrices[] = { &tmpX1Min, &tmpX1Max, &tmpX2Min, &tmpX2Max, &tmpX3Min, &tmpX3Max };
+         int            dx1[] = {        -1,     nx1-1,        -1,        -1,        -1,        -1 };
+         int            dx2[] = {        -1,        -1,        -1,     nx2-1,        -1,        -1 };
+         int            dx3[] = {        -1,        -1,        -1,        -1,        -1,     nx3-1 };
+UBLOG(logINFO," E")
+         for(int i=0; i<6; i++)
+         {
+            McMatrixWrapper wrapper(matrices[i]);
+            McMarchingCubesGenerator mc(wrapper);
+
+            mc.init_all();
+            mc.run(0.5);
+
+            McVertex*   mcvertices   = mc.vertices();
+            McTriangle* mctriangles  = mc.triangles();
+
+            int deltaNodeNr = (int)nodes.size();
+UBLOG(logINFO," GbVoxelMatrix3D node tuple")
+            for(int n=0; n<mc.nverts(); n++)
+               nodes.push_back( makeUbTuple( (float)(minX1 + deltaX1 * (mcvertices[n].x + dx1[i])),   //Anm: kein -1, da man durch manipulation der indices die dreiecke um eins versetzt bekommt
+                                             (float)(minX2 + deltaX2 * (mcvertices[n].y + dx2[i])),
+                                             (float)(minX3 + deltaX3 * (mcvertices[n].z + dx3[i])) ) );
+            for(int t=0; t<mc.ntrigs(); t++)
+               triangles.push_back( makeUbTuple( deltaNodeNr+mctriangles[t].v1, deltaNodeNr+mctriangles[t].v2, deltaNodeNr+mctriangles[t].v3 ) );
+         }
+      }
+   #else
+      cerr<<"void GbVoxelMatrix3D.addSurfaceTriangleSet  - benoetigt MARCHING_CUBE paket aus 3rdParty"<<endl;
+   #endif // MC_CUBES
+
+   UBLOG(logINFO," GbVoxelMatrix3D addSurfaceTriangleSet end")
+}
+/*=======================================================*/
+string GbVoxelMatrix3D::toString() 
+{
+   return "GbVoxelMatrix3D";
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::write(UbFileOutput* out) 
+{                                      
+   out->writeString(this->getCreator()->getTypeID());
+   out->writeDouble(minX1);
+   out->writeDouble(minX2);
+   out->writeDouble(minX3);
+   out->writeDouble(deltaX1);
+   out->writeDouble(deltaX2);
+   out->writeDouble(deltaX3);
+   out->writeInteger(nodesX1);
+   out->writeInteger(nodesX2);
+   out->writeInteger(nodesX3);
+   out->writeDouble(lowerThreshold);
+   out->writeDouble(upperThreshold);
+   out->writeBool(addSurfaceTriangleSetFlag);
+   out->writeBool(transferViaFilename);
+   if(!transferViaFilename)
+   {
+      throw UbException(UB_EXARGS,"void GbVoxelMatrix3D::write(UbFileOutput* out)  - geht ned");
+   }
+   else
+   {
+      out->writeString(filename);
+   }
+
+   
+   //CbUniformMatrix3D<float> voxelMatrix;
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::read(UbFileInput* in) 
+{  
+#ifdef CAB_RCF
+   try
+   {
+#endif
+      //!!! den string nimmt er vorher um das Object zu erstellen
+      //in->readString();      
+      minX1   = in->readDouble();
+      minX2   = in->readDouble();
+      minX3   = in->readDouble();
+      deltaX1 = in->readDouble();
+      deltaX2 = in->readDouble();
+      deltaX3 = in->readDouble();
+      nodesX1 = in->readInteger();
+      nodesX2 = in->readInteger();
+      nodesX3 = in->readInteger();
+      lowerThreshold = in->readDouble();
+      upperThreshold = in->readDouble();
+      addSurfaceTriangleSetFlag = in->readBool();
+      transferViaFilename = in->readBool();
+      if(!transferViaFilename)
+      {
+         throw UbException(UB_EXARGS,"void GbVoxelMatrix3D::read(UbFileOutput* out)  - geht ned");
+      }
+      else
+      {
+         filename = in->readString();
+         this->readMatrixFromVtiASCIIFile(filename);
+      }
+#ifdef CAB_RCF
+   }
+   catch(std::exception& e) { UBLOGML(logERROR, UB_FUNCTION + (std::string)e.what());        throw RCF::Exception(1002, UB_FUNCTION + (std::string)e.what() );        }                                                                                       
+   catch(...)               { UBLOGML(logERROR, UB_FUNCTION + (std::string)"unknown error"); throw RCF::Exception(1002, UB_FUNCTION + (std::string)"unknown error" ); }
+#endif
+}
+/*=======================================================*/
+void GbVoxelMatrix3D::readMatrixFromVtiASCIIFile(std::string filename)
+
+{
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+   UbFileInputASCII in(filename);
+   //ifstream in(filename.c_str(), ios::binary);
+   if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   in.readLine();
+   in.readLine();
+
+   voxelMatrix = Matrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID);
+
+   UBLOG(logINFO,"  - init values");
+   int val;
+   int u=0;
+   for(int x3=0; x3<nodesX3; x3++)
+      for(int x2=0; x2<nodesX2; x2++)
+         for(int x1=0; x1<nodesX1; x1++)
+         {
+            val = in.readInteger();
+            //if( !UbMath::equal(val, 0.0f) ) 
+            //if( UbMath::greater(val, threshold) ) 
+            if( (double)val >= lowerThreshold && (double)val <= upperThreshold ) 
+            {
+               (voxelMatrix)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+            }
+         }
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D done");
+}
+
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundX(double cX1, double cX2, double cX3)
+{
+   double tempMinPunktX1 = minX1  - cX1;
+   double tempMinPunktX2 = minX2  - cX2;
+   double tempMinPunktX3 = getX3Maximum()  - cX3;
+
+   double tempMinPunktX1tf = tempMinPunktX1;
+   double tempMinPunktX2tf = -tempMinPunktX3;
+   double tempMinPunktX3tf = tempMinPunktX2;
+
+   double minX1_temp = tempMinPunktX1tf + cX1;
+   double minX2_temp = tempMinPunktX2tf + cX2;
+   double minX3_temp = tempMinPunktX3tf + cX3;
+
+   minX2 = minX2_temp;
+   minX3 = minX3_temp;
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nx1_new = nx1; 
+   int nx2_new = nx3;
+   int nx3_new = nx2;
+
+   double delta_temp = deltaX2;
+   deltaX2 = deltaX3;
+   deltaX3 = delta_temp;
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1_new, nx2_new, nx3_new);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(x1,nx3-x3-1,x2) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundX()
+{
+   double cX1 = this->getX1Centroid();
+   double cX2 = this->getX2Centroid();
+   double cX3 = this->getX3Centroid();
+
+   rotate90aroundX(cX1, cX2, cX3);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundY(double cX1, double cX2, double cX3)
+{
+   double tempMinPunktX1 = getX1Maximum()  - cX1;
+   double tempMinPunktX2 = minX2  - cX2;
+   double tempMinPunktX3 = minX3  - cX3;
+
+   double tempMinPunktX1tf = tempMinPunktX3;
+   double tempMinPunktX2tf = tempMinPunktX2;
+   double tempMinPunktX3tf = -tempMinPunktX1;
+
+   double minX1_temp = tempMinPunktX1tf + cX1;
+   double minX2_temp = tempMinPunktX2tf + cX2;
+   double minX3_temp = tempMinPunktX3tf + cX3;
+
+   minX1 = minX1_temp;
+   minX3 = minX3_temp;
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nx1_new = nx3; 
+   int nx2_new = nx2;
+   int nx3_new = nx1;
+
+   double delta_temp = deltaX1;
+   deltaX1 = deltaX3;
+   deltaX3 = delta_temp;
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1_new, nx2_new, nx3_new);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(x3,x2,nx1-x1-1) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundY()
+{
+   double cX1 = this->getX1Centroid();
+   double cX2 = this->getX2Centroid();
+   double cX3 = this->getX3Centroid();
+   
+   rotate90aroundY(cX1, cX2, cX3);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundZ(double cX1, double cX2, double cX3)
+{
+   double tempMinPunktX1 = minX1  - cX1;
+   double tempMinPunktX2 = getX2Maximum()  - cX2;
+   double tempMinPunktX3 = minX3  - cX3;
+
+   double tempMinPunktX1tf = -tempMinPunktX2;
+   double tempMinPunktX2tf = tempMinPunktX1;
+   double tempMinPunktX3tf = tempMinPunktX3;
+
+   double minX1_temp = tempMinPunktX1tf + cX1;
+   double minX2_temp = tempMinPunktX2tf + cX2;
+   double minX3_temp = tempMinPunktX3tf + cX3;
+
+   minX1 = minX1_temp;
+   minX2 = minX2_temp;
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nx1_new = nx2; 
+   int nx2_new = nx1;
+   int nx3_new = nx3;
+
+   double delta_temp = deltaX1;
+   deltaX1 = deltaX2;
+   deltaX2 = delta_temp;
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1_new, nx2_new, nx3_new);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(nx2-x2-1,x1,x3) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::rotate90aroundZ()
+{
+   double cX1 = this->getX1Centroid();
+   double cX2 = this->getX2Centroid();
+   double cX3 = this->getX3Centroid();
+
+   rotate90aroundZ(cX1, cX2, cX3);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::mirrorX()
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1, nx2, nx3);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(nx1-x1-1,x2,x3) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::mirrorY()
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1, nx2, nx3);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(x1,nx2-x2-1,x3) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::mirrorZ()
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1, nx2, nx3);
+
+   for (int x3=0; x3<nx3;x3++){
+      for (int x2=0; x2<nx2;x2++){
+         for(int x1=0; x1<nx1;x1++)
+         {
+            voxelMatrix_temp(x1,x2,nx3-x3-1) = this->voxelMatrix(x1,x2,x3);
+         }
+      }
+   }
+   std::swap(this->voxelMatrix, voxelMatrix_temp);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::writeToLegacyVTKASCII( const std::string& fileName )
+{
+   string fn = fileName +".ascii.vtk";
+
+   FILE *file; 
+   file = fopen(fn.c_str(),"w"); 
+
+   if (file == NULL)
+   {
+      std::string pathf = UbSystem::getPathFromString(fn);
+      if (fn.size()>0) { UbSystem::makeDirectory(pathf); file = fopen(fn.c_str(), "w"); }
+      if (file == NULL) throw UbException(UB_EXARGS, "can not open " + fn);
+   }
+
+   if(file == NULL)
+      throw UbException(UB_EXARGS,"can not open "+fn);
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nn = nx1*nx2*nx3;
+
+   fprintf(file,"# vtk DataFile Version 2.0\n");
+   fprintf(file,"vtk output\n");
+   fprintf(file,"ASCII\n");
+   fprintf(file,"DATASET STRUCTURED_POINTS\n");
+   fprintf(file,"DIMENSIONS %d %d %d\n", nx1, nx2, nx3);
+   fprintf(file,"ORIGIN %g %g %g\n", minX1, minX2, minX3);
+   fprintf(file,"SPACING %g %g %g\n", deltaX1, deltaX2, deltaX3);
+   fprintf(file,"POINT_DATA %d\n", nn);
+   fprintf(file,"SCALARS Geo float\n");
+   fprintf(file,"LOOKUP_TABLE default\n");
+
+   for(int k=0 ; k<nx3 ; k++){
+      for(int j=0 ; j<nx2 ; j++){
+         for(int i=0 ; i<nx1 ; i++){
+            fprintf(file,"%g ", voxelMatrix(i,j,k));
+         }
+      }
+   }
+
+   fprintf(file,"\n");
+
+   fclose(file);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::writeToLegacyVTKBinary( const std::string& fileName )
+{
+   string fn = fileName +".binary.vtk";
+  
+   FILE *file; 
+   file = fopen(fn.c_str(),"w"); 
+
+   if (file == NULL)
+   {
+      std::string pathf = UbSystem::getPathFromString(fn);
+      if (fn.size()>0) { UbSystem::makeDirectory(pathf); file = fopen(fn.c_str(), "w"); }
+      if (file == NULL) throw UbException(UB_EXARGS, "can not open " + fn);
+   }
+
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   int nn = nx1*nx2*nx3;
+
+   char LF = 0x0A;
+
+   fprintf(file,"# vtk DataFile Version 3.0\n");
+   fprintf(file,"vtk output\n");
+   fprintf(file,"BINARY\n");
+   fprintf(file,"DATASET STRUCTURED_POINTS\n");
+   fprintf(file,"DIMENSIONS %d %d %d\n", nx1, nx2, nx3);
+   fprintf(file,"ORIGIN %g %g %g\n", minX1, minX2, minX3);
+   fprintf(file,"SPACING %g %g %g\n", deltaX1, deltaX2, deltaX3);
+   fprintf(file,"POINT_DATA %d\n", nn);
+   fprintf(file,"SCALARS Geo float\n");
+   fprintf(file,"LOOKUP_TABLE default");
+   fclose(file);
+
+   GbVoxelMatrix3D::Matrix3D voxelMatrix_temp(nx1, nx2, nx3);
+
+   if (UbSystem::isLittleEndian())
+   {
+      for (int x3=0; x3<nx3;x3++){
+         for (int x2=0; x2<nx2;x2++){
+            for(int x1=0; x1<nx1;x1++)
+            {
+               float tmp = this->voxelMatrix(x1,x2,x3);
+               UbSystem::swapByteOrder((unsigned char*)(&(tmp)), sizeof(float));
+               voxelMatrix_temp(x1,x2,x3) = tmp;
+            }
+         }
+      }
+   }
+
+   file = fopen(fn.c_str(), "ab");
+   
+   fwrite (&LF, sizeof(char), 1, file);
+   fwrite(voxelMatrix_temp.getStartAdressOfSortedArray(0,0,0), sizeof(float), voxelMatrix_temp.getDataVector().size(), file);
+   fwrite (&LF, sizeof(char), 1, file);
+   fclose(file);
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::writeToVTKImageDataASCII( const std::string& fileName )
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   string fn = fileName +".ascii.vti";
+
+   FILE *file; 
+   file = fopen(fn.c_str(),"w"); 
+
+   if (file == NULL)
+   {
+      std::string pathf = UbSystem::getPathFromString(fn);
+      if (fn.size()>0) { UbSystem::makeDirectory(pathf); file = fopen(fn.c_str(), "w"); }
+      if (file == NULL) throw UbException(UB_EXARGS, "can not open " + fn);
+   }
+
+   fprintf(file,"<VTKFile type=\"ImageData\" version=\"1.0\" byte_order=\"LittleEndian\" header_type=\"UInt64\">\n"); //paraview 4.1
+   //fprintf(file,"<VTKFile type=\"ImageData\" version=\"0.1\" byte_order=\"LittleEndian\">\n"); //paraview 3.1
+   fprintf(file,"  <ImageData WholeExtent=\"%d %d %d %d %d %d\" Origin=\"%g %g %g\" Spacing=\"%g %g %g\">\n", 0, nx1-1, 0, nx2-1, 0, nx3-1, minX1, minX2, minX3, deltaX1, deltaX2, deltaX3);
+   fprintf(file,"  <Piece Extent=\"%d %d %d %d %d %d\">\n", 0, nx1-1, 0, nx2-1, 0, nx3-1);
+   fprintf(file,"    <PointData Scalars=\"VoxelMatrix\">\n");
+   fprintf(file,"      <DataArray type=\"Float32\" Name=\"VoxelMatrix\" format=\"ascii\" RangeMin=\"0\" RangeMax=\"1\">\n        "); 
+
+   for(int k=0 ; k<nx3 ; k++){
+      for(int j=0 ; j<nx2 ; j++){
+         for(int i=0 ; i<nx1 ; i++){
+            fprintf(file,"%g ",voxelMatrix(i,j,k));
+         }
+      }
+   }
+
+   fprintf(file,"\n      </DataArray>\n");
+   fprintf(file,"    </PointData>\n");
+   fprintf(file,"    <CellData>\n");
+   fprintf(file,"    </CellData>\n");
+   fprintf(file,"  </Piece>\n");
+   fprintf(file,"  </ImageData>\n");
+   fprintf(file,"</VTKFile>\n");
+
+   fclose(file); 
+}
+//////////////////////////////////////////////////////////////////////////
+void GbVoxelMatrix3D::writeToVTKImageDataAppended( const std::string& fileName )
+{
+   int nx1 = (int)voxelMatrix.getNX1();
+   int nx2 = (int)voxelMatrix.getNX2();
+   int nx3 = (int)voxelMatrix.getNX3();
+
+   string fn = fileName +".appended.vti";
+
+   FILE *file; 
+   file = fopen(fn.c_str(),"w"); 
+
+   if (file == NULL)
+   {
+      std::string pathf = UbSystem::getPathFromString(fn);
+      if (fn.size()>0) { UbSystem::makeDirectory(pathf); file = fopen(fn.c_str(), "w"); }
+      if (file == NULL) throw UbException(UB_EXARGS, "can not open " + fn);
+   }
+
+   fprintf(file,"<VTKFile type=\"ImageData\" version=\"1.0\" byte_order=\"LittleEndian\" header_type=\"UInt64\">\n"); //paraview 4.1
+   fprintf(file,"  <ImageData WholeExtent=\"%d %d %d %d %d %d\" Origin=\"%g %g %g\" Spacing=\"%g %g %g\">\n", 0, nx1-1, 0, nx2-1, 0, nx3-1,  minX1, minX2, minX3, deltaX1, deltaX2, deltaX3);
+   fprintf(file,"  <Piece Extent=\"%d %d %d %d %d %d\">\n", 0, nx1-1, 0, nx2-1, 0, nx3-1);
+   fprintf(file,"    <PointData Scalars=\"VoxelMatrix\">\n");
+   fprintf(file,"      <DataArray type=\"Float32\" Name=\"VoxelMatrix\" format=\"appended\" RangeMin=\"0\" RangeMax=\"1\" offset=\"0\" />\n"); 
+   fprintf(file,"    </PointData>\n");
+   fprintf(file,"    <CellData>\n");
+   fprintf(file,"    </CellData>\n");
+   fprintf(file,"  </Piece>\n");
+   fprintf(file,"  </ImageData>\n");
+   fprintf(file,"  <AppendedData encoding=\"raw\">\n");
+   fprintf(file,"   _");
+   fclose(file);
+
+   file = fopen(fn.c_str(), "ab");
+   int size = (int)voxelMatrix.getDataVector().size() * sizeof(float);
+   fwrite (&size, sizeof(int), 1, file);
+   fwrite(voxelMatrix.getStartAdressOfSortedArray(0,0,0), sizeof(float), voxelMatrix.getDataVector().size(), file);
+   fclose(file);
+
+   file = fopen(fn.c_str(),"a");
+   fprintf(file,"\n");
+   fprintf(file,"  </AppendedData>\n");
+   fprintf(file,"</VTKFile>\n");
+   fclose(file); 
+}
+
+
diff --git a/source/VirtualFluidsCore/Geometry/GbVoxelMatrix3D.h b/source/VirtualFluidsCore/Geometry/GbVoxelMatrix3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c26ca05a2a6b008fe7391e8b27aed68803ee93b
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/GbVoxelMatrix3D.h
@@ -0,0 +1,340 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef GBVOXELMATRIX3D_H
+#define GBVOXELMATRIX3D_H
+
+#ifdef CAB_RCF
+   #include <3rdParty/rcf/RcfSerializationIncludes.h>
+#endif //CAB_RCF
+
+#include <vector>
+#include <cmath>
+
+#include <numerics/geometry3d/GbObject3D.h>
+#include <basics/utilities/UbObserver.h>
+#include <basics/container/CbArray3D.h>
+
+#include <basics/memory/MbSharedPointerDefines.h>
+class GbVoxelMatrix3D;
+typedef VFSharedPtr<GbVoxelMatrix3D> GbVoxelMatrix3DPtr;
+
+
+class GbLine3D;                    
+class GbTriangle3D;                    
+class GbObject3DCreator;
+
+class GbVoxelMatrix3D : public GbObject3D, public UbObserver
+{
+public:              
+   typedef CbArray3D<float> Matrix3D;
+   static const float SOLID; 
+   static const float FLUID; 
+   enum  Endian {BigEndian, LittleEndian};
+
+   GbVoxelMatrix3D();
+   GbVoxelMatrix3D(int nx1, int nx2, int nx3, float initVal, double lowerThreshold=0, double upperThreshold=0);
+   GbVoxelMatrix3D(const Matrix3D& voxelMatrix, double lowerThreshold=0, double upperThreshold=0);
+   ~GbVoxelMatrix3D() {}   
+
+   void finalize() {};
+   GbVoxelMatrix3D* clone(); 
+
+   /*=======================================================================*/
+   Matrix3D::reference operator() (const Matrix3D::size_type& x1, const Matrix3D::size_type& x2, const Matrix3D::size_type& x3)
+   {
+      return voxelMatrix(x1,x2,x3);
+   }
+   /*=======================================================================*/
+   Matrix3D::const_reference operator() (const Matrix3D::size_type& x1, const Matrix3D::size_type& x2, const Matrix3D::size_type& x3)	const
+   {
+      return voxelMatrix(x1,x2,x3);
+   }
+   /*=======================================================================*/
+   void setTransferViaFilename(bool transferViaFilename, std::string filename)
+   {
+      this->filename = filename;
+      this->transferViaFilename = transferViaFilename;
+   }
+   void setThreshold(double lowerThreshold, double upperThreshold) { this->lowerThreshold = lowerThreshold; this->upperThreshold = upperThreshold; }
+   void setAddSurfaceTriangleSetFlag(bool flag) { this->addSurfaceTriangleSetFlag = flag; }
+
+   /*=======================================================================*/
+   void setVoxelMatrixMininum(double minX1, double minX2, double minX3) { this->minX1 = minX1; this->minX2 = minX2; this->minX3 = minX3; }
+   void setVoxelMatrixMinX1(double minX1) { this->minX1 = minX1; }
+   void setVoxelMatrixMinX2(double minX2) { this->minX2 = minX2; }
+   void setVoxelMatrixMinX3(double minX3) { this->minX3 = minX3; }
+   
+   /*=======================================================================*/
+   void setVoxelMatrixDelta(double deltaX1, double deltaX2, double deltaX3) { this->deltaX1 = deltaX1; this->deltaX2 = deltaX2; this->deltaX3 = deltaX3; }
+   void setVoxelMatrixDeltaX1(double deltaX1) { this->deltaX1 = deltaX1; }
+   void setVoxelMatrixDeltaX2(double deltaX2) { this->deltaX2 = deltaX2; }
+   void setVoxelMatrixDeltaX3(double deltaX3) { this->deltaX3 = deltaX3; }
+
+   /*=======================================================================*/
+   double getX1Centroid() { return 0.5 * ( minX1 + this->getX1Maximum() ); } 
+   double getX1Minimum()  { return minX1; }
+   double getX1Maximum()  { return minX1 + deltaX1*voxelMatrix.getNX1(); }  
+
+   double getX2Centroid() { return 0.5 * ( minX2 + this->getX2Maximum() ); } 
+   double getX2Minimum()  { return minX2; }
+   double getX2Maximum()  { return minX2 + deltaX2*voxelMatrix.getNX2(); }  
+
+   double getX3Centroid() { return 0.5 * ( this->getX3Minimum() + this->getX3Maximum() ); } 
+   double getX3Minimum()  { return minX3; }
+   double getX3Maximum()  { return minX3 + deltaX3*voxelMatrix.getNX3(); }  
+
+   double getLengthX1() { return this->getX1Maximum() - minX1; }
+   double getLengthX2() { return this->getX2Maximum() - minX2; }
+   double getLengthX3() { return this->getX3Maximum() - minX3; }
+
+   void setCenterCoordinates(const double& x1, const double& x2, const double& x3);
+   void translate(const double& tx1, const double& tx2, const double& tx3);
+
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p, bool& pointIsOnBoundary);
+   bool isPointInGbObject3D(const double& x1p, const double& x2p, const double& x3p); 
+   bool isCellInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   bool isCellInsideOrCuttingGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+   //double getCellVolumeInsideGbObject3D(const double& x1a,const double& x2a,const double& x3a,const double& x1b,const double& x2b,const double& x3b);
+
+   GbPoint3D*  calculateInterSectionPoint3D(GbPoint3D& point1, GbPoint3D &point2) { throw UbException(__FILE__,__LINE__, UB_FUNCTION,"not implemented");}
+   GbLine3D*   createClippedLine3D(GbPoint3D& point1, GbPoint3D& point2){ throw UbException(__FILE__,__LINE__, UB_FUNCTION,"not implemented");}
+
+   std::vector<GbTriangle3D*> getSurfaceTriangleSet();
+   void addSurfaceTriangleSet(std::vector<UbTupleFloat3>& nodes, std::vector<UbTupleInt3>& triangles);
+
+   bool hasRaytracing() { return true; }
+   /*|r| must be 1! einheitsvector!!*/
+   double getIntersectionRaytraceFactor(const double& x1, const double& x2, const double& x3, const double& rx1, const double& rx2, const double& rx3);
+
+   std::string toString();
+
+   ObObjectCreator* getCreator();
+   void write(UbFileOutput* out);
+   void read(UbFileInput* in);
+
+   //virtuelle Methoden von UbObserver
+   void objectChanged(UbObservable* changedObject) {}
+   void objectWillBeDeleted(UbObservable* objectForDeletion) {}
+
+   template <class T>
+   void readMatrixFromRawFile(std::string filename, GbVoxelMatrix3D::Endian endian);
+   template <class T>
+   void readBufferedMatrixFromRawFile(std::string filename, GbVoxelMatrix3D::Endian endian);
+   void readMatrixFromVtiASCIIFile(std::string filename);
+
+   void rotate90aroundX();
+   void rotate90aroundY();
+   void rotate90aroundZ();
+   void rotate90aroundX(double cX1, double cX2, double cX3);
+   void rotate90aroundY(double cX1, double cX2, double cX3);
+   void rotate90aroundZ(double cX1, double cX2, double cX3);
+   void mirrorX();
+   void mirrorY();
+   void mirrorZ();
+
+   void writeToLegacyVTKASCII(const std::string& fileName);
+   void writeToLegacyVTKBinary( const std::string& fileName );
+   void writeToVTKImageDataASCII(const std::string& fileName);
+   void writeToVTKImageDataAppended(const std::string& fileName);
+
+   void setClosedVoidSpaceToSolid();
+
+   void calculateNumberOfSolidAndFluid();
+   long getNumberOfSolid();
+   long getNumberOfFluid();
+
+protected:
+   void findFluidNeighbor(int cx1, int cx2, int cx3);
+   Matrix3D voxelMatrixTemp;
+   CbArray3D<char> flagMatrix;
+
+   std::vector<int> x1Nbr;
+   std::vector<int> x2Nbr;
+   std::vector<int> x3Nbr;
+
+   std::vector<int> x1NbrTemp;
+   std::vector<int> x2NbrTemp;
+   std::vector<int> x3NbrTemp;
+
+   using GbObject3D::isPointInGbObject3D; //Grund: dadurch muss man hier  isPointInGbObject3D(GbPoint3D*) nicht ausprogrammieren, welche sonst hier "ueberdeckt" waere
+
+#ifdef CAB_RCF
+   template<class Archive>
+   void SF_SERIALIZE(Archive & ar)
+   {
+      SF_SERIALIZE_PARENT<GbObject3D>(ar, *this);
+      ar & minX1;
+      ar & minX2;
+      ar & minX3;
+      ar & deltaX1;
+      ar & deltaX2;
+      ar & deltaX3;
+      ar & nodesX1;
+      ar & nodesX2;
+      ar & nodesX3;
+      ar & threshold;
+      ar & transferViaFilename;
+      ar & addSurfaceTriangleSetFlag;
+      if(!transferViaFilename)
+      {
+         ar & voxelMatrix;
+      }
+      else
+      {
+         ar & filename;
+         if(ArchiveTools::isReading(ar) ) 
+         {
+            this->readMatrixFromVtiASCIIFile(filename);
+         }
+      }
+
+   }
+#endif //CAB_RCF
+
+protected:
+   //for transfer
+   std::string filename;
+   bool transferViaFilename;
+
+   bool addSurfaceTriangleSetFlag;
+
+   int nodesX1;
+   int nodesX2;
+   int nodesX3;
+   double lowerThreshold, upperThreshold;
+
+   double minX1;
+   double minX2;
+   double minX3;
+   double deltaX1;
+   double deltaX2;
+   double deltaX3;
+
+   Matrix3D voxelMatrix;
+
+   long numberOfSolid;
+   long numberOfFluid;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void GbVoxelMatrix3D::readMatrixFromRawFile(std::string filename, GbVoxelMatrix3D::Endian endian)
+{
+   using namespace std;
+   UBLOG(logINFO,"GbVoxelMatrix3D::readMatrixFromFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+   ifstream in(filename.c_str(), ios::binary);
+   if(!in) throw UbException(UB_EXARGS,"could not open file "+filename);
+
+   in.seekg( 0, ios::end );     //Ende springen
+   fstream::off_type length = in.tellg(); //Position abfragen
+   in.seekg( 0, ios::beg );    //An den Anfang springen 
+
+   //UBLOG(logINFO,"number of nodes = "<<nodesX1*nodesX2*nodesX3*sizeof(T)<<" file size = "<<(long)length);
+   //if( (nodesX1*nodesX2*nodesX3)*sizeof(float) != (long)length )
+   unsigned long long nofn = nodesX1*nodesX2*nodesX3*sizeof(T);
+   if (nofn != (unsigned long long)length)
+   {
+      throw UbException(UB_EXARGS,"number of nodes("+UbSystem::toString(nofn)+") doesn't match file size("+UbSystem::toString((long)length)+")");
+   }
+
+   UBLOG(logINFO,"  - create GbVoxelMatrix3D");
+   //GbVoxelMatrix3D* voxelGeo = new GbVoxelMatrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID);
+   voxelMatrix = Matrix3D(nodesX1,nodesX2,nodesX3,GbVoxelMatrix3D::FLUID);
+
+   UBLOG(logINFO,"  - init values");
+   //float val;
+   T val;
+   for(int x3=0; x3<nodesX3; x3++)
+      for(int x2=0; x2<nodesX2; x2++)
+         for(int x1=0; x1<nodesX1; x1++)
+         {
+            //in.read((char*)&val,sizeof(float));
+            in.read((char*)&val,sizeof(T));
+            if (endian == BigEndian)
+               UbSystem::swapByteOrder((unsigned char*)(&(val)), sizeof(T));
+            //if( UbMath::equal((double)val, threshold) ) 
+            //if( UbMath::greater((double)val, threshold) )
+            if( (double)val >= lowerThreshold && (double)val <= upperThreshold ) 
+            {
+               (voxelMatrix)(x1,x2,x3) = GbVoxelMatrix3D::SOLID;
+            }
+            //(voxelMatrix)(x1, x2, x3) = (float)val;
+         }
+
+         UBLOG(logINFO,"GbVoxelMatrix3D::readMatrixFromFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void GbVoxelMatrix3D::readBufferedMatrixFromRawFile(std::string filename, GbVoxelMatrix3D::Endian endian)
+{
+   using namespace std;
+   UBLOG(logINFO, "GbVoxelMatrix3D::readMatrixFromRawFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - start");
+
+   FILE *file;
+   file = fopen(filename.c_str(), "rb");
+   if (file==NULL)
+   {
+      throw UbException(UB_EXARGS, "Could not open file "+filename);
+   }
+
+   // obtain file size:
+   fseek(file, 0, SEEK_END);
+   unsigned long int length = ftell(file);
+   rewind(file);
+
+   UBLOG(logINFO, "number of nodes = "<<(long)nodesX1*(long)nodesX2*(long)nodesX3<<" file size = "<<length);
+   
+   unsigned long int nofn = (long)nodesX1*(long)nodesX2*(long)nodesX3*(long)sizeof(T);
+   if (nofn != length)
+   {
+      //throw UbException(UB_EXARGS, "number of nodes("+UbSystem::toString(nofn)+") doesn't match file size("+UbSystem::toString(length)+")");
+   }
+
+   UBLOG(logINFO, "  - create GbVoxelMatrix3D");
+   voxelMatrix = Matrix3D(nodesX1, nodesX2, nodesX3, GbVoxelMatrix3D::FLUID);
+
+   CbArray3D<T> readMatrix(nodesX1, nodesX2, nodesX3);
+
+   UBLOG(logINFO, "  - read file to matrix");
+   fread(readMatrix.getStartAdressOfSortedArray(0, 0, 0), sizeof(T), readMatrix.getDataVector().size(), file);
+   fclose(file);
+
+   UBLOG(logINFO, "  - init values");
+
+   numberOfSolid = 0;
+   T val;
+   for (int x3 = 0; x3<nodesX3; x3++)
+      for (int x2 = 0; x2<nodesX2; x2++)
+         for (int x1 = 0; x1<nodesX1; x1++)
+         {
+            val = readMatrix(x1, x2, x3);
+
+            if (endian == BigEndian)
+            {
+               UbSystem::swapByteOrder((unsigned char*)(&(val)), sizeof(T));
+            }
+
+            if ((double)val >= lowerThreshold && (double)val <= upperThreshold)
+            {
+               voxelMatrix(x1, x2, x3) = GbVoxelMatrix3D::SOLID;
+            }
+         }
+
+   UBLOG(logINFO, "GbVoxelMatrix3D::readMatrixFromRawFile \""<<filename<<"\" nodes("<<nodesX1<<"/"<<nodesX2<<"/"<<nodesX3<<") - end");
+}
+
+
+#if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+   UB_AUTO_RUN_NAMED(   SF::registerType<GbVoxelMatrix3D>("GbVoxelMatrix3D")        , SF_GbVoxelMatrix3D     );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< GbObject3D, GbVoxelMatrix3D >()), SF_GbVoxelMatrix3D_BD1 );
+   UB_AUTO_RUN_NAMED( ( SF::registerBaseAndDerived< UbObserver, GbVoxelMatrix3D>() ), SF_GbVoxelMatrix3D_BD2 );
+#endif //RCF_USE_SF_SERIALIZATION
+
+
+#endif   
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/CMakePackage.txt b/source/VirtualFluidsCore/Geometry/KdTree/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8d2943620ae0f1b9f1a22b47979b2a23b2523256
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/CMakePackage.txt
@@ -0,0 +1,4 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR}                      ALL_SOURCES)
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR}/splitalgorithms      ALL_SOURCES)
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR}/intersectionhandler ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/KdNode.h b/source/VirtualFluidsCore/Geometry/KdTree/KdNode.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b38011b10a124ad1962f39680479d3142249e5d
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/KdNode.h
@@ -0,0 +1,284 @@
+#ifndef KDNODE_H
+#define KDNODE_H
+
+#include <basics/memory/MbSmartPtr.h>
+
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbKeys.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/KdRay.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdRayIntersectionHandler.h>
+
+
+#include <vector>
+#include <string>
+
+namespace Kd
+{
+   template< typename T >
+   class Node 
+   {
+   public:
+      Node(  const T& x1, const T& y1, const T& z1
+           , const T& x2, const T& y2, const T& z2
+           , const MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFaces
+           , std::vector<GbTriFaceMesh3D::Vertex>* ptrNodes ) 
+         : child1(NULL)
+         , child2(NULL)
+         , triFaces(triFaces)
+         , ptrNodes(ptrNodes)
+      {
+         if( x1 < x2 ) { this->x[0] = x1; this->x[1] = x2; }
+         else          { this->x[0] = x2; this->x[1] = x1; }
+
+         if( y1 < y2 ) { this->y[0] = y1; this->y[1] = y2; }
+         else          { this->y[0] = y2; this->y[1] = y1; }
+
+         if( z1 < z2 ) { this->z[0] = z1; this->z[1] = z2; }
+         else          { this->z[0] = z2; this->z[1] = z1; }
+      }
+      /* ======================================================================================= */
+      ~Node()
+      {
+         if(child1) { delete child1; child1 = NULL;  }
+         if(child2) { delete child2; child2 = NULL;  }
+      }
+      /* ======================================================================================= */
+      bool isLeaf() 
+      {
+         return child1 == NULL && child2 == NULL;
+      }
+      /* ======================================================================================= */
+      void deleteTriFaces() 
+      {
+         triFaces = MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> >();
+      }
+      /* ======================================================================================= */
+      const MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> >& getTriFaces() 
+      {
+         return triFaces;
+      }
+      /* ======================================================================================= */
+      std::vector<GbTriFaceMesh3D::Vertex>& getNodes() 
+      {
+         if(!ptrNodes) throw UbException(UB_EXARGS,"ups,no nodes");
+         return *ptrNodes;
+      }
+
+      /* ======================================================================================= */
+      void buildTree(const int& level, const int& maxLevel, const SplitAlgorithm<T>& splitAlg) 
+      {
+         SplitCandidate<T> splitCandidate = splitAlg.findBestSplitCandidate(level, maxLevel, *this);
+
+         if( splitCandidate.isValid ) 
+         {
+
+            MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFacesForChild1( new std::vector<GbTriFaceMesh3D::TriFace> );
+            MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFacesForChild2( new std::vector<GbTriFaceMesh3D::TriFace> );
+
+            splitAlg.distributeTriFaces(splitCandidate, *triFacesForChild1, *triFacesForChild2, *this);
+
+            //////////////////////////////////////////////////////////////////////////
+            // calculate center points and edges of new child nodes
+            T x1_l = x[0], y1_l = y[0], z1_l = z[0];
+            T x2_l = x[1], y2_l = y[1], z2_l = z[1];
+            T x1_r = x[0], y1_r = y[0], z1_r = z[0];
+            T x2_r = x[1], y2_r = y[1], z2_r = z[1];
+
+            if (splitCandidate.axis == Axis::X) 
+            {
+               x2_l = splitCandidate.position;
+               x1_r = splitCandidate.position;
+            } 
+            else if (splitCandidate.axis == Axis::Y)
+            {
+               y2_l = splitCandidate.position;
+               y1_r = splitCandidate.position;
+            } 
+            else 
+            {
+               z2_l = splitCandidate.position;
+               z1_r = splitCandidate.position;
+            }
+            // ----------------------------------------------------------------------
+            // ----------------------------------------------------------------------
+
+            if (triFacesForChild1->size() > 0) 
+            {
+               if( this->child1 ) delete this->child1;
+               this->child1 = new Node(x1_l, y1_l, z1_l, x2_l, y2_l, z2_l, triFacesForChild1, ptrNodes);
+               this->child1->buildTree(level + 1, maxLevel, splitAlg);
+            }
+            
+            if (triFacesForChild2->size() > 0) 
+            {
+               if( this->child2 ) delete this->child2;
+               this->child2 = new Node(x1_r, y1_r, z1_r, x2_r, y2_r, z2_r, triFacesForChild2, ptrNodes);
+               this->child2->buildTree(level + 1, maxLevel, splitAlg);
+            }
+         }
+      }
+      /* ======================================================================================= */
+      int intersectLineBoundingBox(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2) 
+      {
+         const T& n1X = val<1>(n1);
+         const T& n1Y = val<2>(n1);
+         const T& n1Z = val<3>(n1);
+
+         const T& n2X = val<1>(n2);
+         const T& n2Y = val<2>(n2);
+         const T& n2Z = val<3>(n2);
+
+         double t_nah  = UbMath::max(  ( (n1X <= n2X ? x[0] : x[1]) - n1X) / (n2X - n1X)
+                                     , ( (n1Y <= n2Y ? y[0] : y[1]) - n1Y) / (n2Y - n1Y)
+                                     , ( (n1Z <= n2Z ? z[0] : z[1]) - n1Z) / (n2Z - n1Z) );
+
+         double t_fern = UbMath::min(  ( (n1X >  n2X ? x[0] : x[1]) - n1X) / (n2X - n1X)
+                                     , ( (n1Y >  n2Y ? y[0] : y[1]) - n1Y) / (n2Y - n1Y)
+                                     , ( (n1Z >  n2Z ? z[0] : z[1]) - n1Z) / (n2Z - n1Z) );
+
+         if ( UbMath::greater(  UbMath::max(  ( (n1X <= n2X ? x[0] : x[1]) - n1X) / (n2X - n1X)
+                                            , ( (n1Y <= n2Y ? y[0] : y[1]) - n1Y) / (n2Y - n1Y)
+                                            , ( (n1Z <= n2Z ? z[0] : z[1]) - n1Z) / (n2Z - n1Z) )
+                              , UbMath::min(  ( (n1X >  n2X ? x[0] : x[1]) - n1X) / (n2X - n1X)
+                                            , ( (n1Y >  n2Y ? y[0] : y[1]) - n1Y) / (n2Y - n1Y)
+                                            , ( (n1Z >  n2Z ? z[0] : z[1]) - n1Z) / (n2Z - n1Z) ) ) )
+         {
+            return Intersection::NO_INTERSECTION;
+         } 
+         else
+         {
+            return Intersection::INTERSECTION;
+         }
+      }
+      /* ======================================================================================= */
+      int intersectRayBoundingBox(const Ray<T>& ray) 
+      {
+         T tmin  = (x[  ray.signX] - ray.originX) * ray.inv_directionX;
+         T tmax  = (x[1-ray.signX] - ray.originX) * ray.inv_directionX;
+        
+         T tymin = (y[  ray.signY] - ray.originY) * ray.inv_directionY;
+         T tymax = (y[1-ray.signY] - ray.originY) * ray.inv_directionY;
+         
+         if( (tmin > tymax) || (tymin > tmax) ) 
+         {
+            return false;
+         }
+         if( tymin > tmin ) tmin = tymin;
+         if( tymax < tmax ) tmax = tymax;
+
+         T tzmin = (z[  ray.signZ] - ray.originZ) * ray.inv_directionZ;
+         T tzmax = (z[1-ray.signZ] - ray.originZ) * ray.inv_directionZ;
+         
+         //if( (UbMath::greater( tmin, tzmax) ) || ( UbMath::greater( tzmin, tmax) ) ) 
+         if( ( tmin > tzmax) || ( tzmin > tmax)  ) 
+         {
+            return false;
+         }
+         //if(tzmin > tmin) tmin = tzmin;
+         if(tzmax < tmax) tmax = tzmax;
+         
+         //return ( (tmin =< t1) && (tmax >= t0) );
+         if( UbMath::greaterEqual( tmax, T(0.0) ) )   
+         {
+            return Intersection::INTERSECTION;
+         }
+         else
+         {
+            return Intersection::NO_INTERSECTION;
+         }
+      }
+      /* ======================================================================================= */
+      bool intersectLine(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2, const LineIntersectionHandler<T>& iHandler) 
+      {
+         return iHandler.intersectLine(n1, n2, *this, child1, child2);
+      }
+      /* ======================================================================================= */
+      int intersectRay(const Ray<T>& ray, const RayIntersectionHandler<T>& iHandler, std::set< UbKeys::Key3<int> >& mailbox) 
+      {
+         return iHandler.intersectRay(ray, *this, child1, child2, mailbox);
+      }
+      /* ======================================================================================= */
+      int getNumOfTriFaces()
+      {
+         if(!child1 && !child2)
+         {  
+            if(triFaces) return (int)triFaces->size();
+            else         return 0;
+         } 
+         else 
+         {
+            int sum = 0;
+
+            if(child1) sum += child1->getNumOfTriFaces();
+            if(child2) sum += child2->getNumOfTriFaces();
+
+            return sum;
+         }
+      }
+      /* ======================================================================================= */
+      int getNumOfNodes()
+      {
+         if( !child1 && !child2) 
+         {
+            return 1;
+         } 
+         else
+         {
+            int sum = 0;
+            if(child1) sum += child1->getNumOfNodes();
+            if(child2) sum += child2->getNumOfNodes();
+
+            return 1 + sum;
+         }
+      }
+      /* ======================================================================================= */
+      std::string toString()
+      {
+         return "";//"[" + x1 + "," + y1 + "," + z1 + "]  -" + "  [" + x2 + "," + y2 + "," + z2 + "]";
+      }
+      /* ======================================================================================= */
+      void addCubeInfo(std::vector< UbTupleFloat3 >& nodes, std::vector< UbTupleInt8 >& cells, std::vector<std::string >& datanames, std::vector<std::vector<double > >& celldata)
+      {
+         nodes.push_back( makeUbTuple(float(x[0]), float(y[0]), float(z[0]) ) );
+         nodes.push_back( makeUbTuple(float(x[1]), float(y[0]), float(z[0]) ) );
+         nodes.push_back( makeUbTuple(float(x[1]), float(y[1]), float(z[0]) ) );
+         nodes.push_back( makeUbTuple(float(x[0]), float(y[1]), float(z[0]) ) );
+         
+         nodes.push_back( makeUbTuple(float(x[0]), float(y[0]), float(z[1]) ) );
+         nodes.push_back( makeUbTuple(float(x[1]), float(y[0]), float(z[1]) ) );
+         nodes.push_back( makeUbTuple(float(x[1]), float(y[1]), float(z[1]) ) );
+         nodes.push_back( makeUbTuple(float(x[0]), float(y[1]), float(z[1]) ) );
+
+         cells.push_back( makeUbTuple( int(nodes.size()-8), int(nodes.size()-7), int(nodes.size()-6), int(nodes.size()-5), 
+                                       int(nodes.size()-4), int(nodes.size()-3), int(nodes.size()-2), int(nodes.size()-1) ) );
+         datanames.resize(1);
+         datanames[0] = "childs";
+         celldata.resize( datanames.size() );
+         if     ( child1 && child2 ) celldata[0].push_back(2);
+         else if( child1 || child2 ) celldata[0].push_back(1);
+         else                        celldata[0].push_back(0);
+
+         if(child1) child1->addCubeInfo(nodes, cells, datanames, celldata);
+         if(child2) child2->addCubeInfo(nodes, cells, datanames, celldata);
+      }
+
+   public:
+      T x[2], y[2], z[2];
+
+   private:
+      Node* child1;
+      Node* child2;
+
+      MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFaces;
+      std::vector<GbTriFaceMesh3D::Vertex>*               ptrNodes;  //lediglich für Zugriff auf die Knoten!!!
+   };
+}
+#endif //KDNODE_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/KdRay.h b/source/VirtualFluidsCore/Geometry/KdTree/KdRay.h
new file mode 100644
index 0000000000000000000000000000000000000000..c53dfa93fc5b0b99f9adb40cd556cce5756433aa
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/KdRay.h
@@ -0,0 +1,69 @@
+#ifndef KDRAY_H
+#define KDRAY_H
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbMath.h>
+
+
+namespace Kd
+{
+   /*
+   * Ray class, for use with the optimized ray-box intersection test
+   * described in:
+   *
+   *      Amy Williams, Steve Barrus, R. Keith Morley, and Peter Shirley
+   *      "An Efficient and Robust Ray-Box Intersection Algorithm"
+   *      Journal of graphics tools, 10(1):49-54, 2005
+   * 
+   */
+   template< typename T>
+   class Ray 
+   {
+   public:
+      Ray(  const T& originX   , const T& originY   , const T& originZ
+          , const T& directionX, const T& directionY, const T& directionZ ) 
+      {
+         this->originX        = originX;
+         this->originY        = originY;
+         this->originZ        = originZ;
+
+         //normierung (fuer ray-triangle-intersection)
+         T oneOverLength = T(1.0/std::sqrt(  directionX*directionX 
+                                            + directionY*directionY 
+                                            + directionZ*directionZ ) );
+
+         this->directionX     = directionX*oneOverLength;
+         this->directionY     = directionY*oneOverLength;
+         this->directionZ     = directionZ*oneOverLength;
+
+         this->inv_directionX = T(1.0/this->directionX);   //ACHTUNG: BEWUSST KEINE ==0 Abfrage
+         this->inv_directionY = T(1.0/this->directionY);   //Alg verwendet exlitzit INF
+         this->inv_directionZ = T(1.0/this->directionZ);
+         
+         if(this->inv_directionX < 0.0) this->signX = 1;
+         else                           this->signX = 0;
+         if(this->inv_directionY < 0.0) this->signY = 1;
+         else                           this->signY = 0;
+         if(this->inv_directionZ < 0.0) this->signZ = 1;
+         else                           this->signZ = 0;
+      }
+
+      T   originX;
+      T   originY;
+      T   originZ;
+        
+      T   directionX;
+      T   directionY;
+      T   directionZ;
+        
+      T   inv_directionX;
+      T   inv_directionY;
+      T   inv_directionZ;
+      
+      int signX;
+      int signY;
+      int signZ;
+   };
+} //namespace Kd
+
+#endif //KDRAY_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/KdSplitCandidate.h b/source/VirtualFluidsCore/Geometry/KdTree/KdSplitCandidate.h
new file mode 100644
index 0000000000000000000000000000000000000000..361550555498cf4d5eae0ef00d68a720895055ab
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/KdSplitCandidate.h
@@ -0,0 +1,68 @@
+#ifndef KDSPLITCANDIDATE_H
+#define KDSPLITCANDIDATE_H
+
+#include <basics/utilities/UbMath.h>
+
+namespace Kd
+{
+   template< typename T >
+   class SplitCandidate   
+   {
+   public:
+      SplitCandidate() 
+         :  axis(0)
+          , position(0.0)
+          , starting(0)
+          , ending(0)
+          , np_left(false)
+          , np_right(false)
+          , Cn(0.0)
+          , nr(0)
+          , nl(0)  
+          , isValid(false)
+      {
+
+      }
+      /* ======================================================================================= */
+      SplitCandidate(const int& axis, const T& position, const int& starting, const int& ending, const int& insidePlane)
+         : np_left(false)
+         , np_right(false)
+         , axis(axis)
+         , position(position)
+         , starting(starting)
+         , ending(ending)
+         , np(insidePlane)
+         , Cn(0.0) 
+         , nr(0)  
+         , nl(0)  
+         , isValid(true)
+      {
+      }
+      /* ======================================================================================= */
+      bool operator!() const
+      {
+         return isValid; 
+      }
+      /* ======================================================================================= */
+      friend inline bool operator< (const SplitCandidate& lhs, const SplitCandidate& rhs)  
+      {
+         return  lhs.position < rhs.position;
+      }
+      /* ======================================================================================= */
+
+   public:
+      int     axis;
+      T       Cn;
+      T       position;
+      int     nl;
+      int     nr;
+      int     np;
+      int     starting;
+      int     ending;
+      bool    np_left;
+      bool    np_right;
+      bool    isValid;
+   };
+}
+
+#endif //KDSPLITCANDIDATE_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/KdSplitCandidateManager.h b/source/VirtualFluidsCore/Geometry/KdTree/KdSplitCandidateManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..0278807f8dd3b97e8303f0935205060852adc6d4
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/KdSplitCandidateManager.h
@@ -0,0 +1,75 @@
+#ifndef KDSPLITCANDIDATEMANAGER_H
+#define KDSPLITCANDIDATEMANAGER_H
+
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+
+#include <map>
+#include <vector>
+#include <algorithm>
+
+
+namespace Kd
+{
+   template< typename T >
+   class SplitCandidateManager  
+   {
+   public:
+      SplitCandidateManager()
+         : objects_starting_outside_left(0)
+         , objects_fully_outside_node(0)
+      {
+
+      }
+      /* ======================================================================================= */
+      SplitCandidate<T>& operator[] (const int& i) 
+      { 
+         #ifdef DEBUG
+            return splitCandidatesVec.at(i);
+         #else
+            return splitCandidatesVec[i];
+         #endif  
+      }
+      /* ======================================================================================= */
+      typename std::vector< SplitCandidate< T > >::size_type size()
+      { 
+         return splitCandidatesVec.size();
+      }
+      /* ======================================================================================= */
+      void add(const T& pos, const int& axis, const int& starting, const int& ending, const int& np)
+      {
+         typename std::map<T, SplitCandidate<T> >::iterator it = splitCandidates.find(pos); 
+         if ( it != splitCandidates.end() )   //split candidate is already available -> increase parameter (starting, ending and np)
+         {
+            SplitCandidate<T>& sc = it->second;
+            sc.np       += np;
+            sc.starting += starting;
+            sc.ending   += ending;
+         } 
+         else // split candidate is not available -> add new split candidate
+         {
+            this->splitCandidates[pos] = SplitCandidate<T>(axis, pos, starting, ending, np);
+         }
+      }
+      /* ======================================================================================= */
+      void createSortedArray()
+      {
+         splitCandidatesVec.clear();
+         typename std::map<T, SplitCandidate<T> >::iterator it;
+         for( it=splitCandidates.begin(); it!=splitCandidates.end(); ++it)
+            splitCandidatesVec.push_back(it->second);
+         splitCandidates.clear();
+         std::sort(splitCandidatesVec.begin(), splitCandidatesVec.end(), std::less< SplitCandidate<T> >() );
+      }
+      /* ======================================================================================= */
+
+   public:
+      int objects_starting_outside_left;
+      int objects_fully_outside_node;
+
+   private:
+      std::map<T, SplitCandidate<T> > splitCandidates;
+      std::vector< SplitCandidate<T> >    splitCandidatesVec;
+   };
+}
+
+#endif //KDSPLITCANDIDATEMANAGER_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/KdTree.h b/source/VirtualFluidsCore/Geometry/KdTree/KdTree.h
new file mode 100644
index 0000000000000000000000000000000000000000..83c33266cca0d38e5fbce8094bc2c30c07687f45
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/KdTree.h
@@ -0,0 +1,100 @@
+#ifndef KDTREE_H
+#define KDTREE_H
+
+#include <basics/memory/MbSmartPtr.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <basics/utilities/UbKeys.h>
+
+#include <numerics/geometry3d/KdTree/KdNode.h>
+#include <numerics/geometry3d/KdTree/KdRay.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+
+#include <string>
+
+namespace Kd
+{
+   template< typename T >
+   class Tree 
+   {
+   public:
+      /* ======================================================================================= */
+      Tree(GbTriFaceMesh3D& mesh, const SplitAlgorithm<T>& splitAlg) 
+         : rootNode(NULL)
+      {
+         this->buildTree(mesh, splitAlg);
+      }
+      /* ======================================================================================= */
+      ~Tree()
+      {
+         if(rootNode)  { delete rootNode; rootNode = NULL; }
+      }
+      /* ======================================================================================= */
+      // the IntersectionHandler specifies how to handle the intersection
+      bool intersectLine(const UbTuple< T, T, T >& n1, const UbTuple< T, T, T >& n2, const LineIntersectionHandler<T>& iHandler) 
+      {
+         return rootNode->intersectLine(n1, n2, iHandler);
+      }
+      /* ======================================================================================= */
+      // the IntersectionHandler specifies how to handle the intersection
+      int intersectRay(const Ray<T>& ray, const RayIntersectionHandler<T>& iHandler) 
+      {
+         std::set< UbKeys::Key3<int> > mailbox;
+         return rootNode->intersectRay(ray, iHandler, mailbox);
+      }
+      /* ======================================================================================= */
+      int getNumOfNodes() 
+      {                                               
+         if(rootNode) return rootNode->getNumOfNodes();
+         return 0;
+      }
+      /* ======================================================================================= */
+      int getNumOfTriFaces() 
+      {
+         if(rootNode) return rootNode->getNumOfTriFaces();
+         return 0;
+      }
+      /* ======================================================================================= */
+      std::string toString() 
+      {
+         return "";//Tree:: num of nodes: " + rootNode.getNumOfNodes() + ", primitives:" + rootNode.getNumOfPrimitives() + ", root_primitives:" + getNumOfPrimitives() + ", max_level:" + max_level;
+      }
+      /* ======================================================================================= */
+      void buildTree(GbTriFaceMesh3D& mesh, const SplitAlgorithm<T>& splitAlg ) 
+      {
+         if(rootNode) delete rootNode;
+          
+         // create a copy of triangles 
+         MbSmartPtr< std::vector<GbTriFaceMesh3D::TriFace> > triFaces(new std::vector<GbTriFaceMesh3D::TriFace>(*mesh.getTriangles() ) );
+         
+         int maxLevel = (int)(8.0 + 1.3 * std::log( (double)triFaces->size() ) + 0.5);
+
+         rootNode = new Node<T>(   T( mesh.getX1Minimum() )
+                                 , T( mesh.getX2Minimum() )
+                                 , T( mesh.getX3Minimum() )
+                                 , T( mesh.getX1Maximum() )
+                                 , T( mesh.getX2Maximum() )
+                                 , T( mesh.getX3Maximum() )
+                                 , triFaces, mesh.getNodes() );
+
+         rootNode->buildTree(0, maxLevel, splitAlg);
+      }
+      void writeTree(const std::string& filename, WbWriter* writer = WbWriterVtkXmlBinary::getInstance())
+      {
+         if(rootNode)
+         {
+            std::vector<UbTupleFloat3 >        nodes;
+            std::vector<UbTupleInt8 >          cubes;
+            std::vector<std::string >          datanames;
+            std::vector<std::vector<double > > cubesdata;
+            rootNode->addCubeInfo(nodes, cubes, datanames, cubesdata);
+            writer->writeOctsWithCellData(filename,nodes,cubes,datanames,cubesdata);
+         }
+      }
+   private:
+      Node<T>* rootNode;    
+   };
+}
+
+#endif //KDTREE_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/KdUtilities.cpp b/source/VirtualFluidsCore/Geometry/KdTree/KdUtilities.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..efbdd580caa25bb09f8278bec078da6b0c4fecfb
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/KdUtilities.cpp
@@ -0,0 +1,13 @@
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+
+namespace Kd
+{
+   const int Axis::X = 0;
+   const int Axis::Y = 1;
+   const int Axis::Z = 2;
+
+   const int Intersection::ON_BOUNDARY     = -2;
+   const int Intersection::INTERSECT_EDGE  = -1;
+   const int Intersection::INTERSECTION    =  1;
+const int Intersection::NO_INTERSECTION =  0;
+} //namespace Kd
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/KdUtilities.h b/source/VirtualFluidsCore/Geometry/KdTree/KdUtilities.h
new file mode 100644
index 0000000000000000000000000000000000000000..39a700cc4e216e6349f5d15ddc28c4b6f93c663e
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/KdUtilities.h
@@ -0,0 +1,164 @@
+#ifndef KDUTILIES_H
+#define KDUTILIES_H
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbMath.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <algorithm>
+#include <vector>
+
+namespace Kd
+{
+   struct  Axis 
+   {
+      static const int X;// = 0;
+      static const int Y;// = 1;
+      static const int Z;// = 2;
+   };
+   /* ======================================================================================= */
+   struct Intersection 
+   {
+      static const int ON_BOUNDARY;    // = -2;
+      static const int INTERSECT_EDGE; // = -1;
+      static const int INTERSECTION;   // = 1;
+      static const int NO_INTERSECTION;// = 0;
+   };
+   /* ======================================================================================= */
+   template< typename T>
+   inline void project2Axis(GbTriFaceMesh3D::TriFace& triFace, std::vector<GbTriFaceMesh3D::Vertex>& nodes, const int& axis, std::vector<T>& projection) 
+   {
+      projection.resize(3);
+   
+      if(axis==Axis::X)
+      {
+         projection[0] = triFace.getV1x(nodes);
+         projection[1] = triFace.getV2x(nodes);
+         projection[2] = triFace.getV3x(nodes);
+      }
+      else if(axis==Axis::Y)
+      {
+         projection[0] = triFace.getV1y(nodes);
+         projection[1] = triFace.getV2y(nodes);
+         projection[2] = triFace.getV3y(nodes);
+      }
+      else if(axis==Axis::Z)
+      {
+         projection[0] = triFace.getV1z(nodes);
+         projection[1] = triFace.getV2z(nodes);
+         projection[2] = triFace.getV3z(nodes);
+      }
+      else throw UbException(UB_EXARGS,"unknown axis");
+      
+      std::sort( projection.begin(), projection.end(), std::less<double>() );
+   }
+   /* ======================================================================================= */
+   template< typename T>
+   inline bool isPointOnPlane(const T& px, const T& py, const T& pz, const T& precision, GbTriFaceMesh3D::Vertex& pointOfTriFace, GbTriFaceMesh3D::TriFace& triFace) 
+   {
+      return std::fabs( (px - pointOfTriFace.x) * triFace.nx + (py - pointOfTriFace.y) * triFace.ny + (pz - pointOfTriFace.z) * triFace.nz ) < precision;
+   }
+   /* ======================================================================================= */
+   template< typename T>
+   inline bool isPointOnTriangle( const T& px, const T& py, const T& pz, const T& precision
+                               , GbTriFaceMesh3D::Vertex& p1, GbTriFaceMesh3D::Vertex& p2, GbTriFaceMesh3D::Vertex& p3
+                               , GbTriFaceMesh3D::TriFace& triFace  ) 
+   {
+      if( Kd::isPointOnPlane(px, py, pz, precision, p1, triFace) ) 
+      {
+         T a_x = p1.x - px;
+         T a_y = p1.y - py;
+         T a_z = p1.z - pz;
+         T b_x = p2.x - px;
+         T b_y = p2.y - py;
+         T b_z = p2.z - pz;
+         T c_x = p3.x - px;
+         T c_y = p3.y - py;
+         T c_z = p3.z - pz;
+
+         const T factor = 0.5;
+         T Q1_x = (a_y * b_z - a_z * b_y) * factor;
+         T Q1_y = (a_z * b_x - a_x * b_z) * factor;
+         T Q1_z = (a_x * b_y - a_y * b_x) * factor;
+
+         T Q2_x = (b_y * c_z - b_z * c_y) * factor;
+         T Q2_y = (b_z * c_x - b_x * c_z) * factor;
+         T Q2_z = (b_x * c_y - b_y * c_x) * factor;
+
+         T Q3_x = (c_y * a_z - c_z * a_y) * factor;
+         T Q3_y = (c_z * a_x - c_x * a_z) * factor;
+         T Q3_z = (c_x * a_y - c_y * a_x) * factor;
+
+         T Q_x = Q1_x + Q2_x + Q3_x;
+         T Q_y = Q1_y + Q2_y + Q3_y;
+         T Q_z = Q1_z + Q2_z + Q3_z;
+
+
+         if     ( UbMath::zero(Q_x * Q1_x + Q_y * Q1_y + Q_z * Q1_z         ) ) return true;
+         else if( UbMath::zero(Q_x * Q2_x + Q_y * Q2_y + Q_z * Q2_z         ) ) return true;
+         else if( UbMath::zero(Q_x * Q3_x + Q_y * Q3_y + Q_z * Q3_z         ) ) return true;
+         else if( UbMath::less(Q_x * Q1_x + Q_y * Q1_y + Q_z * Q1_z, T(0.0) ) ) return false;
+         else if( UbMath::less(Q_x * Q2_x + Q_y * Q2_y + Q_z * Q2_z, T(0.0) ) ) return false;
+         else if( UbMath::less(Q_x * Q3_x + Q_y * Q3_y + Q_z * Q3_z, T(0.0) ) ) return false;
+
+         return true;
+      } 
+      
+      return false;
+   }
+   /* ======================================================================================= */
+   template< typename T>
+   inline bool intersectLine(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2, GbTriFaceMesh3D::TriFace& triFace, std::vector<GbTriFaceMesh3D::Vertex>& nodes) 
+   {
+      GbTriFaceMesh3D::Vertex& p0=triFace.getNode(0,nodes);
+      
+      const T& n1X = val<1>(n1);
+      const T& n1Y = val<2>(n1);
+      const T& n1Z = val<3>(n1);
+
+      const T& n2X = val<1>(n2);
+      const T& n2Y = val<2>(n2);
+      const T& n2Z = val<3>(n2);
+
+      //if(   Kd::isPointOnPlane(n1X, n1Y, n1Z, T(1.0E-6), p0, triFace) 
+      //   && Kd::isPointOnPlane(n2X, n2Y, n2Z, T(1.0E-6), p0, triFace)) 
+      //{
+      //   return true;
+      //}
+
+         T denom = ( n2X - n1X ) * triFace.nx + ( n2Y - n1Y ) * triFace.ny + ( n2Z - n1Z ) * triFace.nz;
+
+         if( UbMath::zero( denom ) )  //line does not intersect the plane of the triangle !
+         {
+         return false;
+         } 
+         else 
+         {
+            T d  = - triFace.nx * p0.x - triFace.ny * p0.y - triFace.nz * p0.z;
+            T mu = T(-1.0 * (d + n1X * triFace.nx + n1Y * triFace.ny + n1Z * triFace.nz ) / denom);
+
+            if( !UbMath::inClosedInterval( mu, T(0.0), T(1.0)) )  // Point of intersection of line and plane does not lie on the triangle
+            {
+            return false;
+            } 
+            else 
+            {
+               // intersection with plane
+ 
+               //Test whether Point lies inside the triangle or not
+            GbTriFaceMesh3D::Vertex& p1=triFace.getNode(1,nodes);
+            GbTriFaceMesh3D::Vertex& p2=triFace.getNode(2,nodes);
+               
+               return Kd::isPointOnTriangle(  n1X + ( (n2X - n1X) * mu )   //intersectionPointX
+                                            , n1Y + ( (n2Y - n1Y) * mu )   //intersectionPointY
+                                            , n1Z + ( (n2Z - n1Z) * mu )   //intersectionPointZ
+                                            , T(0.001)
+                                            , p0, p1, p2, triFace );
+            }
+         }
+      } 
+} //namespace Kd
+
+#endif //KDUTILIES_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/examples/AdvancedPIOTests/CMakeLists.txt b/source/VirtualFluidsCore/Geometry/KdTree/examples/AdvancedPIOTests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1b2fd9ad9cd9a3ca227dce4499cb7d665289945a
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/examples/AdvancedPIOTests/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(kdtree_pioTest)
+
+#################################################################
+# MACHINE_SPECIFIC CMAKE_CONFIG_FILE
+#################################################################
+INCLUDE("../../../../../CMake/CMakeCABMacros.txt")
+
+#################################################################
+###   PACKAGES                                               ###
+#################################################################
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/3rdParty/dirstream/CMakePackage.txt)
+
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/container/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/memory/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/objects/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/writer/CMakePackage.txt)
+
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/KdTree/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/fem/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/creator/CMakePackage.txt)
+
+#################################################################
+###   OWN DEFINES 						###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) 
+
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(z_main FILES ${SPECIFIC_FILES})
+
+#################################################################
+###  PROJECT ERSTELLEN                                        ###
+#################################################################
+CREATE_CAB_PROJECT(${PROJECT_NAME} BINARY)
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/examples/AdvancedPIOTests/main.cpp b/source/VirtualFluidsCore/Geometry/KdTree/examples/AdvancedPIOTests/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0c0b9454745a3554ab32b7d81f6639749dd45545
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/examples/AdvancedPIOTests/main.cpp
@@ -0,0 +1,542 @@
+#include <basics/utilities/UbTiming.h>
+#include <basics/utilities/UbRandom.h>
+#include <basics/utilities/UbTuple.h>
+
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/writer/WbWriterAvsBinary.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+
+#include <basics/container/CbUniformMatrix3D.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+
+#include <numerics/geometry3d/KdTree/KdTree.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h>
+
+#include <stack>
+#include <list>
+
+using namespace std;
+
+void createGrid(std::string meshfile, int maxNofPointsPerDir, Kd::SplitAlgorithm<float>& splitAlg, bool writeFiles = true, std::string outpath = "g:/temp");
+void recursiveGridFill(CbUniformMatrix3D<short>& grid, const short& xs, const short& ys, const short& zs, const short& type);
+void iterativeGridFill(CbUniformMatrix3D<short>& grid, const short& xs, const short& ys, const short& zs, const short& type);
+
+#include <3rdParty/dirstream/dirstream.h>
+#include <3rdParty/dirstream/filter_utils.h>  // enthält die Definiton der bool'schen Ops für Filter
+
+
+using namespace std;
+
+int main()
+{
+   try
+   {
+//       //////////////////////////////////////////////////////////////////////////
+//       //STL File auswaehlen
+//       //////////////////////////////////////////////////////////////////////////
+//       string pathname = "c:/temp";
+//       string stlPath = "c:/temp";
+//       dirstr::dirstream str(stlPath.c_str(), dirstr::op(dirstr::pattern_f("*.stl")) 
+//                            || dirstr::op(dirstr::pattern_f("*.ply"))  || dirstr::op(dirstr::pattern_f("*.inp"))
+//                            || dirstr::op(dirstr::pattern_f("*.mesh")));
+// 
+// //      UbLog::setReportingLevel(logDEBUG5);
+//       UbLog::setReportingLevel(logINFO);
+// 
+//       vector<string> filenames;
+//       for(string entry; str >> entry;)
+//       {
+//          GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(entry,"mesh");
+// 
+//          string fn = UbSystem::getFilenameFromString(entry);
+//          mesh->writeMeshPly(pathname+"/"+fn+".ply");
+// 
+//          delete mesh;
+//       }
+// 
+//       exit(0);
+
+      //createGrid("c:/temp/clumps.stl", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/50spheres.inp", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/Sphere5040.inp", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/cooling_2.inp", 400, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/NDR-Konzertsaal.inp", 100, Kd::SAHSplit<float>() , true, "g:/temp");
+      
+      //createGrid("c:/temp/Campus-Details-W3.inp", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/Boein707.mesh", 100, Kd::SAHSplit<float>() , true, "g:/temp");
+      
+      //createGrid("c:/temp/dolphin.mesh", 400, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/box.ply", 10, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/bodyRight.stl", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/flamingo.mesh", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      
+      //createGrid("c:/temp/torus.inp", 256, Kd::SAHSplit<float>() , true, "g:/temp");
+      createGrid("c:/temp/xzx_dragon.stl", 512, Kd::SAHSplit<float>() , true, "g:/temp");
+//       createGrid("c:/temp/bunny_ascii.ply", 256, Kd::SAHSplit<float>() , true, "g:/temp");
+//       createGrid("c:/temp/dragon_ascii.ply", 256, Kd::SAHSplit<float>() , true, "g:/temp");
+//       createGrid("c:/temp/budda_ascii.ply", 256, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGridWithLines("c:/temp/box.ply", 10, Kd::SAHSplit<float>() , true, "g:/temp");
+      
+//       createGrid("c:/temp/beatle.mesh",200, Kd::SAHSplit<float>(), true, "g:/temp");
+//       createGrid("c:/temp/atrium-30000tri.inp",200, Kd::SAHSplit<float>(), true, "g:/temp");
+//       createGrid("c:/temp/Buero.inp",200, Kd::SAHSplit<float>(), true, "g:/temp");
+//       createGrid("c:/temp/office_space.inp",200, Kd::SAHSplit<float>(), true, "g:/temp");
+
+      //createGrid("d:/meshes/50spheres.inp",200, Kd::SAHSplit<float>(), true, "d:/temp");
+
+      //createGrid("c:/temp/torus.inp",200, Kd::SAHSplit<float>(), true, "g:/temp");
+      //createGrid("c:/temp/bodyRight.stl", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+
+      //createGrid("c:/temp/jetta.stl", 200, GbTriFaceMesh3D::KDTREE_SPATIALSPLIT , true, "g:/temp");
+      //createGrid("c:/temp/jetta.stl", 200, Kd::SAHSplit<float>(), true, "g:/temp");
+      //createGrid("c:/temp/VW_body.ply", 200, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/kugel.stl", 50, Kd::SAHSplit<float>() , true, "g:/temp");
+      //createGrid("c:/temp/ship-2.mesh", 100, Kd::SAHSplit<float>() , true, "g:/temp/schiff2");                                                   
+   }
+   catch(const std::exception& e)
+   {
+      UBLOG2(  logERROR, std::cerr, "Caught exception:");
+      UBLOG2(  logERROR, std::cerr, "Type: " << typeid(e).name() );
+      UBLOG2ML(logERROR, std::cerr, "What: " << e.what() );
+   }
+   catch(...)
+   {
+      UBLOG2(logERROR, std::cerr, "unknown exception occurs in "<< UB_FUNCTION)
+   }
+}
+
+namespace Flag
+{
+   const short UNDEF = 2;
+   const short SOLID = 1;
+   const short FLUID = 0;
+}
+
+//////////////////////////////////////////////////////////////////////
+void createGrid(std::string meshfile, int maxNofPointsPerDir, Kd::SplitAlgorithm<float>& splitAlg, bool writeFiles, std::string outpath)
+{
+   UbLog::setReportingLevel(logDEBUG5);
+   std::string filename = UbSystem::getFilenameFromString(meshfile);
+
+   std::list< UbTuple<string, double> > timerVals;
+   UbTimer timer;
+   timer.start();
+   GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(meshfile,"mesh",GbTriFaceMesh3D::KDTREE_SAHPLIT);
+   timerVals.push_back( UbTuple<string, double>("mesh", timer.stop() ) );
+   UBLOG( logINFO, "read mesh in "<<val<2>(timerVals.back())<<"s" );
+   
+   timer.start();
+   Kd::Tree<float> kdTree( *mesh, splitAlg  );
+   timerVals.push_back( UbTuple<string, double>("kdTree", timer.stop() ) );
+   UBLOG( logINFO, "build tree in "<<val<2>(timerVals.back())<<"s" );
+
+   UBLOG(logINFO, "############################################################");
+   UBLOG(logINFO, "nodes of TriFaceMesh....... "<<mesh->getNodes()->size()      );
+   UBLOG(logINFO, "triFaces of TriFaceMesh.... "<<mesh->getTriangles()->size()  );
+   UBLOG(logINFO, "triFace copies in KdTree... "<<kdTree.getNumOfTriFaces()     );
+   UBLOG(logINFO, "nodes of kdNodes of KdTree. "<<kdTree.getNumOfNodes()        );
+   UBLOG(logINFO, "");
+
+   //////////////////////////////////////////////////////////////////////////
+   // Ausgangs 3-D_Feld erstellen
+   //////////////////////////////////////////////////////////////////////////
+   const float percentOverLap = 0.05f; //=5%
+   const float maxLength = (1.0f+percentOverLap)*(float)UbMath::max( mesh->getLengthX1(), mesh->getLengthX2(), mesh->getLengthX3() );
+   const float dx1 = maxLength/(maxNofPointsPerDir-1);
+   const float dx2 = dx1;
+   const float dx3 = dx1;
+
+   const int nx1 = 1 + int( std::ceil(mesh->getLengthX1()*(1.0f+percentOverLap)/dx1)+0.5 );
+   const int nx2 = 1 + int( std::ceil(mesh->getLengthX2()*(1.0f+percentOverLap)/dx2)+0.5 );
+   const int nx3 = 1 + int( std::ceil(mesh->getLengthX3()*(1.0f+percentOverLap)/dx3)+0.5 );
+
+   CbUniformMatrix3D<short> solids(nx1,nx2,nx3,Flag::UNDEF);
+
+   //////////////////////////////////////////////////////////////////////////
+   // Knoten typisieren
+   //////////////////////////////////////////////////////////////////////////
+   const float orgx1 = (float)( -0.5*percentOverLap*mesh->getLengthX1()+mesh->getX1Minimum() );
+   const float orgx2 = (float)( -0.5*percentOverLap*mesh->getLengthX2()+mesh->getX2Minimum() );
+   const float orgx3 = (float)( -0.5*percentOverLap*mesh->getLengthX3()+mesh->getX3Minimum() );
+
+   std::vector<GbTriFaceMesh3D::TriFace>& triFaces = *mesh->getTriangles();
+   std::vector<GbTriFaceMesh3D::Vertex>&  vertices = *mesh->getNodes();
+
+   float x1center = float( mesh->getX1Centroid() );
+   float x2center = float( mesh->getX2Centroid() );
+   float x3center = float( mesh->getX3Centroid() );
+
+   UBLOG( logINFO, "performing point-in-object(PIO)-tests");
+   long  counter1=0, counter2 = 0;
+   float x1w, x2w, x3w;
+   int   x1Min, x2Min, x3Min, x1Max, x2Max, x3Max;
+   float einflussBereichKnoten_sq = dx1*dx1+dx2*dx2+dx3*dx3;
+
+   timer.start();
+   for(size_t t=0; t<triFaces.size(); t++)   
+   {
+      GbTriFaceMesh3D::TriFace& triangle = triFaces[t];
+      GbTriFaceMesh3D::Vertex& v1 = vertices[triangle.v1];
+      GbTriFaceMesh3D::Vertex& v2 = vertices[triangle.v2];
+      GbTriFaceMesh3D::Vertex& v3 = vertices[triangle.v3];
+
+      //////////////////////////////////////////////////////////////////////////
+      // AABB riangle
+      //////////////////////////////////////////////////////////////////////////
+      x1Min = /*UbMath::integerRounding*/( std::floor( ( UbMath::min( v1.x, v2.x, v3.x ) - orgx1) / dx1 ) );
+      x2Min = /*UbMath::integerRounding*/( std::floor( ( UbMath::min( v1.y, v2.y, v3.y ) - orgx2) / dx2 ) );
+      x3Min = /*UbMath::integerRounding*/( std::floor( ( UbMath::min( v1.z, v2.z, v3.z ) - orgx3) / dx3 ) );
+
+      x1Max = /*UbMath::integerRounding*/( std::ceil(  ( UbMath::max( v1.x, v2.x, v3.x ) - orgx1) / dx1 ) );
+      x2Max = /*UbMath::integerRounding*/( std::ceil(  ( UbMath::max( v1.y, v2.y, v3.y ) - orgx2) / dx2 ) );
+      x3Max = /*UbMath::integerRounding*/( std::ceil(  ( UbMath::max( v1.z, v2.z, v3.z ) - orgx3) / dx3 ) );
+
+      GbHalfSpace3D halfSpace(  v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z );
+
+      for(int x3=x3Min; x3<=x3Max; x3++)
+      {
+         for(int x2=x2Min; x2<=x2Max; x2++)
+         {
+            for(int x1=x1Min; x1<=x1Max; x1++)
+            {
+               counter1++;
+               
+               short& solidVal = solids(x1,x2,x3);
+
+               if( solidVal != Flag::UNDEF )  //doppeltes Testen vermeiden
+               {
+                  continue;
+               }
+ 
+               counter2++;
+               
+               //Weltkoords
+               x1w = orgx1+x1*dx1;
+               x2w = orgx2+x2*dx2;
+               x3w = orgx3+x3*dx3;
+
+               float dist = (float)halfSpace.getDistance( x1w, x2w, x3w );
+               if( UbMath::greater( dist, 0.0f) )
+               {
+                  continue;
+               }
+               if( UbMath::greater(dist*dist, einflussBereichKnoten_sq))
+               {
+                  continue;
+               }
+               
+               //eigentlicher PIO-Test
+               bool testFailed = true;
+               for(int i=0; i<100; i++ )
+               {
+                  Kd::Ray<float> ray(  x1w, x2w, x3w  //, 1, 0 ,0 );
+                                     , ( x1w < x1center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                     , ( x2w < x2center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                     , ( x3w < x3center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) ) );
+
+                  int iSec = kdTree.intersectRay( ray, Kd::CountRayIntersectionHandler<float>() );
+                  
+                  if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+                  {
+                     if(iSec == Kd::Intersection::ON_BOUNDARY )
+                     {
+                        solidVal = Flag::SOLID;
+                     }
+                     else
+                     {
+                        solidVal = (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+                     }
+                     testFailed = false;
+                     break;
+                  }
+                  else
+                  {
+                     UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+                  }
+               }
+               if( testFailed ) throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+             }
+         }
+      }
+   }
+   timerVals.push_back( UbTuple<string, double>("PiO-Test", timer.stop() ) );
+   UBLOG( logINFO,counter2 <<" point-in-object(PIO)-tests done in "<<val<2>(timerVals.back())<<"s" );
+   UBLOG( logINFO,counter1-counter2 <<" point-in-object(PIO)-tests uebersprungen" );
+
+   //////////////////////////////////////////////////////////////////////////
+   // FLOOD FILL
+   //////////////////////////////////////////////////////////////////////////
+
+   if( false) //using just one seed point
+   {
+      //FUELL
+      bool foundSeedPoint         = false;
+      int  seedPointSearchCounter = 0;
+      int  seedX1 = Ub::inf;
+      int  seedX2 = Ub::inf;
+      int  seedX3 = Ub::inf;
+
+      timer.start();
+      for(size_t t=0; t<triFaces.size(); t++)   
+      {
+          GbTriFaceMesh3D::TriFace& triangle = triFaces[t];
+          
+          float& nx = triangle.nx;
+          float& ny = triangle.ny;
+          float& nz = triangle.nz;
+
+          float cx1 = triangle.getX1Centroid(vertices);
+          float cx2 = triangle.getX2Centroid(vertices);
+          float cx3 = triangle.getX3Centroid(vertices);
+
+          for(int k=0; k<5; k++) 
+          {
+             seedPointSearchCounter++;
+
+             cx1 -= nx * dx1;
+             cx2 -= ny * dx2;
+             cx3 -= nz * dx3;
+
+             int ix1 = UbMath::integerRounding( (cx1-orgx1)/dx1 );
+             int ix2 = UbMath::integerRounding( (cx2-orgx2)/dx2 );
+             int ix3 = UbMath::integerRounding( (cx3-orgx3)/dx3 );
+
+             if(   solids.indicesInRange(ix1,ix2,ix3)
+                && solids(ix1, ix2, ix3 ) == Flag::UNDEF )
+             {
+                x1w = orgx1+ix1*dx1;
+                x2w = orgx2+ix2*dx2;
+                x3w = orgx3+ix3*dx3;
+
+                Kd::Ray<float> ray(  x1w, x2w, x3w  //, 1, 0 ,0 );
+                                  , ( x1w < x1center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                  , ( x2w < x2center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                  , ( x3w < x3center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) ) );
+
+                int iSec = kdTree.intersectRay( ray, Kd::CountRayIntersectionHandler<float>() );
+
+                if( iSec>0 && (iSec&1) )
+                {
+                   seedX1 = ix1;
+                   seedX2 = ix2;
+                   seedX3 = ix3;
+                   foundSeedPoint = true;
+                   break;
+                }
+              }
+          }
+          if(foundSeedPoint) break;
+      }
+      if(!foundSeedPoint)
+         throw UbException(UB_EXARGS,"fuck no seed point found");
+      timerVals.push_back( UbTuple<string, double>("Seed found in", timer.stop() ) );
+      UBLOG( logINFO,"found seed Point in "<<val<2>(timerVals.back())<<"s with "<<seedPointSearchCounter << " tested points" );
+
+      cout<<nx1<<","<<nx2<<","<<nx3<<endl;
+      bool recursiveFloodFill = ( nx1*nx2*nx3 < 100*100*30 );
+      if(recursiveFloodFill)
+      {
+         timer.start();
+         recursiveGridFill(solids, seedX1, seedX2, seedX3, Flag::SOLID);
+         timerVals.push_back( UbTuple<string, double>("flood fill (r)", timer.stop() ) );
+         UBLOG( logINFO,"recursive flood fill in "<<val<2>(timerVals.back())<<"s with "<<seedPointSearchCounter << " tested points" );
+
+         CbUniformMatrix3D<short> solidsCpy(solids);
+         timer.start();
+         iterativeGridFill(solidsCpy, seedX1, seedX2, seedX3, Flag::SOLID);
+         timerVals.push_back( UbTuple<string, double>("flood fill (i)", timer.stop() ) );
+         UBLOG( logINFO,"iterative flood fill in "<<val<2>(timerVals.back())<<"s with "<<seedPointSearchCounter << " tested points" );
+      }
+      else
+      {
+         timer.start();
+         iterativeGridFill(solids, seedX1, seedX2, seedX3, Flag::SOLID);
+         timerVals.push_back( UbTuple<string, double>("flood fill (r)", timer.stop() ) );
+         UBLOG( logINFO,"recursive flood fill in "<<val<2>(timerVals.back())<<"s with "<<seedPointSearchCounter << " tested points" );
+      }
+      
+      UBLOG(logINFO, "############################################################");
+
+   }
+   else //verifying complete arry
+   {
+      bool recursiveFloodFill = ( nx1*nx2*nx3 < 100*100*30 );
+      int solidCounter  = 0;
+
+      timer.start();
+      for(int x3=0; x3<solids.getNX3(); x3++)
+         for(int x2=0; x2<solids.getNX2(); x2++)
+            for(int x1=0; x1<solids.getNX1(); x1++)
+            {
+               if( solids(x1  ,x2  ,x3 ) == Flag::UNDEF ) 
+               {
+                  x1w = orgx1+x1*dx1;
+                  x2w = orgx2+x2*dx2;
+                  x3w = orgx3+x3*dx3;
+
+                  int iSec = -1;
+                  do{
+                     Kd::Ray<float> ray(  x1w, x2w, x3w  //, 1, 0 ,0 );
+                                       , ( x1w < x1center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                       , ( x2w < x2center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) )
+                                       , ( x3w < x3center ? (float)UbRandom::rand(-1.0,-0.001, 10) : (float)UbRandom::rand(0.001, 1.0, 10) ) );
+
+                     iSec = kdTree.intersectRay( ray, Kd::CountRayIntersectionHandler<float>() );
+                  }while(iSec<0);
+
+                  if( iSec&1 )
+                  {
+                     if(recursiveFloodFill) recursiveGridFill(solids,x1,x2,x3,Flag::SOLID);
+                     else                   iterativeGridFill(solids,x1,x2,x3,Flag::SOLID);
+                  }
+                  else
+                  {
+                     if(recursiveFloodFill) recursiveGridFill(solids,x1,x2,x3,Flag::FLUID);
+                     else                   iterativeGridFill(solids,x1,x2,x3,Flag::FLUID);
+                  }
+               }
+            }
+      if(recursiveFloodFill) timerVals.push_back( UbTuple<string, double>("flood fill (r)", timer.stop() ) );
+      else                   timerVals.push_back( UbTuple<string, double>("flood fill (i)", timer.stop() ) );
+      UBLOG( logINFO,"recursive flood fill in "<<val<2>(timerVals.back())<<"s " );
+   }
+
+   list< UbTuple< string, double > >::iterator iter;
+   for(iter = timerVals.begin(); iter!=timerVals.end(); ++iter)
+   {
+      UBLOG( logINFO, setw(16) << val<1>(*iter) << " in " << setw(8) << setprecision(8) << val<2>(*iter) << "s" );
+   }
+
+   int solidCounter  = 0;
+   for(int x3=0; x3<solids.getNX3(); x3++)
+      for(int x2=0; x2<solids.getNX2(); x2++)
+         for(int x1=0; x1<solids.getNX1(); x1++)
+         {
+            if( solids(x1  ,x2  ,x3 ) == Flag::SOLID ) 
+            {
+               solidCounter++;
+            }
+         }
+
+   UBLOG( logINFO, "SOLIDS = " <<solidCounter);
+   UBLOG( logINFO, "SOLIDS = " <<solidCounter);
+   UBLOG( logINFO, "SOLIDS = " <<solidCounter);
+   UBLOG( logINFO, "SOLIDS = " <<solidCounter);
+
+   /* ======================================================================================= */
+   if(writeFiles) 
+   {
+      UBLOG( logINFO, "writeFiles - start");
+      string subfiledir = outpath+"/"+filename+"_solid_node_files";
+      UbSystem::makeDirectory( subfiledir );
+
+      std::vector<UbTupleFloat3 > nodes;
+      std::vector<std::string > datanames(1,"data");
+      datanames[0] = "solid";
+
+      std::vector< std::string > outFilenames;
+
+      std::vector<std::vector<double > > nodedata( datanames.size() );
+
+      for(int x3=0; x3<solids.getNX3(); x3++)
+         for(int x2=0; x2<solids.getNX2(); x2++)
+            for(int x1=0; x1<solids.getNX1(); x1++)
+            {
+               if( solids(x1  ,x2  ,x3 ) == Flag::SOLID ) 
+               {
+                  nodes.push_back( makeUbTuple(  orgx1+x1*dx1, orgx2+x2*dx2, orgx3+x3*dx3 ) );
+                  nodedata[0].push_back( solids(x1  ,x2  ,x3 ) );
+               }          
+
+               if(    nodes.size() > 2000000  
+                   || ( x1==(solids.getNX1()-1) && x2==(solids.getNX2()-1) && x3==(solids.getNX3()-1) ) ) 
+               {
+                  outFilenames.push_back( WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(subfiledir+"/"+filename+"_solid_nodes_"+"_part"+UbSystem::toString(outFilenames.size()+1),nodes,datanames,nodedata) );
+                  nodes.clear();
+                  nodedata.clear();
+                  nodedata.resize( datanames.size() );
+               }
+            }
+   
+      WbWriterVtkXmlBinary::getInstance()->writeCollection(outpath+"/"+filename+"_solids_nodes",outFilenames,0,false);
+      
+      
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterVtkXmlBinary::getInstance());
+      kdTree.writeTree(outpath+"/"+filename+"_kdTree",WbWriterVtkXmlBinary::getInstance());
+
+      UBLOG( logINFO, "writeFiles - end")
+   }
+
+   delete mesh;
+}
+
+namespace Dirs
+{
+   const int X1[] = { 1, -1,  0,  0,  0,  0,  1, -1,  1, -1,  1, -1,  1, -1,  0,  0,  0,  0,  0 };
+   const int X2[] = { 0,  0,  1, -1,  0,  0,  1, -1, -1,  1,  0,  0,  0,  0,  1, -1,  1, -1,  0 };
+   const int X3[] = { 0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  1, -1, -1,  1,  1, -1, -1,  1,  0 };
+
+   const int START = 0;
+   const int END6  = 5;
+   const int END18 = 17;
+}
+/*==================================================================*/
+bool floodFillCheck(CbUniformMatrix3D<short>& grid, const short& x, const short& y, const short& z)
+{
+   return grid.indicesInRange( x, y, z ) && grid(x,y,z)==Flag::UNDEF;
+}
+int g_counter = 0;
+void recursiveGridFill(CbUniformMatrix3D<short>& grid, const short& xs, const short& ys, const short& zs, const short& type)
+{
+   // Algorithmus zum Füllen eines Polyeders, ausgehend vom Saatpunkt xs,ys,zs
+
+   //Saatknoten einfärben
+   short& val = grid(xs,ys,zs);
+   if( val==Flag::UNDEF )
+   {
+      val = type;
+   }
+   if(   floodFillCheck( grid, xs+1, ys  , zs   ) ) recursiveGridFill( grid, xs+1, ys  , zs  , type );
+   if(   floodFillCheck( grid, xs  , ys+1, zs   ) ) recursiveGridFill( grid, xs  , ys+1, zs  , type );
+   if(   floodFillCheck( grid, xs  , ys  , zs+1 ) ) recursiveGridFill( grid, xs  , ys  , zs+1, type );
+   if(   floodFillCheck( grid, xs-1, ys  , zs   ) ) recursiveGridFill( grid, xs-1, ys  , zs  , type );
+   if(   floodFillCheck( grid, xs  , ys-1, zs   ) ) recursiveGridFill( grid, xs  , ys-1, zs  , type );
+   if(   floodFillCheck( grid, xs  , ys  , zs-1 ) ) recursiveGridFill( grid, xs  , ys  , zs-1, type );
+}
+/*==================================================================*/
+void iterativeGridFill(CbUniformMatrix3D<short>& grid, const short& xs, const short& ys, const short& zs, const short& type)
+{
+   std::stack< UbTupleInt3 > stck;
+   stck.push( UbTupleInt3(xs,ys,zs) );
+
+   int x,y,z;
+
+   while( !stck.empty() )  
+   {
+      x = val<1>( stck.top() );
+      y = val<2>( stck.top() );
+      z = val<3>( stck.top() );
+      stck.pop();
+
+      short& flagType = grid( x, y, z );
+
+      if( flagType == Flag::UNDEF ) 
+      {     
+         flagType = type;
+
+         if ( grid.indicesInRange( x+1, y  , z   ) ) stck.push( UbTupleInt3( x+1, y  , z   ) );
+         if ( grid.indicesInRange( x  , y+1, z   ) ) stck.push( UbTupleInt3( x  , y+1, z   ) );
+         if ( grid.indicesInRange( x  , y  , z+1 ) ) stck.push( UbTupleInt3( x  , y  , z+1 ) );
+         if ( grid.indicesInRange( x-1, y  , z   ) ) stck.push( UbTupleInt3( x-1, y  , z   ) );
+         if ( grid.indicesInRange( x  , y-1, z   ) ) stck.push( UbTupleInt3( x  , y-1, z   ) );
+         if ( grid.indicesInRange( x  , y  , z-1 ) ) stck.push( UbTupleInt3( x  , y  , z-1 ) );
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/examples/PIOTests/CMakeLists.txt b/source/VirtualFluidsCore/Geometry/KdTree/examples/PIOTests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..98a64d3548e709895dc9e1eb8bb0e6eaa378ce7c
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/examples/PIOTests/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(kdtree_pioTest)
+
+#################################################################
+# MACHINE_SPECIFIC CMAKE_CONFIG_FILE
+#################################################################
+INCLUDE("../../../../../CMake/CMakeCABMacros.txt")
+
+#################################################################
+###   PACKAGES                                               ###
+#################################################################
+INCLUDE(${SOURCE_ROOT}/basics/utilities/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/container/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/memory/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/objects/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/basics/writer/CMakePackage.txt)
+
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/KdTree/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/fem/CMakePackage.txt)
+INCLUDE(${SOURCE_ROOT}/numerics/geometry3d/creator/CMakePackage.txt)
+
+#################################################################
+###   OWN DEFINES 						###
+#################################################################
+FILE(GLOB SPECIFIC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h
+                         ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) 
+
+SET(ALL_SOURCES ${ALL_SOURCES} ${SPECIFIC_FILES})
+SOURCE_GROUP(z_main FILES ${SPECIFIC_FILES})
+
+#################################################################
+###  PROJECT ERSTELLEN                                        ###
+#################################################################
+CREATE_CAB_PROJECT(${PROJECT_NAME} BINARY)
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/examples/PIOTests/main.cpp b/source/VirtualFluidsCore/Geometry/KdTree/examples/PIOTests/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..265316c69c61c2c1265a4d4e6000a9f1397880cd
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/examples/PIOTests/main.cpp
@@ -0,0 +1,342 @@
+#include <basics/utilities/UbTiming.h>
+#include <basics/utilities/UbRandom.h>
+
+#include <basics/writer/WbWriterAvsASCII.h>
+#include <basics/writer/WbWriterAvsBinary.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+
+#include <basics/container/CbUniformMatrix4D.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+#include <numerics/geometry3d/creator/GbTriFaceMesh3DCreator.h>
+
+#include <numerics/geometry3d/KdTree/KdTree.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSpatiallMedianSplit.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSAHSplit.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h>
+
+using namespace std;
+
+void KdTreeTest         (std::string meshfile, int maxNofPointsPerDir, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM pio, bool writeFiles = true, std::string outpath = "g:/temp");
+void KdTreeTestWithLines(std::string meshfile, int maxNofPointsPerDir, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM pio, bool writeFiles = true, std::string outpath = "g:/temp");
+
+int main()
+{
+   try
+   {
+      //KdTreeTest("c:/temp/clumps.stl", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/50spheres.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/Sphere5040.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/cooling_2.inp", 400, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/NDR-Konzertsaal.inp", 100, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      
+      //KdTreeTest("c:/temp/Campus-Details-W3.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/Boein707.mesh", 100, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      
+      //KdTreeTest("c:/temp/dolphin.mesh", 400, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/box.ply", 10, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/bodyRight.stl", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/flamingo.mesh", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      
+      //KdTreeTest("c:/temp/torus.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTestWithLines("c:/temp/box.ply", 10, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      
+      KdTreeTest("c:/temp/doppelwandbox.ply", 100, GbTriFaceMesh3D::KDTREE_SPATIALSPLIT, true, "g:/temp");
+      
+      //KdTreeTestWithLines("c:/temp/torus.inp", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT, true, "g:/temp");
+
+      //KdTreeTestWithLines("c:/temp/bodyRight.stl", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+
+      //KdTreeTest("c:/temp/jetta.stl", 200, GbTriFaceMesh3D::KDTREE_SPATIALSPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/jetta.stl", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT, true, "g:/temp");
+      //KdTreeTest("c:/temp/VW_body.ply", 200, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/kugel.stl", 50, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp");
+      //KdTreeTest("c:/temp/ship-2.mesh", 100, GbTriFaceMesh3D::KDTREE_SAHPLIT , true, "g:/temp/schiff2");                                                   
+   }
+   catch(const std::exception& e)
+   {
+      UBLOG2(  logERROR, std::cerr, "Caught exception:");
+      UBLOG2(  logERROR, std::cerr, "Type: " << typeid(e).name() );
+      UBLOG2ML(logERROR, std::cerr, "What: " << e.what() );
+   }
+   catch(...)
+   {
+      UBLOG2(logERROR, std::cerr, "unknown exception occurs in "<< UB_FUNCTION)
+   }
+
+
+
+  
+}
+
+//////////////////////////////////////////////////////////////////////
+void KdTreeTest(std::string meshfile, int maxNofPointsPerDir, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM pio, bool writeFiles, std::string outpath)
+{
+   UbLog::setReportingLevel(logDEBUG5);
+   std::string filename = UbSystem::getFilenameFromString(meshfile);
+
+   GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(meshfile,"mesh",pio);
+   mesh->scale(10000,10000,10000);
+   //dummy test, damit der baum erstellt wird
+   mesh->isPointInGbObject3D(0,0,0);
+
+   UBLOG(logINFO, "############################################################");
+   UBLOG(logINFO, "nodes of TriFaceMesh....... "<<mesh->getNodes()->size()              );
+   UBLOG(logINFO, "triFaces of TriFaceMesh.... "<<mesh->getTriangles()->size()          );
+   UBLOG(logINFO, "triFace copies in KdTree... "<<mesh->getKdTree()->getNumOfTriFaces() );
+   UBLOG(logINFO, "nodes of kdNodes of KdTree. "<<mesh->getKdTree()->getNumOfNodes()   );
+   UBLOG(logINFO, "");
+
+
+   const float percentOverLap = 0.05f; //=5%
+   const float maxLength = (1.0f+percentOverLap)*UbMath::max( mesh->getLengthX1(), mesh->getLengthX2(), mesh->getLengthX3() );
+   const float dx1 = maxLength/(maxNofPointsPerDir-1);
+   const float dx2 = dx1;
+   const float dx3 = dx1;
+
+   const int nx1 = 1 + int( std::ceil(mesh->getLengthX1()*(1.0f+percentOverLap)/dx1)+0.5 );
+   const int nx2 = 1 + int( std::ceil(mesh->getLengthX2()*(1.0f+percentOverLap)/dx2)+0.5 );
+   const int nx3 = 1 + int( std::ceil(mesh->getLengthX3()*(1.0f+percentOverLap)/dx3)+0.5 );
+
+   CbUniformMatrix4D<int> solids(nx1,nx2,nx3,1,0);
+
+   const float orgx1 = -0.5*percentOverLap*mesh->getLengthX1()+mesh->getX1Minimum();
+   const float orgx2 = -0.5*percentOverLap*mesh->getLengthX2()+mesh->getX2Minimum();
+   const float orgx3 = -0.5*percentOverLap*mesh->getLengthX3()+mesh->getX3Minimum();
+
+   const float outX1 = 2*mesh->getX1Maximum();
+   const float outX2 = 0;//2*mesh->getX2Maximum();
+   const float outX3 = 0;//2*mesh->getX3Maximum();
+
+   UBLOG( logINFO, "performing " << nx1*nx2*nx3  <<" point-in-object(PIO)-tests");
+   UbTimer ff;
+   ff.start();
+   for(int x3=0; x3<solids.getNX3(); x3++)
+      for(int x2=0; x2<solids.getNX2(); x2++)
+         for(int x1=0; x1<solids.getNX1(); x1++)
+         {
+            solids(x1,x2,x3,0) = mesh->isPointInGbObject3D(orgx1+x1*dx1, orgx2+x2*dx2, orgx3+x3*dx3);
+         }
+   UBLOG( logINFO, nx1*nx2*nx3 <<" point-in-object(PIO)-tests done in "<<ff.stop()<<"s" );
+   UBLOG(logINFO, "############################################################");
+
+
+   /* ======================================================================================= */
+   if(writeFiles) 
+   {
+      UBLOG( logINFO, "writeFiles - start");
+      string subfiledir = outpath+"/"+filename+"_solid_node_files";
+      UbSystem::makeDirectory( subfiledir );
+
+      std::vector<UbTupleFloat3 > nodes;
+      std::vector<std::string > datanames(solids.getNX4(),"data");
+      datanames[0] = "solid";
+      //datanames[1] = "solid";
+
+      std::vector< std::string > outFilenames;
+
+      std::vector<std::vector<double > > nodedata( datanames.size() );
+      for(int x3=0; x3<solids.getNX3(); x3++)
+         for(int x2=0; x2<solids.getNX2(); x2++)
+            for(int x1=0; x1<solids.getNX1(); x1++)
+            {
+               if( solids(x1  ,x2  ,x3  , 0)  ) 
+               {
+                  nodes.push_back( makeUbTuple(  orgx1+x1*dx1, orgx2+x2*dx2, orgx3+x3*dx3 ) );
+
+                  for(int i=0; i<solids.getNX4(); i++)
+                  {
+                     nodedata[i].push_back( solids(x1  ,x2  ,x3  ,i) );
+                  }
+               }          
+
+               if(    nodes.size() > 2000000  
+                   || ( x1==(solids.getNX1()-1) && x2==(solids.getNX2()-1) && x3==(solids.getNX3()-1) ) ) 
+               {
+                  outFilenames.push_back( WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(subfiledir+"/"+filename+"_solid_nodes_"+"_part"+UbSystem::toString(outFilenames.size()+1),nodes,datanames,nodedata) );
+                  nodes.clear();
+                  nodedata.clear();
+                  nodedata.resize( datanames.size() );
+               }
+            }
+            
+      WbWriterVtkXmlBinary::getInstance()->writeCollection(outpath+"/"+filename+"_solids_nodes",outFilenames,0,false);
+      
+      
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterVtkXmlBinary::getInstance(),true);
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterAvsASCII::getInstance(),true);
+      mesh->getKdTree()->writeTree(outpath+"/"+filename+"_kdTree",WbWriterVtkXmlBinary::getInstance());
+
+      UBLOG( logINFO, "writeFiles - end")
+   }
+}
+
+//////////////////////////////////////////////////////////////////////
+void KdTreeTestWithLines(std::string meshfile, int maxNofPointsPerDir, GbTriFaceMesh3D::KDTREE_SPLITAGORITHM pio, bool writeFiles, std::string outpath)
+{
+   UbLog::setReportingLevel(logDEBUG5);
+   std::string filename = UbSystem::getFilenameFromString(meshfile);
+
+   GbTriFaceMesh3D* mesh = GbTriFaceMesh3DCreator::getInstance()->readMeshFromFile(meshfile,"mesh",pio);
+
+   //dummy test, damit der baum erstellt wird
+   mesh->isPointInGbObject3D(0,0,0);
+
+   UBLOG(logINFO, "############################################################");
+   UBLOG(logINFO, "nodes of TriFaceMesh....... "<<mesh->getNodes()->size()              );
+   UBLOG(logINFO, "triFaces of TriFaceMesh.... "<<mesh->getTriangles()->size()          );
+   UBLOG(logINFO, "triFace copies in KdTree... "<<mesh->getKdTree()->getNumOfTriFaces() );
+   UBLOG(logINFO, "nodes of kdNodes of KdTree. "<<mesh->getKdTree()->getNumOfNodes()   );
+   UBLOG(logINFO, "");
+
+
+   const float percentOverLap = 0.05f; //=5%
+   const float maxLength = (1.0f+percentOverLap)*UbMath::max( mesh->getLengthX1(), mesh->getLengthX2(), mesh->getLengthX3() );
+   const float dx1 = maxLength/(maxNofPointsPerDir-1);
+   const float dx2 = dx1;
+   const float dx3 = dx1;
+
+   const int nx1 = 1 + /*UbMath::integerRounding*/( std::ceil(mesh->getLengthX1()*(1.0f+percentOverLap)/dx1) );
+   const int nx2 = 1 + /*UbMath::integerRounding*/( std::ceil(mesh->getLengthX2()*(1.0f+percentOverLap)/dx2) );
+   const int nx3 = 1 + /*UbMath::integerRounding*/( std::ceil(mesh->getLengthX3()*(1.0f+percentOverLap)/dx3) );
+
+   CbUniformMatrix4D<int> solids(nx1,nx2,nx3,2,0);
+
+   const float orgx1 = -0.5*percentOverLap*mesh->getLengthX1()+mesh->getX1Minimum();
+   const float orgx2 = -0.5*percentOverLap*mesh->getLengthX2()+mesh->getX2Minimum();
+   const float orgx3 = -0.5*percentOverLap*mesh->getLengthX3()+mesh->getX3Minimum();
+
+//    const float outX1 = 2*mesh->getX1Maximum();
+//    const float outX2 = 2*mesh->getX2Maximum();
+//    const float outX3 = 2*mesh->getX3Maximum();
+
+   
+   Kd::Tree<double>* kdTree = mesh->getKdTree();
+   
+   std::vector<GbTriFaceMesh3D::TriFace>& triFaces = *mesh->getTriangles();
+   std::vector<GbTriFaceMesh3D::Vertex>&  vertices = *mesh->getNodes();
+
+   float x1center = float( mesh->getX1Centroid() );
+   float x2center = float( mesh->getX2Centroid() );
+   float x3center = float( mesh->getX3Centroid() );
+
+   UBLOG( logINFO, "performing point-in-object(PIO)-tests");
+   UbTimer ff;
+   ff.start();
+   long counter1=0, counter2 = 0;
+   for(size_t t=0; t<triFaces.size(); t++)   
+   {
+      int x1Min = /*UbMath::integerRounding*/( std::floor( (triFaces[t].getMinX(vertices)-orgx1) / dx1 ) );
+      int x2Min = /*UbMath::integerRounding*/( std::floor( (triFaces[t].getMinY(vertices)-orgx2) / dx2 ) );
+      int x3Min = /*UbMath::integerRounding*/( std::floor( (triFaces[t].getMinZ(vertices)-orgx3) / dx3 ) );
+
+      int x1Max = /*UbMath::integerRounding*/( std::ceil(  (triFaces[t].getMaxX(vertices)-orgx1) / dx1 ) );
+      int x2Max = /*UbMath::integerRounding*/( std::ceil(  (triFaces[t].getMaxY(vertices)-orgx2) / dx2 ) );
+      int x3Max = /*UbMath::integerRounding*/( std::ceil(  (triFaces[t].getMaxZ(vertices)-orgx3) / dx3 ) );
+
+      for(int x3=x3Min; x3<=x3Max; x3++)
+         for(int x2=x2Min; x2<=x2Max; x2++)
+            for(int x1=x1Min; x1<=x1Max; x1++)
+            {
+               counter1++;
+               
+               if( !solids.indicesInRange(x1,x2,x3,0) 
+                  || solids(x1,x2,x3,1) == 1 )  //doppeltes Testeb vermeiden
+               {
+                  continue;
+               }
+
+               counter2++;
+               
+               double x1w = orgx1+x1*dx1;
+               double x2w = orgx2+x2*dx2;
+               double x3w = orgx3+x3*dx3;
+
+               //eigentlicher PIO-Test
+               bool testFailed = true;
+               for(int i=0; i<100; i++)
+               {
+                  UbTupleDouble3 n1(x1w, x2w, x3w);
+                  UbTupleDouble3 n2(  double( x1w < x1center ? mesh->getX1Minimum()-UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX1() : mesh->getX1Maximum()+UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX1() )
+                                    , double( x2w < x2center ? mesh->getX2Minimum()-UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX2() : mesh->getX2Maximum()+UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX2() )
+                                    , double( x3w < x3center ? mesh->getX3Minimum()-UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX3() : mesh->getX3Maximum()+UbRandom::rand(0.5, 1.0, 10)*mesh->getLengthX3() ) );
+
+                  int iSec = kdTree->intersectLine( n1, n2, Kd::CountLineIntersectionHandler<double>() );
+                  
+                  if( iSec != Kd::Intersection::INTERSECT_EDGE ) //KEINE Kante getroffen
+                  {
+                     if(iSec == Kd::Intersection::ON_BOUNDARY )
+                     {
+                        solids(x1,x2,x3,0) = true;
+                     }
+                     else
+                     {
+                        solids(x1,x2,x3,0) = (iSec&1);  //ungerade anzahl an schnitten --> drinnen
+                     }
+                     testFailed = false;
+                     break;
+                  }
+                  else
+                  {
+                     UBLOG(logDEBUG3, "GbTriFaceMesh3D.isPointInGbObject3D.if  - an edge was hit ");
+                  }
+               }
+               if( testFailed ) throw UbException(UB_EXARGS, "ups, nach 100 Strahlen immer noch kein Ergebnis");
+               solids(x1,x2,x3,1) = 1;
+             }
+   }
+   UBLOG( logINFO,counter2 <<" point-in-object(PIO)-tests done in "<<ff.stop()<<"s" );
+   UBLOG( logINFO,counter1-counter2 <<" point-in-object(PIO)-tests uebersprungen" );
+   UBLOG(logINFO, "############################################################");
+
+   /* ======================================================================================= */
+   if(writeFiles) 
+   {
+      UBLOG( logINFO, "writeFiles - start");
+      string subfiledir = outpath+"/"+filename+"_solid_node_files";
+      UbSystem::makeDirectory( subfiledir );
+
+      std::vector<UbTupleFloat3 > nodes;
+      std::vector<std::string > datanames(solids.getNX4(),"data");
+      datanames[0] = "solid";
+      //datanames[1] = "solid";
+
+      std::vector< std::string > outFilenames;
+
+      std::vector<std::vector<double > > nodedata( datanames.size() );
+      for(int x3=0; x3<solids.getNX3(); x3++)
+         for(int x2=0; x2<solids.getNX2(); x2++)
+            for(int x1=0; x1<solids.getNX1(); x1++)
+            {
+               if( solids(x1  ,x2  ,x3  , 0)  ) 
+               {
+                  nodes.push_back( makeUbTuple(  orgx1+x1*dx1, orgx2+x2*dx2, orgx3+x3*dx3 ) );
+
+                  for(int i=0; i<solids.getNX4(); i++)
+                  {
+                     nodedata[i].push_back( solids(x1  ,x2  ,x3  ,i) );
+                  }
+               }          
+
+               if(    nodes.size() > 2000000  
+                   || ( x1==(solids.getNX1()-1) && x2==(solids.getNX2()-1) && x3==(solids.getNX3()-1) ) ) 
+               {
+                  outFilenames.push_back( WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(subfiledir+"/"+filename+"_solid_nodes_"+"_part"+UbSystem::toString(outFilenames.size()+1),nodes,datanames,nodedata) );
+                  nodes.clear();
+                  nodedata.clear();
+                  nodedata.resize( datanames.size() );
+               }
+            }
+   
+      WbWriterVtkXmlBinary::getInstance()->writeCollection(outpath+"/"+filename+"_solids_nodes",outFilenames,0,false);
+      
+      
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterVtkXmlBinary::getInstance());
+      mesh->writeMesh(outpath+"/"+filename+"_mesh",WbWriterAvsASCII::getInstance());
+      mesh->getKdTree()->writeTree(outpath+"/"+filename+"_kdTree",WbWriterVtkXmlBinary::getInstance());
+
+      UBLOG( logINFO, "writeFiles - end")
+   }
+}
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h b/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..eccfde3058e028c2239bcc81de1ebfe0f3306e99
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdCountLineIntersectionHandler.h
@@ -0,0 +1,56 @@
+#ifndef KDCOUNTLINEINTERSECTIONHANDLER_H
+#define KDCOUNTLINEINTERSECTIONHANDLER_H
+
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbKeys.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/KdTree/KdNode.h>
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdLineIntersectionHandler.h>
+
+#include <set>
+
+namespace Kd
+{
+   template< typename T >
+   class CountLineIntersectionHandler : public LineIntersectionHandler<T> 
+   {
+   public:
+      bool intersectLine(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2, Node<T>& parent, Node<T>*& child1, Node<T>*& child2) const
+      {
+         if( parent.intersectLineBoundingBox(n1, n2)  == Intersection::INTERSECTION)
+         {
+            if( parent.isLeaf() ) 
+            {
+               std::vector<GbTriFaceMesh3D::TriFace>& triFaces = *parent.getTriFaces();
+               std::vector<GbTriFaceMesh3D::Vertex>& nodes = parent.getNodes();
+
+         for( std::size_t i=0; i<triFaces.size(); i++ )
+         {
+            GbTriFaceMesh3D::TriFace& triFace = triFaces[i];
+
+                  if( Kd::intersectLine(n1, n2, triFace, nodes) ) return true;
+               }
+               return false;
+               }
+            else
+               {
+               if( child1 )
+               {
+                  if (child1->intersectLine(n1, n2, *this)) return true;
+               }
+               if( child2 ) 
+               {
+                  if (child2->intersectLine(n1, n2, *this)) return true;
+               }
+            }
+         }
+         return false;
+      }
+      /* ======================================================================================= */
+   };
+}
+
+#endif //KDCOUNTLINEINTERSECTIONHANDLER_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h b/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..b95fc676ad04008b43b0ddf6db785887f941e7e0
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdCountRayIntersectionHandler.h
@@ -0,0 +1,164 @@
+#ifndef KDCOUNTRAYINTERSECTIONHANDLER_H
+#define KDCOUNTRAYINTERSECTIONHANDLER_H
+
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbKeys.h>
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/KdTree/KdNode.h>
+//#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/intersectionhandler/KdRayIntersectionHandler.h>
+
+#include <set>
+
+namespace Kd
+{
+   template< typename T >
+   class CountRayIntersectionHandler : public RayIntersectionHandler<T> 
+   {
+   public:
+      int intersectRay(const Ray<T>& ray, Node<T>& parent, Node<T>*& child1, Node<T>*& child2, std::set< UbKeys::Key3<int> >& mailbox) const
+      {
+         if( parent.intersectRayBoundingBox(ray)  == Intersection::INTERSECTION)
+         {
+            if( parent.isLeaf() ) 
+            {
+               return this->checkIntersectionWithTriFaces(ray, *parent.getTriFaces(), parent.getNodes(), mailbox);
+            } 
+            else
+            {
+               int sum = 0;
+               if( child1 )
+               {
+                  int erg = child1->intersectRay(ray, *this, mailbox);
+                  if(erg < 0)
+                  {
+                     return erg;
+                  }
+                  sum += erg;
+               }
+               if( child2 ) 
+               {
+                  int erg = child2->intersectRay(ray, *this, mailbox);
+                  if(erg < 0)
+                  {
+                     return erg;
+                  }
+                  sum += erg;
+               }
+               return sum;
+            }
+         } 
+         else 
+         {
+            return 0;
+         }
+      }
+      /* ======================================================================================= */
+
+   private:
+      int checkIntersectionWithTriFaces(const Ray<T>& ray, std::vector<GbTriFaceMesh3D::TriFace>& triFaces, std::vector<GbTriFaceMesh3D::Vertex>& nodes, std::set< UbKeys::Key3<int> >& mailbox) const
+      {
+         T e1x,e1y,e1z,e2x,e2y,e2z,px,py,pz,a,f,sx,sy,sz,u,qx,qy,qz,v,factor;
+
+         int counter = 0, iSec = 0;
+
+         for( std::size_t i=0; i<triFaces.size(); i++ )
+         {
+            GbTriFaceMesh3D::TriFace& triFace = triFaces[i];
+
+            if( mailbox.find( UbKeys::Key3<int>(triFace.getIndexVertex1(), triFace.getIndexVertex2(), triFace.getIndexVertex3() ) )==mailbox.end() ) 
+            {
+               mailbox.insert( UbKeys::Key3<int>(triFace.getIndexVertex1(), triFace.getIndexVertex2(), triFace.getIndexVertex3() ) ); //schon hier rein, ansonsten muss man es unten bei JEDEm continue und am ende des ifs machen
+
+               GbTriFaceMesh3D::Vertex& v1 = triFace.getNode(0, nodes);
+               GbTriFaceMesh3D::Vertex& v2 = triFace.getNode(1, nodes);
+               GbTriFaceMesh3D::Vertex& v3 = triFace.getNode(2, nodes);
+
+               //////////////////////////////////////////////////////////////////////////
+               //Raytracing - start(  Anm.: prüft NUR in Strahlrichtung
+               // Grundidee: Schnittpunkt in Baryzentrischen Koordinaten besimmten
+               // t(u,v,w) = w*v0 + u*v1 + v*v2 
+               // mit w = 1.0-u-v, da fuer alle Punkte (u,v,w) im Dreick gilt u+v+w = 1
+               // wenn u, v oder w == 0 -> Punkt liegt auf Kante
+               // wenn u, v oder w == 1 -> Punkt liegt auf Eckpunkt (-> die anderen Werte muessen 0 )
+               
+               //e1 = v1 - v0
+               e1x = v2.x-v1.x;
+               e1y = v2.y-v1.y;
+               e1z = v2.z-v1.z;
+
+               //e2 = v2 - v0
+               e2x = v3.x-v1.x;
+               e2y = v3.y-v1.y;
+               e2z = v3.z-v1.z;
+
+               //p = d x e2
+               px = ray.directionY*e2z - ray.directionZ*e2y;
+               py = ray.directionZ*e2x - ray.directionX*e2z;
+               pz = ray.directionX*e2y - ray.directionY*e2x;
+
+               //a = e1 dot p
+               a = e1x*px + e1y*py + e1z*pz;
+               //if( fabs(a)<1.E-10 ) continue;
+               if( fabs(a) < UbMath::Epsilon<T>::val() ) continue;
+               f = T(1.0/a);
+
+               //s = o - v0
+               sx = ray.originX - v1.x;
+               sy = ray.originY - v1.y;
+               sz = ray.originZ - v1.z;
+
+               //u = f * ( s dot p)
+               u = f * ( sx*px + sy*py + sz*pz );
+               
+               //u ist nur gueltig in [0;1] 
+               if( ( UbMath::less(   u, T(0.0) ) ) || ( UbMath::greater(u, T(1.0) ) ) ) 
+               {
+                  continue;
+               }
+
+               //q = s x e1
+               qx = sy*e1z - sz*e1y;
+               qy = sz*e1x - sx*e1z;
+               qz = sx*e1y - sy*e1x;
+
+               //v = f*(e2 dot q)
+               v = f * (ray.directionX*qx + ray.directionY*qy + ray.directionZ*qz);
+               
+               //v ist nur gueltig in [0;1] da aber v bereits gueltig ist -> u+v darf nicht > 1.0 sein ;-)
+               if(   ( UbMath::less(v, T(0.0) ) ) || ( UbMath::greater(u+v, T(1.0) ) ) ) 
+               {
+                  continue;
+               }
+
+               //t = f * (e2 dot q)
+               factor = f * (e2x*qx + e2y*qy + e2z*qz);
+               //Raytracing - end
+               //////////////////////////////////////////////////////////////////////////
+
+               if( UbMath::zero( factor ) ) 
+               {
+                  return Intersection::ON_BOUNDARY; //ray.Org liegt direkt auf einem dreieck --> boundary
+               }
+               if( factor < 0.0 )
+               {
+                  continue;  //Schnittpunkt liegt in entgegengesetzter Strahlrichtung
+               }
+
+               //edge tests
+               //wenn u, v oder w ==0 -> Punkt liegt auf Kante bzw. Eckpunkt
+               if( UbMath::zero(u)          )  return Intersection::INTERSECT_EDGE;
+               if( UbMath::zero(v)          )  return Intersection::INTERSECT_EDGE;
+               if( UbMath::zero(T(1.0)-u-v) )  return Intersection::INTERSECT_EDGE;
+
+               counter++;
+            }
+         }
+         return counter;
+      }
+   };
+}
+
+#endif //KDCOUNTRAYLINEINTERSECTIONHANDLER_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdLineIntersectionHandler.h b/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdLineIntersectionHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..65f94876a94cffc6f6dd9615c4f77d7c73be9a02
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdLineIntersectionHandler.h
@@ -0,0 +1,30 @@
+#ifndef KDLINEINTERSECTIONHANDLER_H
+#define KDLINEINTERSECTIONHANDLER_H
+
+#include <basics/utilities/UbTuple.h>
+//#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <set>
+
+// #ifdef CAB_RCF
+// #  include <3rdParty/rcf/RcfSerializationIncludes.h>
+// #end
+namespace Kd
+{
+   template< typename T>
+   class Node;
+
+   template< typename T>
+   class LineIntersectionHandler 
+   {
+   public:
+      virtual bool intersectLine(const UbTuple<T,T,T>& n1, const UbTuple<T,T,T>& n2, Node<T>& parent, Node<T>*& child1, Node<T>*& child2) const = 0;
+      virtual ~LineIntersectionHandler() {}
+   };
+}
+
+// #if defined(RCF_USE_SF_SERIALIZATION) && !defined(SWIG)
+//    SF_NO_CTOR(Kd::LineIntersectionHandler<float>);
+//    SF_NO_CTOR(Kd::LineIntersectionHandler<double>);
+// #endif //RCF_USE_SF_SERIALIZATI
+#endif //KDLINEINTERSECTIONHANDLER_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdRayIntersectionHandler.h b/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdRayIntersectionHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..7578d9046a68fc2a2b310204379df37f2c758c84
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/intersectionhandler/KdRayIntersectionHandler.h
@@ -0,0 +1,20 @@
+#ifndef KDRAYINTERSECTIONHANDLER_H
+#define KDRAYINTERSECTIONHANDLER_H
+
+#include <basics/utilities/UbTuple.h>
+#include <numerics/geometry3d/KdTree/KdRay.h>
+
+#include <set>
+
+namespace Kd
+{
+   template< typename T>
+   class RayIntersectionHandler 
+   {
+   public:
+      virtual int intersectRay(const Ray<T>& ray, Node<T>& parent, Node<T>*& child1, Node<T>*& child2, std::set< UbKeys::Key3<int> >& mailbox) const = 0;
+      virtual ~RayIntersectionHandler() {}
+   };
+}
+
+#endif //KDRAYINTERSECTIONHANDLER_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSAHSplit.cpp b/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSAHSplit.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..da4ff27465d87a8a6fff032d8f84e427a278255d
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSAHSplit.cpp
@@ -0,0 +1,10 @@
+//#include <numerics/geometry3d/KdTree/SAHSplit.h>
+
+
+// namespace Kd
+// {
+//    const double SAHSplit::Ct = 3.0; //traversal cost
+//    const double SAHSplit::Ci = 4.0; //ray-patch-intersection-cost
+// }
+
+
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSAHSplit.h b/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSAHSplit.h
new file mode 100644
index 0000000000000000000000000000000000000000..52e73ea714969df05098d7fed82f826357beeca5
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSAHSplit.h
@@ -0,0 +1,287 @@
+#ifndef KDSAHSPLIT_H
+#define KDSAHSPLIT_H
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbInfinity.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/KdTree/KdNode.h>
+#include <numerics/geometry3d/KdTree/KdUtilities.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidateManager.h>
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+
+#include <vector>
+#include <cmath>
+
+namespace Kd
+{
+   template< typename T >
+   class SAHSplit : public SplitAlgorithm<T> 
+   {
+   public:
+      /* ======================================================================================= */
+      SplitCandidate<T> findBestSplitCandidate(const int& level, const int& maxLevel, Node<T>& node ) const
+      {
+         if( !node.getTriFaces() )  throw UbException(UB_EXARGS, "triFace NULL pointer");
+
+         if(   node.getTriFaces()->size() <= 1 //max triangles in node
+            || level >= maxLevel     )
+         {
+            return SplitCandidate<T>();
+         }
+
+         SplitCandidate<T> bestSplitCandidate;
+         T minCN = Ub::inf;
+
+         for(int splitAxis = 0; splitAxis < 3; splitAxis++) 
+         {
+            SplitCandidateManager<T> sc;
+            findPossibleSplitCandidates(splitAxis, node, sc);
+
+            // incremental sweep to find best split position
+            for( std::size_t i = 0; i < sc.size(); i++)
+            {
+               if (i == 0) 
+               {
+                  sc[i].nl = sc.objects_starting_outside_left + sc.objects_fully_outside_node;
+                  sc[i].nr = node.getTriFaces()->size() - sc[0].np - sc[0].ending;
+               } 
+               else 
+               {
+                  sc[i].nl = sc[i - 1].nl + sc[i - 1].starting + sc[i - 1].np;
+                  sc[i].nr = sc[i - 1].nr - sc[i    ].ending   - sc[i    ].np;
+               }
+
+               this->calcSAH(sc[i], node);
+
+               if (sc[i].Cn < minCN)
+               {
+                  minCN              = sc[i].Cn;
+                  bestSplitCandidate = sc[i];
+               }
+            }
+         }
+
+         // automatic termination criterion (SAH)
+         if ( bestSplitCandidate.isValid && bestSplitCandidate.Cn >= node.getTriFaces()->size() * Ci) 
+         {
+            return SplitCandidate<T>();
+         }
+
+         return bestSplitCandidate;
+      }
+      /* ======================================================================================= */
+      void distributeTriFaces(const SplitCandidate<T>& candidate, std::vector<GbTriFaceMesh3D::TriFace>& triFacesForChild1, std::vector<GbTriFaceMesh3D::TriFace>& triFacesForChild2, Node<T>& node) const
+      {  
+         if( !node.getTriFaces() )  throw UbException(UB_EXARGS, "null pointer at triface list");
+
+         std::vector<GbTriFaceMesh3D::TriFace>& srcTriFaces = *node.getTriFaces();
+         std::vector<GbTriFaceMesh3D::Vertex>&  srcNodes    = node.getNodes();
+         std::vector<T> projection;
+
+         for(std::size_t i=0; i<srcTriFaces.size(); i++) 
+         {
+            GbTriFaceMesh3D::TriFace& triFace = srcTriFaces[i];
+            Kd::project2Axis(triFace, srcNodes, candidate.axis, projection);
+
+            T& min = projection[0];
+            T& max = projection[2];
+            // --------------------------------------------------- //
+            // case 1 : object inside plane
+            if( UbMath::equal(min, max) )
+            {
+               if( UbMath::equal(min, candidate.position) ) 
+               {
+                  if(candidate.np_left)
+                  {
+                     triFacesForChild1.push_back(triFace);
+                  } 
+                  else if(candidate.np_right) 
+                  {
+                     triFacesForChild2.push_back(triFace);
+                  }
+               } 
+               else if( UbMath::less(min, candidate.position) )
+               {
+                  triFacesForChild1.push_back(triFace);
+               } 
+               else //if( UbMath::greater(min, candidate.position) 
+               {
+                  triFacesForChild2.push_back(triFace);
+               }
+            } //
+            // --------------------------------------------------- //
+            // case 2 : object on left side of plane
+            else if( UbMath::lessEqual(max,candidate.position) )
+            {
+               triFacesForChild1.push_back(triFace);
+            } // --------------------------------------------------- //
+            // case 3 : object on right side of plane
+            else if ( UbMath::greaterEqual( min, candidate.position) ) 
+            {
+               triFacesForChild2.push_back(triFace);
+            }//
+            // --------------------------------------------------- //
+            // case 4 : object in both nodes
+            else 
+            {
+               triFacesForChild1.push_back(triFace);
+               triFacesForChild2.push_back(triFace);
+            }//
+            // --------------------------------------------------- //
+         }
+
+         node.deleteTriFaces();
+      }
+
+
+   private:
+      /* ======================================================================================= */
+      // cost function
+      inline T calcCosts(const int& nl, const int& nr, const T& SA_VL, const T& SA_VR, const T& SA_V) const
+      {
+         return Ct + Ci * (nl * SA_VL / SA_V + nr * SA_VR / SA_V);
+      }
+      /* ======================================================================================= */
+      void findPossibleSplitCandidates(const int& splitAxis, Node<T>& node, SplitCandidateManager<T>& splitCandidateManager) const
+      {
+         T p1_node = (splitAxis == Axis::X ? node.x[0] : splitAxis == Axis::Y ? node.y[0] : node.z[0]);
+         T p2_node = (splitAxis == Axis::X ? node.x[1] : splitAxis == Axis::Y ? node.y[1] : node.z[1]);
+
+         if( !node.getTriFaces() )  throw UbException(UB_EXARGS, "null pointer");
+
+         std::vector<GbTriFaceMesh3D::TriFace>& srcTriFaces = *node.getTriFaces();
+         std::vector<GbTriFaceMesh3D::Vertex >& srcNodes    = node.getNodes();
+         std::vector<T> projection;
+
+         for(std::size_t i=0; i<srcTriFaces.size(); i++) 
+         {
+            GbTriFaceMesh3D::TriFace& triFace = srcTriFaces[i];
+
+            // project object to axis
+            Kd::project2Axis(triFace,srcNodes,splitAxis, projection);
+            // left point
+            T& p1 = projection[0];
+            // right point
+            T& p2 = projection[2];
+
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+            // case 1 : object is fully inside the current node
+            if(   UbMath::greaterEqual(p1, p1_node)   
+               && UbMath::lessEqual(p2, p2_node) )   
+            {
+               if( UbMath::equal(p1, p2) ) 
+               {
+                  // object is inside the plane
+                  splitCandidateManager.add(p1, splitAxis, 0, 0, 1);
+               } 
+               else 
+               {
+                  splitCandidateManager.add(p1, splitAxis, 1, 0, 0);
+                  splitCandidateManager.add(p2, splitAxis, 0, 1, 0);
+               }
+            } //
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+            // case 2 : just the right point (p2) is inside the current node
+            else if(    UbMath::less(p1, p1_node) 
+                     && UbMath::lessEqual(p2,p2_node)
+                     && UbMath::greaterEqual(p2, p1_node)   )
+            {
+               splitCandidateManager.add(p2, splitAxis, 0, 1, 0);
+               splitCandidateManager.objects_starting_outside_left++;
+            } //
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+            // case 3 : just the left point (p1) is inside the current node
+            else if(    UbMath::greaterEqual(p1, p1_node) 
+                     && UbMath::greater(p2, p2_node) 
+                     && UbMath::lessEqual(p1, p2_node)   ) 
+            {
+               splitCandidateManager.add(p1, splitAxis, 1, 0, 0);
+            } //
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+            // case 4 : left and right point are outside the current node
+            else if(   UbMath::less(p1, p1_node)
+                    && UbMath::greater(p2, p2_node) )
+            {
+               splitCandidateManager.objects_fully_outside_node++;
+            } //
+            // --------------------------------------------------- //
+            // --------------------------------------------------- //
+         }
+
+         splitCandidateManager.createSortedArray();
+      }
+
+
+      /* ======================================================================================= */
+      // calculates the costs for a given splitCandidate based on the Surface Area Heuristic (SAH)
+      void calcSAH(SplitCandidate<T>& candidate, Node<T>& node) const 
+      {
+         T p1_node = (candidate.axis == Axis::X ? node.x[0] : candidate.axis == Axis::Y ? node.y[0] : node.z[0]);
+
+         // edges of (root) voxel
+         T dx = std::fabs(node.x[1] - node.x[0]);
+         T dy = std::fabs(node.y[1] - node.y[0]);
+         T dz = std::fabs(node.z[1] - node.z[0]);
+
+         // surface area (root) voxel
+         T SA_V = T((2.0 * dx * dy) + (2.0 * dx * dz) + (2.0 * dy * dz));
+
+         T delta = (candidate.axis == Axis::X ? dx : candidate.axis == Axis::Y ? dy : dz);
+         T deltaL = std::fabs(candidate.position - p1_node);
+         T deltaR = std::fabs(delta - deltaL);
+
+         // edges of sub voxel left
+         T dx_l = (candidate.axis == Axis::X ? deltaL : dx), dy_l = (candidate.axis == Axis::Y ? deltaL : dy), dz_l = (candidate.axis == Axis::Z ? deltaL : dz);
+
+         // surface area sub voxel left
+         T SA_VL = T( (2.0 * dx_l * dy_l) + (2.0 * dx_l * dz_l) + (2.0 * dy_l * dz_l) );
+
+         // edges of sub voxel right
+         T dx_r = (candidate.axis == Axis::X ? deltaR : dx), dy_r = (candidate.axis == Axis::Y ? deltaR : dy), dz_r = (candidate.axis == Axis::Z ? deltaR : dz);
+
+         // surface area sub voxel right
+         T SA_VR = T( (2.0 * dx_r * dy_r) + (2.0 * dx_r * dz_r) + (2.0 * dy_r * dz_r) );
+
+         if (candidate.np == 0) 
+         {
+            candidate.Cn = calcCosts(candidate.nl, candidate.nr, SA_VL, SA_VR, SA_V);
+            return;
+         }
+
+         // once putting np with nl, and once with nr - and select the one with lowest cost
+         // see: Wald, Havran: "On building fast kd-Trees for Ray Tracing, and doing that in O(N log N)", 2006
+         T CP_L = calcCosts(candidate.nl + candidate.np, candidate.nr               , SA_VL, SA_VR, SA_V);
+         T CP_R = calcCosts(candidate.nl               , candidate.nr + candidate.np, SA_VL, SA_VR, SA_V);
+         
+         if(CP_L < CP_R) 
+         {
+            candidate.Cn       = CP_L;
+            candidate.np_right = true;
+         } 
+         else 
+         {
+            candidate.Cn      = CP_R;
+            candidate.np_left = true;
+         }
+      }
+      /* ======================================================================================= */
+
+   protected:
+      static const T Ct;// = 3.0; traversal cost
+      static const T Ci;// = 4.0; ray-patch-intersection-cost
+   };
+
+   
+   template< typename T>
+   const T SAHSplit<T>::Ct = 3.0; //traversal cost
+   template< typename T>
+   const T SAHSplit<T>::Ci = 4.0; //ray-patch-intersection-cost
+}
+
+#endif //KDSAHSPLIT_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSpatiallMedianSplit.h b/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSpatiallMedianSplit.h
new file mode 100644
index 0000000000000000000000000000000000000000..b87c18b4817ab2c017cd76b66c220f5aa41ce90f
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSpatiallMedianSplit.h
@@ -0,0 +1,90 @@
+#ifndef SPATIALLMEDIANSPLIT_H
+#define SPATIALLMEDIANSPLIT_H
+
+#include <basics/utilities/UbMath.h>
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+#include <numerics/geometry3d/KdTree/splitalgorithms/KdSplitAlgorithm.h>
+
+namespace Kd
+{
+   template< typename T >
+   class SpatialMedianSplit : public SplitAlgorithm<T> 
+   {
+      /* ======================================================================================= */
+      SplitCandidate<T> findBestSplitCandidate(const int& level, const int& maxLevel, Node<T>& node )  const
+      {
+         if(   node.getTriFaces()->size() <= 24 //max triangles in node 
+            || level >= maxLevel        )
+         {
+            return SplitCandidate<T>();
+         }
+
+         T dx = std::fabs(node.x[1] - node.x[0]);
+         T dy = std::fabs(node.y[1] - node.y[0]);
+         T dz = std::fabs(node.z[1] - node.z[0]);
+
+         if     ( UbMath::equal(dx, UbMath::max(dx, dy, dz) ) ) return SplitCandidate<T>(Axis::X, node.x[0] + 0.5 * dx, 0, 0, 0);
+         else if( UbMath::equal(dy, UbMath::max(dy, dz    ) ) ) return SplitCandidate<T>(Axis::Y, node.y[0] + 0.5 * dy, 0, 0, 0);
+
+         return SplitCandidate<T>(Axis::Z, node.z[0] + 0.5 * dz, 0, 0, 0);
+
+      }
+      /* ======================================================================================= */
+      void distributeTriFaces(const SplitCandidate<T>& candidate, std::vector<GbTriFaceMesh3D::TriFace>& primitives_child1, std::vector<GbTriFaceMesh3D::TriFace>& primitives_child2, Node<T>& node) const
+      {
+         if( !node.getTriFaces() )  throw UbException(UB_EXARGS, "null pointer");
+
+         std::vector<GbTriFaceMesh3D::TriFace>& srcTriFaces = *node.getTriFaces();
+         std::vector<GbTriFaceMesh3D::Vertex>&  srcNodes    =  node.getNodes();
+         std::vector<T> projection;
+
+         for(std::size_t i=0; i<srcTriFaces.size(); i++) 
+         {
+            GbTriFaceMesh3D::TriFace& triFace = srcTriFaces[i];
+            Kd::project2Axis(triFace, srcNodes, candidate.axis, projection);
+
+            T& min = projection[0];
+            T& max = projection[2];
+         
+            // case 1 : object inside plane
+            if( UbMath::equal(min,max) )
+            {
+               if( UbMath::equal(min,candidate.position) ) 
+               {
+                  primitives_child1.push_back(triFace);
+                  primitives_child2.push_back(triFace);
+               }
+               else if( UbMath::less(min, candidate.position) )
+               {
+                  primitives_child1.push_back(triFace);
+               } 
+               else if( UbMath::greater(min, candidate.position) )
+               {
+                  primitives_child2.push_back(triFace);
+               }
+            } 
+            // case 2 : object on left side of plane
+            else if( UbMath::lessEqual(max, candidate.position) )
+            {
+               primitives_child1.push_back(triFace);
+            } 
+            // case 3 : object on right side of plane
+            else if( UbMath::greaterEqual(min, candidate.position) )
+            {
+               primitives_child2.push_back(triFace);
+            }
+            // case 4 : object in both nodes
+            else 
+            {
+               primitives_child1.push_back(triFace);
+               primitives_child2.push_back(triFace);
+            }
+         }
+
+         node.deleteTriFaces();
+      }
+   };
+}
+
+#endif //SPATIALLMEDIANSPLIT_H
diff --git a/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSplitAlgorithm.h b/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSplitAlgorithm.h
new file mode 100644
index 0000000000000000000000000000000000000000..16244300593b2de61738ade6f09cf8525504551f
--- /dev/null
+++ b/source/VirtualFluidsCore/Geometry/KdTree/splitalgorithms/KdSplitAlgorithm.h
@@ -0,0 +1,26 @@
+#ifndef KDSPLITALGORITHM_H
+#define KDSPLITALGORITHM_H
+
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+//#include <numerics/geometry3d/KdTree/Node.h>
+#include <numerics/geometry3d/KdTree/KdSplitCandidate.h>
+
+#include <vector>
+
+namespace Kd
+{
+   template< typename T >
+   class Node;
+
+   template< typename T >
+   class SplitAlgorithm 
+   {
+   public:
+      virtual SplitCandidate<T> findBestSplitCandidate(const int& level, const int& maxLevel, Node<T>& node ) const = 0;
+      virtual void distributeTriFaces(const SplitCandidate<T>& candidate, std::vector<GbTriFaceMesh3D::TriFace>& triFacesForChild1, std::vector<GbTriFaceMesh3D::TriFace>& triFacesForChild2, Node<T>& node) const=0;
+      virtual ~SplitAlgorithm() {}
+   };
+}
+
+
+#endif  //KDSPLITALGORITHM_H
diff --git a/source/VirtualFluidsCore/Grid/Block3D.cpp b/source/VirtualFluidsCore/Grid/Block3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9cabbb818b5f007dd253753d4b627129d0893562
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Block3D.cpp
@@ -0,0 +1,493 @@
+#include "Block3D.h"
+#include "Grid3DSystem.h"
+#include <boost/foreach.hpp>
+
+int Block3D::counter = 0;
+//////////////////////////////////////////////////////////////////////////
+Block3D::Block3D() : x1(0),x2(0),x3(0)
+                     ,active(true)
+                     ,globalID(-1)
+                     ,rank(-1),part(-1)
+                     ,interpolationFlagCF(0)
+                     ,interpolationFlagFC(0)
+                     ,level(-1)
+                     ,bundle(-1)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+Block3D::Block3D(int x1, int x2, int x3, int level)
+               : x1(x1), x2(x2), x3(x3)
+               ,active(true)
+               ,globalID(-1)
+               ,rank(0),part(0)
+               ,interpolationFlagCF(0)
+               ,interpolationFlagFC(0)
+               ,level(level)
+               ,bundle(0)
+{
+   globalID = counter++;
+}
+//////////////////////////////////////////////////////////////////////////
+Block3D::~Block3D()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::operator==(const Block3D& src) const
+{
+   return (x1==src.x1 && x2==src.x2 && x3==src.x3); 
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::operator!=(const Block3D& src) const
+{
+   return !(*this==src);
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getX1() const 
+{ 
+   return this->x1; 
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getX2() const 
+{ 
+   return this->x2; 
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getX3() const 
+{ 
+   return this->x3; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setActive(bool active) 
+{ 
+   this->active = active; 
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::isActive()    const           
+{ 
+   return this->active;   
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::isNotActive() const           
+{ 
+   return(!this->active); 
+}
+//////////////////////////////////////////////////////////////////////////
+void  Block3D::setKernel(LBMKernel3DPtr kernel) 
+{  
+   this->kernel = kernel; 
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr Block3D::getKernel() const              
+{  
+   return this->kernel; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::deleteKernel()             
+{  
+   this->kernel = LBMKernel3DPtr(); 
+}
+//////////////////////////////////////////////////////////////////////////
+int  Block3D::getBundle() const          
+{ 
+   return bundle;       
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setBundle(int bundle) 
+{ 
+   this->bundle = bundle; 
+} 
+//////////////////////////////////////////////////////////////////////////
+void  Block3D::setRank(int rank) 
+{  
+   this->rank = rank; 
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getRank() const            
+{  
+   return this->rank; 
+}
+//////////////////////////////////////////////////////////////////////////
+void  Block3D::setLocalRank(int rank) 
+{  
+   this->lrank = rank; 
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getLocalRank() const            
+{  
+   return this->lrank; 
+}
+//////////////////////////////////////////////////////////////////////////
+int  Block3D::getGlobalID() const        
+{ 
+   return this->globalID; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setGlobalID(int id) 
+{ 
+   this->globalID = id; 
+}
+//////////////////////////////////////////////////////////////////////////
+int  Block3D::getLocalID() const        
+{ 
+   return this->localID; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setLocalID(int id) 
+{ 
+   this->localID = id; 
+}
+//////////////////////////////////////////////////////////////////////////
+int  Block3D::getPart() const        
+{ 
+   return this->part; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setPart(int part) 
+{ 
+   this->part = part; 
+}
+//////////////////////////////////////////////////////////////////////////
+int  Block3D::getLevel() const        
+{ 
+   return this->level; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setLevel(int level) 
+{ 
+   this->level = level; 
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DConnectorPtr Block3D::getConnector(int dir) const
+{ 
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+      if( c ) 
+      {
+            if(c->getSendDir() == dir) return c;
+      }
+   }
+  return Block3DConnectorPtr();     
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setConnector(Block3DConnectorPtr connector)
+{
+   connectors.push_back(connector);
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::deleteConnectors()
+{
+   connectors.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::hasConnectors()
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+      if( c ) return true;
+   
+   return false;
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackSameLevelConnectors(  std::vector<Block3DConnectorPtr>& localSameLevelConnectors
+                                            , std::vector<Block3DConnectorPtr>& remoteSameLevelConnectors )
+{
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isLocalConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) 
+            localSameLevelConnectors.push_back(this->connectors[i]);
+         else                                
+            remoteSameLevelConnectors.push_back(this->connectors[i]);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackLocalSameLevelConnectors( std::vector<Block3DConnectorPtr>& localSameLevelConnectors )
+{
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isLocalConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) 
+            localSameLevelConnectors.push_back(this->connectors[i]);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackLocalSameLevelConnectors( std::vector<Block3DConnectorPtr>& localSameLevelConnectors, const int& dir)
+{
+   Block3DConnectorPtr connector = this->connectors[dir];
+   if( this->connectors[dir] )
+   {
+      if( connector->isLocalConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) 
+         localSameLevelConnectors.push_back(this->connectors[dir]);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackRemoteSameLevelConnectors( std::vector<Block3DConnectorPtr>& remoteSameLevelConnectors )
+{
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isRemoteConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) 
+            remoteSameLevelConnectors.push_back(this->connectors[i]);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackRemoteSameLevelConnectors( std::vector<Block3DConnectorPtr>& remoteSameLevelConnectors, const int& dir )
+{
+   Block3DConnectorPtr connector = this->connectors[dir];
+   if( this->connectors[dir] )
+   {
+      if( connector->isRemoteConnector() && !connector->isInterpolationConnectorCF() && !connector->isInterpolationConnectorFC() ) 
+         remoteSameLevelConnectors.push_back(this->connectors[dir]);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackLocalInterpolationConnectorsCF( std::vector<Block3DConnectorPtr>& localInterpolationConnectors )
+{
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isLocalConnector() && connector->isInterpolationConnectorCF() )
+            localInterpolationConnectors.push_back(this->connectors[i]);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackRemoteInterpolationConnectorsCF( std::vector<Block3DConnectorPtr>& remoteInterpolationConnectors )
+{
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isRemoteConnector() && connector->isInterpolationConnectorCF() )
+            remoteInterpolationConnectors.push_back(this->connectors[i]);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackLocalInterpolationConnectorsFC( std::vector<Block3DConnectorPtr>& localInterpolationConnectors )
+{
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isLocalConnector() && connector->isInterpolationConnectorFC() )
+            localInterpolationConnectors.push_back(this->connectors[i]);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::pushBackRemoteInterpolationConnectorsFC( std::vector<Block3DConnectorPtr>& remoteInterpolationConnectors )
+{
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isRemoteConnector() && connector->isInterpolationConnectorFC() )
+            remoteInterpolationConnectors.push_back(this->connectors[i]);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getNumberOfLocalConnectors()
+{
+   int count = 0;
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isLocalConnector() ) count++;
+      }
+   }
+   return count;
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getNumberOfRemoteConnectors()
+{
+   int count = 0;
+   for(int i=0; i<(int)connectors.size(); i++)
+   {
+      Block3DConnectorPtr connector = this->connectors[i];
+      if( this->connectors[i] )
+      {
+         if( connector->isRemoteConnector() ) count++;
+      }
+   }
+   return count;
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getNumberOfLocalConnectorsForSurfaces()
+{
+   int count = 0;
+   
+   if(connectors.size() < 6)
+      return count;
+
+   for(int dir=0; dir<=5; dir++) //Hard coding. It works if you have 0...5 for E, N ... B 
+   {
+      Block3DConnectorPtr connector = this->connectors[dir];
+      if( this->connectors[dir] )
+      {
+         if( connector->isLocalConnector() ) count++;
+      }
+   }
+   return count;
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getNumberOfRemoteConnectorsForSurfaces()
+{
+   int count = 0;
+   for(int dir=0; dir<=5; dir++) //Hard coding. It works if you have 0...5 for E, N ... B 
+   {
+      Block3DConnectorPtr connector = this->connectors[dir];
+      if( this->connectors[dir] )
+      {
+         if( connector->isRemoteConnector() ) count++;
+      }
+   }
+   return count;
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setInterpolationFlagCF(int dir)
+{
+   UbSystem::setBit(interpolationFlagCF, 1<<dir);
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getInterpolationFlagCF()
+{
+   return interpolationFlagCF;
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::hasInterpolationFlagCF(int dir)
+{
+   return UbSystem::bitCheck( interpolationFlagCF, 1<<dir );
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setInterpolationFlagFC(int dir)
+{
+   UbSystem::setBit(interpolationFlagFC, 1<<dir);
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getInterpolationFlagFC()
+{
+   return interpolationFlagFC;
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::hasInterpolationFlagFC(int dir)
+{
+   return UbSystem::bitCheck( interpolationFlagFC, 1<<dir );
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::hasInterpolationFlag()
+{ 
+   return(interpolationFlagCF!=0 || interpolationFlagFC!=0); 
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::hasInterpolationFlag(int direction)     
+{ 
+   return(hasInterpolationFlagCF(direction) || hasInterpolationFlagFC(direction)); 
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::hasInterpolationFlagCF()
+{
+   return(interpolationFlagCF!=0);
+}
+//////////////////////////////////////////////////////////////////////////
+bool Block3D::hasInterpolationFlagFC()
+{
+   return(interpolationFlagFC!=0);
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::deleteInterpolationFlag()
+{
+   interpolationFlagFC = 0;
+   interpolationFlagCF = 0;
+}
+//////////////////////////////////////////////////////////////////////////
+double Block3D::getWorkLoad()
+{
+   double l = kernel->getCallculationTime();
+   l *= static_cast<double>(1<<level);
+   return l;
+}
+//////////////////////////////////////////////////////////////////////////
+std::string Block3D::toString() 
+{
+   std::stringstream ss;
+   ss<<"Block3D[(x1,x2,x3,level),";
+   ss<<" ("<<this->x1<<", "<<this->x2<<", "<<this->x3<<", "<<this->level<<"), id=" << globalID; 
+   ss<< ", active="<<this->active<< ", bundle="<<this->bundle<< ", rank="<<this->rank<<"]";
+   ss<<" connectors:";
+   for(std::size_t i=0; i<connectors.size(); i++)
+      if( connectors[i] )
+      {
+         if(connectors[i]->isLocalConnector())
+            ss <<"l."<< Grid3DSystem::getDirectionString(connectors[i]->getSendDir()) << ", ";
+         if(connectors[i]->isRemoteConnector())
+            ss <<"r."<< Grid3DSystem::getDirectionString(connectors[i]->getSendDir()) << ", ";
+         if(connectors[i]->isInterpolationConnectorCF())
+            ss <<"cf."<< Grid3DSystem::getDirectionString(connectors[i]->getSendDir()) << ", ";
+         if(connectors[i]->isInterpolationConnectorFC())
+            ss <<"fc."<< Grid3DSystem::getDirectionString(connectors[i]->getSendDir()) << ", ";
+      }
+   return ss.str();
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::setWeight( int rank, int weight )
+{
+   std::map<int, int>::iterator it;
+   if((it = this->weight.find(rank)) != this->weight.end())
+       it->second = weight;
+   else
+      this->weight.insert(std::make_pair(rank, weight));
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getWeight( int rank )
+{
+   std::map<int, int>::iterator it;
+   if((it = this->weight.find(rank)) != this->weight.end())
+      return it->second;
+   else
+      return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::addWeight( int rank, int weight )
+{
+   int weight_old = getWeight(rank);
+   weight += weight_old;
+   setWeight(rank, weight);
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::addWeightForAll( int weight )
+{
+   typedef std::map<int, int> wMap;
+   BOOST_FOREACH(wMap::value_type &w, this->weight)
+   {
+      w.second += weight;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Block3D::clearWeight()
+{
+   this->weight.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+int Block3D::getWeightSize()
+{
+   return static_cast<int>(this->weight.size());
+}
+
+
diff --git a/source/VirtualFluidsCore/Grid/Block3D.h b/source/VirtualFluidsCore/Grid/Block3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..35b08ea69cff80712b4b57843a37cb8189d1a87f
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Block3D.h
@@ -0,0 +1,156 @@
+#ifndef BLOCK3D_H
+#define BLOCK3D_H
+
+#include <sstream>
+#include <iostream>
+
+#include "UbMath.h"
+#include "CoordinateTransformation3D.h"
+
+#include "Block3DConnector.h"
+
+#include <boost/serialization/shared_ptr.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/foreach.hpp>
+
+#include <boost/shared_ptr.hpp>
+class Block3D;
+typedef boost::shared_ptr<Block3D> Block3DPtr;
+
+#include "LBMKernel3D.h"
+
+class Block3D
+{
+public:
+   Block3D();
+   Block3D(int x1, int x2, int x3, int level);
+   virtual ~Block3D();
+   bool operator==(const Block3D& src) const;
+   bool operator!=(const Block3D& src) const;
+
+   int getX1() const;
+   int getX2() const;
+   int getX3() const;
+
+   void setActive(bool active);
+   bool isActive()    const;
+   bool isNotActive() const;
+
+   void setKernel(LBMKernel3DPtr kernel);
+   LBMKernel3DPtr getKernel() const;
+   void deleteKernel();
+
+   void setBundle(int bundle);
+   int  getBundle() const;
+
+   void setRank(int rank);
+   int  getRank() const;
+
+   void setLocalRank(int rank);
+   int  getLocalRank() const;
+
+   int  getGlobalID() const;
+   void setGlobalID(int id);
+
+   int  getLocalID() const;
+   void setLocalID(int id);
+
+   int  getPart() const;
+   void setPart(int part);
+
+   int  getLevel() const;
+   void setLevel(int level);
+
+   //Connector-Section
+   void                 setConnector(Block3DConnectorPtr connector);
+   Block3DConnectorPtr  getConnector(int dir) const;
+   bool                 hasConnectors();
+   void                 deleteConnectors();
+   void pushBackSameLevelConnectors(  std::vector<Block3DConnectorPtr>& localSameLevelConnectors
+                                    , std::vector<Block3DConnectorPtr>& remoteSameLevelConnectors );
+   void pushBackLocalSameLevelConnectors( std::vector<Block3DConnectorPtr>& localSameLevelConnectors );
+   void pushBackRemoteSameLevelConnectors( std::vector<Block3DConnectorPtr>& remoteSameLevelConnectors );
+   void pushBackLocalInterpolationConnectorsCF( std::vector<Block3DConnectorPtr>& localInterpolationConnectors );
+   void pushBackRemoteInterpolationConnectorsCF( std::vector<Block3DConnectorPtr>& remoteInterpolationConnectors );
+   void pushBackLocalInterpolationConnectorsFC( std::vector<Block3DConnectorPtr>& localInterpolationConnectors );
+   void pushBackRemoteInterpolationConnectorsFC( std::vector<Block3DConnectorPtr>& remoteInterpolationConnectors );
+   void pushBackLocalSameLevelConnectors( std::vector<Block3DConnectorPtr>& localSameLevelConnectors, const int& dir);
+   void pushBackRemoteSameLevelConnectors( std::vector<Block3DConnectorPtr>& remoteSameLevelConnectors, const int& dir );
+   int getNumberOfLocalConnectors();
+   int getNumberOfRemoteConnectors();
+   int getNumberOfLocalConnectorsForSurfaces();
+   int getNumberOfRemoteConnectorsForSurfaces();
+
+   void setWeight(int rank, int weight);
+   int  getWeight(int rank);
+   void addWeightForAll(int weight);
+   void addWeight(int rank, int weight);
+   void clearWeight();
+   int  getWeightSize();
+
+   //interpolation
+   bool hasInterpolationFlag();
+   bool hasInterpolationFlag(int dir);
+   void deleteInterpolationFlag();
+
+   void setInterpolationFlagCF(int dir);
+   int  getInterpolationFlagCF();
+   bool hasInterpolationFlagCF(int dir);
+   bool hasInterpolationFlagCF();
+
+   void setInterpolationFlagFC(int dir);
+   int  getInterpolationFlagFC();
+   bool hasInterpolationFlagFC(int dir);
+   bool hasInterpolationFlagFC();
+
+   double getWorkLoad();
+
+   std::string toString() ;
+
+   static int getMaxGlobalID() { return counter; }
+private:
+  int   x1;
+  int   x2;
+  int   x3;
+
+  bool active;
+
+  int interpolationFlagCF;
+  int interpolationFlagFC;
+
+  LBMKernel3DPtr kernel;
+  std::vector<Block3DConnectorPtr> connectors;
+  std::map<int, int> weight;
+
+  int bundle;
+  int rank;
+  int lrank;
+  int globalID;
+  int localID;
+  int part;
+  int level;
+  static int counter;
+
+  friend class boost::serialization::access;
+  template<class Archive>
+  void serialize(Archive & ar, const unsigned int version)
+  {
+     ar & x1;
+     ar & x2;
+     ar & x3;
+     ar & active;
+     ar & bundle;
+     ar & rank;
+     ar & lrank;
+     ar & part;
+     ar & globalID;
+     ar & localID;
+     ar & level;
+     ar & kernel;
+     ar & interpolationFlagCF;
+     ar & interpolationFlagFC;
+     ar & counter;
+  }
+};
+
+#endif  //BLOCK3D_H
diff --git a/source/VirtualFluidsCore/Grid/BoostSerializationClassExportHelper.h b/source/VirtualFluidsCore/Grid/BoostSerializationClassExportHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..87f034c47c3d768cb6f22b08e7ba04371982ba76
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/BoostSerializationClassExportHelper.h
@@ -0,0 +1,80 @@
+#ifndef BOOSTSERIALIZATIONCLASSEXPORTHELPER_H
+#define BOOSTSERIALIZATIONCLASSEXPORTHELPER_H
+
+#include <LBMKernelETD3Q27.h>
+#include <LBMKernelETD3Q27Cascaded.h>
+#include <D3Q27EsoTwist3DSplittedVector.h>
+#include <D3Q27ETBCProcessor.h>
+#include <D3Q27ETForThinWallBCProcessor.h>
+#include <LBMKernelETD3Q27CascadedTI.h>
+#include <DataSet3D.h>
+#include <LBMKernelETD3Q27BGK.h>
+#include <LBMKernelETD3Q27CCLB.h>
+#include <LBMKernelETD3Q27CCLBWithSpongeLayer.h>
+#include <Interactor3D.h>
+#include <D3Q27Interactor.h>
+#include <Communicator.h>
+#include <MPICommunicator.h>
+#include <Postprocessor.h>
+#include <D3Q27MacroscopicQuantitiesPostprocessor.h>
+#include <D3Q27ShearStressPostprocessor.h>
+#include <AverageValuesPostprocessor.h>
+#include <basics/container/CbArray4D.h>
+#include <basics/writer/WbWriter.h>
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+
+#include <BoundaryCondition.h>
+#include <VelocityBoundaryCondition.h>
+#include <NonEqDensityBoundaryCondition.h>
+#include <EqDensityBoundaryCondition.h>
+#include <NoSlipBoundaryCondition.h>
+#include <HighViscosityNoSlipBoundaryCondition.h>
+#include <SlipBoundaryCondition.h>
+#include <NonReflectingDensityBoundaryCondition.h>
+#include <NonReflectingVelocityBoundaryCondition.h>
+
+#include <D3Q27BoundaryConditionAdapter.h>
+#include <D3Q27DensityBCAdapter.h>
+#include <D3Q27NoSlipBCAdapter.h>
+#include <D3Q27SlipBCAdapter.h>
+#include <D3Q27VelocityBCAdapter.h>
+
+
+#include <boost/serialization/export.hpp>
+
+BOOST_CLASS_EXPORT(LBMKernelETD3Q27)
+BOOST_CLASS_EXPORT(LBMKernelETD3Q27Cascaded)
+BOOST_CLASS_EXPORT(LBMKernelETD3Q27CascadedTI)
+BOOST_CLASS_EXPORT(LBMKernelETD3Q27BGK)
+BOOST_CLASS_EXPORT(LBMKernelETD3Q27CCLB)
+BOOST_CLASS_EXPORT(LBMKernelETD3Q27CCLBWithSpongeLayer)
+BOOST_CLASS_EXPORT(D3Q27EsoTwist3DSplittedVector)
+BOOST_CLASS_EXPORT(D3Q27ETBCProcessor)
+BOOST_CLASS_EXPORT(D3Q27ETForThinWallBCProcessor)
+BOOST_CLASS_EXPORT(DataSet3D)
+BOOST_CLASS_EXPORT(Interactor3D)
+BOOST_CLASS_EXPORT(D3Q27Interactor)
+BOOST_CLASS_EXPORT(Postprocessor)
+BOOST_CLASS_EXPORT(D3Q27MacroscopicQuantitiesPostprocessor)
+BOOST_CLASS_EXPORT(D3Q27ShearStressPostprocessor)
+BOOST_CLASS_EXPORT(AverageValuesPostprocessor)
+BOOST_CLASS_EXPORT(WbWriterVtkXmlASCII)
+BOOST_CLASS_EXPORT(WbWriterVtkXmlBinary)
+
+BOOST_CLASS_EXPORT(BoundaryCondition)
+BOOST_CLASS_EXPORT(VelocityBoundaryCondition)
+BOOST_CLASS_EXPORT(NonEqDensityBoundaryCondition)
+BOOST_CLASS_EXPORT(EqDensityBoundaryCondition)
+BOOST_CLASS_EXPORT(NoSlipBoundaryCondition)
+BOOST_CLASS_EXPORT(HighViscosityNoSlipBoundaryCondition)
+BOOST_CLASS_EXPORT(SlipBoundaryCondition)
+BOOST_CLASS_EXPORT(NonReflectingDensityBoundaryCondition)
+BOOST_CLASS_EXPORT(NonReflectingVelocityBoundaryCondition)
+
+BOOST_CLASS_EXPORT(D3Q27BoundaryConditionAdapter)
+BOOST_CLASS_EXPORT(D3Q27DensityBCAdapter)
+BOOST_CLASS_EXPORT(D3Q27NoSlipBCAdapter)
+BOOST_CLASS_EXPORT(D3Q27SlipBCAdapter)
+BOOST_CLASS_EXPORT(D3Q27VelocityBCAdapter)
+#endif
diff --git a/source/VirtualFluidsCore/Grid/CMakePackage.txt b/source/VirtualFluidsCore/Grid/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Grid/CalculationManager.cpp b/source/VirtualFluidsCore/Grid/CalculationManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c209380fa26ad9573ddd6f01a0eebbadd610ef22
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/CalculationManager.cpp
@@ -0,0 +1,211 @@
+#include "CalculationManager.h"
+
+#include <iomanip>
+#include <list>
+#include <vector>
+
+#include <boost/thread.hpp>
+#include <boost/foreach.hpp>
+
+#include <Calculator.h>
+#include <PrePostBcCalculator.h>
+#include <SimulationParameters.h>
+#include <Communicator.h>
+
+#if defined VF_FETOL
+#include <FETOLCalculator.h>
+#endif
+
+using namespace std;
+//////////////////////////////////////////////////////////////////////////
+CalculationManager::CalculationManager(Grid3DPtr grid, int numOfThreads, double endTime, UbSchedulerPtr visScheduler, CalculationManager::CalculatorType calcType)
+                                       : grid(grid),
+                                         numOfThreads(numOfThreads),
+                                         endTime(endTime),
+                                         visScheduler(visScheduler),
+                                         calcType(calcType)
+{
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+CalculationManager::CalculationManager(Grid3DPtr grid, int numOfThreads, double endTime, UbSchedulerPtr visScheduler, 
+                                       CommunicatorPtr comm, int endDir, LBMReal nu, CalculatorType calcType)
+                                       : grid(grid),
+                                       numOfThreads(numOfThreads),
+                                       endTime(endTime),
+                                       visScheduler(visScheduler),
+                                       calcType(calcType), 
+                                       comm(comm),
+                                       endDir(endDir),
+                                       nu(nu)
+{
+   init();
+   loadBalancer = LoadBalancerPtr(new LoadBalancer(grid, comm, endDir));
+}
+//////////////////////////////////////////////////////////////////////////
+CalculationManager::CalculationManager(Grid3DPtr grid, int numOfThreads, double endTime, UbSchedulerPtr visScheduler, BoundaryConditionProcessorPtr bcProcessor, CalculationManager::CalculatorType calcType)
+   : grid(grid),
+   numOfThreads(numOfThreads),
+   endTime(endTime),
+   visScheduler(visScheduler),
+   bcProcessor(bcProcessor),
+   calcType(calcType)
+{
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+CalculationManager::~CalculationManager()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void CalculationManager::init()
+{
+   this->rank = grid->getRank();
+   initCalcThreads();
+}
+//////////////////////////////////////////////////////////////////////////
+void CalculationManager::calculate()
+{
+   try
+   {
+      boost::thread_group threads;
+      boost::shared_ptr<CalculationManager> this_ = shared_from_this();
+      boost::exception_ptr error;
+
+      for (int i=1; i<calcThreads.size(); i++)
+      {
+         threads.create_thread( boost::bind( &Calculator::calculate, calcThreads[i], endTime, this_,boost::ref(error)) );
+      }
+
+      calcThreads[0]->calculate(endTime, this_, boost::ref(error));
+
+      threads.join_all();
+
+      //if( error )
+      //{
+      //   boost::rethrow_exception(error);
+      //}
+   }
+   catch(std::exception& e)
+   {
+      UBLOG(logERROR, e.what());
+      //throw e;
+      exit (EXIT_FAILURE);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void CalculationManager::initCalcThreads()
+{
+   UBLOG(logDEBUG1, "CalculationManager::initCalcThreads() - started");
+   
+   SynchronizerPtr sync( new Synchronizer(numOfThreads));
+   
+   for (int i =0; i<numOfThreads; i++)
+   {
+      //CalculatorPtr calc = CalculatorPtr (new Calculator(grid, sync, i == 0 ? true : false));
+      CalculatorPtr calc = createCalculator(grid, sync, i == 0 ? true : false);
+      calc->setVisScheduler(visScheduler);
+      calcThreads.push_back(calc);
+   }
+
+   UBLOG(logDEBUG5, "calcThreads - initialized");
+
+   addBlocksToCalcThreads();
+
+   UBLOG(logDEBUG5, "calcThreads - filled with Blocks");
+
+   //BOOST_FOREACH(CalculatorPtr calc,  calcThreads)
+   //{
+   //   calc->initConnectors();
+   //}
+   UBLOG(logDEBUG1, "CalculationManager::initCalcThreads() - stoped");
+}
+//////////////////////////////////////////////////////////////////////////
+void CalculationManager::setVisScheduler(UbSchedulerPtr s)
+{
+   visScheduler = s;
+}
+//////////////////////////////////////////////////////////////////////////
+bool CalculationManager::balance()
+{
+   //if(loadBalancer->balance())
+   //   return true;
+   //else
+   //{
+   //   grid->deleteConnectors();
+
+   //   BOOST_FOREACH(CalculatorPtr calc,  calcThreads)
+   //   {
+   //      calc->deleteConnectors();
+   //   }
+
+   //   TbCbVectorMpiPool<LBMReal>::eraseMap();
+
+   //   D3Q27SetInterfaceBlocksPatchVisitor setInterfaceBlocksPatchVisitor(nue, comm);
+   //   grid->accept(setInterfaceBlocksPatchVisitor);
+
+   //   D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR);
+   //   grid->accept( setConnsVisitor );
+
+   //   PQueuePartitioningPatchVisitor pqPartVisitor(numOfThreads);
+   //   grid->accept(pqPartVisitor);
+
+   //   reinitCalcThreads();
+      return false;
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+void CalculationManager::reinitCalcThreads()
+{
+   BOOST_FOREACH(CalculatorPtr c, calcThreads)
+   {
+      c->deleteBlocks();
+   }
+
+   addBlocksToCalcThreads();
+
+   BOOST_FOREACH(CalculatorPtr calc,  calcThreads)
+   {
+      calc->initConnectors();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void CalculationManager::addBlocksToCalcThreads()
+{
+   int gridRank = grid->getRank();
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      vector<Block3DPtr> blockVector;
+      grid->getBlocks(level, gridRank, true, blockVector);
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         if (block)
+         {
+            calcThreads[block->getPart()]->addBlock(block);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+CalculatorPtr CalculationManager::createCalculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread)
+{
+   switch (calcType)
+   {
+   case CalculationManager::MPI:
+      return CalculatorPtr (new Calculator(grid, sync, bcProcessor, mainThread));
+#if defined VF_FETOL
+   case CalculationManager::FETOL:
+      return CalculatorPtr (new FETOLCalculator(grid, sync, mainThread));
+#endif
+   case CalculationManager::PrePostBc:
+      return CalculatorPtr(new PrePostBcCalculator(grid, sync, bcProcessor, mainThread));
+   default:
+      UB_THROW(UbException(UB_EXARGS,"This Calculator is not defined!"));
+   }
+}
+
+
+
diff --git a/source/VirtualFluidsCore/Grid/CalculationManager.h b/source/VirtualFluidsCore/Grid/CalculationManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..bded50f0ed3142db624f5cd91e17582de29f78f5
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/CalculationManager.h
@@ -0,0 +1,48 @@
+#ifndef CALCULATORMANAGER_H
+#define CALCULATORMANAGER_H
+
+#include "Grid3D.h"
+#include "Communicator.h"
+
+class CalculationManager;
+typedef boost::shared_ptr<CalculationManager> CalculationManagerPtr;
+
+#include "Calculator.h"
+
+class CalculationManager : public boost::enable_shared_from_this<CalculationManager>
+{
+public:
+   enum CalculatorType{MPI, FETOL, PrePostBc};
+public:
+   CalculationManager(Grid3DPtr grid, int numOfThreads, double endTime, UbSchedulerPtr visScheduler, CalculatorType calcType = CalculationManager::MPI);
+   CalculationManager(Grid3DPtr grid, int numOfThreads, double endTime, UbSchedulerPtr visScheduler, 
+                      CommunicatorPtr comm, int endDir, LBMReal nu, CalculatorType calcType = CalculationManager::MPI);
+   CalculationManager(Grid3DPtr grid, int numOfThreads, double endTime, UbSchedulerPtr visScheduler, BoundaryConditionProcessorPtr bcProcessor, CalculatorType calcType = CalculationManager::MPI);
+   virtual ~CalculationManager();
+   void calculate();
+   void setVisScheduler(UbSchedulerPtr s);
+   bool balance();
+private:
+   void init();
+   void calculateMain();
+   void initCalcThreads();
+   void reinitCalcThreads();
+   void addBlocksToCalcThreads();
+   CalculatorPtr createCalculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread);
+   Grid3DPtr grid;
+   int numOfThreads;
+   //boost::exception_ptr error;
+   CalculatorType calcType;
+   std::vector<CalculatorPtr> calcThreads;
+   double endTime;
+   UbSchedulerPtr visScheduler;
+   CommunicatorPtr comm;   
+   int endDir;
+   LoadBalancerPtr loadBalancer;
+   int rank;
+   LBMReal nu;
+   BoundaryConditionProcessorPtr bcProcessor;
+}; 
+
+#endif 
+
diff --git a/source/VirtualFluidsCore/Grid/Calculator.cpp b/source/VirtualFluidsCore/Grid/Calculator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..251bcbf87de41ce24c39ac7236866511a832314f
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Calculator.cpp
@@ -0,0 +1,618 @@
+#include "Calculator.h"
+#include <basics/utilities/UbException.h>
+#include <boost/foreach.hpp>
+#include "SimulationParameters.h"
+#include "MathUtil.hpp"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+
+//#define TIMING
+
+Calculator::Calculator()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+Calculator::Calculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread) : 
+                       grid(grid),
+                       sync(sync),
+                       mainThread(mainThread),
+                       refinement(false)
+{
+   minLevel = grid->getCoarsestInitializedLevel();
+   maxLevel = grid->getFinestInitializedLevel();
+   if(maxLevel > 0)
+      refinement = true;
+   else
+      refinement = false;
+   blocks.resize(maxLevel+1);
+   localConns.resize(maxLevel+1);
+   remoteConns.resize(maxLevel+1);
+   localInterfaceBlockConns.resize(maxLevel+1);
+   remoteInterfaceBlockConns.resize(maxLevel+1);
+   localInterConns.resize(maxLevel);
+   remoteInterConns.resize(maxLevel);
+   loadBalancingComp = false;
+}
+//////////////////////////////////////////////////////////////////////////
+Calculator::Calculator(Grid3DPtr grid, SynchronizerPtr sync, BoundaryConditionProcessorPtr bcProcessor, bool mainThread) :
+grid(grid),
+sync(sync),
+bcProcessor(bcProcessor),
+mainThread(mainThread),
+refinement(false)
+{
+   minLevel = grid->getCoarsestInitializedLevel();
+   maxLevel = grid->getFinestInitializedLevel();
+   if (maxLevel > 0)
+      refinement = true;
+   else
+      refinement = false;
+   blocks.resize(maxLevel+1);
+   localConns.resize(maxLevel+1);
+   remoteConns.resize(maxLevel+1);
+   localInterfaceBlockConns.resize(maxLevel+1);
+   remoteInterfaceBlockConns.resize(maxLevel+1);
+   localInterConns.resize(maxLevel);
+   remoteInterConns.resize(maxLevel);
+   loadBalancingComp = false;
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error)
+{
+   UBLOG(logDEBUG1, "Calculator::calculate() - started");
+   try
+   {
+      initConnectors();
+
+      int anzLevel = maxLevel-minLevel+1;
+
+      int minInitLevel       = minLevel;
+      int maxInitLevel       = maxLevel-minLevel;
+      int straightStartLevel = minInitLevel;
+      int internalIterations = 1 << (maxInitLevel-minInitLevel);
+      int forwardStartLevel;
+      int threshold;
+      int startStep = int(grid->getTimeStep())+1;
+
+      //UBLOG(logINFO, "startStep="<<startStep);
+      int anzCalcSteps = static_cast<int>(endTime);
+#ifdef TIMING
+      UbTimer timer;
+      double time[6];
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//      UBLOG(logINFO, "Number of connectors = " <<this->localConns[0].size());
+//////////////////////////////////////////////////////////////////////////
+
+      for(calcStep=startStep; calcStep<=anzCalcSteps+1; calcStep++)
+      {
+
+         //exchange data between blocks for visualization
+         //sync->wait();
+         ////if(visScheduler->isDue((double)(calcStep-1)))
+         ////{
+         //   //exchangeBlockData(minInitLevel, maxInitLevel, true);
+         ////}
+
+         ////wait for write dump files
+         sync->wait();
+         //write dump 
+         if (mainThread) grid->doPostProcess((double)(calcStep-1));
+         sync->wait();
+
+
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+         //UBLOG(logINFO, "calcStep = " <<calcStep);
+#endif
+//////////////////////////////////////////////////////////////////////////
+         
+         for(int staggeredStep=1; staggeredStep<=internalIterations; staggeredStep++)
+         {
+            forwardStartLevel = straightStartLevel;
+            if(staggeredStep == internalIterations) straightStartLevel = minInitLevel;
+            else
+            {
+               for(straightStartLevel=maxInitLevel,threshold=1;
+                  (staggeredStep&threshold)!=threshold; straightStartLevel--,threshold<<=1);
+            }
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            timer.resetAndStart();
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //applyPreCollisionBC(straightStartLevel, maxInitLevel);
+
+
+            calculateBlocks(straightStartLevel, maxInitLevel);
+            ////calculateBlocks(minInitLevel, maxInitLevel, staggeredStep);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[0] = timer.stop();
+            //UBLOG(logINFO, "calculateBlocks time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //exchange data between blocks
+            //Sleep(10000);
+            exchangeBlockData(straightStartLevel, maxInitLevel, false);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[1] = timer.stop();
+            //UBLOG(logINFO, "exchangeBlockData time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+            //applyBCs(straightStartLevel, maxInitLevel);
+            applyPostCollisionBC(straightStartLevel, maxInitLevel);
+            
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[2] = timer.stop();
+            //UBLOG(logINFO, "applyBCs time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //swap distributions in kernel
+            swapDistributions(straightStartLevel, maxInitLevel);
+
+            //exchangeBlockData(straightStartLevel, maxInitLevel, true);
+            //applyPreCollisionBC(straightStartLevel, maxInitLevel);
+            
+
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[3] = timer.stop();
+            //UBLOG(logINFO, "swapDistributions time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            if (refinement)
+            {
+         //      //exchange data between blocks for grid refinement
+			      ////exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+         //DOES NOT NEED 
+                     if(straightStartLevel<maxInitLevel)
+                        exchangeBlockData(straightStartLevel, maxInitLevel, true);
+         //         //exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+               time[4] = timer.stop();
+               UBLOG(logINFO, "refinement exchangeBlockData time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+               //now ghost nodes have actual values
+			      //interpolation of interface nodes between grid levels
+               interpolation(straightStartLevel, maxInitLevel);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+               time[5] = timer.stop();
+               UBLOG(logINFO, "refinement interpolation time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+            }
+            
+         }
+         //exchange data between blocks for visualization
+        if(mainThread) visScheduler->isDue((double)(calcStep-1));
+        if((int)visScheduler->getNextDueTime() == calcStep)
+        {
+            exchangeBlockData(straightStartLevel, maxInitLevel, true);
+        }
+         //now ghost nodes have actual values
+
+         //dynamic load balancing
+         //sync->wait();
+         //if (mainThread && !loadBalancingComp)
+         //{
+         //   loadBalancingComp = cm->balance();
+         //}
+      }
+      error = boost::exception_ptr();
+      UBLOG(logDEBUG1, "Calculator::calculate() - stoped");
+   }
+   catch( std::exception& e )
+   {
+      //error = boost::current_exception();
+      UBLOG(logERROR, e.what());
+      UBLOG(logERROR, " step = "<<calcStep);
+      boost::dynamic_pointer_cast<MPICommunicator>(Communicator::getInstance())->~MPICommunicator();
+      exit(EXIT_FAILURE);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::calculateBlocks(int startLevel, int maxInitLevel)
+{
+   Block3DPtr blockTemp;
+   try
+   {
+      //startLevel bis maxInitLevel
+      for(int level=startLevel; level<=maxInitLevel; level++)
+      {
+         //timer.resetAndStart();
+         //call LBM kernel
+         BOOST_FOREACH(Block3DPtr block, blocks[level])
+         {
+            blockTemp = block;
+            block->getKernel()->calculate();
+         }
+         //timer.stop();
+         //UBLOG(logINFO, "level = " << level << " blocks = " << blocks[level].size() << " collision time = " << timer.getTotalTime());
+      }
+   }
+   catch( std::exception& e )
+   {      
+      //error = boost::current_exception();
+      UBLOG(logERROR, e.what());
+      UBLOG(logERROR, blockTemp->toString()<<" step = "<<calcStep);
+      exit(EXIT_FAILURE);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::calculateBlocks(int minInitLevel, int maxInitLevel, int staggeredStep)
+{
+   int p, maxi, maxir, maxidp, start, end;
+   for(int level=minInitLevel; level<=maxInitLevel; level++)
+   {
+      p = 1<<(maxInitLevel-level);
+      maxi = maxir = static_cast<int>(blocks[level].size());
+      maxidp = maxi/p;
+      if(p > maxi && maxi != 0){
+         maxidp = 1;
+         maxi = p;
+      }
+      start = (staggeredStep-1)*maxidp;
+      if(start >= maxi)
+         start = 0;
+      end = start + maxidp;
+      if((end + p) >= maxi)
+         end = maxi;
+      for (int i = start; i < end; i++)
+      {
+         if(i < maxir)
+            blocks[level][i]->getKernel()->calculate();
+      }
+   }
+ }
+//////////////////////////////////////////////////////////////////////////
+void Calculator::addBlock(Block3DPtr block)
+{
+   blocks[block->getLevel()].push_back(block);
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::initConnectors()
+{
+   UBLOG(logDEBUG1, "Calculator::initLocalConnectors() - start");
+
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[l])
+      {     
+         block->pushBackLocalSameLevelConnectors(localConns[l]);
+
+         if(block->hasInterpolationFlag())
+            block->pushBackLocalSameLevelConnectors(localInterfaceBlockConns[l]);
+         if (l != maxLevel)
+            block->pushBackLocalInterpolationConnectorsCF(localInterConns[l]);
+      }
+      if (l != maxLevel)
+      {
+         BOOST_FOREACH(Block3DPtr block, blocks[l+1])
+         {     
+            block->pushBackLocalInterpolationConnectorsFC(localInterConns[l]);
+         }
+      }
+      UBLOG(logDEBUG5, "Calculator::initConnectors()-initConnectors(localConns["<<l<<"])");
+      initConnectors(localConns[l]);
+
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator::initConnectors()-initConnectors(localInterConns["<<l<<"])");
+         initConnectors(localInterConns[l]);
+      }
+   }
+   
+   if (mainThread)
+      initRemoteConnectors();
+
+   UBLOG(logDEBUG1, "Calculator::initLocalConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::initRemoteConnectors()
+{
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConnsCF;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConnsFC;
+   remoteInterConnsCF.resize(maxLevel+1);
+   remoteInterConnsFC.resize(maxLevel+1);
+
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+   int gridRank = grid->getRank();
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      std::vector<Block3DPtr> blockVector;
+      //grid->getBlocks(level, gridRank, true, blockVector);
+      grid->getBlocks(level, blockVector);
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         int l = block->getLevel();
+         block->pushBackRemoteSameLevelConnectors(remoteConns[l]);
+
+         //if(block->isInterface())
+         //   block->pushBackRemoteSameLevelConnectors(remoteInterfaceBlockConns[l]);
+         block->pushBackRemoteInterpolationConnectorsCF(remoteInterConnsCF[l]);
+         block->pushBackRemoteInterpolationConnectorsFC(remoteInterConnsFC[l]);
+      }
+   }
+
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-initConnectors(remoteConns["<<l<<"])");
+      initConnectors(remoteConns[l]);
+      if (l != maxLevel)
+      {
+		 for(int i = 0; i < remoteInterConnsCF[l].size(); i++)
+			remoteInterConns[l].push_back(remoteInterConnsCF[l][i]);
+		 for(int i = 0; i < remoteInterConnsFC[l+1].size(); i++)
+	      remoteInterConns[l].push_back(remoteInterConnsFC[l+1][i]);
+       //UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-initConnectors(remoteInterConns["<<l<<"])");
+       //initConnectors(remoteInterConns[l]);
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - start");
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-initConnectors(remoteInterConns["<<l<<"])");
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->init();
+      }
+   }
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - end");
+   //////////////////////////////////////////////////////////////////////////
+   //sendTransmitterDataSize
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - start");
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-sendTransmitterDataSize(remoteInterConns["<<l<<"])");
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->sendTransmitterDataSize();
+      }
+   }
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+   //receiveTransmitterDataSize
+   //wenn er hier bei verteilten berechnungen stopped, dann ist vermutlich auf einer seite ein nicht aktiver block!!!
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - start");
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-receiveTransmitterDataSize(remoteInterConns["<<l<<"])");
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->receiveTransmitterDataSize();
+      }
+   }
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::initConnectors(std::vector<Block3DConnectorPtr>& connectors)
+{
+   UBLOG(logDEBUG1, "Calculator::initConnectors() - start");
+
+   //initialization
+   //////////////////////////////////////////////////////////////////////////
+   //initialize connectors
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->init();
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - end");
+   //////////////////////////////////////////////////////////////////////////
+   //sendTransmitterDataSize
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->sendTransmitterDataSize();
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+   //receiveTransmitterDataSize
+   //wenn er hier bei verteilten berechnungen stopped, dann ist vermutlich auf einer seite ein nicht aktiver block!!!
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->receiveTransmitterDataSize();
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - end");
+
+   UBLOG(logDEBUG1, "Calculator::initConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::exchangeBlockData(int startLevel, int maxInitLevel, bool invStep)
+{
+   sync->wait();
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(localConns[level]);
+      connectorsPrepare(remoteConns[level]);
+
+      connectorsSend(localConns[level], invStep);
+      connectorsSend(remoteConns[level], invStep);
+
+      connectorsReceive(localConns[level], invStep);
+      connectorsReceive(remoteConns[level], invStep);
+   }
+   sync->wait();
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::exchangeInterfaceBlockData(int startLevel, int maxInitLevel, bool invStep)
+{
+   sync->wait();
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(localInterfaceBlockConns[level]);
+      connectorsPrepare(remoteInterfaceBlockConns[level]);
+
+      connectorsSend(localInterfaceBlockConns[level], invStep);
+      connectorsSend(remoteInterfaceBlockConns[level], invStep);
+
+      connectorsReceive(localInterfaceBlockConns[level], invStep);
+      connectorsReceive(remoteInterfaceBlockConns[level], invStep);
+   }
+   sync->wait();
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::swapDistributions(int startLevel, int maxInitLevel)
+{
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->swapDistributions();
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::connectorsPrepare(std::vector< Block3DConnectorPtr >& connectors)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+      c->prepareForReceive();
+      c->prepareForSend();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::connectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+	   c->setInvStep(invStep);
+      c->fillSendVectors();
+      c->sendVectors();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::connectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+	   c->setInvStep(invStep);
+      c->receiveVectors();
+      c->distributeReceiveVectors();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::connectorsSetInvStep(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+      c->setInvStep(invStep);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::interpolation(int startLevel, int maxInitLevel)
+{
+   sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsPrepare(localInterConns[level]);
+      connectorsPrepare(remoteInterConns[level]);
+   }
+
+   sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsSend(localInterConns[level], true);
+      connectorsSend(remoteInterConns[level], true);
+   }
+
+   sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsReceive(localInterConns[level], true);
+      connectorsReceive(remoteInterConns[level], true);
+   }
+
+   sync->wait();
+
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::setVisScheduler(UbSchedulerPtr s)
+{
+   visScheduler = s;
+}
+//////////////////////////////////////////////////////////////////////////
+//double Calculator::getCallculationTime()
+//{
+//   return timer.getTotalTime();
+//}
+//////////////////////////////////////////////////////////////////////////
+std::vector< std::vector< Block3DPtr > > Calculator::getBlocks()
+{
+   return blocks;
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::deleteBlocks()
+{
+   BOOST_FOREACH(std::vector< Block3DPtr > &bs, blocks)
+      bs.resize(0);
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::deleteConnectors()
+{
+   deleteConnectors(localConns);
+   deleteConnectors(remoteConns);
+
+   deleteConnectors(localInterfaceBlockConns);
+   deleteConnectors(remoteInterfaceBlockConns);
+
+   deleteConnectors(localInterConns);
+   deleteConnectors(remoteInterConns);
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::deleteConnectors(std::vector< std::vector< Block3DConnectorPtr > >& conns)
+{
+   BOOST_FOREACH(std::vector< Block3DConnectorPtr > &c, conns)
+      c.resize(0);
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::applyBCs( int startLevel, int maxInitLevel )
+{
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      //call LBM kernel
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->getBCProcessor()->applyBC();
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::applyPreCollisionBC(int startLevel, int maxInitLevel)
+{
+   //startLevel bis maxInitLevel
+   for (int level = startLevel; level<=maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->getBCProcessor()->applyPreCollisionBC();
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator::applyPostCollisionBC(int startLevel, int maxInitLevel)
+{
+   //startLevel bis maxInitLevel
+   for (int level = startLevel; level<=maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->getBCProcessor()->applyPostCollisionBC();
+      }
+   }
+}
+
diff --git a/source/VirtualFluidsCore/Grid/Calculator.h b/source/VirtualFluidsCore/Grid/Calculator.h
new file mode 100644
index 0000000000000000000000000000000000000000..b1ebe69067be3a5329aa16bd2074968d31c8b1f8
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Calculator.h
@@ -0,0 +1,85 @@
+#ifndef CALCULATOR_H
+#define CALCULATOR_H
+
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "Synchronizer.h"
+#include "MathUtil.hpp"
+#include "basics/utilities/UbScheduler.h"
+#include "basics/utilities/UbTiming.h"
+#include "LoadBalancer.h"
+#include "BoundaryConditionProcessor.h"
+
+
+class Calculator;
+typedef boost::shared_ptr<Calculator> CalculatorPtr;
+
+#include "CalculationManager.h"
+
+class Calculator 
+{
+public:
+   Calculator();
+   Calculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread = true);
+   Calculator(Grid3DPtr grid, SynchronizerPtr sync, BoundaryConditionProcessorPtr bcProcessor, bool mainThread = true);
+   virtual ~Calculator(){}
+   virtual void calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error);
+   void addBlock(Block3DPtr block);
+   void initConnectors();
+   void setVisScheduler(UbSchedulerPtr s);
+   //double getCallculationTime();
+   std::vector< std::vector< Block3DPtr > > getBlocks(); 
+   void deleteBlocks();
+   void deleteConnectors();
+protected:
+   void calculateBlocks(int startLevel, int maxInitLevel);
+   void calculateBlocks(int minInitLevel, int maxInitLevel, int staggeredStep);
+   void initConnectors(std::vector<Block3DConnectorPtr>& connectors);
+   virtual void initRemoteConnectors();
+   void swapDistributions(int startLevel, int maxInitLevel);
+   virtual void exchangeBlockData(int startLevel, int maxInitLevel, bool invStep);
+   void exchangeInterfaceBlockData(int startLevel, int maxInitLevel, bool invStep);
+   virtual void connectorsPrepare(std::vector< Block3DConnectorPtr >& connectors);
+   virtual void connectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   virtual void connectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   void connectorsSetInvStep(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   void interpolation(int startLevel, int maxInitLevel);
+   void deleteConnectors(std::vector< std::vector< Block3DConnectorPtr > >& conns);
+   void applyBCs(int startLevel, int maxInitLevel);
+   void applyPreCollisionBC(int startLevel, int maxInitLevel);
+   void applyPostCollisionBC(int startLevel, int maxInitLevel);
+   int minLevel, maxLevel;
+   std::vector< std::vector< Block3DConnectorPtr > > localConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteConns;
+   SynchronizerPtr sync;
+
+   boost::barrier* bar;
+   //double time;
+
+   bool mainThread;
+   bool refinement;
+   Grid3DPtr grid;
+   UbSchedulerPtr visScheduler;
+   int calcStep;
+   BoundaryConditionProcessorPtr bcProcessor;
+   std::vector< std::vector<Block3DPtr> > blocks;
+
+private:
+   std::vector< std::vector< Block3DConnectorPtr > > localInterfaceBlockConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterfaceBlockConns;
+
+   //localInterConns and remoteInterConns save interpolation connectors 
+   //every element save CF connectors for current level and FC connectors for next level
+   //e.g. 
+   //localInterConns[0] = CF(0), FC(1)
+   //localInterConns[1] = CF(1), FC(2)
+   //localInterConns[2] 
+   std::vector< std::vector< Block3DConnectorPtr > > localInterConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConns;
+
+   //UbTimer timer, timer2, timer3;
+   bool loadBalancingComp;
+
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Grid/Calculator2.cpp b/source/VirtualFluidsCore/Grid/Calculator2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..303b2d44eb39f2ea150a07130896520fe039c6ca
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Calculator2.cpp
@@ -0,0 +1,546 @@
+#include "Calculator2.h"
+#include <basics/utilities/UbException.h>
+#include <boost/foreach.hpp>
+#include "SimulationParameters.h"
+#include "MathUtil.hpp"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+
+//#define TIMING
+
+
+Calculator2::Calculator2(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread) : 
+                       grid(grid),
+                       sync(sync),
+                       mainThread(mainThread),
+                       refinement(false)
+{
+   minLevel = grid->getCoarsestInitializedLevel();
+   maxLevel = grid->getFinestInitializedLevel();
+   if(maxLevel > 0)
+      refinement = true;
+   else
+      refinement = false;
+   blocks.resize(maxLevel+1);
+   localConns.resize(maxLevel+1);
+   remoteConns.resize(maxLevel+1);
+   localInterfaceBlockConns.resize(maxLevel+1);
+   remoteInterfaceBlockConns.resize(maxLevel+1);
+   localInterConns.resize(maxLevel);
+   remoteInterConns.resize(maxLevel);
+   loadBalancingComp = false;
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error)
+{
+   UBLOG(logDEBUG1, "Calculator2::calculate() - started");
+   try
+   {
+      int anzLevel = maxLevel-minLevel+1;
+
+      int minInitLevel       = minLevel;
+      int maxInitLevel       = maxLevel-minLevel;
+      int straightStartLevel = minInitLevel;
+      int internalIterations = 1 << (maxInitLevel-minInitLevel);
+      int forwardStartLevel;
+      int threshold;
+      int startStep = int(grid->getTimeStep())+1;
+      //UBLOG(logINFO, "startStep="<<startStep);
+      int anzCalcSteps = static_cast<int>(endTime);
+#ifdef TIMING
+      UbTimer timer;
+      double time[6];
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//      UBLOG(logINFO, "Number of connectors = " <<this->localConns[0].size());
+//////////////////////////////////////////////////////////////////////////
+
+      for(calcStep=startStep; calcStep<=anzCalcSteps; calcStep++)
+      {
+
+         //exchange data between blocks for visualization
+         //sync->wait();
+         ////if(visScheduler->isDue((double)(calcStep-1)))
+         ////{
+         //   //exchangeBlockData(minInitLevel, maxInitLevel, true);
+         ////}
+
+         ////wait for write dump files
+         //sync->wait();
+         //write dump 
+         if (mainThread) grid->doPostProcess((double)(calcStep-1));
+         sync->wait();
+
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+         //UBLOG(logINFO, "calcStep = " <<calcStep);
+#endif
+//////////////////////////////////////////////////////////////////////////
+         
+         for(int staggeredStep=1; staggeredStep<=internalIterations; staggeredStep++)
+         {
+            forwardStartLevel = straightStartLevel;
+            if(staggeredStep == internalIterations) straightStartLevel = minInitLevel;
+            else
+            {
+               for(straightStartLevel=maxInitLevel,threshold=1;
+                  (staggeredStep&threshold)!=threshold; straightStartLevel--,threshold<<=1);
+            }
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            timer.resetAndStart();
+#endif
+//////////////////////////////////////////////////////////////////////////
+            calculateBlocks(straightStartLevel, maxInitLevel);
+            //calculateBlocks(minInitLevel, maxInitLevel, staggeredStep);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[0] = timer.stop();
+            //UBLOG(logINFO, "calculateBlocks time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //exchange data between blocks
+			   exchangeBlockData(straightStartLevel, maxInitLevel, false);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[1] = timer.stop();
+            //UBLOG(logINFO, "exchangeBlockData time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            applyBCs(straightStartLevel, maxInitLevel);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[2] = timer.stop();
+            //UBLOG(logINFO, "applyBCs time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //swap distributions in kernel
+            swapDistributions(straightStartLevel, maxInitLevel);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[3] = timer.stop();
+            //UBLOG(logINFO, "swapDistributions time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            if (refinement)
+            {
+               //exchange data between blocks for grid refinement
+			      //exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+               if(straightStartLevel<maxInitLevel)
+                  //exchangeBlockData(straightStartLevel, maxInitLevel, true);
+                  exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+               time[4] = timer.stop();
+               UBLOG(logINFO, "refinement exchangeBlockData time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+               //now ghost nodes have actual values
+			      //interpolation of interface nodes between grid levels
+               interpolation(straightStartLevel, maxInitLevel);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+               time[5] = timer.stop();
+               UBLOG(logINFO, "refinement interpolation time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+            }
+            
+         }
+         //exchange data between blocks for visualization
+         if((int)visScheduler->getNextDueTime() == calcStep)
+         {
+            if(mainThread) visScheduler->isDue((double)(calcStep-1));
+            exchangeBlockData(straightStartLevel, maxInitLevel, true);
+         }
+         //now ghost nodes have actual values
+
+         //dynamic load balancing
+         //sync->wait();
+         //if (mainThread && !loadBalancingComp)
+         //{
+         //   loadBalancingComp = cm->balance();
+         //}
+      }
+      error = boost::exception_ptr();
+      UBLOG(logDEBUG1, "Calculator2::calculate() - stoped");
+   }
+   catch( ... )
+   {
+      error = boost::current_exception();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::calculateBlocks(int startLevel, int maxInitLevel)
+{
+   Block3DPtr blockTemp;
+   try
+   {
+      //startLevel bis maxInitLevel
+      for(int level=startLevel; level<=maxInitLevel; level++)
+      {
+         //timer.resetAndStart();
+         //call LBM kernel
+         BOOST_FOREACH(Block3DPtr block, blocks[level])
+         {
+            blockTemp = block;
+            block->getKernel()->calculate();
+         }
+         //timer.stop();
+         //UBLOG(logINFO, "level = " << level << " blocks = " << blocks[level].size() << " collision time = " << timer.getTotalTime());
+      }
+   }
+   catch( std::exception& e )
+   {      
+      //error = boost::current_exception();
+      UBLOG(logERROR, e.what());
+      UBLOG(logERROR, blockTemp->toString()<<" step = "<<calcStep);
+      exit(EXIT_FAILURE);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::calculateBlocks(int minInitLevel, int maxInitLevel, int staggeredStep)
+{
+   int p, maxi, maxir, maxidp, start, end;
+   for(int level=minInitLevel; level<=maxInitLevel; level++)
+   {
+      p = 1<<(maxInitLevel-level);
+      maxi = maxir = static_cast<int>(blocks[level].size());
+      maxidp = maxi/p;
+      if(p > maxi && maxi != 0){
+         maxidp = 1;
+         maxi = p;
+      }
+      start = (staggeredStep-1)*maxidp;
+      if(start >= maxi)
+         start = 0;
+      end = start + maxidp;
+      if((end + p) >= maxi)
+         end = maxi;
+      for (int i = start; i < end; i++)
+      {
+         if(i < maxir)
+            blocks[level][i]->getKernel()->calculate();
+      }
+   }
+ }
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::addBlock(Block3DPtr block)
+{
+   blocks[block->getLevel()].push_back(block);
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::initConnectors()
+{
+   UBLOG(logDEBUG1, "Calculator2::initLocalConnectors() - start");
+
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[l])
+      {     
+         block->pushBackLocalSameLevelConnectors(localConns[l]);
+
+         if(block->hasInterpolationFlag())
+            block->pushBackLocalSameLevelConnectors(localInterfaceBlockConns[l]);
+         if (l != maxLevel)
+            block->pushBackLocalInterpolationConnectorsCF(localInterConns[l]);
+      }
+      if (l != maxLevel)
+      {
+         BOOST_FOREACH(Block3DPtr block, blocks[l+1])
+         {     
+            block->pushBackLocalInterpolationConnectorsFC(localInterConns[l]);
+         }
+      }
+      UBLOG(logDEBUG5, "Calculator2::initConnectors()-initConnectors(localConns["<<l<<"])");
+      initConnectors(localConns[l]);
+
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator2::initConnectors()-initConnectors(localInterConns["<<l<<"])");
+         initConnectors(localInterConns[l]);
+      }
+   }
+   
+   if (mainThread)
+      initRemoteConnectors();
+
+   UBLOG(logDEBUG1, "Calculator2::initLocalConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::initRemoteConnectors()
+{
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConnsCF;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConnsFC;
+   remoteInterConnsCF.resize(maxLevel+1);
+   remoteInterConnsFC.resize(maxLevel+1);
+
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+   int gridRank = grid->getRank();
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      std::vector<Block3DPtr> blockVector;
+      //grid->getBlocks(level, gridRank, true, blockVector);
+      grid->getBlocks(level, blockVector);
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         int l = block->getLevel();
+         block->pushBackRemoteSameLevelConnectors(remoteConns[l]);
+
+         //if(block->isInterface())
+         //   block->pushBackRemoteSameLevelConnectors(remoteInterfaceBlockConns[l]);
+         block->pushBackRemoteInterpolationConnectorsCF(remoteInterConnsCF[l]);
+         block->pushBackRemoteInterpolationConnectorsFC(remoteInterConnsFC[l]);
+      }
+   }
+
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      UBLOG(logDEBUG5, "Calculator2::initRemoteConnectors()-initConnectors(remoteConns["<<l<<"])");
+      initConnectors(remoteConns[l]);
+      if (l != maxLevel)
+      {
+		 for(int i = 0; i < remoteInterConnsCF[l].size(); i++)
+			remoteInterConns[l].push_back(remoteInterConnsCF[l][i]);
+		 for(int i = 0; i < remoteInterConnsFC[l+1].size(); i++)
+	      remoteInterConns[l].push_back(remoteInterConnsFC[l+1][i]);
+       //UBLOG(logDEBUG5, "Calculator2::initRemoteConnectors()-initConnectors(remoteInterConns["<<l<<"])");
+       //initConnectors(remoteInterConns[l]);
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   //UBLOG(logDEBUG5, "Calculator2::initConnectors() - connectoren initialisieren - start");
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator2::initRemoteConnectors()-initConnectors(remoteInterConns["<<l<<"])");
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->init();
+      }
+   }
+   //UBLOG(logDEBUG5, "Calculator2::initConnectors() - connectoren initialisieren - end");
+   //////////////////////////////////////////////////////////////////////////
+   //sendTransmitterDataSize
+   //UBLOG(logDEBUG5, "Calculator2::initConnectors() - sendTransmitterDataSize - start");
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator2::initRemoteConnectors()-sendTransmitterDataSize(remoteInterConns["<<l<<"])");
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->sendTransmitterDataSize();
+      }
+   }
+   //UBLOG(logDEBUG5, "Calculator2::initConnectors() - sendTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+   //receiveTransmitterDataSize
+   //wenn er hier bei verteilten berechnungen stopped, dann ist vermutlich auf einer seite ein nicht aktiver block!!!
+   //UBLOG(logDEBUG5, "Calculator2::initConnectors() - receiveTransmitterDataSize - start");
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator2::initRemoteConnectors()-receiveTransmitterDataSize(remoteInterConns["<<l<<"])");
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->receiveTransmitterDataSize();
+      }
+   }
+   //UBLOG(logDEBUG5, "Calculator2::initConnectors() - receiveTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::initConnectors(std::vector<Block3DConnectorPtr>& connectors)
+{
+   UBLOG(logDEBUG1, "Calculator2::initConnectors() - start");
+
+   //initialization
+   //////////////////////////////////////////////////////////////////////////
+   //initialize connectors
+   UBLOG(logDEBUG5, "Calculator2::initConnectors() - connectoren initialisieren - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->init();
+   UBLOG(logDEBUG5, "Calculator2::initConnectors() - connectoren initialisieren - end");
+   //////////////////////////////////////////////////////////////////////////
+   //sendTransmitterDataSize
+   UBLOG(logDEBUG5, "Calculator2::initConnectors() - sendTransmitterDataSize - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->sendTransmitterDataSize();
+   UBLOG(logDEBUG5, "Calculator2::initConnectors() - sendTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+   //receiveTransmitterDataSize
+   //wenn er hier bei verteilten berechnungen stopped, dann ist vermutlich auf einer seite ein nicht aktiver block!!!
+   UBLOG(logDEBUG5, "Calculator2::initConnectors() - receiveTransmitterDataSize - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->receiveTransmitterDataSize();
+   UBLOG(logDEBUG5, "Calculator2::initConnectors() - receiveTransmitterDataSize - end");
+
+   UBLOG(logDEBUG1, "Calculator2::initConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::exchangeBlockData(int startLevel, int maxInitLevel, bool invStep)
+{
+   sync->wait();
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(localConns[level]);
+      connectorsPrepare(remoteConns[level]);
+
+      connectorsSend(localConns[level], invStep);
+      connectorsSend(remoteConns[level], invStep);
+
+      connectorsReceive(localConns[level], invStep);
+      connectorsReceive(remoteConns[level], invStep);
+   }
+   sync->wait();
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::exchangeInterfaceBlockData(int startLevel, int maxInitLevel, bool invStep)
+{
+   sync->wait();
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(localInterfaceBlockConns[level]);
+      connectorsPrepare(remoteInterfaceBlockConns[level]);
+
+      connectorsSend(localInterfaceBlockConns[level], invStep);
+      connectorsSend(remoteInterfaceBlockConns[level], invStep);
+
+      connectorsReceive(localInterfaceBlockConns[level], invStep);
+      connectorsReceive(remoteInterfaceBlockConns[level], invStep);
+   }
+   sync->wait();
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::swapDistributions(int startLevel, int maxInitLevel)
+{
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->swapDistributions();
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::connectorsPrepare(std::vector< Block3DConnectorPtr >& connectors)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+      c->prepareForReceive();
+      c->prepareForSend();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::connectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+	   c->setInvStep(invStep);
+      c->fillSendVectors();
+      c->sendVectors();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::connectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+	   c->setInvStep(invStep);
+      c->receiveVectors();
+      c->distributeReceiveVectors();
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::connectorsSetInvStep(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+      c->setInvStep(invStep);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::interpolation(int startLevel, int maxInitLevel)
+{
+   sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsPrepare(localInterConns[level]);
+      connectorsPrepare(remoteInterConns[level]);
+   }
+
+   sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsSend(localInterConns[level], true);
+      connectorsSend(remoteInterConns[level], true);
+   }
+
+   sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsReceive(localInterConns[level], true);
+      connectorsReceive(remoteInterConns[level], true);
+   }
+
+   sync->wait();
+
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::setVisScheduler(UbSchedulerPtr s)
+{
+   visScheduler = s;
+}
+//////////////////////////////////////////////////////////////////////////
+//double Calculator2::getCallculationTime()
+//{
+//   return timer.getTotalTime();
+//}
+//////////////////////////////////////////////////////////////////////////
+std::vector< std::vector< Block3DPtr > > Calculator2::getBlocks()
+{
+   return blocks;
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::deleteBlocks()
+{
+   BOOST_FOREACH(std::vector< Block3DPtr > &bs, blocks)
+      bs.resize(0);
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::deleteConnectors()
+{
+   deleteConnectors(localConns);
+   deleteConnectors(remoteConns);
+
+   deleteConnectors(localInterfaceBlockConns);
+   deleteConnectors(remoteInterfaceBlockConns);
+
+   deleteConnectors(localInterConns);
+   deleteConnectors(remoteInterConns);
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::deleteConnectors(std::vector< std::vector< Block3DConnectorPtr > >& conns)
+{
+   BOOST_FOREACH(std::vector< Block3DConnectorPtr > &c, conns)
+      c.resize(0);
+}
+//////////////////////////////////////////////////////////////////////////
+void Calculator2::applyBCs( int startLevel, int maxInitLevel )
+{
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      //call LBM kernel
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->getBCProcessor()->applyBC();
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/Grid/Calculator2.h b/source/VirtualFluidsCore/Grid/Calculator2.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c229963c6f1b9c01cf3b970e2e8a5a23a53d72d
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Calculator2.h
@@ -0,0 +1,78 @@
+#ifndef Calculator2_H
+#define Calculator2_H
+
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "Synchronizer.h"
+#include "MathUtil.hpp"
+#include "basics/utilities/UbScheduler.h"
+#include "basics/utilities/UbTiming.h"
+#include "LoadBalancer.h"
+
+
+class Calculator2;
+typedef boost::shared_ptr<Calculator2> Calculator2Ptr;
+
+#include "CalculationManager.h"
+
+class Calculator2 
+{
+public:
+   Calculator2(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread = true);
+   virtual ~Calculator2(){}
+   void calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error);
+   void addBlock(Block3DPtr block);
+   void initConnectors();
+   void setVisScheduler(UbSchedulerPtr s);
+   //double getCallculationTime();
+   std::vector< std::vector< Block3DPtr > > getBlocks(); 
+   void deleteBlocks();
+   void deleteConnectors();
+protected:
+   void calculateBlocks(int startLevel, int maxInitLevel);
+   void calculateBlocks(int minInitLevel, int maxInitLevel, int staggeredStep);
+   void initConnectors(std::vector<Block3DConnectorPtr>& connectors);
+   void initRemoteConnectors();
+   void swapDistributions(int startLevel, int maxInitLevel);
+   void exchangeBlockData(int startLevel, int maxInitLevel, bool invStep);
+   void exchangeInterfaceBlockData(int startLevel, int maxInitLevel, bool invStep);
+   void connectorsPrepare(std::vector< Block3DConnectorPtr >& connectors);
+   void connectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   void connectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   void connectorsSetInvStep(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   void interpolation(int startLevel, int maxInitLevel);
+   void deleteConnectors(std::vector< std::vector< Block3DConnectorPtr > >& conns);
+   void applyBCs(int startLevel, int maxInitLevel);
+private:
+   boost::barrier* bar;
+   //double time;
+   SynchronizerPtr sync;
+   int minLevel, maxLevel;
+   bool mainThread;
+   bool refinement;
+   Grid3DPtr grid;
+   UbSchedulerPtr visScheduler;
+   int calcStep;
+
+   std::vector< std::vector<Block3DPtr> > blocks;
+   std::vector< std::vector< Block3DConnectorPtr > > localConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteConns;
+
+   std::vector< std::vector< Block3DConnectorPtr > > localInterfaceBlockConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterfaceBlockConns;
+
+   //localInterConns and remoteInterConns save interpolation connectors 
+   //every element save CF connectors for current level and FC connectors for next level
+   //e.g. 
+   //localInterConns[0] = CF(0), FC(1)
+   //localInterConns[1] = CF(1), FC(2)
+   //localInterConns[2] 
+   std::vector< std::vector< Block3DConnectorPtr > > localInterConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConns;
+
+   //UbTimer timer, timer2, timer3;
+   bool loadBalancingComp;
+
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Grid/FastSignal.hpp b/source/VirtualFluidsCore/Grid/FastSignal.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f8d9b0209dca5afc4c7826e67ccab61b0d527c6c
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/FastSignal.hpp
@@ -0,0 +1,46 @@
+#include <list>
+#include <boost/function.hpp>
+
+namespace fast_signal
+{
+   template <class Signature>
+   struct signal: public std::list<boost::function<Signature> >{};
+}
+
+// Abkürzung für die Schleife zum Aufrufen
+#define CALL_SIGNALS( SIG, REF, ARGS )\
+   for( fast_signal::signal<SIG>::iterator it = REF.begin();\
+   it != REF.end(); ++it )\
+   (*it)ARGS;
+
+
+//Eigentlich war das schon alles was wir brauchen um unsere sehr einfache Signal und Slot Implementation zu verwenden. 
+//Die Syntax ist zwar nicht ganz gleich wie bei Boost.Signals aber das sollten wir für die Zeitersparnis verkraften können. 
+//Jetzt also ein einfaches Verwendungsbeispiel:
+//#include <iostream>
+//// ... Code von vorher
+//
+//// Testfunktion zum Registrieren als Slots
+//void test( int& i )
+//{
+//   i += 1;
+//}
+//
+//int main()
+//{
+//   tp_fast_signal::signal<void(int&)> test_signal; // Signal erstellen
+//
+//   // 2 Slots registrieren:
+//   test_signal.push_back(&test);
+//   test_signal.push_back(&test);
+//
+//   int test_int = 0;
+//
+//   // Alle Slots aufrufen
+//   CALL_SIGNALS( void(int&), test_signal, (test_int) );
+//
+//   // Und noch testweise den aktuellen Wert von test_int ausgeben
+//   std::cout << "test_int=" << test_int << std::endl;
+//
+//   return 0;
+//}
diff --git a/source/VirtualFluidsCore/Grid/Grid3D.cpp b/source/VirtualFluidsCore/Grid/Grid3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b22d9667b244e7156e6f01e7f289175e975e940
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Grid3D.cpp
@@ -0,0 +1,1931 @@
+#include "Grid3D.h"
+
+#include <vector>
+#include <boost/foreach.hpp>
+#include <boost/functional/hash.hpp>
+
+#include <basics/writer/WbWriterVtkXmlASCII.h>
+#include "Grid3DVisitor.h"
+#include "Block3DVisitor.h"
+#include "Interactor3D.h"
+#include "Grid3DSystem.h"
+
+
+using namespace std;
+
+Grid3D::Grid3D() : 
+                     rank(0),
+                     bundle(0),
+                     orgDeltaX(1.0),
+                     periodicX1(false),
+                     periodicX2(false),
+                     periodicX3(false),
+                     timeStep(0.0),
+                     blockNx1(0),
+                     blockNx2(0),
+                     blockNx3(0),
+                     nx1(0),
+                     nx2(0),
+                     nx3(0)
+{
+   levelSet.resize(Grid3DSystem::MAXLEVEL+1);
+}
+//////////////////////////////////////////////////////////////////////////
+Grid3D::Grid3D(CommunicatorPtr comm) : 
+   rank(0),
+   bundle(0),
+   orgDeltaX(1.0),
+   periodicX1(false),
+   periodicX2(false),
+   periodicX3(false),
+   timeStep(0.0),
+   blockNx1(0),
+   blockNx2(0),
+   blockNx3(0),
+   nx1(0),
+   nx2(0),
+   nx3(0)
+{
+   levelSet.resize(Grid3DSystem::MAXLEVEL+1);
+   bundle = comm->getBundleID();
+   rank = comm->getProcessID();
+}
+//////////////////////////////////////////////////////////////////////////
+Grid3D::Grid3D( CommunicatorPtr comm, int blockNx1, int blockNx2, int blockNx3, int gridNx1, int gridNx2, int gridNx3 ) : 
+   rank(0),
+   bundle(0),
+   orgDeltaX(1.0),
+   periodicX1(false),
+   periodicX2(false),
+   periodicX3(false),
+   timeStep(0.0),
+   blockNx1(blockNx1),
+   blockNx2(blockNx2),
+   blockNx3(blockNx2),
+   nx1(gridNx1),
+   nx2(gridNx2),
+   nx3(gridNx3)
+{
+   levelSet.resize(Grid3DSystem::MAXLEVEL+1);
+   bundle = comm->getBundleID();
+   rank = comm->getProcessID();
+   trafo = CoordinateTransformation3DPtr(new CoordinateTransformation3D(0.0, 0.0, 0.0, (double)blockNx1, (double)blockNx2, (double)blockNx3));
+   UbTupleInt3 minInd(0, 0, 0);
+   UbTupleInt3 maxInd(gridNx1, gridNx2, gridNx3);
+   this->fillExtentWithBlocks(minInd, maxInd);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::addInteractor(Interactor3DPtr interactor)
+{
+   interactors.push_back(interactor);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::addAndInitInteractor(Interactor3DPtr interactor,double timestep)
+{
+   interactors.push_back(interactor);
+   interactor->initInteractor(timestep);
+}
+//////////////////////////////////////////////////////////////////////////
+Grid3D::Interactor3DSet Grid3D::getInteractors()
+{
+   return interactors;
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::accept(Block3DVisitor& blockVisitor)
+{
+   int startLevel   = blockVisitor.getStartLevel();
+   int stopLevel    = blockVisitor.getStopLevel();
+
+   if(startLevel < 0 || stopLevel < 0 || startLevel > Grid3DSystem::MAXLEVEL || stopLevel > Grid3DSystem::MAXLEVEL) 
+      throw UbException(UB_EXARGS,"not valid level!");
+
+   bool dir     = startLevel < stopLevel;
+   if(dir) stopLevel += 1;
+   else stopLevel    -= 1;
+
+   for(int l=startLevel; l!=stopLevel;)
+   {
+      std::vector<Block3DPtr> blockVector;
+      getBlocks(l, blockVector);
+      BOOST_FOREACH(Block3DPtr b, blockVector)
+      {
+         blockVisitor.visit( shared_from_this(), b );
+      }
+      if(dir)  l++;
+      else     l--;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::accept(Grid3DVisitor& gridVisitor)
+{
+   std::size_t counter =0;
+   gridVisitor.visit( shared_from_this() );
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::accept(Grid3DVisitorPtr gridVisitor)
+{
+   gridVisitor->visit( shared_from_this() );
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::addBlock( Block3DPtr block )
+{
+   if (block)
+   {
+      this->blockIdMap.insert( std::make_pair( block->getGlobalID(), block) );
+      int level = block->getLevel();
+      this->levelSet[level].insert( std::make_pair( Block3DKey( block->getX1(), block->getX2(),  block->getX3() ), block) ).second;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+bool Grid3D::deleteBlock( Block3DPtr block )
+{
+   return this->deleteBlock(block->getX1(), block->getX2(), block->getX3(), block->getLevel());
+}
+//////////////////////////////////////////////////////////////////////////
+bool Grid3D::deleteBlock(int ix1, int ix2, int ix3, int level)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2, ix3, level);
+   if(block) 
+   {
+      this->blockIdMap.erase(block->getGlobalID());
+      return this->levelSet[level].erase( Block3DKey(ix1, ix2, ix3) ) > 0;
+   }
+   else
+   {
+      return false;
+   }
+}	
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::replaceBlock(Block3DPtr block)
+{
+   if (block)
+   {
+      this->deleteBlock(block);
+      this->addBlock(block);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DPtr Grid3D::getBlock( int ix1, int ix2, int ix3, int level ) const
+{
+   if( !this->hasLevel(level) ) return Block3DPtr();
+
+   int N1 = (nx1<<level);
+   int N2 = (nx2<<level);
+   int N3 = (nx3<<level);
+
+   if     (!this->isPeriodicX1() && (ix1>N1-1  || ix1<0)) return Block3DPtr();
+   else if( this->isPeriodicX1() && (ix1>=N1-1 || ix1<0)) { ix1=((ix1%N1)+N1)%N1; }
+   if     (!this->isPeriodicX2() && (ix2>N2-1  || ix2<0)) return Block3DPtr();
+   else if( this->isPeriodicX2() && (ix2>=N2-1 || ix2<0)) { ix2=((ix2%N2)+N2)%N2; }
+   if     (!this->isPeriodicX3() && (ix3>N3-1  || ix3<0)) return Block3DPtr();
+   else if( this->isPeriodicX3() && (ix3>=N3-1 || ix3<0)) { ix3=((ix3%N3)+N3)%N3; }
+
+   Block3DMap::const_iterator it;
+   it = levelSet[level].find( Block3DKey(ix1,ix2,ix3) );
+   if( it == levelSet[level].end() )
+      return Block3DPtr();
+   else
+      return it->second;
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DPtr Grid3D::getBlock(int id) const
+{
+   BlockIDMap::const_iterator it;
+   if( ( it=blockIdMap.find( id ) ) == blockIdMap.end() )
+   {
+      return Block3DPtr();
+   }
+
+   return it->second;
+}
+//////////////////////////////////////////////////////////////////////////
+//const Grid3D::Block3DMap& Grid3D::getBlocks(int level) 
+//{ 
+//   return levelSet[level];
+//}
+//////////////////////////////////////////////////////////////////////////
+const Grid3D::BlockIDMap& Grid3D::getBlockIDs() 
+{ 
+   return blockIdMap;
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DPtr Grid3D::getSuperBlock(Block3DPtr block)
+{
+   int ix1 = block->getX1();
+   int ix2 = block->getX2();
+   int ix3 = block->getX3();
+   int level = block->getLevel();
+   return getSuperBlock(ix1, ix2, ix3, level);
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DPtr Grid3D::getSuperBlock(int ix1, int ix2, int ix3, int level)
+{
+   if(!this->hasLevel(level)) return Block3DPtr();
+   if(level <  1) throw UbException(UB_EXARGS,"level <1");
+   
+   //from Lower Level to higher:	 >> 	1 in x1,x2,x3 
+   Block3DPtr block;
+   for(int l=level-1; l>=0; l--)
+   {
+      ix1 = ix1 >> 1;
+      ix2 = ix2 >> 1;
+      ix3 = ix3 >> 1;
+
+      block = this->getBlock(ix1, ix2, ix3, l);
+      if(block) return block;
+   }
+   return Block3DPtr();
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocks(Block3DPtr block, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   int ix1 = block->getX1();
+   int ix2 = block->getX2();
+   int ix3 = block->getX3();
+   int level = block->getLevel();
+   getSubBlocks(ix1, ix2, ix3, level, levelDepth, blocks);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocks(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   if(!this->getBlock(ix1, ix2, ix3, level)) return;
+   if(level > 0 && !this->getSuperBlock(ix1, ix2, ix3, level)) return;
+   if(level >=  Grid3DSystem::MAXLEVEL)    throw UbException(UB_EXARGS,"Level bigger then MAXLEVEL");
+   
+   int x1[] = { ix1<<1, (ix1<<1)+1 };
+   int x2[] = { ix2<<1, (ix2<<1)+1 };
+   int x3[] = { ix3<<1, (ix3<<1)+1 };
+   int l    = level + 1;
+
+   for(int i=0; i<2; i++)
+      for(int j=0; j<2; j++)
+         for(int k=0; k<2; k++)
+         {
+            Block3DPtr block = this->getBlock(x1[i], x2[j], x3[k], l);
+            if(block) blocks.push_back(block);
+            else if(l < levelDepth) this->getSubBlocks(x1[i], x2[j], x3[k], l, levelDepth, blocks);
+         }
+}
+//////////////////////////////////////////////////////////////////////////
+bool Grid3D::expandBlock(int ix1, int ix2, int ix3, int level)
+{
+   this->checkLevel(level);
+
+   Block3DPtr block = this->getBlock( ix1, ix2, ix3, level );
+   if(!block)             throw UbException(UB_EXARGS,"block(x1="+UbSystem::toString(ix1)+", x2="+UbSystem::toString(ix2)+", x3="+UbSystem::toString(ix3)+", l="+UbSystem::toString(level)+") is not exist");
+   //if(!block->isActive()) throw UbException(UB_EXARGS,"block(x1="+UbSystem::toString(ix1)+", x2="+UbSystem::toString(ix2)+", x3="+UbSystem::toString(ix3)+", l="+UbSystem::toString(level)+") is not active");
+
+   //da bei periodic der eigentliche block andere indizes hat:
+   ix1 = block->getX1();
+   ix2 = block->getX2();
+   ix3 = block->getX3();
+
+   int l      = level+1;
+   if( l>Grid3DSystem::MAXLEVEL ) throw UbException(UB_EXARGS,"level > Grid3D::MAXLEVEL");
+
+   int west   = ix1<<1;
+   int east   = west+1;
+   int south  = ix2<<1;
+   int north  = south+1;
+   int bottom = ix3<<1;
+   int top    = bottom+1;
+
+   Block3DPtr blockBSW = Block3DPtr(new Block3D(west, south, bottom, l));
+   Block3DPtr blockBSE = Block3DPtr(new Block3D(east, south, bottom, l));
+   Block3DPtr blockBNW = Block3DPtr(new Block3D(west, north, bottom, l));
+   Block3DPtr blockBNE = Block3DPtr(new Block3D(east, north, bottom, l));
+   Block3DPtr blockTSW = Block3DPtr(new Block3D(west, south, top   , l));
+   Block3DPtr blockTSE = Block3DPtr(new Block3D(east, south, top   , l));
+   Block3DPtr blockTNW = Block3DPtr(new Block3D(west, north, top   , l));
+   Block3DPtr blockTNE = Block3DPtr(new Block3D(east, north, top   , l));
+
+   if( !this->deleteBlock( ix1, ix2, ix3, level ) )
+      throw UbException(UB_EXARGS,"could not delete block");
+
+   this->addBlock(blockBSW);
+   this->addBlock(blockBSE);
+   this->addBlock(blockBNW);
+   this->addBlock(blockBNE);
+   this->addBlock(blockTSW);
+   this->addBlock(blockTSE);
+   this->addBlock(blockTNW);
+   this->addBlock(blockTNE);
+
+   return true;
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DPtr Grid3D::collapseBlock(int fix1, int fix2, int fix3, int flevel, int levelDepth)
+{
+   using UbSystem::toString;
+
+   Block3DPtr fblock = this->getBlock(fix1, fix2, fix3, flevel);
+   if( flevel <  1         ) throw UbException(UB_EXARGS,"level of block ("+toString(fix1)+","+toString(fix2)+","+toString(fix3)+","+toString(flevel)+") is < 1");
+   if( !fblock             ) throw UbException(UB_EXARGS,"specific block("+toString(fix1)+","+toString(fix2)+","+toString(fix3)+","+toString(flevel)+") doesn't exists");
+   if( !fblock->isActive() ) throw UbException(UB_EXARGS,"block("+toString(fix1)+","+toString(fix2)+","+toString(fix3)+","+toString(flevel)+") is not active");
+
+   //da bei periodic der eigentliche block andere indizes hat:
+   fix1 = fblock->getX1();
+   fix2 = fblock->getX2();
+   fix3 = fblock->getX3();
+
+   int cix1 = fblock->getX1() >> 1;
+   int cix2 = fblock->getX2() >> 1;
+   int cix3 = fblock->getX3() >> 1;
+
+   int fx1[2] = { cix1<<1,  (cix1<<1)+1 };
+   int fx2[2] = { cix2<<1,  (cix2<<1)+1 };
+   int fx3[2] = { cix3<<1,  (cix3<<1)+1 };
+   int clevel = flevel - 1;
+
+   vector<Block3DPtr> blocks;
+   for(int i=0; i<2; i++)
+      for(int k=0; k<2; k++)
+         for(int l=0; l<2; l++)
+         {
+            this->getSubBlocks(fx1[k], fx2[i], fx3[l], flevel, levelDepth, blocks);
+            while(!blocks.empty())
+            {
+               //man muss nur eine von den moeglichen acht "collapsen", die anderen werden
+               //dann (rekursiv) collapsed, da die schleife oben alle vier abfragt
+               this->collapseBlock(blocks[0]->getX1(), blocks[0]->getX2(), blocks[0]->getX3(), blocks[0]->getLevel(), levelDepth);
+               this->getSubBlocks(fx1[k], fx2[i], fx3[l], flevel, levelDepth, blocks);
+            }
+         }
+
+         vector<Block3DPtr> fineBlocks(8);
+         /*BSW*/fineBlocks[0] = this->getBlock( fx1[0], fx2[0], fx3[0], flevel );
+         /*BSE*/fineBlocks[1] = this->getBlock( fx1[1], fx2[0], fx3[0], flevel );
+         /*BNE*/fineBlocks[2] = this->getBlock( fx1[1], fx2[1], fx3[0], flevel );
+         /*BNW*/fineBlocks[3] = this->getBlock( fx1[0], fx2[1], fx3[0], flevel );
+         /*TSW*/fineBlocks[4] = this->getBlock( fx1[0], fx2[0], fx3[1], flevel );
+         /*TSE*/fineBlocks[5] = this->getBlock( fx1[1], fx2[0], fx3[1], flevel );
+         /*TNE*/fineBlocks[6] = this->getBlock( fx1[1], fx2[1], fx3[1], flevel );
+         /*TNW*/fineBlocks[7] = this->getBlock( fx1[0], fx2[1], fx3[1], flevel );
+
+         Block3DPtr cblock = Block3DPtr(new Block3D(cix1, cix2, cix3, clevel));
+
+         for(int i=0; i<2; i++)
+            for(int k=0; k<2; k++)
+               for(int l=0; l<2; l++)
+                  if( !this->deleteBlock( fx1[k], fx2[i], fx3[l], flevel ) )
+                     throw UbException(UB_EXARGS,"could not delete block");
+
+         this->addBlock(cblock);
+
+         return cblock;
+}
+//////////////////////////////////////////////////////////////////////////
+// TODO: make visitor for this
+void Grid3D::deleteConnectors()
+{
+   BOOST_FOREACH(Block3DMap blockMap, levelSet)
+   {
+      BOOST_FOREACH(Block3DMap::value_type b, blockMap)
+      {
+         Block3DPtr block =  b.second;
+         block->deleteConnectors();
+         //block->deleteInterpolationConnectors();
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+Grid3D::connection_t Grid3D::connect(Grid3D::signal_t::slot_function_type subscriber)
+{
+   return sig.connect(subscriber);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::disconnect(Grid3D::connection_t subscriber)
+{
+   subscriber.disconnect();
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::doPostProcess(double step)
+{
+   timeStep = step;
+   sig(step);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setRank(int rank)
+{
+   this->rank = rank;
+}
+//////////////////////////////////////////////////////////////////////////
+int Grid3D::getRank() const
+{
+   return rank;
+}
+//////////////////////////////////////////////////////////////////////////
+int  Grid3D::getBundle() const          
+{ 
+   return bundle;       
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setBundle(int bundle) 
+{ 
+   this->bundle = bundle; 
+} 
+//////////////////////////////////////////////////////////////////////////
+bool Grid3D::isPeriodicX1() const 
+{ 
+   return this->periodicX1; 
+}
+//////////////////////////////////////////////////////////////////////////
+bool Grid3D::isPeriodicX2() const 
+{ 
+   return this->periodicX2; 
+}
+//////////////////////////////////////////////////////////////////////////
+bool Grid3D::isPeriodicX3() const 
+{ 
+   return this->periodicX3; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setPeriodicX1(bool value)
+{
+   this->periodicX1 = value;
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setPeriodicX2(bool value)
+{
+   this->periodicX2 = value;
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setPeriodicX3(bool value)
+{
+   this->periodicX3 = value;
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleInt3 Grid3D::getBlockIndexes(double blockX1Coord, double blockX2Coord, double blockX3Coord)  const
+{
+   if(!trafo)
+   {
+      return makeUbTuple( (int)blockX1Coord, (int)blockX2Coord, (int)blockX3Coord );
+   }
+
+   return makeUbTuple(  (int)trafo->transformForwardToX1Coordinate( blockX1Coord, blockX2Coord, blockX3Coord )
+      , (int)trafo->transformForwardToX2Coordinate( blockX1Coord, blockX2Coord, blockX3Coord )
+      , (int)trafo->transformForwardToX3Coordinate( blockX1Coord, blockX2Coord, blockX3Coord ) );
+
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleInt3 Grid3D::getBlockIndexes(double blockX1Coord, double blockX2Coord, double blockX3Coord, int level)  const
+{
+   if(!trafo)
+   {
+      return makeUbTuple( (int)blockX1Coord, (int)blockX2Coord, (int)blockX3Coord );
+   }
+
+   double dx = getDeltaX(level);
+   double blockLentghX1, blockLentghX2, blockLentghX3; 
+   blockLentghX1 = blockNx1*dx;
+   blockLentghX2 = blockNx2*dx;
+   blockLentghX3 = blockNx3*dx;
+   UbTupleDouble3 org = getBlockWorldCoordinates(0, 0, 0, 0);
+
+   CoordinateTransformation3DPtr trafo_temp(new CoordinateTransformation3D(val<1>(org),val<2>(org),val<3>(org),blockLentghX1,blockLentghX2,blockLentghX3));
+
+   if(!trafo_temp)
+   {
+      return makeUbTuple( (int)blockX1Coord, (int)blockX2Coord, (int)blockX3Coord );
+   }
+
+   return makeUbTuple(  (int)trafo_temp->transformForwardToX1Coordinate( blockX1Coord, blockX2Coord, blockX3Coord )
+      , (int)trafo_temp->transformForwardToX2Coordinate( blockX1Coord, blockX2Coord, blockX3Coord )
+      , (int)trafo_temp->transformForwardToX3Coordinate( blockX1Coord, blockX2Coord, blockX3Coord ) );
+
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleDouble3  Grid3D::getBlockLengths(const Block3DPtr block) const
+{
+   int    level = block->getLevel();
+   double delta = 1.0/(double)(1<<level);
+
+   if(!trafo) makeUbTuple<double, double, double>(delta,delta,delta);
+
+   return makeUbTuple(   trafo->getX1CoordinateScaling()*delta,
+                                                       trafo->getX2CoordinateScaling()*delta,
+                                                       trafo->getX3CoordinateScaling()*delta );
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleDouble6 Grid3D::getBlockOversize() const 
+{ 
+   return makeUbTuple(0.0,0.0,0.0,0.0,0.0,0.0); 
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setCoordinateTransformator(CoordinateTransformation3DPtr trafo)
+{
+   this->trafo = trafo;
+}
+//////////////////////////////////////////////////////////////////////////
+const CoordinateTransformation3DPtr Grid3D::getCoordinateTransformator() const 
+{ 
+   return this->trafo; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setDeltaX(double dx)
+{
+   this->orgDeltaX = dx;
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setDeltaX(double worldUnit, double gridUnit)
+{
+   this->orgDeltaX = worldUnit/gridUnit;
+}
+//////////////////////////////////////////////////////////////////////////
+double Grid3D::getDeltaX(int level) const 
+{ 
+   double delta = this->orgDeltaX/(double)(1<<level);
+   return delta; 
+}
+//////////////////////////////////////////////////////////////////////////
+double Grid3D::getDeltaX(Block3DPtr block) const 
+{ 
+   return getDeltaX(block->getLevel()); 
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleDouble3  Grid3D::getNodeOffset(Block3DPtr block) const 
+{ 
+   double delta = this->getDeltaX(block);
+   return makeUbTuple(0.5*delta,0.5*delta,0.5*delta);
+}
+////////////////////////////////////////////////////////////////////////////
+UbTupleDouble3 Grid3D::getNodeCoordinates(Block3DPtr block, int ix1, int ix2, int ix3) const
+{
+   UbTupleDouble3 org = this->getBlockWorldCoordinates(block);
+   UbTupleDouble3 nodeOffset = this->getNodeOffset(block);
+   double deltaX = getDeltaX(block);
+
+   double x1 = val<1>(org) - val<1>(nodeOffset) + (double)ix1*deltaX;
+   double x2 = val<2>(org) - val<2>(nodeOffset) + (double)ix2*deltaX;
+   double x3 = val<3>(org) - val<3>(nodeOffset) + (double)ix3*deltaX;
+
+   return makeUbTuple(x1, x2, x3);
+}
+////////////////////////////////////////////////////////////////////////////
+UbTupleInt3 Grid3D::getNodeIndexes(Block3DPtr block, double nodeX1Coord, double nodeX2Coord, double nodeX3Coord) const
+{
+   UbTupleDouble3 org = this->getBlockWorldCoordinates(block);
+   UbTupleDouble3 nodeOffset = this->getNodeOffset(block);
+   double deltaX = getDeltaX(block);
+
+   int ix1,ix2,ix3;
+   double ixx1=(abs(nodeX1Coord - val<1>(org) + val<1>(nodeOffset)) / deltaX);
+   double ixx2=(abs(nodeX2Coord - val<2>(org) + val<2>(nodeOffset)) / deltaX);
+   double ixx3=(abs(nodeX3Coord - val<3>(org) + val<3>(nodeOffset)) / deltaX);
+   if (ixx1-(int)ixx1>.9999999999) ix1=(int)ixx1+1;else ix1=(int)ixx1; 
+   if (ixx2-(int)ixx2>.9999999999) ix2=(int)ixx2+1;else ix2=(int)ixx2; 
+   if (ixx3-(int)ixx3>.9999999999) ix3=(int)ixx3+1;else ix3=(int)ixx3; 
+
+   return makeUbTuple(ix1, ix2, ix3);
+}
+//////////////////////////////////////////////////////////////////////////
+//returns tuple with origin of block in world-coordinates
+UbTupleDouble3 Grid3D::getBlockWorldCoordinates(Block3DPtr block) const
+{
+   if(!block)
+      throw UbException(UB_EXARGS,"block " + block->toString() + "is not exist");
+
+   int blockX1Index = block->getX1();
+   int blockX2Index = block->getX2();
+   int blockX3Index = block->getX3();
+   int level = block->getLevel();
+
+   return this->getBlockWorldCoordinates(blockX1Index, blockX2Index, blockX3Index, level);
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleDouble3 Grid3D::getBlockWorldCoordinates(int blockX1Index, int blockX2Index, int blockX3Index, int level) const
+{
+   double c1oShiftedLevel = 1.0/(double)(1<<level);
+   double x1 = (double)blockX1Index*c1oShiftedLevel;
+   double x2 = (double)blockX2Index*c1oShiftedLevel;
+   double x3 = (double)blockX3Index*c1oShiftedLevel;
+
+   if(!trafo) return UbTupleDouble3( x1,x2,x3 );
+
+   return UbTupleDouble3( trafo->transformBackwardToX1Coordinate( x1,x2,x3 )
+      ,trafo->transformBackwardToX2Coordinate( x1,x2,x3 )
+      ,trafo->transformBackwardToX3Coordinate( x1,x2,x3 ) );
+}
+//////////////////////////////////////////////////////////////////////////
+//double Grid3D::getDeltaT(Block3DPtr block) const 
+//{ 
+//   int    level = block->getLevel();
+//   double delta = 1.0/(double)(1<<level);
+//   return delta; 
+//}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::checkLevel(int level)
+{
+   if(level < 0)
+   {
+      throw UbException(UB_EXARGS,"l("+UbSystem::toString(level)+(string)")<0");
+   }
+   if(level > Grid3DSystem::MAXLEVEL)
+   {
+      throw UbException(UB_EXARGS,"l("+UbSystem::toString(level)+(string)")>MAXLEVEL");
+   }
+   if(this->levelSet[level].size() == 0)
+   {
+      throw UbException(UB_EXARGS,"levelMap for level("+UbSystem::toString(level)+(string)")==NULL");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+bool Grid3D::hasLevel(int level) const
+{
+   if(level < 0                        ) return false;
+   if(level > Grid3DSystem::MAXLEVEL                 ) return false;
+   if(this->levelSet[level].size() == 0) return false;
+
+   return true;
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setBlockNX( int nx1, int nx2, int nx3 )
+{
+   blockNx1 = nx1;    
+   blockNx2 = nx2;    
+   blockNx3 = nx3; 
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleInt3 Grid3D::getBlockNX() const
+{
+   return makeUbTuple(blockNx1, blockNx2, blockNx3);
+}
+//////////////////////////////////////////////////////////////////////////
+
+Block3DPtr Grid3D::getNeighborBlock( int dir, int ix1, int ix2, int ix3, int level ) const
+{
+   return this->getBlock(  ix1+Grid3DSystem::EX1[dir], ix2+Grid3DSystem::EX2[dir], ix3+Grid3DSystem::EX3[dir], level );
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DPtr Grid3D::getNeighborBlock(int dir, Block3DPtr block) const
+{
+   int x1 = block->getX1();
+   int x2 = block->getX2();
+   int x3 = block->getX3();
+   int level = block->getLevel();
+   return this->getNeighborBlock( dir, x1, x2, x3, level);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getAllNeighbors(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   for(int dir=Grid3DSystem::STARTDIR; dir<=Grid3DSystem::ENDDIR; dir++)
+   //for (int dir = Grid3DSystem::STARTDIR; dir<=Grid3DSystem::TS; dir++)
+   {
+      this->getNeighborBlocksForDirection(dir,ix1,ix2,ix3,level,levelDepth,blocks);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getAllNeighbors(Block3DPtr block, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   int x1 = block->getX1();
+   int x2 = block->getX2();
+   int x3 = block->getX3();
+   getAllNeighbors(x1,x2,x3,level,levelDepth,blocks);
+}
+//////////////////////////////////////////////////////////////////////////
+  /**
+   * Returns all direct northern neighbor cells of the specified grid cell (may be NULL!).
+   * @param ix1 index in x1 direction
+   * @param ix2 index in x2 direction
+   * @param ix3 index in x3 direction
+   * @param level the level
+   */
+void Grid3D::getNeighborsNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+	Block3DPtr block = this->getBlock(ix1, ix2+1, ix3, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2+1, ix3, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksSouth(ix1, ix2+1, ix3, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTop(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottom(ix1, ix2, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottom(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+
+   }
+   this->getSubBlocksTop(ix1, ix2, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2-1, ix3, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2-1, ix3, level);
+      if(block) { blocks.push_back(block); }
+
+   }
+   this->getSubBlocksNorth(ix1, ix2-1, ix3, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+	Block3DPtr block = this->getBlock(ix1+1, ix2, ix3, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2, ix3, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksWest(ix1+1, ix2, ix3, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2, ix3, level);
+   if(block) { blocks.push_back(block);  }
+
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2, ix3, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksEast(ix1-1, ix2, ix3, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+//   diagonals                                            
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1+1, ix2+1, ix3, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2+1, ix3, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksSouthWest(ix1+1, ix2+1, ix3, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2+1, ix3, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2+1, ix3, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksSouthEast(ix1-1, ix2+1, ix3, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1+1, ix2-1, ix3, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2-1, ix3, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksNorthWest(ix1+1, ix2-1, ix3, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2-1, ix3, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2-1, ix3, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksNorthEast(ix1-1, ix2-1, ix3, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+//   diagonals  top                                     
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTopEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1+1, ix2, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottomWest(ix1+1, ix2, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTopWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottomEast(ix1-1, ix2, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTopNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2+1, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2+1, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottomSouth(ix1, ix2+1, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTopSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2-1, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2-1, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottomNorth(ix1, ix2-1, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+//   diagonals  bottom                                
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottomEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1+1, ix2, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksTopWest(ix1+1, ix2, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottomWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksTopEast(ix1-1, ix2, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottomNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2+1, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2+1, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksTopSouth(ix1, ix2+1, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottomSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2-1, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2-1, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksTopNorth(ix1, ix2-1, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTopNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1+1, ix2+1, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2+1, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottomSouthWest(ix1+1, ix2+1, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTopNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2+1, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2+1, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottomSouthEast(ix1-1, ix2+1, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTopSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1+1, ix2-1, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2-1, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottomNorthWest(ix1+1, ix2-1, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsTopSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2-1, ix3+1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2-1, ix3+1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksBottomNorthEast(ix1-1, ix2-1, ix3+1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottomNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1+1, ix2+1, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2+1, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksTopSouthWest(ix1+1, ix2+1, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottomNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2+1, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2+1, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksTopSouthEast(ix1-1, ix2+1, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottomSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1+1, ix2-1, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1+1, ix2-1, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksTopNorthWest(ix1+1, ix2-1, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsBottomSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1-1, ix2-1, ix3-1, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1-1, ix2-1, ix3-1, level);
+      if(block) { blocks.push_back(block); }
+   }
+   this->getSubBlocksTopNorthEast(ix1-1, ix2-1, ix3-1, level, blocks, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborBlocksForDirection(int dir, int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   switch(dir)
+   {
+   case Grid3DSystem::E  : this->getNeighborsEast(ix1, ix2, ix3, level,levelDepth, blocks);break;
+   case Grid3DSystem::W  : this->getNeighborsWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::N  : this->getNeighborsNorth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::S  : this->getNeighborsSouth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::T  : this->getNeighborsTop(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::B  : this->getNeighborsBottom(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::NE : this->getNeighborsNorthEast(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::SW : this->getNeighborsSouthWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::SE : this->getNeighborsSouthEast(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::NW : this->getNeighborsNorthWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TE : this->getNeighborsTopEast(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::BW : this->getNeighborsBottomWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::BE : this->getNeighborsBottomEast(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TW : this->getNeighborsTopWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TN : this->getNeighborsTopNorth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::BS : this->getNeighborsBottomSouth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::BN : this->getNeighborsBottomNorth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TS : this->getNeighborsTopSouth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TNE: this->getNeighborsTopNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::TNW: this->getNeighborsTopNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::TSE: this->getNeighborsTopSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::TSW: this->getNeighborsTopSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::BNE: this->getNeighborsBottomNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::BNW: this->getNeighborsBottomNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::BSE: this->getNeighborsBottomSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::BSW: this->getNeighborsBottomSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   default:throw UbException(UB_EXARGS,"direction "+UbSystem::toString(dir)+" is not exist");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborsZero(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   Block3DPtr block = this->getBlock(ix1, ix2, ix3, level);
+   if(block) { blocks.push_back(block); }
+
+   if(level > 0)
+   {
+      block = this->getSuperBlock(ix1, ix2, ix3, level);
+      if(block) { blocks.push_back(block); }
+   }
+   // this->getSubBlocksNull(ix1, ix2, ix3, level, blocks, levelDepth);
+   this->getSubBlocks(ix1, ix2, ix3, level, levelDepth, blocks);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksZero(int ix1, int ix2, int ix3, int level,vector<Block3DPtr> &blockVector, int levelDepth)
+{
+   int x1E  = (ix1 << 1) + 1;
+   int x1W  = (ix1 << 1) ;
+   int x2S = ix2 << 1;
+   int x2N = x2S + 1;
+   int x3B = ix3 << 1;
+   int x3T = x3B + 1;
+   int l   = level + 1;
+
+   Block3DPtr block = this->getBlock(x1E, x2S, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1E, x2S, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2N, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1E, x2N, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2S, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1E, x2S, x3T, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2N, x3T, l);
+   if(block != NULL)      blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1E, x2N, x3T, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1W, x2S, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1W, x2S, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1W, x2N, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1W, x2N, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1W, x2S, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1W, x2S, x3T, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1W, x2N, x3T, l);
+   if(block != NULL)      blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1W, x2N, x3T, l, blockVector,levelDepth);  
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getNeighborBlocksForDirectionWithDirZero(int dir, int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks)
+{
+   switch(dir)
+   {
+   case Grid3DSystem::E  : this->getNeighborsEast(ix1, ix2, ix3, level,levelDepth, blocks);break;
+   case Grid3DSystem::W  : this->getNeighborsWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::N  : this->getNeighborsNorth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::S  : this->getNeighborsSouth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::T  : this->getNeighborsTop(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::B  : this->getNeighborsBottom(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::NE : this->getNeighborsNorthEast(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::SW : this->getNeighborsSouthWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::SE : this->getNeighborsSouthEast(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::NW : this->getNeighborsNorthWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TE : this->getNeighborsTopEast(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::BW : this->getNeighborsBottomWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::BE : this->getNeighborsBottomEast(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TW : this->getNeighborsTopWest(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TN : this->getNeighborsTopNorth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::BS : this->getNeighborsBottomSouth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::BN : this->getNeighborsBottomNorth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TS : this->getNeighborsTopSouth(ix1, ix2, ix3, level,levelDepth, blocks); break;
+   case Grid3DSystem::TNE: this->getNeighborsTopNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::TNW: this->getNeighborsTopNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::TSE: this->getNeighborsTopSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::TSW: this->getNeighborsTopSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::BNE: this->getNeighborsBottomNorthEast(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::BNW: this->getNeighborsBottomNorthWest(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::BSE: this->getNeighborsBottomSouthEast(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::BSW: this->getNeighborsBottomSouthWest(ix1, ix2, ix3, level, levelDepth, blocks); break;
+   case Grid3DSystem::ZERO: this->getNeighborsZero(ix1, ix2, ix3, level,levelDepth, blocks);break;
+   default:throw UbException(UB_EXARGS,"direction "+UbSystem::toString(dir)+" is not exist");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksEast(int ix1, int ix2, int ix3, int level,vector<Block3DPtr> &blockVector, int levelDepth)
+{
+   int x1  = (ix1 << 1) + 1;
+   int x2S = ix2 << 1;
+   int x2N = x2S + 1;
+   int x3B = ix3 << 1;
+   int x3T = x3B + 1;
+   int l   = level + 1;
+
+   Block3DPtr block = this->getBlock(x1, x2S, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1, x2S, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1, x2N, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1, x2N, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1, x2S, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1, x2S, x3T, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1, x2N, x3T, l);
+   if(block != NULL)      blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksEast(x1, x2N, x3T, l, blockVector,levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksWest(int ix1, int ix2, int ix3, int level,vector<Block3DPtr> &blockVector, int levelDepth)
+{
+   int x1  = ix1 << 1;
+   int x2S = ix2 << 1;
+   int x2N = x2S + 1;
+   int x3B = ix3 << 1;
+   int x3T = x3B + 1;
+   int l   = level + 1;
+
+   Block3DPtr block = this->getBlock(x1, x2S, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksWest(x1, x2S, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1, x2N, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksWest(x1, x2N, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1, x2S, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksWest(x1, x2S, x3T, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1, x2N, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksWest(x1, x2N, x3T, l, blockVector,levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksNorth(int ix1, int ix2, int ix3, int level,vector<Block3DPtr> &blockVector, int levelDepth)
+{
+   int x1W = ix1 << 1;
+   int x1E = x1W + 1;
+   int x2  = (ix2 << 1) + 1;
+   int x3B = ix3 << 1;
+   int x3T = x3B + 1;
+   int l   = level + 1;
+
+   Block3DPtr block = this->getBlock(x1W, x2, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksNorth(x1W, x2, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2, x3B, l);
+   if(block != NULL)      blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksNorth(x1E, x2, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1W, x2, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksNorth(x1W, x2, x3T, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksNorth(x1E, x2, x3T, l, blockVector,levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksSouth(int ix1, int ix2, int ix3, int level,vector<Block3DPtr> &blockVector, int levelDepth)
+{
+   int x1W = ix1 << 1;
+   int x1E = x1W + 1;
+   int x2  = ix2 << 1;
+   int x3B = ix3 << 1;
+   int x3T = x3B + 1;
+   int l   = level + 1;
+
+   Block3DPtr block = this->getBlock(x1W, x2, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksSouth(x1W, x2, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2, x3B, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksSouth(x1E, x2, x3B, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1W, x2, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksSouth(x1W, x2, x3T, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2, x3T, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksSouth(x1E, x2, x3T, l, blockVector,levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTop(int ix1, int ix2, int ix3, int level,vector<Block3DPtr> &blockVector, int levelDepth)
+{
+   int x1W = ix1 << 1;
+   int x1E = x1W + 1;
+   int x2S = ix2 << 1;
+   int x2N = x2S + 1;
+   int x3  = (ix3 << 1) + 1;
+   int l   = level + 1;
+
+   Block3DPtr block = this->getBlock(x1W, x2N, x3, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksTop(x1W, x2N, x3, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2N, x3, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksTop(x1E, x2N, x3, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1W, x2S, x3, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksTop(x1W, x2S, x3, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2S, x3, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksTop(x1E, x2S, x3, l, blockVector,levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottom(int ix1, int ix2, int ix3, int level,vector<Block3DPtr> &blockVector, int levelDepth)
+{
+   int x1W = ix1 << 1;
+   int x1E = x1W + 1;
+   int x2S = ix2 << 1;
+   int x2N = x2S + 1;
+   int x3  = ix3 << 1;
+   int l   = level + 1;
+
+   Block3DPtr block = this->getBlock(x1W, x2N, x3, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksBottom(x1W, x2N, x3, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2N, x3, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksBottom(x1E, x2N, x3, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1W, x2S, x3, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksBottom(x1W, x2S, x3, l, blockVector,levelDepth);
+
+   block = this->getBlock(x1E, x2S, x3, l);
+   if(block != NULL)       blockVector.push_back(block);
+   else if(l < levelDepth) this->getSubBlocksBottom(x1E, x2S, x3, l, blockVector,levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+//  diagonals
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksNorthEast(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1  = (ix1 << 1) + 1;
+   int x2  = (ix2 << 1) + 1;
+   int x3B = (ix3 << 1);
+   int x3T = x3B+1;
+   int l   = level + 1;
+
+   Block3DPtr blockB = this->getBlock(x1, x2, x3B, l);
+   if(blockB) blockVector.push_back(blockB);
+   else if(l < levelDepth) this->getSubBlocksNorthEast(x1, x2, x3B, l, blockVector, levelDepth);
+
+   Block3DPtr blockT = this->getBlock(x1, x2, x3T, l);
+   if(blockT) blockVector.push_back(blockT);
+   else if(l < levelDepth) this->getSubBlocksNorthEast(x1, x2, x3T, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksNorthWest(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1  = (ix1 << 1);
+   int x2  = (ix2 << 1) + 1;
+   int x3B = (ix3 << 1);
+   int x3T = x3B+1;
+   int l   = level + 1;
+
+   Block3DPtr blockB = this->getBlock(x1, x2,x3B, l);
+   if(blockB) blockVector.push_back(blockB);
+   else if(l < levelDepth) this->getSubBlocksNorthWest(x1, x2, x3B, l, blockVector, levelDepth);
+
+   Block3DPtr blockT = this->getBlock(x1, x2,x3T, l);
+   if(blockT) blockVector.push_back(blockT);
+   else if(l < levelDepth) this->getSubBlocksNorthWest(x1, x2, x3T, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksSouthWest(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1  = ix1 << 1;
+   int x2  = ix2 << 1;
+   int x3B = (ix3 << 1);
+   int x3T = x3B+1;
+   int l  = level + 1;
+
+   Block3DPtr blockB = this->getBlock(x1, x2,x3B, l);
+   if(blockB) blockVector.push_back(blockB);
+   else if(l < levelDepth) this->getSubBlocksSouthWest(x1, x2, x3B, l, blockVector, levelDepth);
+
+   Block3DPtr blockT = this->getBlock(x1, x2,x3T, l);
+   if(blockT) blockVector.push_back(blockT);
+   else if(l < levelDepth) this->getSubBlocksSouthWest(x1, x2, x3T, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksSouthEast(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1  = (ix1 << 1) + 1;
+   int x2  = ix2 << 1;
+   int x3B = (ix3 << 1);
+   int x3T = x3B+1;
+   int l   = level + 1;
+
+   Block3DPtr blockB = this->getBlock(x1, x2,x3B, l);
+   if(blockB) blockVector.push_back(blockB);
+   else if(l < levelDepth) this->getSubBlocksSouthEast(x1, x2, x3B, l, blockVector, levelDepth);
+
+   Block3DPtr blockT = this->getBlock(x1, x2,x3T, l);
+   if(blockT) blockVector.push_back(blockT);
+   else if(l < levelDepth) this->getSubBlocksSouthEast(x1, x2, x3T, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+//  diagonals
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTopEast(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1  = (ix1 << 1) + 1;
+   int x2S = (ix2 << 1);
+   int x2N = x2S + 1;
+   int x3  = (ix3 << 1)+1;
+   int l   = level + 1;
+
+   Block3DPtr blockN = this->getBlock(x1, x2N, x3, l);
+   if(blockN) blockVector.push_back(blockN);
+   else if(l < levelDepth) this->getSubBlocksTopEast(x1, x2N, x3, l, blockVector, levelDepth);
+
+   Block3DPtr blockS = this->getBlock(x1, x2S, x3, l);
+   if(blockS) blockVector.push_back(blockS);
+   else if(l < levelDepth) this->getSubBlocksTopEast(x1, x2S, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTopWest(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1  = ix1 << 1;
+   int x2S = ix2 << 1;
+   int x2N = x2S + 1;
+   int x3  = (ix3 << 1)+1;
+   int l   = level + 1;
+
+   Block3DPtr blockN = this->getBlock(x1, x2N, x3, l);
+   if(blockN) blockVector.push_back(blockN);
+   else if(l < levelDepth) this->getSubBlocksTopEast(x1, x2N, x3, l, blockVector, levelDepth);
+
+   Block3DPtr blockS = this->getBlock(x1, x2S, x3, l);
+   if(blockS) blockVector.push_back(blockS);
+   else if(l < levelDepth) this->getSubBlocksTopEast(x1, x2S, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottomEast(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1  = (ix1 << 1) + 1;
+   int x2S = ix2 << 1;
+   int x2N = x2S + 1;
+   int x3  = ix3 << 1;
+   int l   = level + 1;
+
+   Block3DPtr blockN = this->getBlock(x1, x2N, x3, l);
+   if(blockN) blockVector.push_back(blockN);
+   else if(l < levelDepth) this->getSubBlocksTopEast(x1, x2N, x3, l, blockVector, levelDepth);
+
+   Block3DPtr blockS = this->getBlock(x1, x2S, x3, l);
+   if(blockS) blockVector.push_back(blockS);
+   else if(l < levelDepth) this->getSubBlocksTopEast(x1, x2S, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottomWest(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1  = (ix1 << 1);
+   int x2S = (ix2 << 1);
+   int x2N = x2S + 1;
+   int x3  = ix3 << 1;
+   int l   = level + 1;
+
+   Block3DPtr blockN = this->getBlock(x1, x2N, x3, l);
+   if(blockN) blockVector.push_back(blockN);
+   else if(l < levelDepth) this->getSubBlocksTopEast(x1, x2N, x3, l, blockVector, levelDepth);
+
+   Block3DPtr blockS = this->getBlock(x1, x2S, x3, l);
+   if(blockS) blockVector.push_back(blockS);
+   else if(l < levelDepth) this->getSubBlocksTopEast(x1, x2S, x3, l, blockVector, levelDepth);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//  edge-diagonals
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTopNorth(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1E = (ix1 << 1);
+   int x1W = x1E + 1;
+   int x2  = (ix2 << 1)+1;
+   int x3  = (ix3 << 1)+1;
+   int l   = level + 1;
+
+   Block3DPtr blockE = this->getBlock(x1E, x2, x3, l);
+   if(blockE) blockVector.push_back(blockE);
+   else if(l < levelDepth) this->getSubBlocksTopNorth(x1E, x2, x3, l, blockVector, levelDepth);
+
+   Block3DPtr blockW = this->getBlock(x1W, x2, x3, l);
+   if(blockW) blockVector.push_back(blockW);
+   else if(l < levelDepth) this->getSubBlocksTopNorth(x1W, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTopSouth(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1E = (ix1 << 1);
+   int x1W = x1E + 1;
+   int x2  = (ix2 << 1);
+   int x3  = (ix3 << 1)+1;
+   int l   = level + 1;
+
+   Block3DPtr blockE = this->getBlock(x1E, x2, x3, l);
+   if(blockE) blockVector.push_back(blockE);
+   else if(l < levelDepth) this->getSubBlocksTopSouth(x1E, x2, x3, l, blockVector, levelDepth);
+
+   Block3DPtr blockW = this->getBlock(x1W, x2, x3, l);
+   if(blockW) blockVector.push_back(blockW);
+   else if(l < levelDepth) this->getSubBlocksTopSouth(x1W, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottomNorth(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1E = ix1 << 1;
+   int x1W = x1E + 1;
+   int x2  = (ix2 << 1)+1;
+   int x3  = ix3 << 1;
+   int l   = level + 1;
+
+   Block3DPtr blockE = this->getBlock(x1E, x2, x3, l);
+   if(blockE) blockVector.push_back(blockE);
+   else if(l < levelDepth) this->getSubBlocksBottomNorth(x1E, x2, x3, l, blockVector, levelDepth);
+
+   Block3DPtr blockW = this->getBlock(x1W, x2, x3, l);
+   if(blockW) blockVector.push_back(blockW);
+   else if(l < levelDepth) this->getSubBlocksBottomNorth(x1W, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottomSouth(int ix1, int ix2, int ix3, int level, vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1E = (ix1 << 1);
+   int x1W = x1E + 1;
+   int x2  = ix2 << 1;
+   int x3  = ix3 << 1;
+   int l   = level + 1;
+
+   Block3DPtr blockE = this->getBlock(x1E, x2, x3, l);
+   if(blockE) blockVector.push_back(blockE);
+   else if(l < levelDepth) this->getSubBlocksBottomSouth(x1E, x2, x3, l, blockVector, levelDepth);
+
+   Block3DPtr blockW = this->getBlock(x1W, x2, x3, l);
+   if(blockW) blockVector.push_back(blockW);
+   else if(l < levelDepth) this->getSubBlocksBottomSouth(x1W, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+//  space-diagonals
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTopNorthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1 = (ix1 << 1) + 1;
+   int x2 = (ix2 << 1) + 1;
+   int x3 = (ix3 << 1) + 1;
+   int l  = level + 1;
+
+   Block3DPtr blockTNE = this->getBlock(x1, x2, x3, l);
+   if(blockTNE) blockVector.push_back(blockTNE);
+   else if(l < levelDepth) this->getSubBlocksTopNorthEast(x1, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTopNorthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1 = ix1 << 1;
+   int x2 = (ix2 << 1) + 1;
+   int x3 = (ix3 << 1) + 1;
+   int l  = level + 1;
+
+   Block3DPtr blockTNW = this->getBlock(x1, x2, x3, l);
+   if(blockTNW) blockVector.push_back(blockTNW);
+   else if(l < levelDepth) this->getSubBlocksTopNorthWest(x1, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTopSouthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1 = (ix1 << 1) + 1;
+   int x2 =  ix2 << 1;
+   int x3 = (ix3 << 1) + 1;
+   int l  = level + 1;
+
+   Block3DPtr blockTNW = this->getBlock(x1, x2, x3, l);
+   if(blockTNW) blockVector.push_back(blockTNW);
+   else if(l < levelDepth) this->getSubBlocksTopSouthEast(x1, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksTopSouthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1 =  ix1 << 1;
+   int x2 =  ix2 << 1;
+   int x3 = (ix3 << 1) + 1;
+   int l  = level + 1;
+
+   Block3DPtr blockTSW = this->getBlock(x1, x2, x3, l);
+   if(blockTSW) blockVector.push_back(blockTSW);
+   else if(l < levelDepth) this->getSubBlocksTopSouthWest(x1, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottomNorthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1 = (ix1 << 1) + 1;
+   int x2 = (ix2 << 1) + 1;
+   int x3 =  ix3 << 1;
+   int l  = level + 1;
+
+   Block3DPtr blockBNE = this->getBlock(x1, x2, x3, l);
+   if(blockBNE) blockVector.push_back(blockBNE);
+   else if(l < levelDepth) this->getSubBlocksBottomNorthEast(x1, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottomNorthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1 =  ix1 << 1;
+   int x2 = (ix2 << 1) + 1;
+   int x3 =  ix3 << 1;
+   int l  = level + 1;
+
+   Block3DPtr blockBNW = this->getBlock(x1, x2, x3, l);
+   if(blockBNW) blockVector.push_back(blockBNW);
+   else if(l < levelDepth) this->getSubBlocksBottomNorthWest(x1, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottomSouthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1 = (ix1 << 1) + 1;
+   int x2 =  ix2 << 1;
+   int x3 =  ix3 << 1;
+   int l  = level + 1;
+
+   Block3DPtr blockBSE = this->getBlock(x1, x2, x3, l);
+   if(blockBSE) blockVector.push_back(blockBSE);
+   else if(l < levelDepth) this->getSubBlocksBottomSouthEast(x1, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getSubBlocksBottomSouthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth)
+{
+   int x1 = ix1 << 1;
+   int x2 = ix2 << 1;
+   int x3 = ix3 << 1;
+   int l  = level + 1;
+
+   Block3DPtr blockBSW = this->getBlock(x1, x2, x3, l);
+   if(blockBSW) blockVector.push_back(blockBSW);
+   else if(l < levelDepth) this->getSubBlocksBottomSouthWest(x1, x2, x3, l, blockVector, levelDepth);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getBlocks(int level, std::vector<Block3DPtr>& blockVector)
+{
+   BOOST_FOREACH(Block3DMap::value_type b, levelSet[level])
+   {
+      blockVector.push_back(b.second);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getBlocks(int level, int rank, std::vector<Block3DPtr>& blockVector)
+{
+   BOOST_FOREACH(Block3DMap::value_type b, levelSet[level])
+   {
+      Block3DPtr block = b.second;
+      int blockRank = block->getRank();
+      if (blockRank == rank)
+      {
+         blockVector.push_back(b.second);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getBlocks(int level, int rank, bool active, std::vector<Block3DPtr>& blockVector)
+{
+   BOOST_FOREACH(Block3DMap::value_type b, levelSet[level])
+   {
+      Block3DPtr block = b.second;
+      int blockRank = block->getRank();
+
+      if (blockRank == rank && active ? block->isActive() : block->isNotActive())
+      {
+         blockVector.push_back(b.second);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+int Grid3D::getFinestInitializedLevel()
+{
+   for(int i=Grid3DSystem::MAXLEVEL; i>=0; i--) if(this->levelSet[i].size() > 0) return(i);
+   return(-1);
+}
+//////////////////////////////////////////////////////////////////////////
+int Grid3D::getCoarsestInitializedLevel()
+{
+   for(int i=0; i<=Grid3DSystem::MAXLEVEL; i++) if(this->levelSet[i].size() > 0) return(i);
+   return(-1);
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setNX1(int nx1)  
+{ 
+   this->nx1 = nx1; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setNX2(int nx2)  
+{ 
+   this->nx2 = nx2; 
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setNX3(int nx3)  
+{ 
+   this->nx3 = nx3; 
+}
+//////////////////////////////////////////////////////////////////////////
+int Grid3D::getNX1() const 
+{ 
+   return this->nx1; 
+}
+//////////////////////////////////////////////////////////////////////////
+int Grid3D::getNX2() const 
+{ 
+   return this->nx2; 
+}
+//////////////////////////////////////////////////////////////////////////
+int Grid3D::getNX3() const 
+{
+   return this->nx3;
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::deleteBlocks( const std::vector<int>& ids )
+{
+   BOOST_FOREACH(int i, ids)
+   {
+      Block3DPtr block = getBlock(i);
+      if(block) this->deleteBlock(block);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+int Grid3D::getNumberOfBlocks()
+{
+   int c = 0;
+   BOOST_FOREACH(Block3DMap l, levelSet)
+   {
+      c += (int)l.size();
+   }
+   return c;
+}
+//////////////////////////////////////////////////////////////////////////
+int Grid3D::getNumberOfBlocks(int level)
+{
+   return (int)levelSet[level].size();
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getBlocksByCuboid( double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, std::vector<Block3DPtr>& blocks )
+{
+   int coarsestLevel = this->getCoarsestInitializedLevel();
+   int finestLevel   = this->getFinestInitializedLevel();
+
+   //////////////////////////////////////////////////////////////////////////
+   //MINIMALE BLOCK-INDIZES BESTIMMEN
+   //  
+   //min:
+   double dMinX1 = trafo->transformForwardToX1Coordinate( minX1,minX2,minX3 )*(1<<finestLevel);
+   double dMinX2 = trafo->transformForwardToX2Coordinate( minX1,minX2,minX3 )*(1<<finestLevel);
+   double dMinX3 = trafo->transformForwardToX3Coordinate( minX1,minX2,minX3 )*(1<<finestLevel);
+
+   //Achtung, wenn minX1 genau auf grenze zwischen zwei bloecken -> der "kleinere" muss genommen werden,
+   //da beim Transformieren der "groessere" Index rauskommt
+   int iMinX1 = (int)dMinX1; if( UbMath::zero(dMinX1-iMinX1) ) iMinX1-=1;   
+   int iMinX2 = (int)dMinX2; if( UbMath::zero(dMinX2-iMinX2) ) iMinX2-=1;
+   int iMinX3 = (int)dMinX3; if( UbMath::zero(dMinX3-iMinX3) ) iMinX3-=1;
+
+   //max (hier kann die Zusatzabfrage vernachlaessigt werden):
+   int iMaxX1 = (int)(trafo->transformForwardToX1Coordinate( maxX1,maxX2,maxX3 )*(1<<finestLevel));
+   int iMaxX2 = (int)(trafo->transformForwardToX2Coordinate( maxX1,maxX2,maxX3 )*(1<<finestLevel));
+   int iMaxX3 = (int)(trafo->transformForwardToX3Coordinate( maxX1,maxX2,maxX3 )*(1<<finestLevel));
+
+   Block3DPtr block;
+
+   //set, um doppelte bloecke zu vermeiden, die u.U. bei periodic auftreten koennen
+   std::set<Block3DPtr> blockset; 
+   for(int level=coarsestLevel; level<=finestLevel; level++)
+   {
+      //damit bei negativen werten auch der "kleinere" genommen wird -> floor!
+      int minx1 = (int)std::floor( (double)iMinX1/(1<<(finestLevel-level)) );
+      int minx2 = (int)std::floor( (double)iMinX2/(1<<(finestLevel-level)) );
+      int minx3 = (int)std::floor( (double)iMinX3/(1<<(finestLevel-level)) );
+
+      int maxx1 = iMaxX1/(1<<(finestLevel-level));
+      int maxx2 = iMaxX2/(1<<(finestLevel-level));
+      int maxx3 = iMaxX3/(1<<(finestLevel-level));
+
+      for(int ix1=minx1; ix1<=maxx1; ix1++)
+         for(int ix2=minx2; ix2<=maxx2; ix2++)
+            for(int ix3=minx3; ix3<=maxx3; ix3++)
+            if( (block=this->getBlock(ix1,ix2,ix3,level)) )
+            {
+               if (block->getRank() == rank)
+               {
+                  blockset.insert(block);
+               }
+            }
+   }
+
+   blocks.resize(blockset.size());
+   std::copy(blockset.begin(), blockset.end(), blocks.begin());
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::getBlocksByCuboid( int level, double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, std::vector<Block3DPtr>& blocks )
+{
+   //////////////////////////////////////////////////////////////////////////
+   //MINIMALE BLOCK-INDIZES BESTIMMEN
+   //
+   //min:
+   double dMinX1 = trafo->transformForwardToX1Coordinate( minX1,minX2,minX3 )*(1<<level);
+   double dMinX2 = trafo->transformForwardToX2Coordinate( minX1,minX2,minX3 )*(1<<level);
+   double dMinX3 = trafo->transformForwardToX3Coordinate( minX1,minX2,minX3 )*(1<<level);
+
+   //Achtung, wenn minX1 genau auf grenze zwischen zwei bloecken -> der "kleinere" muss genommen werden:
+   int iMinX1 = (int)dMinX1; if( UbMath::zero(dMinX1-iMinX1) ) iMinX1-=1;
+   int iMinX2 = (int)dMinX2; if( UbMath::zero(dMinX2-iMinX2) ) iMinX2-=1;
+   int iMinX3 = (int)dMinX3; if( UbMath::zero(dMinX3-iMinX3) ) iMinX3-=1;
+
+   //max:
+   int iMaxX1 = (int)(trafo->transformForwardToX1Coordinate( maxX1,maxX2,maxX3 )*(1<<level));
+   int iMaxX2 = (int)(trafo->transformForwardToX2Coordinate( maxX1,maxX2,maxX3 )*(1<<level));
+   int iMaxX3 = (int)(trafo->transformForwardToX3Coordinate( maxX1,maxX2,maxX3 )*(1<<level));
+
+
+   //set, um doppelte bloecke zu vermeiden, die u.U. bei periodic auftreten koennen
+   std::set<Block3DPtr> blockset; 
+   Block3DPtr block;
+
+   for(int ix1=iMinX1; ix1<=iMaxX1; ix1++)
+      for(int ix2=iMinX2; ix2<=iMaxX2; ix2++)
+         for(int ix3=iMinX3; ix3<=iMaxX3; ix3++)
+            if( (block=this->getBlock(ix1,ix2,ix3,level)) )
+            {
+               if (block->getRank() == rank)
+               {
+                  blockset.insert(block);
+               }
+            }
+
+   blocks.resize(blockset.size());
+   std::copy(blockset.begin(), blockset.end(), blocks.begin());
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::calcStartCoordinatesAndDelta(Block3DPtr block, double& worldX1, double& worldX2, double& worldX3, double& deltaX)
+{
+   int blocklevel  = block->getLevel();
+   worldX1  = block->getX1()/(float)(1<<blocklevel);
+   worldX2  = block->getX2()/(float)(1<<blocklevel);
+   worldX3  = block->getX3()/(float)(1<<blocklevel);
+   deltaX   = (double)1.0/(double)(this->blockNx1*(double)(1<<blocklevel));
+
+   if(this->trafo)
+   {
+      double x1tmp = worldX1, x2tmp = worldX2, x3tmp = worldX3;
+      worldX1 = this->trafo->transformBackwardToX1Coordinate(x1tmp, x2tmp, x3tmp);
+      worldX2 = this->trafo->transformBackwardToX2Coordinate(x1tmp, x2tmp, x3tmp);
+      worldX3 = this->trafo->transformBackwardToX3Coordinate(x1tmp, x2tmp, x3tmp);
+      deltaX  = this->trafo->getX1CoordinateScaling()/(double)(this->blockNx1*(double)(1<<blocklevel));
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::calcStartCoordinatesWithOutOverlap(Block3DPtr block, double& worldX1, double& worldX2, double& worldX3)
+{
+   int blocklevel  = block->getLevel();
+   worldX1  = block->getX1()/(float)(1<<blocklevel);
+   worldX2  = block->getX2()/(float)(1<<blocklevel);
+   worldX3  = block->getX3()/(float)(1<<blocklevel);
+
+   if(this->trafo)
+   {
+      double x1tmp = worldX1, x2tmp = worldX2, x3tmp = worldX3;
+      worldX1 = this->trafo->transformBackwardToX1Coordinate(x1tmp, x2tmp, x3tmp);
+      worldX2 = this->trafo->transformBackwardToX2Coordinate(x1tmp, x2tmp, x3tmp);
+      worldX3 = this->trafo->transformBackwardToX3Coordinate(x1tmp, x2tmp, x3tmp);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::setTimeStep( double step )
+{
+   timeStep = step;
+}
+//////////////////////////////////////////////////////////////////////////
+double Grid3D::getTimeStep() const
+{
+   return timeStep;
+}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::fillExtentWithBlocks( UbTupleInt3 minInd, UbTupleInt3 maxInd )
+{
+   for(int x3 =  val<3>(minInd); x3 <  val<3>(maxInd); x3++)
+   {
+      for(int x2 =  val<2>(minInd); x2 <  val<2>(maxInd); x2++)
+      {
+         for(int x1 =  val<1>(minInd); x1 <  val<1>(maxInd); x1++)
+         {
+            Block3DPtr block( new Block3D(x1,x2,x3,0) );
+            this->addBlock(block);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//void Grid3D::notifyObservers( double step )
+//{
+//   BOOST_FOREACH(ObserverPtr o, observers)
+//   {
+//      o->update(step);
+//   }
+//
+//   //std::list<ObserverWeakPtr>::iterator iter = observers.begin();
+//
+//   //GridObserversSet::iterator iter = observers.begin();
+//   //while(iter != observers.end())
+//   //{
+//   //   if ((*iter).expired())
+//   //   {
+//   //      iter = observers.erase(iter);
+//   //   }
+//   //   else
+//   //   {
+//   //      ObserverPtr observer = (*iter).lock(); // create a shared_ptr from the weak_ptr
+//   //      observer->update(step);
+//   //      ++iter;
+//   //   }
+//   //}
+//
+//}
+//////////////////////////////////////////////////////////////////////////
+//void Grid3D::addObserver( ObserverPtr observer )
+//{
+//   observers.insert(observer);
+//   //observers.push_back(observer);
+//}
+////////////////////////////////////////////////////////////////////////////
+//void Grid3D::removeObserver( ObserverPtr observer )
+//{
+//   observers.erase(observer);
+//   //observers.remove(observer);
+//}
+//////////////////////////////////////////////////////////////////////////
+void Grid3D::deleteBlockIDs()
+{
+   this->blockIdMap.clear();
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+
diff --git a/source/VirtualFluidsCore/Grid/Grid3D.h b/source/VirtualFluidsCore/Grid/Grid3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3059a4ad300492bb776ba7a0f423de18c12769f
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Grid3D.h
@@ -0,0 +1,280 @@
+#ifndef GRID3D_H
+#define GRID3D_H
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+#include <set>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/signals2/signal.hpp>
+#include <boost/bind.hpp>
+#include <boost/serialization/shared_ptr.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/map.hpp>
+
+#include "UbKeys.h"
+#include "CoordinateTransformation3D.h"
+
+#include <Communicator.h>
+//#include <Observer.h>
+//#include <FastSignal.hpp>
+
+class Grid3D;
+typedef boost::shared_ptr<Grid3D> Grid3DPtr;
+typedef boost::weak_ptr<Grid3D>   Grid3DWeakPtr;
+
+#include <Block3D.h>
+#include <Block3DVisitor.h>
+#include <Grid3DVisitor.h>
+#include <Interactor3D.h>
+
+//////////////////////////////////////////////////////////////////////////
+class Grid3D : public boost::enable_shared_from_this<Grid3D>
+{
+public:
+   typedef UbKeys::Key3<int>                  Block3DKey;
+   typedef std::map< Block3DKey, Block3DPtr > Block3DMap;
+   typedef std::map< int, Block3DPtr >    BlockIDMap;
+   typedef std::vector<Block3DMap>        LevelSet;
+   typedef std::vector<Interactor3DPtr>   Interactor3DSet;
+   //typedef std::set<ObserverPtr>     GridObserversSet;
+
+   typedef boost::signals2::signal<void (double)>  signal_t;
+   typedef boost::signals2::connection  connection_t;
+
+public:
+   Grid3D();
+   Grid3D(CommunicatorPtr comm);
+   Grid3D(CommunicatorPtr comm, int blockNx1, int blockNx2, int blockNx3, int gridNx1, int gridNx2, int gridNx3);
+   virtual ~Grid3D(){}
+   //////////////////////////////////////////////////////////////////////////
+   //blocks control
+   void addBlock(Block3DPtr block);
+   bool deleteBlock(Block3DPtr block);
+   bool deleteBlock(int ix1, int ix2, int ix3, int level);
+   void deleteBlocks(const std::vector<int>& ids);
+   void replaceBlock(Block3DPtr block);
+   Block3DPtr getBlock(int ix1, int ix2, int ix3, int level) const;
+   Block3DPtr getBlock(int id) const;
+   void getBlocksByCuboid(double minX1, double minX2, double minX3, 
+                          double maxX1, double maxX2, double maxX3, 
+                          std::vector<Block3DPtr>& blocks);
+   void getBlocksByCuboid(int level, double minX1, double minX2, double minX3, 
+                          double maxX1, double maxX2, double maxX3, 
+                          std::vector<Block3DPtr>& blocks);
+   //get blocks for level
+   void getBlocks(int level, std::vector<Block3DPtr>& blockVector);
+   //get blocks for level with current rank
+   void getBlocks(int level, int rank, std::vector<Block3DPtr>& blockVector);
+   //get only active or not active blocks 
+   void getBlocks(int level, int rank, bool active, std::vector<Block3DPtr>& blockVector);
+   int getNumberOfBlocks();
+   int getNumberOfBlocks(int level);
+   //const Block3DMap& getBlocks(int level);
+   const BlockIDMap& getBlockIDs();
+   void deleteBlockIDs();
+   Block3DPtr getSuperBlock(Block3DPtr block);
+   Block3DPtr getSuperBlock(int ix1, int ix2, int ix3, int level);
+   void getSubBlocks(Block3DPtr block, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getSubBlocks(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blockVector);
+   Block3DPtr getNeighborBlock(int dir, int ix1, int ix2, int ix3, int level) const;
+   Block3DPtr getNeighborBlock(int dir, Block3DPtr block) const;
+   bool expandBlock(int ix1, int ix2, int ix3, int level);
+   Block3DPtr collapseBlock(int fix1, int fix2, int fix3, int flevel, int levelDepth);
+   void getAllNeighbors(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getAllNeighbors(Block3DPtr block, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborBlocksForDirection(int dir, int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborBlocksForDirectionWithDirZero(int dir, int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+
+   void getNeighborsZero(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsTop(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsBottom(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+
+   void getNeighborsNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+
+   void getNeighborsTopNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsTopSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsTopEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsTopWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+
+   void getNeighborsBottomNorth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsBottomSouth(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsBottomEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsBottomWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+
+   void getNeighborsTopNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsTopNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsTopSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsTopSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsBottomNorthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsBottomNorthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsBottomSouthEast(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   void getNeighborsBottomSouthWest(int ix1, int ix2, int ix3, int level, int levelDepth, std::vector<Block3DPtr>& blocks);
+   //////////////////////////////////////////////////////////////////////////
+   //level control
+   int getFinestInitializedLevel();
+   int getCoarsestInitializedLevel();
+   //////////////////////////////////////////////////////////////////////////
+   void deleteConnectors();
+   //////////////////////////////////////////////////////////////////////////
+   //interactors control
+   void addInteractor(Interactor3DPtr interactor);
+   void addAndInitInteractor(Interactor3DPtr interactor, double timestep=0);
+   Interactor3DSet getInteractors();
+   //////////////////////////////////////////////////////////////////////////
+   //visitors
+   void accept(Block3DVisitor& blockVisitor);
+   void accept(Grid3DVisitor& gridVisitor);
+   void accept(Grid3DVisitorPtr gridVisitor);
+   //////////////////////////////////////////////////////////////////////////
+   //post processing
+   connection_t connect(signal_t::slot_function_type subscriber);
+   void disconnect(connection_t subscriber);
+   void doPostProcess(double step);
+   //////////////////////////////////////////////////////////////////////////
+   //bundle and rank for distributed memory
+   void setBundle(int bundle);
+   int  getBundle() const;
+   int  getRank() const;
+   void setRank(int rank);
+   //////////////////////////////////////////////////////////////////////////
+   //periodic boundary
+   bool isPeriodicX1() const;
+   bool isPeriodicX2() const;
+   bool isPeriodicX3() const;
+   void setPeriodicX1(bool value);
+   void setPeriodicX2(bool value);
+   void setPeriodicX3(bool value);
+   //////////////////////////////////////////////////////////////////////////
+   //Topology
+   UbTupleInt3 getBlockIndexes(double blockX1Coord, double blockX2Coord, double blockX3Coord)  const;
+   UbTupleInt3 getBlockIndexes(double blockX1Coord, double blockX2Coord, double blockX3Coord, int level)  const;
+   UbTupleDouble3 getBlockLengths(Block3DPtr block) const;
+   UbTupleDouble6 getBlockOversize() const ;
+   void setCoordinateTransformator(CoordinateTransformation3DPtr trafo);
+   const CoordinateTransformation3DPtr getCoordinateTransformator() const ;
+   void setDeltaX(double dx);
+   void setDeltaX(double worldUnit, double gridUnit);
+   double getDeltaX(int level) const;
+   double getDeltaX(Block3DPtr block) const;
+   UbTupleDouble3 getNodeOffset(Block3DPtr block) const ;
+   UbTupleDouble3 getNodeCoordinates(Block3DPtr block, int ix1, int ix2, int ix3) const;
+   UbTupleInt3 getNodeIndexes(Block3DPtr block, double nodeX1Coord, double nodeX2Coord, double nodeX3Coord) const;
+   void setBlockNX(int nx1, int nx2, int nx3);
+   UbTupleInt3 getBlockNX() const;
+   UbTupleDouble3 getBlockWorldCoordinates(Block3DPtr block) const;
+   UbTupleDouble3 getBlockWorldCoordinates(int blockX1Index, int blockX2Index, int blockX3Index, int level) const;
+   void setNX1(int nx1);
+   void setNX2(int nx2);
+   void setNX3(int nx3);
+   int  getNX1() const;
+   int  getNX2() const;
+   int  getNX3() const;
+   void calcStartCoordinatesAndDelta(Block3DPtr block, double& worldX1, double& worldX2, double& worldX3, double& deltaX);
+   void calcStartCoordinatesWithOutOverlap(Block3DPtr block, double& worldX1, double& worldX2, double& worldX3);
+   //////////////////////////////////////////////////////////////////////////
+   //LBM
+   //double getDeltaT(Block3DPtr) const;
+   //////////////////////////////////////////////////////////////////////////
+   void setTimeStep(double step);
+   double getTimeStep() const;
+protected:
+   void checkLevel(int level);
+   bool hasLevel(int level) const;
+
+   void fillExtentWithBlocks( UbTupleInt3 minInd, UbTupleInt3 maxInd );
+
+   void getSubBlocksZero(int ix1, int ix2, int ix3, int level,std::vector<Block3DPtr>& blockVector, int levelDepth);
+
+   void getSubBlocksEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksNorth(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksSouth(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksTop(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksBottom(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+
+   void getSubBlocksSouthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksSouthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksNorthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksNorthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+
+   void getSubBlocksTopEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksTopWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksTopNorth(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksTopSouth(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+
+   void getSubBlocksBottomEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksBottomWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksBottomNorth(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksBottomSouth(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+
+   void getSubBlocksTopNorthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksTopNorthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksTopSouthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksTopSouthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksBottomNorthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksBottomNorthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksBottomSouthEast(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+   void getSubBlocksBottomSouthWest(int ix1, int ix2, int ix3, int level, std::vector<Block3DPtr>& blockVector, int levelDepth);
+
+private:
+   LevelSet levelSet;
+   BlockIDMap blockIdMap;
+   Interactor3DSet interactors;
+   //GridObserversSet observers;
+
+   signal_t sig;
+   int rank;
+   int bundle;
+   
+   bool periodicX1;
+   bool periodicX2;
+   bool periodicX3;
+
+   int blockNx1;    
+   int blockNx2;    
+   int blockNx3; 
+
+   int nx1;    
+   int nx2;    
+   int nx3;    
+
+   CoordinateTransformation3DPtr trafo;
+   double orgDeltaX;
+
+   double timeStep;
+   
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & nx1;
+      ar & nx2;
+      ar & nx3;
+      ar & orgDeltaX;
+      ar & trafo;
+      ar & blockNx1;
+      ar & blockNx2;
+      ar & blockNx3;
+      ar & rank;
+      ar & bundle;
+      ar & periodicX1;
+      ar & periodicX2;
+      ar & periodicX3;
+      ar & levelSet;
+      ar & blockIdMap;
+      ar & timeStep;
+      ar & interactors;
+   }
+};
+
+#endif 
diff --git a/source/VirtualFluidsCore/Grid/Grid3DSystem.cpp b/source/VirtualFluidsCore/Grid/Grid3DSystem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea2ecde18744c95c5aa9a242ff2b76b83fb566b9
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Grid3DSystem.cpp
@@ -0,0 +1,48 @@
+#include <Grid3DSystem.h>
+
+namespace Grid3DSystem
+{
+   const int INVDIR[] = { INV_E  ,   
+                          INV_W  ,  
+                          INV_N  ,  
+                          INV_S  ,  
+                          INV_T  ,  
+                          INV_B  ,  
+                          INV_NE , 
+                          INV_NW , 
+                          INV_SE , 
+                          INV_SW ,
+                          INV_TE , 
+                          INV_TW , 
+                          INV_BE , 
+                          INV_BW , 
+                          INV_TN , 
+                          INV_TS , 
+                          INV_BN , 
+                          INV_BS , 
+                          INV_TNE,
+                          INV_TNW,
+                          INV_TSE,
+                          INV_TSW,
+                          INV_BNE,
+                          INV_BNW,
+                          INV_BSE,
+                          INV_BSW    };
+
+   //index             0   1   2   3   4   5  6   7   8    9  10  11  12  13  14  15  16  17  18
+   //direction:        E,  W,  N,  S,  T,  B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW
+   const int EX1[] = { 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1, 0, 0, 0, 0, 1, -1, 1, -1, 1, -1, 1, -1 };
+   const int EX2[] = { 0, 0, 1, -1, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1 };
+   const int EX3[] = { 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1 };
+}
+
+//////////////////////////////////////////////////////////////////////////
+const int& Grid3DSystem::getInvertDirection(const int& direction)
+{  
+#ifdef _DEBUG
+   if(direction<STARTDIR || direction>ENDDIR) 
+      throw UbException(UB_EXARGS,"unknown direction");
+#endif
+   return INVDIR[direction];
+}
+
diff --git a/source/VirtualFluidsCore/Grid/Grid3DSystem.h b/source/VirtualFluidsCore/Grid/Grid3DSystem.h
new file mode 100644
index 0000000000000000000000000000000000000000..6c581c82c49a432612d5928c16a7ce2a5e2d3b00
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/Grid3DSystem.h
@@ -0,0 +1,158 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef Grid3DSystem_H
+#define Grid3DSystem_H
+
+#include <cmath>
+#include <iostream>
+#include <string>
+
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbException.h>
+
+
+namespace Grid3DSystem
+{
+   static const int STARTDIR = 0;
+
+   static const int E    /*f1 */ = 0;
+   static const int W    /*f2 */ = 1;
+   static const int N    /*f3 */ = 2;
+   static const int S    /*f4 */ = 3;
+   static const int T    /*f5 */ = 4;
+   static const int B    /*f6 */ = 5;
+   static const int NE   /*f7 */ = 6;
+   static const int SW   /*f8 */ = 7;
+   static const int SE   /*f9 */ = 8;
+   static const int NW   /*f10*/ = 9;
+   static const int TE   /*f11*/ = 10;
+   static const int BW   /*f12*/ = 11;
+   static const int BE   /*f13*/ = 12;
+   static const int TW   /*f14*/ = 13;
+   static const int TN   /*f15*/ = 14;
+   static const int BS   /*f16*/ = 15;
+   static const int BN   /*f17*/ = 16;
+   static const int TS   /*f18*/ = 17;
+   static const int TNE          = 18;
+   static const int TNW          = 19;
+   static const int TSE          = 20;
+   static const int TSW          = 21;
+   static const int BNE          = 22;
+   static const int BNW          = 23;
+   static const int BSE          = 24;
+   static const int BSW          = 25;
+   static const int ZERO /*f0 */ = 26;
+
+   static const int ENDDIR = 25; 
+
+   static const int INV_E   = W;  
+   static const int INV_W   = E;  
+   static const int INV_N   = S;  
+   static const int INV_S   = N;  
+   static const int INV_T   = B;  
+   static const int INV_B   = T;  
+   static const int INV_NE  = SW; 
+   static const int INV_NW  = SE; 
+   static const int INV_SE  = NW; 
+   static const int INV_SW  = NE; 
+   static const int INV_TE  = BW; 
+   static const int INV_TW  = BE; 
+   static const int INV_BE  = TW; 
+   static const int INV_BW  = TE; 
+   static const int INV_TN  = BS; 
+   static const int INV_TS  = BN; 
+   static const int INV_BN  = TS; 
+   static const int INV_BS  = TN; 
+   static const int INV_TNE = BSW;
+   static const int INV_TNW = BSE;
+   static const int INV_TSE = BNW;
+   static const int INV_TSW = BNE;
+   static const int INV_BNE = TSW;
+   static const int INV_BNW = TSE;
+   static const int INV_BSE = TNW;
+   static const int INV_BSW = TNE;
+
+   extern const int INVDIR[ENDDIR+1];
+
+   static const int MAXLEVEL  = 25;
+
+   extern const int EX1[ENDDIR+1];
+   extern const int EX2[ENDDIR+1];
+   extern const int EX3[ENDDIR+1];
+
+   inline std::string getDirectionString(int direction)
+   {
+      switch(direction)
+      {
+      case E   : return "E"; 
+      case W   : return "W"; 
+      case N   : return "N"; 
+      case S   : return "S"; 
+      case T   : return "T";
+      case B   : return "B"; 
+      case NE  : return "NE";
+      case NW  : return "NW";
+      case SE  : return "SE";
+      case SW  : return "SW";
+      case TE  : return "TE";
+      case TW  : return "TW";
+      case BE  : return "BE";
+      case BW  : return "BW";
+      case TN  : return "TN";
+      case TS  : return "TS";
+      case BN  : return "BN";
+      case BS  : return "BS";
+      case TNE : return "TNE";
+      case TNW : return "TNW";
+      case TSE : return "TSE";
+      case TSW : return "TSW";
+      case BNE : return "BNE";
+      case BNW : return "BNW";
+      case BSE : return "BSE";
+      case BSW : return "BSW";
+      default  : return "Cell3DSystem::getDrectionString(...) - unknown dir";
+      }
+   }
+   static const int&       getInvertDirection(const int& direction);
+
+//////////////////////////////////////////////////////////////////////////
+   static inline void setNeighborCoordinatesForDirection(int &x1, int &x2,int &x3, const int& direction)
+   {
+      switch(direction)
+      {
+      case Grid3DSystem::E  :  x1++;             break;
+      case Grid3DSystem::N  :  x2++;             break;
+      case Grid3DSystem::T  :  x3++;             break;
+      case Grid3DSystem::W  :  x1--;             break;
+      case Grid3DSystem::S  :  x2--;             break;
+      case Grid3DSystem::B  :  x3--;             break;
+      case Grid3DSystem::NE :  x1++; x2++;       break;
+      case Grid3DSystem::NW :  x1--; x2++;       break;
+      case Grid3DSystem::SW :  x1--; x2--;       break;
+      case Grid3DSystem::SE :  x1++; x2--;       break;
+      case Grid3DSystem::TE :  x1++; x3++;       break;
+      case Grid3DSystem::BW :  x1--; x3--;       break;
+      case Grid3DSystem::BE :  x1++; x3--;       break;
+      case Grid3DSystem::TW :  x1--; x3++;       break;
+      case Grid3DSystem::TN :  x2++; x3++;       break;
+      case Grid3DSystem::BS :  x2--; x3--;       break;
+      case Grid3DSystem::BN :  x2++; x3--;       break;
+      case Grid3DSystem::TS :  x2--; x3++;       break;
+      case Grid3DSystem::TNE:  x1++; x2++; x3++; break;
+      case Grid3DSystem::TNW:  x1--; x2++; x3++; break;
+      case Grid3DSystem::TSE:  x1++; x2--; x3++; break;
+      case Grid3DSystem::TSW:  x1--; x2--; x3++; break;
+      case Grid3DSystem::BNE:  x1++; x2++; x3--; break;
+      case Grid3DSystem::BNW:  x1--; x2++; x3--; break;
+      case Grid3DSystem::BSE:  x1++; x2--; x3--; break;
+      case Grid3DSystem::BSW:  x1--; x2--; x3--; break;
+      default: throw UbException(UB_EXARGS,"no direction ...");
+      }
+   }
+}
+
+#endif 
diff --git a/source/VirtualFluidsCore/Grid/MTCalculator.cpp b/source/VirtualFluidsCore/Grid/MTCalculator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0d277a097f81a4f48d94ef0b7f2686f657a97aa9
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/MTCalculator.cpp
@@ -0,0 +1,589 @@
+#include "MTCalculator.h"
+#include <basics/utilities/UbException.h>
+#include <boost/foreach.hpp>
+#include "SimulationParameters.h"
+#include "MathUtil.hpp"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+
+#define TIMING
+
+MTCalculator::MTCalculator()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+MTCalculator::MTCalculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread) : 
+                       grid(grid),
+                       sync(sync),
+                       mainThread(mainThread),
+                       refinement(false)
+{
+   minLevel = grid->getCoarsestInitializedLevel();
+   maxLevel = grid->getFinestInitializedLevel();
+   if(maxLevel > 0)
+      refinement = true;
+   else
+      refinement = false;
+   blocks.resize(maxLevel+1);
+   localConns.resize(maxLevel+1);
+   remoteConns.resize(maxLevel+1);
+   localInterfaceBlockConns.resize(maxLevel+1);
+   remoteInterfaceBlockConns.resize(maxLevel+1);
+   localInterConns.resize(maxLevel);
+   remoteInterConns.resize(maxLevel);
+   loadBalancingComp = false;
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error)
+{
+   UBLOG(logDEBUG1, "Calculator::calculate() - started");
+   try
+   {
+      initConnectors();
+
+      int anzLevel = maxLevel-minLevel+1;
+
+      int minInitLevel       = minLevel;
+      int maxInitLevel       = maxLevel-minLevel;
+      int straightStartLevel = minInitLevel;
+      int internalIterations = 1 << (maxInitLevel-minInitLevel);
+      int forwardStartLevel;
+      int threshold;
+      int startStep = int(grid->getTimeStep())+1;
+
+      //UBLOG(logINFO, "startStep="<<startStep);
+      int anzCalcSteps = static_cast<int>(endTime);
+#ifdef TIMING
+      UbTimer timer;
+      double time[6];
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//      UBLOG(logINFO, "Number of connectors = " <<this->localConns[0].size());
+//////////////////////////////////////////////////////////////////////////
+
+      for(calcStep=startStep; calcStep<=anzCalcSteps; calcStep++)
+      {
+
+         //exchange data between blocks for visualization
+         //sync->wait();
+         ////if(visScheduler->isDue((double)(calcStep-1)))
+         ////{
+         //   //exchangeBlockData(minInitLevel, maxInitLevel, true);
+         ////}
+
+         ////wait for write dump files
+         //sync->wait();
+         //write dump 
+         if (mainThread) grid->doPostProcess((double)(calcStep-1));
+         sync->wait();
+
+
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+         UBLOG(logINFO, "calcStep = " <<calcStep);
+#endif
+//////////////////////////////////////////////////////////////////////////
+         
+         for(int staggeredStep=1; staggeredStep<=internalIterations; staggeredStep++)
+         {
+            forwardStartLevel = straightStartLevel;
+            if(staggeredStep == internalIterations) straightStartLevel = minInitLevel;
+            else
+            {
+               for(straightStartLevel=maxInitLevel,threshold=1;
+                  (staggeredStep&threshold)!=threshold; straightStartLevel--,threshold<<=1);
+            }
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            timer.resetAndStart();
+#endif
+//////////////////////////////////////////////////////////////////////////
+            calculateBlocks(straightStartLevel, maxInitLevel);
+            //calculateBlocks(minInitLevel, maxInitLevel, staggeredStep);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[0] = timer.stop();
+            UBLOG(logINFO, "calculateBlocks time = " <<time[0]);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //exchange data between blocks
+            //Sleep(10000);
+            exchangeBlockData(straightStartLevel, maxInitLevel, false);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[1] = timer.stop();
+            UBLOG(logINFO, "exchangeBlockData time = " <<time[1]);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            applyBCs(straightStartLevel, maxInitLevel);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[2] = timer.stop();
+            UBLOG(logINFO, "applyBCs time = " <<time[2]);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //swap distributions in kernel
+            swapDistributions(straightStartLevel, maxInitLevel);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[3] = timer.stop();
+            UBLOG(logINFO, "swapDistributions time = " <<time[3]);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            if (refinement)
+            {
+               //exchange data between blocks for grid refinement
+			      //exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+               if(straightStartLevel<maxInitLevel)
+                  exchangeBlockData(straightStartLevel, maxInitLevel, true);
+                  //exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+               time[4] = timer.stop();
+               UBLOG(logINFO, "refinement exchangeBlockData time = " <<time[4]);
+#endif
+//////////////////////////////////////////////////////////////////////////
+               //now ghost nodes have actual values
+			      //interpolation of interface nodes between grid levels
+               interpolation(straightStartLevel, maxInitLevel);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+               time[5] = timer.stop();
+               UBLOG(logINFO, "refinement interpolation time = " <<time[5]);
+#endif
+//////////////////////////////////////////////////////////////////////////
+            }
+            
+         }
+         //exchange data between blocks for visualization
+        if(mainThread) visScheduler->isDue((double)(calcStep-1));
+        if((int)visScheduler->getNextDueTime() == calcStep)
+        {
+            exchangeBlockData(straightStartLevel, maxInitLevel, true);
+        }
+         //now ghost nodes have actual values
+
+         //dynamic load balancing
+         //sync->wait();
+         //if (mainThread && !loadBalancingComp)
+         //{
+         //   loadBalancingComp = cm->balance();
+         //}
+      }
+      error = boost::exception_ptr();
+      UBLOG(logDEBUG1, "Calculator::calculate() - stoped");
+   }
+   catch( std::exception& e )
+   {
+      //error = boost::current_exception();
+      UBLOG(logERROR, e.what());
+      UBLOG(logERROR, " step = "<<calcStep);
+      exit(EXIT_FAILURE);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::calculateBlocks(int startLevel, int maxInitLevel)
+{
+   Block3DPtr blockTemp;
+   try
+   {
+      //startLevel bis maxInitLevel
+      for(int level=startLevel; level<=maxInitLevel; level++)
+      {
+         //timer.resetAndStart();
+         //call LBM kernel
+         BOOST_FOREACH(Block3DPtr block, blocks[level])
+         {
+            blockTemp = block;
+            block->getKernel()->calculate();
+         }
+         //timer.stop();
+         //UBLOG(logINFO, "level = " << level << " blocks = " << blocks[level].size() << " collision time = " << timer.getTotalTime());
+      }
+   }
+   catch( std::exception& e )
+   {      
+      //error = boost::current_exception();
+      UBLOG(logERROR, e.what());
+      UBLOG(logERROR, blockTemp->toString()<<" step = "<<calcStep);
+      exit(EXIT_FAILURE);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::calculateBlocks(int minInitLevel, int maxInitLevel, int staggeredStep)
+{
+   int p, maxi, maxir, maxidp, start, end;
+   for(int level=minInitLevel; level<=maxInitLevel; level++)
+   {
+      p = 1<<(maxInitLevel-level);
+      maxi = maxir = static_cast<int>(blocks[level].size());
+      maxidp = maxi/p;
+      if(p > maxi && maxi != 0){
+         maxidp = 1;
+         maxi = p;
+      }
+      start = (staggeredStep-1)*maxidp;
+      if(start >= maxi)
+         start = 0;
+      end = start + maxidp;
+      if((end + p) >= maxi)
+         end = maxi;
+      for (int i = start; i < end; i++)
+      {
+         if(i < maxir)
+            blocks[level][i]->getKernel()->calculate();
+      }
+   }
+ }
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::addBlock(Block3DPtr block)
+{
+   blocks[block->getLevel()].push_back(block);
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::initConnectors()
+{
+   UBLOG(logDEBUG1, "Calculator::initLocalConnectors() - start");
+
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[l])
+      {     
+         block->pushBackLocalSameLevelConnectors(localConns[l]);
+
+         if(block->hasInterpolationFlag())
+            block->pushBackLocalSameLevelConnectors(localInterfaceBlockConns[l]);
+         if (l != maxLevel)
+            block->pushBackLocalInterpolationConnectorsCF(localInterConns[l]);
+      }
+      if (l != maxLevel)
+      {
+         BOOST_FOREACH(Block3DPtr block, blocks[l+1])
+         {     
+            block->pushBackLocalInterpolationConnectorsFC(localInterConns[l]);
+         }
+      }
+      UBLOG(logDEBUG5, "Calculator::initConnectors()-initConnectors(localConns["<<l<<"])");
+      initConnectors(localConns[l]);
+
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator::initConnectors()-initConnectors(localInterConns["<<l<<"])");
+         initConnectors(localInterConns[l]);
+      }
+   }
+   
+   //if (mainThread)
+      initRemoteConnectors();
+
+   sync->wait();
+
+   UBLOG(logDEBUG1, "Calculator::initLocalConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::initRemoteConnectors()
+{
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConnsCF;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConnsFC;
+   remoteInterConnsCF.resize(maxLevel+1);
+   remoteInterConnsFC.resize(maxLevel+1);
+
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+   int gridRank = grid->getRank();
+
+   
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      std::vector<Block3DPtr> blockVector;
+      //grid->getBlocks(level, blockVector);
+      //BOOST_FOREACH(Block3DPtr block, blockVector)
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         int l = block->getLevel();
+         block->pushBackRemoteSameLevelConnectors(remoteConns[l]);
+
+         //if(block->isInterface())
+         //   block->pushBackRemoteSameLevelConnectors(remoteInterfaceBlockConns[l]);
+         block->pushBackRemoteInterpolationConnectorsCF(remoteInterConnsCF[l]);
+         block->pushBackRemoteInterpolationConnectorsFC(remoteInterConnsFC[l]);
+      }
+   }
+   sync->gmtx.lock();
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-initConnectors(remoteConns["<<l<<"]).size ="<<remoteConns[l].size());
+      initConnectors(remoteConns[l]);
+      if (l != maxLevel)
+      {
+		 for(int i = 0; i < remoteInterConnsCF[l].size(); i++)
+			remoteInterConns[l].push_back(remoteInterConnsCF[l][i]);
+		 for(int i = 0; i < remoteInterConnsFC[l+1].size(); i++)
+	      remoteInterConns[l].push_back(remoteInterConnsFC[l+1][i]);
+      }
+   }
+   sync->gmtx.unlock();
+   sync->wait();
+   //////////////////////////////////////////////////////////////////////////
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - initialize remote connectors - start");
+   sync->gmtx.lock();
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-initConnectors(remoteInterConns["<<l<<"]).size ="<<remoteInterConns[l].size());
+         //boost::lock_guard<boost::mutex> guard(mtx_);
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->init();
+      }
+   }
+   sync->gmtx.unlock();
+
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - initialize remote connectors - end");
+
+  // sync->wait();
+   //////////////////////////////////////////////////////////////////////////
+   //sendTransmitterDataSize
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - start");
+   //sync->gmtx.lock();
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-sendTransmitterDataSize(remoteInterConns["<<l<<"]).size ="<<remoteInterConns[l].size());
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->sendTransmitterDataSize();
+      }
+   }
+   //sync->gmtx.unlock();
+
+   //sync->wait();
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+   //receiveTransmitterDataSize
+   //wenn er hier bei verteilten berechnungen stopped, dann ist vermutlich auf einer seite ein nicht aktiver block!!!
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - start");
+
+   //sync->gmtx.lock();
+   for (int l = minLevel; l <= maxLevel; l++)
+   {
+      if (l != maxLevel)
+      {
+         UBLOG(logDEBUG5, "Calculator::initRemoteConnectors()-receiveTransmitterDataSize(remoteInterConns["<<l<<"]).size ="<<remoteInterConns[l].size());
+         BOOST_FOREACH(Block3DConnectorPtr c, remoteInterConns[l] ) c->receiveTransmitterDataSize();
+      }
+   }
+   //sync->gmtx.unlock();
+   //sync->wait();
+   //UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::initConnectors(std::vector<Block3DConnectorPtr>& connectors)
+{
+   UBLOG(logDEBUG1, "Calculator::initConnectors() - start");
+
+   //initialization
+   //////////////////////////////////////////////////////////////////////////
+   //initialize connectors
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->init();
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - connectoren initialisieren - end");
+   //////////////////////////////////////////////////////////////////////////
+   //sendTransmitterDataSize
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->sendTransmitterDataSize();
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - sendTransmitterDataSize - end");
+   //////////////////////////////////////////////////////////////////////////
+   //receiveTransmitterDataSize
+   //wenn er hier bei verteilten berechnungen stopped, dann ist vermutlich auf einer seite ein nicht aktiver block!!!
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors ) c->receiveTransmitterDataSize();
+   UBLOG(logDEBUG5, "Calculator::initConnectors() - receiveTransmitterDataSize - end");
+
+   UBLOG(logDEBUG1, "Calculator::initConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::exchangeBlockData(int startLevel, int maxInitLevel, bool invStep)
+{
+   UBLOG(logDEBUG5, "Calculator::exchangeBlockData() - start");
+   //sync->wait();
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(localConns[level]);
+      connectorsPrepare(remoteConns[level]);
+
+      connectorsSend(localConns[level], invStep);
+      connectorsSend(remoteConns[level], invStep);
+
+      connectorsReceive(localConns[level], invStep);
+      connectorsReceive(remoteConns[level], invStep);
+   }
+   //sync->wait();
+   UBLOG(logDEBUG5, "Calculator::exchangeBlockData() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::exchangeInterfaceBlockData(int startLevel, int maxInitLevel, bool invStep)
+{
+   sync->wait();
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      connectorsPrepare(localInterfaceBlockConns[level]);
+      connectorsPrepare(remoteInterfaceBlockConns[level]);
+
+      connectorsSend(localInterfaceBlockConns[level], invStep);
+      connectorsSend(remoteInterfaceBlockConns[level], invStep);
+
+      connectorsReceive(localInterfaceBlockConns[level], invStep);
+      connectorsReceive(remoteInterfaceBlockConns[level], invStep);
+   }
+   sync->wait();
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::swapDistributions(int startLevel, int maxInitLevel)
+{
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->swapDistributions();
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::connectorsPrepare(std::vector< Block3DConnectorPtr >& connectors)
+{
+   UBLOG(logDEBUG5, "Calculator::connectorsPrepare() - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+      UBLOG(logDEBUG5, "Calculator::connectorsPrepare() - c->prepareForReceive() - start");
+      c->prepareForReceive();
+      UBLOG(logDEBUG5, "Calculator::connectorsPrepare() - c->prepareForReceive() - end");
+      UBLOG(logDEBUG5, "Calculator::connectorsPrepare() - c->prepareForSend() - start");
+      c->prepareForSend();
+      UBLOG(logDEBUG5, "Calculator::connectorsPrepare() - c->prepareForSend() - end");
+   }
+   UBLOG(logDEBUG5, "Calculator::connectorsPrepare() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::connectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   UBLOG(logDEBUG5, "Calculator::connectorsSend() - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+	   c->setInvStep(invStep);
+      c->fillSendVectors();
+      c->sendVectors();
+   }
+   UBLOG(logDEBUG5, "Calculator::connectorsSend() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::connectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   UBLOG(logDEBUG5, "Calculator::connectorsReceive() - start");
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+	   c->setInvStep(invStep);
+      c->receiveVectors();
+      c->distributeReceiveVectors();
+   }
+   UBLOG(logDEBUG5, "Calculator::connectorsReceive() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::connectorsSetInvStep(std::vector< Block3DConnectorPtr >& connectors, bool invStep)
+{
+   BOOST_FOREACH(Block3DConnectorPtr c, connectors)
+   {
+      c->setInvStep(invStep);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::interpolation(int startLevel, int maxInitLevel)
+{
+   UBLOG(logDEBUG5, "Calculator::interpolation() - start");  
+   //sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsPrepare(localInterConns[level]);
+      connectorsPrepare(remoteInterConns[level]);
+   }
+
+   //sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsSend(localInterConns[level], true);
+      connectorsSend(remoteInterConns[level], true);
+   }
+
+   //sync->wait();
+
+   for(int level=startLevel; level<maxInitLevel; level++)
+   {
+      connectorsReceive(localInterConns[level], true);
+      connectorsReceive(remoteInterConns[level], true);
+   }
+
+   //sync->wait();
+   UBLOG(logDEBUG5, "Calculator::interpolation() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::setVisScheduler(UbSchedulerPtr s)
+{
+   visScheduler = s;
+}
+//////////////////////////////////////////////////////////////////////////
+//double Calculator::getCallculationTime()
+//{
+//   return timer.getTotalTime();
+//}
+//////////////////////////////////////////////////////////////////////////
+std::vector< std::vector< Block3DPtr > > MTCalculator::getBlocks()
+{
+   return blocks;
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::deleteBlocks()
+{
+   BOOST_FOREACH(std::vector< Block3DPtr > &bs, blocks)
+      bs.resize(0);
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::deleteConnectors()
+{
+   deleteConnectors(localConns);
+   deleteConnectors(remoteConns);
+
+   deleteConnectors(localInterfaceBlockConns);
+   deleteConnectors(remoteInterfaceBlockConns);
+
+   deleteConnectors(localInterConns);
+   deleteConnectors(remoteInterConns);
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::deleteConnectors(std::vector< std::vector< Block3DConnectorPtr > >& conns)
+{
+   BOOST_FOREACH(std::vector< Block3DConnectorPtr > &c, conns)
+      c.resize(0);
+}
+//////////////////////////////////////////////////////////////////////////
+void MTCalculator::applyBCs( int startLevel, int maxInitLevel )
+{
+   //startLevel bis maxInitLevel
+   for(int level=startLevel; level<=maxInitLevel; level++)
+   {
+      //call LBM kernel
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->getBCProcessor()->applyBC();
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/Grid/MTCalculator.h b/source/VirtualFluidsCore/Grid/MTCalculator.h
new file mode 100644
index 0000000000000000000000000000000000000000..a594990ef19f5b16ca6d96d75f048c9c602c2b06
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/MTCalculator.h
@@ -0,0 +1,82 @@
+#ifndef MTCALCULATOR_H
+#define MTCALCULATOR_H
+
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "Synchronizer.h"
+#include "MathUtil.hpp"
+#include "basics/utilities/UbScheduler.h"
+#include "basics/utilities/UbTiming.h"
+#include "LoadBalancer.h"
+#include "Calculator.h"
+
+class MTCalculator;
+typedef boost::shared_ptr<MTCalculator> MTCalculatorPtr;
+
+#include "CalculationManager.h"
+
+class MTCalculator : public Calculator
+{
+public:
+   MTCalculator();
+   MTCalculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread = true);
+   virtual ~MTCalculator(){}
+   virtual void calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error);
+   void addBlock(Block3DPtr block);
+   void initConnectors();
+   void setVisScheduler(UbSchedulerPtr s);
+   //double getCallculationTime();
+   std::vector< std::vector< Block3DPtr > > getBlocks(); 
+   void deleteBlocks();
+   void deleteConnectors();
+protected:
+   void calculateBlocks(int startLevel, int maxInitLevel);
+   void calculateBlocks(int minInitLevel, int maxInitLevel, int staggeredStep);
+   void initConnectors(std::vector<Block3DConnectorPtr>& connectors);
+   virtual void initRemoteConnectors();
+   void swapDistributions(int startLevel, int maxInitLevel);
+   virtual void exchangeBlockData(int startLevel, int maxInitLevel, bool invStep);
+   void exchangeInterfaceBlockData(int startLevel, int maxInitLevel, bool invStep);
+   virtual void connectorsPrepare(std::vector< Block3DConnectorPtr >& connectors);
+   virtual void connectorsSend(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   virtual void connectorsReceive(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   void connectorsSetInvStep(std::vector< Block3DConnectorPtr >& connectors, bool invStep);
+   void interpolation(int startLevel, int maxInitLevel);
+   void deleteConnectors(std::vector< std::vector< Block3DConnectorPtr > >& conns);
+   void applyBCs(int startLevel, int maxInitLevel);
+   int minLevel, maxLevel;
+   std::vector< std::vector< Block3DConnectorPtr > > localConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteConns;
+   SynchronizerPtr sync;
+
+   boost::barrier* bar;
+   //double time;
+
+   bool mainThread;
+   bool refinement;
+   Grid3DPtr grid;
+   UbSchedulerPtr visScheduler;
+   int calcStep;
+
+private:
+   std::vector< std::vector<Block3DPtr> > blocks;
+
+   std::vector< std::vector< Block3DConnectorPtr > > localInterfaceBlockConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterfaceBlockConns;
+
+   //localInterConns and remoteInterConns save interpolation connectors 
+   //every element save CF connectors for current level and FC connectors for next level
+   //e.g. 
+   //localInterConns[0] = CF(0), FC(1)
+   //localInterConns[1] = CF(1), FC(2)
+   //localInterConns[2] 
+   std::vector< std::vector< Block3DConnectorPtr > > localInterConns;
+   std::vector< std::vector< Block3DConnectorPtr > > remoteInterConns;
+
+   //UbTimer timer, timer2, timer3;
+   bool loadBalancingComp;
+
+
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Grid/PrePostBcCalculator.cpp b/source/VirtualFluidsCore/Grid/PrePostBcCalculator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..535411efc9b1dcc5cad9e11c1e665823ee708e9b
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/PrePostBcCalculator.cpp
@@ -0,0 +1,214 @@
+#include "PrePostBcCalculator.h"
+#include <basics/utilities/UbException.h>
+#include <boost/foreach.hpp>
+#include "SimulationParameters.h"
+#include "MathUtil.hpp"
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+
+//#define TIMING
+
+PrePostBcCalculator::PrePostBcCalculator()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+PrePostBcCalculator::PrePostBcCalculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread) : 
+Calculator(grid, sync, mainThread)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+PrePostBcCalculator::PrePostBcCalculator(Grid3DPtr grid, SynchronizerPtr sync, BoundaryConditionProcessorPtr bcProcessor, bool mainThread) :
+Calculator(grid, sync, bcProcessor, mainThread)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void PrePostBcCalculator::calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error)
+{
+   UBLOG(logDEBUG1, "PrePostBcCalculator::calculate() - started");
+   try
+   {
+      initConnectors();
+
+      int anzLevel = maxLevel-minLevel+1;
+
+      int minInitLevel       = minLevel;
+      int maxInitLevel       = maxLevel-minLevel;
+      int straightStartLevel = minInitLevel;
+      int internalIterations = 1 << (maxInitLevel-minInitLevel);
+      int forwardStartLevel;
+      int threshold;
+      int startStep = int(grid->getTimeStep())+1;
+
+      //UBLOG(logINFO, "startStep="<<startStep);
+      int anzCalcSteps = static_cast<int>(endTime);
+#ifdef TIMING
+      UbTimer timer;
+      double time[6];
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//      UBLOG(logINFO, "Number of connectors = " <<this->localConns[0].size());
+//////////////////////////////////////////////////////////////////////////
+
+      for(calcStep=startStep; calcStep<=anzCalcSteps+1; calcStep++)
+      {
+
+         //exchange data between blocks for visualization
+         //sync->wait();
+         ////if(visScheduler->isDue((double)(calcStep-1)))
+         ////{
+         //   //exchangeBlockData(minInitLevel, maxInitLevel, true);
+         ////}
+
+         ////wait for write dump files
+         //sync->wait();
+         //write dump 
+         if (mainThread) grid->doPostProcess((double)(calcStep-1));
+         sync->wait();
+
+
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+         //UBLOG(logINFO, "calcStep = " <<calcStep);
+#endif
+//////////////////////////////////////////////////////////////////////////
+         
+         for(int staggeredStep=1; staggeredStep<=internalIterations; staggeredStep++)
+         {
+            forwardStartLevel = straightStartLevel;
+            if(staggeredStep == internalIterations) straightStartLevel = minInitLevel;
+            else
+            {
+               for(straightStartLevel=maxInitLevel,threshold=1;
+                  (staggeredStep&threshold)!=threshold; straightStartLevel--,threshold<<=1);
+            }
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            timer.resetAndStart();
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //applyPreCollisionBC(straightStartLevel, maxInitLevel);
+
+
+            calculateBlocks(straightStartLevel, maxInitLevel);
+            ////calculateBlocks(minInitLevel, maxInitLevel, staggeredStep);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[0] = timer.stop();
+            //UBLOG(logINFO, "calculateBlocks time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //exchange data between blocks
+            //Sleep(10000);
+            exchangeBlockData(straightStartLevel, maxInitLevel, false);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[1] = timer.stop();
+            //UBLOG(logINFO, "exchangeBlockData time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+            //applyBCs(straightStartLevel, maxInitLevel);
+            applyPostCollisionBC(straightStartLevel, maxInitLevel);
+            
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[2] = timer.stop();
+            //UBLOG(logINFO, "applyBCs time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            //swap distributions in kernel
+            swapDistributions(straightStartLevel, maxInitLevel);
+
+            //pre-collision boundary conditions
+            exchangeBlockData(straightStartLevel, maxInitLevel, true);
+            applyPreCollisionBC(straightStartLevel, maxInitLevel);
+
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+            time[3] = timer.stop();
+            //UBLOG(logINFO, "swapDistributions time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+            if (refinement)
+            {
+         //      //exchange data between blocks for grid refinement
+			      ////exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+         //DOES NOT NEED 
+               //      if(straightStartLevel<maxInitLevel)
+         //         exchangeBlockData(straightStartLevel, maxInitLevel, true);
+         //         //exchangeInterfaceBlockData(straightStartLevel, maxInitLevel, true);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+               time[4] = timer.stop();
+               UBLOG(logINFO, "refinement exchangeBlockData time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+               //now ghost nodes have actual values
+			      //interpolation of interface nodes between grid levels
+               interpolation(straightStartLevel, maxInitLevel);
+//////////////////////////////////////////////////////////////////////////
+#ifdef TIMING
+               time[5] = timer.stop();
+               UBLOG(logINFO, "refinement interpolation time = " <<time);
+#endif
+//////////////////////////////////////////////////////////////////////////
+            }
+            
+         }
+         //exchange data between blocks for visualization
+        if(mainThread) visScheduler->isDue((double)(calcStep-1));
+        if((int)visScheduler->getNextDueTime() == calcStep)
+        {
+            exchangeBlockData(straightStartLevel, maxInitLevel, true);
+        }
+         //now ghost nodes have actual values
+
+         //dynamic load balancing
+         //sync->wait();
+         //if (mainThread && !loadBalancingComp)
+         //{
+         //   loadBalancingComp = cm->balance();
+         //}
+      }
+      error = boost::exception_ptr();
+      UBLOG(logDEBUG1, "PrePostBcCalculator::calculate() - stoped");
+   }
+   catch( std::exception& e )
+   {
+      //error = boost::current_exception();
+      UBLOG(logERROR, e.what());
+      UBLOG(logERROR, " step = "<<calcStep);
+      boost::dynamic_pointer_cast<MPICommunicator>(Communicator::getInstance())->~MPICommunicator();
+      exit(EXIT_FAILURE);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void PrePostBcCalculator::applyPreCollisionBC(int startLevel, int maxInitLevel)
+{
+   //startLevel bis maxInitLevel
+   for (int level = startLevel; level<=maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->getBCProcessor()->applyPreCollisionBC();
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void PrePostBcCalculator::applyPostCollisionBC(int startLevel, int maxInitLevel)
+{
+   //startLevel bis maxInitLevel
+   for (int level = startLevel; level<=maxInitLevel; level++)
+   {
+      BOOST_FOREACH(Block3DPtr block, blocks[level])
+      {
+         block->getKernel()->getBCProcessor()->applyPostCollisionBC();
+      }
+   }
+}
+
diff --git a/source/VirtualFluidsCore/Grid/PrePostBcCalculator.h b/source/VirtualFluidsCore/Grid/PrePostBcCalculator.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b81c061ccc98db5365fc4e78da531202ad38a63
--- /dev/null
+++ b/source/VirtualFluidsCore/Grid/PrePostBcCalculator.h
@@ -0,0 +1,35 @@
+#ifndef PrePostBcCalculator_h
+#define PrePostBcCalculator_h
+
+#include "Grid3D.h"
+#include "Block3D.h"
+#include "Synchronizer.h"
+#include "MathUtil.hpp"
+#include "basics/utilities/UbScheduler.h"
+#include "basics/utilities/UbTiming.h"
+#include "LoadBalancer.h"
+#include "BoundaryConditionProcessor.h"
+#include "PrePostBcCalculator.h"
+
+
+class PrePostBcCalculator;
+typedef boost::shared_ptr<PrePostBcCalculator> PrePostBcCalculatorPtr;
+
+#include "CalculationManager.h"
+
+class PrePostBcCalculator : public Calculator
+{
+public:
+   PrePostBcCalculator();
+   PrePostBcCalculator(Grid3DPtr grid, SynchronizerPtr sync, bool mainThread = true);
+   PrePostBcCalculator(Grid3DPtr grid, SynchronizerPtr sync, BoundaryConditionProcessorPtr bcProcessor, bool mainThread = true);
+   virtual ~PrePostBcCalculator(){}
+   virtual void calculate(const double& endTime, CalculationManagerPtr cm, boost::exception_ptr& error);
+protected:
+   void applyPreCollisionBC(int startLevel, int maxInitLevel);
+   void applyPostCollisionBC(int startLevel, int maxInitLevel);
+private:
+
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Interactors/CMakePackage.txt b/source/VirtualFluidsCore/Interactors/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Interactors/D3Q27Interactor.cpp b/source/VirtualFluidsCore/Interactors/D3Q27Interactor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b56bddbb3d3894b9f3f2bdf8eb30ac6b8724b806
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/D3Q27Interactor.cpp
@@ -0,0 +1,1407 @@
+#include "D3Q27Interactor.h"
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbLogger.h>
+
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+
+
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/GbLine3D.h>
+#include <numerics/geometry3d/GbCylinder3D.h>
+#include "Block3D.h"
+#include "Grid3D.h"
+#include "BCArray3D.h"
+#include "D3Q27BoundaryCondition.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+
+//#include <3rdParty/MarchingCubes/MarchingCubes.h>
+
+#include <boost/pointer_cast.hpp>
+
+#include <vector>
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+D3Q27Interactor::D3Q27Interactor() : Interactor3D()
+{
+   this->reinitWithStoredQsFlag = false;
+   this->initRayVectors();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27Interactor::D3Q27Interactor(GbObject3DPtr geoObject3D, Grid3DPtr grid, int type)
+: Interactor3D(geoObject3D, grid, type), relevantForForces(false)
+{
+   this->reinitWithStoredQsFlag = false;
+   this->initRayVectors();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27Interactor::D3Q27Interactor(GbObject3DPtr geoObject3D, Grid3DPtr grid, D3Q27BoundaryConditionAdapterPtr bcAdapter,  int type)
+   :   Interactor3D(geoObject3D, grid, type), relevantForForces(false)
+{
+   this->reinitWithStoredQsFlag = false;
+   this->addBCAdapter(bcAdapter); 
+   this->initRayVectors();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27Interactor::D3Q27Interactor(GbObject3DPtr geoObject3D, Grid3DPtr grid, D3Q27BoundaryConditionAdapterPtr bcAdapter,  int type, Interactor3D::Accuracy a)
+   :   Interactor3D(geoObject3D, grid, type, a), relevantForForces(false)
+{
+   this->reinitWithStoredQsFlag = false;
+   this->addBCAdapter(bcAdapter); 
+   this->initRayVectors();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27Interactor::~D3Q27Interactor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27Interactor::initRayVectors()
+{
+   int fdir; double c1oS2 = UbMath::one_over_sqrt2;
+   fdir = D3Q27System::E;  rayX1[fdir] =  1.0;   rayX2[fdir] =  0.0;   rayX3[fdir] =  0.0;
+   fdir = D3Q27System::W;  rayX1[fdir] = -1.0;   rayX2[fdir] =  0.0;   rayX3[fdir] =  0.0;
+   fdir = D3Q27System::N;  rayX1[fdir] =  0.0;   rayX2[fdir] =  1.0;   rayX3[fdir] =  0.0;
+   fdir = D3Q27System::S;  rayX1[fdir] =  0.0;   rayX2[fdir] = -1.0;   rayX3[fdir] =  0.0;
+   fdir = D3Q27System::T;  rayX1[fdir] =  0.0;   rayX2[fdir] =  0.0;   rayX3[fdir] =  1.0;
+   fdir = D3Q27System::B;  rayX1[fdir] =  0.0;   rayX2[fdir] =  0.0;   rayX3[fdir] = -1.0;
+   fdir = D3Q27System::NE; rayX1[fdir] =  c1oS2; rayX2[fdir] =  c1oS2; rayX3[fdir] =  0.0;
+   fdir = D3Q27System::SW; rayX1[fdir] = -c1oS2; rayX2[fdir] = -c1oS2; rayX3[fdir] =  0.0;
+   fdir = D3Q27System::SE; rayX1[fdir] =  c1oS2; rayX2[fdir] = -c1oS2; rayX3[fdir] =  0.0;
+   fdir = D3Q27System::NW; rayX1[fdir] = -c1oS2; rayX2[fdir] =  c1oS2; rayX3[fdir] =  0.0;
+   fdir = D3Q27System::TE; rayX1[fdir] =  c1oS2; rayX2[fdir] = 0.0;    rayX3[fdir] =  c1oS2;
+   fdir = D3Q27System::BW; rayX1[fdir] = -c1oS2; rayX2[fdir] = 0.0;    rayX3[fdir] = -c1oS2;
+   fdir = D3Q27System::BE; rayX1[fdir] =  c1oS2; rayX2[fdir] = 0.0;    rayX3[fdir] = -c1oS2;
+   fdir = D3Q27System::TW; rayX1[fdir] = -c1oS2; rayX2[fdir] = 0.0;    rayX3[fdir] =  c1oS2;
+   fdir = D3Q27System::TN; rayX1[fdir] =  0.0;   rayX2[fdir] = c1oS2;  rayX3[fdir] =  c1oS2;
+   fdir = D3Q27System::BS; rayX1[fdir] =  0.0;   rayX2[fdir] =-c1oS2;  rayX3[fdir] = -c1oS2;
+   fdir = D3Q27System::BN; rayX1[fdir] =  0.0;   rayX2[fdir] = c1oS2;  rayX3[fdir] = -c1oS2;
+   fdir = D3Q27System::TS; rayX1[fdir] =  0.0;   rayX2[fdir] =-c1oS2;  rayX3[fdir] =  c1oS2;
+
+   fdir = D3Q27System::TNW; rayX1[fdir] = -c1oS2; rayX2[fdir] = c1oS2; rayX3[fdir] =  c1oS2;;
+   fdir = D3Q27System::TNE; rayX1[fdir] =  c1oS2; rayX2[fdir] = c1oS2; rayX3[fdir] =  c1oS2;
+   fdir = D3Q27System::TSW; rayX1[fdir] = -c1oS2; rayX2[fdir] =-c1oS2; rayX3[fdir] =  c1oS2;
+   fdir = D3Q27System::TSE; rayX1[fdir] =  c1oS2; rayX2[fdir] =-c1oS2; rayX3[fdir] =  c1oS2;
+   fdir = D3Q27System::BNW; rayX1[fdir] = -c1oS2; rayX2[fdir] = c1oS2; rayX3[fdir] =  -c1oS2;
+   fdir = D3Q27System::BNE; rayX1[fdir] =  c1oS2; rayX2[fdir] = c1oS2; rayX3[fdir] =  -c1oS2;
+   fdir = D3Q27System::BSW; rayX1[fdir] = -c1oS2; rayX2[fdir] =-c1oS2; rayX3[fdir] =  -c1oS2;
+   fdir = D3Q27System::BSE; rayX1[fdir] =  c1oS2; rayX2[fdir] =-c1oS2; rayX3[fdir] =  -c1oS2;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27Interactor::initInteractor(const double& timeStep)
+{
+   UBLOG(logDEBUG5,"D3Q27Interactor::initInteractor - "<<" for timestep = "<<timeStep);
+   
+   //////////////////////////////////////////////////////////////////////////
+   //init bcs
+   int nofAdapter = (int)bcAdapterVector.size();
+   if(nofAdapter==0) UBLOG(logWARNING,"WARNING - D3Q27Interactor::initInteractor Warning - no nodeAdapter available");
+   bool needTimeDependence = false;
+   for(int pos=0; pos<nofAdapter; ++pos)
+   {
+      bcAdapterVector[pos]->init(this,timeStep);
+      if(bcAdapterVector[pos]->isTimeDependent()) needTimeDependence = true;
+   }
+   if(needTimeDependence) this->setTimeDependent();
+   else                   this->unsetTimeDependent();
+
+   Interactor3D::initInteractor(timeStep);
+
+  ////calcForces arbeitet nicht korrekt, wenn Geo mit Bloecken 
+  // //unterschiedlicher Leveltiefe diskretisiert -> exception
+  // //abfrage steht hier, weil es theoretisch sein kann, dass bei parallelen rechnungen
+  // //genau der block mit dem anderen level auf einem anderen prozess liegt...
+  // //Update: es kann u.U. passieren, dass Bl�cke in der Liste nicht aktiv sin
+  // //(falls diese z.B. duch andere Interactoren solid gesetzt wurden)
+  // //diese werden nicht ber�cksichtigt (auch nicht beid er kraftauswertung sp�ter)
+  // if(this->isRelevantForForces() )
+  // {
+  //    int level = -1;     
+  //    for( vector<Block3D*>::const_iterator pos = transBlockSet->begin(); pos!=transBlockSet->end(); ++pos)
+  //       if( (*pos)->isActive() )
+  //       {
+  //          level = (*pos)->getLevel();
+  //          break;
+  //       }
+  //    
+  //    bool check = false;
+  //    for( vector<Block3D*>::const_iterator pos = transBlockSet->begin(); pos!=transBlockSet->end(); ++pos)
+  //       if( (*pos)->isActive() && (*pos)->getLevel()!=level)
+  //       {
+  //          throw UbException(UB_EXARGS,"interactor is relevant for forces,"
+  //                                  +(string)" but has transblocks with different levels"
+  //                                  +(string)" -> not supportet by D3Q27Interactor::getForces()"
+  //                                  +(string)" -> increase refineWidth");
+  //       }
+  // }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27Interactor::updateInteractor(const double& timestep)
+{
+   //UB_THROW( UbException(UB_EXARGS,"toDo") );
+   //if(this->isFluid()) return;
+
+   UBLOG(logDEBUG5,"D3Q27Interactor::updateInteractor - for timestep = "<<timestep);
+
+   //////////////////////////////////////////////////////////////////////////
+   //update bcs
+   int nofAdapter = (int)bcAdapterVector.size();
+   if(nofAdapter==0) UBLOG(logERROR,"WARNING - D3Q27Interactor::updateInteractor Warning - no nodeAdapter available for ");
+
+   bool needTimeDependence = false;
+
+   for(int pos=0; pos<nofAdapter; ++pos)
+   {
+      bcAdapterVector[pos]->update(this,timestep);
+      if(bcAdapterVector[pos]->isTimeDependent()) needTimeDependence = true;
+   }
+   if(needTimeDependence) this->setTimeDependent();
+   else                   this->unsetTimeDependent();
+
+   //update transNodes
+   typedef std::map<Block3DPtr, std::set< std::vector<int> > > TransNodeIndicesMap;
+   
+   //UBLOG(logINFO, "transNodeIndicesMap = "<<transNodeIndicesMap.size());
+   
+   BOOST_FOREACH(TransNodeIndicesMap::value_type t, transNodeIndicesMap)
+   {
+      Block3DPtr block = t.first;
+      std::set< std::vector<int> >& transNodeIndicesSet = t.second;
+
+      //UBLOG(logINFO, "transNodeIndicesSet = "<<transNodeIndicesSet.size());
+
+      if(block->isNotActive() || !block) continue;
+
+      LBMKernel3DPtr kernel = block->getKernel();
+      BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+      set< std::vector<int> >::iterator setPos;
+
+      for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end();  ++setPos)
+      {
+         int    x1      = (*setPos)[0];
+         int    x2      = (*setPos)[1];
+         int    x3      = (*setPos)[2];
+         UbTupleDouble3 coords = grid.lock()->getNodeCoordinates(block, x1, x2, x3);
+         double worldX1 = val<1>(coords);
+         double worldX2 = val<2>(coords);
+         double worldX3 = val<3>(coords);
+
+         D3Q27BoundaryConditionPtr bc = bcArray.getBC(x1,x2,x3);
+         if(bc) //kann sein, dass die BC durch das solid setzen eines andern interactors geloescht wurde
+         {
+            for(size_t i=0; i<bcAdapterVector.size(); i++)
+               bcAdapterVector[i]->adaptBC(*this,bc,worldX1,worldX2,worldX3,timestep);
+         }
+         //else 
+         //{
+         //   UBLOG(logERROR,"D3Q27Interactor.updateInteractor (Z."<<__LINE__<<"): da ist kein BC dran ... kann aber korrekt sein s.h. code");
+         //}
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+// Berechnung findet im realen Koordinatensystem statt !!!
+// nicht im normierten !
+//x1,x2,x3 sind die Koordinaten unten links vom "System"
+//extendedBoundingGeoOfGeoObject MUSS bereits um delta_x_level in jede richtung vergroesert worden sein fuer SOLID
+bool D3Q27Interactor::setDifferencesToGbObject3D(const Block3DPtr block/*,const double& orgX1,const double& orgX2,const double& orgX3,const double& blockLengthX1,const double& blockLengthX2,const double& blockLengthX3, const double& timestep*/)
+{
+   if(!block) return false;
+
+   if(block->isNotActive()) return false;//continue;
+
+   transNodeIndicesMap[block] = set< std::vector<int> >();
+   set< std::vector<int> >& transNodeIndices = transNodeIndicesMap[block];
+   solidNodeIndicesMap[block] = set< UbTupleInt3 >();
+   set< UbTupleInt3 >& solidNodeIndices = solidNodeIndicesMap[block];
+
+
+   double timestep = 0;
+   bool oneEntryGotBC = false; //ob ueberhaupt ein eintrag ein BC zugewiesen wurde
+   bool gotQs         = false; //true, wenn "difference" gesetzt wurde
+   D3Q27BoundaryConditionPtr bc;
+
+   LBMKernel3DPtr kernel = block->getKernel();
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+   double internX1,internX2,internX3;
+
+
+   //width of ghost layer 
+   int gl = kernel->getGhostLayerWidth();
+
+   int startIX1 = 0;
+   int startIX2 = 0;
+   int startIX3 = 0; 
+   int stopIX1  = (int)bcArray.getNX1();
+   int stopIX2  = (int)bcArray.getNX2();
+   int stopIX3  = (int)bcArray.getNX3(); 
+
+   double         dx       = grid.lock()->getDeltaX(block);
+   UbTupleDouble3 orgDelta = grid.lock()->getNodeOffset(block);
+
+   //anderes boundingRect als in init, da hier das boundrect um ein dx vergroessert werden muss
+   GbCuboid3D extendedBoundingGeoOfGeoObject(  geoObject3D->getX1Minimum()-1.02*dx 
+                                             , geoObject3D->getX2Minimum()-1.02*dx 
+                                             , geoObject3D->getX3Minimum()-1.02*dx 
+                                             , geoObject3D->getX1Maximum()+1.02*dx 
+                                             , geoObject3D->getX2Maximum()+1.02*dx 
+                                             , geoObject3D->getX3Maximum()+1.02*dx );
+
+   double deltaX1=dx, deltaX2 =dx, deltaX3=dx;
+
+   if(   geoObject3D->hasRaytracing() 
+        || (this->isInverseSolid() && geoObject3D->raytracingSupportsPointsInside() ) )
+   {
+      //wenn deltaX1==deltaX2==deltaX3 (muss fuer LB!!)
+      if(!UbMath::zero( deltaX1-deltaX2 + deltaX1-deltaX3 + deltaX2-deltaX3 ) )
+         throw UbException(UB_EXARGS,"fuer den bei LB nicht vorkommenden Fall deltaX1!=deltaX2!=deltaX3  nicht implementiert ");
+
+      vector<double> distNeigh(D3Q27System::FENDDIR+1, UbMath::sqrt2*deltaX1);
+      distNeigh[D3Q27System::E] = distNeigh[D3Q27System::W] = distNeigh[D3Q27System::N] = deltaX1;
+      distNeigh[D3Q27System::S] = distNeigh[D3Q27System::T] = distNeigh[D3Q27System::B] = deltaX1;
+
+      double q;
+      bool pointOnBoundary = false;
+
+//#ifdef _OPENMP
+//      #pragma omp parallel for private(internX1,internX2,internX3,gotQs,bc,q )
+//#endif
+      for(int ix3=startIX3; ix3<stopIX3; ix3++)
+      {
+         for(int ix2=startIX2; ix2<stopIX2; ix2++)
+         {
+            for(int ix1=startIX1; ix1<stopIX1; ix1++)
+            {
+               //TODO weiter untersuchen, ob das nicht ein Fehler ist
+               if(bcArray.isUndefined(ix1, ix2, ix3)) continue;
+
+               UbTupleDouble3 coords = grid.lock()->getNodeCoordinates(block, ix1, ix2, ix3);
+               internX1 = val<1>(coords);
+               internX2 = val<2>(coords);
+               internX3 = val<3>(coords);
+
+               //point in object test ist ueberfluessig, weil die start und stop indices bereits zuvor 
+               //ermittelt werden -> es werden nur point-IN-cube indizes betrachtet
+               if(extendedBoundingGeoOfGeoObject.isPointInGbObject3D(internX1,internX2,internX3))
+               {
+                  if(this->isSolid() )
+                  {
+                     if(this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3))
+                     {
+//#ifdef _OPENMP
+//                        #pragma omp critical (SOLIDNODE_SET_CHANGE)
+//#endif
+                        {
+                           solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3));
+                           bcArray.setSolid(ix1,ix2,ix3); 
+                        }
+                        continue;
+                     }
+                  }
+                  else if( this->isInverseSolid()  )
+                  {
+                     //bei inverse solid sind alle Knoten AUSSERHALB und auf der boundary SOLID
+                     if( !this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3, pointOnBoundary) 
+                        || pointOnBoundary == true )
+                     {
+//#ifdef _OPENMP
+//                        #pragma omp critical (SOLID_SET_CHANGE)
+//#endif
+                        {
+                           solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3));
+                           bcArray.setSolid(ix1,ix2,ix3); 
+                        }
+                        continue;
+                     }
+                  }
+
+                  //evtl wurde node von anderen interactoren solid gesetzt (muss hie rein->sonst evtl bei
+                  //ueberschneidender geo -> solidNodeIndicesMap unvollstaendig)
+                  if(bcArray.isSolid(ix1,ix2,ix3)) 
+                     continue;
+
+                  gotQs = false;
+
+                  //TODO: prüfen was passiert wenn ein Geoobjekt zwischen zwei knoten rausguckt
+                  //  * /
+                  //<
+                  //  * \  //
+                  //sollen dann keine qs gesetzt werden
+                  for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                  {
+                     q = geoObject3D->getIntersectionRaytraceFactor(internX1,internX2,internX3,rayX1[fdir],rayX2[fdir],rayX3[fdir]);
+                     q /= distNeigh[fdir];
+
+                     //assert(UbMath::lessEqual(q, 1.0));
+
+                     if( UbMath::inClosedInterval(q, 1.0, 1.0) ) q = 1.0;
+                     if( UbMath::greater(q, 0.0) && UbMath::lessEqual(q, 1.0) )
+                     {
+                        #pragma omp critical (BC_CHANGE)
+                        {
+                           bc = bcArray.getBC(ix1,ix2,ix3);
+                           if(!bc)
+                           {
+                              //bc = bvd->createD3Q27BoundaryCondition(); //= new D3Q27BoundaryCondition();
+                              bc = D3Q27BoundaryConditionPtr(new D3Q27BoundaryCondition);
+                              bcArray.setBC(ix1,ix2,ix3,bc);
+                           }
+                     //TODO: man muss ueberlegen, wie kann man, dass die Geschwindigkeit auf 0.0 gesetzt werden, vermeiden
+                     //das folgt zu unguenstigen "design rules"
+                      //SG 31.08.2010 das Problem - bewegter Interactor angrenzend an stehenden noslip interactor
+                      // hier sollte die Geschwindigkeit auf 0.0 gesetzt werden
+                           if(bc->hasNoSlipBoundary())
+                           {
+                              bc->setBoundaryVelocityX1(0.0);
+                              bc->setBoundaryVelocityX2(0.0);
+                              bc->setBoundaryVelocityX3(0.0);
+                           }
+                       //SG 31.08.2010
+                        
+                           for(int index=(int)bcAdapterVector.size()-1; index>=0; --index)
+                              bcAdapterVector[index]->adaptBCForDirection(*this,bc,internX1,internX2,internX3,q,fdir, timestep);
+                        }
+
+                        gotQs=true;
+                     }
+                  }
+
+                  if(gotQs)
+                  {
+#ifdef _OPENMP
+                     #pragma omp critical (TRANSNODE_SET_CHANGE)
+#endif
+                     {
+                        oneEntryGotBC = true;
+
+                        std::vector<int> p(3);
+                        p[0]=ix1; p[1]=ix2; p[2]=ix3;
+                        transNodeIndices.insert(p);
+                     
+                        for(int index=(int)bcAdapterVector.size()-1; index>=0; --index)
+                           bcAdapterVector[index]->adaptBC(*this,bc,internX1,internX2,internX3, timestep);
+                     }
+                  }
+               }
+               else if( this->isInverseSolid()  )
+               {
+                  //bei inverse solid sind alle Knoten AUSSERHALB und auf der boundary SOLID
+                  if( !this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3, pointOnBoundary) 
+                     || pointOnBoundary == true )
+                 {
+#ifdef _OPENMP 
+   #pragma omp critical (SOLID_SET_CHANGE)
+#endif
+                     {
+                        solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3));
+                        bcArray.setSolid(ix1,ix2,ix3); 
+                     }
+                     continue;
+                  }
+               }
+            }
+         }
+      }
+   }
+   else  //clipping -> langsamer (wird derzeit auch fuer alle inverseSolid objekte verwendet deren raytracing nicht fuer nodes INNERHALB der geo funzt)
+   {
+      bool pointOnBoundary = false;
+      #pragma omp parallel for private(internX1,internX2,internX3,gotQs,bc,pointOnBoundary )
+      for(int ix1=startIX1; ix1<stopIX1; ix1++)
+      {
+         for(int ix2=startIX2; ix2<stopIX2; ix2++)
+         {
+            for(int ix3=startIX3; ix3<stopIX3; ix3++)
+            {
+               if(bcArray.isSolid(ix1,ix2,ix3) || bcArray.isUndefined(ix1, ix2, ix3)) continue;
+
+               UbTupleDouble3 coords = grid.lock()->getNodeCoordinates(block, ix1, ix2, ix3);
+               internX1 = val<1>(coords);
+               internX2 = val<2>(coords);
+               internX3 = val<3>(coords);
+
+               if(extendedBoundingGeoOfGeoObject.isPointInGbObject3D(internX1,internX2,internX3))
+               {
+                  if( this->isSolid() && this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3) )
+                  {
+                     #pragma omp critical (SOLID_SET_CHANGE)
+                     {
+                        solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3));
+                        bcArray.setSolid(ix1,ix2,ix3); 
+                     }
+                     continue;
+                  }
+                  else if( this->isInverseSolid()  )
+                  {
+                     //bei inverse solid sind alle Knoten AUSSERHALB und auf der boundary SOLID
+                     if( !this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3, pointOnBoundary) 
+                         || pointOnBoundary == true )
+                     {
+                        #pragma omp critical (SOLID_SET_CHANGE)
+                        {
+                           solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3));
+                           bcArray.setSolid(ix1,ix2,ix3); 
+                        }
+                        continue;
+                     }
+                  }
+
+                  gotQs = false;
+
+                  GbPoint3D pointA(internX1,internX2,internX3);
+                  for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                  {
+                     double x1B = internX1+D3Q27System::DX1[fdir]*deltaX1;
+                     double x2B = internX2+D3Q27System::DX2[fdir]*deltaX2;
+                     double x3B = internX3+D3Q27System::DX3[fdir]*deltaX3;
+
+                     GbPoint3D pointB(x1B,x2B,x3B);
+                     GbLine3D* clippedLine = this->geoObject3D->createClippedLine3D(pointA, pointB);
+
+                     if(clippedLine)
+                     {
+                        double q=0.0;
+                        if( !this->isInverseSolid() )  //A liegt auf jeden Fall aussen
+                        {
+                           double distanceAB = pointA.getDistance(&pointB); //pointA to B
+                           double distanceAP = UbMath::min(pointA.getDistance(clippedLine->getPoint1()),
+                                                           pointA.getDistance(clippedLine->getPoint2()) );
+                           q = distanceAP/distanceAB;
+                        }
+                        else
+                        {
+                           bool pointIsOnBoundary = false;
+                           if(   !clippedLine->getPoint1()->equals(&pointB)
+                              && !clippedLine->getPoint2()->equals(&pointB) )
+                           {
+                              //A liegt auf jeden Fall drinnen, clipped line darf B nicht enthalten
+                              double distanceAB = pointA.getDistance(&pointB); //pointA to B
+                              double distanceAP = clippedLine->getLength();
+                              q = distanceAP/distanceAB;
+                           }
+                           else if(  this->geoObject3D->isPointInGbObject3D( pointB.getX1Coordinate()
+                                                                            ,pointB.getX2Coordinate()
+                                                                            ,pointB.getX3Coordinate()
+                                                                            ,pointIsOnBoundary )
+                                   && pointIsOnBoundary )
+                           {
+                              //A liegt auf jeden Fall drinnen, B liegt genau auf ObjektBoundary => q=1.0
+                              q=1.0;
+                           }
+                           else
+                           {
+                              q = 0.0;
+                           }
+                        }
+
+                        if(UbMath::inClosedInterval(q, 1.0, 1.0)) q = 1.0;
+                        if(UbMath::lessEqual(q, 1.0) && UbMath::greater(q, 0.0))
+                        {
+                           #pragma omp critical (BC_CHANGE)
+                           {
+                              bc = bcArray.getBC(ix1,ix2,ix3);
+                              if(!bc)
+                              {
+                                 //bc = bvd->createD3Q27BoundaryCondition(); //= new D3Q27BoundaryCondition();
+                                 bc = D3Q27BoundaryConditionPtr(new D3Q27BoundaryCondition);
+                                 bcArray.setBC(ix1,ix2,ix3,bc);
+                              }
+                              for(int index=(int)bcAdapterVector.size()-1; index>=0; --index)
+                                 bcAdapterVector[index]->adaptBCForDirection(*this,bc,internX1,internX2,internX3,q,fdir,timestep);
+                           }
+                                          
+                           gotQs=true;
+                        }
+
+                        clippedLine->deletePoint1();
+                        clippedLine->deletePoint2();
+                        delete clippedLine;
+                     }
+                  }
+
+                  if(gotQs)
+                  {
+                     #pragma omp critical (TRANSNODE_SET_CHANGE)
+                     {
+                        oneEntryGotBC = true;
+
+                        std::vector<int> p(3);
+                        p[0]=ix1; p[1]=ix2; p[2]=ix3;
+                        transNodeIndices.insert(p);
+
+                        for(int index=(int)bcAdapterVector.size()-1; index>=0; --index)
+                           bcAdapterVector[index]->adaptBC(*this,bc,internX1,internX2,internX3,timestep);
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   return oneEntryGotBC;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27Interactor::addQsLineSet(std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines)
+{
+      BOOST_FOREACH(Block3DPtr block, transBlocks)
+      {
+         if(!block) continue;
+
+         double         dx       = grid.lock()->getDeltaX(block);
+         UbTupleDouble3 orgDelta = grid.lock()->getNodeOffset(block);
+
+         LBMKernel3DPtr kernel = block->getKernel();
+         BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+         map<Block3DPtr, set< std::vector<int> > >::iterator pos = transNodeIndicesMap.find(block);
+         if(pos==transNodeIndicesMap.end()) 
+         {
+            UB_THROW( UbException(UB_EXARGS,"block nicht in indizes map!!!") );
+         }
+         set< std::vector<int> >& transNodeIndicesSet = pos->second;
+         set< std::vector<int> >::iterator setPos;
+
+         std::size_t node1Index, node2Index;
+
+         UbTupleDouble3 blockOrg = grid.lock()->getBlockWorldCoordinates(block);
+
+         for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end();  ++setPos)
+         {
+            int ix1 = (*setPos)[0];
+            int ix2 = (*setPos)[1];
+            int ix3 = (*setPos)[2];
+
+            if(bcArray.isFluid(ix1,ix2,ix3)) //es kann sein, dass der node von einem anderen interactor z.B. als solid gemarkt wurde!!!
+            {
+               if( !bcArray.hasBC(ix1,ix2,ix3) ) continue;
+               D3Q27BoundaryConditionPtr bc = bcArray.getBC(ix1,ix2,ix3);
+
+               double x1a = val<1>(blockOrg) - val<1>(orgDelta) + ix1 * dx;
+               double x2a = val<2>(blockOrg) - val<2>(orgDelta) + ix2 * dx;
+               double x3a = val<3>(blockOrg) - val<3>(orgDelta) + ix3 * dx;
+               nodes.push_back( makeUbTuple( (float)x1a, (float)x2a, (float)x3a ) );
+               node1Index = nodes.size()-1;
+
+               for(int dir = D3Q27System::FSTARTDIR; dir<=D3Q27System::FENDDIR; dir++)
+               {
+                  if (bc->hasBoundaryConditionFlag(D3Q27System::INVDIR[dir]))
+                  {
+                     double x1b, x2b, x3b, q = bc->getQ(dir);
+                     switch(dir)
+                     {
+                     case D3Q27System::E : x1b = x1a+q*dx; x2b = x2a         ; x3b = x3a         ; break;
+                     case D3Q27System::N : x1b = x1a         ; x2b = x2a+q*dx; x3b = x3a         ; break;
+                     case D3Q27System::W : x1b = x1a-q*dx; x2b = x2a         ; x3b = x3a         ; break;
+                     case D3Q27System::S : x1b = x1a         ; x2b = x2a-q*dx; x3b = x3a         ; break;
+                     case D3Q27System::NE: x1b = x1a+q*dx; x2b = x2a+q*dx; x3b = x3a         ; break;
+                     case D3Q27System::NW: x1b = x1a-q*dx; x2b = x2a+q*dx; x3b = x3a         ; break;
+                     case D3Q27System::SW: x1b = x1a-q*dx; x2b = x2a-q*dx; x3b = x3a         ; break;
+                     case D3Q27System::SE: x1b = x1a+q*dx; x2b = x2a-q*dx; x3b = x3a         ; break;
+                     case D3Q27System::T : x1b = x1a         ; x2b = x2a         ; x3b = x3a+q*dx; break;
+                     case D3Q27System::TE: x1b = x1a+q*dx; x2b = x2a         ; x3b = x3a+q*dx; break;
+                     case D3Q27System::TN: x1b = x1a         ; x2b = x2a+q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::TW: x1b = x1a-q*dx; x2b = x2a         ; x3b = x3a+q*dx; break;
+                     case D3Q27System::TS: x1b = x1a         ; x2b = x2a-q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::B : x1b = x1a         ; x2b = x2a         ; x3b = x3a-q*dx; break;
+                     case D3Q27System::BE: x1b = x1a+q*dx; x2b = x2a         ; x3b = x3a-q*dx; break;
+                     case D3Q27System::BN: x1b = x1a         ; x2b = x2a+q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::BW: x1b = x1a-q*dx; x2b = x2a         ; x3b = x3a-q*dx; break;
+                     case D3Q27System::BS: x1b = x1a         ; x2b = x2a-q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::TNE : x1b = x1a+q*dx  ; x2b = x2a+q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::BSW : x1b = x1a-q*dx  ; x2b = x2a-q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::BNE : x1b = x1a+q*dx  ; x2b = x2a+q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::TSW : x1b = x1a-q*dx  ; x2b = x2a-q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::TSE : x1b = x1a+q*dx  ; x2b = x2a-q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::BNW : x1b = x1a-q*dx  ; x2b = x2a+q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::BSE : x1b = x1a+q*dx  ; x2b = x2a-q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::TNW : x1b = x1a-q*dx  ; x2b = x2a+q*dx; x3b = x3a+q*dx; break;
+                     default: throw UbException(UB_EXARGS,"unknown direction");
+                     }
+
+                     nodes.push_back( makeUbTuple( (float)x1b, (float)x2b, (float)x3b ) );
+                     node2Index = nodes.size()-1;
+
+                     lines.push_back( makeUbTuple( (int)node1Index, (int)node2Index) );
+                  }
+               }
+            }
+         }
+      }
+}
+////////////////////////////////////////////////////////////////////////////
+vector< pair<GbPoint3D,GbPoint3D> >  D3Q27Interactor::getQsLineSet()
+{
+   vector< pair<GbPoint3D,GbPoint3D> >  QsLineSet;
+   pair<GbPoint3D,GbPoint3D> pointpair;
+
+   UbTupleInt3 blocknx = grid.lock()->getBlockNX();
+
+   int blocknx1 = val<1>(blocknx);
+   int blocknx2 = val<2>(blocknx);
+   int blocknx3 = val<3>(blocknx);
+   //   vector<double> deltaT = grid->getD3Q27Calculator()->getDeltaT();
+
+   BOOST_FOREACH(Block3DPtr block, transBlocks)
+   {
+      LBMKernel3DPtr kernel = block->getKernel();
+      BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+      //double collFactor = ((LbD3Q27Calculator*)grid->getCalculator())->getCollisionsFactors()[block->getLevel()];
+      //checken ob obere reihe doppelt im system vorhanden oder nicht
+      bool include_N_Face  = false; //x1=[0..blocknx1[ && x3=[0..blocknx3[
+      bool include_E_Face  = false; //x2=[0..blocknx2[ && x3=[0..blocknx3[
+      bool include_T_Face  = false; //x1=[0..blocknx1[ && x2=[0..blocknx2[
+      bool include_NE_Edge = false; //(x1/x2/x3)=(blocknx1/blocknx2/[0..blocknx3[)
+      bool include_TN_Edge = false; //(x1/x2/x3)=([0..blocknx1[/blocknx2/blocknx1)
+      bool include_TE_Edge = false; //(x1/x2/x3)=(blocknx1/[0..blocknx2[/blocknx2)
+      if(block)
+      {
+         if( !block->getConnector(D3Q27System::N ) ) include_N_Face  = true;
+         if( !block->getConnector(D3Q27System::E ) ) include_E_Face  = true;
+         if( !block->getConnector(D3Q27System::T ) ) include_T_Face  = true;
+         if( !block->getConnector(D3Q27System::NE) && include_N_Face && include_E_Face ) include_NE_Edge = true;
+         if( !block->getConnector(D3Q27System::TN) && include_T_Face && include_N_Face ) include_TN_Edge = true;
+         if( !block->getConnector(D3Q27System::TE) && include_T_Face && include_E_Face ) include_TE_Edge = true;
+      }
+
+      //      double dT = deltaT[block->getLevel()];
+
+      map<Block3DPtr, set< std::vector<int> > >::iterator pos = transNodeIndicesMap.find(block);
+      if(pos==transNodeIndicesMap.end()) throw UbException(UB_EXARGS,"block nicht in indizes map!!!"+block->toString());
+      set< std::vector<int> >& transNodeIndicesSet = pos->second;
+      set< std::vector<int> >::iterator setPos;
+
+      double x1,x2,x3,dx;
+      grid.lock()->calcStartCoordinatesAndDelta(block,x1,x2,x3,dx);
+
+      //cout<<"getQs: "<<transBlockSet->size()<<" "<<transNodeIndicesVec.size()<<endl;
+
+      for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end();  ++setPos)
+      {
+         int ix1 = (*setPos)[0];
+         int ix2 = (*setPos)[1];
+         int ix3 = (*setPos)[2];
+
+         if(   ( ix1<blocknx1 && ix2<blocknx2 && ix3<blocknx3 ) //std fall
+            || ( include_E_Face  && ix1==blocknx1 && ix2<blocknx2  && ix3<blocknx3  )
+            || ( include_N_Face  && ix2==blocknx2 && ix1<blocknx1  && ix3<blocknx3  )
+            || ( include_T_Face  && ix3==blocknx3 && ix1<blocknx1  && ix2<blocknx2  )
+            || ( include_NE_Edge && ix1==blocknx1 && ix2==blocknx2 )
+            || ( include_TN_Edge && ix2==blocknx2 && ix3==blocknx3 )
+            || ( include_TE_Edge && ix1==blocknx1 && ix3==blocknx3 ) ) //ansonsten doppelt im kraftwert
+         {
+            if(bcMatrix.isFluid(ix1,ix2,ix3)) //es kann sein, dass der node von einem anderen interactor z.B. als solid gemarkt wurde!!!
+            {
+               if( !bcMatrix.hasBC(ix1,ix2,ix3) ) continue;
+               D3Q27BoundaryConditionPtr bc = bcMatrix.getBC(ix1,ix2,ix3);
+               double x1a = x1+dx * ix1;
+               double x2a = x2+dx * ix2;
+               double x3a = x3+dx * ix3;
+               pointpair.first.setX1(x1a);
+               pointpair.first.setX2(x2a);
+               pointpair.first.setX3(x3a);
+               for(int dir = D3Q27System::FSTARTDIR; dir<=D3Q27System::FENDDIR; dir++)
+               {
+                  if (bc->hasBoundaryConditionFlag(D3Q27System::INVDIR[dir]))
+                  {
+                     double x1b, x2b, x3b, q = bc->getQ(dir);
+                     switch(dir)
+                     {
+                     case D3Q27System::E : x1b = x1a+q*dx; x2b = x2a         ; x3b = x3a         ; break;
+                     case D3Q27System::N : x1b = x1a         ; x2b = x2a+q*dx; x3b = x3a         ; break;
+                     case D3Q27System::W : x1b = x1a-q*dx; x2b = x2a         ; x3b = x3a         ; break;
+                     case D3Q27System::S : x1b = x1a         ; x2b = x2a-q*dx; x3b = x3a         ; break;
+                     case D3Q27System::NE: x1b = x1a+q*dx; x2b = x2a+q*dx; x3b = x3a         ; break;
+                     case D3Q27System::NW: x1b = x1a-q*dx; x2b = x2a+q*dx; x3b = x3a         ; break;
+                     case D3Q27System::SW: x1b = x1a-q*dx; x2b = x2a-q*dx; x3b = x3a         ; break;
+                     case D3Q27System::SE: x1b = x1a+q*dx; x2b = x2a-q*dx; x3b = x3a         ; break;
+                     case D3Q27System::T : x1b = x1a         ; x2b = x2a         ; x3b = x3a+q*dx; break;
+                     case D3Q27System::TE: x1b = x1a+q*dx; x2b = x2a         ; x3b = x3a+q*dx; break;
+                     case D3Q27System::TN: x1b = x1a         ; x2b = x2a+q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::TW: x1b = x1a-q*dx; x2b = x2a         ; x3b = x3a+q*dx; break;
+                     case D3Q27System::TS: x1b = x1a         ; x2b = x2a-q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::B : x1b = x1a         ; x2b = x2a         ; x3b = x3a-q*dx; break;
+                     case D3Q27System::BE: x1b = x1a+q*dx; x2b = x2a         ; x3b = x3a-q*dx; break;
+                     case D3Q27System::BN: x1b = x1a         ; x2b = x2a+q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::BW: x1b = x1a-q*dx; x2b = x2a         ; x3b = x3a-q*dx; break;
+                     case D3Q27System::BS: x1b = x1a         ; x2b = x2a-q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::TNE : x1b = x1a+q*dx  ; x2b = x2a+q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::BSW : x1b = x1a-q*dx  ; x2b = x2a-q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::BNE : x1b = x1a+q*dx  ; x2b = x2a+q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::TSW : x1b = x1a-q*dx  ; x2b = x2a-q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::TSE : x1b = x1a+q*dx  ; x2b = x2a-q*dx; x3b = x3a+q*dx; break;
+                     case D3Q27System::BNW : x1b = x1a-q*dx  ; x2b = x2a+q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::BSE : x1b = x1a+q*dx  ; x2b = x2a-q*dx; x3b = x3a-q*dx; break;
+                     case D3Q27System::TNW : x1b = x1a-q*dx  ; x2b = x2a+q*dx; x3b = x3a+q*dx; break;
+                     default: throw UbException(UB_EXARGS,"unknown direction");
+                     }
+                     pointpair.second.setX1(x1b);
+                     pointpair.second.setX2(x2b);
+                     pointpair.second.setX3(x3b);
+                     QsLineSet.push_back(pointpair);
+                  }
+               }
+
+            }
+         }
+      }
+   }
+   //cout<<"getQs: "<<QsLineSet.size()<<endl;
+   return QsLineSet;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void D3Q27Interactor::removeBoundaryInformationOnTransNodes()
+{
+//   if(this->reinitWithStoredQsFlag) return;
+//
+//   oldSolidBlockSet.clear();
+//   vector<Block3D*>& solidBlocks = *this->getSolidBlockSet();
+//   for(int i=0; i<(int)solidBlocks.size(); i++)
+//   {
+//      oldSolidBlockSet.push_back(solidBlocks[i]);
+//
+//      solidBlocks[i]->setActive(true); //<- quick n dirty
+//      D3Q27Block* bvd = (D3Q27Block*) solidBlocks[i]->getBlock();
+//      D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+//
+//      for(int ix1=bcMatrix.getNX1()-1; ix1>=0; ix1--)
+//         for(int ix2=bcMatrix.getNX2()-1; ix2>=0; ix2--)
+//            for(int ix3=bcMatrix.getNX3()-1; ix3>=0; ix3--)
+//               bcMatrix.setFluid(ix1,ix2,ix3);
+//   }
+//   //BC wird entfernt und node wird Fluid-Node
+//   oldSolidNodeIndicesMap.clear();
+//   for(int b=0; b<(int)transBlockSet->size(); b++)
+//   {
+//      Block3D*& block = (*transBlockSet)[b];
+//      D3Q27Block* bvd = (D3Q27Block*)block->getBlock();
+//      D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+//      map<Block3D*, set< UbTupleInt3 > >::iterator pos = transNodeIndicesMap.find(block);
+//      if(pos==transNodeIndicesMap.end()) throw UbException(UB_EXARGS,"block nicht in indizes map!!!");
+////new active node stuff//
+//      oldTransNodeIndicesMap[block] = set< UbTupleInt3LongLong >();
+//      set< UbTupleInt3LongLong >& oldTransNodeIndices = oldTransNodeIndicesMap[block];
+////new active node stuff//
+//      set< UbTupleInt3 >& transNodeIndicesSet = pos->second;
+//      set< UbTupleInt3 >::iterator setPos;
+//      for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end();  ++setPos)
+//      {
+////new active node stuff//
+//         D3Q27BoundaryCondition* bc = bcMatrix.getBC(val<1>(*setPos),val<2>(*setPos),val<3>(*setPos));
+//         if(bc) oldTransNodeIndices.insert(UbTupleInt3LongLong(val<1>(*setPos),val<2>(*setPos),val<3>(*setPos), bc->getNoSlipBoundary()));
+//         else UBLOG(logDEBUG5,"Warum fehlt die BC?");
+////new active node stuff//
+//         bcMatrix.setFluid(val<1>(*setPos),val<2>(*setPos),val<3>(*setPos));
+//      }
+//      transNodeIndicesSet.clear();
+//
+//      map<Block3D*, set< UbTupleInt3 > >::iterator posSolid = solidNodeIndicesMap.find(block);
+//      if(posSolid==solidNodeIndicesMap.end()) throw UbException(UB_EXARGS,"block nicht in indizes map!!!");
+//
+////new active node stuff//
+//      oldSolidNodeIndicesMap[block] = set< UbTupleInt3 >();
+//      set< UbTupleInt3 >& oldSolidNodeIndices = oldSolidNodeIndicesMap[block];
+////new active node stuff//
+//
+//      set< UbTupleInt3 >& solidNodeIndicesSet = posSolid->second;
+//      //set< UbTupleInt3 >::iterator setPos;
+//      for(setPos=solidNodeIndicesSet.begin(); setPos!=solidNodeIndicesSet.end();  ++setPos)
+//      {
+//         oldSolidNodeIndices.insert(UbTupleInt3(val<1>(*setPos),val<2>(*setPos),val<3>(*setPos)));
+//         bcMatrix.setFluid(val<1>(*setPos),val<2>(*setPos),val<3>(*setPos));
+//      }
+//      solidNodeIndicesSet.clear();
+//   }
+//   transNodeIndicesMap.clear();
+//   solidNodeIndicesMap.clear();
+//
+//   this->removeTransBlocks();
+//   this->removeSolidBlocks();
+}
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27Interactor::updateMovedGeometry(const double& timeStep)
+//{
+//   //*************quick n dirty***********
+//   //achtung stark vereinfacht, damit es ueberhaupt geht
+//   //zuvor musste fuer alle interactoren removeBoundaryInformationOnTransNodes aufgerufen werden
+//
+//   //alle notActive blocke active setzen und alle nodes als fluid
+//   //haut natuerlich nur hin, wenn kein block zwei interactoren hat...
+//   //nodes muessen zuvor initilaisiert sein, sonst geht goar nichts
+//
+//   //vector<Block3D*>& solidBlocks = *this->getSolidBlockSet();
+//   //for(int i=0; i<(int)solidBlocks.size(); i++)
+//   //{
+//   //   solidBlocks[i]->setActive(true); //<- quick n dirty
+//   //   D3Q27Block* bvd = (D3Q27Block*) solidBlocks[i]->getBlock();
+//   //   D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+//
+//   //   for(int ix1=bcMatrix.getNX1()-1; ix1>=0; ix1--)
+//   //      for(int ix2=bcMatrix.getNX2()-1; ix2>=0; ix2--)
+//   //         for(int ix3=bcMatrix.getNX3()-1; ix3>=0; ix3--)
+//   //            bcMatrix.setFluid(ix1,ix2,ix3);
+//   //}
+//
+//   //vector<Block3D*>& transBlocks = *this->getTransBlockSet();
+//   //for(int i=0; i<(int)transBlocks.size(); i++)
+//   //{
+//   //   transBlocks[i]->setActive(true); //<- quick n dirty
+//   //   D3Q27Block* bvd = (D3Q27Block*) transBlocks[i]->getBlock();
+//   //   D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+//
+//   //   for(int ix1=bcMatrix.getNX1()-1; ix1>=0; ix1--)
+//   //      for(int ix2=bcMatrix.getNX2()-1; ix2>=0; ix2--)
+//   //         for(int ix3=bcMatrix.getNX3()-1; ix3>=0; ix3--)
+//   //            bcMatrix.setFluid(ix1,ix2,ix3);
+//   //}
+//
+//   //komplett neu initialisieren
+//   //1. velcBC aktualisieren
+//   bool hasVelBC = false;
+//   for(int index=(int)bcAdapterVector.size()-1; index>=0; --index)
+//   {
+//      D3Q27VelocityBCAdapter* velBC = dynamic_cast<D3Q27VelocityBCAdapter*>(bcAdapterVector[index].get());
+//      if(velBC)
+//      {
+//         velBC->setNewVelocities(this->getVelocityX1(),0,D3Q27BCFunction::INFCONST,
+//                                 this->getVelocityX2(),0,D3Q27BCFunction::INFCONST,
+//                                 this->getVelocityX3(),0,D3Q27BCFunction::INFCONST );
+//         hasVelBC = true; 
+//      }
+//   }
+//   if(!hasVelBC) throw UbException(UB_EXARGS,"movingInteractors MUESSEN velBC besitzen");
+//
+//   //2. einfach nochmal initialisieren
+//   D3Q27Interactor::initInteractor(timeStep);  //damit nicht die BCs wieder initialisert werden
+//   this->updateNewNodes();
+//}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27Interactor::updateNewNodes()
+//{
+//   if(!grid) throw UbException(UB_EXARGS,"no grid");
+//
+////new active node stuff//
+//   std::map<Block3D*, std::set< UbTupleInt3 > > newFluidNodeIndicesMap;
+//   for(size_t i=0; i<this->oldSolidBlockSet.size(); i++)
+//   {
+//      Block3D* oldsolidblock = oldSolidBlockSet[i];
+//      for(size_t b=0; b<transBlockSet->size(); b++)
+//      {
+//         Block3D* block = (*transBlockSet)[b];
+//         if(oldsolidblock==block)
+//         {
+//            newFluidNodeIndicesMap[block] = set< UbTupleInt3 >();
+//            set< UbTupleInt3 >& newFluidNodeIndices = newFluidNodeIndicesMap[block];
+//
+//            D3Q27Block* bvd = dynamic_cast<D3Q27Block*>(block->getBlock());
+//            if(!bvd) throw UbException(UB_EXARGS,"kein D3Q27Block");
+//            D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+//
+//            for(int ix1=bcMatrix.getNX1()-1; ix1>=0; ix1--)
+//               for(int ix2=bcMatrix.getNX2()-1; ix2>=0; ix2--)
+//                  for(int ix3=bcMatrix.getNX3()-1; ix3>=0; ix3--)
+//                     if(bcMatrix.isFluid(ix1,ix2,ix3))
+//                        newFluidNodeIndices.insert(UbTupleInt3(ix1,ix2,ix3));
+//            //continue; <-HAEH an Geller: wozu das continue? kam da frueher noch was?
+//         }
+//      }
+//   }
+//
+//   std::map<Block3D*, std::set< UbTupleInt3 > >::iterator oldsolidpos;
+//   for(oldsolidpos=oldSolidNodeIndicesMap.begin(); oldsolidpos!=oldSolidNodeIndicesMap.end();  ++oldsolidpos)
+//   {
+//      Block3D* block = oldsolidpos->first;
+//
+//      map<Block3D*, set< UbTupleInt3 > >::iterator pos = transNodeIndicesMap.find(block);
+//      //wenn ein Block ein Solid hatte sollte er in der TransBlockListe sein
+//      //es sei denn der Block hat jetzt alle Solid und ist somit bei den SolidBl�cken
+//      if(pos==transNodeIndicesMap.end()) 
+//         continue;
+//         //throw UbException(UB_EXARGS,"block nicht in indizes map!!!");
+//
+//      set< UbTupleInt3 >& transNodeIndicesSet = pos->second;
+//      set< UbTupleInt3 >& oldSolidIndicesSet = oldsolidpos->second;
+//      set< UbTupleInt3 >::iterator setPos1;
+//      set< UbTupleInt3 >::iterator setPos2;
+//
+//      for(setPos1=oldSolidIndicesSet.begin(); setPos1!=oldSolidIndicesSet.end();  ++setPos1)
+//      {
+//         int osix1 = val<1>(*setPos1);
+//         int osix2 = val<2>(*setPos1);
+//         int osix3 = val<3>(*setPos1);
+//         for(setPos2=transNodeIndicesSet.begin(); setPos2!=transNodeIndicesSet.end();  ++setPos2)
+//         {
+//            int tix1 = val<1>(*setPos2);
+//            int tix2 = val<2>(*setPos2);
+//            int tix3 = val<3>(*setPos2);
+//            if((osix1==tix1) && (osix2==tix2) && (osix3==tix3))
+//            {
+//               map<Block3D*, set< UbTupleInt3 > >::iterator posX = newFluidNodeIndicesMap.find(block);
+//               if(posX==newFluidNodeIndicesMap.end()) newFluidNodeIndicesMap[block] = set< UbTupleInt3 >();
+//
+//               set< UbTupleInt3 >& newFluidNodeIndices = newFluidNodeIndicesMap[block];
+//               newFluidNodeIndices.insert(UbTupleInt3(tix1,tix2,tix3));
+//            }
+//         }
+//      }
+//   }
+////hier wird gepr�ft ob ein Randknoten die Seite wechselt
+//   std::map<Block3D*, std::set< UbTupleInt3LongLong > >::iterator oldtranspos;
+//   for(oldtranspos=oldTransNodeIndicesMap.begin(); oldtranspos!=oldTransNodeIndicesMap.end();  ++oldtranspos)
+//   {
+//      Block3D* block = oldtranspos->first;
+//
+//      map<Block3D*, set< UbTupleInt3 > >::iterator pos = transNodeIndicesMap.find(block);
+//      //wenn ein Block ein Solid hatte sollte er in der TransBlockListe sein
+//      //es sei denn der Block hat jetzt alle Solid und ist somit bei den SolidBl�cken
+//      if(pos==transNodeIndicesMap.end()) 
+//         continue;
+//      //throw UbException(UB_EXARGS,"block nicht in indizes map!!!");
+//
+//      set< UbTupleInt3 >&        transNodeIndicesSet = pos->second;
+//      set< UbTupleInt3LongLong >& oldTransIndicesSet = oldtranspos->second;
+//      set< UbTupleInt3LongLong >::iterator setPos1;
+//      set< UbTupleInt3 >::iterator setPos2;
+//
+//      D3Q27Block* bvd = dynamic_cast<D3Q27Block*>(block->getBlock());
+//      D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+//
+//      for(setPos1=oldTransIndicesSet.begin(); setPos1!=oldTransIndicesSet.end();  ++setPos1)
+//      {
+//         int osix1 = val<1>(*setPos1);
+//         int osix2 = val<2>(*setPos1);
+//         int osix3 = val<3>(*setPos1);
+//         for(setPos2=transNodeIndicesSet.begin(); setPos2!=transNodeIndicesSet.end();  ++setPos2)
+//         {
+//            int tix1 = val<1>(*setPos2);
+//            int tix2 = val<2>(*setPos2);
+//            int tix3 = val<3>(*setPos2);
+//            if((osix1==tix1) && (osix2==tix2) && (osix3==tix3))
+//            {
+//               long long oldNoSlipBoundary = val<4>(*setPos1);
+//               D3Q27BoundaryCondition* bc = bcMatrix.getBC(tix1,tix2,tix3);
+//               long long newNoSlipBoundary = bc->getNoSlipBoundary();
+//
+//               if(oldNoSlipBoundary==newNoSlipBoundary) continue;
+//               bool newNode = false;
+//               for(int fdir=D3Q27System::STARTF; fdir<=D3Q27System::ENDF; fdir++)
+//               {
+//                  int invDir = D3Q27System::getInvertDirection(fdir);
+//                  //vom 2D code
+//                  //if(((oldNoSlipBoundary&(1<<fdir))==(1<<fdir)) && ((newNoSlipBoundary&(1<<invDir))==(1<<invDir)))
+//                  //{
+//                  //   if((oldNoSlipBoundary&(1<<invDir))==(1<<invDir)) continue;
+//                  //   newNode = true;
+//                  //}
+//                  if((((oldNoSlipBoundary>>(D3Q27BoundaryCondition::optionDigits*fdir)) & D3Q27BoundaryCondition::maxOptionVal) != 0)  
+//                   &&(((newNoSlipBoundary>>(D3Q27BoundaryCondition::optionDigits*invDir)) & D3Q27BoundaryCondition::maxOptionVal) != 0))
+//                  {
+//                     if(((oldNoSlipBoundary>>(D3Q27BoundaryCondition::optionDigits*invDir)) & D3Q27BoundaryCondition::maxOptionVal) != 0) continue;
+//                     newNode = true;
+//                  }
+//               }
+//               if(newNode)
+//               {
+//                  map<Block3D*, set< UbTupleInt3 > >::iterator posX = newFluidNodeIndicesMap.find(block);
+//                  if(posX==newFluidNodeIndicesMap.end()) newFluidNodeIndicesMap[block] = set< UbTupleInt3 >();
+//
+//                  set< UbTupleInt3 >& newFluidNodeIndices = newFluidNodeIndicesMap[block];
+//                  newFluidNodeIndices.insert(UbTupleInt3(tix1,tix2,tix3));
+//               }
+//            }
+//         }
+//      }
+//   }
+////<hier wird gepr�ft ob ein Randknoten die Seite wechselt
+//
+//   //cout<<"newFluidNodeIndicesMap:"<<newFluidNodeIndicesMap.size()<<endl;
+//   std::map<Block3D*, std::set< UbTupleInt3 > >::iterator newfluidpos;
+//   D3Q27PatchGrid* grid = dynamic_cast<D3Q27PatchGrid*>(this->grid);
+//   for(newfluidpos=newFluidNodeIndicesMap.begin(); newfluidpos!=newFluidNodeIndicesMap.end();  ++newfluidpos)
+//   {
+//      Block3D* block = newfluidpos->first;
+//      D3Q27Block* bvd = dynamic_cast<D3Q27Block*>(block->getBlock());
+//      if(!bvd) throw UbException(UB_EXARGS,"kein D3Q27Block");
+//      bvd->getTimer().start();
+//
+//      set< UbTupleInt3 >& newNodes = newfluidpos->second;
+//      UBLOGML(logDEBUG4,"\n set-size:"<<newNodes.size());
+//      bvd->makeInternalIterations(grid,block->getLevel(),newNodes);
+//
+//      bvd->getTimer().stop();
+//
+//   }
+//   //end new active node stuff//
+//}
+////////////////////////////////////////////////////////////////////////////
+//UbTupleDouble3 D3Q27Interactor::getForces()
+//{
+//   D3Q27PatchGrid* grid = dynamic_cast<D3Q27PatchGrid*>(this->grid);
+//   if(!grid) throw UbException(UB_EXARGS,"grid is not a D3Q27PatchGrid");
+//
+//   int blocknx1 = grid->getBlockNX1();
+//   int blocknx2 = grid->getBlockNX2();
+//   int blocknx3 = grid->getBlockNX3();
+//   vector<double> deltaT = grid->getD3Q27Calculator()->getDeltaT();
+//
+//   double forceX1=0.0, forceX2=0.0, forceX3=0.0;
+//
+//   //!!// for(size_t b=0; b<transBlockSet->size(); b++)
+//   //!!// {
+//   //!!//    Block3D*& block = (*transBlockSet)[b];
+//
+//   std::map<Block3D*, std::set< UbTupleInt3 > >::iterator pos;
+//   for ( pos=transNodeIndicesMap.begin() ; pos != transNodeIndicesMap.end(); pos++ )
+//   {
+//      Block3D* block = pos->first;
+//      
+//      if( block->isNotActive() ) 
+//      {
+//         continue;
+//      }
+//      
+//      D3Q27Block* bvd = (D3Q27Block*)block->getBlock();
+//      D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+//
+//      //pruefen ob obere reihe doppelt im system vorhanden oder nicht
+//      //ACHTUNG: so macht es probleme bei bloecken unterschiedlicher Leveltiefe
+//      bool include_N_Face  = false; //x1=[0..blocknx1[ && x3=[0..blocknx3[
+//      bool include_E_Face  = false; //x2=[0..blocknx2[ && x3=[0..blocknx3[
+//      bool include_T_Face  = false; //x1=[0..blocknx1[ && x2=[0..blocknx2[
+//      bool include_NE_Edge = false; //(x1/x2/x3)=(blocknx1/blocknx2/[0..blocknx3[)
+//      bool include_TN_Edge = false; //(x1/x2/x3)=([0..blocknx1[/blocknx2/blocknx1)
+//      bool include_TE_Edge = false; //(x1/x2/x3)=(blocknx1/[0..blocknx2[/blocknx2)
+//      if( !bvd->getConnector(D3Q27System::N ) ) include_N_Face  = true;
+//      if( !bvd->getConnector(D3Q27System::E ) ) include_E_Face  = true;
+//      if( !bvd->getConnector(D3Q27System::T ) ) include_T_Face  = true;
+//      if( !bvd->getConnector(D3Q27System::NE) && include_N_Face && include_E_Face ) include_NE_Edge = true;
+//      if( !bvd->getConnector(D3Q27System::TN) && include_T_Face && include_N_Face ) include_TN_Edge = true;
+//      if( !bvd->getConnector(D3Q27System::TE) && include_T_Face && include_E_Face ) include_TE_Edge = true;
+//
+//      if( (int)deltaT.size()<=block->getLevel() )
+//         throw UbException(UB_EXARGS, "ups, no deltaT for that level... delta not initialized in grid?");
+//      double dT = deltaT[block->getLevel()];
+//
+//  //!!// map<Block3D*, set< UbTupleInt3 > >::iterator pos = transNodeIndicesMap.find(block);
+//      if(pos==transNodeIndicesMap.end()) throw UbException(UB_EXARGS,"block nicht in indizes map!!!"+block->toString());
+//      set< UbTupleInt3 >& transNodeIndicesSet = pos->second;
+//      set< UbTupleInt3 >::iterator setPos;
+//      for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end();  ++setPos)
+//      {
+//         int x1 = val<1>(*setPos);
+//         int x2 = val<2>(*setPos);
+//         int x3 = val<3>(*setPos);
+//
+//         if(   ( x1<blocknx1 && x2<blocknx2 && x3<blocknx3 ) //std fall
+//            || ( include_E_Face  && x1==blocknx1 && x2<blocknx2  && x3<blocknx3  )
+//            || ( include_N_Face  && x2==blocknx2 && x1<blocknx1  && x3<blocknx3  )
+//            || ( include_T_Face  && x3==blocknx3 && x1<blocknx1  && x2<blocknx2  )
+//            || ( include_NE_Edge && x1==blocknx1 && x2==blocknx2 )
+//            || ( include_TN_Edge && x2==blocknx2 && x3==blocknx3 )
+//            || ( include_TE_Edge && x1==blocknx1 && x3==blocknx3 ) ) //ansonsten doppelt im kraftwert
+//         {
+//            if(bcMatrix.isFluid(x1,x2,x3)) //es kann sein, dass der node von einem anderen interactor z.B. als solid gemarkt wurde!!!
+//            {
+//               UbTupleDouble3 forceVec = bvd->getForces(x1,x2,x3,dT);
+//               forceX1 += val<1>(forceVec);
+//               forceX2 += val<2>(forceVec);
+//               forceX3 += val<3>(forceVec);
+//            }
+//         }
+//      }
+//   }
+//   // Bisher wurde die Reaktionskraft der geometrie berechnet,
+//   // Kraft des Fluids ist entgegengesetzt gleich gross -> return -force
+//   return UbTupleDouble3(-forceX1,-forceX2,-forceX3);
+//}
+////////////////////////////////////////////////////////////////////////////
+//string D3Q27Interactor::toString()
+//{
+//   stringstream ss;
+//   ss<< "Interactor3D[label="<<this->getName();
+//   if(this->isSolid()) ss<<", solid";
+//   if(this->isInverseSolid()) ss<<", inversesolid";
+//   if(this->isTimeDependent()) ss<<", timedependent";
+//   if(geoObject3D!=NULL) ss<<", Interactor3D: "<<geoObject3D->toString();
+//   ss<<"]";
+//
+//   return ss.str();
+//}
+////////////////////////////////////////////////////////////////////////////
+//void D3Q27Interactor::write(UbFileOutput* out)
+//{
+//   Interactor3D::write(out);
+//   out->writeLine();
+//
+//   out->writeString("D3Q27InteractorBCAdapter");
+//   out->writeInteger((int)bcAdapterVector.size());
+//   for(int i=0; i<(int)bcAdapterVector.size(); i++)
+//   {
+//      out->writeLine();
+//      bcAdapterVector[i]->write(out);
+//   }
+//}
+//////////////////////////////////////////////////////////////////////////
+//void D3Q27Interactor::read(UbFileInput* in)
+//{
+//   this->initRayVectors();
+//   transNodeIndicesMap.clear();
+//
+//   Interactor3D::read(in);
+//   in->readLine();
+//
+//   in->readString();
+//   bcAdapterVector.resize(in->readInteger(),MbSmartPtr<D3Q27BoundaryConditionAdapter>(NULL));
+//   for(int i=0; i<(int)bcAdapterVector.size(); i++)
+//   {
+//      in->readLine();
+//      bcAdapterVector[i] = MbSmartPtr<D3Q27BoundaryConditionAdapter>(D3Q27BCAdapterFactory::getInstance()->createD3Q27BCAdapter(in));
+//   }
+//}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27Interactor::writeValidationAVSFile(string filename)
+{
+   UBLOG(logINFO,"D3Q27Interactor::writeValidationAVSFile("<<filename<<") - start ");
+   ofstream out(filename.c_str(),ios::out);
+   if(!out) throw UbException(UB_EXARGS,"couldn't open file "+filename);
+
+   int numpoints, numlines;
+   vector< pair<GbPoint3D,GbPoint3D> > qsLineSet = this->getQsLineSet();
+   numlines  = (unsigned)qsLineSet.size();
+   numpoints = numlines*2;
+
+   out<<"# UCD-File created by D3Q27Interactor\n";
+   out<<numpoints<<" "<<numlines<<" 0 0 0 "<<endl;
+   int nr=1;
+   for (int i=0; i<numlines; i++)
+   {
+      out<<nr++<<" "<<qsLineSet[i].first.getX1Coordinate() <<" " <<qsLineSet[i].first.getX2Coordinate() <<" " <<qsLineSet[i].first.getX3Coordinate() <<" \n";
+      out<<nr++<<" "<<qsLineSet[i].second.getX1Coordinate()<<" " <<qsLineSet[i].second.getX2Coordinate()<<" " <<qsLineSet[i].second.getX3Coordinate() <<" \n";
+   }
+   nr = 1;
+   for (int i=0; i<numlines; i++)
+   {
+      int el = nr+1;
+      out<<i+1<<" "<<2<<" line "<<nr<<" "<<el<<" "<<endl;
+      nr=el+1;
+   }
+   UBLOG(logINFO,"D3Q27Interactor::writeValidationAVSFile("<<filename<<") - end");
+}
+//////////////////////////////////////////////////////////////////////////
+//string D3Q27Interactor::writeTransNodes(string filename)
+//{
+//   D3Q27PatchGrid* grid = dynamic_cast<D3Q27PatchGrid*>(this->grid);
+//   if(!grid) throw UbException(UB_EXARGS,"grid is not a D3Q27PatchGrid");
+//
+//   int blocknx1 = grid->getBlockNX1();
+//   int blocknx2 = grid->getBlockNX2();
+//   int blocknx3 = grid->getBlockNX3();
+//
+//   vector< UbTupleFloat3 > nodes;
+//   vector< string > datanames;
+//   datanames.push_back("rho");
+//   datanames.push_back("vx1");
+//   datanames.push_back("vx2");
+//   datanames.push_back("vx3");
+//   vector< vector < double > > nodedata(datanames.size());
+//
+//   double orgX1,orgX2,orgX3,deltaX;
+//
+//   for(size_t b=0; b<transBlockSet->size(); b++)
+//   {
+//      Block3D*& block = (*transBlockSet)[b];
+//
+//      map<Block3D*, set< UbTupleInt3 > >::iterator pos = transNodeIndicesMap.find(block);
+//      if(pos==transNodeIndicesMap.end()) throw UbException(UB_EXARGS,"block nicht in indizes map!!!"+block->toString());
+//
+//      D3Q27Block* bvd = (D3Q27Block*)block->getBlock();
+//      D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+//      D3Q27DistributionsMatrix&              fMatrix  = *bvd->getDistributionMatrix();
+//      
+//      grid->calcStartCoordinatesAndDelta(block,orgX1,orgX2,orgX3,deltaX);
+//
+//      bool include_N_Face  = false; //x1=[0..blocknx1[ && x3=[0..blocknx3[
+//      bool include_E_Face  = false; //x2=[0..blocknx2[ && x3=[0..blocknx3[
+//      bool include_T_Face  = false; //x1=[0..blocknx1[ && x2=[0..blocknx2[
+//      bool include_NE_Edge = false; //(x1/x2/x3)=(blocknx1/blocknx2/[0..blocknx3[)
+//      bool include_TN_Edge = false; //(x1/x2/x3)=([0..blocknx1[/blocknx2/blocknx1)
+//      bool include_TE_Edge = false; //(x1/x2/x3)=(blocknx1/[0..blocknx2[/blocknx2)
+//      if( !bvd->getConnector(D3Q27System::N ) ) include_N_Face  = true;
+//      if( !bvd->getConnector(D3Q27System::E ) ) include_E_Face  = true;
+//      if( !bvd->getConnector(D3Q27System::T ) ) include_T_Face  = true;
+//      if( !bvd->getConnector(D3Q27System::NE) && include_N_Face && include_E_Face ) include_NE_Edge = true;
+//      if( !bvd->getConnector(D3Q27System::TN) && include_T_Face && include_N_Face ) include_TN_Edge = true;
+//      if( !bvd->getConnector(D3Q27System::TE) && include_T_Face && include_E_Face ) include_TE_Edge = true;
+//      
+//      set< UbTupleInt3 >& transNodeIndicesSet = pos->second;
+//      set< UbTupleInt3 >::iterator setPos;
+//
+//      for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end();  ++setPos)
+//      {
+//         int ix1 = val<1>(*setPos);
+//         int ix2 = val<2>(*setPos);
+//         int ix3 = val<3>(*setPos);
+//         if(   ( ix1<blocknx1 && ix2<blocknx2 && ix3<blocknx3 ) //std fall
+//            || ( include_E_Face  && ix1==blocknx1 && ix2<blocknx2  && ix3<blocknx3  )
+//            || ( include_N_Face  && ix2==blocknx2 && ix1<blocknx1  && ix3<blocknx3  )
+//            || ( include_T_Face  && ix3==blocknx3 && ix1<blocknx1  && ix2<blocknx2  )
+//            || ( include_NE_Edge && ix1==blocknx1 && ix2==blocknx2 )
+//            || ( include_TN_Edge && ix2==blocknx2 && ix3==blocknx3 )
+//            || ( include_TE_Edge && ix1==blocknx1 && ix3==blocknx3 ) ) //ansonsten doppelt im kraftwert
+//         {
+//            if(bcMatrix.isFluid(ix1,ix2,ix3)) //es kann sein, dass der node von einem anderen interactor z.B. als solid gemarkt wurde!!!
+//            {
+//               nodes.push_back(makeUbTuple(  float( orgX1 + ix1 * deltaX )
+//                                           , float( orgX2 + ix2 * deltaX )
+//                                           , float( orgX3 + ix3 * deltaX ) ));
+//
+//               if(grid->getCollisionModel()!=D3Q27System::UNDEFINED)
+//               {
+//                  LBMReal* f = fMatrix.getStartAdressOfSortedArray(ix1,ix2,ix3,0);
+//                  nodedata[0].push_back( D3Q27System::getDensity(f) );
+//
+//                  if(D3Q27System::isCompModel(grid->getCollisionModel()))
+//                  {
+//                     nodedata[1].push_back( D3Q27System::getCompVelocityX1(f) );
+//                     nodedata[2].push_back( D3Q27System::getCompVelocityX2(f) );
+//                     nodedata[3].push_back( D3Q27System::getCompVelocityX3(f) );
+//                  }
+//                  else
+//                  {
+//                     nodedata[1].push_back( D3Q27System::getIncompVelocityX1(f) );
+//                     nodedata[2].push_back( D3Q27System::getIncompVelocityX2(f) );
+//                     nodedata[3].push_back( D3Q27System::getIncompVelocityX3(f) );
+//                  }
+//
+//               }
+//            }
+//         }
+//      }
+//   }
+//
+//   if( nodedata[0].empty() ) 
+//      return WbWriterVtkXmlBinary::getInstance()->writeNodes(filename,nodes);
+//   
+//   return WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(filename,nodes,datanames,nodedata);
+//}
+//////////////////////////////////////////////////////////////////////////
+//string D3Q27Interactor::writeTransNodesAsTriangles(string filename)
+//{
+   //D3Q27PatchGrid* grid = dynamic_cast<D3Q27PatchGrid*>(this->grid);
+   //if(!grid) throw UbException(UB_EXARGS,"grid is not a D3Q27PatchGrid");
+
+   //int blocknx1 = grid->getBlockNX1();
+   //int blocknx2 = grid->getBlockNX2();
+   //int blocknx3 = grid->getBlockNX3();
+
+   //vector< UbTupleFloat3 > nodes;
+   //vector< UbTupleInt3 >   triangles;
+   //vector< string >        datanames;
+   //datanames.push_back("rho");
+   //datanames.push_back("vx1");
+   //datanames.push_back("vx2");
+   //datanames.push_back("vx3");
+   //vector< vector < double > > nodedata(datanames.size());
+
+   //double orgX1,orgX2,orgX3,deltaX;
+   //int counter=0;
+
+   //for(size_t b=0; b<transBlockSet->size(); b++)
+   //{
+   //   Block3D*& block = (*transBlockSet)[b];
+
+   //   map<Block3D*, set< UbTupleInt3 > >::iterator pos = transNodeIndicesMap.find(block);
+   //   if(pos==transNodeIndicesMap.end()) throw UbException(UB_EXARGS,"block not in indices map!!!"+block->toString());
+
+   //   D3Q27Block* bvd = (D3Q27Block*)block->getBlock();
+   //   D3Q27BCMatrix<D3Q27BoundaryCondition>& bcMatrix = *bvd->getBcMatrix();
+   //   D3Q27DistributionsMatrix&              fMatrix  = *bvd->getDistributionMatrix();
+
+   //   grid->calcStartCoordinatesAndDelta(block,orgX1,orgX2,orgX3,deltaX);
+
+   //   set< UbTupleInt3 >& transNodeIndicesSet = pos->second;
+   //   set< UbTupleInt3 >::iterator setPos;
+   //   CbUniformMatrix3D<float> bcs(bcMatrix.getNX1(),bcMatrix.getNX2(),bcMatrix.getNX3(),0.0f);
+
+   //   for(setPos=transNodeIndicesSet.begin(); setPos!=transNodeIndicesSet.end();  ++setPos)
+   //   {
+   //      int ix1 = val<1>(*setPos);
+   //      int ix2 = val<2>(*setPos);
+   //      int ix3 = val<3>(*setPos);
+
+   //      if(bcMatrix.isFluid(ix1,ix2,ix3)) //es kann sein, dass der node von einem anderen interactor z.B. als solid gemarkt wurde!!!
+   //      {
+   //         bcs(ix1,ix2,ix3) = 1.0f;
+   //      }
+   //   }
+
+   //   //////////////////////////////////////////////////////////////////////////
+   //   //MC (Dreicksgenerierung)
+   //   //////////////////////////////////////////////////////////////////////////
+   //   typedef McCubes::Matrix3DWrapper< CbUniformMatrix3D<float> > McMatrixWrapper;
+   //   typedef McCubes::MarchingCubes< McMatrixWrapper >            McMarchingCubesGenerator;
+   //   typedef McMarchingCubesGenerator::Vertex                     McVertex;
+   //   typedef McMarchingCubesGenerator::Triangle                   McTriangle;
+
+   //   McMatrixWrapper wrapper(&bcs);
+   //   McMarchingCubesGenerator mc(wrapper);
+
+   //   mc.set_method(true);
+   //   mc.init_all();
+   //   mc.run(1.0f);
+
+   //   const int   nofVertices  = mc.nverts();
+   //   McVertex*   mcvertices   = mc.vertices();
+   //   const int   nofTriangles = mc.ntrigs();
+   //   McTriangle* mctriangles  = mc.triangles();
+
+   //   for(int n=0; n<nofVertices; n++)
+   //   {
+   //      //Da Dreickspunkte hie rper DDefinitionauf den LB-Knoten liegen sollen
+   //      //entsprichen die Knotenkoordinaten den Matrixindizes
+   //      int ix1 = (int)(mcvertices[n].x+0.5);
+   //      int ix2 = (int)(mcvertices[n].y+0.5);
+   //      int ix3 = (int)(mcvertices[n].z+0.5);
+   //      
+   //      nodes.push_back( makeUbTuple(  (float)(orgX1 + deltaX * ix1)    
+   //                                   , (float)(orgX2 + deltaX * ix2)
+   //                                   , (float)(orgX3 + deltaX * ix3) ) );
+
+   //      if(grid->getCollisionModel()!=D3Q27System::UNDEFINED)
+   //      {
+   //         LBMReal* f = fMatrix.getStartAdressOfSortedArray(ix1,ix2,ix3,0);
+   //         nodedata[0].push_back( D3Q27System::getDensity(f) );
+
+   //         if(D3Q27System::isCompModel(grid->getCollisionModel()))
+   //         {
+   //            nodedata[1].push_back( D3Q27System::getCompVelocityX1(f) );
+   //            nodedata[2].push_back( D3Q27System::getCompVelocityX2(f) );
+   //            nodedata[3].push_back( D3Q27System::getCompVelocityX3(f) );
+   //         }
+   //         else
+   //         {
+   //            nodedata[1].push_back( D3Q27System::getIncompVelocityX1(f) );
+   //            nodedata[2].push_back( D3Q27System::getIncompVelocityX2(f) );
+   //            nodedata[3].push_back( D3Q27System::getIncompVelocityX3(f) );
+   //         }
+   //      }
+   //   }
+   //   for(int t=0; t<nofTriangles; t++)
+   //      triangles.push_back( makeUbTuple( mctriangles[t].v1+counter, mctriangles[t].v2+counter, mctriangles[t].v3+counter ) );
+
+   //   counter+=nofVertices;
+   //}
+
+   //if( nodedata[0].empty() ) 
+   //   return WbWriterVtkXmlBinary::getInstance()->writeTriangles(filename,nodes,triangles);
+
+   //return WbWriterVtkXmlBinary::getInstance()->writeTrianglesWithNodeData(filename,nodes,triangles,datanames,nodedata);
+//}
diff --git a/source/VirtualFluidsCore/Interactors/D3Q27Interactor.h b/source/VirtualFluidsCore/Interactors/D3Q27Interactor.h
new file mode 100644
index 0000000000000000000000000000000000000000..1eab8ca274d6d402c77de35310e7ff65c50ba0a1
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/D3Q27Interactor.h
@@ -0,0 +1,129 @@
+//  _    ___      __              __________      _     __
+// | |  / (_)____/ /___  ______ _/ / ____/ /_  __(_)___/ /____
+// | | / / / ___/ __/ / / / __ `/ / /_  / / / / / / __  / ___/
+// | |/ / / /  / /_/ /_/ / /_/ / / __/ / / /_/ / / /_/ (__  )
+// |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
+//
+#ifndef D3Q27INTERACTOR_H
+#define D3Q27INTERACTOR_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <list>
+#include <map>
+#include <set>
+#include <cmath>
+
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/set.hpp>
+
+#include <boost/shared_ptr.hpp>
+
+class D3Q27Interactor;
+typedef boost::shared_ptr<D3Q27Interactor> D3Q27InteractorPtr;
+
+
+#include "UbException.h"
+#include "UbTuple.h"
+#include "ObFactory.h"
+#include "CoordinateTransformation3D.h"
+#include "GbPoint3D.h"
+#include "Interactor3D.h"
+#include "BCArray3D.h"
+#include "D3Q27BoundaryConditionAdapter.h"
+#include "D3Q27BoundaryCondition.h"
+#include "D3Q27System.h"
+
+class UbFileInput;
+class UbFileOutput;
+class GbObject3D;
+
+//////////////////////////////////////////////////////////////////////////
+class D3Q27Interactor : public Interactor3D 
+{
+public:
+   D3Q27Interactor();
+   D3Q27Interactor(GbObject3DPtr geoObject3D, Grid3DPtr grid, int type);
+   D3Q27Interactor(GbObject3DPtr geoObject3D, Grid3DPtr grid, D3Q27BoundaryConditionAdapterPtr bcAdapter,  int type);
+   D3Q27Interactor(GbObject3DPtr geoObject3D, Grid3DPtr grid, D3Q27BoundaryConditionAdapterPtr bcAdapter,  int type, Interactor3D::Accuracy a);
+
+   ~D3Q27Interactor();
+
+   void setRelevantForForces(const bool& value) {  this->relevantForForces = value; }
+   bool isRelevantForForces() { return this->relevantForForces; }
+   //UbTupleDouble3 getForces();
+   //UbTupleDouble3 getForces(Patch3DPtr patch);
+
+   virtual void addBCAdapter(const D3Q27BoundaryConditionAdapterPtr bcAdapter) { bcAdapterVector.push_back(bcAdapter); }
+   void deleteBCAdapter() { bcAdapterVector.clear(); }
+   //virtual std::vector< MbSmartPtr<D3Q27BoundaryConditionAdapter> > getBcAdapters() { return bcAdapterVector; }
+
+ 
+   virtual void initInteractor(const double& timeStep=0);
+   void updateInteractor(const double& timestep=0); 
+   //virtual void updateMovedGeometry(const double& timeStep=0); 
+   //void updateNewNodes();
+   void setReinitWithStoredQs(bool reinitWithStoredQsFlag) { this->reinitWithStoredQsFlag = reinitWithStoredQsFlag; }
+   
+   void removeSolidBlocks() { Interactor3D::removeSolidBlocks(); solidNodeIndicesMap.clear(); }
+   void removeTransBlocks() { Interactor3D::removeTransBlocks(); transNodeIndicesMap.clear(); }
+   virtual void removeBoundaryInformationOnTransNodes();
+
+   bool setDifferencesToGbObject3D(const Block3DPtr block/*, const double& x1, const double& x2, const double& x3, const double& blockLengthX1, const double& blockLengthX2, const double& blockLengthX3, const double& timestep=0*/);
+
+   ObObject* clone() { throw UbException(UB_EXARGS,"not implemented");	}
+   ObObjectCreator* getCreator();
+
+   //std::string toString();
+
+   //------------- implements CAB serialization ----- start
+   //void write(UbFileOutput* out);
+   //void read(UbFileInput* in);
+   //std::string writeTransNodes(std::string filename);
+   //std::string writeTransNodesAsTriangles(std::string filename);
+   void writeValidationAVSFile(std::string filename);  
+   virtual std::vector< std::pair<GbPoint3D,GbPoint3D> >  getQsLineSet();
+
+   void addQsLineSet(std::vector<UbTupleFloat3 >& nodes, std::vector<UbTupleInt2 >& lines);
+
+   const std::map<Block3DPtr, std::set< std::vector<int> > > & getTransNodeIndicesMap() { return transNodeIndicesMap; }
+
+protected:
+   bool relevantForForces;
+   bool reinitWithStoredQsFlag;
+
+   //std::vector< MbSmartPtr<D3Q27BoundaryConditionAdapter> > bcAdapterVector;
+   std::vector<D3Q27BoundaryConditionAdapterPtr> bcAdapterVector;
+   
+   typedef UbTuple<int,int,int,long long>  UbTupleInt3LongLong;
+
+   std::vector<Block3D*> oldSolidBlockSet;
+   std::map<Block3DPtr, std::set< UbTupleInt3 > > oldSolidNodeIndicesMap;
+   std::map<Block3DPtr, std::set< UbTupleInt3LongLong > > oldTransNodeIndicesMap;
+
+   std::map<Block3DPtr, std::set< UbTupleInt3 > > solidNodeIndicesMap;  
+
+   std::map<Block3DPtr, std::set< std::vector<int> > > transNodeIndicesMap;
+   //std::map<Block3DPtr, std::set< UbTupleInt3 > > transNodeIndicesMap;//!!! es kann sein, dass in diesem interactor
+                                                                         //an eine rpos eine BC gesetzt wurde, aber derselbe node in
+                                                                         //in einem anderen in einen anderen Typ (z.B. Solid) geaendert
+                                                                         //wurde --> es ist keine BC mehr an der stelle!
+   
+   void   initRayVectors();
+   double rayX1[D3Q27System::FENDDIR+1];
+   double rayX2[D3Q27System::FENDDIR+1];
+   double rayX3[D3Q27System::FENDDIR+1];
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<Interactor3D>(*this);
+      ar & transNodeIndicesMap;
+      ar & bcAdapterVector;
+   }
+};
+
+
+#endif
diff --git a/source/VirtualFluidsCore/Interactors/D3Q27TriFaceMeshInteractor.cpp b/source/VirtualFluidsCore/Interactors/D3Q27TriFaceMeshInteractor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..06c6dc8136f7cc8192525d41c365a6c8e1fe26d7
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/D3Q27TriFaceMeshInteractor.cpp
@@ -0,0 +1,1822 @@
+#include "D3Q27TriFaceMeshInteractor.h"
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbLogger.h>
+#include <basics/utilities/UbStaticPathMap.h>
+
+#include <basics/writer/WbWriterVtkBinary.h>
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <basics/writer/WbWriterVtkASCII.h>
+#include "basics/writer/WbWriterVtkXmlASCII.h"
+
+#include <numerics/geometry3d/GbSystem3D.h>
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <numerics/geometry3d/GbHalfSpace3D.h>
+#include <numerics/geometry3d/GbMeshTools3D.h>
+#include "Block3D.h"
+#include "Grid3D.h"
+#include "BCArray3D.h"
+#include "D3Q27BoundaryCondition.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "basics/utilities/UbTiming.h"
+
+#include <stack>
+
+using namespace std;
+
+D3Q27TriFaceMeshInteractor::D3Q27TriFaceMeshInteractor()
+: D3Q27Interactor(), forceshift(0.0), velocityshift(0.0), forceshiftpolicy(false), velocityshiftpolicy(false), useHalfSpace(true), regardPIOTest(true)
+{
+   this->stressMode = STRESSNORMAL;
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27TriFaceMeshInteractor::D3Q27TriFaceMeshInteractor(Grid3DPtr grid, std::string name)
+{
+   this->stressMode = STRESSNORMAL;
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27TriFaceMeshInteractor::D3Q27TriFaceMeshInteractor(GbTriFaceMesh3DPtr triFaceMesh, Grid3DPtr grid, D3Q27BoundaryConditionAdapterPtr bcAdapter, int type)
+: D3Q27Interactor(triFaceMesh, grid, bcAdapter, type), forceshift(0.0), velocityshift(0.0), forceshiftpolicy(false), velocityshiftpolicy(false), useHalfSpace(true), regardPIOTest(true)
+{
+   this->stressMode = STRESSNORMAL;
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27TriFaceMeshInteractor::D3Q27TriFaceMeshInteractor(GbTriFaceMesh3DPtr triFaceMesh, Grid3DPtr grid, D3Q27BoundaryConditionAdapterPtr bcAdapter, int type, Interactor3D::Accuracy a)
+   : D3Q27Interactor(triFaceMesh, grid, bcAdapter, type, a), forceshift(0.0), velocityshift(0.0), forceshiftpolicy(false), velocityshiftpolicy(false), useHalfSpace(true), regardPIOTest(true)
+{
+   this->stressMode = STRESSNORMAL;
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27TriFaceMeshInteractor::~D3Q27TriFaceMeshInteractor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27TriFaceMeshInteractor::initInteractor(const double& timeStep)
+{
+   Interactor3D::initInteractor(timeStep);
+   setQs(timeStep);
+}
+//////////////////////////////////////////////////////////////////////////
+bool D3Q27TriFaceMeshInteractor::setDifferencesToGbObject3D(const Block3DPtr block/*,const double& orgX1,const double& orgX2,const double& orgX3,const double& blockLengthX1,const double& blockLengthX2,const double& blockLengthX3, const double& timestep*/)
+{
+   if(!block) return false;
+
+   transNodeIndicesMap[block] = set< std::vector<int> >();
+   set< std::vector<int> >& transNodeIndices = transNodeIndicesMap[block];
+   solidNodeIndicesMap[block] = set< UbTupleInt3 >();
+   set< UbTupleInt3 >& solidNodeIndices = solidNodeIndicesMap[block];
+
+
+   bool oneEntryGotBC = false; //ob ueberhaupt ein eintrag ein BC zugewiesen wurde
+   bool gotQs         = false; //true, wenn "difference" gesetzt wurde
+   D3Q27BoundaryConditionPtr bc;
+
+   LBMKernel3DPtr kernel = block->getKernel();
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+   double internX1,internX2,internX3;
+  
+   int startIX1 = 0, startIX2 = 0, startIX3 = 0; 
+   int stopIX1  = (int)bcArray.getNX1(), stopIX2  = (int)bcArray.getNX2(), stopIX3  = (int)bcArray.getNX3(); 
+
+   double         dx       = grid.lock()->getDeltaX(block);
+   UbTupleDouble3 orgDelta = grid.lock()->getNodeOffset(block);
+
+   bool pointOnBoundary = false;
+
+   for(int ix3=startIX3; ix3<stopIX3; ix3++)
+   {
+      for(int ix2=startIX2; ix2<stopIX2; ix2++)
+      {
+         for(int ix1=startIX1; ix1<stopIX1; ix1++)
+         {
+            UbTupleDouble3 coords = grid.lock()->getNodeCoordinates(block, ix1, ix2, ix3);
+            internX1 = val<1>(coords);
+            internX2 = val<2>(coords);
+            internX3 = val<3>(coords);
+
+            if(this->isSolid() )
+            {
+               if(this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3))
+               {
+                  if(bcArray.isFluid(ix1,ix2,ix3))
+                  {
+                     solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3));
+                     bcArray.setSolid(ix1,ix2,ix3); 
+                  }
+               }
+            }
+            else if( this->isInverseSolid()  )
+            {
+               //bei inverse solid sind alle Knoten AUSSERHALB und auf der boundary SOLID
+               if( !this->geoObject3D->isPointInGbObject3D(internX1, internX2, internX3, pointOnBoundary) || pointOnBoundary == true )
+               {
+                  if(bcArray.isFluid(ix1,ix2,ix3))
+                  {
+                     solidNodeIndices.insert(UbTupleInt3(ix1, ix2, ix3));
+                     bcArray.setSolid(ix1,ix2,ix3);
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   return oneEntryGotBC;
+}
+//////////////////////////////////////////////////////////////////////////
+//E.F. /4/16/2013
+void D3Q27TriFaceMeshInteractor::setQs(const double& timeStep)
+{
+   UBLOGML(logDEBUG1,"\nLBMTriFaceMeshInteractor - setQs start ");
+   if( !this->grid.lock() ) throw UbException(UB_EXARGS,"ups, no grid.lock()!!");
+
+   if( this->reinitWithStoredQsFlag && !transNodeIndicesAndQsMap.empty() )
+   {
+      this->reinitWithStoredQs(timeStep);
+      return;
+   }
+
+   GbTriFaceMesh3D* mesh  = dynamic_cast<GbTriFaceMesh3D*>(this->geoObject3D.get());
+
+   //////////////////////////////////////////////////////////////////////////
+   //init bcs
+   //////////////////////////////////////////////////////////////////////////
+   int nofAdapter = (int)this->bcAdapterVector.size();
+   if(nofAdapter==0) std::cout<<"WARNING - D3Q27TriFaceMeshInteractor::initInteractor Warning - no nodeAdapter available for "/*<<this->getName()*/<<std::endl;
+   bool needTimeDependence = false;
+   for(int pos=0; pos<nofAdapter; ++pos)
+   {
+      this->bcAdapterVector[pos]->init(this,timeStep);
+      if(this->bcAdapterVector[pos]->isTimeDependent()) needTimeDependence = true;
+   }
+   if(needTimeDependence) this->setTimeDependent();
+   else                   this->unsetTimeDependent();
+
+   //////////////////////////////////////////////////////////////////////////
+   //grid.lock() info
+   //////////////////////////////////////////////////////////////////////////
+   int coarsestInitLevel = grid.lock()->getCoarsestInitializedLevel();
+   int finestInitLevel   = grid.lock()->getFinestInitializedLevel();
+
+   UbTupleInt3 blocknx = grid.lock()->getBlockNX();
+   int blocknx1 = val<1>(blocknx); //gilt fuer alle Level
+   int blocknx2 = val<2>(blocknx); //gilt fuer alle Level
+   int blocknx3 = val<3>(blocknx); //gilt fuer alle Level
+
+   //grobe Blocklaengen
+   CoordinateTransformation3DPtr trafo = grid.lock()->getCoordinateTransformator();
+   double cblockDeltaX1,cblockDeltaX2,cblockDeltaX3, delta ;
+   cblockDeltaX1 = cblockDeltaX2 = cblockDeltaX3 = delta = 1.0/(double)(1<<coarsestInitLevel);
+   if(trafo)
+   {
+      cblockDeltaX1 = trafo->getX1CoordinateScaling()*delta;
+      cblockDeltaX2 = trafo->getX2CoordinateScaling()*delta;
+      cblockDeltaX3 = trafo->getX3CoordinateScaling()*delta;
+   }
+   //levelspezifische blocklaengen und knotenabstaende
+   std::vector< std::vector<double> > nodeDeltaToNeigh(finestInitLevel+1);
+   std::vector<float>  deltaMinX1(finestInitLevel+1),deltaMinX2(finestInitLevel+1),deltaMinX3(finestInitLevel+1);
+   std::vector<float>  deltaMaxX1(finestInitLevel+1),deltaMaxX2(finestInitLevel+1),deltaMaxX3(finestInitLevel+1);
+
+   //Im Boltzmankontext muss dx1==dx2==dx3 sein!!
+   assert( UbMath::equal(cblockDeltaX1/(double)blocknx1, cblockDeltaX2/(double)blocknx2 ) );
+   assert( UbMath::equal(cblockDeltaX1/(double)blocknx1, cblockDeltaX3/(double)blocknx3 ) );
+
+   for(int level = coarsestInitLevel; level<=finestInitLevel; level++)
+   {
+      double nodeDeltaX1 = cblockDeltaX1/(double)(blocknx1*(1<<(level-coarsestInitLevel)));
+      double nodeDeltaX2 = cblockDeltaX2/(double)(blocknx2*(1<<(level-coarsestInitLevel)));
+      double nodeDeltaX3 = cblockDeltaX3/(double)(blocknx3*(1<<(level-coarsestInitLevel)));
+
+      std::vector<double> distNeigh(D3Q27System::FENDDIR+1, 0.0);
+      D3Q27System::calcDistanceToNeighbors(distNeigh, nodeDeltaX1,nodeDeltaX2,nodeDeltaX3);
+      //D3Q27System::calcDistanceToNeighbors(distNeigh, nodeDeltaX1);
+
+
+      nodeDeltaToNeigh[level].resize(D3Q27System::ENDDIR+1,0.0);
+      for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+      {
+         nodeDeltaToNeigh[level][fdir] = distNeigh[fdir];
+      }
+
+      //im gegensatz zum allg. Cell3DInteractor kann man hier auf max(0.02*blockDeltaX1[level],fabs(...)) verzichten
+      //da dies nur für blockDeltaCalculator->getMinX1Delta(level)==0.0 benötigt wird. ist im D3Q19... aber nie so
+      //Geller: kann man nicht diesen befuckten DeltaCalculator weglassen und hier einfach die Formel zum Delta rechnen reinpacken
+      //SirAnn: klar, mann kann auch weißwuerste am Alex verkaufen... aber zum einen ist das Ding dazu da
+      // und zum anderen sollt eman mal überlegen: "Formel zum Delta rechnen"->man muss rechnen
+      // blockDeltaCalculator->getMinX1Delta(level) -> ein geinlinter wert wird geholt 
+
+      //TODO: set 5.0 as variable parameter in constructor, default 2.0 
+      deltaMinX1[level] = (float)( 5.0*nodeDeltaX1); //kein minus da unten -deltaMin
+      deltaMinX2[level] = (float)( 5.0*nodeDeltaX2);
+      deltaMinX3[level] = (float)( 5.0*nodeDeltaX3);
+      deltaMaxX1[level] = (float)( 5.0*nodeDeltaX1);
+      deltaMaxX2[level] = (float)( 5.0*nodeDeltaX2);
+      deltaMaxX3[level] = (float)( 5.0*nodeDeltaX3);
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //bounding cubes des TriFaceMesh ermitteln (pro level)
+   //////////////////////////////////////////////////////////////////////////
+   //min/max Werte des Dreiecksnetzes holen
+   double geoMinX1(0.0), geoMinX2(0.0), geoMinX3(0.0), geoMaxX1(0.0), geoMaxX2(0.0), geoMaxX3(0.0);
+
+   geoMinX1 = this->geoObject3D->getX1Minimum();  geoMaxX1 = this->geoObject3D->getX1Maximum();
+   geoMinX2 = this->geoObject3D->getX2Minimum();  geoMaxX2 = this->geoObject3D->getX2Maximum();
+   geoMinX3 = this->geoObject3D->getX3Minimum();  geoMaxX3 = this->geoObject3D->getX3Maximum();
+
+
+   //////////////////////////////////////////////////////////////////////////
+   //DREIECKE: q-Bestimmung
+   //////////////////////////////////////////////////////////////////////////
+
+   //notwendige variablen initialisieren (u.a. blockDeltas des groben levels)
+   float triPoints[3][3];
+   float vx1=0.0, vx2=0.0, vx3=0.0;
+   unsigned counterTriBoxOverlap=0, counterAABBTriFace=0, counterHalfspace=0, counterBilligOBB=0;
+   std::vector<GbTriFaceMesh3D::TriFace>& triangles = *mesh->getTriangles();
+   std::vector<GbTriFaceMesh3D::Vertex>&  nodes     = *mesh->getNodes();
+   std::map< Block3DPtr, std::set< UbTupleInt3 > > tmpSolidNodesFromOtherInteractors;
+
+   int onePercent = UbMath::integerRounding(triangles.size()*0.01);
+   if(onePercent==0) onePercent=1;
+   UbTimer setQTimer; setQTimer.start();
+   UBLOG(logDEBUG3, " - setQs for "<<(int)triangles.size()<<" triangles");
+
+   bool solidFromOtherInteractor = false;
+   float blockMinX[3],blockMaxX[3],boxCenter[3],halfBoxSize[3];
+
+   for(size_t t=0; t<triangles.size(); t++)
+   {
+      //////////////////////////////////////////////////////////////////////////
+      // Halfspace zum Dreieck generieren und min/max des Dreiecks ermitteln
+      //////////////////////////////////////////////////////////////////////////
+      GbTriFaceMesh3D::TriFace& triangle = triangles[t];
+
+      GbTriFaceMesh3D::Vertex& v1 = nodes[triangle.v1];
+      GbTriFaceMesh3D::Vertex& v2 = nodes[triangle.v2];
+      GbTriFaceMesh3D::Vertex& v3 = nodes[triangle.v3];
+
+      if(this->isInverseSolid() )
+      {					
+         triangle.nx*=(-1);
+         triangle.ny*=(-1);
+         triangle.nz*=(-1);	
+      }
+      GbHalfSpace3D halfSpace(  v1.x,v1.y,v1.z,triangle.nx,triangle.ny,triangle.nz );
+
+      //////////////////////////////////////////////////////////////////////////
+      //fuer GbMeshTools3D::triBoxOverlap
+      //////////////////////////////////////////////////////////////////////////
+      triPoints[0][0] = v1.x; triPoints[0][1] = v1.y; triPoints[0][2] = v1.z;
+      triPoints[1][0] = v2.x; triPoints[1][1] = v2.y; triPoints[1][2] = v2.z;
+      triPoints[2][0] = v3.x; triPoints[2][1] = v3.y; triPoints[2][2] = v3.z;
+
+      double minX1 = triangle.getMinX(nodes);   double maxX1 = triangle.getMaxX(nodes);
+      double minX2 = triangle.getMinY(nodes);   double maxX2 = triangle.getMaxY(nodes);
+      double minX3 = triangle.getMinZ(nodes);   double maxX3 = triangle.getMaxZ(nodes);
+
+      //////////////////////////////////////////////////////////////////////////
+      // Schleife ueber alle Level
+      //////////////////////////////////////////////////////////////////////////
+      double e1x1,e1x2,e1x3,e2x1,e2x2,e2x3,px1,px2,px3,a,f,sx1,sx2,sx3,u,qx1,qx2,qx3,v;
+      bool gotQs = false;
+      D3Q27BoundaryConditionPtr bc;
+
+      for(int level=coarsestInitLevel; level<=finestInitLevel; level++)
+      {
+         //////////////////////////////////////////////////////////////////////////
+         // levelspezifisches BoundCube des Dreicks ermitteln und zugehörige Bloecke beziehen
+         //////////////////////////////////////////////////////////////////////////
+         double boundCubeTriangleMinX1 = minX1-deltaMinX1[level];  double boundCubeTriangleMaxX1 = maxX1+deltaMaxX1[level];
+         double boundCubeTriangleMinX2 = minX2-deltaMinX2[level];  double boundCubeTriangleMaxX2 = maxX2+deltaMaxX2[level];
+         double boundCubeTriangleMinX3 = minX3-deltaMinX3[level];  double boundCubeTriangleMaxX3 = maxX3+deltaMaxX3[level];
+
+         GbCuboid3D boundingCubeTriangle(  boundCubeTriangleMinX1, boundCubeTriangleMinX2, boundCubeTriangleMinX3
+            , boundCubeTriangleMaxX1, boundCubeTriangleMaxX2, boundCubeTriangleMaxX3 );
+
+         std::vector<Block3DPtr> triBlocks;
+         grid.lock()->getBlocksByCuboid(level, boundCubeTriangleMinX1, boundCubeTriangleMinX2, boundCubeTriangleMinX3
+            , boundCubeTriangleMaxX1, boundCubeTriangleMaxX2, boundCubeTriangleMaxX3, triBlocks );
+
+         //////////////////////////////////////////////////////////////////////////
+         // Schleife ueber bloecke des level, die das dreieck beinhalten
+         //////////////////////////////////////////////////////////////////////////
+         for(std::size_t b=0; b<triBlocks.size(); b++)
+         {
+            Block3DPtr block = triBlocks[b];
+
+            ////////////////////////////////////////////////////////////////////////////
+            //// Block Dreieck-/test
+            ////////////////////////////////////////////////////////////////////////////
+            UbTupleDouble3 coords = grid.lock()->getBlockWorldCoordinates(block);
+            UbTupleDouble3 deltas = grid.lock()->getBlockLengths(block);
+
+            blockMinX[0]   = (float)(val<1>(coords)-deltaMinX1[level]);
+            blockMinX[1]   = (float)(val<2>(coords)-deltaMinX2[level]);
+            blockMinX[2]   = (float)(val<3>(coords)-deltaMinX3[level]);
+
+            blockMaxX[0]   = (float)(val<1>(coords)+val<1>(deltas)+deltaMaxX1[level]);
+            blockMaxX[1]   = (float)(val<2>(coords)+val<2>(deltas)+deltaMaxX2[level]);
+            blockMaxX[2]   = (float)(val<3>(coords)+val<3>(deltas)+deltaMaxX3[level]);
+
+            boxCenter[0]   = (float)(0.5*(blockMaxX[0]+blockMinX[0]));
+            boxCenter[1]   = (float)(0.5*(blockMaxX[1]+blockMinX[1]));
+            boxCenter[2]   = (float)(0.5*(blockMaxX[2]+blockMinX[2]));
+
+            halfBoxSize[0] = (float)(0.5*(blockMaxX[0]-blockMinX[0]));
+            halfBoxSize[1] = (float)(0.5*(blockMaxX[1]-blockMinX[1]));
+            halfBoxSize[2] = (float)(0.5*(blockMaxX[2]-blockMinX[2]));
+
+            //wenn dreieck "vergroesserten cube" nicht schneidet/beruehrt -> keine BC moeglich -> continue
+            if( !GbMeshTools3D::triBoxOverlap(boxCenter,halfBoxSize,triPoints) )
+            {
+               counterTriBoxOverlap++;
+               continue;
+            }
+
+            //////////////////////////////////////////////////////////////////////////
+            //Untersuchung der einzelnen nodes
+            //////////////////////////////////////////////////////////////////////////
+            bool blockGotBCs = false;
+
+            LBMKernel3DPtr kernel = block->getKernel();
+            BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+            int indexMinX1 = 0;
+            int indexMinX2 = 0;
+            int indexMinX3 = 0;
+
+            int indexMaxX1 = (int)bcMatrix.getNX1();
+            int indexMaxX2 = (int)bcMatrix.getNX2();
+            int indexMaxX3 = (int)bcMatrix.getNX3();
+
+            std::set< std::vector<int> >& transNodeIndices           = this->transNodeIndicesMap[block];
+            std::set< UbTupleInt3 >& solidsFromOtherInteractors = tmpSolidNodesFromOtherInteractors[block];
+            double q, distance;
+
+            double& nodeDx1 = nodeDeltaToNeigh[level][D3Q27System::E];
+            double& nodeDx2 = nodeDeltaToNeigh[level][D3Q27System::N];
+            double& nodeDx3 = nodeDeltaToNeigh[level][D3Q27System::T];
+
+            //fuer OBB-Test
+            double qEinflussDelta = 1.1 * sqrt( nodeDx1*nodeDx1 + nodeDx2*nodeDx2 + nodeDx3*nodeDx3);
+
+            for(int ix3=indexMinX3; ix3<indexMaxX3; ix3++)
+            {
+               for(int ix2=indexMinX2; ix2<indexMaxX2; ix2++)
+               {
+                  for(int ix1=indexMinX1; ix1<indexMaxX1; ix1++)
+                  {	
+                     UbTupleDouble3 pointplane1 =  grid.lock()->getNodeCoordinates(block, ix1,ix2,ix3);
+                     double   internX1=val<1>(pointplane1);
+                     double   internX2=val<2>(pointplane1);
+                     double   internX3=val<3>(pointplane1);
+
+                     int blx1 =block->getX1();
+                     int blx2 = block->getX2();
+                     int blx3 = block->getX3();
+
+                     if(bcMatrix.isSolid(ix1,ix2,ix3) || bcMatrix.isUndefined(ix1,ix2,ix3))
+                     {
+                        continue;
+                     }
+
+                     //////////////////////////////////////////////////////////////////////////
+                     //Punkt in AABB von Dreieck?                     
+                     //////////////////////////////////////////////////////////////////////////
+                     //ehsan changed
+                     bool pointIsOnBoundary = true;
+                     if( !boundingCubeTriangle.isPointInGbObject3D(internX1, internX2, internX3,pointIsOnBoundary) ) 
+                     {
+                        counterAABBTriFace++;
+                        continue;
+                     }
+                     //std::cout<<"internX3  "<<internX3<<"  internX2"<<internX2<<" internX1 "<<internX1<<"\n";
+                     //////////////////////////////////////////////////////////////////////////
+                     // Halbebenentests
+                     //////////////////////////////////////////////////////////////////////////
+                     distance = halfSpace.getDistance( internX1, internX2, internX3 );
+                     //Punkt in Halbebene? (nein, wenn distance<0)
+                     if(useHalfSpace && UbMath::less(distance, 0.0) )//== !halfSpace.ptInside(internX1,internX2,internX3) )
+                     {
+                        counterHalfspace++;
+                        continue;
+                     }
+
+                     //BilligOBB-Test: wenn distance > qEinflussDelta -> kein q
+                     if( UbMath::greater( fabs(distance), qEinflussDelta ) )
+                     {
+                        counterBilligOBB++;
+                        continue;
+                     }
+
+                     /////////////////////////////////////////////////////////////////////////////
+                     //Raytracingfür diskrete Boltzmannrichtungen
+                     /////////////////////////////////////////////////////////////////////////////
+                     gotQs = false;
+                     bc    = D3Q27BoundaryConditionPtr();
+
+                     //RAYTRACING - diskrete LB-dir zu Dreick
+                     //e1 = v1 - v0
+                     e1x1 = v2.x-v1.x;
+                     e1x2 = v2.y-v1.y;
+                     e1x3 = v2.z-v1.z;
+
+                     //e2 = v2 - v0
+                     e2x1 = v3.x-v1.x;
+                     e2x2 = v3.y-v1.y;
+                     e2x3 = v3.z-v1.z;
+
+                     //s = o - v0
+                     sx1 = internX1 - v1.x;
+                     sx2 = internX2 - v1.y;
+                     sx3 = internX3 - v1.z;
+
+                     for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                     {
+                        //p = d x e2
+                        px1 = this->rayX2[fdir]*e2x3 - this->rayX3[fdir]*e2x2;
+                        px2 = this->rayX3[fdir]*e2x1 - this->rayX1[fdir]*e2x3;
+                        px3 = this->rayX1[fdir]*e2x2 - this->rayX2[fdir]*e2x1;
+
+                        //a = e1 dot p
+                        a = e1x1*px1 + e1x2*px2 + e1x3*px3;
+                        if(fabs(a)<1.E-10) continue;
+                        f = 1.0/a;
+
+                        //u = f * ( s dot p)
+                        u = f * ( sx1*px1 + sx2*px2 + sx3*px3 );
+                        if(u<-1.E-10 || u>1.0+1.E-10) continue;
+
+                        //q = s x e1
+                        qx1 = sx2*e1x3 - sx3*e1x2;
+                        qx2 = sx3*e1x1 - sx1*e1x3;
+                        qx3 = sx1*e1x2 - sx2*e1x1;
+
+                        //v = f*(e2 dot q)
+                        v = f * (this->rayX1[fdir]*qx1 + this->rayX2[fdir]*qx2 + this->rayX3[fdir]*qx3);
+                        if(v<-1.E-10 || (u+v)>1.0+1.E-10) continue;
+
+                        //t = f * (e2 dot q)
+                        q = f * (e2x1*qx1 + e2x2*qx2 + e2x3*qx3);
+                        q /= nodeDeltaToNeigh[level][fdir];
+                        /////ehsan q/////////////////////////////////////////////////////////////////////
+                        double det=triangle.nx * this->rayX1[fdir]+ triangle.ny * this->rayX2[fdir]+ triangle.nz * this->rayX3[fdir];
+
+                        if(det>-1.E-10) continue;
+                        double d=triangle.nx*v1.x+triangle.ny*v1.y+triangle.nz*v1.z;
+                        double x1= -((-d* this->rayX1[fdir] - triangle.ny *this->rayX2[fdir]* internX1 - triangle.nz *this->rayX3[fdir]* internX1 + triangle.ny *this->rayX1[fdir]* internX2 + triangle.nz* this->rayX1[fdir]* internX3))/det;
+                        double y1= -((-d* this->rayX2[fdir] + triangle.nx* this->rayX2[fdir]* internX1 - triangle.nx* this->rayX1[fdir]* internX2 - triangle.nz* this->rayX3[fdir] *internX2 + triangle.nz* this->rayX2[fdir]* internX3))/det;
+                        double z1=	-((-d* this->rayX3[fdir] + triangle.nx* this->rayX3[fdir]* internX1 + triangle.ny* this->rayX3[fdir]* internX2 - triangle.nx* this->rayX1[fdir]* internX3 - triangle.ny* this->rayX2[fdir]* internX3))/det;
+                        double q_ehsan=sqrt((x1-internX1)*(x1-internX1)+(y1-internX2)*(y1-internX2)+(z1-internX3)*(z1-internX3));
+                        q_ehsan /= nodeDeltaToNeigh[level][fdir];
+                        q=q_ehsan;	 
+                        if( UbMath::greater(q, 1.0) || UbMath::lessEqual(q, 0.0) )continue;
+
+                        //gefundenes q auf gueltigkeit pruefen
+                        if( UbMath::zero(q) )
+                        {
+                           //neu (18.05.2010)
+                           //es kann vorkommen, dass bei dünnwandigen geos punkte, die auf einem dreieck liegen, qs bekommen, die durch die geo
+                           //durchgehen. diese punkte werden später jedoch nicht mehr auf solid getestet, da sie ja ne BC bekommen haben
+                           //--> da mind ein q==0.0 für eines der dreiecke -> dort solid setzen
+                           this->solidNodeIndicesMap[block].insert( UbTupleInt3(ix1,ix2,ix3) );
+                           bcMatrix.setSolid( ix1, ix2, ix3 );
+                           continue;
+                        }
+
+                        if( UbMath::inClosedInterval(q, 1.0, 1.0) ) q = 1.0;
+                        if( UbMath::greater(q, 0.0) && UbMath::lessEqual(q, 1.0) )
+                        {
+                           gotQs=blockGotBCs=true;
+
+                           bc = bcMatrix.getBC(ix1,ix2,ix3);
+
+                           //SG 26.08.2010 if(!bc && !bcMatrix.isSolid())
+                           if(!bc)
+                           {
+                              bc = D3Q27BoundaryConditionPtr(new D3Q27BoundaryCondition);;
+                              bcMatrix.setBC(ix1,ix2,ix3,bc);
+                           }
+                           else if( UbMath::less( bc->getQ(fdir), q ) )  //schon ein kuerzeres q voehanden?
+                           {
+                              //neu:: 18.05.2010
+                              //um falsche qs die evtl durch die "wand" gehen zu vermeiden 
+                              //q nur dann neu setzen, wenn neues q kleiner als vorhandenes!
+                              //Zudem: insbesondere an ecken mit zwei BC geos ist nur das 
+                              //naehere gueltig
+                              continue;
+                           }
+
+                           bc->setBoundaryVelocityX1(vx1);
+                           bc->setBoundaryVelocityX2(vx2);
+                           bc->setBoundaryVelocityX3(vx3);
+
+                           for(int index=(int)this->bcAdapterVector.size()-1; index>=0; --index)
+                              this->bcAdapterVector[index]->adaptBCForDirection(*this,bc,internX1,internX2,internX3,q,fdir);
+
+                           //fuer beschleunigtes wiedereinlesen
+                           if(this->reinitWithStoredQsFlag)
+                           {
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ].resize(D3Q27System::FENDDIR+1+3, -1.0f);
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ][fdir                    ] = float(q);
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ][D3Q27System::FENDDIR+1+0] = float(internX1);
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ][D3Q27System::FENDDIR+1+1] = float(internX2);
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ][D3Q27System::FENDDIR+1+2] = float(internX3);
+                           }
+                        }
+                     }
+
+                     if(gotQs)
+                     {
+                        std::vector<int> p(3);
+                        p[0]=ix1; p[1]=ix2; p[2]=ix3;
+                        transNodeIndices.insert(p);
+
+                        for(int index=(int)this->bcAdapterVector.size()-1; index>=0; --index)
+                           this->bcAdapterVector[index]->adaptBC(*this,bc,internX1,internX2,internX3);
+                     }
+                  }
+               }
+            }
+         }
+         //dynamische Punkte des GbCuboids muessen leider per "Hand" geloescht werden :-(
+         boundingCubeTriangle.finalize();
+      }
+   }
+   UBLOGML(logDEBUG1,"\nLBMTriFaceMeshInteractor - setQs end ");
+}
+//////////////////////////////////////////////////////////////////////////
+//Vorgehesnweise
+//A – Bestimmung der q's
+//  1. fuer jeden Bounding cube eines Dreiecks des netzes werden die Bloecke des Blockgitter ermittelt
+//  2. mittels eines Dreieck/Block Verschneidungstest werden weitere nicht relevante Bloecke aussortiert
+//     (fuer lange „schief“ im Raum stehende Dreicke, bei denen das Bounding Cube suboptimal ist)
+//  3. jeder Knoten dieser blöcke wird gegen das bound cube des dreiecks getestet
+//  4. Knoten die innerhalb des Cubes aber „innerhalb“ des Netzes liegen werden mittels Halbebenentest aussoriert
+//  5. fuer die restliche Knoten erfolgt die q bestimmung mittels effizienter raytracing algorithmen
+//     fuer die diskreten Boltzmannrichtungen
+//B – Setzen der nicht aktiven Bloecke und Solid Nodes
+//  alle Bloecke des Bounding Cube des Netzes, die mind eine BC erhielten, wurden in A markiert
+//  1. fuer nicht markierte Bloecke genuegt EIN pointInObject(Dreicksnetz)-Test um den gesamten Block bei Erfolg als „not active“ zu markieren
+//  2. fuer markiertre Bloecke wird ein rekursiver Fuellalgorithmus durchgefuehrt
+void D3Q27TriFaceMeshInteractor::initInteractor2(const double& timeStep)
+{
+   UBLOGML(logDEBUG1,"\nLBMTriFaceMeshInteractor - initInteractor start ");
+   if( !this->grid.lock() ) throw UbException(UB_EXARGS,"ups, no grid.lock()!!");
+
+   if( this->reinitWithStoredQsFlag && !transNodeIndicesAndQsMap.empty() )
+   {
+      this->reinitWithStoredQs(timeStep);
+      return;
+   }
+
+   GbTriFaceMesh3D* mesh  = dynamic_cast<GbTriFaceMesh3D*>(this->geoObject3D.get());
+
+   UBLOGML(logDEBUG1,"\nLBMTriFaceMeshInteractor - initInteractor for \""<<mesh->getName()<<" \" t="<<timeStep);
+   //cout<<" - init basics ...";
+
+   this->removeTransBlocks();  //hier wird auch die nodeIndicesMap geloescht!
+   this->removeSolidBlocks();
+
+   //////////////////////////////////////////////////////////////////////////
+   //init bcs
+   //////////////////////////////////////////////////////////////////////////
+   int nofAdapter = (int)this->bcAdapterVector.size();
+   if(nofAdapter==0) std::cout<<"WARNING - D3Q27TriFaceMeshInteractor::initInteractor Warning - no nodeAdapter available for "/*<<this->getName()*/<<std::endl;
+   bool needTimeDependence = false;
+   for(int pos=0; pos<nofAdapter; ++pos)
+   {
+      this->bcAdapterVector[pos]->init(this,timeStep);
+      if(this->bcAdapterVector[pos]->isTimeDependent()) needTimeDependence = true;
+   }
+   if(needTimeDependence) this->setTimeDependent();
+   else                   this->unsetTimeDependent();
+
+   //////////////////////////////////////////////////////////////////////////
+   //grid.lock() info
+   //////////////////////////////////////////////////////////////////////////
+   int coarsestInitLevel = grid.lock()->getCoarsestInitializedLevel();
+   int finestInitLevel   = grid.lock()->getFinestInitializedLevel();
+
+   UbTupleInt3 blocknx = grid.lock()->getBlockNX();
+   int blocknx1 = val<1>(blocknx); //gilt fuer alle Level
+   int blocknx2 = val<2>(blocknx); //gilt fuer alle Level
+   int blocknx3 = val<3>(blocknx); //gilt fuer alle Level
+
+   //grobe Blocklaengen
+   CoordinateTransformation3DPtr trafo = grid.lock()->getCoordinateTransformator();
+   double cblockDeltaX1,cblockDeltaX2,cblockDeltaX3, delta ;
+   cblockDeltaX1 = cblockDeltaX2 = cblockDeltaX3 = delta = 1.0/(double)(1<<coarsestInitLevel);
+   if(trafo)
+   {
+      cblockDeltaX1 = trafo->getX1CoordinateScaling()*delta;
+      cblockDeltaX2 = trafo->getX2CoordinateScaling()*delta;
+      cblockDeltaX3 = trafo->getX3CoordinateScaling()*delta;
+   }
+   //levelspezifische blocklaengen und knotenabstaende
+   std::vector< std::vector<double> > nodeDeltaToNeigh(finestInitLevel+1);
+   //vector<double> blockDeltaX1(finestInitLevel+1), blockDeltaX2(finestInitLevel+1), blockDeltaX3(finestInitLevel+1);
+   std::vector<float>  deltaMinX1(finestInitLevel+1),deltaMinX2(finestInitLevel+1),deltaMinX3(finestInitLevel+1);
+   std::vector<float>  deltaMaxX1(finestInitLevel+1),deltaMaxX2(finestInitLevel+1),deltaMaxX3(finestInitLevel+1);
+
+   //Im Boltzmankontext muss dx1==dx2==dx3 sein!!
+   assert( UbMath::equal(cblockDeltaX1/(double)blocknx1, cblockDeltaX2/(double)blocknx2 ) );
+   assert( UbMath::equal(cblockDeltaX1/(double)blocknx1, cblockDeltaX3/(double)blocknx3 ) );
+
+   for(int level = coarsestInitLevel; level<=finestInitLevel; level++)
+   {
+      double nodeDelta = cblockDeltaX1/(double)(blocknx1*(1<<(level-coarsestInitLevel)));
+
+      std::vector<double> distNeigh(D3Q27System::FENDDIR+1, 0.0);
+      D3Q27System::calcDistanceToNeighbors(distNeigh, nodeDelta);
+
+      nodeDeltaToNeigh[level].resize(D3Q27System::ENDDIR+1,0.0);
+      for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+      {
+         nodeDeltaToNeigh[level][fdir] = distNeigh[fdir];
+      }
+
+      //im gegensatz zum allg. Cell3DInteractor kann man hier auf max(0.02*blockDeltaX1[level],fabs(...)) verzichten
+      //da dies nur für blockDeltaCalculator->getMinX1Delta(level)==0.0 benötigt wird. ist im D3Q19... aber nie so
+      //Geller: kann man nicht diesen befuckten DeltaCalculator weglassen und hier einfach die Formel zum Delta rechnen reinpacken
+      //SirAnn: klar, mann kann auch weißwuerste am Alex verkaufen... aber zum einen ist das Ding dazu da
+      // und zum anderen sollt eman mal überlegen: "Formel zum Delta rechnen"->man muss rechnen
+      // blockDeltaCalculator->getMinX1Delta(level) -> ein geinlinter wert wird geholt 
+
+      deltaMinX1[level] = (float)( 1.2*nodeDelta); //kein minus da unten -deltaMin
+      deltaMinX2[level] = (float)( 1.2*nodeDelta);
+      deltaMinX3[level] = (float)( 1.2*nodeDelta);
+      deltaMaxX1[level] = (float)( 1.2*nodeDelta);
+      deltaMaxX2[level] = (float)( 1.2*nodeDelta);
+      deltaMaxX3[level] = (float)( 1.2*nodeDelta);
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //bounding cubes des TriFaceMesh ermitteln (pro level)
+   //////////////////////////////////////////////////////////////////////////
+   //min/max Werte des Dreiecksnetzes holen
+   double geoMinX1(0.0), geoMinX2(0.0), geoMinX3(0.0), geoMaxX1(0.0), geoMaxX2(0.0), geoMaxX3(0.0);
+   if(this->isSolid() || this->isMoveable())
+   {
+      geoMinX1 = this->geoObject3D->getX1Minimum();  geoMaxX1 = this->geoObject3D->getX1Maximum();
+      geoMinX2 = this->geoObject3D->getX2Minimum();  geoMaxX2 = this->geoObject3D->getX2Maximum();
+      geoMinX3 = this->geoObject3D->getX3Minimum();  geoMaxX3 = this->geoObject3D->getX3Maximum();
+   }
+   else throw UbException(UB_EXARGS,"only TYPE==SOLID is implemented" );
+
+   std::map<Block3DPtr,SolidCheckMethod> blocksForSolidCheck;
+
+   for(int level = coarsestInitLevel; level<=finestInitLevel; level++)
+   {
+      if(this->isSolid() || this->isMoveable())
+      {
+         //bloecke fuer "bounding cube gesamt"
+         std::vector<Block3DPtr> tmpblocks;
+         grid.lock()->getBlocksByCuboid(level,geoMinX1-deltaMinX1[level], geoMinX2-deltaMinX2[level], geoMinX3-deltaMinX3[level],
+            geoMaxX1+deltaMaxX1[level], geoMaxX2+deltaMaxX2[level], geoMaxX3+deltaMaxX3[level],tmpblocks );
+
+         for( size_t i=0; i<tmpblocks.size(); i++ )
+            blocksForSolidCheck[tmpblocks[i]] = PointInObject;
+      }
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //FE-specific
+   //////////////////////////////////////////////////////////////////////////
+   //bool calcVelocities = false;
+   //FeTriFaceMesh3D* feMesh = dynamic_cast<FeTriFaceMesh3D*>(mesh);
+   //std::vector<FeTriFaceMesh3D::VertexAttributes>* attributes = NULL;
+   //if(feMesh)
+   //{
+   //   calcVelocities = true;
+   //   attributes     = feMesh->getAttributes();
+   //}
+
+   //////////////////////////////////////////////////////////////////////////
+   //DREIECKE: q-Bestimmung
+   //////////////////////////////////////////////////////////////////////////
+
+   //notwendige variablen initialisieren (u.a. blockDeltas des groben levels)
+   float triPoints[3][3];
+   float vx1=0.0, vx2=0.0, vx3=0.0;
+   unsigned counterTriBoxOverlap=0, counterAABBTriFace=0, counterHalfspace=0, counterBilligOBB=0;
+   std::vector<GbTriFaceMesh3D::TriFace>& triangles = *mesh->getTriangles();
+   std::vector<GbTriFaceMesh3D::Vertex>&  nodes     = *mesh->getNodes();
+   std::map< Block3DPtr, std::set< std::vector<int> > > tmpSolidNodesFromOtherInteractors;
+
+   int onePercent = UbMath::integerRounding(triangles.size()*0.01);
+   if(onePercent==0) onePercent=1;
+   UbTimer setQTimer; setQTimer.start();
+   UBLOG(logDEBUG3, " - setQs for "<<(int)triangles.size()<<" triangles");
+
+   bool solidFromOtherInteractor = false;
+   float blockMinX[3],blockMaxX[3],boxCenter[3],halfBoxSize[3];
+
+   for(size_t t=0; t<triangles.size(); t++)
+   {
+	   //if (t==10577)
+	   //{
+		  // int ehsan=0;
+	   //}
+      //////////////////////////////////////////////////////////////////////////
+      // Halfspace zum Dreieck generieren und min/max des Dreiecks ermitteln
+      //////////////////////////////////////////////////////////////////////////
+      GbTriFaceMesh3D::TriFace& triangle = triangles[t];
+
+      GbTriFaceMesh3D::Vertex& v1 = nodes[triangle.v1];
+      GbTriFaceMesh3D::Vertex& v2 = nodes[triangle.v2];
+      GbTriFaceMesh3D::Vertex& v3 = nodes[triangle.v3];
+
+      GbHalfSpace3D halfSpace(  v1.x,v1.y,v1.z,v2.x,v2.y,v2.z,v3.x,v3.y,v3.z );
+
+      //if(calcVelocities)
+      //{
+      //   FeTriFaceMesh3D::VertexAttributes& vAttribut1 = (*attributes)[triangle.v1];
+      //   FeTriFaceMesh3D::VertexAttributes& vAttribut2 = (*attributes)[triangle.v2];
+      //   FeTriFaceMesh3D::VertexAttributes& vAttribut3 = (*attributes)[triangle.v3];
+      //   vx1 = (float)(UbMath::c1o3*(vAttribut1.getVelocityX()+vAttribut2.getVelocityX()+vAttribut3.getVelocityX()));
+      //   vx2 = (float)(UbMath::c1o3*(vAttribut1.getVelocityY()+vAttribut2.getVelocityY()+vAttribut3.getVelocityY()));
+      //   vx3 = (float)(UbMath::c1o3*(vAttribut1.getVelocityZ()+vAttribut2.getVelocityZ()+vAttribut3.getVelocityZ()));
+      //}
+
+      //////////////////////////////////////////////////////////////////////////
+      //fuer GbMeshTools3D::triBoxOverlap
+      //////////////////////////////////////////////////////////////////////////
+      triPoints[0][0] = v1.x; triPoints[0][1] = v1.y; triPoints[0][2] = v1.z;
+      triPoints[1][0] = v2.x; triPoints[1][1] = v2.y; triPoints[1][2] = v2.z;
+      triPoints[2][0] = v3.x; triPoints[2][1] = v3.y; triPoints[2][2] = v3.z;
+
+      double minX1 = triangle.getMinX(nodes);   double maxX1 = triangle.getMaxX(nodes);
+      double minX2 = triangle.getMinY(nodes);   double maxX2 = triangle.getMaxY(nodes);
+      double minX3 = triangle.getMinZ(nodes);   double maxX3 = triangle.getMaxZ(nodes);
+
+      //////////////////////////////////////////////////////////////////////////
+      // Schleife ueber alle Level
+      //////////////////////////////////////////////////////////////////////////
+      double e1x1,e1x2,e1x3,e2x1,e2x2,e2x3,px1,px2,px3,a,f,sx1,sx2,sx3,u,qx1,qx2,qx3,v;
+      bool gotQs = false;
+      D3Q27BoundaryConditionPtr bc;
+
+      for(int level=coarsestInitLevel; level<=finestInitLevel; level++)
+      {
+         //////////////////////////////////////////////////////////////////////////
+         // levelspezifisches BoundCube des Dreicks ermitteln und zugehörige Bloecke beziehen
+         //////////////////////////////////////////////////////////////////////////
+         double boundCubeTriangleMinX1 = minX1-deltaMinX1[level];  double boundCubeTriangleMaxX1 = maxX1+deltaMaxX1[level];
+         double boundCubeTriangleMinX2 = minX2-deltaMinX2[level];  double boundCubeTriangleMaxX2 = maxX2+deltaMaxX2[level];
+         double boundCubeTriangleMinX3 = minX3-deltaMinX3[level];  double boundCubeTriangleMaxX3 = maxX3+deltaMaxX3[level];
+
+         GbCuboid3D boundingCubeTriangle(  boundCubeTriangleMinX1, boundCubeTriangleMinX2, boundCubeTriangleMinX3
+            , boundCubeTriangleMaxX1, boundCubeTriangleMaxX2, boundCubeTriangleMaxX3 );
+
+         std::vector<Block3DPtr> triBlocks;
+         grid.lock()->getBlocksByCuboid(level, boundCubeTriangleMinX1, boundCubeTriangleMinX2, boundCubeTriangleMinX3
+            , boundCubeTriangleMaxX1, boundCubeTriangleMaxX2, boundCubeTriangleMaxX3, triBlocks );
+
+         //////////////////////////////////////////////////////////////////////////
+         // Schleife ueber bloecke des level, die das dreieck beinhalten
+         //////////////////////////////////////////////////////////////////////////
+         for(std::size_t b=0; b<triBlocks.size(); b++)
+         {
+            Block3DPtr block = triBlocks[b];
+
+            ////////////////////////////////////////////////////////////////////////////
+            //// Block Dreieck-/test
+            ////////////////////////////////////////////////////////////////////////////
+            UbTupleDouble3 coords = grid.lock()->getBlockWorldCoordinates(block);
+            UbTupleDouble3 deltas = grid.lock()->getBlockLengths(block);
+
+            blockMinX[0]   = (float)(val<1>(coords)-deltaMinX1[level]);
+            blockMinX[1]   = (float)(val<2>(coords)-deltaMinX2[level]);
+            blockMinX[2]   = (float)(val<3>(coords)-deltaMinX3[level]);
+
+            blockMaxX[0]   = (float)(val<1>(coords)+val<1>(deltas)+deltaMaxX1[level]);
+            blockMaxX[1]   = (float)(val<2>(coords)+val<2>(deltas)+deltaMaxX2[level]);
+            blockMaxX[2]   = (float)(val<3>(coords)+val<3>(deltas)+deltaMaxX3[level]);
+
+            boxCenter[0]   = (float)(0.5*(blockMaxX[0]+blockMinX[0]));
+            boxCenter[1]   = (float)(0.5*(blockMaxX[1]+blockMinX[1]));
+            boxCenter[2]   = (float)(0.5*(blockMaxX[2]+blockMinX[2]));
+
+            halfBoxSize[0] = (float)(0.5*(blockMaxX[0]-blockMinX[0]));
+            halfBoxSize[1] = (float)(0.5*(blockMaxX[1]-blockMinX[1]));
+            halfBoxSize[2] = (float)(0.5*(blockMaxX[2]-blockMinX[2]));
+
+            //wenn dreieck "vergroesserten cube" nicht schneidet/beruehrt -> keine BC moeglich -> continue
+            if( !GbMeshTools3D::triBoxOverlap(boxCenter,halfBoxSize,triPoints) )
+            {
+               counterTriBoxOverlap++;
+               continue;
+            }
+
+            //////////////////////////////////////////////////////////////////////////
+            //Untersuchung der einzelnen nodes
+            //////////////////////////////////////////////////////////////////////////
+            bool blockGotBCs = false;
+
+            LBMKernel3DPtr kernel = block->getKernel();
+            BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+            int indexMinX1 = 0;
+            int indexMinX2 = 0;
+            int indexMinX3 = 0;
+
+            int indexMaxX1 = (int)bcMatrix.getNX1();
+            int indexMaxX2 = (int)bcMatrix.getNX2();
+            int indexMaxX3 = (int)bcMatrix.getNX3();
+
+            std::set< std::vector<int> >& transNodeIndices           = this->transNodeIndicesMap[block];
+            std::set< std::vector<int> >& solidsFromOtherInteractors = tmpSolidNodesFromOtherInteractors[block];
+            double q, internX1, internX2, internX3,distance;
+
+            double& nodeDx1 = nodeDeltaToNeigh[level][D3Q27System::E];
+            double& nodeDx2 = nodeDeltaToNeigh[level][D3Q27System::N];
+            double& nodeDx3 = nodeDeltaToNeigh[level][D3Q27System::T];
+
+            //fuer OBB-Test
+            double qEinflussDelta = 1.1 * sqrt( nodeDx1*nodeDx1 + nodeDx2*nodeDx2 + nodeDx3*nodeDx3);
+
+            for(int ix3=indexMinX3; ix3<indexMaxX3; ix3++)
+            {
+               internX3 = val<3>(coords)+nodeDx3*ix3-0.5*nodeDx3;
+               for(int ix2=indexMinX2; ix2<indexMaxX2; ix2++)
+               {
+                  internX2 = val<2>(coords)+nodeDx2*ix2-0.5*nodeDx2;
+                  for(int ix1=indexMinX1; ix1<indexMaxX1; ix1++)
+                  {
+					 
+					  int blx1 =block->getX1();
+					  int blx2 = block->getX2();
+					  int blx3 = block->getX3();
+
+					  if (blx1==0&&blx2==1&&blx3==0)
+					  {
+						  //if (ix2==39&&ix3==4)
+							   if (ix2==39&&ix3==4)
+						  {
+							 int seb=0;
+						  }
+
+					  }
+                     //Problem: wenn voher der punkt durch eine andere geo not active gesetzt wird und
+                     //dieser nun uebersprungen wird, dann hat man spaeter beim fuellalgorithmus luecken
+                     //in der front und der block wird u.U. faelschlicher weise komplett solid markiert
+                     //Lsg: positionen merken und erst Nach dem fuellarlgo wieder auf not active setzen :-)
+                     solidFromOtherInteractor = false;
+                     if(bcMatrix.isSolid(ix1,ix2,ix3))
+                     {
+                        if(this->reinitWithStoredQsFlag)
+                        {
+                           solidFromOtherInteractor = true;   //hier muss man weitermachen
+                           //SG //oje 
+                           std::vector<int> p(3);
+                           p[0]=ix1; p[1]=ix2; p[2]=ix3;
+                           solidsFromOtherInteractors.insert( p );
+                        }
+                        else
+                        {
+                           //SG //oje 
+                           std::vector<int> p(3);
+                           p[0]=ix1; p[1]=ix2; p[2]=ix3;
+                           solidsFromOtherInteractors.insert(p);
+                           //SG continue;   
+                           solidFromOtherInteractor = true;   
+                        }
+                     }
+
+                     internX1 = val<1>(coords)+nodeDx1*ix1-0.5*nodeDx1;
+
+                     //////////////////////////////////////////////////////////////////////////
+                     //Punkt in AABB von Dreieck?                     
+                     //////////////////////////////////////////////////////////////////////////
+					//ehsan changedâ—˜
+					 bool pointIsOnBoundary = false;
+					 if( !boundingCubeTriangle.isPointInGbObject3D(internX1, internX2, internX3,pointIsOnBoundary) ) 
+                    // if( !boundingCubeTriangle.isPointInGbObject3D(internX1, internX2, internX3) ) 
+                     {
+                        counterAABBTriFace++;
+                        continue;
+                     }
+
+                     //////////////////////////////////////////////////////////////////////////
+                     // Halbebenentests
+                     //////////////////////////////////////////////////////////////////////////
+                     distance = halfSpace.getDistance( internX1, internX2, internX3 );
+
+                     //Punkt in Halbebene? (nein, wenn distance<0)
+                     if(useHalfSpace && UbMath::less(distance, 0.0) )//== !halfSpace.ptInside(internX1,internX2,internX3) )
+                     {
+                        counterHalfspace++;
+                        continue;
+                     }
+
+                     //BilligOBB-Test: wenn distance > qEinflussDelta -> kein q
+                     if( UbMath::greater( fabs(distance), qEinflussDelta ) )
+                     {
+                        counterBilligOBB++;
+                        continue;
+                     }
+
+                     /////////////////////////////////////////////////////////////////////////////
+                     //Raytracingfür diskrete Boltzmannrichtungen
+                     /////////////////////////////////////////////////////////////////////////////
+                     gotQs = false;
+                     bc    = D3Q27BoundaryConditionPtr();
+
+                     //RAYTRACING - diskrete LB-dir zu Dreick
+                     //e1 = v1 - v0
+                     e1x1 = v2.x-v1.x;
+                     e1x2 = v2.y-v1.y;
+                     e1x3 = v2.z-v1.z;
+
+                     //e2 = v2 - v0
+                     e2x1 = v3.x-v1.x;
+                     e2x2 = v3.y-v1.y;
+                     e2x3 = v3.z-v1.z;
+
+                     //s = o - v0
+                     sx1 = internX1 - v1.x;
+                     sx2 = internX2 - v1.y;
+                     sx3 = internX3 - v1.z;
+
+                     for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+                     {
+                        //p = d x e2
+                        px1 = this->rayX2[fdir]*e2x3 - this->rayX3[fdir]*e2x2;
+                        px2 = this->rayX3[fdir]*e2x1 - this->rayX1[fdir]*e2x3;
+                        px3 = this->rayX1[fdir]*e2x2 - this->rayX2[fdir]*e2x1;
+
+                        //a = e1 dot p
+                        a = e1x1*px1 + e1x2*px2 + e1x3*px3;
+                        if(fabs(a)<1.E-10) continue;
+                        f = 1.0/a;
+
+                        //u = f * ( s dot p)
+                        u = f * ( sx1*px1 + sx2*px2 + sx3*px3 );
+                        if(u<-1.E-10 || u>1.0+1.E-10) continue;
+
+                        //q = s x e1
+                        qx1 = sx2*e1x3 - sx3*e1x2;
+                        qx2 = sx3*e1x1 - sx1*e1x3;
+                        qx3 = sx1*e1x2 - sx2*e1x1;
+
+                        //v = f*(e2 dot q)
+                        v = f * (this->rayX1[fdir]*qx1 + this->rayX2[fdir]*qx2 + this->rayX3[fdir]*qx3);
+                        if(v<-1.E-10 || (u+v)>1.0+1.E-10) continue;
+
+                        //t = f * (e2 dot q)
+                        q = f * (e2x1*qx1 + e2x2*qx2 + e2x3*qx3);
+                        q /= nodeDeltaToNeigh[level][fdir];
+
+                        //gefundenes q auf gueltigkeit pruefen
+                        if( UbMath::zero(q) )
+                        {
+                           //neu (18.05.2010)
+                           //es kann vorkommen, dass bei dünnwandigen geos punkte, die auf einem dreieck liegen, qs bekommen, die durch die geo
+                           //durchgehen. diese punkte werden später jedoch nicht mehr auf solid getestet, da sie ja ne BC bekommen haben
+                           //--> da mind ein q==0.0 für eines der dreiecke -> dort solid setzen
+                           this->solidNodeIndicesMap[block].insert( UbTupleInt3(ix1,ix2,ix3) );
+                           bcMatrix.setSolid( ix1, ix2, ix3 );
+                           continue;
+                        }
+
+                        if( UbMath::inClosedInterval(q, 1.0, 1.0) ) q = 1.0;
+                        if( UbMath::greater(q, 0.0) && UbMath::lessEqual(q, 1.0) )
+                        {
+                           //if( !solidFromOtherInteractor ) //--> Knoten schon solid-->BC setzen ueberfluessig 
+                           //SG changed to
+                           //if( solidFromOtherInteractor ) //--> Knoten schon solid-->BC setzen ueberfluessig 
+                           {
+                              //SG 26.08.2010 muss bereits hierhin, da das continue sonst den Knoten nicht als transNode fürs
+                              //markiert
+                              gotQs=blockGotBCs=true;
+
+                              bc = bcMatrix.getBC(ix1,ix2,ix3);
+
+                              //SG 26.08.2010 if(!bc && !bcMatrix.isSolid())
+                              if(!bc)
+                              {
+                                 bc = D3Q27BoundaryConditionPtr(new D3Q27BoundaryCondition);;
+                                 bcMatrix.setBC(ix1,ix2,ix3,bc);
+                              }
+                              else if( UbMath::less( bc->getQ(fdir), q ) )  //schon ein kuerzeres q voehanden?
+                              {
+                                 //neu:: 18.05.2010
+                                 //um falsche qs die evtl durch die "wand" gehen zu vermeiden 
+                                 //q nur dann neu setzen, wenn neues q kleiner als vorhandenes!
+                                 //Zudem: insbesondere an ecken mit zwei BC geos ist nur das 
+                                 //naehere gueltig
+                                 continue;
+                              }
+
+                              bc->setBoundaryVelocityX1(vx1);
+                              bc->setBoundaryVelocityX2(vx2);
+                              bc->setBoundaryVelocityX3(vx3);
+
+                              for(int index=(int)this->bcAdapterVector.size()-1; index>=0; --index)
+                                 this->bcAdapterVector[index]->adaptBCForDirection(*this,bc,internX1,internX2,internX3,q,fdir);
+
+                              //SG 26.08.2010 gotQs=blockGotBCs=true;
+                           }
+                           //fuer beschleunigtes wiedereinlesen
+                           if(this->reinitWithStoredQsFlag)
+                           {
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ].resize(D3Q27System::FENDDIR+1+3, -1.0f);
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ][fdir                    ] = float(q);
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ][D3Q27System::FENDDIR+1+0] = float(internX1);
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ][D3Q27System::FENDDIR+1+1] = float(internX2);
+                              transNodeIndicesAndQsMap[block][ UbTupleInt3(ix1, ix2, ix3) ][D3Q27System::FENDDIR+1+2] = float(internX3);
+                           }
+                        }
+                     }
+
+                     if(gotQs)
+                     {
+                        std::vector<int> p(3);
+                        p[0]=ix1; p[1]=ix2; p[2]=ix3;
+                        transNodeIndices.insert(p);
+
+                        for(int index=(int)this->bcAdapterVector.size()-1; index>=0; --index)
+                           this->bcAdapterVector[index]->adaptBC(*this,bc,internX1,internX2,internX3);
+                     }
+                  }
+               }
+            }
+            //Block wird für scanline-check "anmelden", dieser wird dann spaeter zu "transBlocks" hinzugefuegt
+            if(blockGotBCs)
+            {
+               blocksForSolidCheck[block] = ScanLine;
+            }
+            //            bvd->getTimer().stop();
+         }
+         //dynamische Punkte des GbCuboids muessen leider per "Hand" geloescht werden :-(
+         boundingCubeTriangle.finalize();
+      }
+   }
+   setQTimer.stop();
+
+   UBLOG(logDEBUG1," - setQs for "/*<< this->getName()*/ << " - " <<(int)triangles.size()<<" triangles: 100% done in "<<setQTimer.getTotalTime()<<"sec");
+   UBLOG(logDEBUG1,"       * rejected blocks with tribox overlap test : " << counterTriBoxOverlap);
+   UBLOG(logDEBUG1,"       * rejected nodes  with AABB           test : " << counterAABBTriFace);
+   UBLOG(logDEBUG1,"       * rejected nodes  with halfspace      test : " << counterHalfspace);
+   UBLOG(logDEBUG1,"       * rejected nodes  with OBB            test : " << counterBilligOBB);
+
+   typedef std::map<Block3DPtr,SolidCheckMethod>::iterator BlockSolidCheckMethodIterator;
+
+   //////////////////////////////////////////////////////////////////////////
+   // SOLID checks
+   //////////////////////////////////////////////////////////////////////////
+   if( regardPIOTest )
+   {
+      int pointInObjectCounter = 0;
+      int scanlineCounter      = 0;
+      int counter              = 0;
+
+      //sollte die matrix groesse zu gross sein und der rekursive floodFill mehr speicher
+      //benoetigen als der Stack hergibt -> keinen floodFill verwenden!
+      void (D3Q27TriFaceMeshInteractor::*gridFill)(CbArray3D<FLAGS>&, const short&, const short&, const short&, const FLAGS&) = NULL;
+      /*if(blocknx1*blocknx2*blocknx3 < 200000 ) gridFill = &D3Q27TriFaceMeshInteractor::recursiveGridFill;*/
+      /*else */                                    gridFill = &D3Q27TriFaceMeshInteractor::iterativeGridFill; 
+
+      UBLOG(logDEBUG1," - setSolids for "<< blocksForSolidCheck.size() << " blocks");
+
+      UbTimer scanLineTimer;
+      UbTimer solidTimer; 
+      solidTimer.start();
+
+      for(BlockSolidCheckMethodIterator pos=blocksForSolidCheck.begin(); pos!=blocksForSolidCheck.end(); ++pos)
+      {
+         Block3DPtr const& block = pos->first;
+         int level = block->getLevel();
+
+         UbTupleDouble3 coords = grid.lock()->getBlockWorldCoordinates(block);
+
+         //Bloecke, die keinerlei Verschneidung mit Dreicken bzw. deren BoundCubes hatten
+         //hier: durch inside/outside Tests EINES knotens gilt fuer ALLE Knoten des blockes
+         if( pos->second == PointInObject ) 
+         {
+            pointInObjectCounter++;
+            if(mesh->isPointInGbObject3D(val<1>(coords),val<2>(coords),val<3>(coords)) )
+            {
+               //block->setActive(false);
+               //this->solidBlocks.push_back(block);
+            }
+         }
+         //Bloecke, die Verschneidung mit Dreicken bzw. deren BoundCubes hatten
+         //scanline algortihmus. dieser berücksichtigt durch weitere tests, dass innerhalb evtl schon andere
+         //geos bcs gesetzt haben. es werden ausschließelich solids gesetzt (also keine FLUIDS oder neuen BCs)
+         else if( pos->second == ScanLine ) 
+         {
+            scanlineCounter++;
+            scanLineTimer.start();
+
+            LBMKernel3DPtr kernel = block->getKernel();
+            if(!kernel) throw UbException(UB_EXARGS,"na sowas kein kernel bzw. kernel=NULL (2)");
+            BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+            //            bvd->getTimer().start();
+            int indexMinX1 = 0;
+            int indexMinX2 = 0;
+            int indexMinX3 = 0;
+            int indexMaxX1 = (int)bcMatrix.getNX1();
+            int indexMaxX2 = (int)bcMatrix.getNX2();
+            int indexMaxX3 = (int)bcMatrix.getNX3();
+
+            //quick and dirty
+            blocknx1 = indexMaxX1;
+            blocknx2 = indexMaxX2;
+            blocknx3 = indexMaxX3;
+
+            std::set< UbTupleInt3 >& solidNodeIndices = this->solidNodeIndicesMap[block];
+
+            float nodeDeltaX1 = (float)nodeDeltaToNeigh[level][D3Q27System::E];
+            float nodeDeltaX2 = (float)nodeDeltaToNeigh[level][D3Q27System::N];
+            float nodeDeltaX3 = (float)nodeDeltaToNeigh[level][D3Q27System::T];
+
+            //flagfield matrix initialisieren
+            CbArray3D<FLAGS> flagField(blocknx1,blocknx2,blocknx3,UNDEF_FLAG);
+
+            //hier gesetzte bcs markieren
+            std::set< std::vector<int> >& transNodeIndices = this->transNodeIndicesMap[block];
+            std::set< std::vector<int> >::iterator setPos;
+            for(setPos=transNodeIndices.begin(); setPos!=transNodeIndices.end();  ++setPos)
+               flagField( (*setPos)[0], (*setPos)[1], (*setPos)[2] ) = BC_FLAG;
+
+            //solids die bereits durch andere interaktoren gesetzt wurden (wurden oben gespeichert)
+            //ist EMPTY bei reinitWithStoredQsFlag == true
+            //SG 28.08.2010            std::set< UbTupleInt3 >& tmpSolidNodeIndices = tmpSolidNodesFromOtherInteractors[block];
+            //SG 28.08.2010  if(reinitWithStoredQsFlag && !tmpSolidNodeIndices.empty() ) throw UbException(UB_EXARGS, "tmpSolidNodeIndices darf bei reinitWithStoredQsFlag==true keine Knoten enthalten");
+            //SG 28.08.2010            for(setPos=tmpSolidNodeIndices.begin(); setPos!=tmpSolidNodeIndices.end();  ++setPos)
+            //SG 28.08.2010               flagField( val<1>(*setPos), val<2>(*setPos), val<3>(*setPos) ) = OLDSOLID_FLAG;
+
+            //flagfield matrix belegen
+            for(int bx3=0; bx3<blocknx3; ++bx3)
+            {
+               for(int bx2=0; bx2<blocknx2; ++bx2)
+               {
+                  for(int bx1=0; bx1<blocknx1; ++bx1)
+                  {
+                     
+					  if (bx2==9&&bx3==29)
+					  {
+						  int ride=0;
+					  }
+					  if( flagField(bx1,bx2,bx3)==UNDEF_FLAG )
+                     { 
+						 if( mesh->isPointInGbObject3D(  val<1>(coords) + bx1*nodeDeltaX1 - 0.5*nodeDeltaX1 
+                           , val<2>(coords) + bx2*nodeDeltaX2 - 0.5*nodeDeltaX2
+                           , val<3>(coords) + bx3*nodeDeltaX3 - 0.5*nodeDeltaX3) )
+                        {
+                           (this->*gridFill)(flagField,bx1,bx2,bx3,SOLID_FLAG);
+                        }
+                        else
+                        {
+                           (this->*gridFill)(flagField,bx1,bx2,bx3,FLUID_FLAG);
+                        }
+                     }
+
+                     if( flagField(bx1,bx2,bx3)==SOLID_FLAG )
+                     {
+                        //hier ist noch das Problem, das "alle" solid in die solidNodeIndices kommen
+                        //evtl. Abhilfe durch einführen eines anderen Flags bei tmpSolidNodeIndices ..
+                        solidNodeIndices.insert(UbTupleInt3(bx1,bx2,bx3));
+                        bcMatrix.setSolid(bx1,bx2,bx3);
+                     }
+                     //SG 28.08.2010  else if( flagField(bx1,bx2,bx3)==OLDSOLID_FLAG )
+                     //SG 28.08.2010  {
+                     //SG 28.08.2010     bcMatrix.setSolid(bx1,bx2,bx3);
+                     //SG 28.08.2010  }
+                  }
+               }
+            }
+
+            //SG 28.08.2010 halt danach setzen, damit die BCs die fälschlicherweise gesetzt wurden korrigiert werden
+            std::set< std::vector<int> >& tmpSolidNodeIndices = tmpSolidNodesFromOtherInteractors[block];
+            for(setPos=tmpSolidNodeIndices.begin(); setPos!=tmpSolidNodeIndices.end();  ++setPos)
+               bcMatrix.setSolid((*setPos)[0], (*setPos)[1], (*setPos)[2] );
+
+            //block hat  in initInteractor mind eine BC erhalten -> transBlock
+            this->transBlocks.push_back(block);
+            scanLineTimer.stop();
+
+            //            bvd->getTimer().stop();
+         }
+         else throw UbException(UB_EXARGS,"unknown option for in object test");
+      }
+
+      solidTimer.stop();
+
+      UBLOG(logDEBUG1, " - setSolids for "<<blocksForSolidCheck.size()<<" blocks: 100% done in "<<solidTimer.getTotalTime()<<"s");
+      UBLOG(logDEBUG1, "       * pointInObject for "<<pointInObjectCounter<<" blocks in "<<solidTimer.getTotalTime()-scanLineTimer.getTotalTime()<<"s");
+      UBLOG(logDEBUG1, "       * flood fill    for "<<scanlineCounter     <<" blocks in "<<scanLineTimer.getTotalTime()<<" secs");
+      UBLOG(logDEBUG1, "LBMTriFaceMeshInteractor::initInteractor for \""<<mesh->getName()<<"\" done in "<<setQTimer.getTotalTime()+solidTimer.getTotalTime()<<"s");
+   }
+
+   //calcForces arbeitet nicht korrekt, wenn Geo mit Bloecken 
+   //unterschiedlicher Leveltiefe diskretisiert -> exception
+   //abfrage steht hier, weil es theoretisch sein kann, dass bei parallelen rechnungen
+   //genau der block mit dem anderen level auf einem anderen prozess liegt...
+   //Update: es kann u.U. passieren, dass Blöcke in der Liste nicht aktiv sin
+   //(falls diese z.B. duch andere Interactoren solid gesetzt wurden)
+   //diese werden nicht berücksichtigt (auch nicht beid er kraftauswertung später)
+   //if( this->isRelevantForForces() )
+   //{
+   //   int level = -1;     
+   //   for( std::vector<Block3DPtr>::const_iterator pos = this->transBlocks.begin(); pos!=this->transBlocks.end(); ++pos)
+   //      if( (*pos)->isActive() )
+   //      {
+   //         level = (*pos)->getLevel();
+   //         break;
+   //      }
+
+   //      bool check = false;
+   //      for( std::vector<Block3DPtr>::const_iterator pos = this->transBlocks.begin(); pos!=this->transBlocks.end(); ++pos)
+   //         if( (*pos)->isActive() && (*pos)->getLevel()!=level)
+   //         {
+   //            (*pos)->setRank(1000);
+   //            check = true;
+   //            UbTupleDouble3 coords = grid.lock()->getBlockWorldCoordinates((*pos));
+   //            std::cout<<(*pos)->getLevel()<<","<<(*pos)->getX1()<<","<<(*pos)->getX2()<<","<<(*pos)->getX3()<<std::endl;
+   //            std::cout<<std::setprecision(15)<<val<1>(coords)<<","<<val<2>(coords)<<","<<val<3>(coords)<<std::endl<<std::endl;
+
+   //         }
+   //         if(check)
+   //         {
+   //            //this->grid.lock()->writeBlocks(UbStaticPathMap::getPath(UbStaticPathMap::GLOBAL)+"/error_grid",0, WbWriterVtkXmlASCII::getInstance(), false);
+
+   //            throw UbException(UB_EXARGS,"interactor is relevant for forces,"
+   //               +(std::string)" but has transblocks with different levels (wrote error_grid)"
+   //               +(std::string)" -> not supportet by LBMInteractor::getForces()"
+   //               +(std::string)" -> increase refineWidth");
+
+   //         }
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27TriFaceMeshInteractor::refineBlockGridToLevel(int level, double startDistance, double stopDistance)
+{
+   UBLOG(logDEBUG1, "D3Q27TriFaceMeshInteractor::refineBlockGridToLevel - start");
+
+   //ToDo: evtl checken, ob man noch einen HalbraumCheck für StopDistance einbaut
+   //      oder ob man schneller ist, wenn man gar keinen halbraum test macht...
+   if(!grid.lock())
+      throw UbException(UB_EXARGS,"Grid isn't exist!");
+   if( UbMath::greater(startDistance,0.0) )
+      throw UbException(UB_EXARGS,"startDistance>0.0 not supported by this interactor");
+   if( UbMath::less(stopDistance,0.0) )
+      throw UbException(UB_EXARGS,"stopDistance<0.0  not supported by this interactor");
+
+   Grid3DPtr  bgrid = this->grid.lock();
+   GbTriFaceMesh3D& mesh  = dynamic_cast<GbTriFaceMesh3D&>(*this->geoObject3D.get());
+
+   int coarsestLevel = bgrid->getCoarsestInitializedLevel();
+
+   std::vector<GbTriFaceMesh3D::TriFace>& triangles = *mesh.getTriangles();
+   std::vector<GbTriFaceMesh3D::Vertex>&  nodes     = *mesh.getNodes();
+
+   double minX1,minX2,minX3,maxX1,maxX2,maxX3;
+   float blockMinX[3],blockMaxX[3],boxCenter[3],halfBoxSize[3];
+   float triPoints[3][3];
+
+   size_t nofTriangles = (int)triangles.size();
+   for(size_t i=0; i<nofTriangles; i++)
+   {
+      GbTriFaceMesh3D::TriFace& triangle = triangles[i];
+
+      GbTriFaceMesh3D::Vertex& v1 = nodes[triangle.v1];
+      GbTriFaceMesh3D::Vertex& v2 = nodes[triangle.v2];
+      GbTriFaceMesh3D::Vertex& v3 = nodes[triangle.v3];
+
+      //dreick muss normal besitzen!
+      assert( !UbMath::zero(triangle.nx) || !UbMath::zero(triangle.ny) || !UbMath::zero(triangle.nz) );
+      //Normale muss normiert sein!
+      assert( (fabs(std::sqrt( triangle.nx*triangle.nx + triangle.ny*triangle.ny + triangle.nz*triangle.nz ))-1.0f)<1.0E-6);
+
+      //Halfspace um  startDistance entgegen normale verscheiebn, ansonsten werden spaeter
+      //zu testende bloecke auf der dreicksrueckseite nicht getestet!!!
+      GbHalfSpace3D halfSpace(  v1.x+startDistance*triangle.nx, v1.y+startDistance*triangle.ny, v1.z+startDistance*triangle.nz
+         , v2.x+startDistance*triangle.nx, v2.y+startDistance*triangle.ny, v2.z+startDistance*triangle.nz
+         , v3.x+startDistance*triangle.nx, v3.y+startDistance*triangle.ny, v3.z+startDistance*triangle.nz );
+
+      //Boundingbox um massgebliches dx erweitern -> zur Bestimmung der zu testenden Bloecke
+      if( triangle.nx>1.0E-8 ) { minX1 = triangle.getMinX(nodes)+1.05*triangle.nx*startDistance; 
+      maxX1 = triangle.getMaxX(nodes)+1.05*triangle.nx*stopDistance;  }     
+      else                     { minX1 = triangle.getMinX(nodes)+1.05*triangle.nx*stopDistance;  
+      maxX1 = triangle.getMaxX(nodes)+1.05*triangle.nx*startDistance; }     
+
+      if( triangle.ny>1.0E-8 ) { minX2 = triangle.getMinY(nodes)+1.05*triangle.ny*startDistance;
+      maxX2 = triangle.getMaxY(nodes)+1.05*triangle.ny*stopDistance;  }     
+      else                     { minX2 = triangle.getMinY(nodes)+1.05*triangle.ny*stopDistance; 
+      maxX2 = triangle.getMaxY(nodes)+1.05*triangle.ny*startDistance; }     
+
+      if( triangle.nz>1.0E-8 ) { minX3 = triangle.getMinZ(nodes)+1.05*triangle.nz*startDistance;
+      maxX3 = triangle.getMaxZ(nodes)+1.05*triangle.nz*stopDistance;  }     
+      else                     { minX3 = triangle.getMinZ(nodes)+1.05*triangle.nz*stopDistance; 
+      maxX3 = triangle.getMaxZ(nodes)+1.05*triangle.nz*startDistance; }     
+
+
+      int flag = 0;
+      //Levelweise alle Bloecke holen, die erweiterte BB schneiden 
+      //und bearbeiten
+      for(int l=coarsestLevel; l<level; l++)
+      {
+         std::vector<Block3DPtr> consideredBlocks;
+         bgrid->getBlocksByCuboid(l,minX1, minX2, minX3, maxX1, maxX2, maxX3, consideredBlocks);
+         double x1a,x2a,x3a,x1b,x2b,x3b;
+
+         for(size_t b=0; b<consideredBlocks.size(); b++)
+         {
+            Block3DPtr block = consideredBlocks[b];
+            if(block->getLevel()>=level) continue;
+
+            //start coordinaten des blocks ermitteln
+            UbTupleDouble3 coords = bgrid->getBlockWorldCoordinates(block);
+            UbTupleDouble3 deltas = bgrid->getBlockLengths(block);
+
+            //Check, ob block komplett im Halbraum
+            x1a = val<1>(coords);   x1b = val<1>(coords)+val<1>(deltas);
+            x2a = val<2>(coords);   x2b = val<2>(coords)+val<2>(deltas);
+            x3a = val<3>(coords);   x3b = val<3>(coords)+val<3>(deltas);
+
+            flag = 0;
+            if( !halfSpace.ptInside(x1a,x2a,x3a) )  flag |= (1<<0); //1
+            if( !halfSpace.ptInside(x1b,x2a,x3a) )  flag |= (1<<1); //2
+            if( !halfSpace.ptInside(x1b,x2b,x3a) )  flag |= (1<<2); //4
+            if( !halfSpace.ptInside(x1a,x2b,x3a) )  flag |= (1<<3); //8
+            if( !halfSpace.ptInside(x1a,x2a,x3b) )  flag |= (1<<4); //16
+            if( !halfSpace.ptInside(x1b,x2a,x3b) )  flag |= (1<<5); //32
+            if( !halfSpace.ptInside(x1b,x2b,x3b) )  flag |= (1<<6); //64
+            if( !halfSpace.ptInside(x1a,x2b,x3b) )  flag |= (1<<7); //128
+
+
+            if( true && flag!=255 )
+            {
+               //blockseite ermitteln (skalarprodukt dreiecks-normale, vector (midTri->midCub) )
+               //je nachdem muss für den massgeblichen block start oder stopdistance verwendet werden
+               //liegt block auf pos seite -> stopdistance ansonsten startdistance
+               double skalarprod =   triangle.nx * ( 0.5*(x1a+x1b)-triangle.getX1Centroid(nodes) )
+                  + triangle.ny * ( 0.5*(x2a+x2b)-triangle.getX2Centroid(nodes) )
+                  + triangle.nz * ( 0.5*(x3a+x3b)-triangle.getX3Centroid(nodes) );
+
+               double blockdelta  = 1.05*stopDistance;
+               if     (skalarprod<1.E-8       ) blockdelta = -1.05*startDistance;  //startDistance<0!!
+               else if( fabs(skalarprod)<1.E-8) blockdelta =  1.05*UbMath::max(-startDistance,stopDistance);
+
+               //block anpassen
+               blockMinX[0]   = (float)(val<1>(coords)-blockdelta );
+               blockMinX[1]   = (float)(val<2>(coords)-blockdelta );
+               blockMinX[2]   = (float)(val<3>(coords)-blockdelta );
+
+               blockMaxX[0]   = (float)(val<1>(coords)+val<1>(deltas)+blockdelta );
+               blockMaxX[1]   = (float)(val<2>(coords)+val<2>(deltas)+blockdelta );
+               blockMaxX[2]   = (float)(val<3>(coords)+val<3>(deltas)+blockdelta );
+
+               boxCenter[0]   = (float)(0.5*(blockMaxX[0]+blockMinX[0]));
+               boxCenter[1]   = (float)(0.5*(blockMaxX[1]+blockMinX[1]));
+               boxCenter[2]   = (float)(0.5*(blockMaxX[2]+blockMinX[2]));
+
+               halfBoxSize[0] = (float)(0.5*(blockMaxX[0]-blockMinX[0]));
+               halfBoxSize[1] = (float)(0.5*(blockMaxX[1]-blockMinX[1]));
+               halfBoxSize[2] = (float)(0.5*(blockMaxX[2]-blockMinX[2]));
+
+               GbTriFaceMesh3D::Vertex& v1 = nodes[triangle.v1];
+               GbTriFaceMesh3D::Vertex& v2 = nodes[triangle.v2];
+               GbTriFaceMesh3D::Vertex& v3 = nodes[triangle.v3];
+
+               triPoints[0][0] = v1.x; triPoints[0][1] = v1.y; triPoints[0][2] = v1.z; 
+               triPoints[1][0] = v2.x; triPoints[1][1] = v2.y; triPoints[1][2] = v2.z; 
+               triPoints[2][0] = v3.x; triPoints[2][1] = v3.y; triPoints[2][2] = v3.z; 
+
+               //wenn block dreick schneidet, dann muss er verfeinert werden
+               if( GbMeshTools3D::triBoxOverlap(boxCenter,halfBoxSize,triPoints) )
+               {
+                  bgrid->expandBlock(block->getX1(), block->getX2(),block->getX3(),block->getLevel());
+               }
+            }
+         }
+      }
+   }
+   UBLOG(logDEBUG1, " - refine done");
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27TriFaceMeshInteractor::updateMovedGeometry(const double& timeStep)
+{
+
+}
+////////////////////////////////////////////////////////////////////////////
+void D3Q27TriFaceMeshInteractor::recursiveGridFill(CbArray3D<FLAGS>& flagfield, const short& xs, const short& ys, const short& zs, const FLAGS& type)
+{
+   // Algorithmus zum Füllen eines Polyeders, ausgehend vom Saatpunkt xs,ys,zs
+
+   //Saatknoten einfärben
+   if( flagfield(xs,ys,zs)==UNDEF_FLAG )
+   {
+      flagfield(xs,ys,zs) = type;
+
+      if ( flagfield.indicesInRange( xs+1, ys  , zs   ) ) this->recursiveGridFill(flagfield,xs+1, ys  , zs  ,type);
+      if ( flagfield.indicesInRange( xs  , ys+1, zs   ) ) this->recursiveGridFill(flagfield,xs  , ys+1, zs  ,type);
+      if ( flagfield.indicesInRange( xs  , ys  , zs+1 ) ) this->recursiveGridFill(flagfield,xs  , ys  , zs+1,type);
+      if ( flagfield.indicesInRange( xs-1, ys  , zs   ) ) this->recursiveGridFill(flagfield,xs-1, ys  , zs  ,type);
+      if ( flagfield.indicesInRange( xs  , ys-1, zs   ) ) this->recursiveGridFill(flagfield,xs  , ys-1, zs  ,type);
+      if ( flagfield.indicesInRange( xs  , ys  , zs-1 ) ) this->recursiveGridFill(flagfield,xs  , ys  , zs-1,type);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27TriFaceMeshInteractor::iterativeGridFill(CbArray3D<FLAGS>& flagfield, const short& xs, const short& ys, const short& zs, const FLAGS& type)
+{
+   std::stack< UbTupleInt3 > stck;
+   stck.push( UbTupleInt3(xs,ys,zs) );
+
+   int x,y,z;
+
+   while( !stck.empty() )  
+   {
+      x = val<1>( stck.top() );
+      y = val<2>( stck.top() );
+      z = val<3>( stck.top() );
+      stck.pop();
+
+      FLAGS& flagType = flagfield( x, y, z );
+
+      if( flagType == UNDEF_FLAG ) 
+      {     
+         flagType = type;
+
+         if ( flagfield.indicesInRange( x+1, y  , z   ) ) stck.push( UbTupleInt3( x+1, y  , z   ) );
+         if ( flagfield.indicesInRange( x  , y+1, z   ) ) stck.push( UbTupleInt3( x  , y+1, z   ) );
+         if ( flagfield.indicesInRange( x  , y  , z+1 ) ) stck.push( UbTupleInt3( x  , y  , z+1 ) );
+         if ( flagfield.indicesInRange( x-1, y  , z   ) ) stck.push( UbTupleInt3( x-1, y  , z   ) );
+         if ( flagfield.indicesInRange( x  , y-1, z   ) ) stck.push( UbTupleInt3( x  , y-1, z   ) );
+         if ( flagfield.indicesInRange( x  , y  , z-1 ) ) stck.push( UbTupleInt3( x  , y  , z-1 ) );
+      }
+   }
+   return;
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleDouble3 D3Q27TriFaceMeshInteractor::getForces()
+{
+   //FeTriFaceMesh3D* feMesh = dynamic_cast<FeTriFaceMesh3D*>(this->geoObject3D.get());
+   //if(!feMesh)
+   //{
+   //   return D3Q19AMRInteractor::getForces();
+   //}
+   ////return getForcesTriangle();
+   //this->calculateForces();
+
+   double forceX1=0.0;
+   double forceX2=0.0;
+   double forceX3=0.0;
+
+   //double area = 0.0;
+
+   //vector<FeTriFaceMesh3D::VertexAttributes>* attributes = feMesh->getAttributes();
+
+   //for(size_t i=0; i<attributes->size(); i++)
+   //{
+   //   FeTriFaceMesh3D::VertexAttributes& attribut = (*attributes)[i];
+   //   area = attribut.getArea();
+   //   forceX1 += attribut.getFX()*area;
+   //   forceX2 += attribut.getFY()*area;
+   //   forceX3 += attribut.getFZ()*area;
+   //}
+   return UbTupleDouble3(forceX1,forceX2,forceX3);
+}
+//////////////////////////////////////////////////////////////////////////
+UbTupleDouble3 D3Q27TriFaceMeshInteractor::getForcesTriangle()
+{
+   double forceX1=0.0;
+   double forceX2=0.0;
+   double forceX3=0.0;
+
+   //D3Q19BlockGrid& grid.lock() = dynamic_cast<D3Q19BlockGrid&>(*this->grid.lock());
+   ////   CoordinateTransformation3D *trafo = this->grid.lock()->getTransformation();
+   ////   int minLevel = this->grid.lock()->getFinestInitializedLevel();
+   ////    double scaleX = trafo->getX1CoordinateScaling()/(1<<minLevel);
+   ////    double scaleY = trafo->getX2CoordinateScaling()/(1<<minLevel);
+   ////    double scaleZ = trafo->getX3CoordinateScaling()/(1<<minLevel);
+   ////    int blocknx1 = grid.lock()->getBlockNX1();
+   ////    int blocknx2 = grid.lock()->getBlockNX2();
+   ////    int blocknx3 = grid.lock()->getBlockNX3();
+   ////    double xOffset = trafo->getX1CoordinateOffset();
+   ////    double yOffset = trafo->getX2CoordinateOffset();
+   ////    double zOffset = trafo->getX3CoordinateOffset();
+   //vector<D3Q19Real> collFactors = ((D3Q19Calculator*)grid.lock()->getCalculator())->getCollisionsFactors();
+
+   ////for (int i=0;i<(int)gbTriangle3DInteractors.size(); i++)
+   ////{
+   ////   GbTriangle3D* tri = (GbTriangle3D*)gbTriangle3DInteractors[i]->getGbObject3D();
+
+   ////   double px0 = tri->getX1Centroid();
+   ////   double py0 = tri->getX2Centroid();
+   ////   double pz0 = tri->getX3Centroid();
+   ////   double px = px0-xOffset;
+   ////   double py = py0-yOffset;
+   ////   double pz = pz0-zOffset;
+   ////   px = px/scaleX;
+   ////   py = py/scaleY;
+   ////   pz = pz/scaleZ;
+   ////   int x1 = (int)px;
+   ////   int y1 = (int)py;
+   ////   int z1 = (int)pz;
+   ////   AMR3DBlock* block = this->grid.lock()->getBlock(x1,y1,z1,minLevel);
+   ////   if(!block)  block = this->grid.lock()->getSuperBlock(x1,y1,z1,minLevel);
+   ////   if(!block) throw UbException(__FILE__,__LINE__,"kein Block ...");
+
+   ////   double collFactor = collFactors[block->getLevel()];
+   ////   double nodeDistance = grid.lock()->getNodeDeltaX(block->getLevel());
+   ////   double bertX1 = ((px0-xOffset)/(1000.*nodeDistance));
+   ////   double bertX2 = ((py0-yOffset)/(1000.*nodeDistance));
+   ////   double bertX3 = ((pz0-zOffset)/(1000.*nodeDistance));
+   ////   int abstaendeX1 = (int)(bertX1*1000.);
+   ////   int abstaendeX2 = (int)(bertX2*1000.);
+   ////   int abstaendeX3 = (int)(bertX3*1000.);
+   ////   int posW = abstaendeX1 - block->getX1Index()*blocknx1;
+   ////   int posS = abstaendeX2 - block->getX2Index()*blocknx2;
+   ////   int posB = abstaendeX3 - block->getX3Index()*blocknx3;
+   ////   int posE=posW+1;
+   ////   int posN=posS+1;
+   ////   int posT=posB+1;
+
+   ////   D3Q19BlockDescriptor *bvd = dynamic_cast<D3Q19BlockDescriptor*>(block->getBlockDescriptor());
+   ////   if(!bvd) throw UbException(__FILE__,__LINE__,"kein Bvd ...");
+
+   ////   CbUniformMatrix4D<double,IndexerX1X2X3X4>* tempdistributions = bvd->getTempDistributionMatrix();
+   ////   D3Q19BCMatrix<D3Q19BoundaryCondition> *bcMatrix = bvd->getBcMatrix();
+
+   ////   UbTupleDouble6 stresses;
+   ////   double dX = px0-this->geoObject3D->getX1Centroid();
+   ////   double dY = py0-this->geoObject3D->getX2Centroid();
+   ////   double dZ = pz0-this->geoObject3D->getX3Centroid();
+   ////   if(dX<=0.0 && dY<=0.0 && dZ<=0.0)
+   ////   {
+   ////      double *fWSB  = tempdistributions->getStartAdressOfSortedArray(posW,posS,posB,0);
+   ////      if(bcMatrix->isFluid(posW,posS,posB)) stresses = D3Q19System::getIncompStresses(fWSB, collFactor );
+   ////      else cout<<__LINE__<<" nicht fluid ...";
+   ////   }
+   ////   else if(dX<=0.0 && dY>0.0 && dZ<=0.0)
+   ////   {
+   ////      double *fWNB  = tempdistributions->getStartAdressOfSortedArray(posW,posN,posB,0);
+   ////      if(bcMatrix->isFluid(posW,posN,posB)) stresses = D3Q19System::getIncompStresses(fWNB, collFactor );
+   ////      else cout<<__LINE__<<" nicht fluid ...";
+   ////   }
+   ////   else if(dX<=0.0 && dY<=0.0 && dZ>0.0)
+   ////   {
+   ////      double *fWST  = tempdistributions->getStartAdressOfSortedArray(posW,posS,posT,0);
+   ////      if(bcMatrix->isFluid(posW,posS,posT)) stresses = D3Q19System::getIncompStresses(fWST, collFactor );
+   ////      else cout<<__LINE__<<" nicht fluid ...";
+   ////   }
+   ////   else if(dX<=0.0 && dY>0.0 && dZ>0.0)
+   ////   {
+   ////      double *fWNT  = tempdistributions->getStartAdressOfSortedArray(posW,posN,posT,0);
+   ////      if(bcMatrix->isFluid(posW,posN,posT)) stresses = D3Q19System::getIncompStresses(fWNT, collFactor );
+   ////      else cout<<__LINE__<<" nicht fluid ...";
+   ////   }
+   ////   else if(dX>0.0 && dY<=0.0 && dZ<=0.0)
+   ////   {
+   ////      double *fESB  = tempdistributions->getStartAdressOfSortedArray(posE,posS,posB,0);
+   ////      if(bcMatrix->isFluid(posE,posS,posB)) stresses = D3Q19System::getIncompStresses(fESB, collFactor );
+   ////      else cout<<__LINE__<<" nicht fluid ...";
+   ////   }
+   ////   else if(dX>0.0 && dY>0.0 && dZ<=0.0)
+   ////   {
+   ////      double *fENB  = tempdistributions->getStartAdressOfSortedArray(posE,posN,posB,0);
+   ////      if(bcMatrix->isFluid(posE,posN,posB)) stresses = D3Q19System::getIncompStresses(fENB, collFactor );
+   ////      else cout<<__LINE__<<" nicht fluid ...";
+   ////   }
+   ////   else if(dX>0.0 && dY<=0.0 && dZ>0.0)
+   ////   {
+   ////      double *fEST  = tempdistributions->getStartAdressOfSortedArray(posE,posS,posT,0);
+   ////      if(bcMatrix->isFluid(posE,posS,posT)) stresses = D3Q19System::getIncompStresses(fEST, collFactor );
+   ////      else cout<<__LINE__<<" nicht fluid ...";
+   ////   }
+   ////   else if(dX>0.0 && dY>0.0 && dZ>0.0)
+   ////   {
+   ////      double *fENT  = tempdistributions->getStartAdressOfSortedArray(posE,posN,posT,0);
+   ////      if(bcMatrix->isFluid(posE,posN,posT)) stresses = D3Q19System::getIncompStresses(fENT, collFactor );
+   ////      else cout<<__LINE__<<" nicht fluid ...";
+   ////   }
+   ////   else cout<<"punkt mit:"<<dX<<" "<<dY<<" "<<dZ<<" ist nicht bei \n";
+
+   ////   double S11 = val<1>(stresses);
+   ////   double S22 = val<2>(stresses);
+   ////   double S33 = val<3>(stresses);
+   ////   double S12 = val<4>(stresses);
+   ////   double S13 = val<5>(stresses);
+   ////   double S23 = val<6>(stresses);
+
+   ////   GbVector3D normal = tri->getNormal();
+   ////   double nx = normal.X1();
+   ////   double ny = normal.X2();
+   ////   double nz = normal.X3();
+   ////   double area = tri->getArea();
+
+   ////   double Fx1 = area*(S11*nx+S12*ny+S13*nz);
+   ////   double Fy1 = area*(S12*nx+S22*ny+S23*nz);
+   ////   double Fz1 = area*(S13*nx+S23*ny+S33*nz);
+   ////   forceX1 += Fx1;
+   ////   forceX2 += Fy1;
+   ////   forceX3 += Fz1;
+   ////}
+   return UbTupleDouble3(forceX1,forceX2,forceX3);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27TriFaceMeshInteractor::calculateForces()
+{
+   //FeTriFaceMesh3D* feMesh = dynamic_cast<FeTriFaceMesh3D*>(this->geoObject3D.get());
+   //if(!feMesh) throw UbException(UB_EXARGS,"geoObject is not a FeTriFaceMesh3D!");
+
+   //if(this->stressMode == STRESSNORMAL) this->calculateStresses();
+   //else if(this->stressMode == STRESSALTERNATIV) this->calculateStressesAlternativ();
+
+   //vector<FeTriFaceMesh3D::VertexAttributes>* attributes = feMesh->getAttributes();
+
+   //for (int i=0;i<(int)attributes->size() ;i++)
+   //{
+   //   FeTriFaceMesh3D::VertexAttributes& attribut = (*attributes)[i];
+   //   attribut.setFX(0.0);
+   //   attribut.setFY(0.0);
+   //   attribut.setFZ(0.0);
+   //   attribut.setArea(0.0);
+   //}
+   //vector<GbTriFaceMesh3D::TriFace>& triangles = *feMesh->getTriangles();
+   //vector<GbTriFaceMesh3D::Vertex>&  nodes = *feMesh->getNodes();
+   //for (size_t i=0; i<triangles.size(); i++)
+   //{
+   //   GbTriFaceMesh3D::TriFace& triangle = triangles[i];
+   //   FeTriFaceMesh3D::VertexAttributes& vAttribut1 = (*attributes)[triangle.v1];
+   //   FeTriFaceMesh3D::VertexAttributes& vAttribut2 = (*attributes)[triangle.v2];
+   //   FeTriFaceMesh3D::VertexAttributes& vAttribut3 = (*attributes)[triangle.v3];
+   //   UbTupleDouble6& stressesP1 = vAttribut1.getStresses();
+   //   UbTupleDouble6& stressesP2 = vAttribut2.getStresses();
+   //   UbTupleDouble6& stressesP3 = vAttribut3.getStresses();
+   //   double p1S11 = val<1>(stressesP1); double p2S11 = val<1>(stressesP2); double p3S11 = val<1>(stressesP3);
+   //   double p1S22 = val<2>(stressesP1); double p2S22 = val<2>(stressesP2); double p3S22 = val<2>(stressesP3);
+   //   double p1S33 = val<3>(stressesP1); double p2S33 = val<3>(stressesP2); double p3S33 = val<3>(stressesP3);
+   //   double p1S12 = val<4>(stressesP1); double p2S12 = val<4>(stressesP2); double p3S12 = val<4>(stressesP3);
+   //   double p1S13 = val<5>(stressesP1); double p2S13 = val<5>(stressesP2); double p3S13 = val<5>(stressesP3);
+   //   double p1S23 = val<6>(stressesP1); double p2S23 = val<6>(stressesP2); double p3S23 = val<6>(stressesP3);
+
+   //   triangle.calculateNormal(nodes);
+   //   double nx = triangle.nx;
+   //   double ny = triangle.ny;
+   //   double nz = triangle.nz;
+   //   double area = 0.3333*triangle.getArea(nodes);
+
+   //   if(UbMath::lessEqual(area,0.0)) cout<<__FILE__<<" "<<__LINE__<<" area <= 0 "<<endl;
+
+   //   double Fx1 = area*(0.333*(p1S11*nx+p1S12*ny+p1S13*nz)+0.333*(p2S11*nx+p2S12*ny+p2S13*nz)+0.333*(p3S11*nx+p3S12*ny+p3S13*nz));
+   //   double Fx2 = Fx1;
+   //   double Fx3 = Fx1;
+
+   //   double Fy1 = area*(0.333*(p1S12*nx+p1S22*ny+p1S23*nz)+0.333*(p2S12*nx+p2S22*ny+p2S23*nz)+0.333*(p3S12*nx+p3S22*ny+p3S23*nz));
+   //   double Fy2 = Fy1;
+   //   double Fy3 = Fy1;
+
+   //   double Fz1 = area*(0.333*(p1S13*nx+p1S23*ny+p1S33*nz)+0.333*(p2S13*nx+p2S23*ny+p2S33*nz)+0.333*(p3S13*nx+p3S23*ny+p3S33*nz));
+   //   double Fz2 = Fz1;
+   //   double Fz3 = Fz1;
+   //   //  cout<<Fx1<<" "<<Fy1<<" "<<Fz1<<endl;
+   //   vAttribut1.addFX(Fx1);    vAttribut2.addFX(Fx2);    vAttribut3.addFX(Fx3);
+   //   vAttribut1.addFY(Fy1);    vAttribut2.addFY(Fy2);    vAttribut3.addFY(Fy3);
+   //   vAttribut1.addFZ(Fz1);    vAttribut2.addFZ(Fz2);    vAttribut3.addFZ(Fz3);
+   //   vAttribut1.addArea(area); vAttribut2.addArea(area); vAttribut3.addArea(area);
+   //}
+   //for (size_t i=0; i<attributes->size(); i++)
+   //{
+   //   FeTriFaceMesh3D::VertexAttributes& attribut = (*attributes)[i];
+
+   //   double newFX = attribut.getFX()/attribut.getArea();
+   //   double newFY = attribut.getFY()/attribut.getArea();
+   //   double newFZ = attribut.getFZ()/attribut.getArea();
+   //   //if(i==100) cout<<"F:"<<newFX<<" "<<newFY<<" "<<newFZ<<endl;
+   //   //double oldFX = p->getOldFX();
+   //   //double oldFY = p->getOldFY();
+   //   //int alphaSteps = p->getFilteringSteps();
+   //   //double alpha = 1.0;
+   //   //if(alphaSteps != 0)
+   //   //{
+   //   //   alpha = (1.0-alphaSteps*0.1);
+   //   // //  cout<<p->toString()<<" alpha:"<<alpha<<" steps:"<<alphaSteps<<endl;
+   //   //   p->reduceFilteringSteps();
+   //   //}
+   //   //newFX = (1.-alpha)*oldFX+alpha*newFX;
+   //   //newFY = (1.-alpha)*oldFY+alpha*newFY;
+
+   //   attribut.setFX(newFX);
+   //   attribut.setFY(newFY);
+   //   attribut.setFZ(newFZ);
+   //   //cout<<i<<" "<<newFX<<" "<<newFY<<" "<<newFZ<<endl;
+   //   //cout<<i<<" "<<p->toString()<<endl;
+
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+string D3Q27TriFaceMeshInteractor::toString()
+{
+   stringstream ss;
+   ss<< "D3Q27TriFaceMeshInteractor[label=D3Q27TriFaceMeshInteractor";
+   if(this->isSolid()) ss<<", solid";
+   if(this->isInverseSolid()) ss<<", inversesolid";
+   if(this->isTimeDependent()) ss<<", timedependent";
+   if(geoObject3D!=NULL) ss<<", AMR3DInteractor: "<<geoObject3D->toString();
+   ss<<"]";
+
+   return ss.str();
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27TriFaceMeshInteractor::reinitWithStoredQs( const double& timeStep )
+{
+   //alle solid Bloecke wieder solid setzen
+   std::vector<Block3DPtr>& solidBlocks = this->getSolidBlockSet();
+   for(size_t i=0; i<solidBlocks.size(); i++)
+   {
+      solidBlocks[i]->setActive(false); //<- quick n dirty
+   }
+
+   //alle solid-nodes wieder solid setzen (solids die quasi in den TransBloecken liegen)
+   std::map<Block3DPtr, std::set< UbTupleInt3 > >::iterator it1;
+   for( it1=this->solidNodeIndicesMap.begin(); it1!=this->solidNodeIndicesMap.end(); ++it1 )
+   {
+      Block3DPtr block = it1->first;
+
+      LBMKernel3DPtr kernel = block->getKernel();
+      BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+      std::set< UbTupleInt3 >&  indicesSet = it1->second;
+
+      for( std::set< UbTupleInt3 >::iterator setIt=indicesSet.begin(); setIt!=indicesSet.end(); ++setIt )
+      {
+         bcMatrix.setSolid( val<1>(*setIt), val<2>(*setIt), val<3>(*setIt) );
+      }
+   }
+
+   //BCS WIEDERHERSTELLEN
+   std::map<Block3DPtr, std::map< UbTupleInt3, std::vector<float> > >::iterator it;
+   for( it=transNodeIndicesAndQsMap.begin(); it!=transNodeIndicesAndQsMap.end(); ++it )
+   {   
+      Block3DPtr  block    = it->first;
+      LBMKernel3DPtr kernel = block->getKernel();
+      BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+      std::map< UbTupleInt3, std::vector<float> >::iterator it2;
+      for( it2=it->second.begin(); it2!=it->second.end(); ++it2 )
+      {   
+         const UbTupleInt3&    pos = it2->first;
+         std::vector< float >       qs  = it2->second;
+
+         //SG_27.08.2010 
+         if(bcMatrix.isSolid(val<1>(pos), val<2>(pos), val<3>(pos))) continue;
+
+         D3Q27BoundaryConditionPtr   bc = bcMatrix.getBC( val<1>(pos), val<2>(pos), val<3>(pos) );
+         if(!bc)
+         {
+            bc = D3Q27BoundaryConditionPtr(new D3Q27BoundaryCondition);
+            bcMatrix.setBC( val<1>(pos), val<2>(pos), val<3>(pos), bc );
+         }
+
+         double x1w = qs[D3Q27System::FENDDIR+1+0];
+         double x2w = qs[D3Q27System::FENDDIR+1+1];
+         double x3w = qs[D3Q27System::FENDDIR+1+2];
+
+
+         //TODO: HACK GEHOERT NICHT HIERHIER!!! - start
+         //es handelt sich un ein statisches Objekt und beim Propeller gibt
+         // es Schwierigkeiten an den Flügelspitzen, dass kann daher kommen,
+         //dass dort zuviel bc-flaggs sind und mit Geschwindigkeit ergibt dies ziemlich grosse Werte
+         bc->setBoundaryVelocityX1(0.0);
+         bc->setBoundaryVelocityX2(0.0);
+         bc->setBoundaryVelocityX3(0.0);
+         //TODO: HACK GEHOERT NICHT HIERHIER!!! - end
+
+         bool gotQs = false;
+         for(int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+         {
+            if( UbMath::greater(qs[fdir], -1.0) && UbMath::less( qs[fdir], bc->getQ(fdir) ) )
+            {
+               gotQs = true;
+               for(size_t index=0; index<this->bcAdapterVector.size(); index++)
+                  this->bcAdapterVector[index]->adaptBCForDirection( *this, bc, x1w, x2w, x3w, qs[fdir], fdir);
+            }
+         }
+
+         if(gotQs)
+            for(size_t index=0; index<this->bcAdapterVector.size(); index++)
+               this->bcAdapterVector[index]->adaptBC( *this, bc, x1w, x2w, x3w);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27TriFaceMeshInteractor::updateInteractor( const double& timestep/*=0*/ )
+{
+   UB_THROW( UbException("D3Q27TriFaceMeshInteractor::updateInteractor - toDo") );
+}
+
+
+
+
+
+
diff --git a/source/VirtualFluidsCore/Interactors/D3Q27TriFaceMeshInteractor.h b/source/VirtualFluidsCore/Interactors/D3Q27TriFaceMeshInteractor.h
new file mode 100644
index 0000000000000000000000000000000000000000..a788046eb7a331e5dfec542f1c719db6b3d5befb
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/D3Q27TriFaceMeshInteractor.h
@@ -0,0 +1,126 @@
+#ifndef D3Q19AMRTRIFACEMESHINTERACTOR_H
+#define D3Q19AMRTRIFACEMESHINTERACTOR_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <list>
+#include <map>
+#include <cmath>
+
+
+#include "D3Q27Interactor.h"
+#include <numerics/geometry3d/GbTriFaceMesh3D.h>
+
+class UbFileInput;
+class UbFileOutput;
+class GbObject3D;
+class Grid3D;
+
+//////////////////////////////////////////////////////////////////////////
+
+#include <boost/shared_ptr.hpp>
+
+class D3Q27TriFaceMeshInteractor;
+typedef boost::shared_ptr<D3Q27TriFaceMeshInteractor> D3Q27TriFaceMeshInteractorPtr;
+
+//////////////////////////////////////////////////////////////////////////
+// D3Q27TriFaceMeshInteractor
+//
+//////////////////////////////////////////////////////////////////////////
+class D3Q27TriFaceMeshInteractor : public D3Q27Interactor 
+{
+public:
+   static const int STRESSNORMAL=0;
+   static const int STRESSALTERNATIV=1;
+
+   D3Q27TriFaceMeshInteractor();
+   D3Q27TriFaceMeshInteractor(Grid3DPtr grid, std::string name="D3Q27TriFaceMeshInteractor");
+   D3Q27TriFaceMeshInteractor(GbObject3DPtr geoObject3D, Grid3DPtr grid, int type);
+   D3Q27TriFaceMeshInteractor(GbTriFaceMesh3DPtr triFaceMesh, Grid3DPtr grid, D3Q27BoundaryConditionAdapterPtr bcAdapter, int type);
+   D3Q27TriFaceMeshInteractor(GbTriFaceMesh3DPtr triFaceMesh, Grid3DPtr grid, D3Q27BoundaryConditionAdapterPtr bcAdapter, int type, Interactor3D::Accuracy a);
+   //D3Q27TriFaceMeshInteractor(GbTriFaceMesh3DPtr triFaceMesh, D3Q27BoundaryConditionAdapterPtr bcAdapter, int type, std::string name="D3Q27TriFaceMeshInteractor");
+
+   ~D3Q27TriFaceMeshInteractor();
+
+   virtual void initInteractor(const double& timeStep=0);
+   virtual void initInteractor2(const double& timeStep=0);
+
+   void updateInteractor(const double& timestep=0);
+
+   void updateMovedGeometry(const double& timeStep=0);
+   void setQs(const double& timeStep);
+   void refineBlockGridToLevel(int level, double startDistance, double stopDistance);
+
+   bool setDifferencesToGbObject3D(const Block3DPtr block/*,const double& orgX1,const double& orgX2,const double& orgX3,const double& blockLengthX1,const double& blockLengthX2,const double& blockLengthX3, const double& timestep=0*/);
+
+   void setRegardPointInObjectTest( bool opt ) { this->regardPIOTest = opt; }
+
+   ObObject*        clone() { throw UbException(UB_EXARGS,"not implemented");	}
+   ObObjectCreator* getCreator();
+
+   UbTupleDouble3 getForces();
+   UbTupleDouble3 getForcesTriangle();
+
+   void setStressMode(int stressMode)                      { this->stressMode = stressMode;                         }
+   void setUseHalfSpaceCheck(bool useHalfSpace )           { this->useHalfSpace = useHalfSpace;                     }
+   //void setReinitWithStoredQs(bool reinitWithStoredQsFlag) { this->reinitWithStoredQsFlag = reinitWithStoredQsFlag; }
+
+   void calculateForces();
+   void calculateStresses(); 
+   void calculateStressesAlternativ();            
+
+   void calcStressesLine(UbTupleDouble6& stresses, const double& weight, const UbTupleDouble6& stvW, const UbTupleDouble6& stvE );
+   void calcStressesFace(UbTupleDouble6& stresses, const double& weightX, const double& weightY, const UbTupleDouble6& stvSW, const UbTupleDouble6& stvSE, const UbTupleDouble6& stvNE, const UbTupleDouble6& stvNW );
+   void calcStressesCube(UbTupleDouble6& stresses, const double& weightX, const double& weightY, const double& weightZ, const UbTupleDouble6& stvBSW, const UbTupleDouble6& stvBSE, const UbTupleDouble6& stvBNE, const UbTupleDouble6& stvBNW, const UbTupleDouble6& stvTSW, const UbTupleDouble6& stvTSE, const UbTupleDouble6& stvTNE, const UbTupleDouble6& stvTNW  );
+
+   void calculatePressure(); 
+   void calcPressureLine(double &p, const double& weight, const double& pW, const double& pE );
+   void calcPressureFace(double &p, const double& weightX, const double& weightY, const double& pSW, const double& pSE, const double& pNE, const double& pNW );
+   void calcPressureCube(double &p, const double& weightX, const double& weightY, const double& weightZ, const double& pBSW, const double& pBSE, const double& pBNE, const double& pBNW, const double& pTSW, const double& pTSE, const double& pTNE, const double& pTNW  );
+
+   void   setForceShift(double forceshift)   { this->forceshift = forceshift; this->forceshiftpolicy = true; }
+   void   setVelocityShift(double velocityshift)   { this->velocityshift = velocityshift; this->velocityshiftpolicy = true; }
+   double getForceShift()     { return this->forceshift; }
+   double getVelocityShift()  { return this->velocityshift; }
+   bool   getForceShiftPolicy() { return forceshiftpolicy;}
+   bool   getVelocityShiftPolicy() { return velocityshiftpolicy;}
+
+   void clearTransNodeIndicesAndQsMap() { this->transNodeIndicesAndQsMap.clear();}
+
+   virtual std::string toString();
+
+
+protected:
+   int    stressMode;
+
+   double forceshift;       
+   double velocityshift;
+   bool   forceshiftpolicy;
+   bool   velocityshiftpolicy;
+   bool   useHalfSpace;
+   bool   regardPIOTest;
+
+   void reinitWithStoredQs(const double& timeStep);
+   //   bool reinitWithStoredQsFlag;
+   std::map< Block3DPtr, std::map < UbTupleInt3, std::vector< float > > > transNodeIndicesAndQsMap;    //!!! es kann sein, dass in diesem interactor
+   //an eine rpos eine BC gesetzt wurde, aber derselbe node in
+   //in einem anderen in einen anderen Typ (z.B. Solid) geaendert
+   //wurde --> es ist keine BC mehr an der stelle!
+
+   enum SolidCheckMethod { ScanLine, PointInObject };
+
+   enum FLAGS { BC_FLAG, UNDEF_FLAG, FLUID_FLAG, SOLID_FLAG, OLDSOLID_FLAG };
+   void recursiveGridFill(CbArray3D<FLAGS>& flagfield, const short& xs, const short& ys, const short& zs, const FLAGS& type);
+   void iterativeGridFill(CbArray3D<FLAGS>& flagfield, const short& xs, const short& ys, const short& zs, const FLAGS& type); 
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<D3Q27Interactor>(*this);
+   }
+};
+
+
+#endif 
diff --git a/source/VirtualFluidsCore/Interactors/Interactor3D.cpp b/source/VirtualFluidsCore/Interactors/Interactor3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2e966bafc3bc5e673043a0cafe3035480d6828af
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/Interactor3D.cpp
@@ -0,0 +1,492 @@
+#include "Interactor3D.h"
+
+#include <boost/foreach.hpp>
+
+#include <fstream>
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbFileOutput.h>
+
+using namespace std;
+
+const int Interactor3D::SOLID	           = (1<<0); //1
+const int Interactor3D::INVERSESOLID       = (1<<1); //2
+const int Interactor3D::TIMEDEPENDENT      = (1<<2); //4   //zeitlich
+const int Interactor3D::FLUID              = (1<<3); //8
+const int Interactor3D::MOVEABLE           = (1<<4); //16  // geometrisch
+const int Interactor3D::CHANGENOTNECESSARY = (1<<5); //32
+
+//////////////////////////////////////////////////////////////////////////
+Interactor3D::Interactor3D()
+  : type(SOLID)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+Interactor3D::Interactor3D(Grid3DPtr grid, int type)
+   :   type(type)
+     , grid(grid)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+Interactor3D::Interactor3D(GbObject3DPtr geoObject3D, Grid3DPtr grid, int type)
+   :   geoObject3D(geoObject3D)
+     , grid(grid)
+     , type(type)
+     , accuracy(SIMPLE)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+Interactor3D::Interactor3D(GbObject3DPtr geoObject3D, Grid3DPtr grid, int type, Interactor3D::Accuracy a)
+   :   geoObject3D(geoObject3D)
+   , grid(grid)
+   , type(type)
+   , accuracy(a)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+Interactor3D::~Interactor3D()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+//void Interactor3D::deleteSolidBlocks(int level)
+//{
+//   //hier werden die Bloecke aktiv oder nicht aktiv gesetzt
+//   double minX1,minX2,minX3,maxX1,maxX2,maxX3,x1,x2,x3;
+//   int gridRank = grid.lock()->getRank();
+//
+//   vector<Block3DPtr> blockVector;
+//   bool activ = true;
+//   grid.lock()->getBlocks(level, gridRank, activ, blockVector);
+//   BOOST_FOREACH(Block3DPtr block, blockVector)
+//   {
+//      double deltaX = grid.lock()->getDeltaX(block);
+//      UbTupleDouble3 blockLengths  = grid.lock()->getBlockLengths(block);
+//
+//      //Koords bestimmen
+//      UbTupleDouble3 org = grid.lock()->getBlockWorldCoordinates(block);
+//
+//      x1 = val<1>(org);
+//      x2 = val<2>(org);
+//      x3 = val<3>(org);
+//
+//      minX1 = x1;
+//      minX2 = x2;
+//      minX3 = x3;
+//      maxX1 = x1 + val<1>(blockLengths);
+//      maxX2 = x2 + val<2>(blockLengths);
+//      maxX3 = x3 + val<3>(blockLengths);
+//
+//      if(this->isInverseSolid())
+//      {
+//         switch (accuracy)
+//         {
+//         //simple duff
+//         case SIMPLE:
+//            if(!this->geoObject3D->isCellInsideOrCuttingGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3))
+//               block->setActive(false);
+//            break;
+//         //test only edges
+//         case EDGES:
+//            if(arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, minX2, minX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, minX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, maxX2, maxX3, maxX1, maxX2, maxX3, deltaX) &&
+//
+//               arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, minX3, deltaX) &&
+//               arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, minX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(maxX1, minX2, maxX3, maxX1, maxX2, maxX3, deltaX) &&
+//
+//               arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, minX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(maxX1, maxX2, minX3, maxX1, maxX2, maxX3, deltaX))   
+//                  block->setActive(false);
+//            break;
+//         //test only faces
+//         case FACES:
+//            if(arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, minX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, maxX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, minX3, deltaX) &&
+//               arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, maxX2, maxX3, deltaX))
+//                  block->setActive(false);
+//            break;
+//         //test all points
+//         case POINTS:
+//            if(arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX))
+//               block->setActive(false);
+//            break;
+//         default:
+//            UB_THROW( UbException(UB_EXARGS, "Accuracy isn't correct") );
+//            break;
+//         }
+//      }
+//      else //solid 
+//      {
+//         switch (accuracy)
+//         {
+//         //simple duff
+//         case SIMPLE:
+//            if(this->geoObject3D->isCellInsideGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3))
+//               block->setActive(false);
+//            break;
+//         //test only edges
+//         case EDGES:
+//            if(arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, minX2, minX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, minX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, maxX2, maxX3, maxX1, maxX2, maxX3, deltaX) &&
+//
+//               arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, minX3, deltaX) &&
+//               arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, minX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(maxX1, minX2, maxX3, maxX1, maxX2, maxX3, deltaX) &&
+//
+//               arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, minX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(maxX1, maxX2, minX3, maxX1, maxX2, maxX3, deltaX))   
+//               block->setActive(false);
+//            break;
+//         //test only faces
+//         case FACES:
+//            if(arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, minX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, maxX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, minX3, deltaX) &&
+//               arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, maxX2, maxX3, deltaX))
+//               block->setActive(false);
+//            break;
+//         //test all points
+//         case POINTS:
+//            if(arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX))
+//               block->setActive(false);
+//            break;
+//         default:
+//            UB_THROW( UbException(UB_EXARGS, "Accuracy isn't correct") );
+//            break;
+//         }
+//      }
+//   }
+//}
+//////////////////////////////////////////////////////////////////////////
+bool Interactor3D::arePointsInsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta)
+{
+   bool result = true;
+   for (double ix3=minX3; ix3<=maxX3; ix3+=delta)
+      for (double ix2=minX2; ix2<=maxX2; ix2+=delta)
+         for (double ix1=minX1; ix1<=maxX1; ix1+=delta)
+            result = result && this->geoObject3D->isPointInGbObject3D(ix1, ix2, ix3);
+
+   return result;
+}
+//////////////////////////////////////////////////////////////////////////
+bool Interactor3D::arePointsOutsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta)
+{
+   bool result = true;
+   for (double ix3=minX3; ix3<=maxX3; ix3+=delta)
+      for (double ix2=minX2; ix2<=maxX2; ix2+=delta)
+         for (double ix1=minX1; ix1<=maxX1; ix1+=delta)
+            result = result && (!this->geoObject3D->isPointInGbObject3D(ix1, ix2, ix3));
+
+   return result;
+}
+//////////////////////////////////////////////////////////////////////////
+bool Interactor3D::arePointsCuttingGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta)
+{
+   bool result = true;
+   for (double ix3=minX3; ix3<=maxX3; ix3+=delta)
+      for (double ix2=minX2; ix2<=maxX2; ix2+=delta)
+         for (double ix1=minX1; ix1<=maxX1; ix1+=delta)
+            result = result || this->geoObject3D->isPointInGbObject3D(ix1, ix2, ix3);
+
+   return result;
+}
+//////////////////////////////////////////////////////////////////////////
+bool Interactor3D::isBlockOutsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta)
+{
+   switch (accuracy)
+   {
+      //simple duff
+   case SIMPLE:
+      return !this->geoObject3D->isCellInsideOrCuttingGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3);
+      //test only edges
+   case EDGES:
+      return arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, minX2, minX3, delta) &&
+             arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, minX3, delta) &&
+             arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(minX1, maxX2, maxX3, maxX1, maxX2, maxX3, delta) &&
+             
+             arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, minX3, delta) &&
+             arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, minX3, delta) &&
+             arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(maxX1, minX2, maxX3, maxX1, maxX2, maxX3, delta) &&
+             
+             arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, minX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(maxX1, maxX2, minX3, maxX1, maxX2, maxX3, delta);   
+      //test only faces
+   case FACES:
+      return arePointsOutsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, minX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, maxX3, delta) &&
+             arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, minX3, delta) &&
+             arePointsOutsideGeoObject(minX1, minX2, maxX3, maxX1, maxX2, maxX3, delta);
+      //test all points
+   case POINTS:
+      return arePointsOutsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, delta);
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Accuracy isn't correct") );
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+bool Interactor3D::isBlockInsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta)
+{
+   switch (accuracy)
+   {
+      //simple duff
+   case SIMPLE:
+      return this->geoObject3D->isCellInsideGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3);
+      //test only edges
+   case EDGES:
+      return arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, minX2, minX3, delta) &&
+             arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, minX3, delta) &&
+             arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) &&
+             arePointsInsideGeoObject(minX1, maxX2, maxX3, maxX1, maxX2, maxX3, delta) &&
+             
+             arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, minX3, delta) &&
+             arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, minX3, delta) &&
+             arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) &&
+             arePointsInsideGeoObject(maxX1, minX2, maxX3, maxX1, maxX2, maxX3, delta) &&
+             
+             arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) &&
+             arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) &&
+             arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, minX2, maxX3, delta) &&
+             arePointsInsideGeoObject(maxX1, maxX2, minX3, maxX1, maxX2, maxX3, delta);   
+      //test only faces
+   case FACES:
+      return arePointsInsideGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) &&
+             arePointsInsideGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) &&
+             arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, minX2, maxX3, delta) &&
+             arePointsInsideGeoObject(minX1, maxX2, minX3, maxX1, maxX2, maxX3, delta) &&
+             arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, minX3, delta) &&
+             arePointsInsideGeoObject(minX1, minX2, maxX3, maxX1, maxX2, maxX3, delta);
+      //test all points
+   case POINTS:
+      return arePointsInsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, delta);
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Accuracy isn't correct") );
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+bool Interactor3D::isBlockCuttingGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta)
+{
+   switch (accuracy)
+   {
+      //simple duff
+   case SIMPLE:
+      return this->geoObject3D->isCellCuttingGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3);
+      //test only edges
+   case EDGES:
+      return arePointsCuttingGeoObject(minX1, minX2, minX3, maxX1, minX2, minX3, delta) ||
+             arePointsCuttingGeoObject(minX1, maxX2, minX3, maxX1, maxX2, minX3, delta) ||
+             arePointsCuttingGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(minX1, maxX2, maxX3, maxX1, maxX2, maxX3, delta) ||
+                                                                             
+             arePointsCuttingGeoObject(minX1, minX2, minX3, minX1, maxX2, minX3, delta) ||
+             arePointsCuttingGeoObject(maxX1, minX2, minX3, maxX1, maxX2, minX3, delta) ||
+             arePointsCuttingGeoObject(minX1, minX2, maxX3, maxX1, minX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(maxX1, minX2, maxX3, maxX1, maxX2, maxX3, delta) ||
+                                                                             
+             arePointsCuttingGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(minX1, maxX2, minX3, maxX1, minX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(maxX1, maxX2, minX3, maxX1, maxX2, maxX3, delta);   
+      //test only faceCutting
+   case FACES:        
+      return arePointsCuttingGeoObject(minX1, minX2, minX3, minX1, maxX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(maxX1, minX2, minX3, maxX1, maxX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(minX1, minX2, minX3, maxX1, minX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(minX1, maxX2, minX3, maxX1, maxX2, maxX3, delta) ||
+             arePointsCuttingGeoObject(minX1, minX2, minX3, maxX1, maxX2, minX3, delta) ||
+             arePointsCuttingGeoObject(minX1, minX2, maxX3, maxX1, maxX2, maxX3, delta);
+      //test all pointCutting
+   case POINTS:       
+      return arePointsCuttingGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, delta);
+   default:
+      UB_THROW( UbException(UB_EXARGS, "Accuracy isn't correct") );
+      break;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Interactor3D::setSolidBlock(Block3DPtr block)
+{
+   double minX1,minX2,minX3,maxX1,maxX2,maxX3;
+
+   double deltaX = grid.lock()->getDeltaX(block);
+   UbTupleDouble3 blockLengths  = grid.lock()->getBlockLengths(block);
+   UbTupleDouble3 org = grid.lock()->getBlockWorldCoordinates(block);
+   UbTupleDouble3 nodeOffset = grid.lock()->getNodeOffset(block);
+
+   //coordinates of block without ghost layer
+   minX1 = val<1>(org) + val<1>(nodeOffset);
+   minX2 = val<2>(org) + val<2>(nodeOffset);
+   minX3 = val<3>(org) + val<3>(nodeOffset);
+   maxX1 = val<1>(org) + val<1>(blockLengths) - val<1>(nodeOffset);
+   maxX2 = val<2>(org) + val<2>(blockLengths) - val<2>(nodeOffset);
+   maxX3 = val<3>(org) + val<3>(blockLengths) - val<3>(nodeOffset);
+
+   if(this->isInverseSolid())
+   {
+      if(isBlockOutsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX))
+      {
+         block->setActive(false);
+         this->solidBlocks.push_back(block);
+      }
+   }
+   else //solid 
+   {
+      if(isBlockInsideGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX))
+      {
+         block->setActive(false);
+         this->solidBlocks.push_back(block);
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void Interactor3D::setTransBlock(Block3DPtr block)
+{
+   double minX1,minX2,minX3,maxX1,maxX2,maxX3;
+
+   double deltaX = grid.lock()->getDeltaX(block);
+   UbTupleDouble3 blockLengths  = grid.lock()->getBlockLengths(block);
+   UbTupleDouble3 org = grid.lock()->getBlockWorldCoordinates(block);
+   UbTupleDouble3 nodeOffset = grid.lock()->getNodeOffset(block);
+
+   //coordinates of block with ghost layer
+   minX1 = val<1>(org) - val<1>(nodeOffset);
+   minX2 = val<2>(org) - val<2>(nodeOffset);
+   minX3 = val<3>(org) - val<3>(nodeOffset);
+   maxX1 = val<1>(org) + val<1>(blockLengths) + val<1>(nodeOffset);
+   maxX2 = val<2>(org) + val<2>(blockLengths) + val<2>(nodeOffset);
+   maxX3 = val<3>(org) + val<3>(blockLengths) + val<3>(nodeOffset);
+
+   if(isBlockCuttingGeoObject(minX1, minX2, minX3, maxX1, maxX2, maxX3, deltaX))
+      this->transBlocks.push_back(block);
+}
+//////////////////////////////////////////////////////////////////////////
+void Interactor3D::initInteractor(const double& timeStep)
+{
+   //UBLOG(logINFO, "transBlocks.size = "<<transBlocks.size());
+
+   BOOST_FOREACH(Block3DPtr block, transBlocks)
+   {
+      this->setDifferencesToGbObject3D(block);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+//SOLID:
+//bloecke werden nicht activ gesetzt, wenn der Block vollstaendig in der Geometrie
+//blocke werden in transBlock hinzugefuegt, wenn block+delta schnittpunkt oder beruehrungspunkt mit geo hat
+//fuer jeden transblock wird "setDifferencesToGbObject3D aufgerufen
+//void Interactor3D::initInteractor(const double& timeStep)
+//{
+   //this->removeTransBlocks();
+   //this->removeSolidBlocks();
+
+   ////hier werden die Bloecke aktiv oder nicht aktiv gesetzt
+   //double minX1,minX2,minX3,maxX1,maxX2,maxX3,x1,x2,x3;
+   //int gridRank = grid.lock()->getRank();
+
+   //int minInitLevel = this->grid.lock()->getCoarsestInitializedLevel();
+   //int maxInitLevel = this->grid.lock()->getFinestInitializedLevel();
+
+   //for(int level = minInitLevel; level<=maxInitLevel;level++)
+   //{
+   //   vector<Block3DPtr> blockVector;
+   //   grid.lock()->getBlocks(level, gridRank, blockVector);
+   //   BOOST_FOREACH(Block3DPtr block, blockVector)
+   //   {
+   //      //Koords bestimmen
+   //      UbTupleDouble3 org = grid.lock()->getBlockWorldCoordinates(block);
+   //      UbTupleDouble3 blockLengths  = grid.lock()->getBlockLengths(block);
+   //      double dx = grid.lock()->getDeltaX(block);
+   //      UbTupleDouble3 orgDelta = grid.lock()->getNodeOffset(block);
+   //      UbTupleDouble3 coords = grid.lock()->getNodeCoordinates(block, 0, 0, 0);
+
+   //      //x1 = val<1>(org);
+   //      //x2 = val<2>(org);
+   //      //x3 = val<3>(org);
+   //      x1 = val<1>(coords);
+   //      x2 = val<2>(coords);
+   //      x3 = val<3>(coords);
+
+   //      minX1 = x1;
+   //      minX2 = x2;
+   //      minX3 = x3;
+   //      //maxX1 = x1 + val<1>(blockLengths);
+   //      //maxX2 = x2 + val<2>(blockLengths);
+   //      //maxX3 = x3 + val<3>(blockLengths);
+   //      maxX1 = val<1>(coords);
+   //      maxX2 = val<2>(coords);
+   //      maxX3 = val<3>(coords);
+
+   //      if(this->isInverseSolid())
+   //      {
+   //         if(   UbMath::lessEqual(minX1,geoObject3D->getX1Minimum()) 
+   //            && UbMath::lessEqual(minX2,geoObject3D->getX2Minimum())
+   //            && UbMath::lessEqual(minX3,geoObject3D->getX2Minimum())
+   //            && UbMath::greaterEqual(maxX1,geoObject3D->getX1Maximum())
+   //            && UbMath::greaterEqual(maxX2,geoObject3D->getX2Maximum()) 
+   //            && UbMath::greaterEqual(maxX3,geoObject3D->getX2Maximum()))
+   //         {
+   //            this->transBlocks.push_back(block);
+   //            this->setDifferencesToGbObject3D(block/*, x1, x2, x3, val<1>(blockLengths), val<2>(blockLengths), val<3>(blockLengths), timeStep*/);
+   //         }
+   //         else if(this->geoObject3D->isCellCuttingGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3))
+   //         {
+   //            this->transBlocks.push_back(block);
+   //            this->setDifferencesToGbObject3D(block/*, x1, x2, x3, val<1>(blockLengths), val<2>(blockLengths), val<3>(blockLengths), timeStep*/);
+   //         }
+   //      }
+   //      else //solid 
+   //      {
+   //         //1. Fall: block komlett in geo ist in deleteSolidBlocks() erledigt
+   //         //2. Fall:  Celle umhuellt Geo oder Cell schneidet Geo
+   //         if( this->geoObject3D->isCellCuttingGbObject3D(minX1,minX2,minX3,maxX1,maxX2,maxX3) )
+   //         {
+   //            this->transBlocks.push_back(block);
+   //            this->setDifferencesToGbObject3D(block/*,x1,x2,x3,val<1>(blockLengths),val<2>(blockLengths),val<3>(blockLengths),timeStep*/);
+   //         }
+   //         //3. Fall: cell umhuellt geo:
+   //         else if(   UbMath::lessEqual(    minX1, geoObject3D->getX1Minimum() )
+   //            && UbMath::lessEqual(    minX2, geoObject3D->getX2Minimum() )
+   //            && UbMath::lessEqual(    minX3, geoObject3D->getX3Minimum() )
+   //            && UbMath::greaterEqual( maxX1, geoObject3D->getX1Maximum() )
+   //            && UbMath::greaterEqual( maxX2, geoObject3D->getX2Maximum() )
+   //            && UbMath::greaterEqual( maxX3, geoObject3D->getX3Maximum() ) ) //block umhuellt geo
+   //         {
+   //            throw UbException(UB_EXARGS,"//3. Fall: cell umhuellt geo sollte mit Fall 2 abgedeckt sein!!!");
+
+   //            this->transBlocks.push_back(block);
+   //            this->setDifferencesToGbObject3D(block/*,x1,x2,x3,val<1>(blockLengths),val<2>(blockLengths),val<3>(blockLengths),timeStep*/);
+   //         }
+   //      }
+   //   }
+   //}
+//}
+//////////////////////////////////////////////////////////////////////////
+void Interactor3D::updateInteractor(const double& timeStep)
+{
+   UB_THROW( UbException("Interactor3D::updateInteractor - toDo") );
+}
+//////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/Interactors/Interactor3D.h b/source/VirtualFluidsCore/Interactors/Interactor3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..f589d257322e45c75b7152aa18c86611f7080d77
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/Interactor3D.h
@@ -0,0 +1,124 @@
+#ifndef INTERACTOR3D_H
+#define INTERACTOR3D_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <list>
+#include <cmath>
+
+class UbFileInput;
+class UbFileOutput;
+class GbObject3D;
+class Block3D;
+
+#include <boost/serialization/shared_ptr.hpp>
+class Interactor3D;
+typedef boost::shared_ptr<Interactor3D> Interactor3DPtr;
+
+#include "UbException.h"
+#include "UbTuple.h"
+#include "ObObject.h"
+#include "GbObject3D.h"
+#include "Grid3D.h"
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+class Interactor3D 
+{
+public:
+   enum Accuracy{SIMPLE, EDGES, FACES, POINTS};
+   Interactor3D();
+   Interactor3D(Grid3DPtr grid, int type=Interactor3D::SOLID);
+   Interactor3D(GbObject3DPtr geoObject3D, Grid3DPtr grid, int type);
+   //! constructor
+   //! \param a set accuracy for arePointsInObject() and arePointsNotInObject()
+   Interactor3D(GbObject3DPtr geoObject3D, Grid3DPtr grid, int type, Interactor3D::Accuracy a);
+   
+   virtual ~Interactor3D();
+   virtual void initInteractor(const double& timestep=0); 
+   virtual void updateInteractor(const double& timestep=0)=0;
+   //virtual void deleteSolidBlocks(int level);
+
+   void setSolidBlock(Block3DPtr block);
+   void setTransBlock(Block3DPtr block);
+      
+   virtual UbTupleDouble3 getForces() { UB_THROW( UbException("UbTupleDouble3 getForces() - gehoert in die abgeleitete klasse") ); }
+
+   void setSolid()        { UbSystem::setBit(this->type, SOLID   ); }
+   void setMoveable()     { UbSystem::setBit(this->type, MOVEABLE); }
+   
+   bool isSolid()         { return UbSystem::bitCheck(this->type, SOLID        ); }
+   bool isInverseSolid()  { return UbSystem::bitCheck(this->type, INVERSESOLID ); }
+   bool isTimeDependent() { return UbSystem::bitCheck(this->type, TIMEDEPENDENT); }
+   bool isMoveable()      { return UbSystem::bitCheck(this->type, MOVEABLE     ); }
+   
+   Grid3DPtr getGrid3D()  const { return grid.lock();   }
+   void setGrid3D(Grid3DPtr grid) { this->grid = grid; }
+   virtual GbObject3DPtr  getGbObject3D() const { return geoObject3D; }
+   virtual bool setDifferencesToGbObject3D(const Block3DPtr block/*, const double& x1, const double& x2, const double& x3, const double& blockLengthX1, const double& blockLengthX2, const double& blockLengthX3, const double& timestep=0*/)
+   {
+      return false;  
+   }
+
+   virtual std::vector<Block3DPtr>& getTransBlockSet() { return this->transBlocks; }
+   virtual void removeTransBlocks() { this->transBlocks.clear(); }
+   virtual std::vector<Block3DPtr>& getSolidBlockSet() { return this->solidBlocks; }
+   virtual void removeSolidBlocks() { this->solidBlocks.clear(); }
+
+protected:
+   void setTimeDependent()   { UbSystem::setBit(this->type  , TIMEDEPENDENT); }
+   void unsetTimeDependent() { UbSystem::unsetBit(this->type, TIMEDEPENDENT); }
+   
+   //! detect that points are inside object
+   //! \param min/max coordinates of bounding box
+   //! \param delta is delta x
+   bool arePointsInsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta);
+   
+   //! detect that points aren't inside object
+   //! \param min/max coordinates of bounding box
+   //! \param delta is delta x
+   bool arePointsOutsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta);
+
+   //! detect that points are cutting object
+   //! \param min/max coordinates of bounding box
+   //! \param delta is delta x
+   bool arePointsCuttingGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta);
+   
+   bool isBlockOutsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta);
+   bool isBlockInsideGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta);
+   bool isBlockCuttingGeoObject(double minX1, double minX2, double minX3, double maxX1, double maxX2, double maxX3, double delta);
+
+   int type;
+   
+   Grid3DWeakPtr grid;
+   GbObject3DPtr geoObject3D;
+
+   std::vector<Block3DPtr> transBlocks;
+   std::vector<Block3DPtr> solidBlocks;
+   int accuracy;
+
+public:
+   static const int SOLID	            ;//= (1<<0); //1
+   static const int INVERSESOLID       ;//= (1<<1); //2
+   static const int TIMEDEPENDENT      ;//= (1<<2); //4   //zeitlich
+   static const int FLUID              ;//= (1<<3); //8
+   static const int MOVEABLE           ;//= (1<<4); //16  // geometrisch
+   static const int CHANGENOTNECESSARY ;//= (1<<5); //32
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & transBlocks;
+      ar & solidBlocks;
+   }
+
+};
+
+
+
+#endif
diff --git a/source/VirtualFluidsCore/Interactors/InteractorsHelper.cpp b/source/VirtualFluidsCore/Interactors/InteractorsHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..641339a470d92ad80950dea896ff028063bc49bf
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/InteractorsHelper.cpp
@@ -0,0 +1,84 @@
+#include "InteractorsHelper.h"
+#include <SetSolidOrTransBlockVisitor.h>
+#include <Grid3DVisitor.h>
+#include <boost/foreach.hpp>
+
+
+InteractorsHelper::InteractorsHelper(Grid3DPtr grid, Grid3DVisitorPtr visitor) :
+                                     grid(grid), visitor(visitor)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+InteractorsHelper::~InteractorsHelper()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void InteractorsHelper::addInteractor( Interactor3DPtr interactor )
+{
+   interactors.push_back(interactor);
+}
+//////////////////////////////////////////////////////////////////////////
+void InteractorsHelper::deleteSolidBlocks()
+{
+   BOOST_FOREACH(Interactor3DPtr i, interactors)
+   {
+      //UBLOG(logINFO,"rank="<<grid->getRank()<<", SetSolidOrTransBlockVisitor::start");
+      SetSolidOrTransBlockVisitor v(i, SetSolidOrTransBlockVisitor::SOLID);
+      grid->accept(v);
+      //UBLOG(logINFO,"rank="<<grid->getRank()<<", SetSolidOrTransBlockVisitor::end");
+      std::vector<Block3DPtr>& sb = i->getSolidBlockSet();
+      solidBlocks.insert(solidBlocks.end(), sb.begin(), sb.end());
+      i->removeSolidBlocks();
+   }
+   
+   //UBLOG(logINFO,"rank="<<grid->getRank()<<", solidBlocks.size = " <<solidBlocks.size());
+   
+   updateGrid();
+}
+//////////////////////////////////////////////////////////////////////////
+void InteractorsHelper::updateGrid()
+{
+   std::vector<int> ids;
+
+   BOOST_FOREACH(Block3DPtr block, solidBlocks)
+   {
+      ids.push_back(block->getGlobalID());
+   }
+   
+   //UBLOG(logINFO,"rank="<<grid->getRank()<<", ids.size = " <<ids.size());
+
+   std::vector<int> rids;
+   Communicator::getInstance()->allGather(ids, rids);
+   grid->deleteBlocks(rids);
+}
+//////////////////////////////////////////////////////////////////////////
+void InteractorsHelper::setTransBlocks()
+{
+   BOOST_FOREACH(Interactor3DPtr i, interactors)
+   {
+      SetSolidOrTransBlockVisitor v(i, SetSolidOrTransBlockVisitor::TRANS);
+      grid->accept(v);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void InteractorsHelper::selectBlocks()
+{
+   //domain decomposition visitor
+   grid->accept( visitor );
+   //delete solid blocks
+   deleteSolidBlocks();
+   //domain decomposition visitor
+   grid->accept( visitor );
+   //set trans blocks
+   setTransBlocks();
+}
+//////////////////////////////////////////////////////////////////////////
+void InteractorsHelper::setBC()
+{
+   BOOST_FOREACH(Interactor3DPtr i, interactors)
+   {
+      i->initInteractor();
+   }
+}
diff --git a/source/VirtualFluidsCore/Interactors/InteractorsHelper.h b/source/VirtualFluidsCore/Interactors/InteractorsHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..32bf591efcc125cdf94ba87c6fd72d9a5e71955b
--- /dev/null
+++ b/source/VirtualFluidsCore/Interactors/InteractorsHelper.h
@@ -0,0 +1,27 @@
+#ifndef SolidBlocksHelper_h 
+#define SolidBlocksHelper_h
+
+#include <Grid3D.h>
+#include <Communicator.h>
+#include <Interactor3D.h>
+
+class InteractorsHelper
+{
+public:
+   InteractorsHelper(Grid3DPtr grid, Grid3DVisitorPtr visitor);
+   ~InteractorsHelper();
+   void addInteractor(Interactor3DPtr interactor);
+   void selectBlocks();
+   void setBC();
+protected:
+   void deleteSolidBlocks();
+   void setTransBlocks();
+private:
+   void updateGrid();
+   std::vector<Interactor3DPtr> interactors;
+   Grid3DPtr grid;
+   std::vector<Block3DPtr> solidBlocks;
+   Grid3DVisitorPtr visitor;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/CMakePackage.txt b/source/VirtualFluidsCore/LBM/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/LBM/D3Q27CompactInterpolationProcessor.cpp b/source/VirtualFluidsCore/LBM/D3Q27CompactInterpolationProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a0287657f6c624bb3e6cb6cf2693a72c94889eda
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27CompactInterpolationProcessor.cpp
@@ -0,0 +1,372 @@
+#include "D3Q27CompactInterpolationProcessor.h"
+#include "SimulationParameters.h"
+
+#include <boost/foreach.hpp>
+
+D3Q27CompactInterpolationProcessor::D3Q27CompactInterpolationProcessor()
+                              : omegaC(0.0), omegaF(0.0)
+{
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27CompactInterpolationProcessor::D3Q27CompactInterpolationProcessor(LBMReal omegaC, LBMReal omegaF)
+                                                          : omegaC(omegaC), omegaF(omegaF)
+{
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27CompactInterpolationProcessor::~D3Q27CompactInterpolationProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27InterpolationProcessorPtr D3Q27CompactInterpolationProcessor::clone()
+{
+   return D3Q27InterpolationProcessorPtr (new D3Q27CompactInterpolationProcessor(this->omegaC, this->omegaF));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27CompactInterpolationProcessor::init()
+{
+   calcFeqsForDirFct = NULL;
+   calcMacrosFct     = NULL;
+   calcFeqFct        = NULL;
+   SimulationParametersPtr param = SimulationParameters::getInstanz();
+
+   if(param->isCompressibleModel())
+   {
+      calcMacrosFct     = &D3Q27System::calcCompMacroscopicValues;
+      calcFeqFct        = &D3Q27System::calcCompFeq; 
+   }
+   else
+   {
+      calcMacrosFct     = &D3Q27System::calcIncompMacroscopicValues;
+      calcFeqFct        = &D3Q27System::calcIncompFeq; 
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27CompactInterpolationProcessor::setOmegas( LBMReal omegaC, LBMReal omegaF )
+{
+   this->omegaC = omegaC;
+   this->omegaF = omegaF;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27CompactInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
+{
+   calcInterpolatedCoefficiets(icellC, omegaC);
+   calcInterpolatedNode(icellF.BSW, omegaF, -0.25, -0.25, -0.25);
+   calcInterpolatedNode(icellF.BNE, omegaF,  0.25,  0.25, -0.25);
+   calcInterpolatedNode(icellF.TNW, omegaF, -0.25,  0.25,  0.25);
+   calcInterpolatedNode(icellF.TSE, omegaF,  0.25, -0.25,  0.25);
+   calcInterpolatedNode(icellF.BNW, omegaF, -0.25,  0.25, -0.25);
+   calcInterpolatedNode(icellF.BSE, omegaF,  0.25, -0.25, -0.25);
+   calcInterpolatedNode(icellF.TSW, omegaF, -0.25, -0.25,  0.25);
+   calcInterpolatedNode(icellF.TNE, omegaF,  0.25,  0.25,  0.25);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27CompactInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC)
+{
+   calcInterpolatedCoefficiets(icellF, omegaF);
+   calcInterpolatedNode(icellC, omegaC, 0.0, 0.0, 0.0);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27CompactInterpolationProcessor::interpolate8to1(D3Q27ICell& icellF, LBMReal* icellC, double x1, double x2, double x3, LBMReal omega)
+{
+   calcInterpolatedCoefficiets(icellF, omega);
+   calcInterpolatedNode(icellC, omega, x1, x2, x3);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27CompactInterpolationProcessor::calcMoments(const LBMReal* const f, LBMReal omega, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3, 
+                                              LBMReal& kxy, LBMReal& kyz, LBMReal& kxz, LBMReal& kxxMyy, LBMReal& kxxMzz)
+{
+   using namespace D3Q27System;
+
+   LBMReal fd[ENDF+1];
+   LBMReal feq[ENDF+1];
+
+   calcMacrosFct(f,rho,vx1,vx2,vx3);
+   calcFeqFct(feq,rho,vx1,vx2,vx3);
+
+   fd[E]    = f[E] - feq[E];
+   fd[W]    = f[W] - feq[W];
+   fd[N]    = f[N] - feq[N];
+   fd[S]    = f[S] - feq[S];
+   fd[T]    = f[T] - feq[T];
+   fd[B]    = f[B] - feq[B];
+   fd[NE]   = f[NE] - feq[NE];
+   fd[SW]   = f[SW] - feq[SW];
+   fd[SE]   = f[SE] - feq[SE];
+   fd[NW]   = f[NW] - feq[NW];
+   fd[TE]   = f[TE] - feq[TE];
+   fd[BW]   = f[BW] - feq[BW];
+   fd[BE]   = f[BE] - feq[BE];
+   fd[TW]   = f[TW] - feq[TW];
+   fd[TN]   = f[TN] - feq[TN];
+   fd[BS]   = f[BS] - feq[BS];
+   fd[BN]   = f[BN] - feq[BN];
+   fd[TS]   = f[TS] - feq[TS];
+   fd[TNE]  = f[TNE] - feq[TNE];
+   fd[TNW]  = f[TNW] - feq[TNW];
+   fd[TSE]  = f[TSE] - feq[TSE];
+   fd[TSW]  = f[TSW] - feq[TSW];
+   fd[BNE]  = f[BNE] - feq[BNE];
+   fd[BNW]  = f[BNW] - feq[BNW];
+   fd[BSE]  = f[BSE] - feq[BSE];
+   fd[BSW]  = f[BSW] - feq[BSW];
+   fd[ZERO] = f[ZERO] - feq[ZERO];
+
+   kxy    = -3.*omega*(fd[SW]+fd[TSW]+fd[BSW]-fd[NW]-fd[TNW]-fd[BNW]-fd[SE]-fd[TSE]-fd[BSE]+fd[NE]+fd[TNE]+fd[BNE]);
+   kyz    = -3.*omega*(fd[BS]+fd[BSW]+fd[BSE]-fd[TS]-fd[TSW]-fd[TSE]-fd[BN]-fd[BNW]-fd[BNE]+fd[TN]+fd[TNW]+fd[TNE]);
+   kxz    = -3.*omega*(fd[BW]+fd[BNW]+fd[BSW]-fd[TW]-fd[TNW]-fd[TSW]-fd[BE]-fd[BNE]-fd[BSE]+fd[TE]+fd[TNE]+fd[TSE]);
+   kxxMyy = -3./2.*omega*(fd[BW]+fd[W]+fd[TW]-fd[BS]-fd[S]-fd[TS]-fd[BN]-fd[N]-fd[TN]+fd[BE]+fd[E]+fd[TE]);
+   kxxMzz = -3./2.*omega*(fd[SW]+fd[W]+fd[NW]-fd[BS]-fd[TS]-fd[B]-fd[T]-fd[BN]-fd[TN]+fd[SE]+fd[E]+fd[NE]);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27CompactInterpolationProcessor::calcInterpolatedCoefficiets(const D3Q27ICell& icell, LBMReal omega)
+{
+   LBMReal epsylon = 1.0;
+   
+   LBMReal        vx1_SWT,vx2_SWT,vx3_SWT;
+   LBMReal        vx1_NWT,vx2_NWT,vx3_NWT;
+   LBMReal        vx1_NET,vx2_NET,vx3_NET;
+   LBMReal        vx1_SET,vx2_SET,vx3_SET;
+   LBMReal        vx1_SWB,vx2_SWB,vx3_SWB;
+   LBMReal        vx1_NWB,vx2_NWB,vx3_NWB;
+   LBMReal        vx1_NEB,vx2_NEB,vx3_NEB;
+   LBMReal        vx1_SEB,vx2_SEB,vx3_SEB;
+
+   LBMReal        kxyFromfcNEQ_SWT, kyzFromfcNEQ_SWT, kxzFromfcNEQ_SWT, kxxMyyFromfcNEQ_SWT, kxxMzzFromfcNEQ_SWT;
+   LBMReal        kxyFromfcNEQ_NWT, kyzFromfcNEQ_NWT, kxzFromfcNEQ_NWT, kxxMyyFromfcNEQ_NWT, kxxMzzFromfcNEQ_NWT;
+   LBMReal        kxyFromfcNEQ_NET, kyzFromfcNEQ_NET, kxzFromfcNEQ_NET, kxxMyyFromfcNEQ_NET, kxxMzzFromfcNEQ_NET;
+   LBMReal        kxyFromfcNEQ_SET, kyzFromfcNEQ_SET, kxzFromfcNEQ_SET, kxxMyyFromfcNEQ_SET, kxxMzzFromfcNEQ_SET;
+   LBMReal        kxyFromfcNEQ_SWB, kyzFromfcNEQ_SWB, kxzFromfcNEQ_SWB, kxxMyyFromfcNEQ_SWB, kxxMzzFromfcNEQ_SWB;
+   LBMReal        kxyFromfcNEQ_NWB, kyzFromfcNEQ_NWB, kxzFromfcNEQ_NWB, kxxMyyFromfcNEQ_NWB, kxxMzzFromfcNEQ_NWB;
+   LBMReal        kxyFromfcNEQ_NEB, kyzFromfcNEQ_NEB, kxzFromfcNEQ_NEB, kxxMyyFromfcNEQ_NEB, kxxMzzFromfcNEQ_NEB;
+   LBMReal        kxyFromfcNEQ_SEB, kyzFromfcNEQ_SEB, kxzFromfcNEQ_SEB, kxxMyyFromfcNEQ_SEB, kxxMzzFromfcNEQ_SEB;
+   
+   calcMoments(icell.TSW,omega,drho_SWT,vx1_SWT,vx2_SWT,vx3_SWT, kxyFromfcNEQ_SWT, kyzFromfcNEQ_SWT, kxzFromfcNEQ_SWT, kxxMyyFromfcNEQ_SWT, kxxMzzFromfcNEQ_SWT);
+   calcMoments(icell.TNW,omega,drho_NWT,vx1_NWT,vx2_NWT,vx3_NWT, kxyFromfcNEQ_NWT, kyzFromfcNEQ_NWT, kxzFromfcNEQ_NWT, kxxMyyFromfcNEQ_NWT, kxxMzzFromfcNEQ_NWT);
+   calcMoments(icell.TNE,omega,drho_NET,vx1_NET,vx2_NET,vx3_NET, kxyFromfcNEQ_NET, kyzFromfcNEQ_NET, kxzFromfcNEQ_NET, kxxMyyFromfcNEQ_NET, kxxMzzFromfcNEQ_NET);
+   calcMoments(icell.TSE,omega,drho_SET,vx1_SET,vx2_SET,vx3_SET, kxyFromfcNEQ_SET, kyzFromfcNEQ_SET, kxzFromfcNEQ_SET, kxxMyyFromfcNEQ_SET, kxxMzzFromfcNEQ_SET);
+   calcMoments(icell.BSW,omega,drho_SWB,vx1_SWB,vx2_SWB,vx3_SWB, kxyFromfcNEQ_SWB, kyzFromfcNEQ_SWB, kxzFromfcNEQ_SWB, kxxMyyFromfcNEQ_SWB, kxxMzzFromfcNEQ_SWB);
+   calcMoments(icell.BNW,omega,drho_NWB,vx1_NWB,vx2_NWB,vx3_NWB, kxyFromfcNEQ_NWB, kyzFromfcNEQ_NWB, kxzFromfcNEQ_NWB, kxxMyyFromfcNEQ_NWB, kxxMzzFromfcNEQ_NWB);
+   calcMoments(icell.BNE,omega,drho_NEB,vx1_NEB,vx2_NEB,vx3_NEB, kxyFromfcNEQ_NEB, kyzFromfcNEQ_NEB, kxzFromfcNEQ_NEB, kxxMyyFromfcNEQ_NEB, kxxMzzFromfcNEQ_NEB);
+   calcMoments(icell.BSE,omega,drho_SEB,vx1_SEB,vx2_SEB,vx3_SEB, kxyFromfcNEQ_SEB, kyzFromfcNEQ_SEB, kxzFromfcNEQ_SEB, kxxMyyFromfcNEQ_SEB, kxxMzzFromfcNEQ_SEB);
+
+   a0 = 8.*vx1_SWB + 8.*vx1_NWT + 8.*vx1_SET + 8.*vx1_NEB + 2.*vx2_SWB - 2.*vx2_NWT - 2.*vx2_SET + 2.*vx2_NEB + 2.*vx3_SWB - 2.*vx3_NWT + 2.*vx3_SET - 2.*vx3_NEB + kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_NWT - kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_NEB + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_NWT - kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_NEB + 2.*kxyFromfcNEQ_SWB - 2.*kxyFromfcNEQ_NWT + 2.*kxyFromfcNEQ_SET - 2.*kxyFromfcNEQ_NEB + 2.*kxzFromfcNEQ_SWB - 2.*kxzFromfcNEQ_NWT - 2.*kxzFromfcNEQ_SET + 2.*kxzFromfcNEQ_NEB + kyzFromfcNEQ_SWB + kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB;
+   ax = (-4.*vx1_SWB - 4.*vx1_NWT + 4.*vx1_SET + 4.*vx1_NEB - kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET - kxyFromfcNEQ_NEB - kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT - kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB + kyzFromfcNEQ_SWB + kyzFromfcNEQ_NWT - kyzFromfcNEQ_SET - kyzFromfcNEQ_NEB)/epsylon;
+   ay = (-2.*vx1_SWB + 2.*vx1_NWT - 2.*vx1_SET + 2.*vx1_NEB + 2.*vx2_SWB + 2.*vx2_NWT - 2.*vx2_SET - 2.*vx2_NEB - kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_NWT + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_NEB + kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET + kxyFromfcNEQ_NEB)/epsylon;
+   az = (-2.*vx1_SWB + 2.*vx1_NWT + 2.*vx1_SET - 2.*vx1_NEB + 2.*vx3_SWB + 2.*vx3_NWT - 2.*vx3_SET - 2.*vx3_NEB - kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_NWT - kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_NEB + kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT + kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB)/epsylon;
+   axx= (2.*vx2_SWB - 2.*vx2_NWT - 2.*vx2_SET + 2.*vx2_NEB + 2.*vx3_SWB - 2.*vx3_NWT + 2.*vx3_SET - 2.*vx3_NEB - kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_NWT + kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_NEB - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_NWT + kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_NEB + kyzFromfcNEQ_SWB + kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   ayy= (-2.*vx2_SWB + 2.*vx2_NWT + 2.*vx2_SET - 2.*vx2_NEB - 2.*vx3_SWB + 2.*vx3_NWT - 2.*vx3_SET + 2.*vx3_NEB - kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_NWT + kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_NEB + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_NWT - kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_NEB - 2.*kxyFromfcNEQ_SWB + 2.*kxyFromfcNEQ_NWT - 2.*kxyFromfcNEQ_SET + 2.*kxyFromfcNEQ_NEB - kyzFromfcNEQ_SWB - kyzFromfcNEQ_NWT - kyzFromfcNEQ_SET - kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   azz= (-2.*vx2_SWB + 2.*vx2_NWT + 2.*vx2_SET - 2.*vx2_NEB - 2.*vx3_SWB + 2.*vx3_NWT - 2.*vx3_SET + 2.*vx3_NEB + kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_NWT - kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_NEB - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_NWT + kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_NEB - 2.*kxzFromfcNEQ_SWB + 2.*kxzFromfcNEQ_NWT + 2.*kxzFromfcNEQ_SET - 2.*kxzFromfcNEQ_NEB - kyzFromfcNEQ_SWB - kyzFromfcNEQ_NWT - kyzFromfcNEQ_SET - kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   axy= (2.*vx1_SWB - 2.*vx1_NWT - 2.*vx1_SET + 2.*vx1_NEB + 2.*vx3_SWB + 2.*vx3_NWT - 2.*vx3_SET - 2.*vx3_NEB - kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_NWT - kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_NEB + kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT + kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB)/(epsylon*epsylon);
+   axz= (2.*vx1_SWB - 2.*vx1_NWT + 2.*vx1_SET - 2.*vx1_NEB + 2.*vx2_SWB + 2.*vx2_NWT - 2.*vx2_SET - 2.*vx2_NEB - kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_NWT + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_NEB + kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET + kxyFromfcNEQ_NEB)/(epsylon*epsylon);
+   ayz= (-kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET - kxyFromfcNEQ_NEB - kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT - kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB + kyzFromfcNEQ_SWB + kyzFromfcNEQ_NWT - kyzFromfcNEQ_SET - kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   b0 = 2.*vx1_SWB - 2.*vx1_NWT - 2.*vx1_SET + 2.*vx1_NEB + 8.*vx2_SWB + 8.*vx2_NWT + 8.*vx2_SET + 8.*vx2_NEB + 2.*vx3_SWB + 2.*vx3_NWT - 2.*vx3_SET - 2.*vx3_NEB - 2.*kxxMyyFromfcNEQ_SWB + 2.*kxxMyyFromfcNEQ_NWT - 2.*kxxMyyFromfcNEQ_SET + 2.*kxxMyyFromfcNEQ_NEB + kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_NWT + kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_NEB + 2.*kxyFromfcNEQ_SWB + 2.*kxyFromfcNEQ_NWT - 2.*kxyFromfcNEQ_SET - 2.*kxyFromfcNEQ_NEB + kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT + kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB + 2.*kyzFromfcNEQ_SWB - 2.*kyzFromfcNEQ_NWT - 2.*kyzFromfcNEQ_SET + 2.*kyzFromfcNEQ_NEB;
+   bx = (2.*vx1_SWB - 2.*vx1_NWT + 2.*vx1_SET - 2.*vx1_NEB - 2.*vx2_SWB - 2.*vx2_NWT + 2.*vx2_SET + 2.*vx2_NEB + kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_NWT - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_NEB + kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET + kxyFromfcNEQ_NEB)/epsylon;
+   by = (-4.*vx2_SWB + 4.*vx2_NWT - 4.*vx2_SET + 4.*vx2_NEB - kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET - kxyFromfcNEQ_NEB + kxzFromfcNEQ_SWB - kxzFromfcNEQ_NWT + kxzFromfcNEQ_SET - kxzFromfcNEQ_NEB - kyzFromfcNEQ_SWB - kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/epsylon;
+   bz = (-2.*vx2_SWB + 2.*vx2_NWT + 2.*vx2_SET - 2.*vx2_NEB + 2.*vx3_SWB - 2.*vx3_NWT + 2.*vx3_SET - 2.*vx3_NEB + kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_NWT - kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_NEB - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_NWT + kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_NEB + kyzFromfcNEQ_SWB + kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/epsylon;
+   bxx= (-2.*vx1_SWB + 2.*vx1_NWT + 2.*vx1_SET - 2.*vx1_NEB - 2.*vx3_SWB - 2.*vx3_NWT + 2.*vx3_SET + 2.*vx3_NEB + kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_NWT + kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_NEB - 2.*kxyFromfcNEQ_SWB - 2.*kxyFromfcNEQ_NWT + 2.*kxyFromfcNEQ_SET + 2.*kxyFromfcNEQ_NEB - kxzFromfcNEQ_SWB - kxzFromfcNEQ_NWT - kxzFromfcNEQ_SET - kxzFromfcNEQ_NEB)/(epsylon*epsylon);
+   byy= (2.*vx1_SWB - 2.*vx1_NWT - 2.*vx1_SET + 2.*vx1_NEB + 2.*vx3_SWB + 2.*vx3_NWT - 2.*vx3_SET - 2.*vx3_NEB + 2.*kxxMyyFromfcNEQ_SWB - 2.*kxxMyyFromfcNEQ_NWT + 2.*kxxMyyFromfcNEQ_SET - 2.*kxxMyyFromfcNEQ_NEB - kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_NWT - kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_NEB + kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT + kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB)/(epsylon*epsylon);
+   bzz= (-2.*vx1_SWB + 2.*vx1_NWT + 2.*vx1_SET - 2.*vx1_NEB - 2.*vx3_SWB - 2.*vx3_NWT + 2.*vx3_SET + 2.*vx3_NEB - kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_NWT - kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_NEB - kxzFromfcNEQ_SWB - kxzFromfcNEQ_NWT - kxzFromfcNEQ_SET - kxzFromfcNEQ_NEB - 2.*kyzFromfcNEQ_SWB + 2.*kyzFromfcNEQ_NWT + 2.*kyzFromfcNEQ_SET - 2.*kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   bxy= (2.*vx2_SWB - 2.*vx2_NWT - 2.*vx2_SET + 2.*vx2_NEB + 2.*vx3_SWB - 2.*vx3_NWT + 2.*vx3_SET - 2.*vx3_NEB + kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_NWT - kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_NEB - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_NWT + kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_NEB + kyzFromfcNEQ_SWB + kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   bxz= (-kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET - kxyFromfcNEQ_NEB + kxzFromfcNEQ_SWB - kxzFromfcNEQ_NWT + kxzFromfcNEQ_SET - kxzFromfcNEQ_NEB - kyzFromfcNEQ_SWB - kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   byz= (2.*vx1_SWB - 2.*vx1_NWT + 2.*vx1_SET - 2.*vx1_NEB + 2.*vx2_SWB + 2.*vx2_NWT - 2.*vx2_SET - 2.*vx2_NEB + kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_NWT - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_NEB + kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET + kxyFromfcNEQ_NEB)/(epsylon*epsylon);
+   c0 = 2.*vx1_SWB - 2.*vx1_NWT + 2.*vx1_SET - 2.*vx1_NEB + 2.*vx2_SWB + 2.*vx2_NWT - 2.*vx2_SET - 2.*vx2_NEB + 8.*vx3_SWB + 8.*vx3_NWT + 8.*vx3_SET + 8.*vx3_NEB + kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_NWT - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_NEB - 2.*kxxMzzFromfcNEQ_SWB + 2.*kxxMzzFromfcNEQ_NWT + 2.*kxxMzzFromfcNEQ_SET - 2.*kxxMzzFromfcNEQ_NEB + kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET + kxyFromfcNEQ_NEB + 2.*kxzFromfcNEQ_SWB + 2.*kxzFromfcNEQ_NWT - 2.*kxzFromfcNEQ_SET - 2.*kxzFromfcNEQ_NEB + 2.*kyzFromfcNEQ_SWB - 2.*kyzFromfcNEQ_NWT + 2.*kyzFromfcNEQ_SET - 2.*kyzFromfcNEQ_NEB;
+   cx = (2.*vx1_SWB - 2.*vx1_NWT - 2.*vx1_SET + 2.*vx1_NEB - 2.*vx3_SWB - 2.*vx3_NWT + 2.*vx3_SET + 2.*vx3_NEB + kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_NWT + kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_NEB + kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT + kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB)/epsylon;
+   cy = (2.*vx2_SWB - 2.*vx2_NWT - 2.*vx2_SET + 2.*vx2_NEB - 2.*vx3_SWB + 2.*vx3_NWT - 2.*vx3_SET + 2.*vx3_NEB - kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_NWT + kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_NEB + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_NWT - kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_NEB + kyzFromfcNEQ_SWB + kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/epsylon;
+   cz = (-4.*vx3_SWB + 4.*vx3_NWT + 4.*vx3_SET - 4.*vx3_NEB + kxyFromfcNEQ_SWB - kxyFromfcNEQ_NWT - kxyFromfcNEQ_SET + kxyFromfcNEQ_NEB - kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT - kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB - kyzFromfcNEQ_SWB - kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/epsylon;
+   cxx= (-2.*vx1_SWB + 2.*vx1_NWT - 2.*vx1_SET + 2.*vx1_NEB - 2.*vx2_SWB - 2.*vx2_NWT + 2.*vx2_SET + 2.*vx2_NEB + kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_NWT - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_NEB - kxyFromfcNEQ_SWB - kxyFromfcNEQ_NWT - kxyFromfcNEQ_SET - kxyFromfcNEQ_NEB - 2.*kxzFromfcNEQ_SWB - 2.*kxzFromfcNEQ_NWT + 2.*kxzFromfcNEQ_SET + 2.*kxzFromfcNEQ_NEB)/(epsylon*epsylon);
+   cyy= (-2.*vx1_SWB + 2.*vx1_NWT - 2.*vx1_SET + 2.*vx1_NEB - 2.*vx2_SWB - 2.*vx2_NWT + 2.*vx2_SET + 2.*vx2_NEB - kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_NWT + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_NEB - kxyFromfcNEQ_SWB - kxyFromfcNEQ_NWT - kxyFromfcNEQ_SET - kxyFromfcNEQ_NEB - 2.*kyzFromfcNEQ_SWB + 2.*kyzFromfcNEQ_NWT - 2.*kyzFromfcNEQ_SET + 2.*kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   czz= (2.*vx1_SWB - 2.*vx1_NWT + 2.*vx1_SET - 2.*vx1_NEB + 2.*vx2_SWB + 2.*vx2_NWT - 2.*vx2_SET - 2.*vx2_NEB - kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_NWT + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_NEB + 2.*kxxMzzFromfcNEQ_SWB - 2.*kxxMzzFromfcNEQ_NWT - 2.*kxxMzzFromfcNEQ_SET + 2.*kxxMzzFromfcNEQ_NEB + kxyFromfcNEQ_SWB + kxyFromfcNEQ_NWT + kxyFromfcNEQ_SET + kxyFromfcNEQ_NEB)/(epsylon*epsylon);
+   cxy= (kxyFromfcNEQ_SWB - kxyFromfcNEQ_NWT - kxyFromfcNEQ_SET + kxyFromfcNEQ_NEB - kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT - kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB - kyzFromfcNEQ_SWB - kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   cxz= (2.*vx2_SWB - 2.*vx2_NWT - 2.*vx2_SET + 2.*vx2_NEB + 2.*vx3_SWB - 2.*vx3_NWT + 2.*vx3_SET - 2.*vx3_NEB - kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_NWT + kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_NEB + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_NWT - kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_NEB + kyzFromfcNEQ_SWB + kyzFromfcNEQ_NWT + kyzFromfcNEQ_SET + kyzFromfcNEQ_NEB)/(epsylon*epsylon);
+   cyz= (2.*vx1_SWB - 2.*vx1_NWT - 2.*vx1_SET + 2.*vx1_NEB + 2.*vx3_SWB + 2.*vx3_NWT - 2.*vx3_SET - 2.*vx3_NEB + kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_NWT + kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_NEB + kxzFromfcNEQ_SWB + kxzFromfcNEQ_NWT + kxzFromfcNEQ_SET + kxzFromfcNEQ_NEB)/(epsylon*epsylon);
+   //////////////////////////////////////////////////////////////////////////
+   //another 4 points
+   a0 += 8.*vx1_SWT + 8.*vx1_NWB + 8.*vx1_SEB + 8.*vx1_NET + 2.*vx2_SWT - 2.*vx2_NWB - 2.*vx2_SEB + 2.*vx2_NET - 2.*vx3_SWT + 2.*vx3_NWB - 2.*vx3_SEB + 2.*vx3_NET + kxxMyyFromfcNEQ_SWT + kxxMyyFromfcNEQ_NWB - 1.*kxxMyyFromfcNEQ_SEB - 1.*kxxMyyFromfcNEQ_NET + kxxMzzFromfcNEQ_SWT + kxxMzzFromfcNEQ_NWB - 1.*kxxMzzFromfcNEQ_SEB - 1.*kxxMzzFromfcNEQ_NET + 2.*kxyFromfcNEQ_SWT - 2.*kxyFromfcNEQ_NWB + 2.*kxyFromfcNEQ_SEB - 2.*kxyFromfcNEQ_NET - 2.*kxzFromfcNEQ_SWT + 2.*kxzFromfcNEQ_NWB + 2.*kxzFromfcNEQ_SEB - 2.*kxzFromfcNEQ_NET - 1.*kyzFromfcNEQ_SWT - 1.*kyzFromfcNEQ_NWB - 1.*kyzFromfcNEQ_SEB - 1.*kyzFromfcNEQ_NET;
+   ax += (-4.*vx1_SWT - 4.*vx1_NWB + 4.*vx1_SEB + 4.*vx1_NET - 1.*kxyFromfcNEQ_SWT + kxyFromfcNEQ_NWB + kxyFromfcNEQ_SEB - 1.*kxyFromfcNEQ_NET + kxzFromfcNEQ_SWT - 1.*kxzFromfcNEQ_NWB + kxzFromfcNEQ_SEB - 1.*kxzFromfcNEQ_NET - 1.*kyzFromfcNEQ_SWT - 1.*kyzFromfcNEQ_NWB + kyzFromfcNEQ_SEB + kyzFromfcNEQ_NET)/epsylon;
+   ay += (-2.*vx1_SWT + 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET + 2.*vx2_SWT + 2.*vx2_NWB - 2.*vx2_SEB - 2.*vx2_NET - 1.*kxxMyyFromfcNEQ_SWT + kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_SEB - 1.*kxxMyyFromfcNEQ_NET + kxyFromfcNEQ_SWT + kxyFromfcNEQ_NWB + kxyFromfcNEQ_SEB + kxyFromfcNEQ_NET)/epsylon;
+   az += (2.*vx1_SWT - 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET + 2.*vx3_SWT + 2.*vx3_NWB - 2.*vx3_SEB - 2.*vx3_NET + kxxMzzFromfcNEQ_SWT - 1.*kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_SEB - 1.*kxxMzzFromfcNEQ_NET + kxzFromfcNEQ_SWT + kxzFromfcNEQ_NWB + kxzFromfcNEQ_SEB + kxzFromfcNEQ_NET)/epsylon;
+   axx += (2.*vx2_SWT - 2.*vx2_NWB - 2.*vx2_SEB + 2.*vx2_NET - 2.*vx3_SWT + 2.*vx3_NWB - 2.*vx3_SEB + 2.*vx3_NET - 1.*kxxMyyFromfcNEQ_SWT - 1.*kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_NET - 1.*kxxMzzFromfcNEQ_SWT - 1.*kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_NET - 1.*kyzFromfcNEQ_SWT - 1.*kyzFromfcNEQ_NWB - 1.*kyzFromfcNEQ_SEB - 1.*kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   ayy += (-2.*vx2_SWT + 2.*vx2_NWB + 2.*vx2_SEB - 2.*vx2_NET + 2.*vx3_SWT - 2.*vx3_NWB + 2.*vx3_SEB - 2.*vx3_NET - 1.*kxxMyyFromfcNEQ_SWT - 1.*kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_NET + kxxMzzFromfcNEQ_SWT + kxxMzzFromfcNEQ_NWB - 1.*kxxMzzFromfcNEQ_SEB - 1.*kxxMzzFromfcNEQ_NET - 2.*kxyFromfcNEQ_SWT + 2.*kxyFromfcNEQ_NWB - 2.*kxyFromfcNEQ_SEB + 2.*kxyFromfcNEQ_NET + kyzFromfcNEQ_SWT + kyzFromfcNEQ_NWB + kyzFromfcNEQ_SEB + kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   azz += (-2.*vx2_SWT + 2.*vx2_NWB + 2.*vx2_SEB - 2.*vx2_NET + 2.*vx3_SWT - 2.*vx3_NWB + 2.*vx3_SEB - 2.*vx3_NET + kxxMyyFromfcNEQ_SWT + kxxMyyFromfcNEQ_NWB - 1.*kxxMyyFromfcNEQ_SEB - 1.*kxxMyyFromfcNEQ_NET - 1.*kxxMzzFromfcNEQ_SWT - 1.*kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_NET + 2.*kxzFromfcNEQ_SWT - 2.*kxzFromfcNEQ_NWB - 2.*kxzFromfcNEQ_SEB + 2.*kxzFromfcNEQ_NET + kyzFromfcNEQ_SWT + kyzFromfcNEQ_NWB + kyzFromfcNEQ_SEB + kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   axy += (2.*vx1_SWT - 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET - 2.*vx3_SWT - 2.*vx3_NWB + 2.*vx3_SEB + 2.*vx3_NET - 1.*kxxMzzFromfcNEQ_SWT + kxxMzzFromfcNEQ_NWB - 1.*kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_NET - 1.*kxzFromfcNEQ_SWT - 1.*kxzFromfcNEQ_NWB - 1.*kxzFromfcNEQ_SEB - 1.*kxzFromfcNEQ_NET)/(epsylon*epsylon);
+   axz += (-2.*vx1_SWT + 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET - 2.*vx2_SWT - 2.*vx2_NWB + 2.*vx2_SEB + 2.*vx2_NET + kxxMyyFromfcNEQ_SWT - 1.*kxxMyyFromfcNEQ_NWB - 1.*kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_NET - 1.*kxyFromfcNEQ_SWT - 1.*kxyFromfcNEQ_NWB - 1.*kxyFromfcNEQ_SEB - 1.*kxyFromfcNEQ_NET)/(epsylon*epsylon);
+   ayz += (kxyFromfcNEQ_SWT - 1.*kxyFromfcNEQ_NWB - 1.*kxyFromfcNEQ_SEB + kxyFromfcNEQ_NET - 1.*kxzFromfcNEQ_SWT + kxzFromfcNEQ_NWB - 1.*kxzFromfcNEQ_SEB + kxzFromfcNEQ_NET + kyzFromfcNEQ_SWT + kyzFromfcNEQ_NWB - 1.*kyzFromfcNEQ_SEB - 1.*kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   b0 += 2.*vx1_SWT - 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET + 8.*vx2_SWT + 8.*vx2_NWB + 8.*vx2_SEB + 8.*vx2_NET - 2.*vx3_SWT - 2.*vx3_NWB + 2.*vx3_SEB + 2.*vx3_NET - 2.*kxxMyyFromfcNEQ_SWT + 2.*kxxMyyFromfcNEQ_NWB - 2.*kxxMyyFromfcNEQ_SEB + 2.*kxxMyyFromfcNEQ_NET + kxxMzzFromfcNEQ_SWT - 1.*kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_SEB - 1.*kxxMzzFromfcNEQ_NET + 2.*kxyFromfcNEQ_SWT + 2.*kxyFromfcNEQ_NWB - 2.*kxyFromfcNEQ_SEB - 2.*kxyFromfcNEQ_NET - 1.*kxzFromfcNEQ_SWT - 1.*kxzFromfcNEQ_NWB - 1.*kxzFromfcNEQ_SEB - 1.*kxzFromfcNEQ_NET - 2.*kyzFromfcNEQ_SWT + 2.*kyzFromfcNEQ_NWB + 2.*kyzFromfcNEQ_SEB - 2.*kyzFromfcNEQ_NET;
+   bx += (2.*vx1_SWT - 2.*vx1_NWB + 2.*vx1_SEB - 2.*vx1_NET - 2.*vx2_SWT - 2.*vx2_NWB + 2.*vx2_SEB + 2.*vx2_NET + kxxMyyFromfcNEQ_SWT - 1.*kxxMyyFromfcNEQ_NWB - 1.*kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_NET + kxyFromfcNEQ_SWT + kxyFromfcNEQ_NWB + kxyFromfcNEQ_SEB + kxyFromfcNEQ_NET)/epsylon;
+   by += (-4.*vx2_SWT + 4.*vx2_NWB - 4.*vx2_SEB + 4.*vx2_NET - 1.*kxyFromfcNEQ_SWT + kxyFromfcNEQ_NWB + kxyFromfcNEQ_SEB - 1.*kxyFromfcNEQ_NET - 1.*kxzFromfcNEQ_SWT + kxzFromfcNEQ_NWB - 1.*kxzFromfcNEQ_SEB + kxzFromfcNEQ_NET + kyzFromfcNEQ_SWT + kyzFromfcNEQ_NWB - 1.*kyzFromfcNEQ_SEB - 1.*kyzFromfcNEQ_NET)/epsylon;
+   bz += (2.*vx2_SWT - 2.*vx2_NWB - 2.*vx2_SEB + 2.*vx2_NET + 2.*vx3_SWT - 2.*vx3_NWB + 2.*vx3_SEB - 2.*vx3_NET - 1.*kxxMyyFromfcNEQ_SWT - 1.*kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_NET + kxxMzzFromfcNEQ_SWT + kxxMzzFromfcNEQ_NWB - 1.*kxxMzzFromfcNEQ_SEB - 1.*kxxMzzFromfcNEQ_NET + kyzFromfcNEQ_SWT + kyzFromfcNEQ_NWB + kyzFromfcNEQ_SEB + kyzFromfcNEQ_NET)/epsylon;
+   bxx += (-2.*vx1_SWT + 2.*vx1_NWB + 2.*vx1_SEB - 2.*vx1_NET + 2.*vx3_SWT + 2.*vx3_NWB - 2.*vx3_SEB - 2.*vx3_NET + kxxMzzFromfcNEQ_SWT - 1.*kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_SEB - 1.*kxxMzzFromfcNEQ_NET - 2.*kxyFromfcNEQ_SWT - 2.*kxyFromfcNEQ_NWB + 2.*kxyFromfcNEQ_SEB + 2.*kxyFromfcNEQ_NET + kxzFromfcNEQ_SWT + kxzFromfcNEQ_NWB + kxzFromfcNEQ_SEB + kxzFromfcNEQ_NET)/(epsylon*epsylon);
+   byy += (2.*vx1_SWT - 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET - 2.*vx3_SWT - 2.*vx3_NWB + 2.*vx3_SEB + 2.*vx3_NET + 2.*kxxMyyFromfcNEQ_SWT - 2.*kxxMyyFromfcNEQ_NWB + 2.*kxxMyyFromfcNEQ_SEB - 2.*kxxMyyFromfcNEQ_NET - 1.*kxxMzzFromfcNEQ_SWT + kxxMzzFromfcNEQ_NWB - 1.*kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_NET - 1.*kxzFromfcNEQ_SWT - 1.*kxzFromfcNEQ_NWB - 1.*kxzFromfcNEQ_SEB - 1.*kxzFromfcNEQ_NET)/(epsylon*epsylon);
+   bzz += (-2.*vx1_SWT + 2.*vx1_NWB + 2.*vx1_SEB - 2.*vx1_NET + 2.*vx3_SWT + 2.*vx3_NWB - 2.*vx3_SEB - 2.*vx3_NET - 1.*kxxMzzFromfcNEQ_SWT + kxxMzzFromfcNEQ_NWB - 1.*kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_NET + kxzFromfcNEQ_SWT + kxzFromfcNEQ_NWB + kxzFromfcNEQ_SEB + kxzFromfcNEQ_NET + 2.*kyzFromfcNEQ_SWT - 2.*kyzFromfcNEQ_NWB - 2.*kyzFromfcNEQ_SEB + 2.*kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   bxy += (2.*vx2_SWT - 2.*vx2_NWB - 2.*vx2_SEB + 2.*vx2_NET - 2.*vx3_SWT + 2.*vx3_NWB - 2.*vx3_SEB + 2.*vx3_NET + kxxMyyFromfcNEQ_SWT + kxxMyyFromfcNEQ_NWB - 1.*kxxMyyFromfcNEQ_SEB - 1.*kxxMyyFromfcNEQ_NET - 1.*kxxMzzFromfcNEQ_SWT - 1.*kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_NET - 1.*kyzFromfcNEQ_SWT - 1.*kyzFromfcNEQ_NWB - 1.*kyzFromfcNEQ_SEB - 1.*kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   bxz += (kxyFromfcNEQ_SWT - 1.*kxyFromfcNEQ_NWB - 1.*kxyFromfcNEQ_SEB + kxyFromfcNEQ_NET + kxzFromfcNEQ_SWT - 1.*kxzFromfcNEQ_NWB + kxzFromfcNEQ_SEB - 1.*kxzFromfcNEQ_NET - 1.*kyzFromfcNEQ_SWT - 1.*kyzFromfcNEQ_NWB + kyzFromfcNEQ_SEB + kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   byz += (-2.*vx1_SWT + 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET - 2.*vx2_SWT - 2.*vx2_NWB + 2.*vx2_SEB + 2.*vx2_NET - 1.*kxxMyyFromfcNEQ_SWT + kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_SEB - 1.*kxxMyyFromfcNEQ_NET - 1.*kxyFromfcNEQ_SWT - 1.*kxyFromfcNEQ_NWB - 1.*kxyFromfcNEQ_SEB - 1.*kxyFromfcNEQ_NET)/(epsylon*epsylon);
+   c0 += -2.*vx1_SWT + 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET - 2.*vx2_SWT - 2.*vx2_NWB + 2.*vx2_SEB + 2.*vx2_NET + 8.*vx3_SWT + 8.*vx3_NWB + 8.*vx3_SEB + 8.*vx3_NET - 1.*kxxMyyFromfcNEQ_SWT + kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_SEB - 1.*kxxMyyFromfcNEQ_NET + 2.*kxxMzzFromfcNEQ_SWT - 2.*kxxMzzFromfcNEQ_NWB - 2.*kxxMzzFromfcNEQ_SEB + 2.*kxxMzzFromfcNEQ_NET - 1.*kxyFromfcNEQ_SWT - 1.*kxyFromfcNEQ_NWB - 1.*kxyFromfcNEQ_SEB - 1.*kxyFromfcNEQ_NET + 2.*kxzFromfcNEQ_SWT + 2.*kxzFromfcNEQ_NWB - 2.*kxzFromfcNEQ_SEB - 2.*kxzFromfcNEQ_NET + 2.*kyzFromfcNEQ_SWT - 2.*kyzFromfcNEQ_NWB + 2.*kyzFromfcNEQ_SEB - 2.*kyzFromfcNEQ_NET;
+   cx += (-2.*vx1_SWT + 2.*vx1_NWB + 2.*vx1_SEB - 2.*vx1_NET - 2.*vx3_SWT - 2.*vx3_NWB + 2.*vx3_SEB + 2.*vx3_NET - 1.*kxxMzzFromfcNEQ_SWT + kxxMzzFromfcNEQ_NWB - 1.*kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_NET + kxzFromfcNEQ_SWT + kxzFromfcNEQ_NWB + kxzFromfcNEQ_SEB + kxzFromfcNEQ_NET)/epsylon;
+   cy += (-2.*vx2_SWT + 2.*vx2_NWB + 2.*vx2_SEB - 2.*vx2_NET - 2.*vx3_SWT + 2.*vx3_NWB - 2.*vx3_SEB + 2.*vx3_NET + kxxMyyFromfcNEQ_SWT + kxxMyyFromfcNEQ_NWB - 1.*kxxMyyFromfcNEQ_SEB - 1.*kxxMyyFromfcNEQ_NET - 1.*kxxMzzFromfcNEQ_SWT - 1.*kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_NET + kyzFromfcNEQ_SWT + kyzFromfcNEQ_NWB + kyzFromfcNEQ_SEB + kyzFromfcNEQ_NET)/epsylon;
+   cz += (4.*vx3_SWT - 4.*vx3_NWB - 4.*vx3_SEB + 4.*vx3_NET + kxyFromfcNEQ_SWT - 1.*kxyFromfcNEQ_NWB - 1.*kxyFromfcNEQ_SEB + kxyFromfcNEQ_NET + kxzFromfcNEQ_SWT - 1.*kxzFromfcNEQ_NWB + kxzFromfcNEQ_SEB - 1.*kxzFromfcNEQ_NET + kyzFromfcNEQ_SWT + kyzFromfcNEQ_NWB - 1.*kyzFromfcNEQ_SEB - 1.*kyzFromfcNEQ_NET)/epsylon;
+   cxx += (2.*vx1_SWT - 2.*vx1_NWB + 2.*vx1_SEB - 2.*vx1_NET + 2.*vx2_SWT + 2.*vx2_NWB - 2.*vx2_SEB - 2.*vx2_NET - 1.*kxxMyyFromfcNEQ_SWT + kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_SEB - 1.*kxxMyyFromfcNEQ_NET + kxyFromfcNEQ_SWT + kxyFromfcNEQ_NWB + kxyFromfcNEQ_SEB + kxyFromfcNEQ_NET - 2.*kxzFromfcNEQ_SWT - 2.*kxzFromfcNEQ_NWB + 2.*kxzFromfcNEQ_SEB + 2.*kxzFromfcNEQ_NET)/(epsylon*epsylon);
+   cyy += (2.*vx1_SWT - 2.*vx1_NWB + 2.*vx1_SEB - 2.*vx1_NET + 2.*vx2_SWT + 2.*vx2_NWB - 2.*vx2_SEB - 2.*vx2_NET + kxxMyyFromfcNEQ_SWT - 1.*kxxMyyFromfcNEQ_NWB - 1.*kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_NET + kxyFromfcNEQ_SWT + kxyFromfcNEQ_NWB + kxyFromfcNEQ_SEB + kxyFromfcNEQ_NET - 2.*kyzFromfcNEQ_SWT + 2.*kyzFromfcNEQ_NWB - 2.*kyzFromfcNEQ_SEB + 2.*kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   czz += (-2.*vx1_SWT + 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET - 2.*vx2_SWT - 2.*vx2_NWB + 2.*vx2_SEB + 2.*vx2_NET + kxxMyyFromfcNEQ_SWT - 1.*kxxMyyFromfcNEQ_NWB - 1.*kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_NET - 2.*kxxMzzFromfcNEQ_SWT + 2.*kxxMzzFromfcNEQ_NWB + 2.*kxxMzzFromfcNEQ_SEB - 2.*kxxMzzFromfcNEQ_NET - 1.*kxyFromfcNEQ_SWT - 1.*kxyFromfcNEQ_NWB - 1.*kxyFromfcNEQ_SEB - 1.*kxyFromfcNEQ_NET)/(epsylon*epsylon);
+   cxy += (-1.*kxyFromfcNEQ_SWT + kxyFromfcNEQ_NWB + kxyFromfcNEQ_SEB - 1.*kxyFromfcNEQ_NET - 1.*kxzFromfcNEQ_SWT + kxzFromfcNEQ_NWB - 1.*kxzFromfcNEQ_SEB + kxzFromfcNEQ_NET - 1.*kyzFromfcNEQ_SWT - 1.*kyzFromfcNEQ_NWB + kyzFromfcNEQ_SEB + kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   cxz += (2.*vx2_SWT - 2.*vx2_NWB - 2.*vx2_SEB + 2.*vx2_NET - 2.*vx3_SWT + 2.*vx3_NWB - 2.*vx3_SEB + 2.*vx3_NET - 1.*kxxMyyFromfcNEQ_SWT - 1.*kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_NET + kxxMzzFromfcNEQ_SWT + kxxMzzFromfcNEQ_NWB - 1.*kxxMzzFromfcNEQ_SEB - 1.*kxxMzzFromfcNEQ_NET - 1.*kyzFromfcNEQ_SWT - 1.*kyzFromfcNEQ_NWB - 1.*kyzFromfcNEQ_SEB - 1.*kyzFromfcNEQ_NET)/(epsylon*epsylon);
+   cyz += (2.*vx1_SWT - 2.*vx1_NWB - 2.*vx1_SEB + 2.*vx1_NET - 2.*vx3_SWT - 2.*vx3_NWB + 2.*vx3_SEB + 2.*vx3_NET + kxxMzzFromfcNEQ_SWT - 1.*kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_SEB - 1.*kxxMzzFromfcNEQ_NET - 1.*kxzFromfcNEQ_SWT - 1.*kxzFromfcNEQ_NWB - 1.*kxzFromfcNEQ_SEB - 1.*kxzFromfcNEQ_NET)/(epsylon*epsylon);
+   //////////////////////////////////////////////////////////////////////////
+   //normalization
+   a0  /= 2.;
+   ax  /= 2.;
+   ay  /= 2.;
+   az  /= 2.;
+   axx /= 2.;
+   ayy /= 2.;
+   azz /= 2.;
+   axy /= 2.;
+   axz /= 2.;
+   ayz /= 2.;
+   b0  /= 2.;
+   bx  /= 2.;
+   by  /= 2.;
+   bz  /= 2.;
+   bxx /= 2.;
+   byy /= 2.;
+   bzz /= 2.;
+   bxy /= 2.;
+   bxz /= 2.;
+   byz /= 2.;
+   c0  /= 2.;
+   cx  /= 2.;
+   cy  /= 2.;
+   cz  /= 2.;
+   cxx /= 2.;
+   cyy /= 2.;
+   czz /= 2.;
+   cxy /= 2.;
+   cxz /= 2.;
+   cyz /= 2.;
+   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+   a0  /= 32.;
+   ax  /= 8.;
+   ay  /= 8.;
+   az  /= 8.;
+   axx /= 8.;
+   ayy /= 8.;
+   azz /= 8.;
+   axy /= 4.;
+   axz /= 4.;
+   ayz /= 4.;
+   b0  /= 32.;
+   bx  /= 8.;
+   by  /= 8.;
+   bz  /= 8.;
+   bxx /= 8.;
+   byy /= 8.;
+   bzz /= 8.;
+   bxy /= 4.;
+   bxz /= 4.;
+   byz /= 4.;
+   c0  /= 32.;
+   cx  /= 8.;
+   cy  /= 8.;
+   cz  /= 8.;
+   cxx /= 8.;
+   cyy /= 8.;
+   czz /= 8.;
+   cxy /= 4.;
+   cxz /= 4.;
+   cyz /= 4.;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27CompactInterpolationProcessor::calcInterpolatedNode(LBMReal* f, LBMReal omega, LBMReal x, LBMReal y, LBMReal z)
+{
+   using namespace D3Q27System;
+   
+   LBMReal eps_new = 0.5;
+   LBMReal op = 1.0;
+   const LBMReal o = omega;
+
+
+   LBMReal drho = (drho_NEB*(1. + 2.*x + 2.*y + 4.*x*y - 2.*z - 4.*x*z - 4.*y*z - 8.*x*y*z) + 
+                     drho_SET*(1. + 2.*x - 2.*y - 4.*x*y + 2.*z + 4.*x*z - 4.*y*z - 8.*x*y*z) + 
+                     drho_NWT*(1. - 2.*x + 2.*y - 4.*x*y + 2.*z - 4.*x*z + 4.*y*z - 8.*x*y*z) + 
+                     drho_SWB*(1. - 2.*x - 2.*y + 4.*x*y - 2.*z + 4.*x*z + 4.*y*z - 8.*x*y*z) + 
+                     drho_SWT*(1. - 2.*x - 2.*y + 4.*x*y + 2.*z - 4.*x*z - 4.*y*z + 8.*x*y*z) + 
+                     drho_NWB*(1. - 2.*x + 2.*y - 4.*x*y - 2.*z + 4.*x*z - 4.*y*z + 8.*x*y*z) + 
+                     drho_SEB*(1. + 2.*x - 2.*y - 4.*x*y - 2.*z - 4.*x*z + 4.*y*z + 8.*x*y*z) + 
+                     drho_NET*(1. + 2.*x + 2.*y + 4.*x*y + 2.*z + 4.*x*z + 4.*y*z + 8.*x*y*z))/8.;
+   LBMReal vx1  = a0 + ax*x + ay*y + az*z + axx*x*x + ayy*y*y + azz*z*z + axy*x*y + axz*x*z + ayz*y*z;
+   LBMReal vx2  = b0 + bx*x + by*y + bz*z + bxx*x*x + byy*y*y + bzz*z*z + bxy*x*y + bxz*x*z + byz*y*z;
+   LBMReal vx3  = c0 + cx*x + cy*y + cz*z + cxx*x*x + cyy*y*y + czz*z*z + cxy*x*y + cxz*x*z + cyz*y*z;
+
+   LBMReal feq[ENDF+1];
+   calcFeqFct(feq,drho,vx1,vx2,vx3);
+
+   f[E]    = eps_new *((-5*(ax + by + cz + 2*axx*x + bxy*x + cxz*x + axy*y + 2*byy*y + cyz*y + axz*z + byz*z + 2*czz*z))/(9.*op) - 
+            (2*(-by - cz - bxy*x - cxz*x - 2*byy*y - cyz*y - byz*z - 2*czz*z + 2*(ax + 2*axx*x + axy*y + axz*z)))/(9.*o))/2.;
+   f[W]    = eps_new *((-5*(ax + by + cz + 2*axx*x + bxy*x + cxz*x + axy*y + 2*byy*y + cyz*y + axz*z + byz*z + 2*czz*z))/(9.*op) - 
+            (2*(-by - cz - bxy*x - cxz*x - 2*byy*y - cyz*y - byz*z - 2*czz*z + 2*(ax + 2*axx*x + axy*y + axz*z)))/(9.*o))/2.;
+   f[N]    = eps_new *((-5*(ax + by + cz + 2*axx*x + bxy*x + cxz*x + axy*y + 2*byy*y + cyz*y + axz*z + byz*z + 2*czz*z))/(9.*op) - 
+            (2*(-ax - cz - 2*axx*x - cxz*x - axy*y - cyz*y - axz*z - 2*czz*z + 2*(by + bxy*x + 2*byy*y + byz*z)))/(9.*o))/2.;
+   f[S]    = eps_new *((-5*(ax + by + cz + 2*axx*x + bxy*x + cxz*x + axy*y + 2*byy*y + cyz*y + axz*z + byz*z + 2*czz*z))/(9.*op) - 
+            (2*(-ax - cz - 2*axx*x - cxz*x - axy*y - cyz*y - axz*z - 2*czz*z + 2*(by + bxy*x + 2*byy*y + byz*z)))/(9.*o))/2.;
+   f[T]    = eps_new *((-5*(ax + by + cz + 2*axx*x + bxy*x + cxz*x + axy*y + 2*byy*y + cyz*y + axz*z + byz*z + 2*czz*z))/(9.*op) - 
+            (2*(-ax - by - 2*axx*x - bxy*x - axy*y - 2*byy*y - axz*z - byz*z + 2*(cz + cxz*x + cyz*y + 2*czz*z)))/(9.*o))/2.;
+   f[B]    = eps_new *((-5*(ax + by + cz + 2*axx*x + bxy*x + cxz*x + axy*y + 2*byy*y + cyz*y + axz*z + byz*z + 2*czz*z))/(9.*op) - 
+            (2*(-ax - by - 2*axx*x - bxy*x - axy*y - 2*byy*y - axz*z - byz*z + 2*(cz + cxz*x + cyz*y + 2*czz*z)))/(9.*o))/2.;
+   f[NE]   = eps_new *(-(ay + bx + axy*x + 2*bxx*x + 2*ayy*y + bxy*y + ayz*z + bxz*z)/(12.*o));
+   f[SW]   = eps_new *(-(ay + bx + axy*x + 2*bxx*x + 2*ayy*y + bxy*y + ayz*z + bxz*z)/(12.*o));
+   f[SE]   = eps_new *(ay + bx + axy*x + 2*bxx*x + 2*ayy*y + bxy*y + ayz*z + bxz*z)/(12.*o);
+   f[NW]   = eps_new *(ay + bx + axy*x + 2*bxx*x + 2*ayy*y + bxy*y + ayz*z + bxz*z)/(12.*o);
+   f[TE]   = eps_new *(-(az + cx + axz*x + 2*cxx*x + ayz*y + cxy*y + 2*azz*z + cxz*z)/(12.*o));
+   f[BW]   = eps_new *(-(az + cx + axz*x + 2*cxx*x + ayz*y + cxy*y + 2*azz*z + cxz*z)/(12.*o));
+   f[BE]   = eps_new *(az + cx + axz*x + 2*cxx*x + ayz*y + cxy*y + 2*azz*z + cxz*z)/(12.*o);
+   f[TW]   = eps_new *(az + cx + axz*x + 2*cxx*x + ayz*y + cxy*y + 2*azz*z + cxz*z)/(12.*o);
+   f[TN]   = eps_new *(-(bz + cy + bxz*x + cxy*x + byz*y + 2*cyy*y + 2*bzz*z + cyz*z)/(12.*o));
+   f[BS]   = eps_new *(-(bz + cy + bxz*x + cxy*x + byz*y + 2*cyy*y + 2*bzz*z + cyz*z)/(12.*o));
+   f[BN]   = eps_new *(bz + cy + bxz*x + cxy*x + byz*y + 2*cyy*y + 2*bzz*z + cyz*z)/(12.*o);
+   f[TS]   = eps_new *(bz + cy + bxz*x + cxy*x + byz*y + 2*cyy*y + 2*bzz*z + cyz*z)/(12.*o);
+   f[ZERO] = eps_new *(5*(ax + by + cz + 2*axx*x + bxy*x + cxz*x + axy*y + 2*byy*y + cyz*y + axz*z + byz*z + 2*czz*z))/(3.*op) + 
+            (2*(-by - cz - bxy*x - cxz*x - 2*byy*y - cyz*y - byz*z - 2*czz*z + 2*(ax + 2*axx*x + axy*y + axz*z)))/(9.*o) + 
+            (2*(-ax - cz - 2*axx*x - cxz*x - axy*y - cyz*y - axz*z - 2*czz*z + 2*(by + bxy*x + 2*byy*y + byz*z)))/(9.*o) + 
+            (2*(-ax - by - 2*axx*x - bxy*x - axy*y - 2*byy*y - axz*z - byz*z + 2*(cz + cxz*x + cyz*y + 2*czz*z)))/(9.*o);
+   f[TNE]  = 0.0;
+   f[TNW]  = 0.0;
+   f[TSE]  = 0.0;
+   f[TSW]  = 0.0;
+   f[BNE]  = 0.0;
+   f[BNW]  = 0.0;
+   f[BSE]  = 0.0;
+   f[BSW]  = 0.0;
+
+   f[E]    += feq[E];
+   f[W]    += feq[W];
+   f[N]    += feq[N];
+   f[S]    += feq[S];
+   f[T]    += feq[T];
+   f[B]    += feq[B];
+   f[NE]   += feq[NE];
+   f[SW]   += feq[SW];
+   f[SE]   += feq[SE];
+   f[NW]   += feq[NW];
+   f[TE]   += feq[TE];
+   f[BW]   += feq[BW];
+   f[BE]   += feq[BE];
+   f[TW]   += feq[TW];
+   f[TN]   += feq[TN];
+   f[BS]   += feq[BS];
+   f[BN]   += feq[BN];
+   f[TS]   += feq[TS];
+   f[TNE]  += feq[TNE];
+   f[TNW]  += feq[TNW];
+   f[TSE]  += feq[TSE];
+   f[TSW]  += feq[TSW];
+   f[BNE]  += feq[BNE];
+   f[BNW]  += feq[BNW];
+   f[BSE]  += feq[BSE];
+   f[BSW]  += feq[BSW];
+   f[ZERO] += feq[ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/LBM/D3Q27CompactInterpolationProcessor.h b/source/VirtualFluidsCore/LBM/D3Q27CompactInterpolationProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..adaaf907876751dba1e9f7fd981d5373bce29792
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27CompactInterpolationProcessor.h
@@ -0,0 +1,59 @@
+#ifndef D3Q27CompactInterpolationProcessor_H_
+#define D3Q27CompactInterpolationProcessor_H_
+
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27System.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+//it work only for cascaded LBM
+//super compact interpolation method by Martin Geier
+//////////////////////////////////////////////////////////////////////////
+
+class D3Q27CompactInterpolationProcessor;
+typedef boost::shared_ptr<D3Q27CompactInterpolationProcessor> D3Q27CompactInterpolationProcessorPtr;
+
+class D3Q27CompactInterpolationProcessor : public D3Q27InterpolationProcessor
+{
+public:
+   D3Q27CompactInterpolationProcessor();
+   D3Q27CompactInterpolationProcessor(LBMReal omegaC, LBMReal omegaF);
+   virtual ~D3Q27CompactInterpolationProcessor();
+   D3Q27InterpolationProcessorPtr clone();
+   void setOmegas(LBMReal omegaC, LBMReal omegaF);
+   void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF);
+   void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, LBMReal xoff, LBMReal yoff, LBMReal zoff);
+   void interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC); 
+   void interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC, LBMReal xoff, LBMReal yoff, LBMReal zoff); 
+   void interpolate8to1(D3Q27ICell& icellF, LBMReal* icellC, double x1, double x2, double x3, LBMReal omega);
+protected:
+private:
+   typedef void      (*CalcMacrosFct)(const LBMReal* const& /*f[27]*/, LBMReal& /*rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   typedef LBMReal (*CalcFeqForDirFct)(const int& /*direction*/,const LBMReal& /*(d)rho*/,const LBMReal& /*vx1*/,const LBMReal& /*vx2*/,const LBMReal& /*vx3*/);
+   typedef  void     (*CalcFeqFct)(LBMReal* const& /*feq/*[27]*/,const LBMReal& /*rho*/,const LBMReal& /*vx1*/,const LBMReal& /*vx2*/,const LBMReal& /*vx3*/);
+   
+   CalcFeqForDirFct calcFeqsForDirFct;
+   CalcMacrosFct    calcMacrosFct;
+   CalcFeqFct       calcFeqFct;
+   LBMReal omegaC, omegaF;
+   LBMReal a0, ax, ay, az, axx, ayy, azz, axy, axz, ayz, b0, bx, by, bz, bxx, byy, bzz, bxy, bxz, byz, c0, cx, cy, cz, cxx, cyy, czz, cxy, cxz, cyz;
+   LBMReal drho_SWT, drho_NWT, drho_NET, drho_SET, drho_SWB, drho_NWB, drho_NEB, drho_SEB;
+
+   void init();
+   void calcMoments(const LBMReal* const f, LBMReal omega, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3, 
+                           LBMReal& kxy, LBMReal& kyz, LBMReal& kxz, LBMReal& kxxMyy, LBMReal& kxxMzz);
+   void calcInterpolatedCoefficiets(const D3Q27ICell& icell, LBMReal omega);
+   void calcInterpolatedNode(LBMReal* f, LBMReal omega, LBMReal x, LBMReal y, LBMReal z);
+};
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27CompactInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, LBMReal xoff, LBMReal yoff, LBMReal zoff)
+{
+   this->interpolateCoarseToFine(icellC, icellF);
+}
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27CompactInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC, LBMReal xoff, LBMReal yoff, LBMReal zoff)
+{
+   this->interpolateFineToCoarse(icellF, icellC);
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/D3Q27IncompressibleOffsetInterpolationProcessor.cpp b/source/VirtualFluidsCore/LBM/D3Q27IncompressibleOffsetInterpolationProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad9ce39515fd4c9f4296a12026281c68ac002c8b
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27IncompressibleOffsetInterpolationProcessor.cpp
@@ -0,0 +1,749 @@
+#include "D3Q27IncompressibleOffsetInterpolationProcessor.h"
+#include "D3Q27System.h"
+
+#include <boost/foreach.hpp>
+
+D3Q27IncompressibleOffsetInterpolationProcessor::D3Q27IncompressibleOffsetInterpolationProcessor()
+   : omegaC(0.0), omegaF(0.0)
+{
+   //forcingC = 0; //9.99685e-7;
+   //forcingF = 0; //forcingC*0.5;
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27IncompressibleOffsetInterpolationProcessor::D3Q27IncompressibleOffsetInterpolationProcessor(LBMReal omegaC, LBMReal omegaF)
+   : omegaC(omegaC), omegaF(omegaF)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27IncompressibleOffsetInterpolationProcessor::~D3Q27IncompressibleOffsetInterpolationProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27InterpolationProcessorPtr D3Q27IncompressibleOffsetInterpolationProcessor::clone()
+{
+   D3Q27InterpolationProcessorPtr iproc = D3Q27InterpolationProcessorPtr (new D3Q27IncompressibleOffsetInterpolationProcessor(this->omegaC, this->omegaF));
+   //boost::dynamic_pointer_cast<D3Q27IncompressibleOffsetInterpolationProcessor>(iproc)->forcingC = forcingC;
+   //boost::dynamic_pointer_cast<D3Q27IncompressibleOffsetInterpolationProcessor>(iproc)->forcingF = forcingF;
+   return iproc;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::setOmegas( LBMReal omegaC, LBMReal omegaF )
+{
+   this->omegaC = omegaC;
+   this->omegaF = omegaF;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::setOffsets(LBMReal xoff, LBMReal yoff, LBMReal zoff)
+{
+   this->xoff = xoff;
+   this->yoff = yoff;
+   this->zoff = zoff;     
+   this->xoff_sq = xoff * xoff;
+   this->yoff_sq = yoff * yoff;
+   this->zoff_sq = zoff * zoff;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, LBMReal xoff, LBMReal yoff, LBMReal zoff)
+{
+   setOffsets(xoff, yoff, zoff);
+   calcInterpolatedCoefficiets(icellC, omegaC, 0.5);
+   calcInterpolatedNode(icellF.BSW, omegaF, -0.25, -0.25, -0.25, calcPressBSW(), -1, -1, -1);
+   calcInterpolatedNode(icellF.BNE, omegaF,  0.25,  0.25, -0.25, calcPressBNE(),  1,  1, -1);
+   calcInterpolatedNode(icellF.TNW, omegaF, -0.25,  0.25,  0.25, calcPressTNW(), -1,  1,  1);
+   calcInterpolatedNode(icellF.TSE, omegaF,  0.25, -0.25,  0.25, calcPressTSE(),  1, -1,  1);
+   calcInterpolatedNode(icellF.BNW, omegaF, -0.25,  0.25, -0.25, calcPressBNW(), -1,  1, -1);
+   calcInterpolatedNode(icellF.BSE, omegaF,  0.25, -0.25, -0.25, calcPressBSE(),  1, -1, -1);
+   calcInterpolatedNode(icellF.TSW, omegaF, -0.25, -0.25,  0.25, calcPressTSW(), -1, -1,  1);
+   calcInterpolatedNode(icellF.TNE, omegaF,  0.25,  0.25,  0.25, calcPressTNE(),  1,  1,  1);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC, LBMReal xoff, LBMReal yoff, LBMReal zoff)
+{
+   setOffsets(xoff, yoff, zoff);
+   calcInterpolatedCoefficiets(icellF, omegaF, 2.0);
+   calcInterpolatedNodeFC(icellC, omegaC);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::calcMoments(const LBMReal* const f, LBMReal omega, LBMReal& press, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3, 
+                                                    LBMReal& kxy, LBMReal& kyz, LBMReal& kxz, LBMReal& kxxMyy, LBMReal& kxxMzz)
+{
+   using namespace D3Q27System;
+
+   //UBLOG(logINFO,"D3Q27System::BW  = " << D3Q27System::BW);
+   //UBLOG(logINFO,"BW  = " << BW);
+
+   LBMReal rho = 0.0;
+   D3Q27System::calcIncompMacroscopicValues(f,rho,vx1,vx2,vx3);
+   
+   //////////////////////////////////////////////////////////////////////////
+   //DRAFT
+   //if (omega == omegaC)
+   //{
+   //   vx1 += forcingC*0.5;
+   //} 
+   //else
+   //{
+   //   vx1 += forcingF*0.5;
+   //}
+   //////////////////////////////////////////////////////////////////////////
+
+   //press = D3Q27System::calcPress(f,rho,vx1,vx2,vx3);
+   press = rho; //interpolate rho!
+
+   kxy   = -3.*omega*((((f[TSW]+f[BNE])-(f[TNW]+f[BSE]))+((f[BSW]+f[TNE])-(f[BNW]+f[TSE])))+((f[SW]+f[NE])-(f[NW]+f[SE]))-(vx1*vx2));// might not be optimal MG 25.2.13
+   kyz   = -3.*omega*((((f[BSW]+f[TNE])-(f[TSE]+f[BNW]))+((f[BSE]+f[TNW])-(f[TSW]+f[BNE])))+((f[BS]+f[TN])-(f[TS]+f[BN]))-(vx2*vx3));
+   kxz   = -3.*omega*((((f[BNW]+f[TSE])-(f[TSW]+f[BNE]))+((f[BSW]+f[TNE])-(f[BSE]+f[TNW])))+((f[BW]+f[TE])-(f[TW]+f[BE]))-(vx1*vx3));
+   kxxMyy = -3./2.*omega*((((f[D3Q27System::BW]+f[TE])-(f[BS]+f[TN]))+((f[TW]+f[BE])-(f[TS]+f[BN])))+((f[W]+f[E])-(f[S]+f[N]))-(vx1*vx1-vx2*vx2));
+   kxxMzz = -3./2.*omega*((((f[NW]+f[SE])-(f[BS]+f[TN]))+((f[SW]+f[NE])-(f[TS]+f[BN])))+((f[W]+f[E])-(f[B]+f[T]))-(vx1*vx1-vx3*vx3));
+   //kxxMzz = -3./2.*omega*(((((f[NW]+f[SE])-(f[BS]+f[TN]))+((f[SW]+f[NE])-(f[17]+f[BN])))+((f[W]+f[E])-(f[B]+f[T])))-(vx1*vx1-vx3*vx3));
+
+   //UBLOG(logINFO, "t1 = "<<(((f[NW]+f[SE])-(f[BS]+f[TN]))+((f[SW]+f[NE])-(f[17]+f[BN])))+((f[W]+f[E])-(f[B]+f[T])));
+   //UBLOG(logINFO, "kxxMzz = "<<kxxMzz);
+
+   //UBLOG(logINFO,"f[BW]  = " << f[BW] << " BW  = " << BW);
+   //UBLOG(logINFO,"f[BE]  = " << f[BE] << " BE  = " << BE);
+   //UBLOG(logINFO,"f[NW]  = " << f[NW] << " NW  = " << NW);
+   //UBLOG(logINFO,"f[SE]  = " << f[SE] << " SE  = " << SE);
+   //UBLOG(logINFO,"f[BS]  = " << f[BS] << " BS  = " << BS);
+   //UBLOG(logINFO,"f[TN]  = " << f[TN] << " TN  = " << TN);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::calcInterpolatedCoefficiets(const D3Q27ICell& icell, LBMReal omega, LBMReal eps_new)
+{
+   LBMReal        vx1_SWT,vx2_SWT,vx3_SWT;
+   LBMReal        vx1_NWT,vx2_NWT,vx3_NWT;
+   LBMReal        vx1_NET,vx2_NET,vx3_NET;
+   LBMReal        vx1_SET,vx2_SET,vx3_SET;
+   LBMReal        vx1_SWB,vx2_SWB,vx3_SWB;
+   LBMReal        vx1_NWB,vx2_NWB,vx3_NWB;
+   LBMReal        vx1_NEB,vx2_NEB,vx3_NEB;
+   LBMReal        vx1_SEB,vx2_SEB,vx3_SEB;
+
+   LBMReal        kxyFromfcNEQ_SWT, kyzFromfcNEQ_SWT, kxzFromfcNEQ_SWT, kxxMyyFromfcNEQ_SWT, kxxMzzFromfcNEQ_SWT;
+   LBMReal        kxyFromfcNEQ_NWT, kyzFromfcNEQ_NWT, kxzFromfcNEQ_NWT, kxxMyyFromfcNEQ_NWT, kxxMzzFromfcNEQ_NWT;
+   LBMReal        kxyFromfcNEQ_NET, kyzFromfcNEQ_NET, kxzFromfcNEQ_NET, kxxMyyFromfcNEQ_NET, kxxMzzFromfcNEQ_NET;
+   LBMReal        kxyFromfcNEQ_SET, kyzFromfcNEQ_SET, kxzFromfcNEQ_SET, kxxMyyFromfcNEQ_SET, kxxMzzFromfcNEQ_SET;
+   LBMReal        kxyFromfcNEQ_SWB, kyzFromfcNEQ_SWB, kxzFromfcNEQ_SWB, kxxMyyFromfcNEQ_SWB, kxxMzzFromfcNEQ_SWB;
+   LBMReal        kxyFromfcNEQ_NWB, kyzFromfcNEQ_NWB, kxzFromfcNEQ_NWB, kxxMyyFromfcNEQ_NWB, kxxMzzFromfcNEQ_NWB;
+   LBMReal        kxyFromfcNEQ_NEB, kyzFromfcNEQ_NEB, kxzFromfcNEQ_NEB, kxxMyyFromfcNEQ_NEB, kxxMzzFromfcNEQ_NEB;
+   LBMReal        kxyFromfcNEQ_SEB, kyzFromfcNEQ_SEB, kxzFromfcNEQ_SEB, kxxMyyFromfcNEQ_SEB, kxxMzzFromfcNEQ_SEB;
+
+   calcMoments(icell.TSW,omega,press_SWT,vx1_SWT,vx2_SWT,vx3_SWT, kxyFromfcNEQ_SWT, kyzFromfcNEQ_SWT, kxzFromfcNEQ_SWT, kxxMyyFromfcNEQ_SWT, kxxMzzFromfcNEQ_SWT);
+   calcMoments(icell.TNW,omega,press_NWT,vx1_NWT,vx2_NWT,vx3_NWT, kxyFromfcNEQ_NWT, kyzFromfcNEQ_NWT, kxzFromfcNEQ_NWT, kxxMyyFromfcNEQ_NWT, kxxMzzFromfcNEQ_NWT);
+   calcMoments(icell.TNE,omega,press_NET,vx1_NET,vx2_NET,vx3_NET, kxyFromfcNEQ_NET, kyzFromfcNEQ_NET, kxzFromfcNEQ_NET, kxxMyyFromfcNEQ_NET, kxxMzzFromfcNEQ_NET);
+   calcMoments(icell.TSE,omega,press_SET,vx1_SET,vx2_SET,vx3_SET, kxyFromfcNEQ_SET, kyzFromfcNEQ_SET, kxzFromfcNEQ_SET, kxxMyyFromfcNEQ_SET, kxxMzzFromfcNEQ_SET);
+   calcMoments(icell.BSW,omega,press_SWB,vx1_SWB,vx2_SWB,vx3_SWB, kxyFromfcNEQ_SWB, kyzFromfcNEQ_SWB, kxzFromfcNEQ_SWB, kxxMyyFromfcNEQ_SWB, kxxMzzFromfcNEQ_SWB);
+   calcMoments(icell.BNW,omega,press_NWB,vx1_NWB,vx2_NWB,vx3_NWB, kxyFromfcNEQ_NWB, kyzFromfcNEQ_NWB, kxzFromfcNEQ_NWB, kxxMyyFromfcNEQ_NWB, kxxMzzFromfcNEQ_NWB);
+   calcMoments(icell.BNE,omega,press_NEB,vx1_NEB,vx2_NEB,vx3_NEB, kxyFromfcNEQ_NEB, kyzFromfcNEQ_NEB, kxzFromfcNEQ_NEB, kxxMyyFromfcNEQ_NEB, kxxMzzFromfcNEQ_NEB);
+   calcMoments(icell.BSE,omega,press_SEB,vx1_SEB,vx2_SEB,vx3_SEB, kxyFromfcNEQ_SEB, kyzFromfcNEQ_SEB, kxzFromfcNEQ_SEB, kxxMyyFromfcNEQ_SEB, kxxMzzFromfcNEQ_SEB);
+
+   //LBMReal dxRho=c1o4*((press_NET-press_SWB)+(press_SET-press_NWB)+(press_NEB-press_SWT)+(press_SEB-press_NWT));
+   //LBMReal dyRho=c1o4*((press_NET-press_SWB)-(press_SET-press_NWB)+(press_NEB-press_SWT)-(press_SEB-press_NWT));
+   //LBMReal dzRho=c1o4*((press_NET-press_SWB)+(press_SET-press_NWB)-(press_NEB-press_SWT)-(press_SEB-press_NWT));
+
+   //   kxyFromfcNEQ_SWT+=vx1_SWT*dyRho+vx2_SWT*dxRho;
+   //   kxyFromfcNEQ_NWT+=vx1_NWT*dyRho+vx2_NWT*dxRho;
+   //   kxyFromfcNEQ_NET+=vx1_NET*dyRho+vx2_NET*dxRho;
+   //   kxyFromfcNEQ_SET+=vx1_SET*dyRho+vx2_SET*dxRho;
+   //   kxyFromfcNEQ_SWB+=vx1_SWB*dyRho+vx2_SWB*dxRho;
+   //   kxyFromfcNEQ_NWB+=vx1_NWB*dyRho+vx2_NWB*dxRho;
+   //   kxyFromfcNEQ_NEB+=vx1_NEB*dyRho+vx2_NEB*dxRho;
+   //   kxyFromfcNEQ_SEB+=vx1_SEB*dyRho+vx2_SEB*dxRho;
+
+   //   kyzFromfcNEQ_SWT+=vx3_SWT*dyRho+vx2_SWT*dzRho;
+   //   kyzFromfcNEQ_NWT+=vx3_NWT*dyRho+vx2_NWT*dzRho;
+   //   kyzFromfcNEQ_NET+=vx3_NET*dyRho+vx2_NET*dzRho;
+   //   kyzFromfcNEQ_SET+=vx3_SET*dyRho+vx2_SET*dzRho;
+   //   kyzFromfcNEQ_SWB+=vx3_SWB*dyRho+vx2_SWB*dzRho;
+   //   kyzFromfcNEQ_NWB+=vx3_NWB*dyRho+vx2_NWB*dzRho;
+   //   kyzFromfcNEQ_NEB+=vx3_NEB*dyRho+vx2_NEB*dzRho;
+   //   kyzFromfcNEQ_SEB+=vx3_SEB*dyRho+vx2_SEB*dzRho;
+
+   //   kxzFromfcNEQ_SWT+=vx1_SWT*dzRho+vx3_SWT*dxRho;
+   //   kxzFromfcNEQ_NWT+=vx1_NWT*dzRho+vx3_NWT*dxRho;
+   //   kxzFromfcNEQ_NET+=vx1_NET*dzRho+vx3_NET*dxRho;
+   //   kxzFromfcNEQ_SET+=vx1_SET*dzRho+vx3_SET*dxRho;
+   //   kxzFromfcNEQ_SWB+=vx1_SWB*dzRho+vx3_SWB*dxRho;
+   //   kxzFromfcNEQ_NWB+=vx1_NWB*dzRho+vx3_NWB*dxRho;
+   //   kxzFromfcNEQ_NEB+=vx1_NEB*dzRho+vx3_NEB*dxRho;
+   //   kxzFromfcNEQ_SEB+=vx1_SEB*dzRho+vx3_SEB*dxRho;
+
+   //   kxxMyyFromfcNEQ_SWT+=vx1_SWT*dxRho-vx2_SWT*dyRho;
+   //   kxxMyyFromfcNEQ_NWT+=vx1_NWT*dxRho-vx2_NWT*dyRho;
+   //   kxxMyyFromfcNEQ_NET+=vx1_NET*dxRho-vx2_NET*dyRho;
+   //   kxxMyyFromfcNEQ_SET+=vx1_SET*dxRho-vx2_SET*dyRho;
+   //   kxxMyyFromfcNEQ_SWB+=vx1_SWB*dxRho-vx2_SWB*dyRho;
+   //   kxxMyyFromfcNEQ_NWB+=vx1_NWB*dxRho-vx2_NWB*dyRho;
+   //   kxxMyyFromfcNEQ_NEB+=vx1_NEB*dxRho-vx2_NEB*dyRho;
+   //   kxxMyyFromfcNEQ_SEB+=vx1_SEB*dxRho-vx2_SEB*dyRho;
+
+   //   kxxMzzFromfcNEQ_SWT+=vx1_SWT*dxRho-vx3_SWT*dzRho;
+   //   kxxMzzFromfcNEQ_NWT+=vx1_NWT*dxRho-vx3_NWT*dzRho;
+   //   kxxMzzFromfcNEQ_NET+=vx1_NET*dxRho-vx3_NET*dzRho;
+   //   kxxMzzFromfcNEQ_SET+=vx1_SET*dxRho-vx3_SET*dzRho;
+   //   kxxMzzFromfcNEQ_SWB+=vx1_SWB*dxRho-vx3_SWB*dzRho;
+   //   kxxMzzFromfcNEQ_NWB+=vx1_NWB*dxRho-vx3_NWB*dzRho;
+   //   kxxMzzFromfcNEQ_NEB+=vx1_NEB*dxRho-vx3_NEB*dzRho;
+   //   kxxMzzFromfcNEQ_SEB+=vx1_SEB*dxRho-vx3_SEB*dzRho;
+
+
+      //kxxMzzFromfcNEQ_SWT=0.0;
+      //kxxMzzFromfcNEQ_NWT=0.0;
+      //kxxMzzFromfcNEQ_NET=0.0;
+      //kxxMzzFromfcNEQ_SET=0.0;
+      //kxxMzzFromfcNEQ_SWB=0.0;
+      //kxxMzzFromfcNEQ_NWB=0.0;
+      //kxxMzzFromfcNEQ_NEB=0.0;
+      //kxxMzzFromfcNEQ_SEB=0.0;
+
+
+
+
+
+   a0 = (-kxxMyyFromfcNEQ_NEB - kxxMyyFromfcNEQ_NET + kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_NWT -
+      kxxMyyFromfcNEQ_SEB - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_SWT -
+      kxxMzzFromfcNEQ_NEB - kxxMzzFromfcNEQ_NET + kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_NWT -
+      kxxMzzFromfcNEQ_SEB - kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_SWT -
+      2.*kxyFromfcNEQ_NEB - 2.*kxyFromfcNEQ_NET - 2.*kxyFromfcNEQ_NWB - 2.*kxyFromfcNEQ_NWT +
+      2.*kxyFromfcNEQ_SEB + 2.*kxyFromfcNEQ_SET + 2.*kxyFromfcNEQ_SWB + 2.*kxyFromfcNEQ_SWT +
+      2.*kxzFromfcNEQ_NEB - 2.*kxzFromfcNEQ_NET + 2.*kxzFromfcNEQ_NWB - 2.*kxzFromfcNEQ_NWT +
+      2.*kxzFromfcNEQ_SEB - 2.*kxzFromfcNEQ_SET + 2.*kxzFromfcNEQ_SWB - 2.*kxzFromfcNEQ_SWT +
+      8.*vx1_NEB + 8.*vx1_NET + 8.*vx1_NWB + 8.*vx1_NWT + 8.*vx1_SEB +
+      8.*vx1_SET + 8.*vx1_SWB + 8.*vx1_SWT + 2.*vx2_NEB + 2.*vx2_NET -
+      2.*vx2_NWB - 2.*vx2_NWT - 2.*vx2_SEB - 2.*vx2_SET + 2.*vx2_SWB +
+      2.*vx2_SWT - 2.*vx3_NEB + 2.*vx3_NET + 2.*vx3_NWB - 2.*vx3_NWT -
+      2.*vx3_SEB + 2.*vx3_SET + 2.*vx3_SWB - 2.*vx3_SWT)/64.;
+   b0 = (2.*kxxMyyFromfcNEQ_NEB + 2.*kxxMyyFromfcNEQ_NET + 2.*kxxMyyFromfcNEQ_NWB + 2.*kxxMyyFromfcNEQ_NWT -
+      2.*kxxMyyFromfcNEQ_SEB - 2.*kxxMyyFromfcNEQ_SET - 2.*kxxMyyFromfcNEQ_SWB - 2.*kxxMyyFromfcNEQ_SWT -
+      kxxMzzFromfcNEQ_NEB - kxxMzzFromfcNEQ_NET - kxxMzzFromfcNEQ_NWB - kxxMzzFromfcNEQ_NWT +
+      kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_SWT -
+      2.*kxyFromfcNEQ_NEB - 2.*kxyFromfcNEQ_NET + 2.*kxyFromfcNEQ_NWB + 2.*kxyFromfcNEQ_NWT -
+      2.*kxyFromfcNEQ_SEB - 2.*kxyFromfcNEQ_SET + 2.*kxyFromfcNEQ_SWB + 2.*kxyFromfcNEQ_SWT +
+      2.*kyzFromfcNEQ_NEB - 2.*kyzFromfcNEQ_NET + 2.*kyzFromfcNEQ_NWB - 2.*kyzFromfcNEQ_NWT +
+      2.*kyzFromfcNEQ_SEB - 2.*kyzFromfcNEQ_SET + 2.*kyzFromfcNEQ_SWB - 2.*kyzFromfcNEQ_SWT +
+      2.*vx1_NEB + 2.*vx1_NET - 2.*vx1_NWB - 2.*vx1_NWT -
+      2.*vx1_SEB - 2.*vx1_SET + 2.*vx1_SWB + 2.*vx1_SWT +
+      8.*vx2_NEB + 8.*vx2_NET + 8.*vx2_NWB + 8.*vx2_NWT +
+      8.*vx2_SEB + 8.*vx2_SET + 8.*vx2_SWB + 8.*vx2_SWT -
+      2.*vx3_NEB + 2.*vx3_NET - 2.*vx3_NWB + 2.*vx3_NWT +
+      2.*vx3_SEB - 2.*vx3_SET + 2.*vx3_SWB - 2.*vx3_SWT)/64.;
+   c0 = (kxxMyyFromfcNEQ_NEB - kxxMyyFromfcNEQ_NET + kxxMyyFromfcNEQ_NWB - kxxMyyFromfcNEQ_NWT +
+      kxxMyyFromfcNEQ_SEB - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_SWT -
+      2.*kxxMzzFromfcNEQ_NEB + 2.*kxxMzzFromfcNEQ_NET - 2.*kxxMzzFromfcNEQ_NWB + 2.*kxxMzzFromfcNEQ_NWT -
+      2.*kxxMzzFromfcNEQ_SEB + 2.*kxxMzzFromfcNEQ_SET - 2.*kxxMzzFromfcNEQ_SWB + 2.*kxxMzzFromfcNEQ_SWT -
+      2.*kxzFromfcNEQ_NEB - 2.*kxzFromfcNEQ_NET + 2.*kxzFromfcNEQ_NWB + 2.*kxzFromfcNEQ_NWT -
+      2.*kxzFromfcNEQ_SEB - 2.*kxzFromfcNEQ_SET + 2.*kxzFromfcNEQ_SWB + 2.*kxzFromfcNEQ_SWT -
+      2.*kyzFromfcNEQ_NEB - 2.*kyzFromfcNEQ_NET - 2.*kyzFromfcNEQ_NWB - 2.*kyzFromfcNEQ_NWT +
+      2.*kyzFromfcNEQ_SEB + 2.*kyzFromfcNEQ_SET + 2.*kyzFromfcNEQ_SWB + 2.*kyzFromfcNEQ_SWT -
+      2.*vx1_NEB + 2.*vx1_NET + 2.*vx1_NWB - 2.*vx1_NWT -
+      2.*vx1_SEB + 2.*vx1_SET + 2.*vx1_SWB - 2.*vx1_SWT -
+      2.*vx2_NEB + 2.*vx2_NET - 2.*vx2_NWB + 2.*vx2_NWT +
+      2.*vx2_SEB - 2.*vx2_SET + 2.*vx2_SWB - 2.*vx2_SWT +
+      8.*vx3_NEB + 8.*vx3_NET + 8.*vx3_NWB + 8.*vx3_NWT +
+      8.*vx3_SEB + 8.*vx3_SET + 8.*vx3_SWB + 8.*vx3_SWT)/64.;
+   ax = (vx1_NEB + vx1_NET - vx1_NWB - vx1_NWT + vx1_SEB + vx1_SET - vx1_SWB - vx1_SWT)/4.;
+   bx = (vx2_NEB + vx2_NET - vx2_NWB - vx2_NWT + vx2_SEB + vx2_SET - vx2_SWB - vx2_SWT)/4.;
+   cx = (vx3_NEB + vx3_NET - vx3_NWB - vx3_NWT + vx3_SEB + vx3_SET - vx3_SWB - vx3_SWT)/4.;
+   axx= (kxxMyyFromfcNEQ_NEB + kxxMyyFromfcNEQ_NET - kxxMyyFromfcNEQ_NWB - kxxMyyFromfcNEQ_NWT +
+      kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_SWT +
+      kxxMzzFromfcNEQ_NEB + kxxMzzFromfcNEQ_NET - kxxMzzFromfcNEQ_NWB - kxxMzzFromfcNEQ_NWT +
+      kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_SWT +
+      2.*vx2_NEB + 2.*vx2_NET - 2.*vx2_NWB - 2.*vx2_NWT -
+      2.*vx2_SEB - 2.*vx2_SET + 2.*vx2_SWB + 2.*vx2_SWT -
+      2.*vx3_NEB + 2.*vx3_NET + 2.*vx3_NWB - 2.*vx3_NWT -
+      2.*vx3_SEB + 2.*vx3_SET + 2.*vx3_SWB - 2.*vx3_SWT)/16.;
+   bxx= (kxyFromfcNEQ_NEB + kxyFromfcNEQ_NET - kxyFromfcNEQ_NWB - kxyFromfcNEQ_NWT +
+      kxyFromfcNEQ_SEB + kxyFromfcNEQ_SET - kxyFromfcNEQ_SWB - kxyFromfcNEQ_SWT -
+      2.*vx1_NEB - 2.*vx1_NET + 2.*vx1_NWB + 2.*vx1_NWT +
+      2.*vx1_SEB + 2.*vx1_SET - 2.*vx1_SWB - 2.*vx1_SWT)/8.;
+   cxx= (kxzFromfcNEQ_NEB + kxzFromfcNEQ_NET - kxzFromfcNEQ_NWB - kxzFromfcNEQ_NWT +
+      kxzFromfcNEQ_SEB + kxzFromfcNEQ_SET - kxzFromfcNEQ_SWB - kxzFromfcNEQ_SWT +
+      2.*vx1_NEB - 2.*vx1_NET - 2.*vx1_NWB + 2.*vx1_NWT +
+      2.*vx1_SEB - 2.*vx1_SET - 2.*vx1_SWB + 2.*vx1_SWT)/8.;
+   ay = (vx1_NEB + vx1_NET + vx1_NWB + vx1_NWT - vx1_SEB - vx1_SET - vx1_SWB - vx1_SWT)/4.;
+   by = (vx2_NEB + vx2_NET + vx2_NWB + vx2_NWT - vx2_SEB - vx2_SET - vx2_SWB - vx2_SWT)/4.;
+   cy = (vx3_NEB + vx3_NET + vx3_NWB + vx3_NWT - vx3_SEB - vx3_SET - vx3_SWB - vx3_SWT)/4.;
+   ayy= (kxyFromfcNEQ_NEB + kxyFromfcNEQ_NET + kxyFromfcNEQ_NWB + kxyFromfcNEQ_NWT -
+      kxyFromfcNEQ_SEB - kxyFromfcNEQ_SET - kxyFromfcNEQ_SWB - kxyFromfcNEQ_SWT -
+      2.*vx2_NEB - 2.*vx2_NET + 2.*vx2_NWB + 2.*vx2_NWT +
+      2.*vx2_SEB + 2.*vx2_SET - 2.*vx2_SWB - 2.*vx2_SWT)/8.;
+   byy= (-2.*kxxMyyFromfcNEQ_NEB - 2.*kxxMyyFromfcNEQ_NET - 2.*kxxMyyFromfcNEQ_NWB - 2.*kxxMyyFromfcNEQ_NWT +
+      2.*kxxMyyFromfcNEQ_SEB + 2.*kxxMyyFromfcNEQ_SET + 2.*kxxMyyFromfcNEQ_SWB + 2.*kxxMyyFromfcNEQ_SWT +
+      kxxMzzFromfcNEQ_NEB + kxxMzzFromfcNEQ_NET + kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_NWT -
+      kxxMzzFromfcNEQ_SEB - kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_SWT +
+      2.*vx1_NEB + 2.*vx1_NET - 2.*vx1_NWB - 2.*vx1_NWT -
+      2.*vx1_SEB - 2.*vx1_SET + 2.*vx1_SWB + 2.*vx1_SWT -
+      2.*vx3_NEB + 2.*vx3_NET - 2.*vx3_NWB + 2.*vx3_NWT +
+      2.*vx3_SEB - 2.*vx3_SET + 2.*vx3_SWB - 2.*vx3_SWT)/16.;
+   cyy= (kyzFromfcNEQ_NEB + kyzFromfcNEQ_NET + kyzFromfcNEQ_NWB + kyzFromfcNEQ_NWT -
+      kyzFromfcNEQ_SEB - kyzFromfcNEQ_SET - kyzFromfcNEQ_SWB - kyzFromfcNEQ_SWT +
+      2.*vx2_NEB - 2.*vx2_NET + 2.*vx2_NWB - 2.*vx2_NWT -
+      2.*vx2_SEB + 2.*vx2_SET - 2.*vx2_SWB + 2.*vx2_SWT)/8.;
+   az = (-vx1_NEB + vx1_NET - vx1_NWB + vx1_NWT - vx1_SEB + vx1_SET - vx1_SWB + vx1_SWT)/4.;
+   bz = (-vx2_NEB + vx2_NET - vx2_NWB + vx2_NWT - vx2_SEB + vx2_SET - vx2_SWB + vx2_SWT)/4.;
+   cz = (-vx3_NEB + vx3_NET - vx3_NWB + vx3_NWT - vx3_SEB + vx3_SET - vx3_SWB + vx3_SWT)/4.;
+   azz= (-kxzFromfcNEQ_NEB + kxzFromfcNEQ_NET - kxzFromfcNEQ_NWB + kxzFromfcNEQ_NWT -
+      kxzFromfcNEQ_SEB + kxzFromfcNEQ_SET - kxzFromfcNEQ_SWB + kxzFromfcNEQ_SWT +
+      2.*vx3_NEB - 2.*vx3_NET - 2.*vx3_NWB + 2.*vx3_NWT +
+      2.*vx3_SEB - 2.*vx3_SET - 2.*vx3_SWB + 2.*vx3_SWT)/8.;
+   bzz= (-kyzFromfcNEQ_NEB + kyzFromfcNEQ_NET - kyzFromfcNEQ_NWB + kyzFromfcNEQ_NWT -
+      kyzFromfcNEQ_SEB + kyzFromfcNEQ_SET - kyzFromfcNEQ_SWB + kyzFromfcNEQ_SWT +
+      2.*vx3_NEB - 2.*vx3_NET + 2.*vx3_NWB - 2.*vx3_NWT -
+      2.*vx3_SEB + 2.*vx3_SET - 2.*vx3_SWB + 2.*vx3_SWT)/8.;
+   czz= (-kxxMyyFromfcNEQ_NEB + kxxMyyFromfcNEQ_NET - kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_NWT -
+      kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_SWT +
+      2.*kxxMzzFromfcNEQ_NEB - 2.*kxxMzzFromfcNEQ_NET + 2.*kxxMzzFromfcNEQ_NWB - 2.*kxxMzzFromfcNEQ_NWT +
+      2.*kxxMzzFromfcNEQ_SEB - 2.*kxxMzzFromfcNEQ_SET + 2.*kxxMzzFromfcNEQ_SWB - 2.*kxxMzzFromfcNEQ_SWT -
+      2.*vx1_NEB + 2.*vx1_NET + 2.*vx1_NWB - 2.*vx1_NWT -
+      2.*vx1_SEB + 2.*vx1_SET + 2.*vx1_SWB - 2.*vx1_SWT -
+      2.*vx2_NEB + 2.*vx2_NET - 2.*vx2_NWB + 2.*vx2_NWT +
+      2.*vx2_SEB - 2.*vx2_SET + 2.*vx2_SWB - 2.*vx2_SWT)/16.;
+   axy= (vx1_NEB + vx1_NET - vx1_NWB - vx1_NWT - vx1_SEB - vx1_SET + vx1_SWB + vx1_SWT)/2.;
+   bxy= (vx2_NEB + vx2_NET - vx2_NWB - vx2_NWT - vx2_SEB - vx2_SET + vx2_SWB + vx2_SWT)/2.;
+   cxy= (vx3_NEB + vx3_NET - vx3_NWB - vx3_NWT - vx3_SEB - vx3_SET + vx3_SWB + vx3_SWT)/2.;
+   axz= (-vx1_NEB + vx1_NET + vx1_NWB - vx1_NWT - vx1_SEB + vx1_SET + vx1_SWB - vx1_SWT)/2.;
+   bxz= (-vx2_NEB + vx2_NET + vx2_NWB - vx2_NWT - vx2_SEB + vx2_SET + vx2_SWB - vx2_SWT)/2.;
+   cxz= (-vx3_NEB + vx3_NET + vx3_NWB - vx3_NWT - vx3_SEB + vx3_SET + vx3_SWB - vx3_SWT)/2.;
+   ayz= (-vx1_NEB + vx1_NET - vx1_NWB + vx1_NWT + vx1_SEB - vx1_SET + vx1_SWB - vx1_SWT)/2.;
+   byz= (-vx2_NEB + vx2_NET - vx2_NWB + vx2_NWT + vx2_SEB - vx2_SET + vx2_SWB - vx2_SWT)/2.;
+   cyz= (-vx3_NEB + vx3_NET - vx3_NWB + vx3_NWT + vx3_SEB - vx3_SET + vx3_SWB - vx3_SWT)/2.;
+   axyz=-vx1_NEB + vx1_NET + vx1_NWB - vx1_NWT + vx1_SEB - vx1_SET - vx1_SWB + vx1_SWT;
+   bxyz=-vx2_NEB + vx2_NET + vx2_NWB - vx2_NWT + vx2_SEB - vx2_SET - vx2_SWB + vx2_SWT;
+   cxyz=-vx3_NEB + vx3_NET + vx3_NWB - vx3_NWT + vx3_SEB - vx3_SET - vx3_SWB + vx3_SWT;
+
+
+   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+   kxyAverage       =(kxyFromfcNEQ_SWB+
+                      kxyFromfcNEQ_SWT+
+                      kxyFromfcNEQ_SET+
+                      kxyFromfcNEQ_SEB+
+                      kxyFromfcNEQ_NWB+
+                      kxyFromfcNEQ_NWT+
+                      kxyFromfcNEQ_NET+
+                      kxyFromfcNEQ_NEB)*c1o8-(ay+bx);
+   kyzAverage       =(kyzFromfcNEQ_SWB+
+                      kyzFromfcNEQ_SWT+
+                      kyzFromfcNEQ_SET+
+                      kyzFromfcNEQ_SEB+
+                      kyzFromfcNEQ_NWB+
+                      kyzFromfcNEQ_NWT+
+                      kyzFromfcNEQ_NET+
+                      kyzFromfcNEQ_NEB)*c1o8-(bz+cy);
+   kxzAverage       =(kxzFromfcNEQ_SWB+
+                      kxzFromfcNEQ_SWT+
+                      kxzFromfcNEQ_SET+
+                      kxzFromfcNEQ_SEB+
+                      kxzFromfcNEQ_NWB+
+                      kxzFromfcNEQ_NWT+
+                      kxzFromfcNEQ_NET+
+                      kxzFromfcNEQ_NEB)*c1o8-(az+cx);
+   kxxMyyAverage    =(kxxMyyFromfcNEQ_SWB+
+                      kxxMyyFromfcNEQ_SWT+
+                      kxxMyyFromfcNEQ_SET+
+                      kxxMyyFromfcNEQ_SEB+
+                      kxxMyyFromfcNEQ_NWB+
+                      kxxMyyFromfcNEQ_NWT+
+                      kxxMyyFromfcNEQ_NET+
+                      kxxMyyFromfcNEQ_NEB)*c1o8-(ax-by);
+   kxxMzzAverage    =(kxxMzzFromfcNEQ_SWB+
+                     kxxMzzFromfcNEQ_SWT+
+                     kxxMzzFromfcNEQ_SET+
+                     kxxMzzFromfcNEQ_SEB+
+                     kxxMzzFromfcNEQ_NWB+
+                     kxxMzzFromfcNEQ_NWT+
+                     kxxMzzFromfcNEQ_NET+
+                     kxxMzzFromfcNEQ_NEB)*c1o8-(ax-cz);
+   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+   //
+   // Bernd das Brot
+   //
+   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+   a0 = a0 + xoff * ax + yoff * ay + zoff * az + xoff_sq * axx + yoff_sq * ayy + zoff_sq * azz + xoff*yoff*axy + xoff*zoff*axz + yoff*zoff*ayz + xoff*yoff*zoff*axyz ;
+   ax = ax + 2. * xoff * axx + yoff * axy + zoff * axz + yoff*zoff*axyz;
+   ay = ay + 2. * yoff * ayy + xoff * axy + zoff * ayz + xoff*zoff*axyz;
+   az = az + 2. * zoff * azz + xoff * axz + yoff * ayz + xoff*yoff*axyz;
+   b0 = b0 + xoff * bx + yoff * by + zoff * bz + xoff_sq * bxx + yoff_sq * byy + zoff_sq * bzz + xoff*yoff*bxy + xoff*zoff*bxz + yoff*zoff*byz + xoff*yoff*zoff*bxyz;
+   bx = bx + 2. * xoff * bxx + yoff * bxy + zoff * bxz + yoff*zoff*bxyz;
+   by = by + 2. * yoff * byy + xoff * bxy + zoff * byz + xoff*zoff*bxyz;
+   bz = bz + 2. * zoff * bzz + xoff * bxz + yoff * byz + xoff*yoff*bxyz;
+   c0 = c0 + xoff * cx + yoff * cy + zoff * cz + xoff_sq * cxx + yoff_sq * cyy + zoff_sq * czz + xoff*yoff*cxy + xoff*zoff*cxz + yoff*zoff*cyz + xoff*yoff*zoff*cxyz;
+   cx = cx + 2. * xoff * cxx + yoff * cxy + zoff * cxz + yoff*zoff*cxyz;
+   cy = cy + 2. * yoff * cyy + xoff * cxy + zoff * cyz + xoff*zoff*cxyz;
+   cz = cz + 2. * zoff * czz + xoff * cxz + yoff * cyz + xoff*yoff*cxyz;
+   axy= axy + zoff*axyz;
+   axz= axz + yoff*axyz;
+   ayz= ayz + xoff*axyz;
+   bxy= bxy + zoff*bxyz;
+   bxz= bxz + yoff*bxyz;
+   byz= byz + xoff*bxyz;
+   cxy= cxy + zoff*cxyz;
+   cxz= cxz + yoff*cxyz;
+   cyz= cyz + xoff*cxyz;
+   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+   const LBMReal o = omega;
+
+   f_E = eps_new*((2*(-2*ax + by + cz-kxxMzzAverage-kxxMyyAverage))/(27.*o));
+   f_N = eps_new*((2*(ax - 2*by + cz+2*kxxMyyAverage-kxxMzzAverage))/(27.*o));
+   f_T = eps_new*((2*(ax + by - 2*cz-kxxMyyAverage+2*kxxMzzAverage))/(27.*o));
+   f_NE = eps_new*(-(ax + 3*ay + 3*bx + by - 2*cz+2*kxxMyyAverage-kxxMyyAverage+3*kxyAverage)/(54.*o));
+   f_SE = eps_new*(-(ax - 3*ay - 3*bx + by - 2*cz+2*kxxMyyAverage-kxxMyyAverage-3*kxyAverage)/(54.*o));
+   f_TE = eps_new*(-(ax + 3*az - 2*by + 3*cx + cz+2*kxxMyyAverage-kxxMzzAverage+3*kxzAverage)/(54.*o));
+   f_BE = eps_new*(-(ax - 3*az - 2*by - 3*cx + cz+2*kxxMyyAverage-kxxMzzAverage-3*kxzAverage)/(54.*o));
+   f_TN = eps_new*(-(-2*ax + by + 3*bz + 3*cy + cz-kxxMyyAverage-kxxMzzAverage+3*kyzAverage)/(54.*o));
+   f_BN = eps_new*(-(-2*ax + by - 3*bz - 3*cy + cz-kxxMyyAverage-kxxMzzAverage-3*kyzAverage)/(54.*o));
+   f_ZERO = 0.;
+   f_TNE = eps_new*(-(ay + az + bx + bz + cx + cy+kxyAverage+kxzAverage+kyzAverage)/(72.*o));
+   f_TSW = eps_new*((-ay + az - bx + bz + cx + cy-kxyAverage+kxzAverage+kyzAverage)/(72.*o));
+   f_TSE = eps_new*((ay - az + bx + bz - cx + cy+kxyAverage-kxzAverage+kyzAverage)/(72.*o));
+   f_TNW = eps_new*((ay + az + bx - bz + cx - cy+kxyAverage+kxzAverage-kyzAverage)/(72.*o));
+
+   x_E = 0.25*eps_new*((2*(-4*axx + bxy + cxz))/(27.*o));
+   x_N = 0.25*eps_new*((2*(2*axx - 2*bxy + cxz))/(27.*o));
+   x_T = 0.25*eps_new*((2*(2*axx + bxy - 2*cxz))/(27.*o));
+   x_NE = 0.25*eps_new*(-((2*axx + 3*axy + 6*bxx + bxy - 2*cxz))/(54.*o));
+   x_SE = 0.25*eps_new*(-((2*axx - 3*axy - 6*bxx + bxy - 2*cxz))/(54.*o));
+   x_TE = 0.25*eps_new*(-((2*axx + 3*axz - 2*bxy + 6*cxx + cxz))/(54.*o));
+   x_BE = 0.25*eps_new*(-((2*axx - 3*axz - 2*bxy - 6*cxx + cxz))/(54.*o));
+   x_TN = 0.25*eps_new*(-((-4*axx + bxy + 3*bxz + 3*cxy + cxz))/(54.*o));
+   x_BN = 0.25*eps_new*(-((-4*axx + bxy - 3*bxz - 3*cxy + cxz))/(54.*o));
+   x_ZERO = 0.;
+   x_TNE = 0.25*eps_new*(-((axy + axz + 2*bxx + bxz + 2*cxx + cxy))/(72.*o));
+   x_TSW = 0.25*eps_new*(((-axy + axz - 2*bxx + bxz + 2*cxx + cxy))/(72.*o));
+   x_TSE = 0.25*eps_new*(((axy - axz + 2*bxx + bxz - 2*cxx + cxy))/(72.*o));
+   x_TNW = 0.25*eps_new*(((axy + axz + 2*bxx - bxz + 2*cxx - cxy))/(72.*o));
+
+   y_E = 0.25*eps_new*(2*(-2*axy + 2*byy + cyz))/(27.*o);
+   y_N = 0.25*eps_new*(2*(axy - 4*byy + cyz))/(27.*o);
+   y_T = 0.25*eps_new*(2*(axy + 2*byy - 2*cyz))/(27.*o);
+   y_NE = 0.25*eps_new*(-((axy + 6*ayy + 3*bxy + 2*byy - 2*cyz))/(54.*o));
+   y_SE = 0.25*eps_new*(-((axy - 6*ayy - 3*bxy + 2*byy - 2*cyz))/(54.*o));
+   y_TE = 0.25*eps_new*(-((axy + 3*ayz - 4*byy + 3*cxy + cyz))/(54.*o));
+   y_BE = 0.25*eps_new*(-((axy - 3*ayz - 4*byy - 3*cxy + cyz))/(54.*o));
+   y_TN = 0.25*eps_new*(-((-2*axy + 2*byy + 3*byz + 6*cyy + cyz))/(54.*o));
+   y_BN = 0.25*eps_new*(-((-2*axy + 2*byy - 3*byz - 6*cyy + cyz))/(54.*o));
+   y_ZERO = 0.;
+   y_TNE = 0.25*eps_new*(-((2*ayy + ayz + bxy + byz + cxy + 2*cyy))/(72.*o));
+   y_TSW = 0.25*eps_new*(((-2*ayy + ayz - bxy + byz + cxy + 2*cyy))/(72.*o));
+   y_TSE = 0.25*eps_new*(((2*ayy - ayz + bxy + byz - cxy + 2*cyy))/(72.*o));
+   y_TNW = 0.25*eps_new*(((2*ayy + ayz + bxy - byz + cxy - 2*cyy))/(72.*o));
+
+   z_E = 0.25*eps_new*((2*(-2*axz + byz + 2*czz))/(27.*o));
+   z_N = 0.25*eps_new*((2*(axz - 2*byz + 2*czz))/(27.*o));
+   z_T = 0.25*eps_new*((2*(axz + byz - 4*czz))/(27.*o));
+   z_NE = 0.25*eps_new*(-((axz + 3*ayz + 3*bxz + byz - 4*czz))/(54.*o));
+   z_SE = 0.25*eps_new*(-((axz - 3*ayz - 3*bxz + byz - 4*czz))/(54.*o));
+   z_TE = 0.25*eps_new*(-((axz + 6*azz - 2*byz + 3*cxz + 2*czz))/(54.*o));
+   z_BE = 0.25*eps_new*(-((axz - 6*azz - 2*byz - 3*cxz + 2*czz))/(54.*o));
+   z_TN = 0.25*eps_new*(-((-2*axz + byz + 6*bzz + 3*cyz + 2*czz))/(54.*o));
+   z_BN = 0.25*eps_new*(-((-2*axz + byz - 6*bzz - 3*cyz + 2*czz))/(54.*o));
+   z_ZERO = 0.;
+   z_TNE = 0.25*eps_new*(-((ayz + 2*azz + bxz + 2*bzz + cxz + cyz))/(72.*o));
+   z_TSW = 0.25*eps_new*(((-ayz + 2*azz - bxz + 2*bzz + cxz + cyz))/(72.*o));
+   z_TSE = 0.25*eps_new*(((ayz - 2*azz + bxz + 2*bzz - cxz + cyz))/(72.*o));
+   z_TNW = 0.25*eps_new*(((ayz + 2*azz + bxz - 2*bzz + cxz - cyz))/(72.*o));
+
+   xy_E   =   0.0625*eps_new *((                       2.*cxyz)/(27.*o));
+   xy_N   =   0.0625*eps_new *((                       2.*cxyz)/(27.*o));
+   xy_T   = -(0.0625*eps_new *((                       4.*cxyz)/(27.*o)));
+   xy_NE  =   0.0625*eps_new *(                            cxyz /(27.*o));
+   xy_SE  =   0.0625*eps_new *(                            cxyz /(27.*o));
+   xy_TE  = -(0.0625*eps_new *(( 3.*axyz            +     cxyz)/(54.*o)));
+   xy_BE  = -(0.0625*eps_new *((-3.*axyz            +     cxyz)/(54.*o)));
+   xy_TN  = -(0.0625*eps_new *((            3.*bxyz +     cxyz)/(54.*o)));
+   xy_BN  = -(0.0625*eps_new *((          - 3.*bxyz +     cxyz)/(54.*o)));
+   //xy_ZERO=   0.0625*eps_new;
+   xy_TNE = -(0.0625*eps_new *((     axyz +     bxyz           )/(72.*o)));
+   xy_TSW =   0.0625*eps_new *((     axyz +     bxyz           )/(72.*o));
+   xy_TSE =   0.0625*eps_new *((-    axyz +     bxyz           )/(72.*o));
+   xy_TNW =   0.0625*eps_new *((     axyz -     bxyz           )/(72.*o));
+
+   xz_E   =   0.0625*eps_new *((            2.*bxyz           )/(27.*o));
+   xz_N   = -(0.0625*eps_new *((            4.*bxyz           )/(27.*o)));
+   xz_T   =   0.0625*eps_new *((            2.*bxyz           )/(27.*o));
+   xz_NE  = -(0.0625*eps_new *(( 3.*axyz +     bxyz           )/(54.*o)));
+   xz_SE  = -(0.0625*eps_new *((-3.*axyz +     bxyz           )/(54.*o)));
+   xz_TE  =   0.0625*eps_new *((                bxyz           )/(27.*o));
+   xz_BE  =   0.0625*eps_new *((                bxyz           )/(27.*o));
+   xz_TN  = -(0.0625*eps_new *((                bxyz + 3.*cxyz)/(54.*o)));
+   xz_BN  = -(0.0625*eps_new *((                bxyz - 3.*cxyz)/(54.*o)));
+   //xz_ZERO=   0.0625*eps_new;
+   xz_TNE = -(0.0625*eps_new *((     axyz            +     cxyz)/(72.*o)));
+   xz_TSW =   0.0625*eps_new *((-    axyz            +     cxyz)/(72.*o));
+   xz_TSE =   0.0625*eps_new *((     axyz            +     cxyz)/(72.*o));
+   xz_TNW =   0.0625*eps_new *((     axyz            -     cxyz)/(72.*o));
+
+   yz_E   = -(0.0625*eps_new *(( 4.*axyz                      )/(27.*o)));
+   yz_N   =   0.0625*eps_new *(( 2.*axyz                      )/(27.*o));
+   yz_T   =   0.0625*eps_new *(( 2.*axyz                      )/(27.*o));
+   yz_NE  = -(0.0625*eps_new *((     axyz + 3.*bxyz           )/(54.*o)));
+   yz_SE  = -(0.0625*eps_new *((     axyz - 3.*bxyz           )/(54.*o)));
+   yz_TE  = -(0.0625*eps_new *((     axyz            + 3.*cxyz)/(54.*o)));
+   yz_BE  = -(0.0625*eps_new *((     axyz            - 3.*cxyz)/(54.*o)));
+   yz_TN  =   0.0625*eps_new *((     axyz                      )/(27.*o));
+   yz_BN  =   0.0625*eps_new *((     axyz                      )/(27.*o));
+   //yz_ZERO=   0.0625*eps_new;
+   yz_TNE = -(0.0625*eps_new *((                bxyz +     cxyz)/(72.*o)));
+   yz_TSW =   0.0625*eps_new *((          -     bxyz +     cxyz)/(72.*o));
+   yz_TSE =   0.0625*eps_new *((                bxyz -     cxyz)/(72.*o));
+   yz_TNW =   0.0625*eps_new *((                bxyz +     cxyz)/(72.*o));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::calcInterpolatedNode(LBMReal* f, LBMReal omega, LBMReal x, LBMReal y, LBMReal z, LBMReal press, LBMReal xs, LBMReal ys, LBMReal zs)
+{
+   using namespace D3Q27System;
+
+   LBMReal rho  = press ;//+ (2.*axx*x+axy*y+axz*z+axyz*y*z+ax + 2.*byy*y+bxy*x+byz*z+bxyz*x*z+by + 2.*czz*z+cxz*x+cyz*y+cxyz*x*y+cz)/3.;
+   LBMReal vx1  = a0 + 0.25*( xs*ax + ys*ay + zs*az) + 0.0625*(axx + xs*ys*axy + xs*zs*axz + ayy + ys*zs*ayz + azz) + 0.015625*(xs*ys*zs*axyz);
+   LBMReal vx2  = b0 + 0.25*( xs*bx + ys*by + zs*bz) + 0.0625*(bxx + xs*ys*bxy + xs*zs*bxz + byy + ys*zs*byz + bzz) + 0.015625*(xs*ys*zs*bxyz);
+   LBMReal vx3  = c0 + 0.25*( xs*cx + ys*cy + zs*cz) + 0.0625*(cxx + xs*ys*cxy + xs*zs*cxz + cyy + ys*zs*cyz + czz) + 0.015625*(xs*ys*zs*cxyz);
+
+   //////////////////////////////////////////////////////////////////////////
+   //DRAFT
+   //vx1 -= forcingF*0.5;
+   //////////////////////////////////////////////////////////////////////////
+
+   LBMReal feq[ENDF+1];
+   D3Q27System::calcIncompFeq(feq,rho,vx1,vx2,vx3);
+
+   f[E]    = f_E    + xs*x_E    + ys*y_E    + zs*z_E    + xs*ys*xy_E    + xs*zs*xz_E    + ys*zs*yz_E    + feq[E];
+   f[W]    = f_E    + xs*x_E    + ys*y_E    + zs*z_E    + xs*ys*xy_E    + xs*zs*xz_E    + ys*zs*yz_E    + feq[W];
+   f[N]    = f_N    + xs*x_N    + ys*y_N    + zs*z_N    + xs*ys*xy_N    + xs*zs*xz_N    + ys*zs*yz_N    + feq[N];
+   f[S]    = f_N    + xs*x_N    + ys*y_N    + zs*z_N    + xs*ys*xy_N    + xs*zs*xz_N    + ys*zs*yz_N    + feq[S];
+   f[T]    = f_T    + xs*x_T    + ys*y_T    + zs*z_T    + xs*ys*xy_T    + xs*zs*xz_T    + ys*zs*yz_T    + feq[T];
+   f[B]    = f_T    + xs*x_T    + ys*y_T    + zs*z_T    + xs*ys*xy_T    + xs*zs*xz_T    + ys*zs*yz_T    + feq[B];
+   f[NE]   = f_NE   + xs*x_NE   + ys*y_NE   + zs*z_NE   + xs*ys*xy_NE   + xs*zs*xz_NE   + ys*zs*yz_NE   + feq[NE];
+   f[SW]   = f_NE   + xs*x_NE   + ys*y_NE   + zs*z_NE   + xs*ys*xy_NE   + xs*zs*xz_NE   + ys*zs*yz_NE   + feq[SW];
+   f[SE]   = f_SE   + xs*x_SE   + ys*y_SE   + zs*z_SE   + xs*ys*xy_SE   + xs*zs*xz_SE   + ys*zs*yz_SE   + feq[SE];
+   f[NW]   = f_SE   + xs*x_SE   + ys*y_SE   + zs*z_SE   + xs*ys*xy_SE   + xs*zs*xz_SE   + ys*zs*yz_SE   + feq[NW];
+   f[TE]   = f_TE   + xs*x_TE   + ys*y_TE   + zs*z_TE   + xs*ys*xy_TE   + xs*zs*xz_TE   + ys*zs*yz_TE   + feq[TE];
+   f[BW]   = f_TE   + xs*x_TE   + ys*y_TE   + zs*z_TE   + xs*ys*xy_TE   + xs*zs*xz_TE   + ys*zs*yz_TE   + feq[BW];
+   f[BE]   = f_BE   + xs*x_BE   + ys*y_BE   + zs*z_BE   + xs*ys*xy_BE   + xs*zs*xz_BE   + ys*zs*yz_BE   + feq[BE];
+   f[TW]   = f_BE   + xs*x_BE   + ys*y_BE   + zs*z_BE   + xs*ys*xy_BE   + xs*zs*xz_BE   + ys*zs*yz_BE   + feq[TW];
+   f[TN]   = f_TN   + xs*x_TN   + ys*y_TN   + zs*z_TN   + xs*ys*xy_TN   + xs*zs*xz_TN   + ys*zs*yz_TN   + feq[TN];
+   f[BS]   = f_TN   + xs*x_TN   + ys*y_TN   + zs*z_TN   + xs*ys*xy_TN   + xs*zs*xz_TN   + ys*zs*yz_TN   + feq[BS];
+   f[BN]   = f_BN   + xs*x_BN   + ys*y_BN   + zs*z_BN   + xs*ys*xy_BN   + xs*zs*xz_BN   + ys*zs*yz_BN   + feq[BN];
+   f[TS]   = f_BN   + xs*x_BN   + ys*y_BN   + zs*z_BN   + xs*ys*xy_BN   + xs*zs*xz_BN   + ys*zs*yz_BN   + feq[TS];
+   f[TNE]  = f_TNE  + xs*x_TNE  + ys*y_TNE  + zs*z_TNE  + xs*ys*xy_TNE  + xs*zs*xz_TNE  + ys*zs*yz_TNE  + feq[TNE];
+   f[TSW]  = f_TSW  + xs*x_TSW  + ys*y_TSW  + zs*z_TSW  + xs*ys*xy_TSW  + xs*zs*xz_TSW  + ys*zs*yz_TSW  + feq[TSW];
+   f[TSE]  = f_TSE  + xs*x_TSE  + ys*y_TSE  + zs*z_TSE  + xs*ys*xy_TSE  + xs*zs*xz_TSE  + ys*zs*yz_TSE  + feq[TSE];
+   f[TNW]  = f_TNW  + xs*x_TNW  + ys*y_TNW  + zs*z_TNW  + xs*ys*xy_TNW  + xs*zs*xz_TNW  + ys*zs*yz_TNW  + feq[TNW];
+   f[BNE]  = f_TSW  + xs*x_TSW  + ys*y_TSW  + zs*z_TSW  + xs*ys*xy_TSW  + xs*zs*xz_TSW  + ys*zs*yz_TSW  + feq[BNE];
+   f[BSW]  = f_TNE  + xs*x_TNE  + ys*y_TNE  + zs*z_TNE  + xs*ys*xy_TNE  + xs*zs*xz_TNE  + ys*zs*yz_TNE  + feq[BSW];
+   f[BSE]  = f_TNW  + xs*x_TNW  + ys*y_TNW  + zs*z_TNW  + xs*ys*xy_TNW  + xs*zs*xz_TNW  + ys*zs*yz_TNW  + feq[BSE];
+   f[BNW]  = f_TSE  + xs*x_TSE  + ys*y_TSE  + zs*z_TSE  + xs*ys*xy_TSE  + xs*zs*xz_TSE  + ys*zs*yz_TSE  + feq[BNW];
+   f[ZERO] = f_ZERO + xs*x_ZERO + ys*y_ZERO + zs*z_ZERO                                                 + feq[ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+//Position SWB -0.25, -0.25, -0.25
+LBMReal D3Q27IncompressibleOffsetInterpolationProcessor::calcPressBSW()
+{
+   return   press_SWT * (0.140625 + 0.1875 * xoff + 0.1875 * yoff - 0.5625 * zoff) +
+      press_NWT * (0.046875 + 0.0625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
+      press_SET * (0.046875 - 0.1875 * xoff + 0.0625 * yoff - 0.1875 * zoff) +
+      press_NET * (0.015625 - 0.0625 * xoff - 0.0625 * yoff - 0.0625 * zoff) +
+      press_NEB * (0.046875 - 0.1875 * xoff - 0.1875 * yoff + 0.0625 * zoff) +
+      press_NWB * (0.140625 + 0.1875 * xoff - 0.5625 * yoff + 0.1875 * zoff) +
+      press_SEB * (0.140625 - 0.5625 * xoff + 0.1875 * yoff + 0.1875 * zoff) +
+      press_SWB * (0.421875 + 0.5625 * xoff + 0.5625 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position SWT -0.25, -0.25, 0.25
+LBMReal D3Q27IncompressibleOffsetInterpolationProcessor::calcPressTSW()
+{
+   return   press_SWT * (0.421875 + 0.5625 * xoff + 0.5625 * yoff - 0.5625 * zoff) +
+      press_NWT * (0.140625 + 0.1875 * xoff - 0.5625 * yoff - 0.1875 * zoff) +
+      press_SET * (0.140625 - 0.5625 * xoff + 0.1875 * yoff - 0.1875 * zoff) +
+      press_NET * (0.046875 - 0.1875 * xoff - 0.1875 * yoff - 0.0625 * zoff) +
+      press_NEB * (0.015625 - 0.0625 * xoff - 0.0625 * yoff + 0.0625 * zoff) +
+      press_NWB * (0.046875 + 0.0625 * xoff - 0.1875 * yoff + 0.1875 * zoff) +
+      press_SEB * (0.046875 - 0.1875 * xoff + 0.0625 * yoff + 0.1875 * zoff) +
+      press_SWB * (0.140625 + 0.1875 * xoff + 0.1875 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position SET 0.25, -0.25, 0.25
+LBMReal D3Q27IncompressibleOffsetInterpolationProcessor::calcPressTSE()
+{
+   return   press_SET * (0.421875 - 0.5625 * xoff + 0.5625 * yoff - 0.5625 * zoff) +
+      press_NET * (0.140625 - 0.1875 * xoff - 0.5625 * yoff - 0.1875 * zoff) +
+      press_SWT * (0.140625 + 0.5625 * xoff + 0.1875 * yoff - 0.1875 * zoff) +
+      press_NWT * (0.046875 + 0.1875 * xoff - 0.1875 * yoff - 0.0625 * zoff) +
+      press_NWB * (0.015625 + 0.0625 * xoff - 0.0625 * yoff + 0.0625 * zoff) +
+      press_NEB * (0.046875 - 0.0625 * xoff - 0.1875 * yoff + 0.1875 * zoff) +
+      press_SWB * (0.046875 + 0.1875 * xoff + 0.0625 * yoff + 0.1875 * zoff) +
+      press_SEB * (0.140625 - 0.1875 * xoff + 0.1875 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position SEB 0.25, -0.25, -0.25
+LBMReal D3Q27IncompressibleOffsetInterpolationProcessor::calcPressBSE()
+{
+   return   press_SET * (0.140625 - 0.1875 * xoff + 0.1875 * yoff - 0.5625 * zoff) +
+      press_NET * (0.046875 - 0.0625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
+      press_SWT * (0.046875 + 0.1875 * xoff + 0.0625 * yoff - 0.1875 * zoff) +
+      press_NWT * (0.015625 + 0.0625 * xoff - 0.0625 * yoff - 0.0625 * zoff) +
+      press_NWB * (0.046875 + 0.1875 * xoff - 0.1875 * yoff + 0.0625 * zoff) +
+      press_NEB * (0.140625 - 0.1875 * xoff - 0.5625 * yoff + 0.1875 * zoff) +
+      press_SWB * (0.140625 + 0.5625 * xoff + 0.1875 * yoff + 0.1875 * zoff) +
+      press_SEB * (0.421875 - 0.5625 * xoff + 0.5625 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position NWB -0.25, 0.25, -0.25
+LBMReal D3Q27IncompressibleOffsetInterpolationProcessor::calcPressBNW()
+{
+   return   press_NWT * (0.140625 + 0.1875 * xoff - 0.1875 * yoff - 0.5625 * zoff) +
+      press_NET * (0.046875 - 0.1875 * xoff - 0.0625 * yoff - 0.1875 * zoff) +
+      press_SWT * (0.046875 + 0.0625 * xoff + 0.1875 * yoff - 0.1875 * zoff) +
+      press_SET * (0.015625 - 0.0625 * xoff + 0.0625 * yoff - 0.0625 * zoff) +
+      press_SEB * (0.046875 - 0.1875 * xoff + 0.1875 * yoff + 0.0625 * zoff) +
+      press_NEB * (0.140625 - 0.5625 * xoff - 0.1875 * yoff + 0.1875 * zoff) +
+      press_SWB * (0.140625 + 0.1875 * xoff + 0.5625 * yoff + 0.1875 * zoff) +
+      press_NWB * (0.421875 + 0.5625 * xoff - 0.5625 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position NWT -0.25, 0.25, 0.25
+LBMReal D3Q27IncompressibleOffsetInterpolationProcessor::calcPressTNW()
+{
+   return   press_NWT * (0.421875 + 0.5625 * xoff - 0.5625 * yoff - 0.5625 * zoff) +
+      press_NET * (0.140625 - 0.5625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
+      press_SWT * (0.140625 + 0.1875 * xoff + 0.5625 * yoff - 0.1875 * zoff) +
+      press_SET * (0.046875 - 0.1875 * xoff + 0.1875 * yoff - 0.0625 * zoff) +
+      press_SEB * (0.015625 - 0.0625 * xoff + 0.0625 * yoff + 0.0625 * zoff) +
+      press_NEB * (0.046875 - 0.1875 * xoff - 0.0625 * yoff + 0.1875 * zoff) +
+      press_SWB * (0.046875 + 0.0625 * xoff + 0.1875 * yoff + 0.1875 * zoff) +
+      press_NWB * (0.140625 + 0.1875 * xoff - 0.1875 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position NET 0.25, 0.25, 0.25
+LBMReal D3Q27IncompressibleOffsetInterpolationProcessor::calcPressTNE()
+{
+   return   press_NET * (0.421875 - 0.5625 * xoff - 0.5625 * yoff - 0.5625 * zoff) +
+      press_NWT * (0.140625 + 0.5625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
+      press_SET * (0.140625 - 0.1875 * xoff + 0.5625 * yoff - 0.1875 * zoff) +
+      press_SWT * (0.046875 + 0.1875 * xoff + 0.1875 * yoff - 0.0625 * zoff) +
+      press_SWB * (0.015625 + 0.0625 * xoff + 0.0625 * yoff + 0.0625 * zoff) +
+      press_NWB * (0.046875 + 0.1875 * xoff - 0.0625 * yoff + 0.1875 * zoff) +
+      press_SEB * (0.046875 - 0.0625 * xoff + 0.1875 * yoff + 0.1875 * zoff) +
+      press_NEB * (0.140625 - 0.1875 * xoff - 0.1875 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position NEB 0.25, 0.25, -0.25
+LBMReal D3Q27IncompressibleOffsetInterpolationProcessor::calcPressBNE()
+{
+   return   press_NET * (0.140625 - 0.1875 * xoff - 0.1875 * yoff - 0.5625 * zoff) +
+      press_NWT * (0.046875 + 0.1875 * xoff - 0.0625 * yoff - 0.1875 * zoff) +
+      press_SET * (0.046875 - 0.0625 * xoff + 0.1875 * yoff - 0.1875 * zoff) +
+      press_SWT * (0.015625 + 0.0625 * xoff + 0.0625 * yoff - 0.0625 * zoff) +
+      press_SWB * (0.046875 + 0.1875 * xoff + 0.1875 * yoff + 0.0625 * zoff) +
+      press_NWB * (0.140625 + 0.5625 * xoff - 0.1875 * yoff + 0.1875 * zoff) +
+      press_SEB * (0.140625 - 0.1875 * xoff + 0.5625 * yoff + 0.1875 * zoff) +
+      press_NEB * (0.421875 - 0.5625 * xoff - 0.5625 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position C 0.0, 0.0, 0.0
+void D3Q27IncompressibleOffsetInterpolationProcessor::calcInterpolatedNodeFC(LBMReal* f, LBMReal omega)
+{
+   using namespace D3Q27System;
+
+   LBMReal press  =  press_NET * (0.125 - 0.25 * xoff - 0.25 * yoff - 0.25 * zoff) +
+      press_NWT * (0.125 + 0.25 * xoff - 0.25 * yoff - 0.25 * zoff) +
+      press_SET * (0.125 - 0.25 * xoff + 0.25 * yoff - 0.25 * zoff) +
+      press_SWT * (0.125 + 0.25 * xoff + 0.25 * yoff - 0.25 * zoff) +
+      press_NEB * (0.125 - 0.25 * xoff - 0.25 * yoff + 0.25 * zoff) +
+      press_NWB * (0.125 + 0.25 * xoff - 0.25 * yoff + 0.25 * zoff) +
+      press_SEB * (0.125 - 0.25 * xoff + 0.25 * yoff + 0.25 * zoff) +
+      press_SWB * (0.125 + 0.25 * xoff + 0.25 * yoff + 0.25 * zoff);
+   LBMReal vx1  = a0;
+   LBMReal vx2  = b0;
+   LBMReal vx3  = c0;
+
+   LBMReal rho = press ;//+ (ax+by+cz)/3.;
+
+   //////////////////////////////////////////////////////////////////////////
+   //DRAFT
+   //vx1 -= forcingC*0.5;
+   //////////////////////////////////////////////////////////////////////////
+
+   LBMReal feq[ENDF+1];
+   D3Q27System::calcIncompFeq(feq,rho,vx1,vx2,vx3);
+
+   LBMReal eps_new = 2.;
+   LBMReal o  = omega;
+   LBMReal op = 1.;
+
+   //f_E    = eps_new *((5.*ax*o + 5.*by*o + 5.*cz*o - 8.*ax*op + 4.*by*op + 4.*cz*op)/(54.*o*op));
+   //f_N    = f_E + eps_new *((2.*(ax - by))/(9.*o));
+   //f_T    = f_E + eps_new *((2.*(ax - cz))/(9.*o));
+   //f_NE   = eps_new *(-(5.*cz*o + 3.*(ay + bx)*op - 2.*cz*op + ax*(5.*o + op) + by*(5.*o + op))/(54.*o*op));
+   //f_SE   = f_NE + eps_new *((  ay + bx )/(9.*o));
+   //f_TE   = eps_new *(-(5.*cz*o + by*(5.*o - 2.*op) + 3.*(az + cx)*op + cz*op + ax*(5.*o + op))/(54.*o*op));
+   //f_BE   = f_TE + eps_new *((  az + cx )/(9.*o));
+   //f_TN   = eps_new *(-(5.*ax*o + 5.*by*o + 5.*cz*o - 2.*ax*op + by*op + 3.*bz*op + 3.*cy*op + cz*op)/(54.*o*op));
+   //f_BN   = f_TN + eps_new *((  bz + cy )/(9.*o));
+   //f_ZERO = eps_new *((5.*(ax + by + cz))/(9.*op));
+   //f_TNE  = eps_new *(-(ay + az + bx + bz + cx + cy)/(72.*o));
+   //f_TSW  = - eps_new *((ay + bx)/(36.*o)) - f_TNE;
+   //f_TSE  = - eps_new *((az + cx)/(36.*o)) - f_TNE;
+   //f_TNW  = - eps_new *((bz + cy)/(36.*o)) - f_TNE;
+
+   f_E = eps_new*((2*(-2*ax + by + cz-kxxMzzAverage-kxxMyyAverage))/(27.*o));
+   f_N = eps_new*((2*(ax - 2*by + cz+2*kxxMyyAverage-kxxMzzAverage))/(27.*o));
+   f_T = eps_new*((2*(ax + by - 2*cz-kxxMyyAverage+2*kxxMzzAverage))/(27.*o));
+   f_NE = eps_new*(-(ax + 3*ay + 3*bx + by - 2*cz+2*kxxMyyAverage-kxxMyyAverage+3*kxyAverage)/(54.*o));
+   f_SE = eps_new*(-(ax - 3*ay - 3*bx + by - 2*cz+2*kxxMyyAverage-kxxMyyAverage-3*kxyAverage)/(54.*o));
+   f_TE = eps_new*(-(ax + 3*az - 2*by + 3*cx + cz+2*kxxMyyAverage-kxxMzzAverage+3*kxzAverage)/(54.*o));
+   f_BE = eps_new*(-(ax - 3*az - 2*by - 3*cx + cz+2*kxxMyyAverage-kxxMzzAverage-3*kxzAverage)/(54.*o));
+   f_TN = eps_new*(-(-2*ax + by + 3*bz + 3*cy + cz-kxxMyyAverage-kxxMzzAverage+3*kyzAverage)/(54.*o));
+   f_BN = eps_new*(-(-2*ax + by - 3*bz - 3*cy + cz-kxxMyyAverage-kxxMzzAverage-3*kyzAverage)/(54.*o));
+   f_ZERO = 0.;
+   f_TNE = eps_new*(-(ay + az + bx + bz + cx + cy+kxyAverage+kxzAverage+kyzAverage)/(72.*o));
+   f_TSW = eps_new*((-ay + az - bx + bz + cx + cy-kxyAverage+kxzAverage+kyzAverage)/(72.*o));
+   f_TSE = eps_new*((ay - az + bx + bz - cx + cy+kxyAverage-kxzAverage+kyzAverage)/(72.*o));
+   f_TNW = eps_new*((ay + az + bx - bz + cx - cy+kxyAverage+kxzAverage-kyzAverage)/(72.*o));
+
+   f[E]    = f_E    + feq[E];
+   f[W]    = f_E    + feq[W];
+   f[N]    = f_N    + feq[N];
+   f[S]    = f_N    + feq[S];
+   f[T]    = f_T    + feq[T];
+   f[B]    = f_T    + feq[B];
+   f[NE]   = f_NE   + feq[NE];
+   f[SW]   = f_NE   + feq[SW];
+   f[SE]   = f_SE   + feq[SE];
+   f[NW]   = f_SE   + feq[NW];
+   f[TE]   = f_TE   + feq[TE];
+   f[BW]   = f_TE   + feq[BW];
+   f[BE]   = f_BE   + feq[BE];
+   f[TW]   = f_BE   + feq[TW];
+   f[TN]   = f_TN   + feq[TN];
+   f[BS]   = f_TN   + feq[BS];
+   f[BN]   = f_BN   + feq[BN];
+   f[TS]   = f_BN   + feq[TS];
+   f[TNE]  = f_TNE  + feq[TNE];
+   f[TNW]  = f_TNW  + feq[TNW];
+   f[TSE]  = f_TSE  + feq[TSE];
+   f[TSW]  = f_TSW  + feq[TSW];
+   f[BNE]  = f_TSW  + feq[BNE];
+   f[BNW]  = f_TSE  + feq[BNW];
+   f[BSE]  = f_TNW  + feq[BSE];
+   f[BSW]  = f_TNE  + feq[BSW];
+   f[ZERO] = f_ZERO + feq[ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::calcInterpolatedVelocity(LBMReal x, LBMReal y, LBMReal z, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3)
+{
+	vx1  = a0 + ax*x + ay*y + az*z + axx*x*x + ayy*y*y + azz*z*z + axy*x*y + axz*x*z + ayz*y*z+axyz*x*y*z;
+	vx2  = b0 + bx*x + by*y + bz*z + bxx*x*x + byy*y*y + bzz*z*z + bxy*x*y + bxz*x*z + byz*y*z+bxyz*x*y*z;
+	vx3  = c0 + cx*x + cy*y + cz*z + cxx*x*x + cyy*y*y + czz*z*z + cxy*x*y + cxz*x*z + cyz*y*z+cxyz*x*y*z;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IncompressibleOffsetInterpolationProcessor::calcInterpolatedShearStress(LBMReal x, LBMReal y, LBMReal z,LBMReal& tauxx, LBMReal& tauyy, LBMReal& tauzz,LBMReal& tauxy, LBMReal& tauxz, LBMReal& tauyz)
+{
+	tauxx=ax+2*axx*x+axy*y+axz*z+axyz*y*z;
+	tauyy=by+2*byy*y+bxy*x+byz*z+bxyz*x*z;
+	tauzz=cz+2*czz*z+cxz*x+cyz*y+cxyz*x*y;
+	tauxy=0.5*((ay+2.0*ayy*y+axy*x+ayz*z+axyz*x*z)+(bx+2.0*bxx*x+bxy*y+bxz*z+bxyz*y*z));
+	tauxz=0.5*((az+2.0*azz*z+axz*x+ayz*y+axyz*x*y)+(cx+2.0*cxx*x+cxy*y+cxz*z+cxyz*y*z));
+	tauyz=0.5*((bz+2.0*bzz*z+bxz*x+byz*y+bxyz*x*y)+(cy+2.0*cyy*y+cxy*x+cyz*z+cxyz*x*z));
+}
diff --git a/source/VirtualFluidsCore/LBM/D3Q27IncompressibleOffsetInterpolationProcessor.h b/source/VirtualFluidsCore/LBM/D3Q27IncompressibleOffsetInterpolationProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb2df0b667446f638537497b7668f3216d1ee6c5
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27IncompressibleOffsetInterpolationProcessor.h
@@ -0,0 +1,77 @@
+#ifndef D3Q27IncompressibleOffsetInterpolationProcessor_H_
+#define D3Q27IncompressibleOffsetInterpolationProcessor_H_
+
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27System.h"
+
+//////////////////////////////////////////////////////////////////////////
+//it works only for cascaded LBM
+//super compact interpolation method by Martin Geier
+//////////////////////////////////////////////////////////////////////////
+
+class D3Q27IncompressibleOffsetInterpolationProcessor;
+typedef boost::shared_ptr<D3Q27IncompressibleOffsetInterpolationProcessor> D3Q27IncompressibleOffsetInterpolationProcessorPtr;
+
+class D3Q27IncompressibleOffsetInterpolationProcessor : public D3Q27InterpolationProcessor
+{
+public:
+   D3Q27IncompressibleOffsetInterpolationProcessor();
+   D3Q27IncompressibleOffsetInterpolationProcessor(LBMReal omegaC, LBMReal omegaF);
+   virtual ~D3Q27IncompressibleOffsetInterpolationProcessor();
+   D3Q27InterpolationProcessorPtr clone();
+   void setOmegas(LBMReal omegaC, LBMReal omegaF);
+   void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF);
+   void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, LBMReal xoff, LBMReal yoff, LBMReal zoff);
+   void interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC); 
+   void interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC, LBMReal xoff, LBMReal yoff, LBMReal zoff); 
+   //LBMReal forcingC, forcingF;
+protected:   
+private:
+   LBMReal omegaC, omegaF;
+   LBMReal a0, ax, ay, az, axx, ayy, azz, axy, axz, ayz, b0, bx, by, bz, bxx, byy, bzz, bxy, bxz, byz, c0, cx, cy, cz, cxx, cyy, czz, cxy, cxz, cyz, axyz, bxyz, cxyz;
+   LBMReal xoff,    yoff,    zoff;
+   LBMReal xoff_sq, yoff_sq, zoff_sq;
+   LBMReal press_SWT, press_NWT, press_NET, press_SET, press_SWB, press_NWB, press_NEB, press_SEB;
+
+   LBMReal  f_E,  f_N,  f_T,  f_NE,  f_SE,  f_BE,  f_TE,  f_TN,  f_BN,  f_TNE,  f_TNW,  f_TSE,  f_TSW,  f_ZERO;
+   LBMReal  x_E,  x_N,  x_T,  x_NE,  x_SE,  x_BE,  x_TE,  x_TN,  x_BN,  x_TNE,  x_TNW,  x_TSE,  x_TSW,  x_ZERO;
+   LBMReal  y_E,  y_N,  y_T,  y_NE,  y_SE,  y_BE,  y_TE,  y_TN,  y_BN,  y_TNE,  y_TNW,  y_TSE,  y_TSW,  y_ZERO;
+   LBMReal  z_E,  z_N,  z_T,  z_NE,  z_SE,  z_BE,  z_TE,  z_TN,  z_BN,  z_TNE,  z_TNW,  z_TSE,  z_TSW,  z_ZERO;
+   LBMReal xy_E, xy_N, xy_T, xy_NE, xy_SE, xy_BE, xy_TE, xy_TN, xy_BN, xy_TNE, xy_TNW, xy_TSE, xy_TSW/*, xy_ZERO*/;
+   LBMReal xz_E, xz_N, xz_T, xz_NE, xz_SE, xz_BE, xz_TE, xz_TN, xz_BN, xz_TNE, xz_TNW, xz_TSE, xz_TSW/*, xz_ZERO*/;
+   LBMReal yz_E, yz_N, yz_T, yz_NE, yz_SE, yz_BE, yz_TE, yz_TN, yz_BN, yz_TNE, yz_TNW, yz_TSE, yz_TSW/*, yz_ZERO*/;
+
+   LBMReal kxyAverage, kyzAverage, kxzAverage, kxxMyyAverage, kxxMzzAverage; 
+
+   LBMReal a,b,c;
+
+   void setOffsets(LBMReal xoff, LBMReal yoff, LBMReal zoff);
+   void calcMoments(const LBMReal* const f, LBMReal omega, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3, 
+      LBMReal& kxy, LBMReal& kyz, LBMReal& kxz, LBMReal& kxxMyy, LBMReal& kxxMzz);
+   void calcInterpolatedCoefficiets(const D3Q27ICell& icell, LBMReal omega, LBMReal eps_new);
+   void calcInterpolatedNode(LBMReal* f, LBMReal omega, LBMReal x, LBMReal y, LBMReal z, LBMReal press, LBMReal xs, LBMReal ys, LBMReal zs);
+   LBMReal calcPressBSW();
+   LBMReal calcPressTSW();
+   LBMReal calcPressTSE();
+   LBMReal calcPressBSE();
+   LBMReal calcPressBNW();
+   LBMReal calcPressTNW();
+   LBMReal calcPressTNE();
+   LBMReal calcPressBNE();
+   void calcInterpolatedNodeFC(LBMReal* f, LBMReal omega);
+   void calcInterpolatedVelocity(LBMReal x, LBMReal y, LBMReal z,LBMReal& vx1, LBMReal& vx2, LBMReal& vx3);
+   void calcInterpolatedShearStress(LBMReal x, LBMReal y, LBMReal z,LBMReal& tauxx, LBMReal& tauyy, LBMReal& tauzz,LBMReal& tauxy, LBMReal& tauxz, LBMReal& tauyz);
+};
+
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27IncompressibleOffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
+{
+   this->interpolateCoarseToFine(icellC, icellF, 0.0, 0.0, 0.0);
+}
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27IncompressibleOffsetInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC)
+{
+   this->interpolateFineToCoarse(icellF, icellC, 0.0, 0.0, 0.0);
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/D3Q27IntegrateValuesHelper.cpp b/source/VirtualFluidsCore/LBM/D3Q27IntegrateValuesHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2fa4fe7d69988fa13a543863a616045bf3d5fd24
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27IntegrateValuesHelper.cpp
@@ -0,0 +1,293 @@
+#include "D3Q27IntegrateValuesHelper.h"
+
+#include <boost/foreach.hpp>
+#include <numerics/geometry3d/GbCuboid3D.h>
+#include <vector>
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+
+using namespace std;
+//////////////////////////////////////////////////////////////////////////
+D3Q27IntegrateValuesHelper::D3Q27IntegrateValuesHelper(Grid3DPtr grid, CommunicatorPtr comm,
+   double minX1, double minX2,
+   double minX3, double maxX1,
+   double maxX2, double maxX3) :
+
+   grid(grid),
+   comm(comm),
+   sVx1(0.0), sVx2(0.0), sVx3(0.0), sRho(0.0), sCellVolume(0.0),
+   numberOfFluidsNodes(0),
+   numberOfSolidNodes(0)
+{
+   boundingBox =  GbCuboid3DPtr(new GbCuboid3D(minX1, minX2, minX3, maxX1, maxX2, maxX3));
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27IntegrateValuesHelper::~D3Q27IntegrateValuesHelper()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IntegrateValuesHelper::init()
+{
+   double orgX1, orgX2, orgX3;
+   int gridRank = grid->getRank();
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   double numSolids = 0.0;
+   double numFluids = 0.0;
+   for (int level = minInitLevel; level<=maxInitLevel; level++)
+   {
+      vector<Block3DPtr> blockVector;
+      grid->getBlocks(level, gridRank, blockVector);
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         CalcNodes cn;
+         cn.block = block;
+         //Koords bestimmen
+         UbTupleDouble3 org = grid->getBlockWorldCoordinates(block);
+
+         orgX1 = val<1>(org);
+         orgX2 = val<2>(org);
+         orgX3 = val<3>(org);
+
+         LBMKernelETD3Q27Ptr kernel = boost::dynamic_pointer_cast<LBMKernelETD3Q27>(block->getKernel());
+         BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+         int ghostLayerWitdh = kernel->getGhostLayerWidth();
+         DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+         double internX1, internX2, internX3;
+
+         double         dx       = grid->getDeltaX(block);
+         UbTupleDouble3 orgDelta = grid->getNodeOffset(block);
+
+         for (int ix3=ghostLayerWitdh; ix3<(int)distributions->getNX3()-ghostLayerWitdh; ix3++)
+         {
+            for (int ix2=ghostLayerWitdh; ix2<(int)distributions->getNX2()-ghostLayerWitdh; ix2++)
+            {
+               for (int ix1=ghostLayerWitdh; ix1<(int)distributions->getNX1()-ghostLayerWitdh; ix1++)
+               {
+                  internX1 = orgX1 - val<1>(orgDelta) +ix1 * dx;
+                  internX2 = orgX2 - val<2>(orgDelta) +ix2 * dx;
+                  internX3 = orgX3 - val<3>(orgDelta) +ix3 * dx;
+                  if (boundingBox->isPointInGbObject3D(internX1, internX2, internX3))
+                  {
+                     if (!bcArray.isSolid(ix1, ix2, ix3) && !bcArray.isUndefined(ix1, ix2, ix3))
+                     {
+                        cn.nodes.push_back(UbTupleInt3(ix1, ix2, ix3));
+                        numFluids++;
+                     }
+                     else if (bcArray.isSolid(ix1, ix2, ix3))
+                     {
+                        numSolids++;
+                     }
+                  }
+               }
+            }
+         }
+         if (cn.nodes.size() > 0)
+            cnodes.push_back(cn);
+      }
+   }
+   vector<double> rvalues;
+   vector<double> values;
+   values.push_back(numSolids);
+   values.push_back(numFluids);
+   rvalues = comm->gather(values);
+
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      numberOfSolidNodes = 0.0;
+      numberOfFluidsNodes = 0.0;
+      int rsize = (int)rvalues.size();
+      int vsize = (int)values.size();
+      for (int i = 0; i < rsize; i += vsize)
+      {
+         numberOfSolidNodes += rvalues[i];
+         numberOfFluidsNodes += rvalues[i+1];
+      }
+   }
+
+}
+// calculation conventional rho, velocity and averaged data
+void D3Q27IntegrateValuesHelper::calculateAV()
+{
+   clearData();
+   //Funktionszeiger
+   typedef void(*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/, LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   CalcMacrosFct calcMacros = NULL;
+
+   BOOST_FOREACH(CalcNodes cn, cnodes)
+   {
+      LBMKernel3DPtr kernel = cn.block->getKernel();
+      if (kernel->getCompressible())
+      {
+         calcMacros = &D3Q27System::calcCompMacroscopicValues;
+      }
+      else
+      {
+         calcMacros = &D3Q27System::calcIncompMacroscopicValues;
+      }
+      BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+      int ghostLayerWitdh = kernel->getGhostLayerWidth();
+      AverageValuesArray3DPtr averagedValues = kernel->getDataSet()->getAverageValues();
+
+      BOOST_FOREACH(UbTupleInt3 node, cn.nodes)
+      {
+         double Avx = (*averagedValues)(val<1>(node), val<2>(node), val<3>(node), AvVx);
+         double Avy = (*averagedValues)(val<1>(node), val<2>(node), val<3>(node), AvVy);
+         double Avz = (*averagedValues)(val<1>(node), val<2>(node), val<3>(node), AvVz);
+
+         double Avxx = (*averagedValues)(val<1>(node), val<2>(node), val<3>(node), AvVxx);
+         double Avyy = (*averagedValues)(val<1>(node), val<2>(node), val<3>(node), AvVyy);
+         double Avzz = (*averagedValues)(val<1>(node), val<2>(node), val<3>(node), AvVzz);
+
+         double Avxz = (*averagedValues)(val<1>(node), val<2>(node), val<3>(node), AvVxz);
+         sAvVx1 +=abs(Avx);
+         sAvVx2 +=abs(Avy);
+         sAvVx3 +=abs(Avz);
+
+         sTSx1 += sqrt(Avxx);
+         sTSx2 += sqrt(Avyy);
+         sTSx3 += sqrt(Avzz);
+
+         sTSx1x3 += Avxz;
+         numberOfFluidsNodes++;
+      }
+   }
+   vector<double> values;
+   vector<double> rvalues;
+   values.push_back(sAvVx1);
+   values.push_back(sAvVx2);
+   values.push_back(sAvVx3);
+   values.push_back(sTSx1);
+   values.push_back(sTSx2);
+   values.push_back(sTSx3);
+   values.push_back(sTSx1x3);
+   values.push_back(numberOfFluidsNodes);
+
+   rvalues = comm->gather(values);
+   if (comm->getProcessID() == comm->getRoot())
+   {
+      clearData();
+      for (int i = 0; i < (int)rvalues.size(); i+=8)
+      {
+         sAvVx1 += rvalues[i];
+         sAvVx2 += rvalues[i+1];
+         sAvVx3 += rvalues[i+2];
+         sTSx1 += rvalues[i+3];
+         sTSx2 += rvalues[i+4];
+         sTSx3 += rvalues[i+5];
+         sTSx1x3 += rvalues[i+6];
+         numberOfFluidsNodes += rvalues[i+7];
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IntegrateValuesHelper::calculateMQ()
+{
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal vx1, vx2, vx3, rho;
+   clearData();
+
+   //Funktionszeiger
+   typedef void(*CalcMacrosFct)(const LBMReal* const& /*feq[27]*/, LBMReal& /*(d)rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+
+   CalcMacrosFct calcMacros = NULL;
+
+   BOOST_FOREACH(CalcNodes cn, cnodes)
+   {
+      LBMKernel3DPtr kernel = cn.block->getKernel();
+      LBMReal dx = 1.0 / (LBMReal)(1 << cn.block->getLevel());
+      LBMReal cellVolume = dx*dx*dx;
+
+      if (kernel->getCompressible())
+      {
+         calcMacros = &D3Q27System::calcCompMacroscopicValues;
+      }
+      else
+      {
+         calcMacros = &D3Q27System::calcIncompMacroscopicValues;
+      }
+
+      BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+      int ghostLayerWitdh = kernel->getGhostLayerWidth();
+      DistributionArray3DPtr distributions = kernel->getDataSet()->getFdistributions();
+      BOOST_FOREACH(UbTupleInt3 node, cn.nodes)
+      {
+         distributions->getDistribution(f, val<1>(node), val<2>(node), val<3>(node));
+         calcMacros(f, rho, vx1, vx2, vx3);
+         //press = D3Q27System::calcPress(f,rho,vx1,vx2,vx3);
+         sRho += rho*cellVolume;
+         sVx1 += vx1*cellVolume;
+         sVx2 += vx2*cellVolume;
+         sVx3 += vx3*cellVolume;
+         sCellVolume+=cellVolume;
+         //sPress += press*area;
+         //sVm += (sqrt(vx1*vx1 + vx2*vx2 + vx3*vx3)*area);
+      }
+   }
+   vector<double> values;
+   vector<double> rvalues;
+   values.push_back(sRho);
+   values.push_back(sVx1);
+   values.push_back(sVx2);
+   values.push_back(sVx3);
+   values.push_back(sCellVolume);
+   //values.push_back(sPress);
+   //values.push_back(sVm);
+
+   comm->allGather(values, rvalues);
+   clearData();
+   int rsize = (int)rvalues.size();
+   int vsize = (int)values.size();
+   for (int i = 0; i < rsize; i+=vsize)
+   {
+      sRho += rvalues[i];
+      sVx1 += rvalues[i+1];
+      sVx2 += rvalues[i+2];
+      sVx3 += rvalues[i+3];
+      sCellVolume += rvalues[i+4];
+      //sPress += rvalues[i+5];
+      //sVm += rvalues[i+6];
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27IntegrateValuesHelper::clearData()
+{
+   sRho = 0.0;
+   sVx1 = 0.0;
+   sVx2 = 0.0;
+   sVx3 = 0.0;
+   sCellVolume= 0.0;
+   //sVm = 0.0;
+   //sPress = 0.0;
+   //numberOfFluidsNodes = 0.0;
+   sAvVx1 = 0.0;
+   sAvVx2 = 0.0;
+   sAvVx3 = 0.0;
+   sTSx1 = 0.0;
+   sTSx2 = 0.0;
+   sTSx3 = 0.0;
+   sTSx1x3 = 0.0;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMReal D3Q27IntegrateValuesHelper::getNumberOfFluidsNodes()
+{
+   return this->numberOfFluidsNodes;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMReal D3Q27IntegrateValuesHelper::getNumberOfSolidNodes()
+{
+   return this->numberOfSolidNodes;
+}
+//////////////////////////////////////////////////////////////////////////
+GbCuboid3DPtr D3Q27IntegrateValuesHelper::getBoundingBox()
+{
+   return this->boundingBox;
+}
+//////////////////////////////////////////////////////////////////////////
+std::vector<CalcNodes> D3Q27IntegrateValuesHelper::getCNodes()
+{
+   return cnodes;
+}
diff --git a/source/VirtualFluidsCore/LBM/D3Q27IntegrateValuesHelper.h b/source/VirtualFluidsCore/LBM/D3Q27IntegrateValuesHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..bee613655c3ed4bd37e28d9a578bcd9154a9f72f
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27IntegrateValuesHelper.h
@@ -0,0 +1,63 @@
+#ifndef D3Q27INTEGRATEVALUESHELPER_H
+#define D3Q27INTEGRATEVALUESHELPER_H
+
+#include "Grid3D.h"
+#include "D3Q27System.h"
+#include "Communicator.h"
+#include "GbCuboid3D.h"
+
+struct CalcNodes 
+{
+	Block3DPtr block;
+	std::vector<UbTupleInt3> nodes;
+};
+
+class D3Q27IntegrateValuesHelper;
+typedef boost::shared_ptr<D3Q27IntegrateValuesHelper> D3Q27IntegrateValuesHelperPtr;
+
+class D3Q27IntegrateValuesHelper
+{
+public:
+	D3Q27IntegrateValuesHelper(Grid3DPtr grid, CommunicatorPtr comm, 
+		double minX1, double minX2, double minX3, 
+		double  maxX1, double maxX2, double maxX3);
+	virtual ~D3Q27IntegrateValuesHelper();
+
+	void calculateMQ();
+	void calculateAV();
+	void clearData();
+
+	LBMReal getRho() {return sRho;}
+	LBMReal getVx1() {return sVx1;} 
+	LBMReal getVx2() {return sVx2;}
+	LBMReal getVx3() {return sVx3;}
+   LBMReal getCellsVolume() { return sCellVolume; }
+ //  LBMReal getVm() { return sVm; }
+	//LBMReal getPress() {return sPress;}
+	LBMReal getAvVx1(){return sAvVx1;}
+	LBMReal getAvVx2(){return sAvVx2;}
+	LBMReal getAvVx3(){return sAvVx3;}
+	LBMReal getTSx1(){return sTSx1;}
+	LBMReal getTSx2(){return sTSx2;}
+	LBMReal getTSx3(){return sTSx3;}
+	LBMReal getTSx1x3(){return sTSx1x3;}
+	LBMReal getNumberOfFluidsNodes();
+	LBMReal getNumberOfSolidNodes();
+	GbCuboid3DPtr getBoundingBox();
+   std::vector<CalcNodes> getCNodes();
+
+protected:
+private:
+	void init();
+	Grid3DPtr grid;
+   LBMReal sVx1, sVx2, sVx3, sRho, sCellVolume;// sPress, sVm;
+	LBMReal numberOfFluidsNodes, numberOfSolidNodes;
+	LBMReal sAvVx1, sAvVx2, sAvVx3, sTSx1, sTSx2, sTSx3, sTSx1x3;
+	std::vector<CalcNodes> cnodes;
+	GbCuboid3DPtr boundingBox;
+	CommunicatorPtr comm;
+	enum Values{AvVx = 0, AvVy = 1, AvVz = 2, AvVxx = 3, AvVyy = 4, AvVzz = 5, AvVxy = 6, AvVyz = 7, AvVxz = 8};
+
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/D3Q27InterpolationHelper.cpp b/source/VirtualFluidsCore/LBM/D3Q27InterpolationHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..643781c47dbd986ca844c985ca0862796f4d2979
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27InterpolationHelper.cpp
@@ -0,0 +1,39 @@
+#include "D3Q27InterpolationHelper.h"
+
+
+
+D3Q27InterpolationHelper::D3Q27InterpolationHelper(D3Q27InterpolationProcessorPtr iProcessor) : iProcessor(iProcessor)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27InterpolationHelper::~D3Q27InterpolationHelper()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27InterpolationHelper::interpolate8to1( D3Q27ICell& icellF, LBMReal* icellC, double x1, double x2, double x3, LBMReal omega )
+{
+   iProcessor->calcInterpolatedCoefficiets(icellF, omega, 1.0);
+   iProcessor->calcInterpolatedNodeFC(icellC, omega);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27InterpolationHelper::interpolate8to1WithVelocity( D3Q27ICell& icellF, double x1, double x2, double x3, LBMReal omega, LBMReal &vx1, LBMReal &vx2, LBMReal &vx3 )
+{
+   iProcessor->setOffsets(0.0, 0.0, 0.0);
+   iProcessor->calcInterpolatedCoefficiets(icellF, omega, 0.0);	
+   iProcessor->calcInterpolatedVelocity(x1, x2, x3, vx1, vx2, vx3);	
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27InterpolationHelper::interpolate8to1WithVelocityWithShearStress( D3Q27ICell& icellF, double x1, double x2, double x3, LBMReal omega, 
+                                                                    LBMReal &vx1, LBMReal &vx2, LBMReal &vx3, 
+                                                                    LBMReal &tauxx, LBMReal &tauyy, LBMReal &tauzz,LBMReal &tauxy, LBMReal &tauxz, LBMReal &tauyz )
+{
+   iProcessor->setOffsets(0.0, 0.0, 0.0);
+   iProcessor->calcInterpolatedCoefficiets(icellF, omega, 0.0);	
+   iProcessor->calcInterpolatedVelocity(x1, x2, x3, vx1, vx2, vx3);	
+   iProcessor->calcInterpolatedShearStress(x1,x2,x3,tauxx,tauyy,tauzz,tauxy,tauxz,tauyz);
+}
+
+//////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/LBM/D3Q27InterpolationHelper.h b/source/VirtualFluidsCore/LBM/D3Q27InterpolationHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..113810c19f60639556ef9b3d027e25f3d8e4176f
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27InterpolationHelper.h
@@ -0,0 +1,25 @@
+#ifndef D3Q27InterpolationHelper_H_
+#define D3Q27InterpolationHelper_H_
+
+#include "D3Q27InterpolationProcessor.h"
+
+class D3Q27InterpolationHelper;
+typedef boost::shared_ptr<D3Q27InterpolationHelper> D3Q27InterpolationHelperPtr;
+
+class D3Q27InterpolationHelper
+{
+public:
+   D3Q27InterpolationHelper(D3Q27InterpolationProcessorPtr iProcessor);
+   ~D3Q27InterpolationHelper();
+   void interpolate8to1(D3Q27ICell& icellF, LBMReal* icellC, double x1, double x2, double x3, LBMReal omega);
+   void interpolate8to1WithVelocity(D3Q27ICell& icellF, double x1, double x2, double x3, LBMReal omega, LBMReal &vx1, LBMReal &vx2, LBMReal &vx3);
+   void interpolate8to1WithVelocityWithShearStress(D3Q27ICell& icellF, double x1, double x2, double x3, LBMReal omega, 
+                                             LBMReal &vx1, LBMReal &vx2, LBMReal &vx3, 
+                                             LBMReal &tauxx, LBMReal &tauyy, LBMReal &tauzz,LBMReal &tauxy, LBMReal &tauxz, LBMReal &tauyz);
+protected:
+private:
+   D3Q27InterpolationProcessorPtr iProcessor;
+};
+
+#endif
+
diff --git a/source/VirtualFluidsCore/LBM/D3Q27InterpolationProcessor.cpp b/source/VirtualFluidsCore/LBM/D3Q27InterpolationProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a6f02f49e7998f87a1f25bf7f9b544354e5db49e
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27InterpolationProcessor.cpp
@@ -0,0 +1,297 @@
+#include "D3Q27InterpolationProcessor.h"
+#include "StringUtil.hpp"
+
+
+//////////////////////////////////////////////////////////////////////////
+D3Q27InterpolationProcessor::D3Q27InterpolationProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27InterpolationProcessor::~D3Q27InterpolationProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27InterpolationProcessor::readICell(DistributionArray3DPtr f, D3Q27ICell& icell, int x1, int x2, int x3) 
+{
+   f->getDistribution(icell.BSW, x1, x2, x3);
+   f->getDistribution(icell.BSE, x1+1, x2, x3);
+   f->getDistribution(icell.BNW, x1, x2+1, x3);
+   f->getDistribution(icell.BNE, x1+1, x2+1, x3);
+   f->getDistribution(icell.TSW, x1, x2, x3+1);
+   f->getDistribution(icell.TSE, x1+1, x2, x3+1);
+   f->getDistribution(icell.TNW, x1, x2+1, x3+1);
+   f->getDistribution(icell.TNE, x1+1, x2+1, x3+1);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27InterpolationProcessor::writeICell(DistributionArray3DPtr f, const D3Q27ICell& icell, int x1, int x2, int x3) 
+{
+   f->setDistributionInv(icell.BSW, x1, x2, x3);
+   f->setDistributionInv(icell.BSE, x1+1, x2, x3);
+   f->setDistributionInv(icell.BNW, x1, x2+1, x3);
+   f->setDistributionInv(icell.BNE, x1+1, x2+1, x3);
+   f->setDistributionInv(icell.TSW, x1, x2, x3+1);
+   f->setDistributionInv(icell.TSE, x1+1, x2, x3+1);
+   f->setDistributionInv(icell.TNW, x1, x2+1, x3+1);
+   f->setDistributionInv(icell.TNE, x1+1, x2+1, x3+1);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27InterpolationProcessor::writeINode(DistributionArray3DPtr f, const LBMReal* const inode, int x1, int x2, int x3) 
+{
+   f->setDistributionInv(inode, x1, x2, x3);
+}
+//////////////////////////////////////////////////////////////////////////
+bool D3Q27InterpolationProcessor::iCellHasSolid(const BCArray3D<D3Q27BoundaryCondition>& bcArray, int x1, int x2, int x3) 
+{
+   for (int ix3 = x3; ix3 <= x3 + 1; ix3++)
+      for(int ix2 = x2; ix2 <= x2 + 1; ix2++)
+         for(int ix1 = x1; ix1 <= x1 + 1; ix1++)
+         {
+            if(bcArray.isSolid(ix1, ix2, ix3))
+               return true;
+         }
+   return false;  
+}
+//////////////////////////////////////////////////////////////////////////
+bool D3Q27InterpolationProcessor::findNeighborICell(const BCArray3D<D3Q27BoundaryCondition>& bcArray, DistributionArray3DPtr f, 
+                                                    D3Q27ICell& icell, int maxX1, int maxX2, int maxX3, 
+                                                    int x1, int x2, int x3, LBMReal& xoff, LBMReal& yoff, LBMReal& zoff) 
+{
+   m_maxX1 = maxX1;
+   m_maxX2 = maxX2;
+   m_maxX3 = maxX3;
+
+   //GoWest
+   if(inRange(x1-1,x2,x3) && !iCellHasSolid(bcArray, x1-1,x2,x3))
+   {
+      readICell(f,icell,x1-1,x2,x3);
+      xoff = 1;
+      yoff = 0;
+      zoff = 0;
+   }
+   //GoEast
+   else if(inRange(x1+2,x2,x3) && !iCellHasSolid(bcArray, x1+1,x2,x3)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2,x3);
+      xoff = -1;
+      yoff = 0;
+      zoff = 0;
+   }
+   //GoSouth
+   else if(inRange(x1,x2-1,x3) && !iCellHasSolid(bcArray, x1,x2-1,x3)) 
+   {
+      readICell(f,icell,x1,x2-1,x3);
+      xoff = 0;
+      yoff = 1;
+      zoff = 0;
+   }
+   //GoNorth
+   else if(inRange(x1,x2+2,x3) && !iCellHasSolid(bcArray, x1,x2+1,x3)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1,x2+1,x3);
+      xoff = 0;
+      yoff = -1;
+      zoff = 0;
+   }
+   //GoBottom
+   else if(inRange(x1,x2,x3-1) && !iCellHasSolid(bcArray, x1,x2,x3-1)) 
+   {
+      readICell(f,icell,x1,x2,x3-1);
+      xoff = 0;
+      yoff = 0;
+      zoff = 1;
+   }
+   //GoTop
+   else if(inRange(x1,x2,x3+2) && !iCellHasSolid(bcArray, x1,x2,x3+1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1,x2,x3+1);
+      xoff = 0;
+      yoff = 0;
+      zoff = -1;
+   }
+   //GoNW
+   else if(inRange(x1-1,x2+2,x3) && !iCellHasSolid(bcArray, x1-1,x2+1,x3)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1-1,x2+1,x3);
+      xoff = 1;
+      yoff = -1;
+      zoff = 0;
+   }
+   //GoNE
+   else if(inRange(x1+2,x2+2,x3) && !iCellHasSolid(bcArray, x1+1,x2+1,x3)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2+1,x3);
+      xoff = -1;
+      yoff = -1;
+      zoff = 0;
+   }
+   //GoSW
+   else if(inRange(x1-1,x2-1,x3) && !iCellHasSolid(bcArray, x1-1,x2-1,x3)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1-1,x2-1,x3);
+      xoff = 1;
+      yoff = 1;
+      zoff = 0;
+   }
+   //GoSE
+   else if(inRange(x1+2,x2-1,x3) && !iCellHasSolid(bcArray, x1+1,x2-1,x3)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2-1,x3);
+      xoff = -1;
+      yoff = 1;
+      zoff = 0;
+   }
+   //GoBW
+   else if(inRange(x1-1,x2,x3-1) && !iCellHasSolid(bcArray, x1-1,x2,x3-1))
+   {
+      readICell(f,icell,x1-1,x2,x3-1);
+      xoff = 1;
+      yoff = 0;
+      zoff = 1;
+   }
+   //GoBE
+   else if(inRange(x1+2,x2,x3-1) && !iCellHasSolid(bcArray, x1+1,x2,x3-1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2,x3-1);
+      xoff = -1;
+      yoff = 0;
+      zoff = 1;
+   }
+   //GoBS
+   else if(inRange(x1,x2-1,x3-1) && !iCellHasSolid(bcArray, x1,x2-1,x3-1)) 
+   {
+      readICell(f,icell,x1,x2-1,x3-1);
+      xoff = 0;
+      yoff = 1;
+      zoff = 1;
+   }
+   //GoBN
+   else if(inRange(x1,x2+2,x3-1) && !iCellHasSolid(bcArray, x1,x2+1,x3-1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1,x2+1,x3-1);
+      xoff = 0;
+      yoff = -1;
+      zoff = 1;
+   }
+   //GoTW
+   else if(inRange(x1-1,x2,x3+2) && !iCellHasSolid(bcArray, x1-1,x2,x3+1))
+   {
+      readICell(f,icell,x1-1,x2,x3+1);
+      xoff = 1;
+      yoff = 0;
+      zoff = -1;
+   }
+   //GoTE
+   else if(inRange(x1+2,x2,x3+2) && !iCellHasSolid(bcArray, x1+1,x2,x3+1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2,x3+1);
+      xoff = -1;
+      yoff = 0;
+      zoff = -1;
+   }
+   //GoTS
+   else if(inRange(x1,x2-1,x3+2) && !iCellHasSolid(bcArray, x1,x2-1,x3+1)) 
+   {
+      readICell(f,icell,x1,x2-1,x3+1);
+      xoff = 0;
+      yoff = 1;
+      zoff = -1;
+   }
+   //GoTN
+   else if(inRange(x1,x2+2,x3+2) && !iCellHasSolid(bcArray, x1,x2+1,x3+1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1,x2+1,x3+1);
+      xoff = 0;
+      yoff = -1;
+      zoff = -1;
+   }
+   //GoTNW
+   else if(inRange(x1-1,x2+2,x3+2) && !iCellHasSolid(bcArray, x1-1,x2+1,x3+1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1-1,x2+1,x3+1);
+      xoff = 1;
+      yoff = -1;
+      zoff = -1;
+   }
+   //GoTNE
+   else if(inRange(x1+2,x2+2,x3+2) && !iCellHasSolid(bcArray, x1+1,x2+1,x3+1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2+1,x3+1);
+      xoff = -1;
+      yoff = -1;
+      zoff = -1;
+   }
+   //GoTSE
+   else if(inRange(x1+2,x2-1,x3+2) && !iCellHasSolid(bcArray, x1+1,x2-1,x3+1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2-1,x3+1);
+      xoff = -1;
+      yoff =  1;
+      zoff = -1;
+   }
+   //GoTSW
+   else if(inRange(x1-1,x2-1,x3+2) && !iCellHasSolid(bcArray, x1-1,x2-1,x3+1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1-1,x2-1,x3+1);
+      xoff =  1;
+      yoff =  1;
+      zoff = -1;
+   }
+   //GoBNW
+   else if(inRange(x1-1,x2+2,x3-1) && !iCellHasSolid(bcArray, x1-1,x2+1,x3-1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1-1,x2+1,x3-1);
+      xoff =  1;
+      yoff = -1;
+      zoff =  1;
+   }
+   //GoBNE
+   else if(inRange(x1+2,x2+2,x3-1) && !iCellHasSolid(bcArray, x1+1,x2+1,x3-1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2+1,x3-1);
+      xoff = -1;
+      yoff = -1;
+      zoff =  1;
+   }
+   //GoBSE
+   else if(inRange(x1+2,x2-1,x3-1) && !iCellHasSolid(bcArray, x1+1,x2-1,x3-1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1+1,x2-1,x3-1);
+      xoff = -1;
+      yoff =  1;
+      zoff =  1;
+   }
+   //GoBSW
+   else if(inRange(x1-1,x2-1,x3-1) && !iCellHasSolid(bcArray, x1-1,x2-1,x3-1)) // ist übernächster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+   {
+      readICell(f,icell,x1-1,x2-1,x3-1);
+      xoff =  1;
+      yoff =  1;
+      zoff =  1;
+   }
+   //default
+   else
+   {
+      //std::string err = "For x1="+StringUtil::toString(x1)+", x2=" + StringUtil::toString(x2)+", x3=" + StringUtil::toString(x3)+
+      //                  " interpolation is not implemented for other direction"+
+      //                  " by using in: "+(std::string)typeid(*this).name()+ 
+      //                  " or maybe you have a solid on the block boundary";
+      //UB_THROW(UbException(UB_EXARGS, err));
+      return 0;
+   }
+   return 1;
+}
+//////////////////////////////////////////////////////////////////////////
+int D3Q27InterpolationProcessor::iCellHowManySolids( const BCArray3D<D3Q27BoundaryCondition>& bcArray, int x1, int x2, int x3 )
+{
+   int count = 0;
+   for (int ix3 = x3; ix3 <= x3 + 1; ix3++)
+      for(int ix2 = x2; ix2 <= x2 + 1; ix2++)
+         for(int ix1 = x1; ix1 <= x1 + 1; ix1++)
+         {
+            if(bcArray.isSolid(ix1, ix2, ix3))
+               count++;
+         }
+   return count;  
+}
diff --git a/source/VirtualFluidsCore/LBM/D3Q27InterpolationProcessor.h b/source/VirtualFluidsCore/LBM/D3Q27InterpolationProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..a207c2ea21f00e19cdc0ba82ec5c279c37b1be4a
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27InterpolationProcessor.h
@@ -0,0 +1,69 @@
+#ifndef D3Q27INTRPOLATIOPROCESSOR_H_
+#define D3Q27INTRPOLATIOPROCESSOR_H_
+
+#include "InterpolationProcessor.h"
+#include "LBMSystem.h"
+#include "Block3D.h"
+#include "DistributionArray3D.h"
+#include "D3Q27BoundaryCondition.h"
+#include "BCArray3D.h"
+
+
+struct D3Q27ICell
+{
+   LBMReal TSW[27]; 
+   LBMReal TNW[27];
+   LBMReal TNE[27];
+   LBMReal TSE[27];
+   LBMReal BSW[27];
+   LBMReal BNW[27];
+   LBMReal BNE[27];
+   LBMReal BSE[27];
+};
+
+class D3Q27InterpolationProcessor;
+typedef boost::shared_ptr<D3Q27InterpolationProcessor> D3Q27InterpolationProcessorPtr;
+
+#include "D3Q27InterpolationHelper.h"
+
+class D3Q27InterpolationProcessor : public InterpolationProcessor
+{
+public:
+   D3Q27InterpolationProcessor();
+   virtual ~D3Q27InterpolationProcessor();
+   virtual D3Q27InterpolationProcessorPtr clone() = 0;
+   virtual void setOmegas(LBMReal omegaC, LBMReal omegaF) = 0;
+   virtual void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF) = 0;
+   virtual void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, LBMReal xoff, LBMReal yoff, LBMReal zoff) = 0;
+   virtual void interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC) = 0; 
+   virtual void interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC, LBMReal xoff, LBMReal yoff, LBMReal zoff) = 0; 
+
+   static void readICell(DistributionArray3DPtr f, D3Q27ICell& icell, int x1, int x2, int x3);
+   static void writeICell(DistributionArray3DPtr f, const D3Q27ICell& icell, int x1, int x2, int x3);
+   static void writeINode(DistributionArray3DPtr f, const LBMReal* const inode, int x1, int x2, int x3);
+   static bool iCellHasSolid(const BCArray3D<D3Q27BoundaryCondition>& bcArray, int x1, int x2, int x3);
+   static int  iCellHowManySolids(const BCArray3D<D3Q27BoundaryCondition>& bcArray, int x1, int x2, int x3);
+
+   bool findNeighborICell(const BCArray3D<D3Q27BoundaryCondition>& bcArray, DistributionArray3DPtr f, 
+                          D3Q27ICell& icell, int maxX1, int maxX2, int maxX3, 
+                          int x1, int x2, int x3, LBMReal& xoff, LBMReal& yoff, LBMReal& zoff);
+
+protected:
+   virtual void calcInterpolatedCoefficiets(const D3Q27ICell& icell, LBMReal omega, LBMReal eps_new){}
+   virtual void calcInterpolatedNodeFC(LBMReal* f, LBMReal omega){}
+   virtual void calcInterpolatedVelocity(LBMReal x, LBMReal y, LBMReal z,LBMReal& vx1, LBMReal& vx2, LBMReal& vx3){}
+   virtual void calcInterpolatedShearStress(LBMReal x, LBMReal y, LBMReal z,LBMReal& tauxx, LBMReal& tauyy, LBMReal& tauzz,LBMReal& tauxy, LBMReal& tauxz, LBMReal& tauyz){}
+   virtual void setOffsets(LBMReal xoff, LBMReal yoff, LBMReal zoff){}
+   friend class D3Q27InterpolationHelper;
+private:
+   bool inRange(int x1, int x2, int x3);
+   int m_maxX1, m_maxX2, m_maxX3;
+};
+
+//////////////////////////////////////////////////////////////////////////
+inline bool D3Q27InterpolationProcessor::inRange(int x1, int x2, int x3)
+{
+   return x1 >= 0 && x1 < m_maxX1 && x2 >= 0 && x2 < m_maxX2 && x3 >= 0 && x3 < m_maxX3;
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/D3Q27OffsetInterpolationProcessor.cpp b/source/VirtualFluidsCore/LBM/D3Q27OffsetInterpolationProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d12c43f50eba5a9368dbafebbdcb8573ce7f3845
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27OffsetInterpolationProcessor.cpp
@@ -0,0 +1,610 @@
+#include "D3Q27OffsetInterpolationProcessor.h"
+#include "SimulationParameters.h"
+
+#include <boost/foreach.hpp>
+
+D3Q27OffsetInterpolationProcessor::D3Q27OffsetInterpolationProcessor()
+   : omegaC(0.0), omegaF(0.0)
+{
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27OffsetInterpolationProcessor::D3Q27OffsetInterpolationProcessor(LBMReal omegaC, LBMReal omegaF)
+   : omegaC(omegaC), omegaF(omegaF)
+{
+   init();
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27OffsetInterpolationProcessor::~D3Q27OffsetInterpolationProcessor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27InterpolationProcessorPtr D3Q27OffsetInterpolationProcessor::clone()
+{
+   return D3Q27InterpolationProcessorPtr (new D3Q27OffsetInterpolationProcessor(this->omegaC, this->omegaF));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::init()
+{
+   calcFeqsForDirFct = NULL;
+   calcMacrosFct     = NULL;
+   calcFeqFct        = NULL;
+   //SimulationParametersPtr param = SimulationParameters::getInstanz();
+
+   //if(param->isCompressibleModel())
+   //{
+      calcMacrosFct     = &D3Q27System::calcCompMacroscopicValues;
+      calcFeqFct        = &D3Q27System::calcCompFeq; 
+   //}
+   //else
+   //{
+   //   calcMacrosFct     = &D3Q27System::calcIncompMacroscopicValues;
+   //   calcFeqFct        = &D3Q27System::calcIncompFeq; 
+   //}
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::setOmegas( LBMReal omegaC, LBMReal omegaF )
+{
+   this->omegaC = omegaC;
+   this->omegaF = omegaF;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::setOffsets(LBMReal xoff, LBMReal yoff, LBMReal zoff)
+{
+   this->xoff = xoff;
+   this->yoff = yoff;
+   this->zoff = zoff;     
+   this->xoff_sq = xoff * xoff;
+   this->yoff_sq = yoff * yoff;
+   this->zoff_sq = zoff * zoff;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, LBMReal xoff, LBMReal yoff, LBMReal zoff)
+{
+   setOffsets(xoff, yoff, zoff);
+   calcInterpolatedCoefficiets(icellC, omegaC, 0.5);
+   calcInterpolatedNode(icellF.BSW, omegaF, -0.25, -0.25, -0.25, calcPressBSW(), -1, -1, -1);
+   calcInterpolatedNode(icellF.BNE, omegaF,  0.25,  0.25, -0.25, calcPressBNE(),  1,  1, -1);
+   calcInterpolatedNode(icellF.TNW, omegaF, -0.25,  0.25,  0.25, calcPressTNW(), -1,  1,  1);
+   calcInterpolatedNode(icellF.TSE, omegaF,  0.25, -0.25,  0.25, calcPressTSE(),  1, -1,  1);
+   calcInterpolatedNode(icellF.BNW, omegaF, -0.25,  0.25, -0.25, calcPressBNW(), -1,  1, -1);
+   calcInterpolatedNode(icellF.BSE, omegaF,  0.25, -0.25, -0.25, calcPressBSE(),  1, -1, -1);
+   calcInterpolatedNode(icellF.TSW, omegaF, -0.25, -0.25,  0.25, calcPressTSW(), -1, -1,  1);
+   calcInterpolatedNode(icellF.TNE, omegaF,  0.25,  0.25,  0.25, calcPressTNE(),  1,  1,  1);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC, LBMReal xoff, LBMReal yoff, LBMReal zoff)
+{
+   setOffsets(xoff, yoff, zoff);
+   calcInterpolatedCoefficiets(icellF, omegaF, 2.0);
+   calcInterpolatedNodeFC(icellC, omegaC);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::calcMoments(const LBMReal* const f, LBMReal omega, LBMReal& press, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3, 
+   LBMReal& kxy, LBMReal& kyz, LBMReal& kxz, LBMReal& kxxMyy, LBMReal& kxxMzz)
+{
+   using namespace D3Q27System;
+   
+   LBMReal rho = 0.0;
+   calcMacrosFct(f,rho,vx1,vx2,vx3);
+   //press = D3Q27System::calcPress(f,rho,vx1,vx2,vx3);
+   press = rho; //interpolate rho!
+
+   kxy    = -3.*omega*(f[SW]+f[TSW]+f[BSW]-f[NW]-f[TNW]-f[BNW]-f[SE]-f[TSE]-f[BSE]+f[NE]+f[TNE]+f[BNE]-(vx1*vx2));
+   kyz    = -3.*omega*(f[BS]+f[BSW]+f[BSE]-f[TS]-f[TSW]-f[TSE]-f[BN]-f[BNW]-f[BNE]+f[TN]+f[TNW]+f[TNE]-(vx2*vx3));
+   kxz    = -3.*omega*(f[BW]+f[BNW]+f[BSW]-f[TW]-f[TNW]-f[TSW]-f[BE]-f[BNE]-f[BSE]+f[TE]+f[TNE]+f[TSE]-(vx1*vx3));
+   kxxMyy = -3./2.*omega*(f[BW]+f[W]+f[TW]-f[BS]-f[S]-f[TS]-f[BN]-f[N]-f[TN]+f[BE]+f[E]+f[TE]-(vx1*vx1-vx2*vx2));
+   kxxMzz = -3./2.*omega*(f[SW]+f[W]+f[NW]-f[BS]-f[TS]-f[B]-f[T]-f[BN]-f[TN]+f[SE]+f[E]+f[NE]-(vx1*vx1-vx3*vx3));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::calcInterpolatedCoefficiets(const D3Q27ICell& icell, LBMReal omega, LBMReal eps_new)
+{
+   LBMReal        vx1_SWT,vx2_SWT,vx3_SWT;
+   LBMReal        vx1_NWT,vx2_NWT,vx3_NWT;
+   LBMReal        vx1_NET,vx2_NET,vx3_NET;
+   LBMReal        vx1_SET,vx2_SET,vx3_SET;
+   LBMReal        vx1_SWB,vx2_SWB,vx3_SWB;
+   LBMReal        vx1_NWB,vx2_NWB,vx3_NWB;
+   LBMReal        vx1_NEB,vx2_NEB,vx3_NEB;
+   LBMReal        vx1_SEB,vx2_SEB,vx3_SEB;
+
+   LBMReal        kxyFromfcNEQ_SWT, kyzFromfcNEQ_SWT, kxzFromfcNEQ_SWT, kxxMyyFromfcNEQ_SWT, kxxMzzFromfcNEQ_SWT;
+   LBMReal        kxyFromfcNEQ_NWT, kyzFromfcNEQ_NWT, kxzFromfcNEQ_NWT, kxxMyyFromfcNEQ_NWT, kxxMzzFromfcNEQ_NWT;
+   LBMReal        kxyFromfcNEQ_NET, kyzFromfcNEQ_NET, kxzFromfcNEQ_NET, kxxMyyFromfcNEQ_NET, kxxMzzFromfcNEQ_NET;
+   LBMReal        kxyFromfcNEQ_SET, kyzFromfcNEQ_SET, kxzFromfcNEQ_SET, kxxMyyFromfcNEQ_SET, kxxMzzFromfcNEQ_SET;
+   LBMReal        kxyFromfcNEQ_SWB, kyzFromfcNEQ_SWB, kxzFromfcNEQ_SWB, kxxMyyFromfcNEQ_SWB, kxxMzzFromfcNEQ_SWB;
+   LBMReal        kxyFromfcNEQ_NWB, kyzFromfcNEQ_NWB, kxzFromfcNEQ_NWB, kxxMyyFromfcNEQ_NWB, kxxMzzFromfcNEQ_NWB;
+   LBMReal        kxyFromfcNEQ_NEB, kyzFromfcNEQ_NEB, kxzFromfcNEQ_NEB, kxxMyyFromfcNEQ_NEB, kxxMzzFromfcNEQ_NEB;
+   LBMReal        kxyFromfcNEQ_SEB, kyzFromfcNEQ_SEB, kxzFromfcNEQ_SEB, kxxMyyFromfcNEQ_SEB, kxxMzzFromfcNEQ_SEB;
+
+   calcMoments(icell.TSW,omega,press_SWT,vx1_SWT,vx2_SWT,vx3_SWT, kxyFromfcNEQ_SWT, kyzFromfcNEQ_SWT, kxzFromfcNEQ_SWT, kxxMyyFromfcNEQ_SWT, kxxMzzFromfcNEQ_SWT);
+   calcMoments(icell.TNW,omega,press_NWT,vx1_NWT,vx2_NWT,vx3_NWT, kxyFromfcNEQ_NWT, kyzFromfcNEQ_NWT, kxzFromfcNEQ_NWT, kxxMyyFromfcNEQ_NWT, kxxMzzFromfcNEQ_NWT);
+   calcMoments(icell.TNE,omega,press_NET,vx1_NET,vx2_NET,vx3_NET, kxyFromfcNEQ_NET, kyzFromfcNEQ_NET, kxzFromfcNEQ_NET, kxxMyyFromfcNEQ_NET, kxxMzzFromfcNEQ_NET);
+   calcMoments(icell.TSE,omega,press_SET,vx1_SET,vx2_SET,vx3_SET, kxyFromfcNEQ_SET, kyzFromfcNEQ_SET, kxzFromfcNEQ_SET, kxxMyyFromfcNEQ_SET, kxxMzzFromfcNEQ_SET);
+   calcMoments(icell.BSW,omega,press_SWB,vx1_SWB,vx2_SWB,vx3_SWB, kxyFromfcNEQ_SWB, kyzFromfcNEQ_SWB, kxzFromfcNEQ_SWB, kxxMyyFromfcNEQ_SWB, kxxMzzFromfcNEQ_SWB);
+   calcMoments(icell.BNW,omega,press_NWB,vx1_NWB,vx2_NWB,vx3_NWB, kxyFromfcNEQ_NWB, kyzFromfcNEQ_NWB, kxzFromfcNEQ_NWB, kxxMyyFromfcNEQ_NWB, kxxMzzFromfcNEQ_NWB);
+   calcMoments(icell.BNE,omega,press_NEB,vx1_NEB,vx2_NEB,vx3_NEB, kxyFromfcNEQ_NEB, kyzFromfcNEQ_NEB, kxzFromfcNEQ_NEB, kxxMyyFromfcNEQ_NEB, kxxMzzFromfcNEQ_NEB);
+   calcMoments(icell.BSE,omega,press_SEB,vx1_SEB,vx2_SEB,vx3_SEB, kxyFromfcNEQ_SEB, kyzFromfcNEQ_SEB, kxzFromfcNEQ_SEB, kxxMyyFromfcNEQ_SEB, kxxMzzFromfcNEQ_SEB);
+
+   a0 = (-kxxMyyFromfcNEQ_NEB - kxxMyyFromfcNEQ_NET + kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_NWT -
+      kxxMyyFromfcNEQ_SEB - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_SWT -
+      kxxMzzFromfcNEQ_NEB - kxxMzzFromfcNEQ_NET + kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_NWT -
+      kxxMzzFromfcNEQ_SEB - kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_SWT -
+      2.*kxyFromfcNEQ_NEB - 2.*kxyFromfcNEQ_NET - 2.*kxyFromfcNEQ_NWB - 2.*kxyFromfcNEQ_NWT +
+      2.*kxyFromfcNEQ_SEB + 2.*kxyFromfcNEQ_SET + 2.*kxyFromfcNEQ_SWB + 2.*kxyFromfcNEQ_SWT +
+      2.*kxzFromfcNEQ_NEB - 2.*kxzFromfcNEQ_NET + 2.*kxzFromfcNEQ_NWB - 2.*kxzFromfcNEQ_NWT +
+      2.*kxzFromfcNEQ_SEB - 2.*kxzFromfcNEQ_SET + 2.*kxzFromfcNEQ_SWB - 2.*kxzFromfcNEQ_SWT +
+      8.*vx1_NEB + 8.*vx1_NET + 8.*vx1_NWB + 8.*vx1_NWT + 8.*vx1_SEB +
+      8.*vx1_SET + 8.*vx1_SWB + 8.*vx1_SWT + 2.*vx2_NEB + 2.*vx2_NET -
+      2.*vx2_NWB - 2.*vx2_NWT - 2.*vx2_SEB - 2.*vx2_SET + 2.*vx2_SWB +
+      2.*vx2_SWT - 2.*vx3_NEB + 2.*vx3_NET + 2.*vx3_NWB - 2.*vx3_NWT -
+      2.*vx3_SEB + 2.*vx3_SET + 2.*vx3_SWB - 2.*vx3_SWT)/64.;
+   b0 = (2.*kxxMyyFromfcNEQ_NEB + 2.*kxxMyyFromfcNEQ_NET + 2.*kxxMyyFromfcNEQ_NWB + 2.*kxxMyyFromfcNEQ_NWT -
+      2.*kxxMyyFromfcNEQ_SEB - 2.*kxxMyyFromfcNEQ_SET - 2.*kxxMyyFromfcNEQ_SWB - 2.*kxxMyyFromfcNEQ_SWT -
+      kxxMzzFromfcNEQ_NEB - kxxMzzFromfcNEQ_NET - kxxMzzFromfcNEQ_NWB - kxxMzzFromfcNEQ_NWT +
+      kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_SWT -
+      2.*kxyFromfcNEQ_NEB - 2.*kxyFromfcNEQ_NET + 2.*kxyFromfcNEQ_NWB + 2.*kxyFromfcNEQ_NWT -
+      2.*kxyFromfcNEQ_SEB - 2.*kxyFromfcNEQ_SET + 2.*kxyFromfcNEQ_SWB + 2.*kxyFromfcNEQ_SWT +
+      2.*kyzFromfcNEQ_NEB - 2.*kyzFromfcNEQ_NET + 2.*kyzFromfcNEQ_NWB - 2.*kyzFromfcNEQ_NWT +
+      2.*kyzFromfcNEQ_SEB - 2.*kyzFromfcNEQ_SET + 2.*kyzFromfcNEQ_SWB - 2.*kyzFromfcNEQ_SWT +
+      2.*vx1_NEB + 2.*vx1_NET - 2.*vx1_NWB - 2.*vx1_NWT -
+      2.*vx1_SEB - 2.*vx1_SET + 2.*vx1_SWB + 2.*vx1_SWT +
+      8.*vx2_NEB + 8.*vx2_NET + 8.*vx2_NWB + 8.*vx2_NWT +
+      8.*vx2_SEB + 8.*vx2_SET + 8.*vx2_SWB + 8.*vx2_SWT -
+      2.*vx3_NEB + 2.*vx3_NET - 2.*vx3_NWB + 2.*vx3_NWT +
+      2.*vx3_SEB - 2.*vx3_SET + 2.*vx3_SWB - 2.*vx3_SWT)/64.;
+   c0 = (kxxMyyFromfcNEQ_NEB - kxxMyyFromfcNEQ_NET + kxxMyyFromfcNEQ_NWB - kxxMyyFromfcNEQ_NWT +
+      kxxMyyFromfcNEQ_SEB - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_SWT -
+      2.*kxxMzzFromfcNEQ_NEB + 2.*kxxMzzFromfcNEQ_NET - 2.*kxxMzzFromfcNEQ_NWB + 2.*kxxMzzFromfcNEQ_NWT -
+      2.*kxxMzzFromfcNEQ_SEB + 2.*kxxMzzFromfcNEQ_SET - 2.*kxxMzzFromfcNEQ_SWB + 2.*kxxMzzFromfcNEQ_SWT -
+      2.*kxzFromfcNEQ_NEB - 2.*kxzFromfcNEQ_NET + 2.*kxzFromfcNEQ_NWB + 2.*kxzFromfcNEQ_NWT -
+      2.*kxzFromfcNEQ_SEB - 2.*kxzFromfcNEQ_SET + 2.*kxzFromfcNEQ_SWB + 2.*kxzFromfcNEQ_SWT -
+      2.*kyzFromfcNEQ_NEB - 2.*kyzFromfcNEQ_NET - 2.*kyzFromfcNEQ_NWB - 2.*kyzFromfcNEQ_NWT +
+      2.*kyzFromfcNEQ_SEB + 2.*kyzFromfcNEQ_SET + 2.*kyzFromfcNEQ_SWB + 2.*kyzFromfcNEQ_SWT -
+      2.*vx1_NEB + 2.*vx1_NET + 2.*vx1_NWB - 2.*vx1_NWT -
+      2.*vx1_SEB + 2.*vx1_SET + 2.*vx1_SWB - 2.*vx1_SWT -
+      2.*vx2_NEB + 2.*vx2_NET - 2.*vx2_NWB + 2.*vx2_NWT +
+      2.*vx2_SEB - 2.*vx2_SET + 2.*vx2_SWB - 2.*vx2_SWT +
+      8.*vx3_NEB + 8.*vx3_NET + 8.*vx3_NWB + 8.*vx3_NWT +
+      8.*vx3_SEB + 8.*vx3_SET + 8.*vx3_SWB + 8.*vx3_SWT)/64.;
+   ax = (vx1_NEB + vx1_NET - vx1_NWB - vx1_NWT + vx1_SEB + vx1_SET - vx1_SWB - vx1_SWT)/4.;
+   bx = (vx2_NEB + vx2_NET - vx2_NWB - vx2_NWT + vx2_SEB + vx2_SET - vx2_SWB - vx2_SWT)/4.;
+   cx = (vx3_NEB + vx3_NET - vx3_NWB - vx3_NWT + vx3_SEB + vx3_SET - vx3_SWB - vx3_SWT)/4.;
+   axx= (kxxMyyFromfcNEQ_NEB + kxxMyyFromfcNEQ_NET - kxxMyyFromfcNEQ_NWB - kxxMyyFromfcNEQ_NWT +
+      kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_SWT +
+      kxxMzzFromfcNEQ_NEB + kxxMzzFromfcNEQ_NET - kxxMzzFromfcNEQ_NWB - kxxMzzFromfcNEQ_NWT +
+      kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_SWT +
+      2.*vx2_NEB + 2.*vx2_NET - 2.*vx2_NWB - 2.*vx2_NWT -
+      2.*vx2_SEB - 2.*vx2_SET + 2.*vx2_SWB + 2.*vx2_SWT -
+      2.*vx3_NEB + 2.*vx3_NET + 2.*vx3_NWB - 2.*vx3_NWT -
+      2.*vx3_SEB + 2.*vx3_SET + 2.*vx3_SWB - 2.*vx3_SWT)/16.;
+   bxx= (kxyFromfcNEQ_NEB + kxyFromfcNEQ_NET - kxyFromfcNEQ_NWB - kxyFromfcNEQ_NWT +
+      kxyFromfcNEQ_SEB + kxyFromfcNEQ_SET - kxyFromfcNEQ_SWB - kxyFromfcNEQ_SWT -
+      2.*vx1_NEB - 2.*vx1_NET + 2.*vx1_NWB + 2.*vx1_NWT +
+      2.*vx1_SEB + 2.*vx1_SET - 2.*vx1_SWB - 2.*vx1_SWT)/8.;
+   cxx= (kxzFromfcNEQ_NEB + kxzFromfcNEQ_NET - kxzFromfcNEQ_NWB - kxzFromfcNEQ_NWT +
+      kxzFromfcNEQ_SEB + kxzFromfcNEQ_SET - kxzFromfcNEQ_SWB - kxzFromfcNEQ_SWT +
+      2.*vx1_NEB - 2.*vx1_NET - 2.*vx1_NWB + 2.*vx1_NWT +
+      2.*vx1_SEB - 2.*vx1_SET - 2.*vx1_SWB + 2.*vx1_SWT)/8.;
+   ay = (vx1_NEB + vx1_NET + vx1_NWB + vx1_NWT - vx1_SEB - vx1_SET - vx1_SWB - vx1_SWT)/4.;
+   by = (vx2_NEB + vx2_NET + vx2_NWB + vx2_NWT - vx2_SEB - vx2_SET - vx2_SWB - vx2_SWT)/4.;
+   cy = (vx3_NEB + vx3_NET + vx3_NWB + vx3_NWT - vx3_SEB - vx3_SET - vx3_SWB - vx3_SWT)/4.;
+   ayy= (kxyFromfcNEQ_NEB + kxyFromfcNEQ_NET + kxyFromfcNEQ_NWB + kxyFromfcNEQ_NWT -
+      kxyFromfcNEQ_SEB - kxyFromfcNEQ_SET - kxyFromfcNEQ_SWB - kxyFromfcNEQ_SWT -
+      2.*vx2_NEB - 2.*vx2_NET + 2.*vx2_NWB + 2.*vx2_NWT +
+      2.*vx2_SEB + 2.*vx2_SET - 2.*vx2_SWB - 2.*vx2_SWT)/8.;
+   byy= (-2.*kxxMyyFromfcNEQ_NEB - 2.*kxxMyyFromfcNEQ_NET - 2.*kxxMyyFromfcNEQ_NWB - 2.*kxxMyyFromfcNEQ_NWT +
+      2.*kxxMyyFromfcNEQ_SEB + 2.*kxxMyyFromfcNEQ_SET + 2.*kxxMyyFromfcNEQ_SWB + 2.*kxxMyyFromfcNEQ_SWT +
+      kxxMzzFromfcNEQ_NEB + kxxMzzFromfcNEQ_NET + kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_NWT -
+      kxxMzzFromfcNEQ_SEB - kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_SWT +
+      2.*vx1_NEB + 2.*vx1_NET - 2.*vx1_NWB - 2.*vx1_NWT -
+      2.*vx1_SEB - 2.*vx1_SET + 2.*vx1_SWB + 2.*vx1_SWT -
+      2.*vx3_NEB + 2.*vx3_NET - 2.*vx3_NWB + 2.*vx3_NWT +
+      2.*vx3_SEB - 2.*vx3_SET + 2.*vx3_SWB - 2.*vx3_SWT)/16.;
+   cyy= (kyzFromfcNEQ_NEB + kyzFromfcNEQ_NET + kyzFromfcNEQ_NWB + kyzFromfcNEQ_NWT -
+      kyzFromfcNEQ_SEB - kyzFromfcNEQ_SET - kyzFromfcNEQ_SWB - kyzFromfcNEQ_SWT +
+      2.*vx2_NEB - 2.*vx2_NET + 2.*vx2_NWB - 2.*vx2_NWT -
+      2.*vx2_SEB + 2.*vx2_SET - 2.*vx2_SWB + 2.*vx2_SWT)/8.;
+   az = (-vx1_NEB + vx1_NET - vx1_NWB + vx1_NWT - vx1_SEB + vx1_SET - vx1_SWB + vx1_SWT)/4.;
+   bz = (-vx2_NEB + vx2_NET - vx2_NWB + vx2_NWT - vx2_SEB + vx2_SET - vx2_SWB + vx2_SWT)/4.;
+   cz = (-vx3_NEB + vx3_NET - vx3_NWB + vx3_NWT - vx3_SEB + vx3_SET - vx3_SWB + vx3_SWT)/4.;
+   azz= (-kxzFromfcNEQ_NEB + kxzFromfcNEQ_NET - kxzFromfcNEQ_NWB + kxzFromfcNEQ_NWT -
+      kxzFromfcNEQ_SEB + kxzFromfcNEQ_SET - kxzFromfcNEQ_SWB + kxzFromfcNEQ_SWT +
+      2.*vx3_NEB - 2.*vx3_NET - 2.*vx3_NWB + 2.*vx3_NWT +
+      2.*vx3_SEB - 2.*vx3_SET - 2.*vx3_SWB + 2.*vx3_SWT)/8.;
+   bzz= (-kyzFromfcNEQ_NEB + kyzFromfcNEQ_NET - kyzFromfcNEQ_NWB + kyzFromfcNEQ_NWT -
+      kyzFromfcNEQ_SEB + kyzFromfcNEQ_SET - kyzFromfcNEQ_SWB + kyzFromfcNEQ_SWT +
+      2.*vx3_NEB - 2.*vx3_NET + 2.*vx3_NWB - 2.*vx3_NWT -
+      2.*vx3_SEB + 2.*vx3_SET - 2.*vx3_SWB + 2.*vx3_SWT)/8.;
+   czz= (-kxxMyyFromfcNEQ_NEB + kxxMyyFromfcNEQ_NET - kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_NWT -
+      kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_SWT +
+      2.*kxxMzzFromfcNEQ_NEB - 2.*kxxMzzFromfcNEQ_NET + 2.*kxxMzzFromfcNEQ_NWB - 2.*kxxMzzFromfcNEQ_NWT +
+      2.*kxxMzzFromfcNEQ_SEB - 2.*kxxMzzFromfcNEQ_SET + 2.*kxxMzzFromfcNEQ_SWB - 2.*kxxMzzFromfcNEQ_SWT -
+      2.*vx1_NEB + 2.*vx1_NET + 2.*vx1_NWB - 2.*vx1_NWT -
+      2.*vx1_SEB + 2.*vx1_SET + 2.*vx1_SWB - 2.*vx1_SWT -
+      2.*vx2_NEB + 2.*vx2_NET - 2.*vx2_NWB + 2.*vx2_NWT +
+      2.*vx2_SEB - 2.*vx2_SET + 2.*vx2_SWB - 2.*vx2_SWT)/16.;
+   axy= (vx1_NEB + vx1_NET - vx1_NWB - vx1_NWT - vx1_SEB - vx1_SET + vx1_SWB + vx1_SWT)/2.;
+   bxy= (vx2_NEB + vx2_NET - vx2_NWB - vx2_NWT - vx2_SEB - vx2_SET + vx2_SWB + vx2_SWT)/2.;
+   cxy= (vx3_NEB + vx3_NET - vx3_NWB - vx3_NWT - vx3_SEB - vx3_SET + vx3_SWB + vx3_SWT)/2.;
+   axz= (-vx1_NEB + vx1_NET + vx1_NWB - vx1_NWT - vx1_SEB + vx1_SET + vx1_SWB - vx1_SWT)/2.;
+   bxz= (-vx2_NEB + vx2_NET + vx2_NWB - vx2_NWT - vx2_SEB + vx2_SET + vx2_SWB - vx2_SWT)/2.;
+   cxz= (-vx3_NEB + vx3_NET + vx3_NWB - vx3_NWT - vx3_SEB + vx3_SET + vx3_SWB - vx3_SWT)/2.;
+   ayz= (-vx1_NEB + vx1_NET - vx1_NWB + vx1_NWT + vx1_SEB - vx1_SET + vx1_SWB - vx1_SWT)/2.;
+   byz= (-vx2_NEB + vx2_NET - vx2_NWB + vx2_NWT + vx2_SEB - vx2_SET + vx2_SWB - vx2_SWT)/2.;
+   cyz= (-vx3_NEB + vx3_NET - vx3_NWB + vx3_NWT + vx3_SEB - vx3_SET + vx3_SWB - vx3_SWT)/2.;
+   axyz=-vx1_NEB + vx1_NET + vx1_NWB - vx1_NWT + vx1_SEB - vx1_SET - vx1_SWB + vx1_SWT;
+   bxyz=-vx2_NEB + vx2_NET + vx2_NWB - vx2_NWT + vx2_SEB - vx2_SET - vx2_SWB + vx2_SWT;
+   cxyz=-vx3_NEB + vx3_NET + vx3_NWB - vx3_NWT + vx3_SEB - vx3_SET - vx3_SWB + vx3_SWT;
+
+   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+   //
+   // Bernd das Brot
+   //
+   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+   a0 = a0 + xoff * ax + yoff * ay + zoff * az + xoff_sq * axx + yoff_sq * ayy + zoff_sq * azz + xoff*yoff*axy + xoff*zoff*axz + yoff*zoff*ayz + xoff*yoff*zoff*axyz ;
+   ax = ax + 2. * xoff * axx + yoff * axy + zoff * axz + yoff*zoff*axyz;
+   ay = ay + 2. * yoff * ayy + xoff * axy + zoff * ayz + xoff*zoff*axyz;
+   az = az + 2. * zoff * azz + xoff * axz + yoff * ayz + xoff*yoff*axyz;
+   b0 = b0 + xoff * bx + yoff * by + zoff * bz + xoff_sq * bxx + yoff_sq * byy + zoff_sq * bzz + xoff*yoff*bxy + xoff*zoff*bxz + yoff*zoff*byz + xoff*yoff*zoff*bxyz;
+   bx = bx + 2. * xoff * bxx + yoff * bxy + zoff * bxz + yoff*zoff*bxyz;
+   by = by + 2. * yoff * byy + xoff * bxy + zoff * byz + xoff*zoff*bxyz;
+   bz = bz + 2. * zoff * bzz + xoff * bxz + yoff * byz + xoff*yoff*bxyz;
+   c0 = c0 + xoff * cx + yoff * cy + zoff * cz + xoff_sq * cxx + yoff_sq * cyy + zoff_sq * czz + xoff*yoff*cxy + xoff*zoff*cxz + yoff*zoff*cyz + xoff*yoff*zoff*cxyz;
+   cx = cx + 2. * xoff * cxx + yoff * cxy + zoff * cxz + yoff*zoff*cxyz;
+   cy = cy + 2. * yoff * cyy + xoff * cxy + zoff * cyz + xoff*zoff*cxyz;
+   cz = cz + 2. * zoff * czz + xoff * cxz + yoff * cyz + xoff*yoff*cxyz;
+   axy= axy + zoff*axyz;
+   axz= axz + yoff*axyz;
+   ayz= ayz + xoff*axyz;
+   bxy= bxy + zoff*bxyz;
+   bxz= bxz + yoff*bxyz;
+   byz= byz + xoff*bxyz;
+   cxy= cxy + zoff*cxyz;
+   cxz= cxz + yoff*cxyz;
+   cyz= cyz + xoff*cxyz;
+   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+   const LBMReal o = omega;
+
+   f_E = eps_new*((2*(-2*ax + by + cz))/(27.*o));
+   f_N = eps_new*((2*(ax - 2*by + cz))/(27.*o));
+   f_T = eps_new*((2*(ax + by - 2*cz))/(27.*o));
+   f_NE = eps_new*(-(ax + 3*ay + 3*bx + by - 2*cz)/(54.*o));
+   f_SE = eps_new*(-(ax - 3*ay - 3*bx + by - 2*cz)/(54.*o));
+   f_TE = eps_new*(-(ax + 3*az - 2*by + 3*cx + cz)/(54.*o));
+   f_BE = eps_new*(-(ax - 3*az - 2*by - 3*cx + cz)/(54.*o));
+   f_TN = eps_new*(-(-2*ax + by + 3*bz + 3*cy + cz)/(54.*o));
+   f_BN = eps_new*(-(-2*ax + by - 3*bz - 3*cy + cz)/(54.*o));
+   f_ZERO = 0.;
+   f_TNE = eps_new*(-(ay + az + bx + bz + cx + cy)/(72.*o));
+   f_TSW = eps_new*((-ay + az - bx + bz + cx + cy)/(72.*o));
+   f_TSE = eps_new*((ay - az + bx + bz - cx + cy)/(72.*o));
+   f_TNW = eps_new*((ay + az + bx - bz + cx - cy)/(72.*o));
+
+   x_E = 0.25*eps_new*((2*(-4*axx + bxy + cxz))/(27.*o));
+   x_N = 0.25*eps_new*((2*(2*axx - 2*bxy + cxz))/(27.*o));
+   x_T = 0.25*eps_new*((2*(2*axx + bxy - 2*cxz))/(27.*o));
+   x_NE = 0.25*eps_new*(-((2*axx + 3*axy + 6*bxx + bxy - 2*cxz))/(54.*o));
+   x_SE = 0.25*eps_new*(-((2*axx - 3*axy - 6*bxx + bxy - 2*cxz))/(54.*o));
+   x_TE = 0.25*eps_new*(-((2*axx + 3*axz - 2*bxy + 6*cxx + cxz))/(54.*o));
+   x_BE = 0.25*eps_new*(-((2*axx - 3*axz - 2*bxy - 6*cxx + cxz))/(54.*o));
+   x_TN = 0.25*eps_new*(-((-4*axx + bxy + 3*bxz + 3*cxy + cxz))/(54.*o));
+   x_BN = 0.25*eps_new*(-((-4*axx + bxy - 3*bxz - 3*cxy + cxz))/(54.*o));
+   x_ZERO = 0.;
+   x_TNE = 0.25*eps_new*(-((axy + axz + 2*bxx + bxz + 2*cxx + cxy))/(72.*o));
+   x_TSW = 0.25*eps_new*(((-axy + axz - 2*bxx + bxz + 2*cxx + cxy))/(72.*o));
+   x_TSE = 0.25*eps_new*(((axy - axz + 2*bxx + bxz - 2*cxx + cxy))/(72.*o));
+   x_TNW = 0.25*eps_new*(((axy + axz + 2*bxx - bxz + 2*cxx - cxy))/(72.*o));
+
+   y_E = 0.25*eps_new*(2*(-2*axy + 2*byy + cyz))/(27.*o);
+   y_N = 0.25*eps_new*(2*(axy - 4*byy + cyz))/(27.*o);
+   y_T = 0.25*eps_new*(2*(axy + 2*byy - 2*cyz))/(27.*o);
+   y_NE = 0.25*eps_new*(-((axy + 6*ayy + 3*bxy + 2*byy - 2*cyz))/(54.*o));
+   y_SE = 0.25*eps_new*(-((axy - 6*ayy - 3*bxy + 2*byy - 2*cyz))/(54.*o));
+   y_TE = 0.25*eps_new*(-((axy + 3*ayz - 4*byy + 3*cxy + cyz))/(54.*o));
+   y_BE = 0.25*eps_new*(-((axy - 3*ayz - 4*byy - 3*cxy + cyz))/(54.*o));
+   y_TN = 0.25*eps_new*(-((-2*axy + 2*byy + 3*byz + 6*cyy + cyz))/(54.*o));
+   y_BN = 0.25*eps_new*(-((-2*axy + 2*byy - 3*byz - 6*cyy + cyz))/(54.*o));
+   y_ZERO = 0.;
+   y_TNE = 0.25*eps_new*(-((2*ayy + ayz + bxy + byz + cxy + 2*cyy))/(72.*o));
+   y_TSW = 0.25*eps_new*(((-2*ayy + ayz - bxy + byz + cxy + 2*cyy))/(72.*o));
+   y_TSE = 0.25*eps_new*(((2*ayy - ayz + bxy + byz - cxy + 2*cyy))/(72.*o));
+   y_TNW = 0.25*eps_new*(((2*ayy + ayz + bxy - byz + cxy - 2*cyy))/(72.*o));
+
+   z_E = 0.25*eps_new*((2*(-2*axz + byz + 2*czz))/(27.*o));
+   z_N = 0.25*eps_new*((2*(axz - 2*byz + 2*czz))/(27.*o));
+   z_T = 0.25*eps_new*((2*(axz + byz - 4*czz))/(27.*o));
+   z_NE = 0.25*eps_new*(-((axz + 3*ayz + 3*bxz + byz - 4*czz))/(54.*o));
+   z_SE = 0.25*eps_new*(-((axz - 3*ayz - 3*bxz + byz - 4*czz))/(54.*o));
+   z_TE = 0.25*eps_new*(-((axz + 6*azz - 2*byz + 3*cxz + 2*czz))/(54.*o));
+   z_BE = 0.25*eps_new*(-((axz - 6*azz - 2*byz - 3*cxz + 2*czz))/(54.*o));
+   z_TN = 0.25*eps_new*(-((-2*axz + byz + 6*bzz + 3*cyz + 2*czz))/(54.*o));
+   z_BN = 0.25*eps_new*(-((-2*axz + byz - 6*bzz - 3*cyz + 2*czz))/(54.*o));
+   z_ZERO = 0.;
+   z_TNE = 0.25*eps_new*(-((ayz + 2*azz + bxz + 2*bzz + cxz + cyz))/(72.*o));
+   z_TSW = 0.25*eps_new*(((-ayz + 2*azz - bxz + 2*bzz + cxz + cyz))/(72.*o));
+   z_TSE = 0.25*eps_new*(((ayz - 2*azz + bxz + 2*bzz - cxz + cyz))/(72.*o));
+   z_TNW = 0.25*eps_new*(((ayz + 2*azz + bxz - 2*bzz + cxz - cyz))/(72.*o));
+
+   xy_E   =   0.0625*eps_new *((                       2.*cxyz)/(27.*o));
+   xy_N   =   0.0625*eps_new *((                       2.*cxyz)/(27.*o));
+   xy_T   = -(0.0625*eps_new *((                       4.*cxyz)/(27.*o)));
+   xy_NE  =   0.0625*eps_new *(                            cxyz /(27.*o));
+   xy_SE  =   0.0625*eps_new *(                            cxyz /(27.*o));
+   xy_TE  = -(0.0625*eps_new *(( 3.*axyz            +     cxyz)/(54.*o)));
+   xy_BE  = -(0.0625*eps_new *((-3.*axyz            +     cxyz)/(54.*o)));
+   xy_TN  = -(0.0625*eps_new *((            3.*bxyz +     cxyz)/(54.*o)));
+   xy_BN  = -(0.0625*eps_new *((          - 3.*bxyz +     cxyz)/(54.*o)));
+   //xy_ZERO=   0.0625*eps_new;
+   xy_TNE = -(0.0625*eps_new *((     axyz +     bxyz           )/(72.*o)));
+   xy_TSW =   0.0625*eps_new *((     axyz +     bxyz           )/(72.*o));
+   xy_TSE =   0.0625*eps_new *((-    axyz +     bxyz           )/(72.*o));
+   xy_TNW =   0.0625*eps_new *((     axyz -     bxyz           )/(72.*o));
+
+   xz_E   =   0.0625*eps_new *((            2.*bxyz           )/(27.*o));
+   xz_N   = -(0.0625*eps_new *((            4.*bxyz           )/(27.*o)));
+   xz_T   =   0.0625*eps_new *((            2.*bxyz           )/(27.*o));
+   xz_NE  = -(0.0625*eps_new *(( 3.*axyz +     bxyz           )/(54.*o)));
+   xz_SE  = -(0.0625*eps_new *((-3.*axyz +     bxyz           )/(54.*o)));
+   xz_TE  =   0.0625*eps_new *((                bxyz           )/(27.*o));
+   xz_BE  =   0.0625*eps_new *((                bxyz           )/(27.*o));
+   xz_TN  = -(0.0625*eps_new *((                bxyz + 3.*cxyz)/(54.*o)));
+   xz_BN  = -(0.0625*eps_new *((                bxyz - 3.*cxyz)/(54.*o)));
+   //xz_ZERO=   0.0625*eps_new;
+   xz_TNE = -(0.0625*eps_new *((     axyz            +     cxyz)/(72.*o)));
+   xz_TSW =   0.0625*eps_new *((-    axyz            +     cxyz)/(72.*o));
+   xz_TSE =   0.0625*eps_new *((     axyz            +     cxyz)/(72.*o));
+   xz_TNW =   0.0625*eps_new *((     axyz            -     cxyz)/(72.*o));
+
+   yz_E   = -(0.0625*eps_new *(( 4.*axyz                      )/(27.*o)));
+   yz_N   =   0.0625*eps_new *(( 2.*axyz                      )/(27.*o));
+   yz_T   =   0.0625*eps_new *(( 2.*axyz                      )/(27.*o));
+   yz_NE  = -(0.0625*eps_new *((     axyz + 3.*bxyz           )/(54.*o)));
+   yz_SE  = -(0.0625*eps_new *((     axyz - 3.*bxyz           )/(54.*o)));
+   yz_TE  = -(0.0625*eps_new *((     axyz            + 3.*cxyz)/(54.*o)));
+   yz_BE  = -(0.0625*eps_new *((     axyz            - 3.*cxyz)/(54.*o)));
+   yz_TN  =   0.0625*eps_new *((     axyz                      )/(27.*o));
+   yz_BN  =   0.0625*eps_new *((     axyz                      )/(27.*o));
+   //yz_ZERO=   0.0625*eps_new;
+   yz_TNE = -(0.0625*eps_new *((                bxyz +     cxyz)/(72.*o)));
+   yz_TSW =   0.0625*eps_new *((          -     bxyz +     cxyz)/(72.*o));
+   yz_TSE =   0.0625*eps_new *((                bxyz -     cxyz)/(72.*o));
+   yz_TNW =   0.0625*eps_new *((                bxyz +     cxyz)/(72.*o));
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::calcInterpolatedNode(LBMReal* f, LBMReal omega, LBMReal x, LBMReal y, LBMReal z, LBMReal press, LBMReal xs, LBMReal ys, LBMReal zs)
+{
+   using namespace D3Q27System;
+
+   LBMReal rho  = press ;//+ (2.*axx*x+axy*y+axz*z+axyz*y*z+ax + 2.*byy*y+bxy*x+byz*z+bxyz*x*z+by + 2.*czz*z+cxz*x+cyz*y+cxyz*x*y+cz)/3.;
+   LBMReal vx1  = a0 + 0.25*( xs*ax + ys*ay + zs*az) + 0.0625*(axx + xs*ys*axy + xs*zs*axz + ayy + ys*zs*ayz + azz) + 0.015625*(xs*ys*zs*axyz);
+   LBMReal vx2  = b0 + 0.25*( xs*bx + ys*by + zs*bz) + 0.0625*(bxx + xs*ys*bxy + xs*zs*bxz + byy + ys*zs*byz + bzz) + 0.015625*(xs*ys*zs*bxyz);
+   LBMReal vx3  = c0 + 0.25*( xs*cx + ys*cy + zs*cz) + 0.0625*(cxx + xs*ys*cxy + xs*zs*cxz + cyy + ys*zs*cyz + czz) + 0.015625*(xs*ys*zs*cxyz);
+
+   LBMReal feq[ENDF+1];
+   calcFeqFct(feq,rho,vx1,vx2,vx3);
+
+   f[E]    = f_E    + xs*x_E    + ys*y_E    + zs*z_E    + xs*ys*xy_E    + xs*zs*xz_E    + ys*zs*yz_E    + feq[E];
+   f[W]    = f_E    + xs*x_E    + ys*y_E    + zs*z_E    + xs*ys*xy_E    + xs*zs*xz_E    + ys*zs*yz_E    + feq[W];
+   f[N]    = f_N    + xs*x_N    + ys*y_N    + zs*z_N    + xs*ys*xy_N    + xs*zs*xz_N    + ys*zs*yz_N    + feq[N];
+   f[S]    = f_N    + xs*x_N    + ys*y_N    + zs*z_N    + xs*ys*xy_N    + xs*zs*xz_N    + ys*zs*yz_N    + feq[S];
+   f[T]    = f_T    + xs*x_T    + ys*y_T    + zs*z_T    + xs*ys*xy_T    + xs*zs*xz_T    + ys*zs*yz_T    + feq[T];
+   f[B]    = f_T    + xs*x_T    + ys*y_T    + zs*z_T    + xs*ys*xy_T    + xs*zs*xz_T    + ys*zs*yz_T    + feq[B];
+   f[NE]   = f_NE   + xs*x_NE   + ys*y_NE   + zs*z_NE   + xs*ys*xy_NE   + xs*zs*xz_NE   + ys*zs*yz_NE   + feq[NE];
+   f[SW]   = f_NE   + xs*x_NE   + ys*y_NE   + zs*z_NE   + xs*ys*xy_NE   + xs*zs*xz_NE   + ys*zs*yz_NE   + feq[SW];
+   f[SE]   = f_SE   + xs*x_SE   + ys*y_SE   + zs*z_SE   + xs*ys*xy_SE   + xs*zs*xz_SE   + ys*zs*yz_SE   + feq[SE];
+   f[NW]   = f_SE   + xs*x_SE   + ys*y_SE   + zs*z_SE   + xs*ys*xy_SE   + xs*zs*xz_SE   + ys*zs*yz_SE   + feq[NW];
+   f[TE]   = f_TE   + xs*x_TE   + ys*y_TE   + zs*z_TE   + xs*ys*xy_TE   + xs*zs*xz_TE   + ys*zs*yz_TE   + feq[TE];
+   f[BW]   = f_TE   + xs*x_TE   + ys*y_TE   + zs*z_TE   + xs*ys*xy_TE   + xs*zs*xz_TE   + ys*zs*yz_TE   + feq[BW];
+   f[BE]   = f_BE   + xs*x_BE   + ys*y_BE   + zs*z_BE   + xs*ys*xy_BE   + xs*zs*xz_BE   + ys*zs*yz_BE   + feq[BE];
+   f[TW]   = f_BE   + xs*x_BE   + ys*y_BE   + zs*z_BE   + xs*ys*xy_BE   + xs*zs*xz_BE   + ys*zs*yz_BE   + feq[TW];
+   f[TN]   = f_TN   + xs*x_TN   + ys*y_TN   + zs*z_TN   + xs*ys*xy_TN   + xs*zs*xz_TN   + ys*zs*yz_TN   + feq[TN];
+   f[BS]   = f_TN   + xs*x_TN   + ys*y_TN   + zs*z_TN   + xs*ys*xy_TN   + xs*zs*xz_TN   + ys*zs*yz_TN   + feq[BS];
+   f[BN]   = f_BN   + xs*x_BN   + ys*y_BN   + zs*z_BN   + xs*ys*xy_BN   + xs*zs*xz_BN   + ys*zs*yz_BN   + feq[BN];
+   f[TS]   = f_BN   + xs*x_BN   + ys*y_BN   + zs*z_BN   + xs*ys*xy_BN   + xs*zs*xz_BN   + ys*zs*yz_BN   + feq[TS];
+   f[TNE]  = f_TNE  + xs*x_TNE  + ys*y_TNE  + zs*z_TNE  + xs*ys*xy_TNE  + xs*zs*xz_TNE  + ys*zs*yz_TNE  + feq[TNE];
+   f[TSW]  = f_TSW  + xs*x_TSW  + ys*y_TSW  + zs*z_TSW  + xs*ys*xy_TSW  + xs*zs*xz_TSW  + ys*zs*yz_TSW  + feq[TSW];
+   f[TSE]  = f_TSE  + xs*x_TSE  + ys*y_TSE  + zs*z_TSE  + xs*ys*xy_TSE  + xs*zs*xz_TSE  + ys*zs*yz_TSE  + feq[TSE];
+   f[TNW]  = f_TNW  + xs*x_TNW  + ys*y_TNW  + zs*z_TNW  + xs*ys*xy_TNW  + xs*zs*xz_TNW  + ys*zs*yz_TNW  + feq[TNW];
+   f[BNE]  = f_TSW  + xs*x_TSW  + ys*y_TSW  + zs*z_TSW  + xs*ys*xy_TSW  + xs*zs*xz_TSW  + ys*zs*yz_TSW  + feq[BNE];
+   f[BSW]  = f_TNE  + xs*x_TNE  + ys*y_TNE  + zs*z_TNE  + xs*ys*xy_TNE  + xs*zs*xz_TNE  + ys*zs*yz_TNE  + feq[BSW];
+   f[BSE]  = f_TNW  + xs*x_TNW  + ys*y_TNW  + zs*z_TNW  + xs*ys*xy_TNW  + xs*zs*xz_TNW  + ys*zs*yz_TNW  + feq[BSE];
+   f[BNW]  = f_TSE  + xs*x_TSE  + ys*y_TSE  + zs*z_TSE  + xs*ys*xy_TSE  + xs*zs*xz_TSE  + ys*zs*yz_TSE  + feq[BNW];
+   f[ZERO] = f_ZERO + xs*x_ZERO + ys*y_ZERO + zs*z_ZERO                                                 + feq[ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+//Position SWB -0.25, -0.25, -0.25
+LBMReal D3Q27OffsetInterpolationProcessor::calcPressBSW()
+{
+   return   press_SWT * (0.140625 + 0.1875 * xoff + 0.1875 * yoff - 0.5625 * zoff) +
+            press_NWT * (0.046875 + 0.0625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
+            press_SET * (0.046875 - 0.1875 * xoff + 0.0625 * yoff - 0.1875 * zoff) +
+            press_NET * (0.015625 - 0.0625 * xoff - 0.0625 * yoff - 0.0625 * zoff) +
+            press_NEB * (0.046875 - 0.1875 * xoff - 0.1875 * yoff + 0.0625 * zoff) +
+            press_NWB * (0.140625 + 0.1875 * xoff - 0.5625 * yoff + 0.1875 * zoff) +
+            press_SEB * (0.140625 - 0.5625 * xoff + 0.1875 * yoff + 0.1875 * zoff) +
+            press_SWB * (0.421875 + 0.5625 * xoff + 0.5625 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position SWT -0.25, -0.25, 0.25
+LBMReal D3Q27OffsetInterpolationProcessor::calcPressTSW()
+{
+   return   press_SWT * (0.421875 + 0.5625 * xoff + 0.5625 * yoff - 0.5625 * zoff) +
+            press_NWT * (0.140625 + 0.1875 * xoff - 0.5625 * yoff - 0.1875 * zoff) +
+            press_SET * (0.140625 - 0.5625 * xoff + 0.1875 * yoff - 0.1875 * zoff) +
+            press_NET * (0.046875 - 0.1875 * xoff - 0.1875 * yoff - 0.0625 * zoff) +
+            press_NEB * (0.015625 - 0.0625 * xoff - 0.0625 * yoff + 0.0625 * zoff) +
+            press_NWB * (0.046875 + 0.0625 * xoff - 0.1875 * yoff + 0.1875 * zoff) +
+            press_SEB * (0.046875 - 0.1875 * xoff + 0.0625 * yoff + 0.1875 * zoff) +
+            press_SWB * (0.140625 + 0.1875 * xoff + 0.1875 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position SET 0.25, -0.25, 0.25
+LBMReal D3Q27OffsetInterpolationProcessor::calcPressTSE()
+{
+   return   press_SET * (0.421875 - 0.5625 * xoff + 0.5625 * yoff - 0.5625 * zoff) +
+            press_NET * (0.140625 - 0.1875 * xoff - 0.5625 * yoff - 0.1875 * zoff) +
+            press_SWT * (0.140625 + 0.5625 * xoff + 0.1875 * yoff - 0.1875 * zoff) +
+            press_NWT * (0.046875 + 0.1875 * xoff - 0.1875 * yoff - 0.0625 * zoff) +
+            press_NWB * (0.015625 + 0.0625 * xoff - 0.0625 * yoff + 0.0625 * zoff) +
+            press_NEB * (0.046875 - 0.0625 * xoff - 0.1875 * yoff + 0.1875 * zoff) +
+            press_SWB * (0.046875 + 0.1875 * xoff + 0.0625 * yoff + 0.1875 * zoff) +
+            press_SEB * (0.140625 - 0.1875 * xoff + 0.1875 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position SEB 0.25, -0.25, -0.25
+LBMReal D3Q27OffsetInterpolationProcessor::calcPressBSE()
+{
+   return   press_SET * (0.140625 - 0.1875 * xoff + 0.1875 * yoff - 0.5625 * zoff) +
+            press_NET * (0.046875 - 0.0625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
+            press_SWT * (0.046875 + 0.1875 * xoff + 0.0625 * yoff - 0.1875 * zoff) +
+            press_NWT * (0.015625 + 0.0625 * xoff - 0.0625 * yoff - 0.0625 * zoff) +
+            press_NWB * (0.046875 + 0.1875 * xoff - 0.1875 * yoff + 0.0625 * zoff) +
+            press_NEB * (0.140625 - 0.1875 * xoff - 0.5625 * yoff + 0.1875 * zoff) +
+            press_SWB * (0.140625 + 0.5625 * xoff + 0.1875 * yoff + 0.1875 * zoff) +
+            press_SEB * (0.421875 - 0.5625 * xoff + 0.5625 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position NWB -0.25, 0.25, -0.25
+LBMReal D3Q27OffsetInterpolationProcessor::calcPressBNW()
+{
+   return   press_NWT * (0.140625 + 0.1875 * xoff - 0.1875 * yoff - 0.5625 * zoff) +
+            press_NET * (0.046875 - 0.1875 * xoff - 0.0625 * yoff - 0.1875 * zoff) +
+            press_SWT * (0.046875 + 0.0625 * xoff + 0.1875 * yoff - 0.1875 * zoff) +
+            press_SET * (0.015625 - 0.0625 * xoff + 0.0625 * yoff - 0.0625 * zoff) +
+            press_SEB * (0.046875 - 0.1875 * xoff + 0.1875 * yoff + 0.0625 * zoff) +
+            press_NEB * (0.140625 - 0.5625 * xoff - 0.1875 * yoff + 0.1875 * zoff) +
+            press_SWB * (0.140625 + 0.1875 * xoff + 0.5625 * yoff + 0.1875 * zoff) +
+            press_NWB * (0.421875 + 0.5625 * xoff - 0.5625 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position NWT -0.25, 0.25, 0.25
+LBMReal D3Q27OffsetInterpolationProcessor::calcPressTNW()
+{
+   return   press_NWT * (0.421875 + 0.5625 * xoff - 0.5625 * yoff - 0.5625 * zoff) +
+            press_NET * (0.140625 - 0.5625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
+            press_SWT * (0.140625 + 0.1875 * xoff + 0.5625 * yoff - 0.1875 * zoff) +
+            press_SET * (0.046875 - 0.1875 * xoff + 0.1875 * yoff - 0.0625 * zoff) +
+            press_SEB * (0.015625 - 0.0625 * xoff + 0.0625 * yoff + 0.0625 * zoff) +
+            press_NEB * (0.046875 - 0.1875 * xoff - 0.0625 * yoff + 0.1875 * zoff) +
+            press_SWB * (0.046875 + 0.0625 * xoff + 0.1875 * yoff + 0.1875 * zoff) +
+            press_NWB * (0.140625 + 0.1875 * xoff - 0.1875 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position NET 0.25, 0.25, 0.25
+LBMReal D3Q27OffsetInterpolationProcessor::calcPressTNE()
+{
+   return   press_NET * (0.421875 - 0.5625 * xoff - 0.5625 * yoff - 0.5625 * zoff) +
+            press_NWT * (0.140625 + 0.5625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
+            press_SET * (0.140625 - 0.1875 * xoff + 0.5625 * yoff - 0.1875 * zoff) +
+            press_SWT * (0.046875 + 0.1875 * xoff + 0.1875 * yoff - 0.0625 * zoff) +
+            press_SWB * (0.015625 + 0.0625 * xoff + 0.0625 * yoff + 0.0625 * zoff) +
+            press_NWB * (0.046875 + 0.1875 * xoff - 0.0625 * yoff + 0.1875 * zoff) +
+            press_SEB * (0.046875 - 0.0625 * xoff + 0.1875 * yoff + 0.1875 * zoff) +
+            press_NEB * (0.140625 - 0.1875 * xoff - 0.1875 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position NEB 0.25, 0.25, -0.25
+LBMReal D3Q27OffsetInterpolationProcessor::calcPressBNE()
+{
+   return   press_NET * (0.140625 - 0.1875 * xoff - 0.1875 * yoff - 0.5625 * zoff) +
+            press_NWT * (0.046875 + 0.1875 * xoff - 0.0625 * yoff - 0.1875 * zoff) +
+            press_SET * (0.046875 - 0.0625 * xoff + 0.1875 * yoff - 0.1875 * zoff) +
+            press_SWT * (0.015625 + 0.0625 * xoff + 0.0625 * yoff - 0.0625 * zoff) +
+            press_SWB * (0.046875 + 0.1875 * xoff + 0.1875 * yoff + 0.0625 * zoff) +
+            press_NWB * (0.140625 + 0.5625 * xoff - 0.1875 * yoff + 0.1875 * zoff) +
+            press_SEB * (0.140625 - 0.1875 * xoff + 0.5625 * yoff + 0.1875 * zoff) +
+            press_NEB * (0.421875 - 0.5625 * xoff - 0.5625 * yoff + 0.5625 * zoff);
+}
+//////////////////////////////////////////////////////////////////////////
+//Position C 0.0, 0.0, 0.0
+void D3Q27OffsetInterpolationProcessor::calcInterpolatedNodeFC(LBMReal* f, LBMReal omega)
+{
+   using namespace D3Q27System;
+
+   LBMReal press  =  press_NET * (0.125 - 0.25 * xoff - 0.25 * yoff - 0.25 * zoff) +
+                     press_NWT * (0.125 + 0.25 * xoff - 0.25 * yoff - 0.25 * zoff) +
+                     press_SET * (0.125 - 0.25 * xoff + 0.25 * yoff - 0.25 * zoff) +
+                     press_SWT * (0.125 + 0.25 * xoff + 0.25 * yoff - 0.25 * zoff) +
+                     press_NEB * (0.125 - 0.25 * xoff - 0.25 * yoff + 0.25 * zoff) +
+                     press_NWB * (0.125 + 0.25 * xoff - 0.25 * yoff + 0.25 * zoff) +
+                     press_SEB * (0.125 - 0.25 * xoff + 0.25 * yoff + 0.25 * zoff) +
+                     press_SWB * (0.125 + 0.25 * xoff + 0.25 * yoff + 0.25 * zoff);
+   LBMReal vx1  = a0;
+   LBMReal vx2  = b0;
+   LBMReal vx3  = c0;
+
+   LBMReal rho = press ;//+ (ax+by+cz)/3.;
+
+   LBMReal feq[ENDF+1];
+   calcFeqFct(feq,rho,vx1,vx2,vx3);
+
+   LBMReal eps_new = 2.;
+   LBMReal o  = omega;
+   LBMReal op = 1.;
+
+   f_E    = eps_new *((5.*ax*o + 5.*by*o + 5.*cz*o - 8.*ax*op + 4.*by*op + 4.*cz*op)/(54.*o*op));
+   f_N    = f_E + eps_new *((2.*(ax - by))/(9.*o));
+   f_T    = f_E + eps_new *((2.*(ax - cz))/(9.*o));
+   f_NE   = eps_new *(-(5.*cz*o + 3.*(ay + bx)*op - 2.*cz*op + ax*(5.*o + op) + by*(5.*o + op))/(54.*o*op));
+   f_SE   = f_NE + eps_new *((  ay + bx )/(9.*o));
+   f_TE   = eps_new *(-(5.*cz*o + by*(5.*o - 2.*op) + 3.*(az + cx)*op + cz*op + ax*(5.*o + op))/(54.*o*op));
+   f_BE   = f_TE + eps_new *((  az + cx )/(9.*o));
+   f_TN   = eps_new *(-(5.*ax*o + 5.*by*o + 5.*cz*o - 2.*ax*op + by*op + 3.*bz*op + 3.*cy*op + cz*op)/(54.*o*op));
+   f_BN   = f_TN + eps_new *((  bz + cy )/(9.*o));
+   f_ZERO = eps_new *((5.*(ax + by + cz))/(9.*op));
+   f_TNE  = eps_new *(-(ay + az + bx + bz + cx + cy)/(72.*o));
+   f_TSW  = - eps_new *((ay + bx)/(36.*o)) - f_TNE;
+   f_TSE  = - eps_new *((az + cx)/(36.*o)) - f_TNE;
+   f_TNW  = - eps_new *((bz + cy)/(36.*o)) - f_TNE;
+
+
+   f[E]    = f_E    + feq[E];
+   f[W]    = f_E    + feq[W];
+   f[N]    = f_N    + feq[N];
+   f[S]    = f_N    + feq[S];
+   f[T]    = f_T    + feq[T];
+   f[B]    = f_T    + feq[B];
+   f[NE]   = f_NE   + feq[NE];
+   f[SW]   = f_NE   + feq[SW];
+   f[SE]   = f_SE   + feq[SE];
+   f[NW]   = f_SE   + feq[NW];
+   f[TE]   = f_TE   + feq[TE];
+   f[BW]   = f_TE   + feq[BW];
+   f[BE]   = f_BE   + feq[BE];
+   f[TW]   = f_BE   + feq[TW];
+   f[TN]   = f_TN   + feq[TN];
+   f[BS]   = f_TN   + feq[BS];
+   f[BN]   = f_BN   + feq[BN];
+   f[TS]   = f_BN   + feq[TS];
+   f[TNE]  = f_TNE  + feq[TNE];
+   f[TNW]  = f_TNW  + feq[TNW];
+   f[TSE]  = f_TSE  + feq[TSE];
+   f[TSW]  = f_TSW  + feq[TSW];
+   f[BNE]  = f_TSW  + feq[BNE];
+   f[BNW]  = f_TSE  + feq[BNW];
+   f[BSE]  = f_TNW  + feq[BSE];
+   f[BSW]  = f_TNE  + feq[BSW];
+   f[ZERO] = f_ZERO + feq[ZERO];
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::calcInterpolatedVelocity(LBMReal x, LBMReal y, LBMReal z, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3)
+{
+   vx1  = a0 + ax*x + ay*y + az*z + axx*x*x + ayy*y*y + azz*z*z + axy*x*y + axz*x*z + ayz*y*z+axyz*x*y*z;
+   vx2  = b0 + bx*x + by*y + bz*z + bxx*x*x + byy*y*y + bzz*z*z + bxy*x*y + bxz*x*z + byz*y*z+bxyz*x*y*z;
+   vx3  = c0 + cx*x + cy*y + cz*z + cxx*x*x + cyy*y*y + czz*z*z + cxy*x*y + cxz*x*z + cyz*y*z+cxyz*x*y*z;
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27OffsetInterpolationProcessor::calcInterpolatedShearStress(LBMReal x, LBMReal y, LBMReal z,LBMReal& tauxx, LBMReal& tauyy, LBMReal& tauzz,LBMReal& tauxy, LBMReal& tauxz, LBMReal& tauyz)
+{
+   tauxx=ax+2*axx*x+axy*y+axz*z+axyz*y*z;
+   tauyy=by+2*byy*y+bxy*x+byz*z+bxyz*x*z;
+   tauzz=cz+2*czz*z+cxz*x+cyz*y+cxyz*x*y;
+   tauxy=0.5*((ay+2.0*ayy*y+axy*x+ayz*z+axyz*x*z)+(bx+2.0*bxx*x+bxy*y+bxz*z+bxyz*y*z));
+   tauxz=0.5*((az+2.0*azz*z+axz*x+ayz*y+axyz*x*y)+(cx+2.0*cxx*x+cxy*y+cxz*z+cxyz*y*z));
+   tauyz=0.5*((bz+2.0*bzz*z+bxz*x+byz*y+bxyz*x*y)+(cy+2.0*cyy*y+cxy*x+cyz*z+cxyz*x*z));
+}
+//////////////////////////////////////////////////////////////////////////
+
diff --git a/source/VirtualFluidsCore/LBM/D3Q27OffsetInterpolationProcessor.h b/source/VirtualFluidsCore/LBM/D3Q27OffsetInterpolationProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..29d37b810ff686b17e36cfad716f35649c8ce7b5
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27OffsetInterpolationProcessor.h
@@ -0,0 +1,81 @@
+#ifndef D3Q27OffsetInterpolationProcessor_H_
+#define D3Q27OffsetInterpolationProcessor_H_
+
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27System.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+//it work only for cascaded LBM
+//super compact interpolation method by Martin Geier
+//////////////////////////////////////////////////////////////////////////
+
+class D3Q27OffsetInterpolationProcessor;
+typedef boost::shared_ptr<D3Q27OffsetInterpolationProcessor> D3Q27OffsetInterpolationProcessorPtr;
+
+class D3Q27OffsetInterpolationProcessor : public D3Q27InterpolationProcessor
+{
+public:
+   D3Q27OffsetInterpolationProcessor();
+   D3Q27OffsetInterpolationProcessor(LBMReal omegaC, LBMReal omegaF);
+   virtual ~D3Q27OffsetInterpolationProcessor();
+   D3Q27InterpolationProcessorPtr clone();
+   void setOmegas(LBMReal omegaC, LBMReal omegaF);
+   void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF);
+   void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, LBMReal xoff, LBMReal yoff, LBMReal zoff);
+   void interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC); 
+   void interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC, LBMReal xoff, LBMReal yoff, LBMReal zoff); 
+protected:
+private:
+   typedef void      (*CalcMacrosFct)(const LBMReal* const& /*f[27]*/, LBMReal& /*rho*/, LBMReal& /*vx1*/, LBMReal& /*vx2*/, LBMReal& /*vx3*/);
+   typedef LBMReal (*CalcFeqForDirFct)(const int& /*direction*/,const LBMReal& /*(d)rho*/,const LBMReal& /*vx1*/,const LBMReal& /*vx2*/,const LBMReal& /*vx3*/);
+   typedef  void     (*CalcFeqFct)(LBMReal* const& /*feq/*[27]*/,const LBMReal& /*rho*/,const LBMReal& /*vx1*/,const LBMReal& /*vx2*/,const LBMReal& /*vx3*/);
+
+   CalcFeqForDirFct calcFeqsForDirFct;
+   CalcMacrosFct    calcMacrosFct;
+   CalcFeqFct       calcFeqFct;
+   LBMReal omegaC, omegaF;
+   LBMReal a0, ax, ay, az, axx, ayy, azz, axy, axz, ayz, b0, bx, by, bz, bxx, byy, bzz, bxy, bxz, byz, c0, cx, cy, cz, cxx, cyy, czz, cxy, cxz, cyz, axyz, bxyz, cxyz;
+   LBMReal xoff,    yoff,    zoff;
+   LBMReal xoff_sq, yoff_sq, zoff_sq;
+   LBMReal press_SWT, press_NWT, press_NET, press_SET, press_SWB, press_NWB, press_NEB, press_SEB;
+   
+   LBMReal  f_E,  f_N,  f_T,  f_NE,  f_SE,  f_BE,  f_TE,  f_TN,  f_BN,  f_TNE,  f_TNW,  f_TSE,  f_TSW,  f_ZERO;
+   LBMReal  x_E,  x_N,  x_T,  x_NE,  x_SE,  x_BE,  x_TE,  x_TN,  x_BN,  x_TNE,  x_TNW,  x_TSE,  x_TSW,  x_ZERO;
+   LBMReal  y_E,  y_N,  y_T,  y_NE,  y_SE,  y_BE,  y_TE,  y_TN,  y_BN,  y_TNE,  y_TNW,  y_TSE,  y_TSW,  y_ZERO;
+   LBMReal  z_E,  z_N,  z_T,  z_NE,  z_SE,  z_BE,  z_TE,  z_TN,  z_BN,  z_TNE,  z_TNW,  z_TSE,  z_TSW,  z_ZERO;
+   LBMReal xy_E, xy_N, xy_T, xy_NE, xy_SE, xy_BE, xy_TE, xy_TN, xy_BN, xy_TNE, xy_TNW, xy_TSE, xy_TSW/*, xy_ZERO*/;
+   LBMReal xz_E, xz_N, xz_T, xz_NE, xz_SE, xz_BE, xz_TE, xz_TN, xz_BN, xz_TNE, xz_TNW, xz_TSE, xz_TSW/*, xz_ZERO*/;
+   LBMReal yz_E, yz_N, yz_T, yz_NE, yz_SE, yz_BE, yz_TE, yz_TN, yz_BN, yz_TNE, yz_TNW, yz_TSE, yz_TSW/*, yz_ZERO*/;
+
+   void init();
+   void setOffsets(LBMReal xoff, LBMReal yoff, LBMReal zoff);
+   void calcMoments(const LBMReal* const f, LBMReal omega, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3, 
+      LBMReal& kxy, LBMReal& kyz, LBMReal& kxz, LBMReal& kxxMyy, LBMReal& kxxMzz);
+   void calcInterpolatedCoefficiets(const D3Q27ICell& icell, LBMReal omega, LBMReal eps_new);
+   void calcInterpolatedNode(LBMReal* f, LBMReal omega, LBMReal x, LBMReal y, LBMReal z, LBMReal press, LBMReal xs, LBMReal ys, LBMReal zs);
+   LBMReal calcPressBSW();
+   LBMReal calcPressTSW();
+   LBMReal calcPressTSE();
+   LBMReal calcPressBSE();
+   LBMReal calcPressBNW();
+   LBMReal calcPressTNW();
+   LBMReal calcPressTNE();
+   LBMReal calcPressBNE();
+   void calcInterpolatedNodeFC(LBMReal* f, LBMReal omega);
+   void calcInterpolatedVelocity(LBMReal x, LBMReal y, LBMReal z,LBMReal& vx1, LBMReal& vx2, LBMReal& vx3);
+   void calcInterpolatedShearStress(LBMReal x, LBMReal y, LBMReal z,LBMReal& tauxx, LBMReal& tauyy, LBMReal& tauzz,LBMReal& tauxy, LBMReal& tauxz, LBMReal& tauyz);
+};
+
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27OffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
+{
+   this->interpolateCoarseToFine(icellC, icellF, 0.0, 0.0, 0.0);
+}
+//////////////////////////////////////////////////////////////////////////
+inline void D3Q27OffsetInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, LBMReal* icellC)
+{
+   this->interpolateFineToCoarse(icellF, icellC, 0.0, 0.0, 0.0);
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/D3Q27System.cpp b/source/VirtualFluidsCore/LBM/D3Q27System.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..99b6e5b542c1e11beb59e83905e20a698f181376
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27System.cpp
@@ -0,0 +1,146 @@
+#include "D3Q27System.h"
+namespace D3Q27System
+{
+   //index             0   1   2   3   4   5  6   7   8    9  10  11  12  13  14  15  16  17  18//falsch
+   //f:              ZERO, E,  W,  N,  S,  T,  B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW
+   //const int EX1[] = { 0,  1, -1,  0,  0,  0,  0,  1, -1,  1, -1,  1, -1,  1, -1,  0,  0,  0,  0,  1, -1,  1, -1,  1, -1,  1, -1 };
+   //const int EX2[] = { 0,  0,  0,  1, -1,  0,  0,  1, -1, -1,  1,  0,  0,  0,  0,  1, -1,  1, -1,  1,  1, -1, -1,  1,  1, -1, -1 };
+   //const int EX3[] = { 0,  0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  1, -1, -1,  1,  1, -1, -1,  1,  1,  1,  1,  1, -1, -1, -1, -1 };
+
+   //index             0   1   2   3   4   5  6   7   8    9  10  11  12  13  14  15  16  17  18
+   //f:                E,  W,  N,  S,  T,  B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW
+   const int DX1[] = { 1, -1,  0,  0,  0,  0,  1, -1,  1, -1,  1, -1,  1, -1,  0,  0,  0,  0,  1, -1,  1, -1,  1, -1,  1, -1 };
+   const int DX2[] = { 0,  0,  1, -1,  0,  0,  1, -1, -1,  1,  0,  0,  0,  0,  1, -1,  1, -1,  1,  1, -1, -1,  1,  1, -1, -1 };
+   const int DX3[] = { 0,  0,  0,  0,  1, -1,  0,  0,  0,  0,  1, -1, -1,  1,  1, -1, -1,  1,  1,  1,  1,  1, -1, -1, -1, -1 };
+
+   ////index                0   1   2   3   4   5  6   7   8    9  10  11  12  13  14  15  16  17  18
+   ////f:                   E,  W,  N,  S,  T,  B, NE, SW, SE, NW, TE, BW, BE, TW, TN, BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW
+   const double WEIGTH[] = { c2o27, c2o27,  c2o27,  c2o27,  c2o27,  c2o27,  c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o54, c1o216, c1o216, c1o216, c1o216, c1o216, c1o216, c1o216, c1o216 , c8o27};
+  
+
+   const int INVDIR[] = { 
+                          INV_E,   
+                          INV_W,  
+                          INV_N,  
+                          INV_S,  
+                          INV_T,  
+                          INV_B,  
+                          INV_NE, 
+                          INV_SW, 
+                          INV_SE, 
+                          INV_NW,
+                          INV_TE, 
+                          INV_BW, 
+                          INV_BE, 
+                          INV_TW, 
+                          INV_TN, 
+                          INV_BS, 
+                          INV_BN, 
+                          INV_TS, 
+                          INV_TNE,
+                          INV_TNW,
+                          INV_TSE,
+                          INV_TSW,
+                          INV_BNE,
+                          INV_BNW,
+                          INV_BSE,
+                          INV_BSW    };
+}
+
+    //const int FSTARTDIR = 0;
+    //const int FENDDIR   = 25;   //D3Q27
+
+    //const int STARTF = 0;
+    //const int ENDF   = 26;   //D3Q27
+
+    //const int EX1[ENDF+1];
+    //const int EX2[ENDF+1];
+    //const int EX3[ENDF+1];
+
+    //const int STARTDIR = 0;
+    //const int ENDDIR   = 26; //alle geometrischen richtungen
+
+    //const int DX1[ENDDIR+1];
+    //const int DX2[ENDDIR+1];
+    //const int DX3[ENDDIR+1];
+
+
+    //const int E    /*f1 */ = 0;
+    //const int W    /*f2 */ = 1;
+    //const int N    /*f3 */ = 2;
+    //const int S    /*f4 */ = 3;
+    //const int T    /*f5 */ = 4;
+    //const int B    /*f6 */ = 5;
+    //const int NE   /*f7 */ = 6;
+    //const int SW   /*f8 */ = 7;
+    //const int SE   /*f9 */ = 8;
+    //const int NW   /*f10*/ = 9;
+    //const int TE   /*f11*/ = 10;
+    //const int BW   /*f12*/ = 11;
+    //const int BE   /*f13*/ = 12;
+    //const int TW   /*f14*/ = 13;
+    //const int TN   /*f15*/ = 14;
+    //const int BS   /*f16*/ = 15;
+    //const int BN   /*f17*/ = 16;
+    //const int TS   /*f18*/ = 17;
+    //const int TNE          = 18;
+    //const int TNW          = 19;
+    //const int TSE          = 20;
+    //const int TSW          = 21;
+    //const int BNE          = 22;
+    //const int BNW          = 23;
+    //const int BSE          = 24;
+    //const int BSW          = 25;
+    //const int ZERO /*f0 */ = 26;
+
+    //const int INV_E   = W;  
+    //const int INV_W   = E;  
+    //const int INV_N   = S;  
+    //const int INV_S   = N;  
+    //const int INV_T   = B;  
+    //const int INV_B   = T;  
+    //const int INV_NE  = SW; 
+    //const int INV_SW  = NE; 
+    //const int INV_SE  = NW; 
+    //const int INV_NW  = SE; 
+    //const int INV_TE  = BW; 
+    //const int INV_BW  = TE; 
+    //const int INV_BE  = TW; 
+    //const int INV_TW  = BE; 
+    //const int INV_TN  = BS; 
+    //const int INV_BS  = TN; 
+    //const int INV_BN  = TS; 
+    //const int INV_TS  = BN; 
+    //const int INV_TNE = BSW;
+    //const int INV_TNW = BSE;
+    //const int INV_TSE = BNW;
+    //const int INV_TSW = BNE;
+    //const int INV_BNE = TSW;
+    //const int INV_BNW = TSE;
+    //const int INV_BSE = TNW;
+    //const int INV_BSW = TNE;
+
+    //const int INVDIR[ENDDIR+1];
+
+    //const int M_RHO     = 0;  
+    //const int M_EN      = 1;  
+    //const int M_EPS     = 2;  
+    //const int M_JX1     = 3;  
+    //const int M_QX1     = 4;  
+    //const int M_JX2     = 5;  
+    //const int M_QX2     = 6;  
+    //const int M_JX3     = 7;  
+    //const int M_QX3     = 8;  
+    //const int M_3PX1X1  = 9;  
+    //const int M_3PIX1X1 = 10; 
+    //const int M_PWW     = 11; 
+    //const int M_PIWW    = 12; 
+    //const int M_PX1X2   = 13; 
+    //const int M_PX2X3   = 14; 
+    //const int M_PX1X3   = 15; 
+    //const int M_MX1     = 16; 
+    //const int M_MX2     = 17; 
+    //const int M_MX3     = 18; 
+
+    //const int STARTM = 0;
+    //const int ENDM   = 18;   //D3Q27
diff --git a/source/VirtualFluidsCore/LBM/D3Q27System.h b/source/VirtualFluidsCore/LBM/D3Q27System.h
new file mode 100644
index 0000000000000000000000000000000000000000..23c2fb8ef4106779cac5e5a6f7b7ece2cba0e27a
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/D3Q27System.h
@@ -0,0 +1,673 @@
+#ifndef D3Q27SYSTEM_H
+#define D3Q27SYSTEM_H
+
+#include <cmath>
+#include <string>
+#include <iostream>
+
+#ifdef RCF_USE_SF_SERIALIZATION
+   #include <SF/Serializer.hpp>
+
+   #if CAB_RCF <= 903
+      #include <SF/SerializeEnum.hpp>   
+   #endif
+#endif //RCF_USE_SF_SERIALIZATION
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbSystem.h>
+//#include "Patch3DSystem.h"
+#include "LBMSystem.h"
+	
+/*=========================================================================*/
+/*  D3Q27System                                                            */
+/*                                                                         */
+/**
+class for global system-functions
+<BR><BR>
+@author <A HREF="mailto:kucher@irmb.tu-bs.de">K. Kucher</A>
+@version 1.0 - 22.10.09
+*/ 
+
+/*
+usage: ...
+*/
+
+
+#ifndef SWIG
+   using namespace UbMath;
+#endif
+
+namespace D3Q27System
+{
+   //enum COLLISIONMODEL { UNDEFINED, INCOMPLBGKMODEL,   COMPLBGKMODEL,   COMPLBGKWTMODEL,   INCOMPLBGKLESMODEL, INCOMPLBGKNONNEWTONIANMODEL    
+   //                               , INCOMPGLBEJTMODEL, COMPGLBEJTMODEL, COMPGLBEJTWTMODEL, INCOMPGLBEJTLESMODEL, INCOMPGLBEJTWALEMODEL  
+   //                               , CASCADEDMODEL};
+   //
+   // #if defined(RCF_USE_SF_SERIALIZATION) && (CAB_RCF <= 903)
+   //    SF_SERIALIZE_ENUM(COLLISIONMODEL) //muss im namespace stehen, sonst funzt es nicht!
+   // #endif
+
+   ///*=====================================================================*/
+   //std::string toString(const COLLISIONMODEL& model);
+   ///*=====================================================================*/
+   //COLLISIONMODEL getCollModelByString(const std::string& str);
+   ///*=====================================================================*/
+
+   ///*=====================================================================*/
+   //static bool isCompModel(const COLLISIONMODEL& model) 
+   //{
+   //   switch(model)
+   //   {
+   //   case COMPLBGKMODEL               : return true; 
+   //   case COMPLBGKWTMODEL             : return true; 
+   //   case COMPGLBEJTWTMODEL           : return true;
+   //   case COMPGLBEJTMODEL             : return true;
+   //   case CASCADEDMODEL               : return true;
+   //   
+   //   case INCOMPLBGKMODEL             : return false;
+   //   case INCOMPGLBEJTMODEL           : return false;
+   //   case INCOMPLBGKLESMODEL          : return false;
+   //   case INCOMPGLBEJTLESMODEL        : return false;
+   //   case INCOMPGLBEJTWALEMODEL       : return false;
+   //   case INCOMPLBGKNONNEWTONIANMODEL : return false;
+
+   //   default: throw UbException(UB_EXARGS,"unknown model");
+   //   }
+   //}
+   ///*=====================================================================*/
+   //static bool isGLBEModel(const COLLISIONMODEL& model) 
+   //{
+   //   switch(model)
+   //   {
+   //   case COMPGLBEJTWTMODEL           : return true;
+   //   case COMPGLBEJTMODEL             : return true;
+   //   case INCOMPGLBEJTMODEL           : return true;
+   //   case INCOMPGLBEJTLESMODEL        : return true;
+   //   case INCOMPGLBEJTWALEMODEL       : return false;
+
+   //   case COMPLBGKMODEL               : return false; 
+   //   case COMPLBGKWTMODEL             : return false; 
+   //   case INCOMPLBGKMODEL             : return false;
+   //   case INCOMPLBGKLESMODEL          : return false;
+   //   case INCOMPLBGKNONNEWTONIANMODEL : return false;
+
+   //   default: throw UbException(UB_EXARGS,"unknown model");
+   //   }
+   //}
+   //static bool isLESModel(const COLLISIONMODEL& model) 
+   //{
+   //   switch(model)
+   //   {
+   //   case INCOMPGLBEJTLESMODEL        : return true;
+   //   case INCOMPLBGKLESMODEL          : return true;
+   //   case INCOMPGLBEJTWALEMODEL       : return true;
+   //   
+   //   case COMPGLBEJTWTMODEL           : return false;
+   //   case COMPGLBEJTMODEL             : return false;
+   //   case INCOMPGLBEJTMODEL           : return false;
+   //   case COMPLBGKMODEL               : return false; 
+   //   case COMPLBGKWTMODEL             : return false; 
+   //   case INCOMPLBGKMODEL             : return false;
+   //   case INCOMPLBGKNONNEWTONIANMODEL : return false;
+
+   //   default: throw UbException(UB_EXARGS,"unknown model");
+   //   }
+   //}
+
+   //////////////////////////////////////////////////////////////////////////
+   //////////////////////////////////////////////////////////////////////////
+   //DIRECTION STUFF
+   static const int FSTARTDIR = 0;
+   static const int FENDDIR   = 25;   //D3Q27
+
+   //static const int FSTARTDIR = 1;
+   //static const int FENDDIR   = 26;   //D3Q27
+
+   static const int STARTF = 0;
+   static const int ENDF   = 26;   //D3Q27
+
+   //extern const int EX1[ENDF+1];
+   //extern const int EX2[ENDF+1];
+   //extern const int EX3[ENDF+1];
+
+   static const int STARTDIR = 0;
+   static const int ENDDIR   = 26; //alle geometrischen richtungen
+
+   extern const int DX1[ENDDIR+1];
+   extern const int DX2[ENDDIR+1];
+   extern const int DX3[ENDDIR+1];
+   extern const double WEIGTH[ENDDIR+1];
+   
+   //static const int ZERO /*f0 */ = 0;
+   //static const int E    /*f1 */ = 1;
+   //static const int W    /*f2 */ = 2;
+   //static const int N    /*f3 */ = 3;
+   //static const int S    /*f4 */ = 4;
+   //static const int T    /*f5 */ = 5;
+   //static const int B    /*f6 */ = 6;
+   //static const int NE   /*f7 */ = 7;
+   //static const int SW   /*f8 */ = 8;
+   //static const int SE   /*f9 */ = 9;
+   //static const int NW   /*f10*/ = 10;
+   //static const int TE   /*f11*/ = 11;
+   //static const int BW   /*f12*/ = 12;
+   //static const int BE   /*f13*/ = 13;
+   //static const int TW   /*f14*/ = 14;
+   //static const int TN   /*f15*/ = 15;
+   //static const int BS   /*f16*/ = 16;
+   //static const int BN   /*f17*/ = 17;
+   //static const int TS   /*f18*/ = 18;
+   //static const int TNE          = 19;
+   //static const int TNW          = 20;
+   //static const int TSE          = 21;
+   //static const int TSW          = 22;
+   //static const int BNE          = 23;
+   //static const int BNW          = 24;
+   //static const int BSE          = 25;
+   //static const int BSW          = 26;
+
+   static const int E    /*f1 */ = 0;
+   static const int W    /*f2 */ = 1;
+   static const int N    /*f3 */ = 2;
+   static const int S    /*f4 */ = 3;
+   static const int T    /*f5 */ = 4;
+   static const int B    /*f6 */ = 5;
+   static const int NE   /*f7 */ = 6;
+   static const int SW   /*f8 */ = 7;
+   static const int SE   /*f9 */ = 8;
+   static const int NW   /*f10*/ = 9;
+   static const int TE   /*f11*/ = 10;
+   static const int BW   /*f12*/ = 11;
+   static const int BE   /*f13*/ = 12;
+   static const int TW   /*f14*/ = 13;
+   static const int TN   /*f15*/ = 14;
+   static const int BS   /*f16*/ = 15;
+   static const int BN   /*f17*/ = 16;
+   static const int TS   /*f18*/ = 17;
+   static const int TNE          = 18;
+   static const int TNW          = 19;
+   static const int TSE          = 20;
+   static const int TSW          = 21;
+   static const int BNE          = 22;
+   static const int BNW          = 23;
+   static const int BSE          = 24;
+   static const int BSW          = 25;
+   static const int ZERO /*f0 */ = 26;
+
+   static const int INV_E   = W;  
+   static const int INV_W   = E;  
+   static const int INV_N   = S;  
+   static const int INV_S   = N;  
+   static const int INV_T   = B;  
+   static const int INV_B   = T;  
+   static const int INV_NE  = SW; 
+   static const int INV_SW  = NE; 
+   static const int INV_SE  = NW; 
+   static const int INV_NW  = SE; 
+   static const int INV_TE  = BW; 
+   static const int INV_BW  = TE; 
+   static const int INV_BE  = TW; 
+   static const int INV_TW  = BE; 
+   static const int INV_TN  = BS; 
+   static const int INV_BS  = TN; 
+   static const int INV_BN  = TS; 
+   static const int INV_TS  = BN; 
+   static const int INV_TNE = BSW;
+   static const int INV_TNW = BSE;
+   static const int INV_TSE = BNW;
+   static const int INV_TSW = BNE;
+   static const int INV_BNE = TSW;
+   static const int INV_BNW = TSE;
+   static const int INV_BSE = TNW;
+   static const int INV_BSW = TNE;
+                                       
+   extern const int INVDIR[ENDDIR+1];
+
+   static const int ET_E   = 0;
+   static const int ET_W   = 0;
+   static const int ET_N   = 1;
+   static const int ET_S   = 1;
+   static const int ET_T   = 2;
+   static const int ET_B   = 2;
+   static const int ET_NE  = 3;
+   static const int ET_SW  = 3;
+   static const int ET_SE  = 4;
+   static const int ET_NW  = 4;
+   static const int ET_TE  = 5;
+   static const int ET_BW  = 5;
+   static const int ET_BE  = 6;
+   static const int ET_TW  = 6;
+   static const int ET_TN  = 7;
+   static const int ET_BS  = 7;
+   static const int ET_BN  = 8;
+   static const int ET_TS  = 8;
+   static const int ET_TNE = 9;
+   static const int ET_BSW = 9;
+   static const int ET_TNW = 10;
+   static const int ET_BSE = 10;
+   static const int ET_TSE = 11;
+   static const int ET_BNW = 11;
+   static const int ET_TSW = 12;
+   static const int ET_BNE = 12;
+
+   static const int M_RHO     = 0;  
+   static const int M_EN      = 1;  
+   static const int M_EPS     = 2;  
+   static const int M_JX1     = 3;  
+   static const int M_QX1     = 4;  
+   static const int M_JX2     = 5;  
+   static const int M_QX2     = 6;  
+   static const int M_JX3     = 7;  
+   static const int M_QX3     = 8;  
+   static const int M_3PX1X1  = 9;  
+   static const int M_3PIX1X1 = 10; 
+   static const int M_PWW     = 11; 
+   static const int M_PIWW    = 12; 
+   static const int M_PX1X2   = 13; 
+   static const int M_PX2X3   = 14; 
+   static const int M_PX1X3   = 15; 
+   static const int M_MX1     = 16; 
+   static const int M_MX2     = 17; 
+   static const int M_MX3     = 18; 
+   
+   static const int STARTM = 0;
+   static const int ENDM   = 18;   //D3Q27
+
+
+   
+   //////////////////////////////////////////////////////////////////////////
+   //MACROSCOPIC VALUES                  
+   /*=====================================================================*/
+   static LBMReal getDensity(const LBMReal* const& f/*[27]*/)
+   {
+      return  ((f[TNE] + f[BSW])+(f[TSE]+f[BNW]))+((f[BSE]+f[TNW])+ (f[TSW]+f[BNE]))
+             +(((f[NE] + f[SW]) + (f[SE] + f[NW]))+((f[TE] + f[BW])+(f[BE]+ f[TW]))
+             +((f[BN] + f[TS]) + (f[TN] + f[BS])))+((f[E] + f[W])+(f[N] + f[S])
+             +(f[T] + f[B]))+f[ZERO];
+   }
+   /*=====================================================================*/
+   //ACHTUNG: gilt nicht fuer alle modelle -> praedikat verwenden anstelle static! toDo
+   static LBMReal getPressure(const LBMReal* const& f/*[27]*/)
+   {
+      return  REAL_CAST( c1o3 )*getDensity(f);
+   }
+   /*=====================================================================*/
+   static LBMReal getIncompVelocityX1(const LBMReal* const& f/*[27]*/)
+   {
+      return ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) +
+             (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) +
+             (f[E]-f[W]));  
+   }
+   /*=====================================================================*/
+   static LBMReal getIncompVelocityX2(const LBMReal* const& f/*[27]*/)
+   {
+      return ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) +
+             (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) +
+             (f[N]-f[S]));  
+   }
+   /*=====================================================================*/
+   static LBMReal getIncompVelocityX3(const LBMReal* const& f/*[27]*/)
+   {
+      return ((((f[TNE] - f[BSW]) + (f[TSE] - f[BNW])) + ((f[TNW] - f[BSE]) + (f[TSW] - f[BNE]))) +
+             (((f[TS] - f[BN]) + (f[TN] - f[BS])) + ((f[TW] - f[BE]) + (f[TE] - f[BW]))) +
+             (f[T] - f[B]));
+   }
+   /*=====================================================================*/
+   static void calcDensity(const LBMReal* const& f/*[27]*/, LBMReal& rho)
+   {
+      rho = ((f[TNE] + f[BSW])+(f[TSE]+f[BNW]))+((f[BSE]+f[TNW])+ (f[TSW]+f[BNE]))
+         +(((f[NE] + f[SW]) + (f[SE] + f[NW]))+((f[TE] + f[BW])+(f[BE]+ f[TW]))
+         +((f[BN] + f[TS]) + (f[TN] + f[BS])))+((f[E] + f[W])+(f[N] + f[S])
+         +(f[T] + f[B]))+f[ZERO];
+         
+   }
+   /*=====================================================================*/
+   static void calcIncompVelocityX1(const LBMReal* const& f/*[27]*/, LBMReal& vx1)
+   {
+      vx1 = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) +
+             (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) +
+             (f[E]-f[W]));
+   }
+   /*=====================================================================*/
+   static void calcIncompVelocityX2(const LBMReal* const& f/*[27]*/, LBMReal& vx2)
+   {
+      vx2 = ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) +
+             (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) +
+             (f[N]-f[S]));
+   }
+   /*=====================================================================*/
+   static void calcIncompVelocityX3(const LBMReal* const& f/*[27]*/, LBMReal& vx3)
+   {
+      vx3 =((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[TNW]-f[BSE]) + (f[TSW]-f[BNE]))) +
+             (((f[TS]-f[BN]) + (f[TN]-f[BS])) + ((f[TW]-f[BE]) + (f[TE]-f[BW]))) +
+             (f[T]-f[B]));
+   }
+   /*=====================================================================*/
+   static LBMReal getCompVelocityX1(const LBMReal* const& f/*[27]*/)
+   {
+      return ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) +
+             (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) +
+             (f[E]-f[W]))/getDensity(f);  
+   }
+   /*=====================================================================*/
+   static LBMReal getCompVelocityX2(const LBMReal* const& f/*[27]*/)
+   {
+      return ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) +
+             (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) +
+             (f[N]-f[S]))/getDensity(f);  
+  }
+   /*=====================================================================*/
+   static LBMReal getCompVelocityX3(const LBMReal* const& f/*[27]*/)
+   {
+      return ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[TNW]-f[BSE]) + (f[TSW]-f[BNE]))) +
+             (((f[TS]-f[BN]) + (f[TN]-f[BS])) + ((f[TW]-f[BE]) + (f[TE]-f[BW]))) +
+             (f[T]-f[B]))/getDensity(f);
+   }
+   /*=====================================================================*/
+   static void calcCompVelocityX1(const LBMReal* const& f/*[27]*/, LBMReal& vx1)
+   {
+      vx1 = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) +
+            (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) +
+            (f[E]-f[W]))/getDensity(f);  
+   }
+   /*=====================================================================*/
+   static void calcCompVelocityX2(const LBMReal* const& f/*[27]*/, LBMReal& vx2)
+   {
+      vx2 = ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) +
+            (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) +
+            (f[N]-f[S]))/getDensity(f);  
+   }
+   /*=====================================================================*/
+   static void calcCompVelocityX3(const LBMReal* const& f/*[27]*/, LBMReal& vx3)
+   {
+      vx3 = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[TNW]-f[BSE]) + (f[TSW]-f[BNE]))) +
+            (((f[TS]-f[BN]) + (f[TN]-f[BS])) + ((f[TW]-f[BE]) + (f[TE]-f[BW]))) +
+            (f[T]-f[B]))/getDensity(f);
+   }
+   /*=====================================================================*/
+   static void calcIncompMacroscopicValues(const LBMReal* const& f/*[27]*/, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3)
+   {
+      D3Q27System::calcDensity(f, rho);
+      D3Q27System::calcIncompVelocityX1(f, vx1);
+      D3Q27System::calcIncompVelocityX2(f, vx2);
+      D3Q27System::calcIncompVelocityX3(f, vx3);
+   }
+
+   /*=====================================================================*/
+   static void calcCompMacroscopicValues(const LBMReal* const& f/*[27]*/, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3)
+   {
+      D3Q27System::calcDensity(f, rho);
+      D3Q27System::calcIncompVelocityX1(f, vx1);
+      D3Q27System::calcIncompVelocityX2(f, vx2);
+      D3Q27System::calcIncompVelocityX3(f, vx3);
+      vx1/=rho;
+      vx2/=rho;
+      vx3/=rho;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static LBMReal getCompFeqForDirection(const int& direction, const LBMReal& rho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3)
+   {
+      LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+      switch(direction)    
+      {
+         case ZERO : return REAL_CAST( c8o27*rho*(1.0-cu_sq));
+         case E : return REAL_CAST(  c2o27*rho*(1.0+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq));
+         case W : return REAL_CAST(  c2o27*rho*(1.0+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq));
+         case N : return REAL_CAST(  c2o27*rho*(1.0+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq));
+         case S : return REAL_CAST(  c2o27*rho*(1.0+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq));
+         case T : return REAL_CAST(  c2o27*rho*(1.0+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq));
+         case B : return REAL_CAST(  c2o27*rho*(1.0+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq));
+         case NE : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq));
+         case SW : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq));
+         case SE : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq));
+         case NW : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq));
+         case TE : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq));
+         case BW : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq));
+         case BE : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq));
+         case TW : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq));
+         case TN : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq));
+         case BS : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq));
+         case BN : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq));
+         case TS : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq));
+         case TNE : return REAL_CAST(c1o216*rho*(1.0+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq));
+         case BSW : return REAL_CAST(c1o216*rho*(1.0+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq));
+         case BNE : return REAL_CAST(c1o216*rho*(1.0+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq));
+         case TSW : return REAL_CAST(c1o216*rho*(1.0+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq));
+         case TSE : return REAL_CAST(c1o216*rho*(1.0+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq));
+         case BNW : return REAL_CAST(c1o216*rho*(1.0+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq));
+         case BSE : return REAL_CAST(c1o216*rho*(1.0+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq));
+         case TNW : return REAL_CAST(c1o216*rho*(1.0+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq));
+         default: throw UbException(UB_EXARGS,"unknown dir");
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void calcCompFeq(LBMReal* const& feq/*[27]*/,const LBMReal& rho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3)	
+   {
+      LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+      feq[ZERO] =  c8o27*rho*(1.0-cu_sq);
+      feq[E] =   c2o27*rho*(1.0+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq);
+      feq[W] =   c2o27*rho*(1.0+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq);
+      feq[N] =   c2o27*rho*(1.0+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq);
+      feq[S] =   c2o27*rho*(1.0+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq);
+      feq[T] =   c2o27*rho*(1.0+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq);
+      feq[B] =   c2o27*rho*(1.0+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq);
+      feq[NE] =  c1o54*rho*(1.0+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq);
+      feq[SW] =  c1o54*rho*(1.0+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq);
+      feq[SE] =  c1o54*rho*(1.0+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq);
+      feq[NW] =  c1o54*rho*(1.0+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq);
+      feq[TE] =  c1o54*rho*(1.0+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq);
+      feq[BW] =  c1o54*rho*(1.0+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq);
+      feq[BE] =  c1o54*rho*(1.0+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq);
+      feq[TW] =  c1o54*rho*(1.0+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq);
+      feq[TN] =  c1o54*rho*(1.0+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq);
+      feq[BS] =  c1o54*rho*(1.0+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq);
+      feq[BN] =  c1o54*rho*(1.0+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq);
+      feq[TS] =  c1o54*rho*(1.0+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq);
+      feq[TNE] = c1o216*rho*(1.0+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq);
+      feq[BSW] = c1o216*rho*(1.0+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq);
+      feq[BNE] = c1o216*rho*(1.0+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq);
+      feq[TSW] = c1o216*rho*(1.0+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq);
+      feq[TSE] = c1o216*rho*(1.0+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq);
+      feq[BNW] = c1o216*rho*(1.0+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq);
+      feq[BSE] = c1o216*rho*(1.0+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq);
+      feq[TNW] = c1o216*rho*(1.0+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static LBMReal getIncompFeqForDirection(const int& direction,const LBMReal& drho, const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3)	
+   {	
+      LBMReal cu_sq=1.5f*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+      switch(direction)    
+      {		 
+         case ZERO : return REAL_CAST( c8o27*(drho-cu_sq));
+         case E : return REAL_CAST( c2o27*(drho+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq));
+         case W : return REAL_CAST( c2o27*(drho+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq));
+         case N : return REAL_CAST( c2o27*(drho+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq));
+         case S : return REAL_CAST( c2o27*(drho+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq));
+         case T : return REAL_CAST( c2o27*(drho+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq));
+         case B : return REAL_CAST( c2o27*(drho+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq));
+         case NE : return REAL_CAST( c1o54*(drho+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq));
+         case SW : return REAL_CAST( c1o54*(drho+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq));
+         case SE : return REAL_CAST( c1o54*(drho+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq));
+         case NW : return REAL_CAST( c1o54*(drho+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq));
+         case TE : return REAL_CAST( c1o54*(drho+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq));
+         case BW : return REAL_CAST( c1o54*(drho+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq));
+         case BE : return REAL_CAST( c1o54*(drho+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq));
+         case TW : return REAL_CAST( c1o54*(drho+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq));
+         case TN : return REAL_CAST( c1o54*(drho+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq));
+         case BS : return REAL_CAST( c1o54*(drho+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq));
+         case BN : return REAL_CAST( c1o54*(drho+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq));
+         case TS : return REAL_CAST( c1o54*(drho+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq));
+         case TNE : return REAL_CAST(c1o216*(drho+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq));
+         case BSW : return REAL_CAST(c1o216*(drho+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq));
+         case BNE : return REAL_CAST(c1o216*(drho+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq));
+         case TSW : return REAL_CAST(c1o216*(drho+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq));
+         case TSE : return REAL_CAST(c1o216*(drho+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq));
+         case BNW : return REAL_CAST(c1o216*(drho+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq));
+         case BSE : return REAL_CAST(c1o216*(drho+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq));
+         case TNW : return REAL_CAST(c1o216*(drho+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq));
+         default: throw UbException(UB_EXARGS,"unknown dir");
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void calcIncompFeq(LBMReal* const& feq/*[27]*/,const LBMReal& drho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3)	
+   {
+      LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+      feq[ZERO] =  c8o27*(drho-cu_sq);
+      feq[E] =  c2o27*(drho+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq);
+      feq[W] =  c2o27*(drho+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq);
+      feq[N] =  c2o27*(drho+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq);
+      feq[S] =  c2o27*(drho+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq);
+      feq[T] =  c2o27*(drho+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq);
+      feq[B] =  c2o27*(drho+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq);
+      feq[NE] =  c1o54*(drho+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq);
+      feq[SW] =  c1o54*(drho+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq);
+      feq[SE] =  c1o54*(drho+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq);
+      feq[NW] =  c1o54*(drho+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq);
+      feq[TE] =  c1o54*(drho+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq);
+      feq[BW] =  c1o54*(drho+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq);
+      feq[BE] =  c1o54*(drho+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq);
+      feq[TW] =  c1o54*(drho+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq);
+      feq[TN] =  c1o54*(drho+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq);
+      feq[BS] =  c1o54*(drho+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq);
+      feq[BN] =  c1o54*(drho+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq);
+      feq[TS] =  c1o54*(drho+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq);
+      feq[TNE] = c1o216*(drho+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq);
+      feq[BSW] = c1o216*(drho+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq);
+      feq[BNE] = c1o216*(drho+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq);
+      feq[TSW] = c1o216*(drho+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq);
+      feq[TSE] = c1o216*(drho+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq);
+      feq[BNW] = c1o216*(drho+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq);
+      feq[BSE] = c1o216*(drho+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq);
+      feq[TNW] = c1o216*(drho+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq);   
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static inline float getBoundaryVelocityForDirection(const int& direction, const float& bcVelocityX1,const float& bcVelocityX2,const float& bcVelocityX3)
+   {
+      switch(direction) 
+      {          
+      case E:   return (float)( UbMath::c4o9*(+bcVelocityX1) );
+      case W:   return (float)( UbMath::c4o9*(-bcVelocityX1) );
+      case N:   return (float)( UbMath::c4o9*(+bcVelocityX2) );
+      case S:   return (float)( UbMath::c4o9*(-bcVelocityX2) );
+      case T:   return (float)( UbMath::c4o9*(+bcVelocityX3) );
+      case B:   return (float)( UbMath::c4o9*(-bcVelocityX3) );
+      case NE:  return (float)( UbMath::c1o9*(+bcVelocityX1+bcVelocityX2             ) );
+      case SW:  return (float)( UbMath::c1o9*(-bcVelocityX1-bcVelocityX2             ) );
+      case SE:  return (float)( UbMath::c1o9*(+bcVelocityX1-bcVelocityX2             ) );
+      case NW:  return (float)( UbMath::c1o9*(-bcVelocityX1+bcVelocityX2             ) );
+      case TE:  return (float)( UbMath::c1o9*(+bcVelocityX1             +bcVelocityX3) );
+      case BW:  return (float)( UbMath::c1o9*(-bcVelocityX1             -bcVelocityX3) );
+      case BE:  return (float)( UbMath::c1o9*(+bcVelocityX1             -bcVelocityX3) );
+      case TW:  return (float)( UbMath::c1o9*(-bcVelocityX1             +bcVelocityX3) );
+      case TN:  return (float)( UbMath::c1o9*(             +bcVelocityX2+bcVelocityX3) );
+      case BS:  return (float)( UbMath::c1o9*(             -bcVelocityX2-bcVelocityX3) );
+      case BN:  return (float)( UbMath::c1o9*(             +bcVelocityX2-bcVelocityX3) );
+      case TS:  return (float)( UbMath::c1o9*(             -bcVelocityX2+bcVelocityX3) );
+      case TNE: return (float)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2+bcVelocityX3) );
+      case BSW: return (float)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2-bcVelocityX3) );
+      case BNE: return (float)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2-bcVelocityX3) );
+      case TSW: return (float)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2+bcVelocityX3) );
+      case TSE: return (float)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2+bcVelocityX3) );
+      case BNW: return (float)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2-bcVelocityX3) );
+      case BSE: return (float)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2-bcVelocityX3) );
+      case TNW: return (float)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2+bcVelocityX3) );
+      default: throw UbException(UB_EXARGS,"unknown direction"); 
+      }
+   }
+   /*=====================================================================*/
+   static const int& getInvertDirection(const int& direction)
+   {  
+   #ifdef _DEBUG
+      if(direction<STARTDIR || direction>ENDDIR) 
+         throw UbException(UB_EXARGS,"unknown direction");
+   #endif
+      return INVDIR[direction];
+   }
+   /*=====================================================================*/
+   static void getLBMDirections(std::vector<int>& dirs, bool onlyLBdirs = false)
+   {
+      std::vector<int> D3Q27Dirs;
+      if(onlyLBdirs) /*FSTARTDIR->FENDDIR*/
+      {
+         dirs.resize(FENDDIR+1);
+         for(int dir=FSTARTDIR; dir<=FENDDIR; ++dir)
+            dirs[dir] = dir;
+      }
+      else /*STARTDIR->ENDDIR*/
+      {
+         dirs.resize(ENDDIR+1);
+         for(int dir=STARTDIR; dir<=ENDDIR; ++dir)
+            dirs[dir] = dir;
+      }
+   }
+//////////////////////////////////////////////////////////////////////////
+   static std::vector<int> getEX(const int& exn)
+   {
+      std::vector<int> ex;
+      ex.resize(ENDDIR+1);
+      switch (exn)
+      {
+      case 1:
+         for(int dir=STARTDIR; dir<ENDDIR; ++dir)
+            ex[dir] = DX1[dir];
+      	break;
+      case 2:
+         for(int dir=STARTDIR; dir<ENDDIR; ++dir)
+            ex[dir] = DX2[dir];
+         break;
+      case 3:
+         for(int dir=STARTDIR; dir<ENDDIR; ++dir)
+            ex[dir] = DX3[dir];
+         break;
+      }
+      return ex;
+   }
+//////////////////////////////////////////////////////////////////////////
+   static inline void calcDistanceToNeighbors(std::vector<double>& distNeigh, const double& deltaX1)
+   {
+      //distNeigh.resize(FENDDIR+1, UbMath::sqrt2*deltaX1);
+      double sqrt3 = UbMath::sqrt3;
+      double sqrt2 = UbMath::sqrt2;
+      distNeigh[E] = distNeigh[W] = distNeigh[N] = deltaX1;
+      distNeigh[S] = distNeigh[T] = distNeigh[B] = deltaX1;
+      distNeigh[NE] = distNeigh[NW] = distNeigh[SW] = distNeigh[SE] = sqrt2*deltaX1;
+      distNeigh[TE] = distNeigh[TN] = distNeigh[TW] = distNeigh[TS] = sqrt2*deltaX1;
+      distNeigh[BE] = distNeigh[BN] = distNeigh[BW] = distNeigh[BS] = sqrt2*deltaX1;
+      distNeigh[TNE] = distNeigh[TNW] = distNeigh[TSE] = distNeigh[TSW] = sqrt3*deltaX1;
+      distNeigh[BNE] = distNeigh[BNW] = distNeigh[BSE] = distNeigh[BSW] = sqrt3*deltaX1;
+   }
+//////////////////////////////////////////////////////////////////////////
+   static inline void calcDistanceToNeighbors(std::vector<double>& distNeigh, const double& deltaX1,const double& deltaX2,const double& deltaX3)
+   {
+      //distNeigh.resize(FENDDIR+1, UbMath::sqrt2*deltaX1);
+      double sqrt3 = UbMath::sqrt3;
+      double sqrt2 = UbMath::sqrt2;
+      distNeigh[E] = distNeigh[W] =  deltaX1;
+      distNeigh[N] = distNeigh[S] =  deltaX2;
+      distNeigh[T] = distNeigh[B] = deltaX3;
+      distNeigh[NE] = distNeigh[NW] = distNeigh[SW] = distNeigh[SE] = sqrt(deltaX1*deltaX1+deltaX2*deltaX2);
+      distNeigh[TE] = distNeigh[TN] = distNeigh[TW] = distNeigh[TS] = sqrt(deltaX1*deltaX1+deltaX3*deltaX3);
+      distNeigh[BE] = distNeigh[BN] = distNeigh[BW] = distNeigh[BS] = sqrt(deltaX2*deltaX2+deltaX3*deltaX3);
+      distNeigh[TNE] = distNeigh[TNW] = distNeigh[TSE] = distNeigh[TSW] = sqrt(deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3);
+      distNeigh[BNE] = distNeigh[BNW] = distNeigh[BSE] = distNeigh[BSW] = sqrt(deltaX1*deltaX1+deltaX2*deltaX2+deltaX3*deltaX3);
+   }
+//////////////////////////////////////////////////////////////////////////
+   static inline LBMReal calcPress(const LBMReal* const f, LBMReal rho, LBMReal vx1, LBMReal vx2, LBMReal vx3)
+   {
+      LBMReal op=1.0;
+      return ((f[E]+f[W]+f[N]+f[S]+f[T]+f[B]+2.*(f[NE]+f[SW]+f[SE]+f[NW]+f[TE]+f[BW]+f[BE]+f[TW]+f[TN]+f[BS]+f[BN]+f[TS])+
+         3.*(f[TNE]+f[TSW]+f[TSE]+f[TNW]+f[BNE]+f[BSW]+f[BSE]+f[BNW])-(vx1*vx1+vx2*vx2+vx3*vx3))*(1-0.5*op)+op*0.5*(rho))*c1o3;
+
+   }
+}
+
+#endif
+
+
+
diff --git a/source/VirtualFluidsCore/LBM/ICell.h b/source/VirtualFluidsCore/LBM/ICell.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9a05924bf02604de18a5d99017e067eeb3e3b63
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/ICell.h
@@ -0,0 +1,33 @@
+#ifndef ICell_H
+#define ICell_H
+
+#include "LBMSystem.h"
+#include <vector>
+
+struct ICell3D
+{
+   ICell3D(int size);
+
+   std::vector<LBMReal> TSW; 
+   std::vector<LBMReal> TNW;
+   std::vector<LBMReal> TNE;
+   std::vector<LBMReal> TSE;
+   std::vector<LBMReal> BSW;
+   std::vector<LBMReal> BNW;
+   std::vector<LBMReal> BNE;
+   std::vector<LBMReal> BSE;
+};
+
+ICell3D::ICell3D(int size)
+{
+   TSW.resize(size); 
+   TNW.resize(size);
+   TNE.resize(size);
+   TSE.resize(size);
+   BSW.resize(size);
+   BNW.resize(size);
+   BNE.resize(size);
+   BSE.resize(size);
+}
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/InterpolationProcessor.h b/source/VirtualFluidsCore/LBM/InterpolationProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..83d8ffa03f4562bf1c0c0f67319169131d22cf31
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/InterpolationProcessor.h
@@ -0,0 +1,19 @@
+#ifndef INTERPOLATIONPRZESSOR_H_
+#define INTERPOLATIONPRZESSOR_H_
+
+#include "LBMSystem.h"
+
+
+class InterpolationProcessor;
+typedef boost::shared_ptr<InterpolationProcessor> InterpolationProcessorPtr;
+
+class InterpolationProcessor
+{
+public:
+   //virtual void interpolate() = 0;
+protected:
+private:
+};
+
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernel3D.cpp b/source/VirtualFluidsCore/LBM/LBMKernel3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4a82ef7cd6c4e4bc4bd61586ca6743bef75ef8c1
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernel3D.cpp
@@ -0,0 +1,196 @@
+#include "LBMKernel3D.h"
+
+
+LBMKernel3D::LBMKernel3D() : ghostLayerWidth(1),
+                             deltaT(1.0),
+                             withForcing(false),
+                             withSpongeLayer(false)
+{
+   this->setForcingX1(0.0);
+   this->setForcingX2(0.0);
+   this->setForcingX3(0.0);
+   dataSet = DataSet3DPtr(new DataSet3D());
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3D::~LBMKernel3D()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setBCProcessor(BCProcessorPtr bcp)
+{
+   bcProcessor = bcp;
+}
+//////////////////////////////////////////////////////////////////////////
+BCProcessorPtr LBMKernel3D::getBCProcessor() 
+{
+   return bcProcessor;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setCollisionFactor(double collFactor) 
+{
+   this->collFactor = collFactor;
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernel3D::getCollisionFactor() const
+{
+   return collFactor;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setForcingX1(LBMReal forcingX1)
+{
+    this->muForcingX1.SetExpr( UbSystem::toString(forcingX1,LBMRealLim::digits10) );  
+    this->checkFunction(muForcingX1); 
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setForcingX2(LBMReal forcingX2)
+{
+   this->muForcingX2.SetExpr( UbSystem::toString(forcingX2,LBMRealLim::digits10) );  
+   this->checkFunction(muForcingX2);
+}
+void LBMKernel3D::setForcingX3(LBMReal forcingX3)
+{
+   this->muForcingX3.SetExpr( UbSystem::toString(forcingX3,LBMRealLim::digits10) );  
+   this->checkFunction(muForcingX3); 
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setForcingX1( const mu::Parser& parser)
+{ 
+   this->checkFunction(parser); 
+   this->muForcingX1 = parser;  
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setForcingX2( const mu::Parser& parser)  
+{ 
+   this->checkFunction(parser); 
+   this->muForcingX2 = parser;  
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setForcingX3( const mu::Parser& parser)  
+{ 
+   this->checkFunction(parser); 
+   this->muForcingX3 = parser;  
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setForcingX1( const std::string& muParserString)  
+{ 
+   this->muForcingX1.SetExpr(muParserString); 
+   this->checkFunction(muForcingX1); 
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setForcingX2( const std::string& muParserString)  
+{ 
+   this->muForcingX2.SetExpr(muParserString); 
+   this->checkFunction(muForcingX2); 
+}
+void LBMKernel3D::setForcingX3( const std::string& muParserString)  
+{ 
+   this->muForcingX3.SetExpr(muParserString); 
+   this->checkFunction(muForcingX3); 
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::checkFunction(mu::Parser fct)
+{
+   double x1=1.0,x2=1.0,x3=1.0, dt=1.0, nue=1.0;
+   fct.DefineVar("x1",&x1); 
+   fct.DefineVar("x2",&x2); 
+   fct.DefineVar("x3",&x3);
+   fct.DefineVar("dt",&dt);
+   fct.DefineVar("nue",&nue);
+
+   try
+   {
+      fct.Eval();
+      fct.ClearVar();
+   }
+   catch(mu::ParserError& e)
+   {
+      throw UbException(UB_EXARGS,"function: "+e.GetExpr() + (std::string)"error: "+e.GetMsg()
+         +(std::string)", only x1,x2,x3,dx are allowed as variables" );
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setGhostLayerWidth(int witdh)
+{
+   ghostLayerWidth = witdh;
+}
+//////////////////////////////////////////////////////////////////////////
+int  LBMKernel3D::getGhostLayerWidth() const
+{
+   return ghostLayerWidth;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setIndex( int x1, int x2, int x3 )
+{
+   this->ix1 = x1;
+   this->ix2 = x2;
+   this->ix3 = x3;
+}
+//////////////////////////////////////////////////////////////////////////
+DataSet3DPtr LBMKernel3D::getDataSet() const
+{
+   return this->dataSet;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setDeltaT( LBMReal dt )
+{
+   deltaT = dt;
+}
+//////////////////////////////////////////////////////////////////////////
+bool LBMKernel3D::getCompressible() const 
+{ 
+   return compressible; 
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setCompressible(bool val) 
+{ 
+   compressible = val; 
+}
+//////////////////////////////////////////////////////////////////////////
+bool LBMKernel3D::getWithForcing() const
+{
+   return withForcing;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setWithForcing( bool val )
+{
+   withForcing = val;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setBlock( Block3DPtr block )
+{
+   this->block = block;
+}
+//////////////////////////////////////////////////////////////////////////
+Block3DPtr LBMKernel3D::getBlock() const
+{
+   return block.lock();
+}
+//////////////////////////////////////////////////////////////////////////
+bool LBMKernel3D::getWithSpongeLayer() const
+{
+   return withSpongeLayer;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setWithSpongeLayer( bool val )
+{
+   withSpongeLayer = val;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setSpongeLayer( const mu::Parser& parser )
+{
+   this->checkFunction(parser); 
+   this->muSpongeLayer = parser;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setSpongeLayer( const std::string& muParserString )
+{
+   this->muSpongeLayer.SetExpr(muParserString); 
+   this->checkFunction(muSpongeLayer); 
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernel3D::setDataSet(DataSet3DPtr dataSet)
+{
+   this->dataSet = dataSet;
+}
+
diff --git a/source/VirtualFluidsCore/LBM/LBMKernel3D.h b/source/VirtualFluidsCore/LBM/LBMKernel3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..011a6bd037b3d175cbe3c510b56f5702e1728938
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernel3D.h
@@ -0,0 +1,122 @@
+#ifndef LBMKERNEL_H
+#define LBMKERNEL_H
+
+#include "LBMSystem.h"
+#include "DistributionArray3D.h"
+#include "DataSet3D.h"
+
+#include "InterpolationProcessor.h"
+#include <MuParser/include/muParser.h>
+
+#include <boost/serialization/serialization.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#include <boost/weak_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+class LBMKernel3D;
+typedef boost::shared_ptr<LBMKernel3D> LBMKernel3DPtr;
+
+#include "BCProcessor.h"
+#include "Block3D.h"
+
+class LBMKernel3D : public boost::enable_shared_from_this<LBMKernel3D>
+{
+public:
+   typedef std::numeric_limits<LBMReal> LBMRealLim;
+public:
+   LBMKernel3D();
+   virtual ~LBMKernel3D();
+
+   virtual LBMKernel3DPtr clone() = 0;
+
+   virtual void calculate() = 0;
+   virtual void swapDistributions() = 0;
+   virtual double getCallculationTime() = 0;
+
+   virtual void setBCProcessor(BCProcessorPtr bcp);
+   virtual BCProcessorPtr getBCProcessor();
+   
+   virtual void setCollisionFactor(double collFactor);
+   virtual double getCollisionFactor() const;
+   
+   virtual void setGhostLayerWidth(int witdh);
+   virtual int  getGhostLayerWidth() const;
+
+   void setDataSet(DataSet3DPtr dataSet);
+   DataSet3DPtr getDataSet() const;
+
+   void setForcingX1(LBMReal forcingX1);
+   void setForcingX2(LBMReal forcingX2);
+   void setForcingX3(LBMReal forcingX3);
+
+   void setForcingX1( const mu::Parser& parser);
+   void setForcingX2( const mu::Parser& parser);
+   void setForcingX3( const mu::Parser& parser);
+
+   void setForcingX1( const std::string& muParserString);
+   void setForcingX2( const std::string& muParserString);
+   void setForcingX3( const std::string& muParserString);
+
+   void setIndex(int x1, int x2, int x3);
+
+   void setDeltaT(LBMReal dt);
+
+   bool getCompressible() const;
+   void setCompressible(bool val);
+
+   bool getWithForcing() const;
+   void setWithForcing(bool val);
+
+   bool getWithSpongeLayer() const;
+   void setWithSpongeLayer(bool val);
+
+   void setSpongeLayer(const mu::Parser& parser);
+   void setSpongeLayer(const std::string& muParserString);
+
+   void setBlock(Block3DPtr block);
+   Block3DPtr getBlock() const;
+
+protected:
+   DataSet3DPtr dataSet;
+   BCProcessorPtr bcProcessor; 
+   LBMReal collFactor;
+   int ghostLayerWidth;
+   bool compressible;
+   
+   //forcing 
+   bool withForcing;
+   mu::Parser muForcingX1;
+   mu::Parser muForcingX2;
+   mu::Parser muForcingX3;
+   int ix1, ix2, ix3;
+   LBMReal deltaT;
+
+   //sponge layer
+   bool withSpongeLayer;
+   mu::Parser muSpongeLayer;
+
+   boost::weak_ptr<Block3D> block;
+
+
+private:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & collFactor;
+      ar & ghostLayerWidth;
+      ar & compressible;
+      ar & withForcing;
+      //ar & withSpongeLayer;
+      ar & deltaT;
+      ar & dataSet;
+      ar & bcProcessor;
+      ar & ix1;
+      ar & ix2;
+      ar & ix3;
+   }
+
+   void checkFunction(mu::Parser fct);
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelESD3Q27CCLB.cpp b/source/VirtualFluidsCore/LBM/LBMKernelESD3Q27CCLB.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4f70920ab8424e41c02f4e0d9cb905652c060774
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelESD3Q27CCLB.cpp
@@ -0,0 +1,1000 @@
+#include "LBMKernelESD3Q27CCLB.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+#include <math.h>
+
+
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelESD3Q27CCLB::LBMKernelESD3Q27CCLB()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelESD3Q27CCLB::LBMKernelESD3Q27CCLB(int nx1, int nx2, int nx3, Grid3DPtr grid) 
+   : LBMKernelETD3Q27(nx1, nx2, nx3),
+     grid(grid)
+{
+   this->compressible = false;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelESD3Q27CCLB::~LBMKernelESD3Q27CCLB(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelESD3Q27CCLB::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1, nx2, nx3, 0.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelESD3Q27CCLB::initNeighbours()
+{
+   int x1 = block.lock()->getX1();
+   int x2 = block.lock()->getX2();
+   int x3 = block.lock()->getX3();
+   int level = block.lock()->getLevel();
+
+   if(Block3DPtr block = grid->getBlock(x1+1,x2,x3,level))
+   {
+      blockN100L = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+      blockN100NL = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   }   
+   if(Block3DPtr block = grid->getBlock(x1,x2+1,x3,level))
+   {
+      blockN010L = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+      blockN010NL = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   }
+   if(Block3DPtr block = grid->getBlock(x1,x2,x3+1,level))
+   {
+      blockN001L = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+      blockN001NL = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   }
+   if(Block3DPtr block = grid->getBlock(x1+1,x2+1,x3,level))
+   {
+      blockN110L = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+      blockN110NL = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   }
+   if(Block3DPtr block = grid->getBlock(x1,x2+1,x3+1,level))
+   {
+      blockN011L = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+      blockN011NL = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   }
+   if(Block3DPtr block = grid->getBlock(x1+1,x2,x3+1,level))
+   {
+      blockN101L = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+      blockN101NL = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   }
+   if(Block3DPtr block = grid->getBlock(x1+1,x2+1,x3+1,level))
+   {
+      blockN111L = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+      blockN111NL = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(block->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   }
+
+   UbTupleInt3 blockNX = grid->getBlockNX();
+   blockNX1 = val<1>(blockNX);
+   blockNX2 = val<2>(blockNX);
+   blockNX3 = val<3>(blockNX);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelESD3Q27CCLB::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelESD3Q27CCLB(nx1, nx2, nx3, grid));
+   kernel->setBlock(this->getBlock());
+   boost::dynamic_pointer_cast<LBMKernelESD3Q27CCLB>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelESD3Q27CCLB::calculate()
+{
+   timer.resetAndStart();
+   collideAll();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelESD3Q27CCLB::collideAll()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dx",&muDeltaT);
+      muForcingX2.DefineVar("dx",&muDeltaT);
+      muForcingX3.DefineVar("dx",&muDeltaT);
+
+      muNue = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nue",&muNue);
+      muForcingX2.DefineVar("nue",&muNue);
+      muForcingX3.DefineVar("nue",&muNue);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   s9 = - collFactor;
+   c1o27=1.0/27.0;
+   c2o3=2.0/3.0;
+   w2=-1.0; //MXXpMYYpMZZ bulk viscosity
+   w7=-1.0;//s9; //ORDER 4 Isotropic
+   w9=-1.0;
+   w10=-1.0;//s9;//-1.0; // ORDER 6 Isotropic
+   w1=s9;
+   // wenn es mal an den Ecken nicht gut aussieht -2.0-s9 probieren
+   w3=-1.0;//-2.0-s9;//-1.0;//MXXYpMYZZ
+   w4=-1.0;//-2.0-s9;//-1.0;//MXXYmMYZZ
+   w5=-1.0;//-2.0-s9;//-1.0;//MYXZ
+   w6=-1.0; //MXXYYpm2p
+   w8=-1.0; //M_zXXYZ 
+
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = 0;//ghostLayerWidth;
+   int minX2 = 0;//ghostLayerWidth;
+   int minX3 = 0;//ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1;//-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2;//-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3;//-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////
+
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+
+               //Rest ist b
+//////////////////////////////////////////////////////////////////////////
+               //CbArray4D<LBMReal,IndexerX4X3X2X1>* temp = (localDistributions.get())+1;
+               //CbArray4D<LBMReal,IndexerX4X3X2X1>* temp = (localDistributions.get())+1;
+
+               PxL = localDistributions;
+               PxNL = nonLocalDistributions;
+               PxyL = localDistributions;
+               PxyNL = nonLocalDistributions;
+               PxzL = localDistributions;
+               PxzNL = nonLocalDistributions;
+               //PxyzL = localDistributions;
+               PxyzNL = nonLocalDistributions;
+               PyL = localDistributions;
+               PyNL = nonLocalDistributions;
+               PzL = localDistributions;
+               PzNL = nonLocalDistributions;
+               PyzL = localDistributions;
+               PyzNL = nonLocalDistributions;
+               int x1p=x1+1;
+               int x2p=x2+1;
+               int x3p=x3+1;
+
+
+               if (x1+1 >= blockNX1)
+               {
+                  x1p=1;
+                  PxL = blockN100L;
+                  PxNL = blockN100NL;
+                  PxyL = blockN100L;
+                  PxyNL = blockN100NL;
+                  PxzL = blockN100L;
+                  PxzNL = blockN100NL;
+                  //PxyzL = blockN100L;
+                  PxyzNL = blockN100NL;
+                  
+
+               }
+               if (x2+1 >= blockNX2)
+               {
+                  x2p=1;
+                  PyL = blockN010L;
+                  PyNL = blockN010NL;
+                  if(x1+1 >= blockNX1){
+                     PxyL = blockN110L;
+                     PxyNL = blockN110NL;
+                     //PxyzL = blockN110L;
+                     PxyzNL = blockN110NL;
+                  }
+               }
+               if (x3+1 >= blockNX3)
+               {
+                  x3p=1;
+                  PzL = blockN001L;
+                  PzNL = blockN001NL;
+                  if(x1+1 >= blockNX1){
+                     PxzL = blockN101L;
+                     PxzNL = blockN101NL;
+                        if (x2+1 >= blockNX2)
+                           {
+                              //PxyzL = blockN111L;
+                              PxyzNL = blockN111NL;
+                           }
+                  }
+                  if (x2+1 >= blockNX2)
+                  {
+                     PyzL = blockN011L;
+                     PyzNL = blockN011NL;
+                  }
+               }
+              
+               //PxL = CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr(localDistributions.get() + (x1+1)/blockNX1 * (-localDistributions.get() + blockN100L.get()));
+
+               LBMReal mfaaa = (*PxyzNL)(D3Q27System::ET_BSW,x1p,x2p,x3p); 
+               LBMReal mfaab = (*PxyNL)(D3Q27System::ET_SW,x1p,x2p,x3 );
+               LBMReal mfaac = (*PxyL)(D3Q27System::ET_TSW,x1p,x2p,x3);
+               LBMReal mfaba = (*PxzNL)(D3Q27System::ET_BW,x1p,x2,x3p );
+               LBMReal mfabb = (*PxNL)(D3Q27System::ET_W,x1p,x2,x3  );
+               LBMReal mfabc = (*PxL)(D3Q27System::ET_TW, x1p,x2,x3);
+               LBMReal mfbaa = (*PyzNL)(D3Q27System::ET_BS,x1,x2p,x3p );
+               LBMReal mfbab = (*PyNL)(D3Q27System::ET_S,x1,x2p,x3  );
+               LBMReal mfbac = (*PyL)(D3Q27System::ET_TS,x1,x2p,x3);
+               LBMReal mfbba = (*PzNL)(D3Q27System::ET_B,x1,x2,x3p  );
+               LBMReal mfbbb = (*zeroDistributions)(x1,x2,x3);
+               LBMReal mfbbc = (*localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               LBMReal mfaca = (*PxzNL)(D3Q27System::ET_BNW,x1p,x2,x3p);
+               LBMReal mfacb = (*PxL)(D3Q27System::ET_NW,x1p,x2,x3);
+               LBMReal mfacc = (*PxL)(D3Q27System::ET_TNW,x1p,x2,x3);
+               LBMReal mfcaa = (*PyzNL)(D3Q27System::ET_BSE,x1,x2p,x3p);
+               LBMReal mfcab = (*PyNL)(D3Q27System::ET_SE,x1,x2p,x3 );
+               LBMReal mfcac = (*PyL)(D3Q27System::ET_TSE,x1,x2p,x3);
+               LBMReal mfcca = (*PzNL)(D3Q27System::ET_BNE,x1,x2,x3p);
+               LBMReal mfccb = (*localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               LBMReal mfccc = (*localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               LBMReal mfbca = (*PzNL)(D3Q27System::ET_BN,x1,x2,x3p );
+               LBMReal mfbcb = (*localDistributions)(D3Q27System::ET_N,x1,x2,x3); 
+               LBMReal mfbcc = (*localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               LBMReal mfcba = (*PzNL)(D3Q27System::ET_BE,x1,x2,x3p );
+               LBMReal mfcbb = (*localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               LBMReal mfcbc = (*localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               LBMReal m0, m1, m2;
+
+
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb));
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab));
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba));
+               ////////////////////////////////////////////////////////////////////////////////////
+
+               LBMReal oMdrho;
+               {
+                  oMdrho=mfccc+mfaaa;
+                  m0=mfaca+mfcac;
+                  m1=mfacc+mfcaa;
+                  m2=mfaac+mfcca;
+                  oMdrho+=m0;
+                  m1+=m2;
+                  oMdrho+=m1;
+                  m0=mfbac+mfbca;
+                  m1=mfbaa+mfbcc;
+                  m0+=m1;
+                  m1=mfabc+mfcba;
+                  m2=mfaba+mfcbc;
+                  m1+=m2;
+                  m0+=m1;
+                  m1=mfacb+mfcab;
+                  m2=mfaab+mfccb;
+                  m1+=m2;
+                  m0+=m1;
+                  oMdrho+=m0;
+                  m0=mfabb+mfcbb;
+                  m1=mfbab+mfbcb;
+                  m2=mfbba+mfbbc;
+                  m0+=m1+m2;
+                  m0+=mfbbb; //hat gefehlt
+                  oMdrho = 1. - (oMdrho + m0);
+               }
+               LBMReal vx2;
+               LBMReal vy2;
+               LBMReal vz2;
+
+               vx2=vvx*vvx;
+               vy2=vvy*vvy;
+               vz2=vvz*vvz;
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal wadjust;
+               LBMReal qudricLimit = 0.01;
+               //LBMReal s9 = minusomega;
+               //test
+               //s9 = 0.;
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa + mfaac;
+               m1    = mfaac - mfaaa;
+               m0    = m2          + mfaab;
+               mfaaa = m0;
+               m0   += c1o36 * oMdrho;   
+               mfaab = m1 -        m0 * vvz;
+               mfaac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2          + mfabb;
+               mfaba = m0;
+               m0   += c1o9 * oMdrho;
+               mfabb = m1 -        m0 * vvz;
+               mfabc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2          + mfacb;
+               mfaca = m0;
+               m0   += c1o36 * oMdrho;
+               mfacb = m1 -        m0 * vvz;
+               mfacc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbac;
+               m1    = mfbac - mfbaa;
+               m0    = m2          + mfbab;
+               mfbaa = m0;
+               m0   += c1o9 * oMdrho;
+               mfbab = m1 -        m0 * vvz;
+               mfbac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2          + mfbbb;
+               mfbba = m0;
+               m0   += c4o9 * oMdrho;
+               mfbbb = m1 -        m0 * vvz;
+               mfbbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2          + mfbcb;
+               mfbca = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcb = m1 -        m0 * vvz;
+               mfbcc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcac;
+               m1    = mfcac - mfcaa;
+               m0    = m2          + mfcab;
+               mfcaa = m0;
+               m0   += c1o36 * oMdrho;
+               mfcab = m1 -        m0 * vvz;
+               mfcac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2          + mfcbb;
+               mfcba = m0;
+               m0   += c1o9 * oMdrho;
+               mfcbb = m1 -        m0 * vvz;
+               mfcbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2          + mfccb;
+               mfcca = m0;
+               m0   += c1o36 * oMdrho;
+               mfccb = m1 -        m0 * vvz;
+               mfccc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa + mfaca;
+               m1    = mfaca - mfaaa;
+               m0    = m2          + mfaba;
+               mfaaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfaba = m1 -        m0 * vvy;
+               mfaca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2          + mfabb;
+               mfaab = m0;
+               mfabb = m1 -        m0 * vvy;
+               mfacb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2          + mfabc;
+               mfaac = m0;
+               m0   += c1o18 * oMdrho;
+               mfabc = m1 -        m0 * vvy;
+               mfacc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbca;
+               m1    = mfbca - mfbaa;
+               m0    = m2          + mfbba;
+               mfbaa = m0;
+               m0   += c2o3 * oMdrho;
+               mfbba = m1 -        m0 * vvy;
+               mfbca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2          + mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -        m0 * vvy;
+               mfbcb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2          + mfbbc;
+               mfbac = m0;
+               m0   += c2o9 * oMdrho;
+               mfbbc = m1 -        m0 * vvy;
+               mfbcc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcca;
+               m1    = mfcca - mfcaa;
+               m0    = m2          + mfcba;
+               mfcaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfcba = m1 -        m0 * vvy;
+               mfcca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2          + mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -        m0 * vvy;
+               mfccb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2          + mfcbc;
+               mfcac = m0;
+               m0   += c1o18 * oMdrho;
+               mfcbc = m1 -        m0 * vvy;
+               mfccc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9            Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa + mfcaa;
+               m1    = mfcaa - mfaaa;
+               m0    = m2          + mfbaa;
+               mfaaa = m0;
+               m0   += 1. * oMdrho;
+               mfbaa = m1 -        m0 * vvx;
+               mfcaa = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2          + mfbba;
+               mfaba = m0;
+               mfbba = m1 -        m0 * vvx;
+               mfcba = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2          + mfbca;
+               mfaca = m0;
+               m0   += c1o3 * oMdrho;
+               mfbca = m1 -        m0 * vvx;
+               mfcca = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab + mfcab;
+               m1    = mfcab - mfaab;
+               m0    = m2          + mfbab;
+               mfaab = m0;
+               mfbab = m1 -        m0 * vvx;
+               mfcab = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2          + mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -        m0 * vvx;
+               mfcbb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2          + mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -        m0 * vvx;
+               mfccb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac + mfcac;
+               m1    = mfcac - mfaac;
+               m0    = m2          + mfbac;
+               mfaac = m0;
+               m0   += c1o3 * oMdrho;
+               mfbac = m1 -        m0 * vvx;
+               mfcac = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2          + mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -        m0 * vvx;
+               mfcbc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2          + mfbcc;
+               mfacc = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcc = m1 -        m0 * vvx;
+               mfccc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal OxxPyyPzz = 1.;
+               LBMReal OxyyPxzz  = 1.;//-s9;//2+s9;//
+               LBMReal OxyyMxzz  = 1.;//2+s9;//
+               LBMReal O4        = 1.;
+               LBMReal O5        = 1.;
+               LBMReal O6        = 1.;
+
+               //Cum 4.
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //Cum 5.
+               LBMReal CUMbcc = (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) - c1o3 * (mfbca + mfbac) * oMdrho;
+               LBMReal CUMcbc = (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) - c1o3 * (mfcba + mfabc) * oMdrho;
+               LBMReal CUMccb = (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) - c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc  +((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) +c1o27*oMdrho;
+
+               //2.
+               // linear combinations
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz         = mfcaa - mfaac;
+
+               {
+                  LBMReal dxux = c1o2 * (s9 *(mxxMyy + mxxMzz) + (mfaaa - mxxPyyPzz));
+                  LBMReal dyuy = dxux - s9 * c3o2 * mxxMyy;
+                  LBMReal dzuz = dxux - s9 * c3o2 * mxxMzz;
+
+                  //relax
+                  mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+                  mxxMyy    += -s9 * (-mxxMyy) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vy2 * dyuy);
+                  mxxMzz    += -s9 * (-mxxMzz) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vz2 * dzuz);
+               }
+               mfabb     += -s9 * (-mfabb);
+               mfbab     += -s9 * (-mfbab);
+               mfbba     += -s9 * (-mfbba);
+
+               // linear combinations back
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mfbbb)/(fabs(mfbbb)+qudricLimit);
+               mfbbb     += wadjust * (-mfbbb);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxyPyzz)/(fabs(mxxyPyzz)+qudricLimit);
+               mxxyPyzz  += wadjust * (-mxxyPyzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxyMyzz)/(fabs(mxxyMyzz)+qudricLimit);
+               mxxyMyzz  += wadjust * (-mxxyMyzz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxzPyyz)/(fabs(mxxzPyyz)+qudricLimit);
+               mxxzPyyz  += wadjust * (-mxxzPyyz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxzMyyz)/(fabs(mxxzMyyz)+qudricLimit);
+               mxxzMyyz  += wadjust * (-mxxzMyyz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxyyPxzz)/(fabs(mxyyPxzz)+qudricLimit);
+               mxyyPxzz  += wadjust * (-mxyyPxzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxyyMxzz)/(fabs(mxyyMxzz)+qudricLimit);
+               mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               //4.
+               CUMacc += O4 * (-CUMacc);
+               CUMcac += O4 * (-CUMcac);
+               CUMcca += O4 * (-CUMcca);
+
+               CUMbbc += O4 * (-CUMbbc);
+               CUMbcb += O4 * (-CUMbcb);
+               CUMcbb += O4 * (-CUMcbb);
+
+               //5.
+               CUMbcc += O5 * (-CUMbcc);
+               CUMcbc += O5 * (-CUMcbc);
+               CUMccb += O5 * (-CUMccb);
+
+               //6.
+               CUMccc += O6 * (-CUMccc);
+
+               //back cumulants to central moments
+               //4.
+               mfcbb = CUMcbb + ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               mfbcb = CUMbcb + ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               mfbbc = CUMbbc + ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac) * oMdrho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc) * oMdrho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) -c1o27*oMdrho;
+               ////////////////////////////////////////////////////////////////////////////////////
+
+               //////////////////////////////////////////////////////////////////////////////////////
+               //// Cumulants
+               //////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa                * (1. - vz2)              - 1. * oMdrho * vz2;
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2;
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2);
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2;
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2);
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2;
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2);
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2;
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2);
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2;
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2);
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca                  * (1. - vz2)              - c1o9 * oMdrho * vz2;
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab                  * (1. - vy2)              - c2o3 * oMdrho * vy2;
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2;
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2);
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2);
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2);
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab                  * (1. - vy2)              - c2o9 * oMdrho * vy2;
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb                  * (1. - vx2)              - c4o9 * oMdrho * vx2;
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho="+UbSystem::toString(rho)+", rho_post="+UbSystem::toString(rho_post)
+                     +" dif="+UbSystem::toString(dif)
+                     +" rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelESD3Q27CCLB::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*localDistributions)(D3Q27System::ET_E,x1,  x2,  x3)    = mfabb;
+               (*localDistributions)(D3Q27System::ET_N,x1,  x2,  x3)    = mfbab;
+               (*localDistributions)(D3Q27System::ET_T,x1,  x2,  x3)    = mfbba;
+               (*localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3)   = mfaab;
+               (*PxL)(D3Q27System::ET_NW,x1p,x2,  x3)   = mfcab;
+               (*localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3)   = mfaba;
+               (*PxL)(D3Q27System::ET_TW,x1p,x2,  x3)   = mfcba;
+               (*localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3)   = mfbaa;
+               (*PyL)(D3Q27System::ET_TS,x1,  x2p,x3)   = mfbca;
+               (*localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3)  = mfaaa;
+               (*PxL)(D3Q27System::ET_TNW,x1p,x2,  x3)  = mfcaa;
+               (*PyL)(D3Q27System::ET_TSE,x1,  x2p,x3)  = mfaca;
+               (*PxyL)(D3Q27System::ET_TSW,x1p,x2p,x3)  = mfcca;
+
+               (*PxNL)(D3Q27System::ET_W,x1p,x2,  x3    ) = mfcbb;
+               (*PyNL)(D3Q27System::ET_S,x1,  x2p,x3    ) = mfbcb;
+               (*PzNL)(D3Q27System::ET_B,x1,  x2,  x3p  ) = mfbbc;
+               (*PxyNL)(D3Q27System::ET_SW,x1p,x2p,x3   ) = mfccb;
+               (*PyNL)(D3Q27System::ET_SE,x1,  x2p,x3   ) = mfacb;
+               (*PxzNL)(D3Q27System::ET_BW,x1p,x2,  x3p ) = mfcbc;
+               (*PzNL)(D3Q27System::ET_BE,x1,  x2,  x3p ) = mfabc;
+               (*PyzNL)(D3Q27System::ET_BS,x1,  x2p,x3p ) = mfbcc;
+               (*PzNL)(D3Q27System::ET_BN,x1,  x2,  x3p ) = mfbac;
+               (*PxyzNL)(D3Q27System::ET_BSW,x1p,x2p,x3p) = mfccc;
+               (*PyzNL)(D3Q27System::ET_BSE,x1,  x2p,x3p) = mfacc;
+               (*PxzNL)(D3Q27System::ET_BNW,x1p,x2,  x3p) = mfcac;
+               (*PzNL)(D3Q27System::ET_BNE,x1,  x2,  x3p) = mfaac;
+
+               (*this->zeroDistributions)(x1,x2,x3) = mfbbb;
+               //////////////////////////////////////////////////////////////////////////
+
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelESD3Q27CCLB::getCallculationTime()
+{
+   //return timer.getDuration();
+   return timer.getTotalTime();
+}
+
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelESD3Q27CCLB.h b/source/VirtualFluidsCore/LBM/LBMKernelESD3Q27CCLB.h
new file mode 100644
index 0000000000000000000000000000000000000000..616d83d70666c07311e4bdcbc7105ad8e9bcc518
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelESD3Q27CCLB.h
@@ -0,0 +1,77 @@
+//Cascaded Cumulant LBM
+
+#ifndef LBMKernelESD3Q27CCLB_H
+#define LBMKernelESD3Q27CCLB_H
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+#include "Grid3D.h"
+
+
+class LBMKernelESD3Q27CCLB;
+typedef boost::shared_ptr<LBMKernelESD3Q27CCLB> LBMKernelESD3Q27CCLBPtr;
+
+
+class LBMKernelESD3Q27CCLB :  public LBMKernelETD3Q27
+{
+public:
+   LBMKernelESD3Q27CCLB();
+   LBMKernelESD3Q27CCLB(int nx1, int nx2, int nx3, Grid3DPtr grid);
+   ~LBMKernelESD3Q27CCLB(void);
+   void calculate();
+   LBMKernel3DPtr clone();
+   double getCallculationTime();
+   void initNeighbours();
+
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+   }
+
+   void collideAll();  
+
+   void init();
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal rho, vx, vy, vz, durchrho;
+   LBMReal w1,w2,w3,w4,w5,w6,w7,w8,w9,w10;
+   LBMReal s9,c1o27,c2o3;
+
+   LBMReal M_zXX, M_zYY, M_zZZ, M_zXY,    M_zXZ,  M_zYZ,
+      M_zXXY,    M_zXYY,    M_zXXZ,    M_zXZZ,   M_zYYZ,  M_zYZZ,  M_zXYZ,
+      M_zXXYY,   M_zXXZZ,   M_zYYZZ,   M_zXXYZ,  M_zXYYZ,  M_zXYZZ,
+      M_zXXYYZ,  M_zXXYZZ,  M_zXYYZZ,  M_zXXYYZZ;
+   LBMReal mu200, mu020, mu002,mu110, mu101,mu011,mu210,mu120,mu102,mu111, 
+      mu201,mu021,mu012,mu220,mu121,mu202,mu211,mu112,mu022,mu221,mu122,mu212,mu222,mu000,mu100,mu010,mu001;
+   LBMReal vx_sq, vy_sq, vz_sq, vx_vy, vx_vz, vy_vz, vx_vy_vz;
+   LBMReal MXXpMYYpMZZ,MXXmMYY, MXXmMZZ,
+      MXXYpMYZZ,MXXZpMYYZ,MXYYpMXZZ,  MXXYmMYZZ,MXXZmMYYZ,MXYYmMXZZ,
+      MXXYYppp,MXXYYpm2p, MXXYYppm2;
+   UbTimer timer;
+
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributions;
+
+   mu::value_type muX1,muX2,muX3;
+   mu::value_type muDeltaT;
+   mu::value_type muNue;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+   Grid3DPtr grid;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr blockN100L, blockN010L, blockN001L, blockN110L, blockN011L, blockN101L, blockN111L;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr blockN100NL, blockN010NL, blockN001NL, blockN110NL, blockN011NL, blockN101NL, blockN111NL;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr PxL, PxyL, PxyzL, PyL, PyzL, PxzL, PzL;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr PxNL, PxyNL, PxyzNL, PyNL, PyzNL, PxzNL, PzNL;
+   int blockNX1, blockNX2, blockNX3;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ebabaea116850de0c99f1e1142d01f384d59ddca
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27.cpp
@@ -0,0 +1,25 @@
+#include "LBMKernelETD3Q27.h"
+
+//BOOST_CLASS_EXPORT(LBMKernelETD3Q27Cascaded)
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27::LBMKernelETD3Q27()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27::LBMKernelETD3Q27(int nx1, int nx2, int nx3) 
+                                    : LBMKernel3D(), nx1(nx1), nx2(nx2), nx3(nx3)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27::~LBMKernelETD3Q27(void) 
+{ 
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27::swapDistributions() 
+{
+   dataSet->getFdistributions()->swap();
+}
+
+
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27.h
new file mode 100644
index 0000000000000000000000000000000000000000..c3f4da8db3f234ed8071fb7e7ce1413cad3bd2c4
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27.h
@@ -0,0 +1,31 @@
+#ifndef LBMKERNELETD3Q27_H
+#define LBMKERNELETD3Q27_H
+
+#include "LBMKernel3D.h"
+#include "BCProcessor.h"
+#include "D3Q27ETBCProcessor.h"
+#include "EsoTwist3D.h"
+
+#include <boost/serialization/base_object.hpp>
+
+class LBMKernelETD3Q27;
+typedef boost::shared_ptr<LBMKernelETD3Q27> LBMKernelETD3Q27Ptr;
+
+class LBMKernelETD3Q27 : public LBMKernel3D
+{
+public:
+   LBMKernelETD3Q27();
+   LBMKernelETD3Q27(int nx1, int nx2, int nx3); 
+   virtual ~LBMKernelETD3Q27(void);
+   void swapDistributions();
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernel3D>(*this);
+      ar & nx1 & nx2 & nx3;
+   }
+   int nx1, nx2, nx3;
+};
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27BGK.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27BGK.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9466a4fcad9cb5e29ffc6372c0ff86456ea1e094
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27BGK.cpp
@@ -0,0 +1,580 @@
+#include "LBMKernelETD3Q27BGK.h"
+#include "D3Q27System.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+#include "D3Q27EsoTwist3DSoA.h"
+
+//#define PROOF_CORRECTNESS
+
+LBMKernelETD3Q27BGK::LBMKernelETD3Q27BGK(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27BGK::LBMKernelETD3Q27BGK(int nx1, int nx2, int nx3, bool compressible) : 
+                                         LBMKernelETD3Q27(nx1, nx2, nx3)
+{
+   this->compressible = compressible;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27BGK::~LBMKernelETD3Q27BGK(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27BGK::init()
+{
+   int ghostLayerWitdh = this->getGhostLayerWidth();
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSoA(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27BGK::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27BGK(nx1, nx2, nx3, this->compressible));
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27BGK>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27BGK::calculate()
+{
+   if(this->compressible)
+      collideAllCompressible();
+   else
+      collideAllIncompressible();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27BGK::collideAllCompressible()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   ///////////////////////////////////
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   //Distributions d = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSoA>(dataSet->getFdistributions())->getDistributions();
+   
+   D3Q27BoundaryConditionPtr bcPtr;
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal feq[D3Q27System::ENDF+1];
+   LBMReal rho,vx1,vx2,vx3;
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               int x1p = x1 + 1;
+               int x2p = x2 + 1;
+               int x3p = x3 + 1;
+
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               f[ZERO] = (*this->zeroDistributions)(x1,x2,x3);
+
+               f[E] = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               f[N] = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3);  
+               f[T] = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               f[NE] = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               f[NW] = (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,x3);
+               f[TE] = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               f[TW] = (*this->localDistributions)(D3Q27System::ET_TW, x1p,x2,x3);
+               f[TN] = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               f[TS] = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2p,x3);
+               f[TNE] = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               f[TNW] = (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,x3);
+               f[TSE] = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2p,x3);
+               f[TSW] = (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3);
+
+               f[W ] = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,x3  );
+               f[S ] = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2p,x3  );
+               f[B ] = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3p  );
+               f[SW] = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3 );
+               f[SE] = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2p,x3 );
+               f[BW] = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,x3p );
+               f[BE] = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3p );
+               f[BS] = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2p,x3p );
+               f[BN] = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3p );
+               f[BSW] = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p);
+               f[BSE] = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2p,x3p);
+               f[BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,x3p);
+               f[BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3p);
+
+               //////////////////////////////////////////////////////////////////////////
+                  
+               rho = ((f[TNE] + f[BSW])+(f[TSE]+f[BNW]))+((f[BSE]+f[TNW])+ (f[TSW]+f[BNE]))
+                    +(((f[NE] + f[SW]) + (f[SE] + f[NW]))+((f[TE] + f[BW])+(f[BE]+ f[TW]))
+                    +((f[BN] + f[TS]) + (f[TN] + f[BS])))+((f[E] + f[W])+(f[N] + f[S])
+                    +(f[T] + f[B]))+f[ZERO];
+
+               vx1 = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[BSE]-f[TNW]) + (f[BNE]-f[TSW]))) +
+                  (((f[BE]-f[TW]) + (f[TE]-f[BW])) + ((f[SE]-f[NW]) + (f[NE]-f[SW]))) +
+                  (f[E]-f[W])); 
+
+               vx2 = ((((f[TNE]-f[BSW]) + (f[BNW]-f[TSE])) + ((f[TNW]-f[BSE]) + (f[BNE]-f[TSW]))) +
+                  (((f[BN]-f[TS]) + (f[TN]-f[BS])) + ((f[NW]-f[SE]) + (f[NE]-f[SW]))) +
+                  (f[N]-f[S])); 
+
+               vx3 = ((((f[TNE]-f[BSW]) + (f[TSE]-f[BNW])) + ((f[TNW]-f[BSE]) + (f[TSW]-f[BNE]))) +
+                  (((f[TS]-f[BN]) + (f[TN]-f[BS])) + ((f[TW]-f[BE]) + (f[TE]-f[BW]))) +
+                  (f[T]-f[B]));
+
+               vx1/=rho;
+               vx2/=rho;
+               vx3/=rho;
+
+               LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+               feq[ZERO] =  c8o27*rho*(1.0-cu_sq);
+               feq[E] =   c2o27*rho*(1.0+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq);
+               feq[W] =   c2o27*rho*(1.0+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq);
+               feq[N] =   c2o27*rho*(1.0+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq);
+               feq[S] =   c2o27*rho*(1.0+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq);
+               feq[T] =   c2o27*rho*(1.0+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq);
+               feq[B] =   c2o27*rho*(1.0+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq);
+               feq[NE] =  c1o54*rho*(1.0+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq);
+               feq[SW] =  c1o54*rho*(1.0+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq);
+               feq[SE] =  c1o54*rho*(1.0+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq);
+               feq[NW] =  c1o54*rho*(1.0+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq);
+               feq[TE] =  c1o54*rho*(1.0+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq);
+               feq[BW] =  c1o54*rho*(1.0+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq);
+               feq[BE] =  c1o54*rho*(1.0+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq);
+               feq[TW] =  c1o54*rho*(1.0+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq);
+               feq[TN] =  c1o54*rho*(1.0+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq);
+               feq[BS] =  c1o54*rho*(1.0+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq);
+               feq[BN] =  c1o54*rho*(1.0+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq);
+               feq[TS] =  c1o54*rho*(1.0+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq);
+               feq[TNE] = c1o216*rho*(1.0+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq);
+               feq[BSW] = c1o216*rho*(1.0+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq);
+               feq[BNE] = c1o216*rho*(1.0+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq);
+               feq[TSW] = c1o216*rho*(1.0+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq);
+               feq[TSE] = c1o216*rho*(1.0+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq);
+               feq[BNW] = c1o216*rho*(1.0+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq);
+               feq[BSE] = c1o216*rho*(1.0+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq);
+               feq[TNW] = c1o216*rho*(1.0+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq);
+                  
+               //Relaxation
+               f[ZERO] += (feq[ZERO]-f[ZERO])*collFactor;
+               f[E] += (feq[E]-f[E])*collFactor;
+               f[W] += (feq[W]-f[W])*collFactor;
+               f[N] += (feq[N]-f[N])*collFactor;
+               f[S] += (feq[S]-f[S])*collFactor;
+               f[T] += (feq[T]-f[T])*collFactor;
+               f[B] += (feq[B]-f[B])*collFactor;
+               f[NE] += (feq[NE]-f[NE])*collFactor;
+               f[SW] += (feq[SW]-f[SW])*collFactor;
+               f[SE] += (feq[SE]-f[SE])*collFactor;
+               f[NW] += (feq[NW]-f[NW])*collFactor;
+               f[TE] += (feq[TE]-f[TE])*collFactor;
+               f[BW] += (feq[BW]-f[BW])*collFactor;
+               f[BE] += (feq[BE]-f[BE])*collFactor;
+               f[TW] += (feq[TW]-f[TW])*collFactor;
+               f[TN] += (feq[TN]-f[TN])*collFactor;
+               f[BS] += (feq[BS]-f[BS])*collFactor;
+               f[BN] += (feq[BN]-f[BN])*collFactor;
+               f[TS] += (feq[TS]-f[TS])*collFactor;
+
+               f[TNE] += (feq[TNE]-f[TNE])*collFactor;
+               f[BSW] += (feq[BSW]-f[BSW])*collFactor;
+               f[BNE] += (feq[BNE]-f[BNE])*collFactor;
+               f[TSW] += (feq[TSW]-f[TSW])*collFactor;
+               f[TSE] += (feq[TSE]-f[TSE])*collFactor;
+               f[BNW] += (feq[BNW]-f[BNW])*collFactor;
+               f[BSE] += (feq[BSE]-f[BSE])*collFactor;
+               f[TNW] += (feq[TNW]-f[TNW])*collFactor;
+
+               //////////////////////////////////////////////////////////////////////////
+               //forcing
+               //////////////////////////////////////////////////////////////////////////
+               if (withForcing)
+               {
+                  muX1 = x1+ix1*bcArrayMaxX1;
+                  muX2 = x2+ix2*bcArrayMaxX2;
+                  muX3 = x3+ix3*bcArrayMaxX3;
+
+                  forcingX1 = muForcingX1.Eval();
+                  forcingX2 = muForcingX2.Eval();
+                  forcingX3 = muForcingX3.Eval();
+
+                  f[ZERO] +=                   0.0                        ;
+                  f[E  ] +=  3.0*c2o27  *  (forcingX1)                    ;
+                  f[W  ] +=  3.0*c2o27  *  (-forcingX1)                   ;
+                  f[N  ] +=  3.0*c2o27  *             (forcingX2)         ;
+                  f[S  ] +=  3.0*c2o27  *             (-forcingX2)        ;
+                  f[T  ] +=  3.0*c2o27  *                     (forcingX3) ;
+                  f[B  ] +=  3.0*c2o27  *                     (-forcingX3);
+                  f[NE ] +=  3.0*c1o54 * ( forcingX1+forcingX2          ) ;
+                  f[SW ] +=  3.0*c1o54 * (-forcingX1-forcingX2          ) ;
+                  f[SE ] +=  3.0*c1o54 * ( forcingX1-forcingX2          ) ;
+                  f[NW ] +=  3.0*c1o54 * (-forcingX1+forcingX2          ) ;
+                  f[TE ] +=  3.0*c1o54 * ( forcingX1          +forcingX3) ;
+                  f[BW ] +=  3.0*c1o54 * (-forcingX1          -forcingX3) ;
+                  f[BE ] +=  3.0*c1o54 * ( forcingX1          -forcingX3) ;
+                  f[TW ] +=  3.0*c1o54 * (-forcingX1          +forcingX3) ;
+                  f[TN ] +=  3.0*c1o54 * (           forcingX2+forcingX3) ;
+                  f[BS ] +=  3.0*c1o54 * (          -forcingX2-forcingX3) ;
+                  f[BN ] +=  3.0*c1o54 * (           forcingX2-forcingX3) ;
+                  f[TS ] +=  3.0*c1o54 * (          -forcingX2+forcingX3) ;
+                  f[TNE] +=  3.0*c1o216* ( forcingX1+forcingX2+forcingX3) ;
+                  f[BSW] +=  3.0*c1o216* (-forcingX1-forcingX2-forcingX3) ;
+                  f[BNE] +=  3.0*c1o216* ( forcingX1+forcingX2-forcingX3) ;
+                  f[TSW] +=  3.0*c1o216* (-forcingX1-forcingX2+forcingX3) ;
+                  f[TSE] +=  3.0*c1o216* ( forcingX1-forcingX2+forcingX3) ;
+                  f[BNW] +=  3.0*c1o216* (-forcingX1+forcingX2-forcingX3) ;
+                  f[BSE] +=  3.0*c1o216* ( forcingX1-forcingX2-forcingX3) ;
+                  f[TNW] +=  3.0*c1o216* (-forcingX1+forcingX2+forcingX3) ;
+               }
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = ((f[TNE] + f[BSW])+(f[TSE]+f[BNW]))+((f[BSE]+f[TNW])+ (f[TSW]+f[BNE]))
+                                 +(((f[NE] + f[SW]) + (f[SE] + f[NW]))+((f[TE] + f[BW])+(f[BE]+ f[TW]))
+                                 +((f[BN] + f[TS]) + (f[TN] + f[BS])))+((f[E] + f[W])+(f[N] + f[S])
+                                 +(f[T] + f[B]))+f[ZERO];
+
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho is not correct, dif = " + UbSystem::toString(dif)));
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::INV_E];
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::INV_N];
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::INV_T];
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::INV_NE];
+               (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,  x3) = f[D3Q27System::INV_NW];
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::INV_TE];
+               (*this->localDistributions)(D3Q27System::ET_TW,x1p,x2,  x3) = f[D3Q27System::INV_TW];
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::INV_TN];
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2p,x3) = f[D3Q27System::INV_TS];
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::INV_TNE];
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,  x3) = f[D3Q27System::INV_TNW];
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2p,x3) = f[D3Q27System::INV_TSE];
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3) = f[D3Q27System::INV_TSW];
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,  x3    ) = f[D3Q27System::INV_W ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2p,x3    ) = f[D3Q27System::INV_S ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3p  ) = f[D3Q27System::INV_B ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3   ) = f[D3Q27System::INV_SW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2p,x3   ) = f[D3Q27System::INV_SE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,  x3p ) = f[D3Q27System::INV_BW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3p ) = f[D3Q27System::INV_BE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2p,x3p ) = f[D3Q27System::INV_BS];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3p ) = f[D3Q27System::INV_BN];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p) = f[D3Q27System::INV_BSW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2p,x3p) = f[D3Q27System::INV_BSE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,  x3p) = f[D3Q27System::INV_BNW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3p) = f[D3Q27System::INV_BNE];
+
+               (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO];
+
+
+              //////////////////////////////////////////////////////////////////////////
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27BGK::collideAllIncompressible()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+      forcingX1 = 0;
+      forcingX2 = 0;
+      forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+   D3Q27BoundaryConditionPtr bcPtr;
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal feq[D3Q27System::ENDF+1];
+   LBMReal drho,vx1,vx2,vx3;
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               int x1p = x1 + 1;
+               int x2p = x2 + 1;
+               int x3p = x3 + 1;
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               f[ZERO] = (*this->zeroDistributions)(x1,x2,x3);
+
+               f[E] = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               f[N] = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3);  
+               f[T] = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               f[NE] = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               f[NW] = (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,x3);
+               f[TE] = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               f[TW] = (*this->localDistributions)(D3Q27System::ET_TW, x1p,x2,x3);
+               f[TN] = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               f[TS] = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2p,x3);
+               f[TNE] = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               f[TNW] = (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,x3);
+               f[TSE] = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2p,x3);
+               f[TSW] = (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3);
+
+               f[W ] = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,x3  );
+               f[S ] = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2p,x3  );
+               f[B ] = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3p  );
+               f[SW] = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3 );
+               f[SE] = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2p,x3 );
+               f[BW] = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,x3p );
+               f[BE] = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3p );
+               f[BS] = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2p,x3p );
+               f[BN] = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3p );
+               f[BSW] = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p);
+               f[BSE] = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2p,x3p);
+               f[BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,x3p);
+               f[BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3p);
+               //////////////////////////////////////////////////////////////////////////
+
+               drho = f[ZERO] + f[E] + f[W] + f[N] + f[S] + f[T] + f[B] 
+               + f[NE] + f[SW] + f[SE] + f[NW] + f[TE] + f[BW] + f[BE]
+               + f[TW] + f[TN] + f[BS] + f[BN] + f[TS] + f[TNE] + f[TSW]
+               + f[TSE] + f[TNW] + f[BNE] + f[BSW] + f[BSE] + f[BNW];
+
+               vx1 = f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] - f[BW]
+               + f[BE] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+               + f[BSE] - f[BNW]; 
+
+               vx2 = f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+               - f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+               + f[BNW]; 
+
+               vx3 = f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+               + f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+               - f[BNW];
+
+               LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+               feq[ZERO] =  c8o27*(drho-cu_sq);
+               feq[E] =  c2o27*(drho+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq);
+               feq[W] =  c2o27*(drho+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq);
+               feq[N] =  c2o27*(drho+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq);
+               feq[S] =  c2o27*(drho+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq);
+               feq[T] =  c2o27*(drho+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq);
+               feq[B] =  c2o27*(drho+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq);
+               feq[NE] = c1o54*(drho+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq);
+               feq[SW] = c1o54*(drho+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq);
+               feq[SE] = c1o54*(drho+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq);
+               feq[NW] = c1o54*(drho+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq);
+               feq[TE] = c1o54*(drho+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq);
+               feq[BW] = c1o54*(drho+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq);
+               feq[BE] = c1o54*(drho+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq);
+               feq[TW] = c1o54*(drho+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq);
+               feq[TN] = c1o54*(drho+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq);
+               feq[BS] = c1o54*(drho+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq);
+               feq[BN] = c1o54*(drho+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq);
+               feq[TS] = c1o54*(drho+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq);
+               feq[TNE]= c1o216*(drho+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq);
+               feq[BSW]= c1o216*(drho+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq);
+               feq[BNE]= c1o216*(drho+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq);
+               feq[TSW]= c1o216*(drho+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq);
+               feq[TSE]= c1o216*(drho+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq);
+               feq[BNW]= c1o216*(drho+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq);
+               feq[BSE]= c1o216*(drho+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq);
+               feq[TNW]= c1o216*(drho+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq);
+
+               //Relaxation
+               f[ZERO] += (feq[ZERO]-f[ZERO])*collFactor;
+               f[E] += (feq[E]-f[E])*collFactor;
+               f[W] += (feq[W]-f[W])*collFactor;
+               f[N] += (feq[N]-f[N])*collFactor;
+               f[S] += (feq[S]-f[S])*collFactor;
+               f[T] += (feq[T]-f[T])*collFactor;
+               f[B] += (feq[B]-f[B])*collFactor;
+               f[NE] += (feq[NE]-f[NE])*collFactor;
+               f[SW] += (feq[SW]-f[SW])*collFactor;
+               f[SE] += (feq[SE]-f[SE])*collFactor;
+               f[NW] += (feq[NW]-f[NW])*collFactor;
+               f[TE] += (feq[TE]-f[TE])*collFactor;
+               f[BW] += (feq[BW]-f[BW])*collFactor;
+               f[BE] += (feq[BE]-f[BE])*collFactor;
+               f[TW] += (feq[TW]-f[TW])*collFactor;
+               f[TN] += (feq[TN]-f[TN])*collFactor;
+               f[BS] += (feq[BS]-f[BS])*collFactor;
+               f[BN] += (feq[BN]-f[BN])*collFactor;
+               f[TS] += (feq[TS]-f[TS])*collFactor;
+
+               f[TNE] += (feq[TNE]-f[TNE])*collFactor;
+               f[BSW] += (feq[BSW]-f[BSW])*collFactor;
+               f[BNE] += (feq[BNE]-f[BNE])*collFactor;
+               f[TSW] += (feq[TSW]-f[TSW])*collFactor;
+               f[TSE] += (feq[TSE]-f[TSE])*collFactor;
+               f[BNW] += (feq[BNW]-f[BNW])*collFactor;
+               f[BSE] += (feq[BSE]-f[BSE])*collFactor;
+               f[TNW] += (feq[TNW]-f[TNW])*collFactor;
+
+               //////////////////////////////////////////////////////////////////////////
+               //forcing
+               if (withForcing)
+               {
+                  muX1 = x1+ix1*bcArrayMaxX1;
+                  muX2 = x2+ix2*bcArrayMaxX2;
+                  muX3 = x3+ix3*bcArrayMaxX3;
+
+                  forcingX1 = muForcingX1.Eval();
+                  forcingX2 = muForcingX2.Eval();
+                  forcingX3 = muForcingX3.Eval();
+
+                  f[ZERO] +=                   0.0                        ;
+                  f[E  ] +=  3.0*c2o27  *  (forcingX1)                    ;
+                  f[W  ] +=  3.0*c2o27  *  (-forcingX1)                   ;
+                  f[N  ] +=  3.0*c2o27  *             (forcingX2)         ;
+                  f[S  ] +=  3.0*c2o27  *             (-forcingX2)        ;
+                  f[T  ] +=  3.0*c2o27  *                     (forcingX3) ;
+                  f[B  ] +=  3.0*c2o27  *                     (-forcingX3);
+                  f[NE ] +=  3.0*c1o54 * ( forcingX1+forcingX2          ) ;
+                  f[SW ] +=  3.0*c1o54 * (-forcingX1-forcingX2          ) ;
+                  f[SE ] +=  3.0*c1o54 * ( forcingX1-forcingX2          ) ;
+                  f[NW ] +=  3.0*c1o54 * (-forcingX1+forcingX2          ) ;
+                  f[TE ] +=  3.0*c1o54 * ( forcingX1          +forcingX3) ;
+                  f[BW ] +=  3.0*c1o54 * (-forcingX1          -forcingX3) ;
+                  f[BE ] +=  3.0*c1o54 * ( forcingX1          -forcingX3) ;
+                  f[TW ] +=  3.0*c1o54 * (-forcingX1          +forcingX3) ;
+                  f[TN ] +=  3.0*c1o54 * (           forcingX2+forcingX3) ;
+                  f[BS ] +=  3.0*c1o54 * (          -forcingX2-forcingX3) ;
+                  f[BN ] +=  3.0*c1o54 * (           forcingX2-forcingX3) ;
+                  f[TS ] +=  3.0*c1o54 * (          -forcingX2+forcingX3) ;
+                  f[TNE] +=  3.0*c1o216* ( forcingX1+forcingX2+forcingX3) ;
+                  f[BSW] +=  3.0*c1o216* (-forcingX1-forcingX2-forcingX3) ;
+                  f[BNE] +=  3.0*c1o216* ( forcingX1+forcingX2-forcingX3) ;
+                  f[TSW] +=  3.0*c1o216* (-forcingX1-forcingX2+forcingX3) ;
+                  f[TSE] +=  3.0*c1o216* ( forcingX1-forcingX2+forcingX3) ;
+                  f[BNW] +=  3.0*c1o216* (-forcingX1+forcingX2-forcingX3) ;
+                  f[BSE] +=  3.0*c1o216* ( forcingX1-forcingX2-forcingX3) ;
+                  f[TNW] +=  3.0*c1o216* (-forcingX1+forcingX2+forcingX3) ;
+               }
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = f[ZERO] + f[E] + f[W] + f[N] + f[S] + f[T] + f[B] 
+               + f[NE] + f[SW] + f[SE] + f[NW] + f[TE] + f[BW] + f[BE]
+               + f[TW] + f[TN] + f[BS] + f[BN] + f[TS] + f[TNE] + f[TSW]
+               + f[TSE] + f[TNW] + f[BNE] + f[BSW] + f[BSE] + f[BNW];
+               LBMReal dif = drho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho is not correct"));
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::INV_E];
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::INV_N];
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::INV_T];
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::INV_NE];
+               (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,  x3) = f[D3Q27System::INV_NW];
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::INV_TE];
+               (*this->localDistributions)(D3Q27System::ET_TW,x1p,x2,  x3) = f[D3Q27System::INV_TW];
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::INV_TN];
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2p,x3) = f[D3Q27System::INV_TS];
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::INV_TNE];
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,  x3) = f[D3Q27System::INV_TNW];
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2p,x3) = f[D3Q27System::INV_TSE];
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3) = f[D3Q27System::INV_TSW];
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,  x3    ) = f[D3Q27System::INV_W ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2p,x3    ) = f[D3Q27System::INV_S ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3p  ) = f[D3Q27System::INV_B ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3   ) = f[D3Q27System::INV_SW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2p,x3   ) = f[D3Q27System::INV_SE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,  x3p ) = f[D3Q27System::INV_BW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3p ) = f[D3Q27System::INV_BE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2p,x3p ) = f[D3Q27System::INV_BS];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3p ) = f[D3Q27System::INV_BN];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p) = f[D3Q27System::INV_BSW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2p,x3p) = f[D3Q27System::INV_BSE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,  x3p) = f[D3Q27System::INV_BNW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3p) = f[D3Q27System::INV_BNE];
+
+               (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO];
+               //////////////////////////////////////////////////////////////////////////
+
+
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelETD3Q27BGK::getCallculationTime()
+{
+   return 0;
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27BGK.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27BGK.h
new file mode 100644
index 0000000000000000000000000000000000000000..c3a7c3c31bb932794563baa3ba9be4c977c34800
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27BGK.h
@@ -0,0 +1,45 @@
+#ifndef LBMKERNELETD3Q27BGK_H
+#define LBMKERNELETD3Q27BGK_H
+
+#include "LBMKernelETD3Q27.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+#include <boost/serialization/export.hpp>
+
+class LBMKernelETD3Q27BGK;
+typedef boost::shared_ptr<LBMKernelETD3Q27BGK> LBMKernelETD3Q27BGKPtr;
+
+class LBMKernelETD3Q27BGK :  public LBMKernelETD3Q27
+{
+public:
+   LBMKernelETD3Q27BGK();
+   LBMKernelETD3Q27BGK(int nx1, int nx2, int nx3, bool compressible);
+   ~LBMKernelETD3Q27BGK(void);
+   void calculate();
+   LBMKernel3DPtr clone();
+   double getCallculationTime();
+
+private:
+   void init();
+   void collideAllCompressible();
+   void collideAllIncompressible();
+
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributions;
+
+   mu::value_type muX1,muX2,muX3;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+   }
+
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..239324658abc0b71d7b682ce49735ec9395e3970
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB.cpp
@@ -0,0 +1,915 @@
+#include "LBMKernelETD3Q27CCLB.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+#include <math.h>
+#include <omp.h>
+
+#define PROOF_CORRECTNESS
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLB::LBMKernelETD3Q27CCLB()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLB::LBMKernelETD3Q27CCLB(int nx1, int nx2, int nx3, Parameter p) 
+   : LBMKernelETD3Q27(nx1, nx2, nx3),
+     parameter(p)
+{
+   this->compressible = false;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLB::~LBMKernelETD3Q27CCLB(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLB::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+2, nx2+2, nx3+2, -999.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27CCLB::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB(nx1, nx2, nx3, parameter));
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLB>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   switch (parameter)
+   {
+   case NORMAL:
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLB>(kernel)->OxyyMxzz = 1.0;
+   	break;
+   case MAGIC:
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLB>(kernel)->OxyyMxzz = 2.0 +(-collFactor);
+      break;
+   }
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLB::calculate()
+{
+   timer.resetAndStart();
+   collideAll();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLB::collideAll()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dt",&muDeltaT);
+      muForcingX2.DefineVar("dt",&muDeltaT);
+      muForcingX3.DefineVar("dt",&muDeltaT);
+
+      muNu = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nu",&muNu);
+      muForcingX2.DefineVar("nu",&muNu);
+      muForcingX3.DefineVar("nu",&muNu);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth;
+
+
+//#pragma omp parallel num_threads(8)
+   {
+   //   int i = omp_get_thread_num();
+   //   printf_s("Hello from thread %d\n", i);
+   //}
+//#pragma omp for 
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               int x1p = x1 + 1;
+               int x2p = x2 + 1;
+               int x3p = x3 + 1;
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////
+
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+
+               //Rest ist b
+
+               //mfxyz
+               //a - negative
+               //b - null
+               //c - positive
+               
+               // a b c
+               //-1 0 1
+
+               LBMReal mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               LBMReal mfbcb = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3); 
+               LBMReal mfbbc = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               LBMReal mfccb = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               LBMReal mfacb = (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,x3);
+               LBMReal mfcbc = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               LBMReal mfabc = (*this->localDistributions)(D3Q27System::ET_TW, x1p,x2,x3);
+               LBMReal mfbcc = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               LBMReal mfbac = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2p,x3);
+               LBMReal mfccc = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               LBMReal mfacc = (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,x3);
+               LBMReal mfcac = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2p,x3);
+               LBMReal mfaac = (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3);
+
+               LBMReal mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,x3  );
+               LBMReal mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2p,x3  );
+               LBMReal mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3p  );
+               LBMReal mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3 );
+               LBMReal mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2p,x3 );
+               LBMReal mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,x3p );
+               LBMReal mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3p );
+               LBMReal mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2p,x3p );
+               LBMReal mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3p );
+               LBMReal mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p);
+               LBMReal mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2p,x3p);
+               LBMReal mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,x3p);
+               LBMReal mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3p);
+
+               LBMReal mfbbb = (*this->zeroDistributions)(x1,x2,x3);
+
+               LBMReal m0, m1, m2;
+
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb));
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab));
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba));
+
+               //forcing 
+               ///////////////////////////////////////////////////////////////////////////////////////////
+               if (withForcing)
+               {
+                  muX1 = static_cast<double>(x1-1+ix1*maxX1);
+                  muX2 = static_cast<double>(x2-1+ix2*maxX2);
+                  muX3 = static_cast<double>(x3-1+ix3*maxX3);
+
+                  forcingX1 = muForcingX1.Eval();
+                  forcingX2 = muForcingX2.Eval();
+                  forcingX3 = muForcingX3.Eval();
+
+                  vvx += forcingX1*deltaT*0.5; // X
+                  vvy += forcingX2*deltaT*0.5; // Y
+                  vvz += forcingX3*deltaT*0.5; // Z
+               }
+               ///////////////////////////////////////////////////////////////////////////////////////////               
+               LBMReal oMdrho;
+
+               oMdrho=mfccc+mfaaa;
+               m0=mfaca+mfcac;
+               m1=mfacc+mfcaa;
+               m2=mfaac+mfcca;
+               oMdrho+=m0;
+               m1+=m2;
+               oMdrho+=m1;
+               m0=mfbac+mfbca;
+               m1=mfbaa+mfbcc;
+               m0+=m1;
+               m1=mfabc+mfcba;
+               m2=mfaba+mfcbc;
+               m1+=m2;
+               m0+=m1;
+               m1=mfacb+mfcab;
+               m2=mfaab+mfccb;
+               m1+=m2;
+               m0+=m1;
+               oMdrho+=m0;
+               m0=mfabb+mfcbb;
+               m1=mfbab+mfbcb;
+               m2=mfbba+mfbbc;
+               m0+=m1+m2;
+               m0+=mfbbb; //hat gefehlt
+               oMdrho = 1. - (oMdrho + m0);
+
+               LBMReal vx2;
+               LBMReal vy2;
+               LBMReal vz2;
+               vx2=vvx*vvx;
+               vy2=vvy*vvy;
+               vz2=vvz*vvz;
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal wadjust;
+               LBMReal qudricLimit = 0.01;
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa + mfaac;
+               m1    = mfaac - mfaaa;
+               m0    = m2          + mfaab;
+               mfaaa = m0;
+               m0   += c1o36 * oMdrho;   
+               mfaab = m1 -        m0 * vvz;
+               mfaac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2          + mfabb;
+               mfaba = m0;
+               m0   += c1o9 * oMdrho;
+               mfabb = m1 -        m0 * vvz;
+               mfabc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2          + mfacb;
+               mfaca = m0;
+               m0   += c1o36 * oMdrho;
+               mfacb = m1 -        m0 * vvz;
+               mfacc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbac;
+               m1    = mfbac - mfbaa;
+               m0    = m2          + mfbab;
+               mfbaa = m0;
+               m0   += c1o9 * oMdrho;
+               mfbab = m1 -        m0 * vvz;
+               mfbac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2          + mfbbb;
+               mfbba = m0;
+               m0   += c4o9 * oMdrho;
+               mfbbb = m1 -        m0 * vvz;
+               mfbbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2          + mfbcb;
+               mfbca = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcb = m1 -        m0 * vvz;
+               mfbcc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcac;
+               m1    = mfcac - mfcaa;
+               m0    = m2          + mfcab;
+               mfcaa = m0;
+               m0   += c1o36 * oMdrho;
+               mfcab = m1 -        m0 * vvz;
+               mfcac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2          + mfcbb;
+               mfcba = m0;
+               m0   += c1o9 * oMdrho;
+               mfcbb = m1 -        m0 * vvz;
+               mfcbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2          + mfccb;
+               mfcca = m0;
+               m0   += c1o36 * oMdrho;
+               mfccb = m1 -        m0 * vvz;
+               mfccc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa + mfaca;
+               m1    = mfaca - mfaaa;
+               m0    = m2          + mfaba;
+               mfaaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfaba = m1 -        m0 * vvy;
+               mfaca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2          + mfabb;
+               mfaab = m0;
+               mfabb = m1 -        m0 * vvy;
+               mfacb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2          + mfabc;
+               mfaac = m0;
+               m0   += c1o18 * oMdrho;
+               mfabc = m1 -        m0 * vvy;
+               mfacc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbca;
+               m1    = mfbca - mfbaa;
+               m0    = m2          + mfbba;
+               mfbaa = m0;
+               m0   += c2o3 * oMdrho;
+               mfbba = m1 -        m0 * vvy;
+               mfbca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2          + mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -        m0 * vvy;
+               mfbcb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2          + mfbbc;
+               mfbac = m0;
+               m0   += c2o9 * oMdrho;
+               mfbbc = m1 -        m0 * vvy;
+               mfbcc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcca;
+               m1    = mfcca - mfcaa;
+               m0    = m2          + mfcba;
+               mfcaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfcba = m1 -        m0 * vvy;
+               mfcca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2          + mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -        m0 * vvy;
+               mfccb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2          + mfcbc;
+               mfcac = m0;
+               m0   += c1o18 * oMdrho;
+               mfcbc = m1 -        m0 * vvy;
+               mfccc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9            Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa + mfcaa;
+               m1    = mfcaa - mfaaa;
+               m0    = m2          + mfbaa;
+               mfaaa = m0;
+               m0   += 1. * oMdrho;
+               mfbaa = m1 -        m0 * vvx;
+               mfcaa = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2          + mfbba;
+               mfaba = m0;
+               mfbba = m1 -        m0 * vvx;
+               mfcba = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2          + mfbca;
+               mfaca = m0;
+               m0   += c1o3 * oMdrho;
+               mfbca = m1 -        m0 * vvx;
+               mfcca = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab + mfcab;
+               m1    = mfcab - mfaab;
+               m0    = m2          + mfbab;
+               mfaab = m0;
+               mfbab = m1 -        m0 * vvx;
+               mfcab = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2          + mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -        m0 * vvx;
+               mfcbb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2          + mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -        m0 * vvx;
+               mfccb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac + mfcac;
+               m1    = mfcac - mfaac;
+               m0    = m2          + mfbac;
+               mfaac = m0;
+               m0   += c1o3 * oMdrho;
+               mfbac = m1 -        m0 * vvx;
+               mfcac = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2          + mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -        m0 * vvx;
+               mfcbc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2          + mfbcc;
+               mfacc = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcc = m1 -        m0 * vvx;
+               mfccc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal OxxPyyPzz = 1.; //omega2 or bulk viscosity
+               LBMReal OxyyPxzz  = 1.;//-s9;//2+s9;//
+               //LBMReal OxyyMxzz  = 1.;//2+s9;//
+               LBMReal O4        = 1.;
+               LBMReal O5        = 1.;
+               LBMReal O6        = 1.;
+
+               //Cum 4.
+               //LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab); // till 18.05.2015
+               //LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb); // till 18.05.2015
+               //LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb); // till 18.05.2015
+
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 ) * mfabb + 2. * mfbba * mfbab);
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 ) * mfbab + 2. * mfbba * mfabb);
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 ) * mfbba + 2. * mfbab * mfabb);
+
+               LBMReal CUMcca = mfcca - ((mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho);
+               LBMReal CUMcac = mfcac - ((mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho);
+               LBMReal CUMacc = mfacc - ((mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho);
+
+               //Cum 5.
+               LBMReal CUMbcc = mfbcc - (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) - c1o3 * (mfbca + mfbac) * oMdrho;
+               LBMReal CUMcbc = mfcbc - (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) - c1o3 * (mfcba + mfabc) * oMdrho;
+               LBMReal CUMccb = mfccb - (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) - c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc  +((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) +c1o27*oMdrho;
+
+               //2.
+               // linear combinations
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz         = mfcaa - mfaac;
+
+               LBMReal dxux = -c1o2 * collFactor *(mxxMyy + mxxMzz) + c1o2 * OxxPyyPzz*(mfaaa - mxxPyyPzz);
+               LBMReal dyuy = dxux + collFactor * c3o2 * mxxMyy;
+               LBMReal dzuz = dxux + collFactor * c3o2 * mxxMzz;
+
+               //relax
+               mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+               mxxMyy    += collFactor * (-mxxMyy) - 3. * (1. - c1o2 * collFactor) * (vx2 * dxux - vy2 * dyuy);
+               mxxMzz    += collFactor * (-mxxMzz) - 3. * (1. - c1o2 * collFactor) * (vx2 * dxux - vz2 * dzuz);
+
+               mfabb     += collFactor * (-mfabb);
+               mfbab     += collFactor * (-mfbab);
+               mfbba     += collFactor * (-mfbba);
+
+               // linear combinations back
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mfbbb)/(fabs(mfbbb)+qudricLimit);
+               mfbbb     += wadjust * (-mfbbb);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxyPyzz)/(fabs(mxxyPyzz)+qudricLimit);
+               mxxyPyzz  += wadjust * (-mxxyPyzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxyMyzz)/(fabs(mxxyMyzz)+qudricLimit);
+               mxxyMyzz  += wadjust * (-mxxyMyzz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxzPyyz)/(fabs(mxxzPyyz)+qudricLimit);
+               mxxzPyyz  += wadjust * (-mxxzPyyz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxzMyyz)/(fabs(mxxzMyyz)+qudricLimit);
+               mxxzMyyz  += wadjust * (-mxxzMyyz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxyyPxzz)/(fabs(mxyyPxzz)+qudricLimit);
+               mxyyPxzz  += wadjust * (-mxyyPxzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxyyMxzz)/(fabs(mxyyMxzz)+qudricLimit);
+               mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               //4.
+               CUMacc += O4 * (-CUMacc);
+               CUMcac += O4 * (-CUMcac);
+               CUMcca += O4 * (-CUMcca);
+
+               CUMbbc += O4 * (-CUMbbc);
+               CUMbcb += O4 * (-CUMbcb);
+               CUMcbb += O4 * (-CUMcbb);
+
+               //5.
+               CUMbcc += O5 * (-CUMbcc);
+               CUMcbc += O5 * (-CUMcbc);
+               CUMccb += O5 * (-CUMccb);
+
+               //6.
+               CUMccc += O6 * (-CUMccc);
+
+               //back cumulants to central moments
+               //4.
+               //mfcbb = CUMcbb + ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab); // till 18.05.2015
+               //mfbcb = CUMbcb + ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb); // till 18.05.2015
+               //mfbbc = CUMbbc + ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb); // till 18.05.2015
+
+               mfcbb = CUMcbb + ((mfcaa + c1o3 ) * mfabb + 2. * mfbba * mfbab);
+               mfbcb = CUMbcb + ((mfaca + c1o3 ) * mfbab + 2. * mfbba * mfabb);
+               mfbbc = CUMbbc + ((mfaac + c1o3 ) * mfbba + 2. * mfbab * mfabb);
+
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac) * oMdrho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc) * oMdrho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) -c1o27*oMdrho;
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //forcing
+               mfbaa=-mfbaa;
+               mfaba=-mfaba;
+               mfaab=-mfaab;
+               //////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa                * (1. - vz2)              - 1. * oMdrho * vz2;
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2;
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2);
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2;
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2);
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2;
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2);
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2;
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2);
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2;
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2);
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca                  * (1. - vz2)              - c1o9 * oMdrho * vz2;
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab                  * (1. - vy2)              - c2o3 * oMdrho * vy2;
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2;
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2);
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2);
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2);
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab                  * (1. - vy2)              - c2o9 * oMdrho * vy2;
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb                  * (1. - vx2)              - c4o9 * oMdrho * vx2;
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho="+UbSystem::toString(rho)+", rho_post="+UbSystem::toString(rho_post)
+                     +" dif="+UbSystem::toString(dif)
+                     +" rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27CCLB::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3)    = mfabb;
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3)    = mfbab;
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3)    = mfbba;
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3)   = mfaab;
+               (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,  x3)   = mfcab;
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3)   = mfaba;
+               (*this->localDistributions)(D3Q27System::ET_TW,x1p,x2,  x3)   = mfcba;
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3)   = mfbaa;
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2p,x3)   = mfbca;
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3)  = mfaaa;
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,  x3)  = mfcaa;
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2p,x3)  = mfaca;
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3)  = mfcca;
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,  x3    ) = mfcbb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2p,x3    ) = mfbcb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3p  ) = mfbbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3   ) = mfccb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2p,x3   ) = mfacb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,  x3p ) = mfcbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3p ) = mfabc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2p,x3p ) = mfbcc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3p ) = mfbac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p) = mfccc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2p,x3p) = mfacc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,  x3p) = mfcac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3p) = mfaac;
+
+               (*this->zeroDistributions)(x1,x2,x3) = mfbbb;
+               //////////////////////////////////////////////////////////////////////////
+
+            }
+         }
+      }
+   }
+
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelETD3Q27CCLB::getCallculationTime()
+{
+   //return timer.getDuration();
+   return timer.getTotalTime();
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc08a8b320abf68164037c0d6e1ae36a3033f452
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB.h
@@ -0,0 +1,69 @@
+//Cascaded Cumulant LBM
+
+#ifndef LBMKernelETD3Q27CCLB_H
+#define LBMKernelETD3Q27CCLB_H
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+
+class LBMKernelETD3Q27CCLB;
+typedef boost::shared_ptr<LBMKernelETD3Q27CCLB> LBMKernelETD3Q27CCLBPtr;
+
+//! \brief   Cascaded Cumulant LBM kernel. 
+//! \details CFD solver that use Cascaded Cumulant Lattice Boltzmann method for D3Q27 model
+//! \author  K. Kucher, M. Geier
+class LBMKernelETD3Q27CCLB :  public LBMKernelETD3Q27
+{
+public:
+   //! This option set relaxation parameter: NORMAL  
+   enum Parameter{NORMAL, MAGIC};
+public:
+   LBMKernelETD3Q27CCLB();
+   //! Constructor
+   //! \param nx1 number of nodes in x dimension
+   //! \param nx2 number of nodes in y dimension
+   //! \param nx3 number of nodes in z dimension
+   //! \param p   set relaxation parameter: NORMAL is OxyyMxzz = 1.0 and MAGIC is OxyyMxzz = 2.0 +(-collFactor)
+   LBMKernelETD3Q27CCLB(int nx1, int nx2, int nx3, Parameter p);
+   virtual ~LBMKernelETD3Q27CCLB(void);
+   virtual void calculate();
+   virtual LBMKernel3DPtr clone();
+   double getCallculationTime();
+
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+      ar & OxyyMxzz; 
+      ar & parameter;
+   }
+
+   virtual void collideAll();  
+   virtual void init();
+   LBMReal f[D3Q27System::ENDF+1];
+
+   UbTimer timer;
+
+   LBMReal OxyyMxzz;
+   Parameter parameter;
+
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributions;
+
+   mu::value_type muX1,muX2,muX3;
+   mu::value_type muDeltaT;
+   mu::value_type muNu;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBSparse.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBSparse.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..66dae51fdd7b8ccdab9d27059c04ace4061b7208
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBSparse.cpp
@@ -0,0 +1,903 @@
+#include "LBMKernelETD3Q27CCLBSparse.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "EsoTwistD3Q27SparseData.h"
+#include <math.h>
+
+#define PROOF_CORRECTNESS
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBSparse::LBMKernelETD3Q27CCLBSparse()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBSparse::LBMKernelETD3Q27CCLBSparse(int nx1, int nx2, int nx3, Parameter p) 
+   : LBMKernelETD3Q27(nx1, nx2, nx3),
+   parameter(p)
+{
+   this->compressible = false;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBSparse::~LBMKernelETD3Q27CCLBSparse(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBSparse::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   size_t ibx[3];
+   ibx[0] = block.lock()->getX1();
+   ibx[1] = block.lock()->getX2();
+   ibx[2] = block.lock()->getX3();
+
+   size_t nx[3];
+   nx[0] = nx1;
+   nx[1] = nx2;
+   nx[2] = nx3;
+
+   DistributionArray3DPtr d(new EsoTwistD3Q27SparseData(ibx, nx, block.lock()->getLevel(), -999.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27CCLBSparse::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLBSparse(nx1, nx2, nx3, parameter));
+   kernel->setBlock(block.lock());
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBSparse>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   switch (parameter)
+   {
+   case NORMAL:
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBSparse>(kernel)->OxyyMxzz = 1.0;
+      break;
+   case MAGIC:
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBSparse>(kernel)->OxyyMxzz = 2.0 +(-collFactor);
+      break;
+   }
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBSparse::calculate()
+{
+   timer.resetAndStart();
+   collideAll();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBSparse::collideAll()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dx",&muDeltaT);
+      muForcingX2.DefineVar("dx",&muDeltaT);
+      muForcingX3.DefineVar("dx",&muDeltaT);
+
+      muNu = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nu",&muNu);
+      muForcingX2.DefineVar("nu",&muNu);
+      muForcingX3.DefineVar("nu",&muNu);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   EsoTwistD3Q27SparseDataPtr fd = boost::dynamic_pointer_cast<EsoTwistD3Q27SparseData>(dataSet->getFdistributions());
+   EsoTwistD3Q27SparseData::SparseDataPtr ld  = fd->getLocalDistributions();;
+   EsoTwistD3Q27SparseData::SparseDataPtr nld = fd->getNonLocalDistributions();
+   EsoTwistD3Q27SparseData::SparseDataPtr zd  = fd->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = 0;//ghostLayerWidth;
+   int minX2 = 0;//ghostLayerWidth;
+   int minX3 = 0;//ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1;//-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2;//-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3;//-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+
+               //Rest ist b
+
+               size_t x1plus = x1+1;
+               size_t x2plus = x2+1;
+               size_t x3plus = x3+1;
+
+               LBMReal mfcbb = (*ld)[fd->index4D(D3Q27System::ET_E, x1,x2,x3)];
+               LBMReal mfbcb = (*ld)[fd->index4D(D3Q27System::ET_N,x1,x2,x3)];  
+               LBMReal mfbbc = (*ld)[fd->index4D(D3Q27System::ET_T,x1,x2,x3)];
+               LBMReal mfccb = (*ld)[fd->index4D(D3Q27System::ET_NE,x1,x2,x3)];
+               LBMReal mfacb = (*ld)[fd->index4D(D3Q27System::ET_NW,x1plus,x2,x3)];
+               LBMReal mfcbc = (*ld)[fd->index4D(D3Q27System::ET_TE,x1,x2,x3)];
+               LBMReal mfabc = (*ld)[fd->index4D(D3Q27System::ET_TW, x1plus,x2,x3)];
+               LBMReal mfbcc = (*ld)[fd->index4D(D3Q27System::ET_TN,x1,x2,x3)];
+               LBMReal mfbac = (*ld)[fd->index4D(D3Q27System::ET_TS,x1,x2plus,x3)];
+               LBMReal mfccc = (*ld)[fd->index4D(D3Q27System::ET_TNE,x1,x2,x3)];
+               LBMReal mfacc = (*ld)[fd->index4D(D3Q27System::ET_TNW,x1plus,x2,x3)];
+               LBMReal mfcac = (*ld)[fd->index4D(D3Q27System::ET_TSE,x1,x2plus,x3)];
+               LBMReal mfaac = (*ld)[fd->index4D(D3Q27System::ET_TSW,x1plus,x2plus,x3)];
+
+               LBMReal mfabb = (*nld)[fd->index4D(D3Q27System::ET_W,x1plus,x2,x3  )];
+               LBMReal mfbab = (*nld)[fd->index4D(D3Q27System::ET_S,x1,x2plus,x3  )];
+               LBMReal mfbba = (*nld)[fd->index4D(D3Q27System::ET_B,x1,x2,x3plus  )];
+               LBMReal mfaab = (*nld)[fd->index4D(D3Q27System::ET_SW,x1plus,x2plus,x3 )];
+               LBMReal mfcab = (*nld)[fd->index4D(D3Q27System::ET_SE,x1,x2plus,x3 )];
+               LBMReal mfaba = (*nld)[fd->index4D(D3Q27System::ET_BW,x1plus,x2,x3plus )];
+               LBMReal mfcba = (*nld)[fd->index4D(D3Q27System::ET_BE,x1,x2,x3plus )];
+               LBMReal mfbaa = (*nld)[fd->index4D(D3Q27System::ET_BS,x1,x2plus,x3plus )];
+               LBMReal mfbca = (*nld)[fd->index4D(D3Q27System::ET_BN,x1,x2,x3plus )];
+               LBMReal mfaaa = (*nld)[fd->index4D(D3Q27System::ET_BSW,x1plus,x2plus,x3plus)];
+               LBMReal mfcaa = (*nld)[fd->index4D(D3Q27System::ET_BSE,x1,x2plus,x3plus)];
+               LBMReal mfaca = (*nld)[fd->index4D(D3Q27System::ET_BNW,x1plus,x2,x3plus)];
+               LBMReal mfcca = (*nld)[fd->index4D(D3Q27System::ET_BNE,x1,x2,x3plus)];
+               
+               LBMReal mfbbb = (*zd)[fd->index3D(x1,x2,x3)];
+               //////////////////////////////////////////////////////////////////////////
+ 
+ 
+               LBMReal m0, m1, m2;
+
+
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb));
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab));
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba));
+
+               //forcing 
+               ///////////////////////////////////////////////////////////////////////////////////////////
+               if (withForcing)
+               {
+                  muX1 = static_cast<double>(x1-1+ix1*maxX1);
+                  muX2 = static_cast<double>(x2-1+ix2*maxX2);
+                  muX3 = static_cast<double>(x3-1+ix3*maxX3);
+
+                  forcingX1 = muForcingX1.Eval();
+                  forcingX2 = muForcingX2.Eval();
+                  forcingX3 = muForcingX3.Eval();
+
+                  vvx += forcingX1*0.5; // X
+                  vvy += forcingX2*0.5; // Y
+                  vvz += forcingX3*0.5; // Z
+               }
+               ///////////////////////////////////////////////////////////////////////////////////////////               
+               LBMReal oMdrho;
+
+               oMdrho=mfccc+mfaaa;
+               m0=mfaca+mfcac;
+               m1=mfacc+mfcaa;
+               m2=mfaac+mfcca;
+               oMdrho+=m0;
+               m1+=m2;
+               oMdrho+=m1;
+               m0=mfbac+mfbca;
+               m1=mfbaa+mfbcc;
+               m0+=m1;
+               m1=mfabc+mfcba;
+               m2=mfaba+mfcbc;
+               m1+=m2;
+               m0+=m1;
+               m1=mfacb+mfcab;
+               m2=mfaab+mfccb;
+               m1+=m2;
+               m0+=m1;
+               oMdrho+=m0;
+               m0=mfabb+mfcbb;
+               m1=mfbab+mfbcb;
+               m2=mfbba+mfbbc;
+               m0+=m1+m2;
+               m0+=mfbbb; //hat gefehlt
+               oMdrho = 1. - (oMdrho + m0);
+
+               LBMReal vx2;
+               LBMReal vy2;
+               LBMReal vz2;
+               vx2=vvx*vvx;
+               vy2=vvy*vvy;
+               vz2=vvz*vvz;
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal wadjust;
+               LBMReal qudricLimit = 0.01;
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa + mfaac;
+               m1    = mfaac - mfaaa;
+               m0    = m2          + mfaab;
+               mfaaa = m0;
+               m0   += c1o36 * oMdrho;   
+               mfaab = m1 -        m0 * vvz;
+               mfaac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2          + mfabb;
+               mfaba = m0;
+               m0   += c1o9 * oMdrho;
+               mfabb = m1 -        m0 * vvz;
+               mfabc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2          + mfacb;
+               mfaca = m0;
+               m0   += c1o36 * oMdrho;
+               mfacb = m1 -        m0 * vvz;
+               mfacc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbac;
+               m1    = mfbac - mfbaa;
+               m0    = m2          + mfbab;
+               mfbaa = m0;
+               m0   += c1o9 * oMdrho;
+               mfbab = m1 -        m0 * vvz;
+               mfbac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2          + mfbbb;
+               mfbba = m0;
+               m0   += c4o9 * oMdrho;
+               mfbbb = m1 -        m0 * vvz;
+               mfbbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2          + mfbcb;
+               mfbca = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcb = m1 -        m0 * vvz;
+               mfbcc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcac;
+               m1    = mfcac - mfcaa;
+               m0    = m2          + mfcab;
+               mfcaa = m0;
+               m0   += c1o36 * oMdrho;
+               mfcab = m1 -        m0 * vvz;
+               mfcac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2          + mfcbb;
+               mfcba = m0;
+               m0   += c1o9 * oMdrho;
+               mfcbb = m1 -        m0 * vvz;
+               mfcbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2          + mfccb;
+               mfcca = m0;
+               m0   += c1o36 * oMdrho;
+               mfccb = m1 -        m0 * vvz;
+               mfccc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa + mfaca;
+               m1    = mfaca - mfaaa;
+               m0    = m2          + mfaba;
+               mfaaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfaba = m1 -        m0 * vvy;
+               mfaca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2          + mfabb;
+               mfaab = m0;
+               mfabb = m1 -        m0 * vvy;
+               mfacb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2          + mfabc;
+               mfaac = m0;
+               m0   += c1o18 * oMdrho;
+               mfabc = m1 -        m0 * vvy;
+               mfacc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbca;
+               m1    = mfbca - mfbaa;
+               m0    = m2          + mfbba;
+               mfbaa = m0;
+               m0   += c2o3 * oMdrho;
+               mfbba = m1 -        m0 * vvy;
+               mfbca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2          + mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -        m0 * vvy;
+               mfbcb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2          + mfbbc;
+               mfbac = m0;
+               m0   += c2o9 * oMdrho;
+               mfbbc = m1 -        m0 * vvy;
+               mfbcc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcca;
+               m1    = mfcca - mfcaa;
+               m0    = m2          + mfcba;
+               mfcaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfcba = m1 -        m0 * vvy;
+               mfcca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2          + mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -        m0 * vvy;
+               mfccb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2          + mfcbc;
+               mfcac = m0;
+               m0   += c1o18 * oMdrho;
+               mfcbc = m1 -        m0 * vvy;
+               mfccc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9            Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa + mfcaa;
+               m1    = mfcaa - mfaaa;
+               m0    = m2          + mfbaa;
+               mfaaa = m0;
+               m0   += 1. * oMdrho;
+               mfbaa = m1 -        m0 * vvx;
+               mfcaa = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2          + mfbba;
+               mfaba = m0;
+               mfbba = m1 -        m0 * vvx;
+               mfcba = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2          + mfbca;
+               mfaca = m0;
+               m0   += c1o3 * oMdrho;
+               mfbca = m1 -        m0 * vvx;
+               mfcca = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab + mfcab;
+               m1    = mfcab - mfaab;
+               m0    = m2          + mfbab;
+               mfaab = m0;
+               mfbab = m1 -        m0 * vvx;
+               mfcab = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2          + mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -        m0 * vvx;
+               mfcbb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2          + mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -        m0 * vvx;
+               mfccb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac + mfcac;
+               m1    = mfcac - mfaac;
+               m0    = m2          + mfbac;
+               mfaac = m0;
+               m0   += c1o3 * oMdrho;
+               mfbac = m1 -        m0 * vvx;
+               mfcac = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2          + mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -        m0 * vvx;
+               mfcbc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2          + mfbcc;
+               mfacc = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcc = m1 -        m0 * vvx;
+               mfccc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal OxxPyyPzz = 1.;
+               LBMReal OxyyPxzz  = 1.;//-s9;//2+s9;//
+               //LBMReal OxyyMxzz  = 1.;//2+s9;//
+               LBMReal O4        = 1.;
+               LBMReal O5        = 1.;
+               LBMReal O6        = 1.;
+
+               //Cum 4.
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //Cum 5.
+               LBMReal CUMbcc = mfbcc - (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) - c1o3 * (mfbca + mfbac) * oMdrho;
+               LBMReal CUMcbc = mfcbc - (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) - c1o3 * (mfcba + mfabc) * oMdrho;
+               LBMReal CUMccb = mfccb - (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) - c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc  +((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) +c1o27*oMdrho;
+
+               //2.
+               // linear combinations
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz         = mfcaa - mfaac;
+
+               LBMReal dxux = -c1o2 * collFactor *(mxxMyy + mxxMzz) + c1o2 * OxxPyyPzz*(mfaaa - mxxPyyPzz);
+               LBMReal dyuy = dxux + collFactor * c3o2 * mxxMyy;
+               LBMReal dzuz = dxux + collFactor * c3o2 * mxxMzz;
+
+               //relax
+               mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+               mxxMyy    += collFactor * (-mxxMyy) - 3. * (1. - c1o2 * collFactor) * (vx2 * dxux - vy2 * dyuy);
+               mxxMzz    += collFactor * (-mxxMzz) - 3. * (1. - c1o2 * collFactor) * (vx2 * dxux - vz2 * dzuz);
+
+               mfabb     += collFactor * (-mfabb);
+               mfbab     += collFactor * (-mfbab);
+               mfbba     += collFactor * (-mfbba);
+
+               // linear combinations back
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mfbbb)/(fabs(mfbbb)+qudricLimit);
+               mfbbb     += wadjust * (-mfbbb);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxyPyzz)/(fabs(mxxyPyzz)+qudricLimit);
+               mxxyPyzz  += wadjust * (-mxxyPyzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxyMyzz)/(fabs(mxxyMyzz)+qudricLimit);
+               mxxyMyzz  += wadjust * (-mxxyMyzz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxzPyyz)/(fabs(mxxzPyyz)+qudricLimit);
+               mxxzPyyz  += wadjust * (-mxxzPyyz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxzMyyz)/(fabs(mxxzMyyz)+qudricLimit);
+               mxxzMyyz  += wadjust * (-mxxzMyyz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxyyPxzz)/(fabs(mxyyPxzz)+qudricLimit);
+               mxyyPxzz  += wadjust * (-mxyyPxzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxyyMxzz)/(fabs(mxyyMxzz)+qudricLimit);
+               mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               //4.
+               CUMacc += O4 * (-CUMacc);
+               CUMcac += O4 * (-CUMcac);
+               CUMcca += O4 * (-CUMcca);
+
+               CUMbbc += O4 * (-CUMbbc);
+               CUMbcb += O4 * (-CUMbcb);
+               CUMcbb += O4 * (-CUMcbb);
+
+               //5.
+               CUMbcc += O5 * (-CUMbcc);
+               CUMcbc += O5 * (-CUMcbc);
+               CUMccb += O5 * (-CUMccb);
+
+               //6.
+               CUMccc += O6 * (-CUMccc);
+
+               //back cumulants to central moments
+               //4.
+               mfcbb = CUMcbb + ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               mfbcb = CUMbcb + ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               mfbbc = CUMbbc + ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac) * oMdrho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc) * oMdrho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) -c1o27*oMdrho;
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //forcing
+               mfbaa=-mfbaa;
+               mfaba=-mfaba;
+               mfaab=-mfaab;
+               //////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa                * (1. - vz2)              - 1. * oMdrho * vz2;
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2;
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2);
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2;
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2);
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2;
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2);
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2;
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2);
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2;
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2);
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca                  * (1. - vz2)              - c1o9 * oMdrho * vz2;
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab                  * (1. - vy2)              - c2o3 * oMdrho * vy2;
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2;
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2);
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2);
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2);
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab                  * (1. - vy2)              - c2o9 * oMdrho * vy2;
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb                  * (1. - vx2)              - c4o9 * oMdrho * vx2;
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho="+UbSystem::toString(rho)+", rho_post="+UbSystem::toString(rho_post)
+                     +" dif="+UbSystem::toString(dif)
+                     +" rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27CCLBSparse::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*ld)[fd->index4D(D3Q27System::ET_E, x1,x2,x3)]               = mfabb;
+               (*ld)[fd->index4D(D3Q27System::ET_N,x1,x2,x3)]                = mfbab;
+               (*ld)[fd->index4D(D3Q27System::ET_T,x1,x2,x3)]                = mfbba;
+               (*ld)[fd->index4D(D3Q27System::ET_NE,x1,x2,x3)]               = mfaab;
+               (*ld)[fd->index4D(D3Q27System::ET_NW,x1plus,x2,x3)]           = mfcab;
+               (*ld)[fd->index4D(D3Q27System::ET_TE,x1,x2,x3)]               = mfaba;
+               (*ld)[fd->index4D(D3Q27System::ET_TW, x1plus,x2,x3)]          = mfcba;
+               (*ld)[fd->index4D(D3Q27System::ET_TN,x1,x2,x3)]               = mfbaa;
+               (*ld)[fd->index4D(D3Q27System::ET_TS,x1,x2plus,x3)]           = mfbca;
+               (*ld)[fd->index4D(D3Q27System::ET_TNE,x1,x2,x3)]              = mfaaa;
+               (*ld)[fd->index4D(D3Q27System::ET_TNW,x1plus,x2,x3)]          = mfcaa;
+               (*ld)[fd->index4D(D3Q27System::ET_TSE,x1,x2plus,x3)]          = mfaca;
+               (*ld)[fd->index4D(D3Q27System::ET_TSW,x1plus,x2plus,x3)]      = mfcca;
+                                                                          
+               (*nld)[fd->index4D(D3Q27System::ET_W,x1plus,x2,x3  )]         = mfcbb;
+               (*nld)[fd->index4D(D3Q27System::ET_S,x1,x2plus,x3  )]         = mfbcb;
+               (*nld)[fd->index4D(D3Q27System::ET_B,x1,x2,x3plus  )]         = mfbbc;
+               (*nld)[fd->index4D(D3Q27System::ET_SW,x1plus,x2plus,x3)]      = mfccb;
+               (*nld)[fd->index4D(D3Q27System::ET_SE,x1,x2plus,x3 )]         = mfacb;
+               (*nld)[fd->index4D(D3Q27System::ET_BW,x1plus,x2,x3plus)]      = mfcbc;
+               (*nld)[fd->index4D(D3Q27System::ET_BE,x1,x2,x3plus )]         = mfabc;
+               (*nld)[fd->index4D(D3Q27System::ET_BS,x1,x2plus,x3plus)]      = mfbcc;
+               (*nld)[fd->index4D(D3Q27System::ET_BN,x1,x2,x3plus )]         = mfbac;
+               (*nld)[fd->index4D(D3Q27System::ET_BSW,x1plus,x2plus,x3plus)] = mfccc;
+               (*nld)[fd->index4D(D3Q27System::ET_BSE,x1,x2plus,x3plus)]     = mfacc;
+               (*nld)[fd->index4D(D3Q27System::ET_BNW,x1plus,x2,x3plus)]     = mfcac;
+               (*nld)[fd->index4D(D3Q27System::ET_BNE,x1,x2,x3plus)]         = mfaac;
+
+               mfbbb = (*zd)[fd->index3D(x1,x2,x3)];
+               //////////////////////////////////////////////////////////////////////////
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelETD3Q27CCLBSparse::getCallculationTime()
+{
+   //return timer.getDuration();
+   return timer.getTotalTime();
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBSparse.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBSparse.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6b71a68c7608621b8eebd0dafa042c1568941c0
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBSparse.h
@@ -0,0 +1,68 @@
+//Cascaded Cumulant LBM
+
+#ifndef LBMKernelETD3Q27CCLBSparse_H
+#define LBMKernelETD3Q27CCLBSparse_H
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+//#include <SparseMatrix3D.h>
+//#include <SparseMatrix4D.h>
+
+
+class LBMKernelETD3Q27CCLBSparse;
+typedef boost::shared_ptr<LBMKernelETD3Q27CCLBSparse> LBMKernelETD3Q27CCLBSparsePtr;
+
+//! \brief   Cascaded Cumulant LBM kernel. 
+//! \details CFD solver that use Cascaded Cumulant Lattice Boltzmann method for D3Q27 model
+//! \author  K. Kucher, M. Geier
+class LBMKernelETD3Q27CCLBSparse :  public LBMKernelETD3Q27
+{
+public:
+   //! This option set relaxation parameter: NORMAL  
+   enum Parameter{NORMAL, MAGIC};
+public:
+   LBMKernelETD3Q27CCLBSparse();
+   //! Constructor
+   //! \param nx1 number of nodes in x dimension
+   //! \param nx2 number of nodes in y dimension
+   //! \param nx3 number of nodes in z dimension
+   //! \param p   set relaxation parameter: NORMAL is OxyyMxzz = 1.0 and MAGIC is OxyyMxzz = 2.0 +(-collFactor)
+   LBMKernelETD3Q27CCLBSparse(int nx1, int nx2, int nx3, Parameter p);
+   virtual ~LBMKernelETD3Q27CCLBSparse(void);
+   void calculate();
+   LBMKernel3DPtr clone();
+   double getCallculationTime();
+
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+      ar & OxyyMxzz; 
+      ar & parameter;
+   }
+
+   void collideAll();  
+   void init();
+   LBMReal f[D3Q27System::ENDF+1];
+
+   UbTimer timer;
+
+   LBMReal OxyyMxzz;
+   Parameter parameter;
+   
+   mu::value_type muX1,muX2,muX3;
+   mu::value_type muDeltaT;
+   mu::value_type muNu;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBWithSpongeLayer.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBWithSpongeLayer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78b0f94a78d1783fdc185be27e1983f2c7f1dc92
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBWithSpongeLayer.cpp
@@ -0,0 +1,931 @@
+#include "LBMKernelETD3Q27CCLBWithSpongeLayer.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+#include <math.h>
+
+#define PROOF_CORRECTNESS
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBWithSpongeLayer::LBMKernelETD3Q27CCLBWithSpongeLayer()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBWithSpongeLayer::LBMKernelETD3Q27CCLBWithSpongeLayer(int nx1, int nx2, int nx3, Parameter p) 
+   : LBMKernelETD3Q27CCLB(nx1, nx2, nx3, p)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBWithSpongeLayer::~LBMKernelETD3Q27CCLBWithSpongeLayer(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBWithSpongeLayer::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+2, nx2+2, nx3+2, -999.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27CCLBWithSpongeLayer::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLBWithSpongeLayer(nx1, nx2, nx3, parameter));
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBWithSpongeLayer>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   switch (parameter)
+   {
+   case NORMAL:
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBWithSpongeLayer>(kernel)->OxyyMxzz = 1.0;
+      break;
+   case MAGIC:
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBWithSpongeLayer>(kernel)->OxyyMxzz = 2.0 +(-collFactor);
+      break;
+   }
+
+   kernel->setWithSpongeLayer(withSpongeLayer);
+   if(withSpongeLayer) kernel->setSpongeLayer(muSpongeLayer);
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBWithSpongeLayer::calculate()
+{
+   timer.resetAndStart();
+   collideAll();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBWithSpongeLayer::collideAll()
+{
+   using namespace D3Q27System;
+
+   if(!withSpongeLayer)
+   {
+      UB_THROW(UbException(UB_EXARGS,"Sponge layer isn't initialized!"));
+   }
+   //initializing of forcing stuff 
+   //if (withForcing)
+   //{
+   //   muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+   //   muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+   //   muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+   //   muDeltaT = deltaT;
+
+   //   muForcingX1.DefineVar("dx",&muDeltaT);
+   //   muForcingX2.DefineVar("dx",&muDeltaT);
+   //   muForcingX3.DefineVar("dx",&muDeltaT);
+
+   //   muNu = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+   //   muForcingX1.DefineVar("nu",&muNu);
+   //   muForcingX2.DefineVar("nu",&muNu);
+   //   muForcingX3.DefineVar("nu",&muNu);
+
+   //   LBMReal forcingX1 = 0;
+   //   LBMReal forcingX2 = 0;
+   //   LBMReal forcingX3 = 0;
+   //}
+   /////////////////////////////////////
+   //initialization of sponge layer variables
+   //if (withSpongeLayer)
+   //{
+      muDeltaT = deltaT;
+      muSpongeLayer.DefineVar("dx",&muDeltaT);
+      muSpongeLayer.DefineVar("x1",&muX1); muSpongeLayer.DefineVar("x2",&muX2); muSpongeLayer.DefineVar("x3",&muX3);
+   //}
+   /////////////////////////////////////
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth-1;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth-1;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth-1;
+
+   LBMReal collFactor0 = collFactor;
+
+   for(int x3 = minX3; x3 <= maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 <= maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 <= maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               int x1p = x1 + 1;
+               int x2p = x2 + 1;
+               int x3p = x3 + 1;
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////
+
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+
+               //Rest ist b
+
+               LBMReal mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               LBMReal mfbcb = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3); 
+               LBMReal mfbbc = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               LBMReal mfccb = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               LBMReal mfacb = (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,x3);
+               LBMReal mfcbc = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               LBMReal mfabc = (*this->localDistributions)(D3Q27System::ET_TW, x1p,x2,x3);
+               LBMReal mfbcc = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               LBMReal mfbac = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2p,x3);
+               LBMReal mfccc = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               LBMReal mfacc = (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,x3);
+               LBMReal mfcac = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2p,x3);
+               LBMReal mfaac = (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3);
+
+               LBMReal mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,x3  );
+               LBMReal mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2p,x3  );
+               LBMReal mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3p  );
+               LBMReal mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3 );
+               LBMReal mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2p,x3 );
+               LBMReal mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,x3p );
+               LBMReal mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3p );
+               LBMReal mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2p,x3p );
+               LBMReal mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3p );
+               LBMReal mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p);
+               LBMReal mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2p,x3p);
+               LBMReal mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,x3p);
+               LBMReal mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3p);
+
+               LBMReal mfbbb = (*this->zeroDistributions)(x1,x2,x3);
+
+               LBMReal m0, m1, m2;
+               
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb));
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab));
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba));
+               //////////////////////////////////////////////////////////////////////////
+               //forcing 
+               ///////////////////////////////////////////////////////////////////////////////////////////
+               //if (withForcing)
+               //{
+               //   muX1 = (double)(x1-1+ix1*maxX1);
+               //   muX2 = (double)(x2-1+ix2*maxX2);
+               //   muX3 = (double)(x3-1+ix3*maxX3);
+
+               //   forcingX1 = muForcingX1.Eval();
+               //   forcingX2 = muForcingX2.Eval();
+               //   forcingX3 = muForcingX3.Eval();
+
+               //   vvx += forcingX1*0.5; // X
+               //   vvy += forcingX2*0.5; // Y
+               //   vvz += forcingX3*0.5; // Z
+               //}
+               ///////////////////////////////////////////////////////////////////////////////////////////      
+               //sponge layer
+               ///////////////////////////////////////////////////////////////////////////////////////////
+               //if (withSpongeLayer)
+               //{
+                  //if (!withForcing)
+                  //{
+                     muX1 = (double)(x1-1+ix1*maxX1);
+                     //muX2 = (double)(x2-1+ix2*maxX2);
+                     //muX3 = (double)(x3-1+ix3*maxX3);
+                  //}
+                  //spongeFactor ist von Funktion in muSpongeLayer abhängich und variiert zwischen 1 (nix tun) und 0.5 (collFactor etwa auf 1);
+                  LBMReal spongeFactor = muSpongeLayer.Eval();
+
+                  //if (spongeFactor == 0.5)
+                  //{
+                  //   int Test=0;
+                  //}
+
+                  //if(muX3 == ix3*maxX3/2 && muX2==ix2*maxX2/2)
+                  //   UBLOG(logINFO," x1="<<muX1<<" spongeFactor = " << spongeFactor <<" collFactor="<<collFactor);
+
+                  collFactor *= spongeFactor;
+
+                  //if(muX3 == ix3*maxX3/2 && muX2==ix2*maxX2/2)
+                  //   UBLOG(logINFO," x1="<<muX1<<" spongeFactor = " << spongeFactor <<" collFactor="<<collFactor);
+
+               //}
+               //////////////////////////////////////////////////////////////////////////
+
+               LBMReal oMdrho;
+
+               oMdrho=mfccc+mfaaa;
+               m0=mfaca+mfcac;
+               m1=mfacc+mfcaa;
+               m2=mfaac+mfcca;
+               oMdrho+=m0;
+               m1+=m2;
+               oMdrho+=m1;
+               m0=mfbac+mfbca;
+               m1=mfbaa+mfbcc;
+               m0+=m1;
+               m1=mfabc+mfcba;
+               m2=mfaba+mfcbc;
+               m1+=m2;
+               m0+=m1;
+               m1=mfacb+mfcab;
+               m2=mfaab+mfccb;
+               m1+=m2;
+               m0+=m1;
+               oMdrho+=m0;
+               m0=mfabb+mfcbb;
+               m1=mfbab+mfbcb;
+               m2=mfbba+mfbbc;
+               m0+=m1+m2;
+               m0+=mfbbb; //hat gefehlt
+               oMdrho = 1. - (oMdrho + m0);
+
+               LBMReal vx2;
+               LBMReal vy2;
+               LBMReal vz2;
+               vx2=vvx*vvx;
+               vy2=vvy*vvy;
+               vz2=vvz*vvz;
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal wadjust;
+               LBMReal qudricLimit = 0.01;
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa + mfaac;
+               m1    = mfaac - mfaaa;
+               m0    = m2          + mfaab;
+               mfaaa = m0;
+               m0   += c1o36 * oMdrho;   
+               mfaab = m1 -        m0 * vvz;
+               mfaac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2          + mfabb;
+               mfaba = m0;
+               m0   += c1o9 * oMdrho;
+               mfabb = m1 -        m0 * vvz;
+               mfabc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2          + mfacb;
+               mfaca = m0;
+               m0   += c1o36 * oMdrho;
+               mfacb = m1 -        m0 * vvz;
+               mfacc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbac;
+               m1    = mfbac - mfbaa;
+               m0    = m2          + mfbab;
+               mfbaa = m0;
+               m0   += c1o9 * oMdrho;
+               mfbab = m1 -        m0 * vvz;
+               mfbac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2          + mfbbb;
+               mfbba = m0;
+               m0   += c4o9 * oMdrho;
+               mfbbb = m1 -        m0 * vvz;
+               mfbbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2          + mfbcb;
+               mfbca = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcb = m1 -        m0 * vvz;
+               mfbcc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcac;
+               m1    = mfcac - mfcaa;
+               m0    = m2          + mfcab;
+               mfcaa = m0;
+               m0   += c1o36 * oMdrho;
+               mfcab = m1 -        m0 * vvz;
+               mfcac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2          + mfcbb;
+               mfcba = m0;
+               m0   += c1o9 * oMdrho;
+               mfcbb = m1 -        m0 * vvz;
+               mfcbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2          + mfccb;
+               mfcca = m0;
+               m0   += c1o36 * oMdrho;
+               mfccb = m1 -        m0 * vvz;
+               mfccc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa + mfaca;
+               m1    = mfaca - mfaaa;
+               m0    = m2          + mfaba;
+               mfaaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfaba = m1 -        m0 * vvy;
+               mfaca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2          + mfabb;
+               mfaab = m0;
+               mfabb = m1 -        m0 * vvy;
+               mfacb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2          + mfabc;
+               mfaac = m0;
+               m0   += c1o18 * oMdrho;
+               mfabc = m1 -        m0 * vvy;
+               mfacc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbca;
+               m1    = mfbca - mfbaa;
+               m0    = m2          + mfbba;
+               mfbaa = m0;
+               m0   += c2o3 * oMdrho;
+               mfbba = m1 -        m0 * vvy;
+               mfbca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2          + mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -        m0 * vvy;
+               mfbcb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2          + mfbbc;
+               mfbac = m0;
+               m0   += c2o9 * oMdrho;
+               mfbbc = m1 -        m0 * vvy;
+               mfbcc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcca;
+               m1    = mfcca - mfcaa;
+               m0    = m2          + mfcba;
+               mfcaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfcba = m1 -        m0 * vvy;
+               mfcca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2          + mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -        m0 * vvy;
+               mfccb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2          + mfcbc;
+               mfcac = m0;
+               m0   += c1o18 * oMdrho;
+               mfcbc = m1 -        m0 * vvy;
+               mfccc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9            Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa + mfcaa;
+               m1    = mfcaa - mfaaa;
+               m0    = m2          + mfbaa;
+               mfaaa = m0;
+               m0   += 1. * oMdrho;
+               mfbaa = m1 -        m0 * vvx;
+               mfcaa = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2          + mfbba;
+               mfaba = m0;
+               mfbba = m1 -        m0 * vvx;
+               mfcba = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2          + mfbca;
+               mfaca = m0;
+               m0   += c1o3 * oMdrho;
+               mfbca = m1 -        m0 * vvx;
+               mfcca = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab + mfcab;
+               m1    = mfcab - mfaab;
+               m0    = m2          + mfbab;
+               mfaab = m0;
+               mfbab = m1 -        m0 * vvx;
+               mfcab = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2          + mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -        m0 * vvx;
+               mfcbb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2          + mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -        m0 * vvx;
+               mfccb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac + mfcac;
+               m1    = mfcac - mfaac;
+               m0    = m2          + mfbac;
+               mfaac = m0;
+               m0   += c1o3 * oMdrho;
+               mfbac = m1 -        m0 * vvx;
+               mfcac = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2          + mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -        m0 * vvx;
+               mfcbc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2          + mfbcc;
+               mfacc = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcc = m1 -        m0 * vvx;
+               mfccc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal OxxPyyPzz = 1.;
+               LBMReal OxyyPxzz  = 1.;//-s9;//2+s9;//
+               //LBMReal OxyyMxzz  = 1.;//2+s9;//
+               LBMReal O4        = 1.;
+               LBMReal O5        = 1.;
+               LBMReal O6        = 1.;
+
+               //Cum 4.
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //Cum 5.
+               LBMReal CUMbcc = mfbcc - (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) - c1o3 * (mfbca + mfbac) * oMdrho;
+               LBMReal CUMcbc = mfcbc - (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) - c1o3 * (mfcba + mfabc) * oMdrho;
+               LBMReal CUMccb = mfccb - (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) - c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc  +((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) +c1o27*oMdrho;
+
+               //2.
+               // linear combinations
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz         = mfcaa - mfaac;
+
+               LBMReal dxux = -c1o2 * collFactor *(mxxMyy + mxxMzz) + c1o2 * OxxPyyPzz*(mfaaa - mxxPyyPzz);
+               LBMReal dyuy = dxux + collFactor * c3o2 * mxxMyy;
+               LBMReal dzuz = dxux + collFactor * c3o2 * mxxMzz;
+
+               //relax
+               mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+               mxxMyy    += collFactor * (-mxxMyy) - 3. * (1. - c1o2 * collFactor) * (vx2 * dxux - vy2 * dyuy);
+               mxxMzz    += collFactor * (-mxxMzz) - 3. * (1. - c1o2 * collFactor) * (vx2 * dxux - vz2 * dzuz);
+
+               mfabb     += collFactor * (-mfabb);
+               mfbab     += collFactor * (-mfbab);
+               mfbba     += collFactor * (-mfbba);
+
+               // linear combinations back
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mfbbb)/(fabs(mfbbb)+qudricLimit);
+               mfbbb     += wadjust * (-mfbbb);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxyPyzz)/(fabs(mxxyPyzz)+qudricLimit);
+               mxxyPyzz  += wadjust * (-mxxyPyzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxyMyzz)/(fabs(mxxyMyzz)+qudricLimit);
+               mxxyMyzz  += wadjust * (-mxxyMyzz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxzPyyz)/(fabs(mxxzPyyz)+qudricLimit);
+               mxxzPyyz  += wadjust * (-mxxzPyyz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxzMyyz)/(fabs(mxxzMyyz)+qudricLimit);
+               mxxzMyyz  += wadjust * (-mxxzMyyz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxyyPxzz)/(fabs(mxyyPxzz)+qudricLimit);
+               mxyyPxzz  += wadjust * (-mxyyPxzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxyyMxzz)/(fabs(mxyyMxzz)+qudricLimit);
+               mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               //4.
+               CUMacc += O4 * (-CUMacc);
+               CUMcac += O4 * (-CUMcac);
+               CUMcca += O4 * (-CUMcca);
+
+               CUMbbc += O4 * (-CUMbbc);
+               CUMbcb += O4 * (-CUMbcb);
+               CUMcbb += O4 * (-CUMcbb);
+
+               //5.
+               CUMbcc += O5 * (-CUMbcc);
+               CUMcbc += O5 * (-CUMcbc);
+               CUMccb += O5 * (-CUMccb);
+
+               //6.
+               CUMccc += O6 * (-CUMccc);
+
+               //back cumulants to central moments
+               //4.
+               mfcbb = CUMcbb + ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               mfbcb = CUMbcb + ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               mfbbc = CUMbbc + ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac) * oMdrho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc) * oMdrho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) -c1o27*oMdrho;
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //forcing
+               mfbaa=-mfbaa;
+               mfaba=-mfaba;
+               mfaab=-mfaab;
+               //////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa                * (1. - vz2)              - 1. * oMdrho * vz2;
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2;
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2);
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2;
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2);
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2;
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2);
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2;
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2);
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2;
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2);
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca                  * (1. - vz2)              - c1o9 * oMdrho * vz2;
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab                  * (1. - vy2)              - c2o3 * oMdrho * vy2;
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2;
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2);
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2);
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2);
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab                  * (1. - vy2)              - c2o9 * oMdrho * vy2;
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb                  * (1. - vx2)              - c4o9 * oMdrho * vx2;
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho="+UbSystem::toString(rho)+", rho_post="+UbSystem::toString(rho_post)
+                     +" dif="+UbSystem::toString(dif)
+                     +" rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27CCLB::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3)    = mfabb;
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3)    = mfbab;
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3)    = mfbba;
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3)   = mfaab;
+               (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,  x3)   = mfcab;
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3)   = mfaba;
+               (*this->localDistributions)(D3Q27System::ET_TW,x1p,x2,  x3)   = mfcba;
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3)   = mfbaa;
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2p,x3)   = mfbca;
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3)  = mfaaa;
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,  x3)  = mfcaa;
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2p,x3)  = mfaca;
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3)  = mfcca;
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,  x3    ) = mfcbb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2p,x3    ) = mfbcb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3p  ) = mfbbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3   ) = mfccb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2p,x3   ) = mfacb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,  x3p ) = mfcbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3p ) = mfabc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2p,x3p ) = mfbcc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3p ) = mfbac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p) = mfccc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2p,x3p) = mfacc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,  x3p) = mfcac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3p) = mfaac;
+
+               (*this->zeroDistributions)(x1,x2,x3) = mfbbb;
+               //////////////////////////////////////////////////////////////////////////
+
+               collFactor = collFactor0;
+
+            }
+         }
+      }
+   }
+}
+
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBWithSpongeLayer.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBWithSpongeLayer.h
new file mode 100644
index 0000000000000000000000000000000000000000..77326dfd6b4db817750515d77e1f2e25261fef96
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBWithSpongeLayer.h
@@ -0,0 +1,57 @@
+#ifndef LBMKernelETD3Q27CCLBWithSpongeLayer_H
+#define LBMKernelETD3Q27CCLBWithSpongeLayer_H
+
+#include "LBMKernelETD3Q27CCLB.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+
+class LBMKernelETD3Q27CCLBWithSpongeLayer;
+typedef boost::shared_ptr<LBMKernelETD3Q27CCLBWithSpongeLayer> LBMKernelETD3Q27CCLBWithSpongeLayerPtr;
+
+//! \brief   Cascaded Cumulant LBM kernel. 
+//! \details CFD solver with sponge layer that use Cascaded Cumulant Lattice Boltzmann method for D3Q27 model <br>
+//! variable spongeFactor is depending on funktion in muSpongeLayer and varies between 1 (do nothing) und 0.5 (collFactor about 1);
+//! Initialization in test case (example): <br>
+//! \code{.cpp}
+//! int sizeSP=8; //width of sponge layer in blocks 
+//! mu::Parser spongeLayer;
+//! spongeLayer.SetExpr("x1>=(sizeX-sizeSP)/dt ? (sizeX-(x1+1))/sizeSP/2.0 + 0.5 : 1.0");
+//! spongeLayer.DefineConst("sizeX", nx[0]*blocknx[0]); // width of grid for X in coarse nodes
+//! spongeLayer.DefineConst("sizeSP", sizeSP*blocknx[0]); // width of sponge layer in coarse nodes
+//! kernel->setWithSpongeLayer(true);
+//! kernel->setSpongeLayer(spongeLayer);
+//! \endcode
+//! \author  K. Kucher, M. Geier
+class LBMKernelETD3Q27CCLBWithSpongeLayer :  public LBMKernelETD3Q27CCLB
+{
+public:
+   LBMKernelETD3Q27CCLBWithSpongeLayer();
+   //! Constructor
+   //! \param nx1 number of nodes in x dimension
+   //! \param nx2 number of nodes in y dimension
+   //! \param nx3 number of nodes in z dimension
+   //! \param p   set relaxation parameter: NORMAL is OxyyMxzz = 1.0 and MAGIC is OxyyMxzz = 2.0 +(-collFactor)
+   LBMKernelETD3Q27CCLBWithSpongeLayer(int nx1, int nx2, int nx3, Parameter p);
+   virtual ~LBMKernelETD3Q27CCLBWithSpongeLayer(void);
+   LBMKernel3DPtr clone();
+   void calculate();
+protected:
+   void init();
+   LBMReal OxyyMxzz;
+
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27CCLB>(*this);
+      ar & OxyyMxzz;
+   }
+
+   void collideAll();  
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB_Geier.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB_Geier.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3abf78790cb1747d94416e6b77e2470c7a3b4fe7
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB_Geier.cpp
@@ -0,0 +1,3378 @@
+#include "LBMKernelETD3Q27CCLB_Geier.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+#include <math.h>
+
+#define PROOF_CORRECTNESS
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLB_Geier::LBMKernelETD3Q27CCLB_Geier()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLB_Geier::LBMKernelETD3Q27CCLB_Geier(int nx1, int nx2, int nx3, int option) 
+   : LBMKernelETD3Q27(nx1, nx2, nx3),
+     option(option)
+{
+   this->compressible = false;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLB_Geier::~LBMKernelETD3Q27CCLB_Geier(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLB_Geier::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+2, nx2+2, nx3+2, -999.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27CCLB_Geier::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLB_Geier(nx1, nx2, nx3, option));
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLB_Geier>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   if (option == 0)
+   {
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLB_Geier>(kernel)->OxyyMxzz = 1.0;
+   }
+   else if (option == 1)
+   {
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLB_Geier>(kernel)->OxyyMxzz = 2.0 +(-collFactor);
+   }
+   
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLB_Geier::calculate()
+{
+   timer.resetAndStart();
+   collideAll2();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLB_Geier::collideAll()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dx",&muDeltaT);
+      muForcingX2.DefineVar("dx",&muDeltaT);
+      muForcingX3.DefineVar("dx",&muDeltaT);
+
+      muNue = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nue",&muNue);
+      muForcingX2.DefineVar("nue",&muNue);
+      muForcingX3.DefineVar("nue",&muNue);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   s9 = - collFactor;
+   c1o27=1.0/27.0;
+   c2o3=2.0/3.0;
+   w2=-1.0; //MXXpMYYpMZZ bulk viscosity
+   w7=-1.0;//s9; //ORDER 4 Isotropic
+   w9=-1.0;
+   w10=-1.0;//s9;//-1.0; // ORDER 6 Isotropic
+   w1=s9;
+   // wenn es mal an den Ecken nicht gut aussieht -2.0-s9 probieren
+   w3=-1.0;//-2.0-s9;//-1.0;//MXXYpMYZZ
+   w4=-1.0;//-2.0-s9;//-1.0;//MXXYmMYZZ
+   w5=-1.0;//-2.0-s9;//-1.0;//MYXZ
+   w6=-1.0; //MXXYYpm2p
+   w8=-1.0; //M_zXXYZ 
+
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////
+
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+               
+               //Rest ist b
+
+               LBMReal mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1); 
+               LBMReal mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+               LBMReal mfaac = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+               LBMReal mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+               LBMReal mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3  );
+               LBMReal mfabc = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3);
+               LBMReal mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+               LBMReal mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3  );
+               LBMReal mfbac = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3);
+               LBMReal mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1  );
+               LBMReal mfbbb = (*this->zeroDistributions)(x1,x2,x3);
+               LBMReal mfbbc = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               LBMReal mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+               LBMReal mfacb = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3);
+               LBMReal mfacc = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3);
+               LBMReal mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+               LBMReal mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 );
+               LBMReal mfcac = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3);
+               LBMReal mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1);
+               LBMReal mfccb = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               LBMReal mfccc = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               LBMReal mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 );
+               LBMReal mfbcb = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3); 
+               LBMReal mfbcc = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               LBMReal mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 );
+               LBMReal mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               LBMReal mfcbc = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               LBMReal m0, m1, m2;
+
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               mfaaa -=c1o216;
+               mfaab -=c1o54;
+               mfaac -=c1o216;
+               mfaba -=c1o54;
+               mfabb -=c2o27;
+               mfabc -=c1o54;
+               mfbaa -=c1o54;
+               mfbab -=c2o27;
+               mfbac -=c1o54;
+               mfbba -=c2o27;
+               mfbbb -=c8o27;
+               mfbbc -=c2o27;
+               mfaca -=c1o216;
+               mfacb -=c1o54;
+               mfacc -=c1o216;
+               mfcaa -=c1o216;
+               mfcab -=c1o54;
+               mfcac -=c1o216;
+               mfcca -=c1o216;
+               mfccb -=c1o54;
+               mfccc -=c1o216;
+               mfbca -=c1o54;
+               mfbcb -=c2o27;
+               mfbcc -=c1o54;
+               mfcba -=c1o54;
+               mfcbb -=c2o27;
+               mfcbc -=c1o54;
+
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb))/rho;
+
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab))/rho;
+
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba))/rho; 
+
+               LBMReal vx2=vvx*vvx;
+               LBMReal vy2=vvy*vvy;
+               LBMReal vz2=vvz*vvz;
+
+
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa	+ mfaac;
+               m1    = mfaac	- mfaaa;
+               m0    = m2		+ mfaab;
+               mfaaa = m0;
+               m0   += c1o36;	
+               mfaab = m1 -		m0 * vvz;
+               mfaac = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2		+ mfabb;
+               mfaba = m0;
+               m0   += c1o9;
+               mfabb = m1 -		m0 * vvz;
+               mfabc = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2		+ mfacb;
+               mfaca = m0;
+               m0   += c1o36;
+               mfacb = m1 -		m0 * vvz;
+               mfacc = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa	+ mfbac;
+               m1    = mfbac	- mfbaa;
+               m0    = m2		+ mfbab;
+               mfbaa = m0;
+               m0   += c1o9;
+               mfbab = m1 -		m0 * vvz;
+               mfbac = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2		+ mfbbb;
+               mfbba = m0;
+               m0   += c4o9;
+               mfbbb = m1 -		m0 * vvz;
+               mfbbc = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2		+ mfbcb;
+               mfbca = m0;
+               m0   += c1o9;
+               mfbcb = m1 -		m0 * vvz;
+               mfbcc = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa	+ mfcac;
+               m1    = mfcac	- mfcaa;
+               m0    = m2		+ mfcab;
+               mfcaa = m0;
+               m0   += c1o36;
+               mfcab = m1 -		m0 * vvz;
+               mfcac = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2		+ mfcbb;
+               mfcba = m0;
+               m0   += c1o9;
+               mfcbb = m1 -		m0 * vvz;
+               mfcbc = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2		+ mfccb;
+               mfcca = m0;
+               m0   += c1o36;
+               mfccb = m1 -		m0 * vvz;
+               mfccc = m2 - 2. *	m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa	+ mfaca;
+               m1    = mfaca	- mfaaa;
+               m0    = m2		+ mfaba;
+               mfaaa = m0;
+               m0   += c1o6;
+               mfaba = m1 -		m0 * vvy;
+               mfaca = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2		+ mfabb;
+               mfaab = m0;
+               mfabb = m1 -		m0 * vvy;
+               mfacb = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2		+ mfabc;
+               mfaac = m0;
+               m0   += c1o18;
+               mfabc = m1 -		m0 * vvy;
+               mfacc = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa	+ mfbca;
+               m1    = mfbca	- mfbaa;
+               m0    = m2		+ mfbba;
+               mfbaa = m0;
+               m0   += c2o3;
+               mfbba = m1 -		m0 * vvy;
+               mfbca = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2		+ mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -		m0 * vvy;
+               mfbcb = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2		+ mfbbc;
+               mfbac = m0;
+               m0   += c2o9;
+               mfbbc = m1 -		m0 * vvy;
+               mfbcc = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa	+ mfcca;
+               m1    = mfcca	- mfcaa;
+               m0    = m2		+ mfcba;
+               mfcaa = m0;
+               m0   += c1o6;
+               mfcba = m1 -		m0 * vvy;
+               mfcca = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2		+ mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -		m0 * vvy;
+               mfccb = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2		+ mfcbc;
+               mfcac = m0;
+               m0   += c1o18;
+               mfcbc = m1 -		m0 * vvy;
+               mfccc = m2 - 2. *	m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9		Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa	+ mfcaa;
+               m1    = mfcaa	- mfaaa;
+               m0    = m2		+ mfbaa;
+               mfaaa = m0;
+               m0   += 1.;
+               mfbaa = m1 -		m0 * vvx;
+               mfcaa = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2		+ mfbba;
+               mfaba = m0;
+               mfbba = m1 -		m0 * vvx;
+               mfcba = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2		+ mfbca;
+               mfaca = m0;
+               m0   += c1o3;
+               mfbca = m1 -		m0 * vvx;
+               mfcca = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab	+ mfcab;
+               m1    = mfcab	- mfaab;
+               m0    = m2		+ mfbab;
+               mfaab = m0;
+               mfbab = m1 -		m0 * vvx;
+               mfcab = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2		+ mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -		m0 * vvx;
+               mfcbb = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2		+ mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -		m0 * vvx;
+               mfccb = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac	+ mfcac;
+               m1    = mfcac	- mfaac;
+               m0    = m2		+ mfbac;
+               mfaac = m0;
+               m0   += c1o3;
+               mfbac = m1 -		m0 * vvx;
+               mfcac = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2		+ mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -		m0 * vvx;
+               mfcbc = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2		+ mfbcc;
+               mfacc = m0;
+               m0   += c1o9;
+               mfbcc = m1 -		m0 * vvx;
+               mfccc = m2 - 2. *	m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+
+
+               //////////////////////////////////////////////////////////////////////////////////////
+               //// BGK
+               //////////////////////////////////////////////////////////////////////////////////////
+               ////2.
+               //mfabb += -s9 * (-mfabb);
+               //mfbab += -s9 * (-mfbab);
+               //mfbba += -s9 * (-mfbba);
+               //
+               //mfcaa += -s9 * (c1o3 * mfaaa - mfcaa);
+               //mfaca += -s9 * (c1o3 * mfaaa - mfaca);
+               //mfaac += -s9 * (c1o3 * mfaaa - mfaac);
+               //
+               ////3.
+               //mfabc += -s9 * (-mfabc);
+               //mfbac += -s9 * (-mfbac);
+               //
+               //mfacb += -s9 * (-mfacb);
+               //mfbca += -s9 * (-mfbca);
+
+               //mfcab += -s9 * (-mfcab);
+               //mfcba += -s9 * (-mfcba);
+
+               //mfbbb += -s9 * (-mfbbb);
+
+               ////4.
+               //mfacc += -s9 * (c1o9 * mfaaa - mfacc);
+               //mfcac += -s9 * (c1o9 * mfaaa - mfcac);
+               //mfcca += -s9 * (c1o9 * mfaaa - mfcca);
+
+               //mfbbc += -s9 * (-mfbbc);
+               //mfbcb += -s9 * (-mfbcb);
+               //mfcbb += -s9 * (-mfcbb);
+
+               ////5.
+               //mfbcc += -s9 * (-mfbcc);
+               //mfcbc += -s9 * (-mfcbc);
+               //mfccb += -s9 * (-mfccb);
+
+               ////6.
+               //mfccc += -s9 * (c1o27 * mfaaa - mfccc);
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Central Moments Style
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Cum 4.
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * rho) * mfabb + 2. * mfbba * mfbab) / rho;
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * rho) * mfbab + 2. * mfbba * mfabb) / rho;
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * rho) * mfbba + 2. * mfbab * mfabb) / rho; 
+
+               LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) / rho - c1o3 * (mfcaa + mfaca);
+               LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) / rho - c1o3 * (mfcaa + mfaac);
+               LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) / rho - c1o3 * (mfaac + mfaca);
+
+               //Cum 5.
+               LBMReal CUMbcc = mfbcc - (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) / rho - c1o3 * (mfbca + mfbac);
+               LBMReal CUMcbc = mfcbc - (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) / rho - c1o3 * (mfcba + mfabc);
+               LBMReal CUMccb = mfccb - (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) / rho - c1o3 * (mfacb + mfcab);
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc +(-4. *  mfbbb * mfbbb  
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) / rho
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb) / (rho * rho)
+                  - c1o3* (mfacc + mfcac + mfcca)
+                  + c1o9* (mfcaa + mfaca + mfaac)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3 / rho;
+
+               //4.
+               CUMacc += 1.0 * (-CUMacc); 
+               CUMcac += 1.0 * (-CUMcac); 
+               CUMcca += 1.0 * (-CUMcca); 
+
+               CUMbbc += 1.0 * (-CUMbbc); 
+               CUMbcb += 1.0 * (-CUMbcb); 
+               CUMcbb += 1.0 * (-CUMcbb); 
+
+               //5.
+               CUMbcc += 1.0 * (-CUMbcc);
+               CUMcbc += 1.0 * (-CUMcbc);
+               CUMccb += 1.0 * (-CUMccb);
+
+               //6.
+               CUMccc += 1.0 * (-CUMccc);
+
+     
+               //
+               //mfabb += -s9 * (-mfabb);
+               //mfbab += -s9 * (-mfbab);
+               //mfbba += -s9 * (-mfbba);
+               //
+               //mfcaa += -s9 * (c1o3 * mfaaa - mfcaa);
+               //mfaca += -s9 * (c1o3 * mfaaa - mfaca);
+               //mfaac += -s9 * (c1o3 * mfaaa - mfaac);
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz	   = mfcaa - mfaac;
+
+               //relax
+               mxxPyyPzz += 1.0*(mfaaa-mxxPyyPzz);
+               mxxMyy    += -s9 * (-mxxMyy);
+               mxxMzz    += -s9 * (-mxxMzz);
+               mfabb     += -s9 * (-mfabb);
+               mfbab     += -s9 * (-mfbab);
+               mfbba     += -s9 * (-mfbba);
+
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+
+               //3.
+               //mfabc += 1.0 * (-mfabc);
+               //mfbac += 1.0 * (-mfbac);
+               //
+               //mfacb += 1.0 * (-mfacb);
+               //mfbca += 1.0 * (-mfbca);
+
+               //mfcab += 1.0 * (-mfcab);
+               //mfcba += 1.0 * (-mfcba);
+
+               //mfbbb += 1.0 * (-mfbbb);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+
+
+               mfbbb     +=  1.0* (-mfbbb);
+               mxxyPyzz  +=  1.0 * (-mxxyPyzz);
+               mxxyMyzz  += 1.0 * (-mxxyMyzz);
+               mxxzPyyz  += 1.0 * (-mxxzPyyz);
+               mxxzMyyz  += 1.0 * (-mxxzMyyz);
+               mxyyPxzz  += 1.0 * (-mxyyPxzz);
+               mxyyMxzz  += 1.0 * (-mxyyMxzz);
+ 
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+               //4.
+               mfacc += 1.0 * (c1o9 * mfaaa - mfacc);
+               mfcac += 1.0 * (c1o9 * mfaaa - mfcac);
+               mfcca += 1.0 * (c1o9 * mfaaa - mfcca);
+
+               mfbbc += 1.0 * (-mfbbc);
+               mfbcb += 1.0 * (-mfbcb);
+               mfcbb += 1.0 * (-mfcbb);
+
+               //5.
+               mfbcc += 1.0 * (-mfbcc);
+               mfcbc += 1.0 * (-mfcbc);
+               mfccb += 1.0 * (-mfccb);
+
+               ////6.
+               mfccc += 1.0 * (c1o27 * mfaaa - mfccc);
+ 
+               //back cumulants to central moments
+               //4.
+               mfcbb = CUMcbb + ((mfcaa + c1o3 ) * mfabb + 2. * mfbba * mfbab) / rho;
+               mfbcb = CUMbcb + ((mfaca + c1o3 ) * mfbab + 2. * mfbba * mfabb) / rho;
+               mfbbc = CUMbbc + ((mfaac + c1o3 ) * mfbba + 2. * mfbab * mfabb) / rho; 
+
+               //here is problem
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) / rho + c1o3 * (mfcaa + mfaca)/rho-(1.0-1.0/rho)*c1o9;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) / rho + c1o3 * (mfcaa + mfaac)/rho-(1.0-1.0/rho)*c1o9;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) / rho + c1o3 * (mfaac + mfaca)/rho-(1.0-1.0/rho)*c1o9;
+
+               ////5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) / rho + c1o3 * (mfbca + mfbac)/rho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) / rho + c1o3 * (mfcba + mfabc)/rho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) / rho + c1o3 * (mfacb + mfcab)/rho;
+
+               ////6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb  
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) / rho
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb) / (rho * rho)
+                  - c1o3* (mfacc + mfcac + mfcca)/rho
+                  - c1o9* (mfcaa + mfaca + mfaac)/rho
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3 / rho) -(1.0-1.0/rho)*c1o27;
+               //////////////////////////////////////////////////////////////////////////////////////
+
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               //////////////////////////////////////////////////////////////////////////////////////
+               //LBMReal OxxPyyPzz = 1.;
+               //LBMReal OxyyPxzz  = 1.0;
+               //LBMReal OxyyMxzz  = 1.0;
+               //LBMReal O4        = 1.;
+               //LBMReal O5        = 1.;
+               //LBMReal O6        = 1.;
+
+               ////LBMReal OxxPyyPzz = -s9;
+               ////LBMReal OxyyPxzz  = -s9;
+               ////LBMReal OxyyMxzz  = -s9;
+               ////LBMReal O4        = -s9;
+               ////LBMReal O5        = -s9;
+               ////LBMReal O6        = -s9;
+
+
+               ////Cum 4.
+               //LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * rho) * mfabb + 2. * mfbba * mfbab) / rho;
+               //LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * rho) * mfbab + 2. * mfbba * mfabb) / rho;
+               //LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * rho) * mfbba + 2. * mfbab * mfabb) / rho; 
+
+               //LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) / rho - c1o3 * (mfcaa + mfaca);
+               //LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) / rho - c1o3 * (mfcaa + mfaac);
+               //LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) / rho - c1o3 * (mfaac + mfaca);
+
+               ////Cum 5.
+               //LBMReal CUMbcc = mfbcc - (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) / rho - c1o3 * (mfbca + mfbac);
+               //LBMReal CUMcbc = mfcbc - (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) / rho - c1o3 * (mfcba + mfabc);
+               //LBMReal CUMccb = mfccb - (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) / rho - c1o3 * (mfacb + mfcab);
+
+               ////Cum 6.
+               //LBMReal CUMccc = mfccc +(-4. *  mfbbb * mfbbb  
+               //   -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+               //   -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+               //   -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) / rho
+               //   +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+               //   +  2. * (mfcaa * mfaca * mfaac)
+               //   + 16. *  mfbba * mfbab * mfabb) / (rho * rho)
+               //   - c1o3* (mfacc + mfcac + mfcca)
+               //   + c1o9* (mfcaa + mfaca + mfaac)
+               //   +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+               //   +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3 / rho;
+
+               //////////
+               ////2.
+
+               //// linear combinations
+               ////LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               ////LBMReal mxxMyy    = mfcaa - mfaca;
+               ////LBMReal mxxMzz    = mfcaa - mfaac;
+               ////{
+               ////   LBMReal dxux = c1o2 * (s9 *(mxxMyy + mxxMzz) + (mfaaa - mxxPyyPzz));
+               ////   LBMReal dyuy = dxux - s9 * c3o2 * mxxMyy;
+               ////   LBMReal dzuz = dxux - s9 * c3o2 * mxxMzz;
+               ////   //relax
+               ////   mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+               ////   mxxMyy    += -s9 * (-mxxMyy) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vy2 * dyuy);
+               ////   mxxMzz    += -s9 * (-mxxMzz) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vz2 * dzuz);
+               ////}
+               ////mfabb     += -s9 * (-mfabb);
+               ////mfbab     += -s9 * (-mfbab);
+               ////mfbba     += -s9 * (-mfbba);
+               ////// linear combinations back
+               ////mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               ////mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               ////mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+               ////////////
+
+               //////// simple 2nd moments without high order Galilean invariance
+               ////2.
+               //// linear combinations
+               //LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               //LBMReal mxxMyy    = mfcaa - mfaca;
+               //LBMReal mxxMzz	   = mfcaa - mfaac;
+
+               ////relax
+               //mxxPyyPzz += OxxPyyPzz*(mfaaa-mxxPyyPzz);
+               //mxxMyy    += -s9 * (-mxxMyy);
+               //mxxMzz    += -s9 * (-mxxMzz);
+               //mfabb     += -s9 * (-mfabb);
+               //mfbab     += -s9 * (-mfbab);
+               //mfbba     += -s9 * (-mfbba);
+
+               //// linear combinations back
+               //mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               //mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               //mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               ////3.
+               //// linear combinations
+               //LBMReal mxxyPyzz = mfcba + mfabc;
+               //LBMReal mxxyMyzz = mfcba - mfabc;
+
+               //LBMReal mxxzPyyz = mfcab + mfacb;
+               //LBMReal mxxzMyyz = mfcab - mfacb;
+
+               //LBMReal mxyyPxzz = mfbca + mfbac;
+               //LBMReal mxyyMxzz = mfbca - mfbac;
+
+               ////relax
+
+
+               //mfbbb     +=  OxyyMxzz* (-mfbbb);
+               //mxxyPyzz  +=  OxyyPxzz * (-mxxyPyzz);
+               //mxxyMyzz  += OxyyMxzz * (-mxxyMyzz);
+               //mxxzPyyz  += OxyyPxzz * (-mxxzPyyz);
+               //mxxzMyyz  += OxyyMxzz * (-mxxzMyyz);
+               //mxyyPxzz  += OxyyPxzz * (-mxyyPxzz);
+               //mxyyMxzz  += OxyyMxzz * (-mxyyMxzz);
+               ////wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mfbbb)/(abs(mfbbb)+qudricLimit);
+               ////mfbbb     += wadjust * (-mfbbb);
+               ////wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxxyPyzz)/(abs(mxxyPyzz)+qudricLimit);
+               ////mxxyPyzz  += wadjust * (-mxxyPyzz);
+               ////wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxxyMyzz)/(abs(mxxyMyzz)+qudricLimit);
+               ////mxxyMyzz  += wadjust * (-mxxyMyzz);
+               ////wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxxzPyyz)/(abs(mxxzPyyz)+qudricLimit);
+               ////mxxzPyyz  += wadjust * (-mxxzPyyz);
+               ////wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxxzMyyz)/(abs(mxxzMyyz)+qudricLimit);
+               ////mxxzMyyz  += wadjust * (-mxxzMyyz);
+               ////wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxyyPxzz)/(abs(mxyyPxzz)+qudricLimit);
+               ////mxyyPxzz  += wadjust * (-mxyyPxzz);
+               ////wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxyyMxzz)/(abs(mxyyMxzz)+qudricLimit);
+               ////mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               //// linear combinations back
+               //mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               //mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               //mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               //mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               //mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               //mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               ////4.
+               //CUMacc += O4 * (-CUMacc); 
+               //CUMcac += O4 * (-CUMcac); 
+               //CUMcca += O4 * (-CUMcca); 
+
+               //CUMbbc += O4 * (-CUMbbc); 
+               //CUMbcb += O4 * (-CUMbcb); 
+               //CUMcbb += O4 * (-CUMcbb); 
+
+               ////5.
+               //CUMbcc += O5 * (-CUMbcc);
+               //CUMcbc += O5 * (-CUMcbc);
+               //CUMccb += O5 * (-CUMccb);
+
+               ////6.
+               //CUMccc += O6 * (-CUMccc);
+
+               ////back cumulants to central moments
+               ////4.
+               //mfcbb = CUMcbb + ((mfcaa + c1o3 * rho) * mfabb + 2. * mfbba * mfbab) / rho;
+               //mfbcb = CUMbcb + ((mfaca + c1o3 * rho) * mfbab + 2. * mfbba * mfabb) / rho;
+               //mfbbc = CUMbbc + ((mfaac + c1o3 * rho) * mfbba + 2. * mfbab * mfabb) / rho; 
+
+               //mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) / rho + c1o3 * (mfcaa + mfaca);
+               //mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) / rho + c1o3 * (mfcaa + mfaac);
+               //mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) / rho + c1o3 * (mfaac + mfaca);
+
+               ////5.
+               //mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) / rho + c1o3 * (mfbca + mfbac);
+               //mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) / rho + c1o3 * (mfcba + mfabc);
+               //mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) / rho + c1o3 * (mfacb + mfcab);
+
+               ////6.
+               //mfccc = CUMccc  -((-4. *  mfbbb * mfbbb  
+               //   -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+               //   -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+               //   -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) / rho
+               //   +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+               //   +  2. * (mfcaa * mfaca * mfaac)
+               //   + 16. *  mfbba * mfbab * mfabb) / (rho * rho)
+               //   - c1o3* (mfacc + mfcac + mfcca)
+               //   + c1o9* (mfcaa + mfaca + mfaac)
+               //   +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+               //   +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3 / rho);
+               //////////////////////////////////////////////////////////////////////////////////////
+
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1.) * (     vz2 - vvz) * c1o2; 
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa       * (1. - vz2)              - 1. * vz2; 
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1.) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2; 
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2); 
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3) * (     vz2 - vvz) * c1o2; 
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca         * (1. - vz2)              - c1o3 * vz2; 
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2; 
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2); 
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2; 
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2); 
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2; 
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2); 
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3) * (     vz2 - vvz) * c1o2; 
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa         * (1. - vz2)              - c1o3 * vz2; 
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2; 
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2); 
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9) * (     vz2 - vvz) * c1o2; 
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca         * (1. - vz2)              - c1o9 * vz2; 
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6) * (     vy2 - vvy) * c1o2; 
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa         * (1. - vy2)              - c1o6 * vy2; 
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3) * (     vy2 - vvy) * c1o2; 
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab         * (1. - vy2)              - c2o3 * vy2; 
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6) * (     vy2 - vvy) * c1o2; 
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac         * (1. - vy2)              - c1o6 * vy2; 
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2; 
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2); 
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2; 
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2); 
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2; 
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2); 
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18) * (     vy2 - vvy) * c1o2; 
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa          * (1. - vy2)              - c1o18 * vy2; 
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9) * (     vy2 - vvy) * c1o2; 
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab         * (1. - vy2)              - c2o9 * vy2; 
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18) * (     vy2 - vvy) * c1o2; 
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac          * (1. - vy2)              - c1o18 * vy2; 
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa          * (1. - vx2)              - c1o36 * vx2; 
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba         * (1. - vx2)              - c1o9 * vx2; 
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca          * (1. - vx2)              - c1o36 * vx2; 
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab         * (1. - vx2)              - c1o9 * vx2; 
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb         * (1. - vx2)              - c4o9 * vx2; 
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb         * (1. - vx2)              - c1o9 * vx2; 
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac          * (1. - vx2)              - c1o36 * vx2; 
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc         * (1. - vx2)              - c1o9 * vx2; 
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36) * (     vx2 - vvx) * c1o2; 
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc          * (1. - vx2)              - c1o36 * vx2; 
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               mfaaa +=c1o216;
+               mfaab +=c1o54;
+               mfaac +=c1o216;
+               mfaba +=c1o54;
+               mfabb +=c2o27;
+               mfabc +=c1o54;
+               mfbaa +=c1o54;
+               mfbab +=c2o27;
+               mfbac +=c1o54;
+               mfbba +=c2o27;
+               mfbbb +=c8o27;
+               mfbbc +=c2o27;
+               mfaca +=c1o216;
+               mfacb +=c1o54;
+               mfacc +=c1o216;
+               mfcaa +=c1o216;
+               mfcab +=c1o54;
+               mfcac +=c1o216;
+               mfcca +=c1o216;
+               mfccb +=c1o54;
+               mfccc +=c1o216;
+               mfbca +=c1o54;
+               mfbcb +=c2o27;
+               mfbcc +=c1o54;
+               mfcba +=c1o54;
+               mfcbb +=c2o27;
+               mfcbc +=c1o54;
+          
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                     +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                     +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27CCLB::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3)    = mfabb;
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3)    = mfbab;
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3)    = mfbba;
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3)   = mfaab;
+               (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3)   = mfcab;
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3)   = mfaba;
+               (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3)   = mfcba;
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3)   = mfbaa;
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3)   = mfbca;
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3)  = mfaaa;
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3)  = mfcaa;
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3)  = mfaca;
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3)  = mfcca;
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = mfcbb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = mfbcb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = mfbbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = mfccb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = mfacb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = mfcbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = mfabc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = mfbcc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = mfbac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = mfccc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = mfacc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = mfcac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = mfaac;
+
+               (*this->zeroDistributions)(x1,x2,x3) = mfbbb;
+               //////////////////////////////////////////////////////////////////////////
+
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLB_Geier::collideAll2()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dx",&muDeltaT);
+      muForcingX2.DefineVar("dx",&muDeltaT);
+      muForcingX3.DefineVar("dx",&muDeltaT);
+
+      muNue = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nue",&muNue);
+      muForcingX2.DefineVar("nue",&muNue);
+      muForcingX3.DefineVar("nue",&muNue);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   s9 = - collFactor;
+   c1o27=1.0/27.0;
+   c2o3=2.0/3.0;
+   w2=-1.0; //MXXpMYYpMZZ bulk viscosity
+   w7=-1.0;//s9; //ORDER 4 Isotropic
+   w9=-1.0;
+   w10=-1.0;//s9;//-1.0; // ORDER 6 Isotropic
+   w1=s9;
+   // wenn es mal an den Ecken nicht gut aussieht -2.0-s9 probieren
+   w3=-1.0;//-2.0-s9;//-1.0;//MXXYpMYZZ
+   w4=-1.0;//-2.0-s9;//-1.0;//MXXYmMYZZ
+   w5=-1.0;//-2.0-s9;//-1.0;//MYXZ
+   w6=-1.0; //MXXYYpm2p
+   w8=-1.0; //M_zXXYZ 
+
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////
+
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+
+               //Rest ist b
+
+               LBMReal mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1); 
+               LBMReal mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+               LBMReal mfaac = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+               LBMReal mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+               LBMReal mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3  );
+               LBMReal mfabc = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3);
+               LBMReal mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+               LBMReal mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3  );
+               LBMReal mfbac = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3);
+               LBMReal mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1  );
+               LBMReal mfbbb = (*this->zeroDistributions)(x1,x2,x3);
+               LBMReal mfbbc = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               LBMReal mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+               LBMReal mfacb = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3);
+               LBMReal mfacc = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3);
+               LBMReal mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+               LBMReal mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 );
+               LBMReal mfcac = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3);
+               LBMReal mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1);
+               LBMReal mfccb = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               LBMReal mfccc = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               LBMReal mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 );
+               LBMReal mfbcb = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3); 
+               LBMReal mfbcc = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               LBMReal mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 );
+               LBMReal mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               LBMReal mfcbc = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               LBMReal m0, m1, m2;
+
+
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               //mfaaa -=c1o216;
+               //mfaab -=c1o54;
+               //mfaac -=c1o216;
+               //mfaba -=c1o54;
+               //mfabb -=c2o27;
+               //mfabc -=c1o54;
+               //mfbaa -=c1o54;
+               //mfbab -=c2o27;
+               //mfbac -=c1o54;
+               //mfbba -=c2o27;
+               //mfbbb -=c8o27;
+               //mfbbc -=c2o27;
+               //mfaca -=c1o216;
+               //mfacb -=c1o54;
+               //mfacc -=c1o216;
+               //mfcaa -=c1o216;
+               //mfcab -=c1o54;
+               //mfcac -=c1o216;
+               //mfcca -=c1o216;
+               //mfccb -=c1o54;
+               //mfccc -=c1o216;
+               //mfbca -=c1o54;
+               //mfbcb -=c2o27;
+               //mfbcc -=c1o54;
+               //mfcba -=c1o54;
+               //mfcbb -=c2o27;
+               //mfcbc -=c1o54;
+               
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb));
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab));
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba));
+
+               //forcing 
+               ///////////////////////////////////////////////////////////////////////////////////////////
+               if (withForcing)
+               {
+                  muX1 = static_cast<double>(x1+ix1*bcArrayMaxX1);
+                  muX2 = static_cast<double>(x2+ix2*bcArrayMaxX2);
+                  muX3 = static_cast<double>(x3+ix3*bcArrayMaxX3);
+
+                  forcingX1 = muForcingX1.Eval();
+                  forcingX2 = muForcingX2.Eval();
+                  forcingX3 = muForcingX3.Eval();
+
+                  vvx += forcingX1*0.5; // X
+                  vvy += forcingX2*0.5; // Y
+                  vvz += forcingX3*0.5; // Z
+               }
+               ///////////////////////////////////////////////////////////////////////////////////////////               
+               
+               ////////////////////////////////////////////////////////////////////////////////////
+               //fast
+               //LBMReal oMdrho = 1. - (mfccc+mfaaa + mfaca+mfcac + mfacc+mfcaa + mfaac+mfcca +
+               //                                   mfbac+mfbca + mfbaa+mfbcc + mfabc+mfcba + mfaba+mfcbc + mfacb+mfcab + mfaab+mfccb +
+               //                                   mfabb+mfcbb + mfbab+mfbcb  +  mfbba+mfbbc);//fehlt mfbbb
+               //LBMReal vvx    =mfccc-mfaaa + mfcac-mfaca + mfcaa-mfacc + mfcca-mfaac +
+               //                         mfcba-mfabc + mfcbc-mfaba + mfcab-mfacb + mfccb-mfaab +
+               //                         mfcbb-mfabb;
+               //LBMReal vvy    =mfccc-mfaaa + mfaca-mfcac + mfacc-mfcaa + mfcca-mfaac +
+               //                         mfbca-mfbac + mfbcc-mfbaa + mfacb-mfcab + mfccb-mfaab +
+               //                         mfbcb-mfbab;
+               //LBMReal vvz    =mfccc-mfaaa + mfcac-mfaca + mfacc-mfcaa + mfaac-mfcca +
+               //                         mfbac-mfbca + mfbcc-mfbaa + mfabc-mfcba + mfcbc-mfaba +
+               //                         mfbbc-mfbba;
+               ////////////////////////////////////////////////////////////////////////////////////
+               // oMdrho assembler style -------> faaaaaastaaaa
+               //LBMReal m0, m1, m2;
+               LBMReal oMdrho;
+               {
+                  oMdrho=mfccc+mfaaa;
+                  m0=mfaca+mfcac;
+                  m1=mfacc+mfcaa;
+                  m2=mfaac+mfcca;
+                  oMdrho+=m0;
+                  m1+=m2;
+                  oMdrho+=m1;
+                  m0=mfbac+mfbca;
+                  m1=mfbaa+mfbcc;
+                  m0+=m1;
+                  m1=mfabc+mfcba;
+                  m2=mfaba+mfcbc;
+                  m1+=m2;
+                  m0+=m1;
+                  m1=mfacb+mfcab;
+                  m2=mfaab+mfccb;
+                  m1+=m2;
+                  m0+=m1;
+                  oMdrho+=m0;
+                  m0=mfabb+mfcbb;
+                  m1=mfbab+mfbcb;
+                  m2=mfbba+mfbbc;
+                  m0+=m1+m2;
+                  m0+=mfbbb; //hat gefehlt
+                  oMdrho = 1. - (oMdrho + m0);
+               }
+               //LBMReal vvx;
+               LBMReal vx2;
+               //{
+               //     vvx = mfccc-mfaaa;
+               //     m0  = mfcac-mfaca;
+               //     m1  = mfcaa-mfacc;
+               //     m2  = mfcca-mfaac;
+               //     vvx+= m0;
+               //     m1 += m2;
+               //     vvx+= m1;
+               //     vx2 = mfcba-mfabc;
+               //     m0  = mfcbc-mfaba;
+               //     m1  = mfcab-mfacb;
+               //     m2  = mfccb-mfaab;
+               //     vx2+= m0;
+               //     m1 += m2;
+               //     vx2+= m1;
+               //     vvx+= vx2;
+               //     vx2 = mfcbb-mfabb;
+               //     vvx+= vx2;
+               //}
+               //LBMReal vvy;
+               LBMReal vy2;
+               //{
+               //     vvy = mfccc-mfaaa;
+               //     m0  = mfaca-mfcac;
+               //     m1  = mfacc-mfcaa;
+               //     m2  = mfcca-mfaac;
+               //     vvy+= m0;
+               //     m1 += m2;
+               //     vvy+= m1;
+               //     vy2 = mfbca-mfbac;
+               //     m0  = mfbcc-mfbaa;
+               //     m1  = mfacb-mfcab;
+               //     m2  = mfccb-mfaab;
+               //     vy2+= m0;
+               //     m1 += m2;
+               //     vy2+= m1;
+               //     vvy+= vy2;
+               //     vy2 = mfbcb-mfbab;
+               //     vvy+= vy2;
+               //}
+               //LBMReal vvz;
+               LBMReal vz2;
+               //{
+               //     vvz = mfccc-mfaaa;
+               //     m0  = mfcac-mfaca;
+               //     m1  = mfacc-mfcaa;
+               //     m2  = mfaac-mfcca;
+               //     vvz+= m0;
+               //     m1 += m2;
+               //     vvz+= m1;
+               //     vz2 = mfbac-mfbca;
+               //     m0  = mfbcc-mfbaa;
+               //     m1  = mfabc-mfcba;
+               //     m2  = mfcbc-mfaba;
+               //     vz2+= m0;
+               //     m1 += m2;
+               //     vz2+= m1;
+               //     vvz+= vz2;
+               //     vz2 = mfbbc-mfbba;
+               //     vvz+= vz2;
+               //}
+               vx2=vvx*vvx;
+               vy2=vvy*vvy;
+               vz2=vvz*vvz;
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal wadjust;
+               LBMReal qudricLimit = 0.01;
+               //LBMReal s9 = minusomega;
+               //test
+               //s9 = 0.;
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa + mfaac;
+               m1    = mfaac - mfaaa;
+               m0    = m2          + mfaab;
+               mfaaa = m0;
+               m0   += c1o36 * oMdrho;   
+               mfaab = m1 -        m0 * vvz;
+               mfaac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2          + mfabb;
+               mfaba = m0;
+               m0   += c1o9 * oMdrho;
+               mfabb = m1 -        m0 * vvz;
+               mfabc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2          + mfacb;
+               mfaca = m0;
+               m0   += c1o36 * oMdrho;
+               mfacb = m1 -        m0 * vvz;
+               mfacc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbac;
+               m1    = mfbac - mfbaa;
+               m0    = m2          + mfbab;
+               mfbaa = m0;
+               m0   += c1o9 * oMdrho;
+               mfbab = m1 -        m0 * vvz;
+               mfbac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2          + mfbbb;
+               mfbba = m0;
+               m0   += c4o9 * oMdrho;
+               mfbbb = m1 -        m0 * vvz;
+               mfbbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2          + mfbcb;
+               mfbca = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcb = m1 -        m0 * vvz;
+               mfbcc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcac;
+               m1    = mfcac - mfcaa;
+               m0    = m2          + mfcab;
+               mfcaa = m0;
+               m0   += c1o36 * oMdrho;
+               mfcab = m1 -        m0 * vvz;
+               mfcac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2          + mfcbb;
+               mfcba = m0;
+               m0   += c1o9 * oMdrho;
+               mfcbb = m1 -        m0 * vvz;
+               mfcbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2          + mfccb;
+               mfcca = m0;
+               m0   += c1o36 * oMdrho;
+               mfccb = m1 -        m0 * vvz;
+               mfccc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa + mfaca;
+               m1    = mfaca - mfaaa;
+               m0    = m2          + mfaba;
+               mfaaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfaba = m1 -        m0 * vvy;
+               mfaca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2          + mfabb;
+               mfaab = m0;
+               mfabb = m1 -        m0 * vvy;
+               mfacb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2          + mfabc;
+               mfaac = m0;
+               m0   += c1o18 * oMdrho;
+               mfabc = m1 -        m0 * vvy;
+               mfacc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbca;
+               m1    = mfbca - mfbaa;
+               m0    = m2          + mfbba;
+               mfbaa = m0;
+               m0   += c2o3 * oMdrho;
+               mfbba = m1 -        m0 * vvy;
+               mfbca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2          + mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -        m0 * vvy;
+               mfbcb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2          + mfbbc;
+               mfbac = m0;
+               m0   += c2o9 * oMdrho;
+               mfbbc = m1 -        m0 * vvy;
+               mfbcc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcca;
+               m1    = mfcca - mfcaa;
+               m0    = m2          + mfcba;
+               mfcaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfcba = m1 -        m0 * vvy;
+               mfcca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2          + mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -        m0 * vvy;
+               mfccb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2          + mfcbc;
+               mfcac = m0;
+               m0   += c1o18 * oMdrho;
+               mfcbc = m1 -        m0 * vvy;
+               mfccc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9            Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa + mfcaa;
+               m1    = mfcaa - mfaaa;
+               m0    = m2          + mfbaa;
+               mfaaa = m0;
+               m0   += 1. * oMdrho;
+               mfbaa = m1 -        m0 * vvx;
+               mfcaa = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2          + mfbba;
+               mfaba = m0;
+               mfbba = m1 -        m0 * vvx;
+               mfcba = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2          + mfbca;
+               mfaca = m0;
+               m0   += c1o3 * oMdrho;
+               mfbca = m1 -        m0 * vvx;
+               mfcca = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab + mfcab;
+               m1    = mfcab - mfaab;
+               m0    = m2          + mfbab;
+               mfaab = m0;
+               mfbab = m1 -        m0 * vvx;
+               mfcab = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2          + mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -        m0 * vvx;
+               mfcbb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2          + mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -        m0 * vvx;
+               mfccb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac + mfcac;
+               m1    = mfcac - mfaac;
+               m0    = m2          + mfbac;
+               mfaac = m0;
+               m0   += c1o3 * oMdrho;
+               mfbac = m1 -        m0 * vvx;
+               mfcac = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2          + mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -        m0 * vvx;
+               mfcbc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2          + mfbcc;
+               mfacc = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcc = m1 -        m0 * vvx;
+               mfccc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////////////////
+               //// BGK
+               //////////////////////////////////////////////////////////////////////////////////////
+               ////2.
+               //mfabb += -s9 * (-mfabb);
+               //mfbab += -s9 * (-mfbab);
+               //mfbba += -s9 * (-mfbba);
+               //
+               //mfcaa += -s9 * (c1o3 * mfaaa - mfcaa);
+               //mfaca += -s9 * (c1o3 * mfaaa - mfaca);
+               //mfaac += -s9 * (c1o3 * mfaaa - mfaac);
+               //
+               ////3.
+               //mfabc += -s9 * (-mfabc);
+               //mfbac += -s9 * (-mfbac);
+               //
+               //mfacb += -s9 * (-mfacb);
+               //mfbca += -s9 * (-mfbca);
+               //mfcab += -s9 * (-mfcab);
+               //mfcba += -s9 * (-mfcba);
+               //mfbbb += -s9 * (-mfbbb);
+               ////4.
+               //mfacc += -s9 * (c1o9 * mfaaa - mfacc);
+               //mfcac += -s9 * (c1o9 * mfaaa - mfcac);
+               //mfcca += -s9 * (c1o9 * mfaaa - mfcca);
+               //mfbbc += -s9 * (-mfbbc);
+               //mfbcb += -s9 * (-mfbcb);
+               //mfcbb += -s9 * (-mfcbb);
+               ////5.
+               //mfbcc += -s9 * (-mfbcc);
+               //mfcbc += -s9 * (-mfcbc);
+               //mfccb += -s9 * (-mfccb);
+               ////6.
+               //mfccc += -s9 * (c1o27 * mfaaa - mfccc);
+               //////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal OxxPyyPzz = 1.;
+               LBMReal OxyyPxzz  = 1.;//-s9;//2+s9;//
+               //LBMReal OxyyMxzz  = 1.;//2+s9;//
+               LBMReal O4        = 1.;
+               LBMReal O5        = 1.;
+               LBMReal O6        = 1.;
+
+               //Cum 4.
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //Cum 5.
+               LBMReal CUMbcc = (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) - c1o3 * (mfbca + mfbac) * oMdrho;
+               LBMReal CUMcbc = (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) - c1o3 * (mfcba + mfabc) * oMdrho;
+               LBMReal CUMccb = (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) - c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc  +((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) +c1o27*oMdrho;
+
+               //2.
+               // linear combinations
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz         = mfcaa - mfaac;
+
+               {
+                  LBMReal dxux = c1o2 * (s9 *(mxxMyy + mxxMzz) + (mfaaa - mxxPyyPzz));
+                  LBMReal dyuy = dxux - s9 * c3o2 * mxxMyy;
+                  LBMReal dzuz = dxux - s9 * c3o2 * mxxMzz;
+
+                  //relax
+                  mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+                  mxxMyy    += -s9 * (-mxxMyy) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vy2 * dyuy);
+                  mxxMzz    += -s9 * (-mxxMzz) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vz2 * dzuz);
+               }
+               mfabb     += -s9 * (-mfabb);
+               mfbab     += -s9 * (-mfbab);
+               mfbba     += -s9 * (-mfbba);
+
+               // linear combinations back
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mfbbb)/(fabs(mfbbb)+qudricLimit);
+               mfbbb     += wadjust * (-mfbbb);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxyPyzz)/(fabs(mxxyPyzz)+qudricLimit);
+               mxxyPyzz  += wadjust * (-mxxyPyzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxyMyzz)/(fabs(mxxyMyzz)+qudricLimit);
+               mxxyMyzz  += wadjust * (-mxxyMyzz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxzPyyz)/(fabs(mxxzPyyz)+qudricLimit);
+               mxxzPyyz  += wadjust * (-mxxzPyyz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxzMyyz)/(fabs(mxxzMyyz)+qudricLimit);
+               mxxzMyyz  += wadjust * (-mxxzMyyz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxyyPxzz)/(fabs(mxyyPxzz)+qudricLimit);
+               mxyyPxzz  += wadjust * (-mxyyPxzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxyyMxzz)/(fabs(mxyyMxzz)+qudricLimit);
+               mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               //4.
+               CUMacc += O4 * (-CUMacc);
+               CUMcac += O4 * (-CUMcac);
+               CUMcca += O4 * (-CUMcca);
+
+               CUMbbc += O4 * (-CUMbbc);
+               CUMbcb += O4 * (-CUMbcb);
+               CUMcbb += O4 * (-CUMcbb);
+
+               //5.
+               CUMbcc += O5 * (-CUMbcc);
+               CUMcbc += O5 * (-CUMcbc);
+               CUMccb += O5 * (-CUMccb);
+
+               //6.
+               CUMccc += O6 * (-CUMccc);
+
+               //back cumulants to central moments
+               //4.
+               mfcbb = CUMcbb + ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               mfbcb = CUMbcb + ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               mfbbc = CUMbbc + ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac) * oMdrho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc) * oMdrho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) -c1o27*oMdrho;
+               
+               ////////////////////////////////////////////////////////////////////////////////////
+               //forcing
+               mfbaa=-mfbaa;
+               mfaba=-mfaba;
+               mfaab=-mfaab;
+               //////////////////////////////////////////////////////////////////////////////////////
+               //// Cumulants
+               //////////////////////////////////////////////////////////////////////////////////////
+               //LBMReal OxxPyyPzz = 1.;
+               //LBMReal OxyyPxzz  = 2+s9;//1.;
+               //LBMReal OxyyMxzz  = 2+s9;//1.;
+               //LBMReal O4        = 1.;
+               //LBMReal O5        = 1.;
+               //LBMReal O6        = 1.;
+               ////Cum 4.
+               //LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3) * mfabb + 2. * mfbba * mfbab);
+               //LBMReal CUMbcb = mfbcb - ((mfaca + c1o3) * mfbab + 2. * mfbba * mfabb);
+               //LBMReal CUMbbc = mfbbc - ((mfaac + c1o3) * mfbba + 2. * mfbab * mfabb);
+               //LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba)- c1o3 * (mfcaa + mfaca);
+               //LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab)- c1o3 * (mfcaa + mfaac);
+               //LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb)- c1o3 * (mfaac + mfaca);
+               ////Cum 5.
+               //LBMReal CUMbcc = mfbcc - (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) //O(eps^5)
+               //   - c1o3 * (mfbca + mfbac); //O(eps^3)
+               //LBMReal CUMcbc = mfcbc - (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) //O(eps^5)
+               //   - c1o3 * (mfcba + mfabc); //O(eps^3)
+               //LBMReal CUMccb = mfccb - (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) //O(eps^5)
+               //   - c1o3 * (mfacb + mfcab);//O(eps^3)
+               ////Cum 6.
+               //LBMReal CUMccc = mfccc +(-4. *  mfbbb * mfbbb  //O(eps^6)
+               //   -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) // O(eps^4)
+               //   -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc) // O(eps^6)
+               //   -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) // O(esp^6)
+               //   +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) //O(eps^6)
+               //   +  2. * (mfcaa * mfaca * mfaac) //O(eps^6)
+               //   + 16. *  mfbba * mfbab * mfabb) //O(eps^6)
+               //   - c1o3* (mfacc + mfcac + mfcca) //O(eps^2)
+               //   + c1o9* (mfcaa + mfaca + mfaac) //O(eps^2)
+               //   +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)//O(eps^4)
+               //   +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3;//O(eps^4)
+               ////2.
+               //// linear combinations
+               //LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               //LBMReal mxxMyy    = mfcaa - mfaca;
+               //LBMReal mxxMzz         = mfcaa - mfaac;
+               //{
+               //   LBMReal dxux = c1o2 * (s9 *(mxxMyy + mxxMzz) + (mfaaa - mxxPyyPzz));
+               //   LBMReal dyuy = dxux - s9 * c3o2 * mxxMyy;
+               //   LBMReal dzuz = dxux - s9 * c3o2 * mxxMzz;
+               //   //relax
+               //   mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+               //   mxxMyy    += -s9 * (-mxxMyy) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vy2 * dyuy);
+               //   mxxMzz    += -s9 * (-mxxMzz) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vz2 * dzuz);
+               //}
+               //mfabb     += -s9 * (-mfabb);
+               //mfbab     += -s9 * (-mfbab);
+               //mfbba     += -s9 * (-mfbba);
+               //// linear combinations back
+               //mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               //mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               //mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+               ////3.
+               //// linear combinations
+               //LBMReal mxxyPyzz = mfcba + mfabc;
+               //LBMReal mxxyMyzz = mfcba - mfabc;
+               //LBMReal mxxzPyyz = mfcab + mfacb;
+               //LBMReal mxxzMyyz = mfcab - mfacb;
+               //LBMReal mxyyPxzz = mfbca + mfbac;
+               //LBMReal mxyyMxzz = mfbca - mfbac;
+               ////relax
+               //wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mfbbb)/(abs(mfbbb)+qudricLimit);
+               //mfbbb     += wadjust * (-mfbbb);
+               //wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxxyPyzz)/(abs(mxxyPyzz)+qudricLimit);
+               //mxxyPyzz  += wadjust * (-mxxyPyzz);
+               //wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxxyMyzz)/(abs(mxxyMyzz)+qudricLimit);
+               //mxxyMyzz  += wadjust * (-mxxyMyzz);
+               //wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxxzPyyz)/(abs(mxxzPyyz)+qudricLimit);
+               //mxxzPyyz  += wadjust * (-mxxzPyyz);
+               //wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxxzMyyz)/(abs(mxxzMyyz)+qudricLimit);
+               //mxxzMyyz  += wadjust * (-mxxzMyyz);
+               //wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxyyPxzz)/(abs(mxyyPxzz)+qudricLimit);
+               //mxyyPxzz  += wadjust * (-mxyyPxzz);
+               //wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxyyMxzz)/(abs(mxyyMxzz)+qudricLimit);
+               //mxyyMxzz  += wadjust * (-mxyyMxzz);
+               //// linear combinations back
+               //mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               //mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               //mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               //mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               //mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               //mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+               ////4.
+               //CUMacc += O4 * (-CUMacc);
+               //CUMcac += O4 * (-CUMcac);
+               //CUMcca += O4 * (-CUMcca);
+               //CUMbbc += O4 * (-CUMbbc);
+               //CUMbcb += O4 * (-CUMbcb);
+               //CUMcbb += O4 * (-CUMcbb);
+               ////5.
+               //CUMbcc += O5 * (-CUMbcc);
+               //CUMcbc += O5 * (-CUMcbc);
+               //CUMccb += O5 * (-CUMccb);
+               ////6.
+               //CUMccc += O6 * (-CUMccc);
+               ////back cumulants to central moments
+               ////4.
+               //mfcbb = CUMcbb + ((mfcaa + c1o3) * mfabb + 2. * mfbba * mfbab);
+               //mfbcb = CUMbcb + ((mfaca + c1o3) * mfbab + 2. * mfbba * mfabb);
+               //mfbbc = CUMbbc + ((mfaac + c1o3) * mfbba + 2. * mfbab * mfabb);
+               //mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca);
+               //mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac);
+               //mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca);
+               ////5.
+               //mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac);
+               //mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc);
+               //mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab);
+               ////6.
+               //mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+               //   -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+               //   -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+               //   -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+               //   +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+               //   +  2. * (mfcaa * mfaca * mfaac)
+               //   + 16. *  mfbba * mfbab * mfabb)
+               //   - c1o3* (mfacc + mfcac + mfcca)
+               //   + c1o9* (mfcaa + mfaca + mfaac)
+               //   +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+               //   +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3);
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa                * (1. - vz2)              - 1. * oMdrho * vz2;
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2;
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2);
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2;
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2);
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2;
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2);
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2;
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2);
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2;
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2);
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca                  * (1. - vz2)              - c1o9 * oMdrho * vz2;
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab                  * (1. - vy2)              - c2o3 * oMdrho * vy2;
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2;
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2);
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2);
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2);
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab                  * (1. - vy2)              - c2o9 * oMdrho * vy2;
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb                  * (1. - vx2)              - c4o9 * oMdrho * vx2;
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mfaaa +=c1o216;
+               //mfaab +=c1o54;
+               //mfaac +=c1o216;
+               //mfaba +=c1o54;
+               //mfabb +=c2o27;
+               //mfabc +=c1o54;
+               //mfbaa +=c1o54;
+               //mfbab +=c2o27;
+               //mfbac +=c1o54;
+               //mfbba +=c2o27;
+               //mfbbb +=c8o27;
+               //mfbbc +=c2o27;
+               //mfaca +=c1o216;
+               //mfacb +=c1o54;
+               //mfacc +=c1o216;
+               //mfcaa +=c1o216;
+               //mfcab +=c1o54;
+               //mfcac +=c1o216;
+               //mfcca +=c1o216;
+               //mfccb +=c1o54;
+               //mfccc +=c1o216;
+               //mfbca +=c1o54;
+               //mfbcb +=c2o27;
+               //mfbcc +=c1o54;
+               //mfcba +=c1o54;
+               //mfcbb +=c2o27;
+               //mfcbc +=c1o54;
+
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho="+UbSystem::toString(rho)+", rho_post="+UbSystem::toString(rho_post)
+                                       +" dif="+UbSystem::toString(dif)
+                                       +" rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27CCLB::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3)    = mfabb;
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3)    = mfbab;
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3)    = mfbba;
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3)   = mfaab;
+               (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3)   = mfcab;
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3)   = mfaba;
+               (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3)   = mfcba;
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3)   = mfbaa;
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3)   = mfbca;
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3)  = mfaaa;
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3)  = mfcaa;
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3)  = mfaca;
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3)  = mfcca;
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = mfcbb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = mfbcb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = mfbbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = mfccb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = mfacb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = mfcbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = mfabc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = mfbcc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = mfbac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = mfccc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = mfacc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = mfcac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = mfaac;
+
+               (*this->zeroDistributions)(x1,x2,x3) = mfbbb;
+               //////////////////////////////////////////////////////////////////////////
+
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLB_Geier::collideAll3()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dx",&muDeltaT);
+      muForcingX2.DefineVar("dx",&muDeltaT);
+      muForcingX3.DefineVar("dx",&muDeltaT);
+
+      muNue = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nue",&muNue);
+      muForcingX2.DefineVar("nue",&muNue);
+      muForcingX3.DefineVar("nue",&muNue);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   s9 = - collFactor;
+   c1o27=1.0/27.0;
+   c2o3=2.0/3.0;
+   w2=-1.0; //MXXpMYYpMZZ bulk viscosity
+   w7=-1.0;//s9; //ORDER 4 Isotropic
+   w9=-1.0;
+   w10=-1.0;//s9;//-1.0; // ORDER 6 Isotropic
+   w1=s9;
+   // wenn es mal an den Ecken nicht gut aussieht -2.0-s9 probieren
+   w3=-1.0;//-2.0-s9;//-1.0;//MXXYpMYZZ
+   w4=-1.0;//-2.0-s9;//-1.0;//MXXYmMYZZ
+   w5=-1.0;//-2.0-s9;//-1.0;//MYXZ
+   w6=-1.0; //MXXYYpm2p
+   w8=-1.0; //M_zXXYZ 
+
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////
+
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+
+               //Rest ist b
+
+               LBMReal mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1); 
+               LBMReal mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+               LBMReal mfaac = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+               LBMReal mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+               LBMReal mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3  );
+               LBMReal mfabc = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3);
+               LBMReal mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+               LBMReal mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3  );
+               LBMReal mfbac = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3);
+               LBMReal mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1  );
+               LBMReal mfbbb = (*this->zeroDistributions)(x1,x2,x3);
+               LBMReal mfbbc = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               LBMReal mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+               LBMReal mfacb = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3);
+               LBMReal mfacc = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3);
+               LBMReal mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+               LBMReal mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 );
+               LBMReal mfcac = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3);
+               LBMReal mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1);
+               LBMReal mfccb = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               LBMReal mfccc = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               LBMReal mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 );
+               LBMReal mfbcb = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3); 
+               LBMReal mfbcc = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               LBMReal mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 );
+               LBMReal mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               LBMReal mfcbc = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               LBMReal m0, m1, m2;
+
+
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               //mfaaa -=c1o216;
+               //mfaab -=c1o54;
+               //mfaac -=c1o216;
+               //mfaba -=c1o54;
+               //mfabb -=c2o27;
+               //mfabc -=c1o54;
+               //mfbaa -=c1o54;
+               //mfbab -=c2o27;
+               //mfbac -=c1o54;
+               //mfbba -=c2o27;
+               //mfbbb -=c8o27;
+               //mfbbc -=c2o27;
+               //mfaca -=c1o216;
+               //mfacb -=c1o54;
+               //mfacc -=c1o216;
+               //mfcaa -=c1o216;
+               //mfcab -=c1o54;
+               //mfcac -=c1o216;
+               //mfcca -=c1o216;
+               //mfccb -=c1o54;
+               //mfccc -=c1o216;
+               //mfbca -=c1o54;
+               //mfbcb -=c2o27;
+               //mfbcc -=c1o54;
+               //mfcba -=c1o54;
+               //mfcbb -=c2o27;
+               //mfcbc -=c1o54;
+
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb));
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab));
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba));
+               ////////////////////////////////////////////////////////////////////////////////////
+               //fast
+               //LBMReal oMdrho = 1. - (mfccc+mfaaa + mfaca+mfcac + mfacc+mfcaa + mfaac+mfcca +
+               //                                   mfbac+mfbca + mfbaa+mfbcc + mfabc+mfcba + mfaba+mfcbc + mfacb+mfcab + mfaab+mfccb +
+               //                                   mfabb+mfcbb + mfbab+mfbcb  +  mfbba+mfbbc);//fehlt mfbbb
+               //LBMReal vvx    =mfccc-mfaaa + mfcac-mfaca + mfcaa-mfacc + mfcca-mfaac +
+               //                         mfcba-mfabc + mfcbc-mfaba + mfcab-mfacb + mfccb-mfaab +
+               //                         mfcbb-mfabb;
+               //LBMReal vvy    =mfccc-mfaaa + mfaca-mfcac + mfacc-mfcaa + mfcca-mfaac +
+               //                         mfbca-mfbac + mfbcc-mfbaa + mfacb-mfcab + mfccb-mfaab +
+               //                         mfbcb-mfbab;
+               //LBMReal vvz    =mfccc-mfaaa + mfcac-mfaca + mfacc-mfcaa + mfaac-mfcca +
+               //                         mfbac-mfbca + mfbcc-mfbaa + mfabc-mfcba + mfcbc-mfaba +
+               //                         mfbbc-mfbba;
+               ////////////////////////////////////////////////////////////////////////////////////
+               // oMdrho assembler style -------> faaaaaastaaaa
+               //LBMReal m0, m1, m2;
+               LBMReal oMdrho;
+               {
+                  oMdrho=mfccc+mfaaa;
+                  m0=mfaca+mfcac;
+                  m1=mfacc+mfcaa;
+                  m2=mfaac+mfcca;
+                  oMdrho+=m0;
+                  m1+=m2;
+                  oMdrho+=m1;
+                  m0=mfbac+mfbca;
+                  m1=mfbaa+mfbcc;
+                  m0+=m1;
+                  m1=mfabc+mfcba;
+                  m2=mfaba+mfcbc;
+                  m1+=m2;
+                  m0+=m1;
+                  m1=mfacb+mfcab;
+                  m2=mfaab+mfccb;
+                  m1+=m2;
+                  m0+=m1;
+                  oMdrho+=m0;
+                  m0=mfabb+mfcbb;
+                  m1=mfbab+mfbcb;
+                  m2=mfbba+mfbbc;
+                  m0+=m1+m2;
+                  m0+=mfbbb; //hat gefehlt
+                  oMdrho = 1. - (oMdrho + m0);
+               }
+               //LBMReal vvx;
+               LBMReal vx2;
+               //{
+               //     vvx = mfccc-mfaaa;
+               //     m0  = mfcac-mfaca;
+               //     m1  = mfcaa-mfacc;
+               //     m2  = mfcca-mfaac;
+               //     vvx+= m0;
+               //     m1 += m2;
+               //     vvx+= m1;
+               //     vx2 = mfcba-mfabc;
+               //     m0  = mfcbc-mfaba;
+               //     m1  = mfcab-mfacb;
+               //     m2  = mfccb-mfaab;
+               //     vx2+= m0;
+               //     m1 += m2;
+               //     vx2+= m1;
+               //     vvx+= vx2;
+               //     vx2 = mfcbb-mfabb;
+               //     vvx+= vx2;
+               //}
+               //LBMReal vvy;
+               LBMReal vy2;
+               //{
+               //     vvy = mfccc-mfaaa;
+               //     m0  = mfaca-mfcac;
+               //     m1  = mfacc-mfcaa;
+               //     m2  = mfcca-mfaac;
+               //     vvy+= m0;
+               //     m1 += m2;
+               //     vvy+= m1;
+               //     vy2 = mfbca-mfbac;
+               //     m0  = mfbcc-mfbaa;
+               //     m1  = mfacb-mfcab;
+               //     m2  = mfccb-mfaab;
+               //     vy2+= m0;
+               //     m1 += m2;
+               //     vy2+= m1;
+               //     vvy+= vy2;
+               //     vy2 = mfbcb-mfbab;
+               //     vvy+= vy2;
+               //}
+               //LBMReal vvz;
+               LBMReal vz2;
+               //{
+               //     vvz = mfccc-mfaaa;
+               //     m0  = mfcac-mfaca;
+               //     m1  = mfacc-mfcaa;
+               //     m2  = mfaac-mfcca;
+               //     vvz+= m0;
+               //     m1 += m2;
+               //     vvz+= m1;
+               //     vz2 = mfbac-mfbca;
+               //     m0  = mfbcc-mfbaa;
+               //     m1  = mfabc-mfcba;
+               //     m2  = mfcbc-mfaba;
+               //     vz2+= m0;
+               //     m1 += m2;
+               //     vz2+= m1;
+               //     vvz+= vz2;
+               //     vz2 = mfbbc-mfbba;
+               //     vvz+= vz2;
+               //}
+               vx2=vvx*vvx;
+               vy2=vvy*vvy;
+               vz2=vvz*vvz;
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal wadjust;
+               LBMReal qudricLimit = 0.01;
+               //LBMReal s9 = minusomega;
+               //test
+               //s9 = 0.;
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa + mfaac;
+               m1    = mfaac - mfaaa;
+               m0    = m2          + mfaab;
+               mfaaa = m0;
+               m0   += c1o36 * oMdrho;   
+               mfaab = m1 -        m0 * vvz;
+               mfaac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2          + mfabb;
+               mfaba = m0;
+               m0   += c1o9 * oMdrho;
+               mfabb = m1 -        m0 * vvz;
+               mfabc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2          + mfacb;
+               mfaca = m0;
+               m0   += c1o36 * oMdrho;
+               mfacb = m1 -        m0 * vvz;
+               mfacc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbac;
+               m1    = mfbac - mfbaa;
+               m0    = m2          + mfbab;
+               mfbaa = m0;
+               m0   += c1o9 * oMdrho;
+               mfbab = m1 -        m0 * vvz;
+               mfbac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2          + mfbbb;
+               mfbba = m0;
+               m0   += c4o9 * oMdrho;
+               mfbbb = m1 -        m0 * vvz;
+               mfbbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2          + mfbcb;
+               mfbca = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcb = m1 -        m0 * vvz;
+               mfbcc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcac;
+               m1    = mfcac - mfcaa;
+               m0    = m2          + mfcab;
+               mfcaa = m0;
+               m0   += c1o36 * oMdrho;
+               mfcab = m1 -        m0 * vvz;
+               mfcac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2          + mfcbb;
+               mfcba = m0;
+               m0   += c1o9 * oMdrho;
+               mfcbb = m1 -        m0 * vvz;
+               mfcbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2          + mfccb;
+               mfcca = m0;
+               m0   += c1o36 * oMdrho;
+               mfccb = m1 -        m0 * vvz;
+               mfccc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa + mfaca;
+               m1    = mfaca - mfaaa;
+               m0    = m2          + mfaba;
+               mfaaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfaba = m1 -        m0 * vvy;
+               mfaca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2          + mfabb;
+               mfaab = m0;
+               mfabb = m1 -        m0 * vvy;
+               mfacb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2          + mfabc;
+               mfaac = m0;
+               m0   += c1o18 * oMdrho;
+               mfabc = m1 -        m0 * vvy;
+               mfacc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbca;
+               m1    = mfbca - mfbaa;
+               m0    = m2          + mfbba;
+               mfbaa = m0;
+               m0   += c2o3 * oMdrho;
+               mfbba = m1 -        m0 * vvy;
+               mfbca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2          + mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -        m0 * vvy;
+               mfbcb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2          + mfbbc;
+               mfbac = m0;
+               m0   += c2o9 * oMdrho;
+               mfbbc = m1 -        m0 * vvy;
+               mfbcc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcca;
+               m1    = mfcca - mfcaa;
+               m0    = m2          + mfcba;
+               mfcaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfcba = m1 -        m0 * vvy;
+               mfcca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2          + mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -        m0 * vvy;
+               mfccb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2          + mfcbc;
+               mfcac = m0;
+               m0   += c1o18 * oMdrho;
+               mfcbc = m1 -        m0 * vvy;
+               mfccc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9            Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa + mfcaa;
+               m1    = mfcaa - mfaaa;
+               m0    = m2          + mfbaa;
+               mfaaa = m0;
+               m0   += 1. * oMdrho;
+               mfbaa = m1 -        m0 * vvx;
+               mfcaa = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2          + mfbba;
+               mfaba = m0;
+               mfbba = m1 -        m0 * vvx;
+               mfcba = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2          + mfbca;
+               mfaca = m0;
+               m0   += c1o3 * oMdrho;
+               mfbca = m1 -        m0 * vvx;
+               mfcca = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab + mfcab;
+               m1    = mfcab - mfaab;
+               m0    = m2          + mfbab;
+               mfaab = m0;
+               mfbab = m1 -        m0 * vvx;
+               mfcab = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2          + mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -        m0 * vvx;
+               mfcbb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2          + mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -        m0 * vvx;
+               mfccb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac + mfcac;
+               m1    = mfcac - mfaac;
+               m0    = m2          + mfbac;
+               mfaac = m0;
+               m0   += c1o3 * oMdrho;
+               mfbac = m1 -        m0 * vvx;
+               mfcac = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2          + mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -        m0 * vvx;
+               mfcbc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2          + mfbcc;
+               mfacc = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcc = m1 -        m0 * vvx;
+               mfccc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //////////////////////////////////////////////////////////////////////////////////////
+               //// BGK
+               //////////////////////////////////////////////////////////////////////////////////////
+               ////2.
+               //mfabb += -s9 * (-mfabb);
+               //mfbab += -s9 * (-mfbab);
+               //mfbba += -s9 * (-mfbba);
+               //
+               //mfcaa += -s9 * (c1o3 * mfaaa - mfcaa);
+               //mfaca += -s9 * (c1o3 * mfaaa - mfaca);
+               //mfaac += -s9 * (c1o3 * mfaaa - mfaac);
+               //
+               ////3.
+               //mfabc += -s9 * (-mfabc);
+               //mfbac += -s9 * (-mfbac);
+               //
+               //mfacb += -s9 * (-mfacb);
+               //mfbca += -s9 * (-mfbca);
+               //mfcab += -s9 * (-mfcab);
+               //mfcba += -s9 * (-mfcba);
+               //mfbbb += -s9 * (-mfbbb);
+               ////4.
+               //mfacc += -s9 * (c1o9 * mfaaa - mfacc);
+               //mfcac += -s9 * (c1o9 * mfaaa - mfcac);
+               //mfcca += -s9 * (c1o9 * mfaaa - mfcca);
+               //mfbbc += -s9 * (-mfbbc);
+               //mfbcb += -s9 * (-mfbcb);
+               //mfcbb += -s9 * (-mfcbb);
+               ////5.
+               //mfbcc += -s9 * (-mfbcc);
+               //mfcbc += -s9 * (-mfcbc);
+               //mfccb += -s9 * (-mfccb);
+               ////6.
+               //mfccc += -s9 * (c1o27 * mfaaa - mfccc);
+               //////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal OxxPyyPzz = 1.;
+               LBMReal OxyyPxzz  = 1.;//-s9;//2+s9;//
+               LBMReal OxyyMxzz  = 2+s9;//
+               LBMReal O4        = 1.;
+               LBMReal O5        = 1.;
+               LBMReal O6        = 1.;
+
+               //Cum 4.
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //Cum 5.
+               LBMReal CUMbcc = (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) - c1o3 * (mfbca + mfbac) * oMdrho;
+               LBMReal CUMcbc = (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) - c1o3 * (mfcba + mfabc) * oMdrho;
+               LBMReal CUMccb = (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) - c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc  +((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) +c1o27*oMdrho;
+
+               //2.
+               // linear combinations
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz         = mfcaa - mfaac;
+
+               {
+                  LBMReal dxux = c1o2 * (s9 *(mxxMyy + mxxMzz) + (mfaaa - mxxPyyPzz));
+                  LBMReal dyuy = dxux - s9 * c3o2 * mxxMyy;
+                  LBMReal dzuz = dxux - s9 * c3o2 * mxxMzz;
+
+                  //relax
+                  mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+                  mxxMyy    += -s9 * (-mxxMyy) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vy2 * dyuy);
+                  mxxMzz    += -s9 * (-mxxMzz) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vz2 * dzuz);
+               }
+               mfabb     += -s9 * (-mfabb);
+               mfbab     += -s9 * (-mfbab);
+               mfbba     += -s9 * (-mfbba);
+
+               // linear combinations back
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mfbbb)/(fabs(mfbbb)+qudricLimit);
+               mfbbb     += wadjust * (-mfbbb);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxyPyzz)/(fabs(mxxyPyzz)+qudricLimit);
+               mxxyPyzz  += wadjust * (-mxxyPyzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxyMyzz)/(fabs(mxxyMyzz)+qudricLimit);
+               mxxyMyzz  += wadjust * (-mxxyMyzz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxzPyyz)/(fabs(mxxzPyyz)+qudricLimit);
+               mxxzPyyz  += wadjust * (-mxxzPyyz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxzMyyz)/(fabs(mxxzMyyz)+qudricLimit);
+               mxxzMyyz  += wadjust * (-mxxzMyyz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxyyPxzz)/(fabs(mxyyPxzz)+qudricLimit);
+               mxyyPxzz  += wadjust * (-mxyyPxzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxyyMxzz)/(fabs(mxyyMxzz)+qudricLimit);
+               mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               //4.
+               CUMacc += O4 * (-CUMacc);
+               CUMcac += O4 * (-CUMcac);
+               CUMcca += O4 * (-CUMcca);
+
+               CUMbbc += O4 * (-CUMbbc);
+               CUMbcb += O4 * (-CUMbcb);
+               CUMcbb += O4 * (-CUMcbb);
+
+               //5.
+               CUMbcc += O5 * (-CUMbcc);
+               CUMcbc += O5 * (-CUMcbc);
+               CUMccb += O5 * (-CUMccb);
+
+               //6.
+               CUMccc += O6 * (-CUMccc);
+
+               //back cumulants to central moments
+               //4.
+               mfcbb = CUMcbb + ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               mfbcb = CUMbcb + ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               mfbbc = CUMbbc + ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac) * oMdrho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc) * oMdrho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) -c1o27*oMdrho;
+               ////////////////////////////////////////////////////////////////////////////////////
+
+               //////////////////////////////////////////////////////////////////////////////////////
+               //// Cumulants
+               //////////////////////////////////////////////////////////////////////////////////////
+               //LBMReal OxxPyyPzz = 1.;
+               //LBMReal OxyyPxzz  = 2+s9;//1.;
+               //LBMReal OxyyMxzz  = 2+s9;//1.;
+               //LBMReal O4        = 1.;
+               //LBMReal O5        = 1.;
+               //LBMReal O6        = 1.;
+               ////Cum 4.
+               //LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3) * mfabb + 2. * mfbba * mfbab);
+               //LBMReal CUMbcb = mfbcb - ((mfaca + c1o3) * mfbab + 2. * mfbba * mfabb);
+               //LBMReal CUMbbc = mfbbc - ((mfaac + c1o3) * mfbba + 2. * mfbab * mfabb);
+               //LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba)- c1o3 * (mfcaa + mfaca);
+               //LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab)- c1o3 * (mfcaa + mfaac);
+               //LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb)- c1o3 * (mfaac + mfaca);
+               ////Cum 5.
+               //LBMReal CUMbcc = mfbcc - (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) //O(eps^5)
+               //   - c1o3 * (mfbca + mfbac); //O(eps^3)
+               //LBMReal CUMcbc = mfcbc - (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) //O(eps^5)
+               //   - c1o3 * (mfcba + mfabc); //O(eps^3)
+               //LBMReal CUMccb = mfccb - (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) //O(eps^5)
+               //   - c1o3 * (mfacb + mfcab);//O(eps^3)
+               ////Cum 6.
+               //LBMReal CUMccc = mfccc +(-4. *  mfbbb * mfbbb  //O(eps^6)
+               //   -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) // O(eps^4)
+               //   -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc) // O(eps^6)
+               //   -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) // O(esp^6)
+               //   +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) //O(eps^6)
+               //   +  2. * (mfcaa * mfaca * mfaac) //O(eps^6)
+               //   + 16. *  mfbba * mfbab * mfabb) //O(eps^6)
+               //   - c1o3* (mfacc + mfcac + mfcca) //O(eps^2)
+               //   + c1o9* (mfcaa + mfaca + mfaac) //O(eps^2)
+               //   +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)//O(eps^4)
+               //   +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3;//O(eps^4)
+               ////2.
+               //// linear combinations
+               //LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               //LBMReal mxxMyy    = mfcaa - mfaca;
+               //LBMReal mxxMzz         = mfcaa - mfaac;
+               //{
+               //   LBMReal dxux = c1o2 * (s9 *(mxxMyy + mxxMzz) + (mfaaa - mxxPyyPzz));
+               //   LBMReal dyuy = dxux - s9 * c3o2 * mxxMyy;
+               //   LBMReal dzuz = dxux - s9 * c3o2 * mxxMzz;
+               //   //relax
+               //   mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+               //   mxxMyy    += -s9 * (-mxxMyy) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vy2 * dyuy);
+               //   mxxMzz    += -s9 * (-mxxMzz) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vz2 * dzuz);
+               //}
+               //mfabb     += -s9 * (-mfabb);
+               //mfbab     += -s9 * (-mfbab);
+               //mfbba     += -s9 * (-mfbba);
+               //// linear combinations back
+               //mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               //mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               //mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+               ////3.
+               //// linear combinations
+               //LBMReal mxxyPyzz = mfcba + mfabc;
+               //LBMReal mxxyMyzz = mfcba - mfabc;
+               //LBMReal mxxzPyyz = mfcab + mfacb;
+               //LBMReal mxxzMyyz = mfcab - mfacb;
+               //LBMReal mxyyPxzz = mfbca + mfbac;
+               //LBMReal mxyyMxzz = mfbca - mfbac;
+               ////relax
+               //wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mfbbb)/(abs(mfbbb)+qudricLimit);
+               //mfbbb     += wadjust * (-mfbbb);
+               //wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxxyPyzz)/(abs(mxxyPyzz)+qudricLimit);
+               //mxxyPyzz  += wadjust * (-mxxyPyzz);
+               //wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxxyMyzz)/(abs(mxxyMyzz)+qudricLimit);
+               //mxxyMyzz  += wadjust * (-mxxyMyzz);
+               //wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxxzPyyz)/(abs(mxxzPyyz)+qudricLimit);
+               //mxxzPyyz  += wadjust * (-mxxzPyyz);
+               //wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxxzMyyz)/(abs(mxxzMyyz)+qudricLimit);
+               //mxxzMyyz  += wadjust * (-mxxzMyyz);
+               //wadjust    = OxyyPxzz+(1.-OxyyPxzz)*abs(mxyyPxzz)/(abs(mxyyPxzz)+qudricLimit);
+               //mxyyPxzz  += wadjust * (-mxyyPxzz);
+               //wadjust    = OxyyMxzz+(1.-OxyyMxzz)*abs(mxyyMxzz)/(abs(mxyyMxzz)+qudricLimit);
+               //mxyyMxzz  += wadjust * (-mxyyMxzz);
+               //// linear combinations back
+               //mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               //mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               //mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               //mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               //mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               //mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+               ////4.
+               //CUMacc += O4 * (-CUMacc);
+               //CUMcac += O4 * (-CUMcac);
+               //CUMcca += O4 * (-CUMcca);
+               //CUMbbc += O4 * (-CUMbbc);
+               //CUMbcb += O4 * (-CUMbcb);
+               //CUMcbb += O4 * (-CUMcbb);
+               ////5.
+               //CUMbcc += O5 * (-CUMbcc);
+               //CUMcbc += O5 * (-CUMcbc);
+               //CUMccb += O5 * (-CUMccb);
+               ////6.
+               //CUMccc += O6 * (-CUMccc);
+               ////back cumulants to central moments
+               ////4.
+               //mfcbb = CUMcbb + ((mfcaa + c1o3) * mfabb + 2. * mfbba * mfbab);
+               //mfbcb = CUMbcb + ((mfaca + c1o3) * mfbab + 2. * mfbba * mfabb);
+               //mfbbc = CUMbbc + ((mfaac + c1o3) * mfbba + 2. * mfbab * mfabb);
+               //mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca);
+               //mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac);
+               //mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca);
+               ////5.
+               //mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac);
+               //mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc);
+               //mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab);
+               ////6.
+               //mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+               //   -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+               //   -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+               //   -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+               //   +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+               //   +  2. * (mfcaa * mfaca * mfaac)
+               //   + 16. *  mfbba * mfbab * mfabb)
+               //   - c1o3* (mfacc + mfcac + mfcca)
+               //   + c1o9* (mfcaa + mfaca + mfaac)
+               //   +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+               //   +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3);
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa                * (1. - vz2)              - 1. * oMdrho * vz2;
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2;
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2);
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2;
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2);
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2;
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2);
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2;
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2);
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2;
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2);
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca                  * (1. - vz2)              - c1o9 * oMdrho * vz2;
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab                  * (1. - vy2)              - c2o3 * oMdrho * vy2;
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2;
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2);
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2);
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2);
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab                  * (1. - vy2)              - c2o9 * oMdrho * vy2;
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb                  * (1. - vx2)              - c4o9 * oMdrho * vx2;
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mfaaa +=c1o216;
+               //mfaab +=c1o54;
+               //mfaac +=c1o216;
+               //mfaba +=c1o54;
+               //mfabb +=c2o27;
+               //mfabc +=c1o54;
+               //mfbaa +=c1o54;
+               //mfbab +=c2o27;
+               //mfbac +=c1o54;
+               //mfbba +=c2o27;
+               //mfbbb +=c8o27;
+               //mfbbc +=c2o27;
+               //mfaca +=c1o216;
+               //mfacb +=c1o54;
+               //mfacc +=c1o216;
+               //mfcaa +=c1o216;
+               //mfcab +=c1o54;
+               //mfcac +=c1o216;
+               //mfcca +=c1o216;
+               //mfccb +=c1o54;
+               //mfccc +=c1o216;
+               //mfbca +=c1o54;
+               //mfbcb +=c2o27;
+               //mfbcc +=c1o54;
+               //mfcba +=c1o54;
+               //mfcbb +=c2o27;
+               //mfcbc +=c1o54;
+
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho="+UbSystem::toString(rho)+", rho_post="+UbSystem::toString(rho_post)
+                     +" dif="+UbSystem::toString(dif)
+                     +" rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27CCLB::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3)    = mfabb;
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3)    = mfbab;
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3)    = mfbba;
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3)   = mfaab;
+               (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3)   = mfcab;
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3)   = mfaba;
+               (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3)   = mfcba;
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3)   = mfbaa;
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3)   = mfbca;
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3)  = mfaaa;
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3)  = mfcaa;
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3)  = mfaca;
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3)  = mfcca;
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = mfcbb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = mfbcb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = mfbbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = mfccb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = mfacb;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = mfcbc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = mfabc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = mfbcc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = mfbac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = mfccc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = mfacc;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = mfcac;
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = mfaac;
+
+               (*this->zeroDistributions)(x1,x2,x3) = mfbbb;
+               //////////////////////////////////////////////////////////////////////////
+
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelETD3Q27CCLB_Geier::getCallculationTime()
+{
+   //return timer.getDuration();
+   return timer.getTotalTime();
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB_Geier.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB_Geier.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d2fbea6f8cb48ad25c051d0d1eaab5bb4135e27
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLB_Geier.h
@@ -0,0 +1,74 @@
+//Cascaded Cumulant LBM
+
+#ifndef LBMKernelETD3Q27CCLB_Geier_H
+#define LBMKernelETD3Q27CCLB_Geier_H
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+
+class LBMKernelETD3Q27CCLB_Geier;
+typedef boost::shared_ptr<LBMKernelETD3Q27CCLB_Geier> LBMKernelETD3Q27CCLB_GeierPtr;
+
+
+class LBMKernelETD3Q27CCLB_Geier :  public LBMKernelETD3Q27
+{
+public:
+   LBMKernelETD3Q27CCLB_Geier();
+   LBMKernelETD3Q27CCLB_Geier(int nx1, int nx2, int nx3, int option);
+   ~LBMKernelETD3Q27CCLB_Geier(void);
+   void calculate();
+   LBMKernel3DPtr clone();
+   double getCallculationTime();
+
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+      ar & OxyyMxzz; 
+      ar & option;
+   }
+
+   void collideAll();  
+   void collideAll2(); 
+   void collideAll3();
+   void init();
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal rho, vx, vy, vz, durchrho;
+   LBMReal w1,w2,w3,w4,w5,w6,w7,w8,w9,w10;
+   LBMReal s9,c1o27,c2o3;
+
+   LBMReal M_zXX, M_zYY, M_zZZ, M_zXY,    M_zXZ,  M_zYZ,
+      M_zXXY,    M_zXYY,    M_zXXZ,    M_zXZZ,   M_zYYZ,  M_zYZZ,  M_zXYZ,
+      M_zXXYY,   M_zXXZZ,   M_zYYZZ,   M_zXXYZ,  M_zXYYZ,  M_zXYZZ,
+      M_zXXYYZ,  M_zXXYZZ,  M_zXYYZZ,  M_zXXYYZZ;
+   LBMReal mu200, mu020, mu002,mu110, mu101,mu011,mu210,mu120,mu102,mu111, 
+      mu201,mu021,mu012,mu220,mu121,mu202,mu211,mu112,mu022,mu221,mu122,mu212,mu222,mu000,mu100,mu010,mu001;
+   LBMReal vx_sq, vy_sq, vz_sq, vx_vy, vx_vz, vy_vz, vx_vy_vz;
+   LBMReal MXXpMYYpMZZ,MXXmMYY, MXXmMZZ,
+      MXXYpMYZZ,MXXZpMYYZ,MXYYpMXZZ,  MXXYmMYZZ,MXXZmMYYZ,MXYYmMXZZ,
+      MXXYYppp,MXXYYpm2p, MXXYYppm2;
+   UbTimer timer;
+
+   LBMReal OxyyMxzz;
+   int option;
+
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributions;
+
+   mu::value_type muX1,muX2,muX3;
+   mu::value_type muDeltaT;
+   mu::value_type muNue;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7dd71536c4dca11a4f4e42770d44e4351c9fb96c
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex.cpp
@@ -0,0 +1,1088 @@
+#include "LBMKernelETD3Q27CCLBex.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27EsoTwist3DSplittedVectorEx.h"
+#include <math.h>
+
+//#define PROOF_CORRECTNESS
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBex::LBMKernelETD3Q27CCLBex()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBex::LBMKernelETD3Q27CCLBex(int nx1, int nx2, int nx3, int option, Grid3DPtr grid) 
+   : LBMKernelETD3Q27(nx1, nx2, nx3),
+     option(option),
+     grid(grid)
+{
+   this->compressible = false;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBex::~LBMKernelETD3Q27CCLBex(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBex::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   int tnx1=nx1;
+   int tnx2=nx2;
+   int tnx3=nx3;
+   bX1=block.lock()->getX1();
+   bX2=block.lock()->getX2();
+   bX3=block.lock()->getX3();
+   level = block.lock()->getLevel();
+   if(!grid->getBlock(bX1+1,bX2,bX3,level) && !grid->isPeriodicX1()) tnx1++;
+   if(!grid->getBlock(bX1,bX2+1,bX3,level) && !grid->isPeriodicX2()) tnx2++;
+   if(!grid->getBlock(bX1,bX2,bX3+1,level) && !grid->isPeriodicX3()) tnx3++;
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVectorEx(tnx1, tnx2, tnx3, 0.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27CCLBex::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLBex(nx1, nx2, nx3, option, grid));
+   kernel->setBlock(this->getBlock());
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBex>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   if (option == 0)
+   {
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBex>(kernel)->OxyyMxzz = 1.0;
+   }
+   else if (option == 1)
+   {
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBex>(kernel)->OxyyMxzz = 2.0 +(-collFactor);
+   }
+   
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBex::calculate()
+{
+   timer.resetAndStart();
+   collideAll();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBex::setNewDistributions(int x1, int x2, int x3)
+{
+   int gX1 = bX1 * nx1 + x1-1;
+   int gX2 = bX2 * nx2 + x2-1;
+   int gX3 = bX3 * nx3 + x3-1;
+
+   int nbX1 = (gX1 + 1) / nx1;
+   int nbX2 = (gX2 + 1) / nx2;
+   int nbX3 = (gX3 + 1) / nx3;
+
+   lX1 = (gX1 + 1) - nbX1 * nx1;
+   lX2 = (gX2 + 1) - nbX2 * nx2;
+   lX3 = (gX3 + 1) - nbX3 * nx3;
+
+   Block3DPtr nblock = grid->getBlock(nbX1,nbX2,nbX3,level);
+
+   if (nblock)
+   {
+      localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(nblock->getKernel()->getDataSet()->getFdistributions())->getLocalDistributions();
+      nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(nblock->getKernel()->getDataSet()->getFdistributions())->getNonLocalDistributions();
+   }
+   else
+   {
+      localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+      nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+      lX1 = x1;
+      lX2 = x2;
+      lX3 = x3;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBex::collideAll()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dx",&muDeltaT);
+      muForcingX2.DefineVar("dx",&muDeltaT);
+      muForcingX3.DefineVar("dx",&muDeltaT);
+
+      muNue = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nue",&muNue);
+      muForcingX2.DefineVar("nue",&muNue);
+      muForcingX3.DefineVar("nue",&muNue);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   s9 = - collFactor;
+   c1o27=1.0/27.0;
+   c2o3=2.0/3.0;
+   w2=-1.0; //MXXpMYYpMZZ bulk viscosity
+   w7=-1.0;//s9; //ORDER 4 Isotropic
+   w9=-1.0;
+   w10=-1.0;//s9;//-1.0; // ORDER 6 Isotropic
+   w1=s9;
+   // wenn es mal an den Ecken nicht gut aussieht -2.0-s9 probieren
+   w3=-1.0;//-2.0-s9;//-1.0;//MXXYpMYZZ
+   w4=-1.0;//-2.0-s9;//-1.0;//MXXYmMYZZ
+   w5=-1.0;//-2.0-s9;//-1.0;//MYXZ
+   w6=-1.0; //MXXYYpm2p
+   w8=-1.0; //M_zXXYZ 
+
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = 0; //ghostLayerWidth;
+   int minX2 = 0; //ghostLayerWidth;
+   int minX3 = 0; //ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1; //-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2; //-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3; //-ghostLayerWidth;
+
+   int maxX1m = bcArrayMaxX1-1;
+   int maxX2m = bcArrayMaxX2-1;
+   int maxX3m = bcArrayMaxX3-1;
+
+   LBMReal mfaaa;
+   LBMReal mfaab;
+   LBMReal mfaac;
+   LBMReal mfaba;
+   LBMReal mfabb;
+   LBMReal mfabc;
+   LBMReal mfbaa;
+   LBMReal mfbab;
+   LBMReal mfbac;
+   LBMReal mfbba;
+   LBMReal mfbbb;
+   LBMReal mfbbc;
+   LBMReal mfaca;
+   LBMReal mfacb;
+   LBMReal mfacc;
+   LBMReal mfcaa;
+   LBMReal mfcab;
+   LBMReal mfcac;
+   LBMReal mfcca;
+   LBMReal mfccb;
+   LBMReal mfccc;
+   LBMReal mfbca;
+   LBMReal mfbcb;
+   LBMReal mfbcc;
+   LBMReal mfcba;
+   LBMReal mfcbb;
+   LBMReal mfcbc;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+
+               //Rest ist b
+               //////////////////////////////////////////////////////////////////////////
+               int x1p = x1 + 1;
+               int x2p = x2 + 1;
+               int x3p = x3 + 1;
+               if (x1 == maxX1m || x2 == maxX2m || x3 == maxX3m)
+               {
+                  setNewDistributions(x1p, x2p, x3p);
+                  mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1p, x2p, x3);
+                  mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW,lX1,lX2,lX3);
+                  mfaac = (*this->localDistributions)(D3Q27System::ET_TSW,lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1p, x2, x3p);
+                  mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW,lX1,lX2,lX3);
+                  mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1p, x2, x3);
+                  mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W,lX1,lX2,lX3);
+                  mfabc = (*this->localDistributions)(D3Q27System::ET_TW, lX1,lX2,lX3);
+                  mfacb = (*this->localDistributions)(D3Q27System::ET_NW,lX1,lX2,lX3);
+                  mfacc = (*this->localDistributions)(D3Q27System::ET_TNW,lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1, x2p, x3p);
+                  mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS,lX1,lX2,lX3);
+                  mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1, x2p, x3);
+                  mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S,lX1,lX2,lX3);
+                  mfbac = (*this->localDistributions)(D3Q27System::ET_TS,lX1,lX2,lX3);
+                  mfcac = (*this->localDistributions)(D3Q27System::ET_TSE,lX1,lX2,lX3);
+                  mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE,lX1,lX2,lX3);
+
+                  setNewDistributions(x1, x2, x3p);
+                  mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B,lX1,lX2,lX3);
+                  mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,lX1,lX2,lX3);
+                  mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN,lX1,lX2,lX3);
+                  mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE,lX1,lX2,lX3);
+
+                  localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+                  nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+                  mfbbc = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+                  mfccb = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+                  mfccc = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+                  mfbcb = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3); 
+                  mfbcc = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+                  mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+                  mfcbc = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+                  mfbbb = (*this->zeroDistributions)(x1,x2,x3);
+               }
+               else
+               {
+                  //localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+                  //nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+                  mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+                  mfbcb = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3);
+                  mfbbc = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+                  mfccb = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+                  mfacb = (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,x3);
+                  mfcbc = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+                  mfabc = (*this->localDistributions)(D3Q27System::ET_TW, x1p,x2,x3);
+                  mfbcc = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+                  mfbac = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2p,x3);
+                  mfccc = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+                  mfacc = (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,x3);
+                  mfcac = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2p,x3);
+                  mfaac = (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3);
+
+                  mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,x3);
+                  mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2p,x3);
+                  mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3p);
+                  mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3);
+                  mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2p,x3 );
+                  mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,x3p );
+                  mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3p );
+                  mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2p,x3p );
+                  mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3p );
+                  mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p); 
+                  mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2p,x3p);
+                  mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,x3p);
+                  mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3p);
+                  
+                  mfbbb = (*this->zeroDistributions)(x1,x2,x3);
+               }
+               LBMReal m0, m1, m2;
+
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb));
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab));
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba));
+
+               //forcing 
+               ///////////////////////////////////////////////////////////////////////////////////////////
+               if (withForcing)
+               {
+                  muX1 = static_cast<double>(x1+ix1*bcArrayMaxX1);
+                  muX2 = static_cast<double>(x2+ix2*bcArrayMaxX2);
+                  muX3 = static_cast<double>(x3+ix3*bcArrayMaxX3);
+
+                  forcingX1 = muForcingX1.Eval();
+                  forcingX2 = muForcingX2.Eval();
+                  forcingX3 = muForcingX3.Eval();
+
+                  vvx += forcingX1*0.5; // X
+                  vvy += forcingX2*0.5; // Y
+                  vvz += forcingX3*0.5; // Z
+               }
+               ///////////////////////////////////////////////////////////////////////////////////////////               
+
+               LBMReal oMdrho;
+               {
+                  oMdrho=mfccc+mfaaa;
+                  m0=mfaca+mfcac;
+                  m1=mfacc+mfcaa;
+                  m2=mfaac+mfcca;
+                  oMdrho+=m0;
+                  m1+=m2;
+                  oMdrho+=m1;
+                  m0=mfbac+mfbca;
+                  m1=mfbaa+mfbcc;
+                  m0+=m1;
+                  m1=mfabc+mfcba;
+                  m2=mfaba+mfcbc;
+                  m1+=m2;
+                  m0+=m1;
+                  m1=mfacb+mfcab;
+                  m2=mfaab+mfccb;
+                  m1+=m2;
+                  m0+=m1;
+                  oMdrho+=m0;
+                  m0=mfabb+mfcbb;
+                  m1=mfbab+mfbcb;
+                  m2=mfbba+mfbbc;
+                  m0+=m1+m2;
+                  m0+=mfbbb; //hat gefehlt
+                  oMdrho = 1. - (oMdrho + m0);
+               }
+               LBMReal vx2;
+               LBMReal vy2;
+               LBMReal vz2;
+
+               vx2=vvx*vvx;
+               vy2=vvy*vvy;
+               vz2=vvz*vvz;
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal wadjust;
+               LBMReal qudricLimit = 0.01;
+               //LBMReal s9 = minusomega;
+               //test
+               //s9 = 0.;
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa + mfaac;
+               m1    = mfaac - mfaaa;
+               m0    = m2          + mfaab;
+               mfaaa = m0;
+               m0   += c1o36 * oMdrho;   
+               mfaab = m1 -        m0 * vvz;
+               mfaac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2          + mfabb;
+               mfaba = m0;
+               m0   += c1o9 * oMdrho;
+               mfabb = m1 -        m0 * vvz;
+               mfabc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2          + mfacb;
+               mfaca = m0;
+               m0   += c1o36 * oMdrho;
+               mfacb = m1 -        m0 * vvz;
+               mfacc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbac;
+               m1    = mfbac - mfbaa;
+               m0    = m2          + mfbab;
+               mfbaa = m0;
+               m0   += c1o9 * oMdrho;
+               mfbab = m1 -        m0 * vvz;
+               mfbac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2          + mfbbb;
+               mfbba = m0;
+               m0   += c4o9 * oMdrho;
+               mfbbb = m1 -        m0 * vvz;
+               mfbbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2          + mfbcb;
+               mfbca = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcb = m1 -        m0 * vvz;
+               mfbcc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcac;
+               m1    = mfcac - mfcaa;
+               m0    = m2          + mfcab;
+               mfcaa = m0;
+               m0   += c1o36 * oMdrho;
+               mfcab = m1 -        m0 * vvz;
+               mfcac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2          + mfcbb;
+               mfcba = m0;
+               m0   += c1o9 * oMdrho;
+               mfcbb = m1 -        m0 * vvz;
+               mfcbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2          + mfccb;
+               mfcca = m0;
+               m0   += c1o36 * oMdrho;
+               mfccb = m1 -        m0 * vvz;
+               mfccc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa + mfaca;
+               m1    = mfaca - mfaaa;
+               m0    = m2          + mfaba;
+               mfaaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfaba = m1 -        m0 * vvy;
+               mfaca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2          + mfabb;
+               mfaab = m0;
+               mfabb = m1 -        m0 * vvy;
+               mfacb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2          + mfabc;
+               mfaac = m0;
+               m0   += c1o18 * oMdrho;
+               mfabc = m1 -        m0 * vvy;
+               mfacc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbca;
+               m1    = mfbca - mfbaa;
+               m0    = m2          + mfbba;
+               mfbaa = m0;
+               m0   += c2o3 * oMdrho;
+               mfbba = m1 -        m0 * vvy;
+               mfbca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2          + mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -        m0 * vvy;
+               mfbcb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2          + mfbbc;
+               mfbac = m0;
+               m0   += c2o9 * oMdrho;
+               mfbbc = m1 -        m0 * vvy;
+               mfbcc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcca;
+               m1    = mfcca - mfcaa;
+               m0    = m2          + mfcba;
+               mfcaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfcba = m1 -        m0 * vvy;
+               mfcca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2          + mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -        m0 * vvy;
+               mfccb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2          + mfcbc;
+               mfcac = m0;
+               m0   += c1o18 * oMdrho;
+               mfcbc = m1 -        m0 * vvy;
+               mfccc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9            Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa + mfcaa;
+               m1    = mfcaa - mfaaa;
+               m0    = m2          + mfbaa;
+               mfaaa = m0;
+               m0   += 1. * oMdrho;
+               mfbaa = m1 -        m0 * vvx;
+               mfcaa = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2          + mfbba;
+               mfaba = m0;
+               mfbba = m1 -        m0 * vvx;
+               mfcba = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2          + mfbca;
+               mfaca = m0;
+               m0   += c1o3 * oMdrho;
+               mfbca = m1 -        m0 * vvx;
+               mfcca = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab + mfcab;
+               m1    = mfcab - mfaab;
+               m0    = m2          + mfbab;
+               mfaab = m0;
+               mfbab = m1 -        m0 * vvx;
+               mfcab = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2          + mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -        m0 * vvx;
+               mfcbb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2          + mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -        m0 * vvx;
+               mfccb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac + mfcac;
+               m1    = mfcac - mfaac;
+               m0    = m2          + mfbac;
+               mfaac = m0;
+               m0   += c1o3 * oMdrho;
+               mfbac = m1 -        m0 * vvx;
+               mfcac = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2          + mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -        m0 * vvx;
+               mfcbc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2          + mfbcc;
+               mfacc = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcc = m1 -        m0 * vvx;
+               mfccc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal OxxPyyPzz = 1.;
+               LBMReal OxyyPxzz  = 1.;//-s9;//2+s9;//
+               //LBMReal OxyyMxzz  = 1.;//2+s9;//
+               LBMReal O4        = 1.;
+               LBMReal O5        = 1.;
+               LBMReal O6        = 1.;
+
+               //Cum 4.
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //Cum 5.
+               LBMReal CUMbcc = (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) - c1o3 * (mfbca + mfbac) * oMdrho;
+               LBMReal CUMcbc = (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) - c1o3 * (mfcba + mfabc) * oMdrho;
+               LBMReal CUMccb = (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) - c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc  +((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) +c1o27*oMdrho;
+
+               //2.
+               // linear combinations
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz         = mfcaa - mfaac;
+
+               {
+                  LBMReal dxux = c1o2 * (s9 *(mxxMyy + mxxMzz) + (mfaaa - mxxPyyPzz));
+                  LBMReal dyuy = dxux - s9 * c3o2 * mxxMyy;
+                  LBMReal dzuz = dxux - s9 * c3o2 * mxxMzz;
+
+                  //relax
+                  mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+                  mxxMyy    += -s9 * (-mxxMyy) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vy2 * dyuy);
+                  mxxMzz    += -s9 * (-mxxMzz) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vz2 * dzuz);
+               }
+               mfabb     += -s9 * (-mfabb);
+               mfbab     += -s9 * (-mfbab);
+               mfbba     += -s9 * (-mfbba);
+
+               // linear combinations back
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mfbbb)/(fabs(mfbbb)+qudricLimit);
+               mfbbb     += wadjust * (-mfbbb);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxyPyzz)/(fabs(mxxyPyzz)+qudricLimit);
+               mxxyPyzz  += wadjust * (-mxxyPyzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxyMyzz)/(fabs(mxxyMyzz)+qudricLimit);
+               mxxyMyzz  += wadjust * (-mxxyMyzz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxzPyyz)/(fabs(mxxzPyyz)+qudricLimit);
+               mxxzPyyz  += wadjust * (-mxxzPyyz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxzMyyz)/(fabs(mxxzMyyz)+qudricLimit);
+               mxxzMyyz  += wadjust * (-mxxzMyyz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxyyPxzz)/(fabs(mxyyPxzz)+qudricLimit);
+               mxyyPxzz  += wadjust * (-mxyyPxzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxyyMxzz)/(fabs(mxyyMxzz)+qudricLimit);
+               mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               //4.
+               CUMacc += O4 * (-CUMacc);
+               CUMcac += O4 * (-CUMcac);
+               CUMcca += O4 * (-CUMcca);
+
+               CUMbbc += O4 * (-CUMbbc);
+               CUMbcb += O4 * (-CUMbcb);
+               CUMcbb += O4 * (-CUMcbb);
+
+               //5.
+               CUMbcc += O5 * (-CUMbcc);
+               CUMcbc += O5 * (-CUMcbc);
+               CUMccb += O5 * (-CUMccb);
+
+               //6.
+               CUMccc += O6 * (-CUMccc);
+
+               //back cumulants to central moments
+               //4.
+               mfcbb = CUMcbb + ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               mfbcb = CUMbcb + ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               mfbbc = CUMbbc + ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac) * oMdrho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc) * oMdrho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) -c1o27*oMdrho;
+               
+               ////////////////////////////////////////////////////////////////////////////////////
+               //forcing
+               mfbaa=-mfbaa;
+               mfaba=-mfaba;
+               mfaab=-mfaab;
+               //////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa                * (1. - vz2)              - 1. * oMdrho * vz2;
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2;
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2);
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2;
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2);
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2;
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2);
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2;
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2);
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2;
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2);
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca                  * (1. - vz2)              - c1o9 * oMdrho * vz2;
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab                  * (1. - vy2)              - c2o3 * oMdrho * vy2;
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2;
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2);
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2);
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2);
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab                  * (1. - vy2)              - c2o9 * oMdrho * vy2;
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb                  * (1. - vx2)              - c4o9 * oMdrho * vx2;
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho="+UbSystem::toString(rho)+", rho_post="+UbSystem::toString(rho_post)
+                                       +" dif="+UbSystem::toString(dif)
+                                       +" rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27CCLB::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               if (x1 == maxX1m || x2 == maxX2m || x3 == maxX3m)
+               {
+                  setNewDistributions(x1p, x2, x3);
+                  (*this->localDistributions)(D3Q27System::ET_NW,lX1,lX2,lX3) = mfcab;
+                  (*this->localDistributions)(D3Q27System::ET_TW,lX1,lX2,lX3) = mfcba;
+                  (*this->localDistributions)(D3Q27System::ET_TNW,lX1,lX2,lX3) = mfcaa;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_W,lX1,lX2,lX3) = mfcbb;
+
+                  setNewDistributions(x1, x2p, x3);
+                  (*this->localDistributions)(D3Q27System::ET_TS,lX1,lX2,lX3) = mfbca;
+                  (*this->localDistributions)(D3Q27System::ET_TSE,lX1,lX2,lX3) = mfaca;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_S,lX1,lX2,lX3) = mfbcb;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_SE,lX1,lX2,lX3) = mfacb;
+
+                  setNewDistributions(x1p, x2p, x3);
+                  (*this->localDistributions)(D3Q27System::ET_TSW,lX1,lX2,lX3) = mfcca;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_SW,lX1,lX2,lX3) = mfccb;
+
+                  setNewDistributions(x1p, x2, x3p);
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BW,lX1,lX2,lX3) = mfcbc;  
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BNW,lX1,lX2,lX3) = mfcac;
+
+                  setNewDistributions(x1, x2, x3p);
+                  (*this->nonLocalDistributions)(D3Q27System::ET_B,lX1,lX2,lX3) = mfbbc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BE,lX1,lX2,lX3) = mfabc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BN,lX1,lX2,lX3) = mfbac;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BNE,lX1,lX2,lX3) = mfaac;
+
+                  setNewDistributions(x1, x2p, x3p);
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BS,lX1,lX2,lX3) = mfbcc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BSE,lX1,lX2,lX3) = mfacc;
+
+                  setNewDistributions(x1p, x2p, x3p);
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BSW,lX1,lX2,lX3) = mfccc;
+
+                  localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+                  nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+                  (*this->localDistributions)(D3Q27System::ET_E,x1,x2,x3) = mfabb;
+                  (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3) = mfbab;
+                  (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3) = mfbba;
+                  (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3) = mfaab;
+                  (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3) = mfaba;
+                  (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3) = mfbaa;
+                  (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3) = mfaaa;
+
+                  (*this->zeroDistributions)(x1,x2,x3) = mfbbb;
+               }
+               else
+               {
+                  //localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+                  //nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+                  (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3)    = mfabb;
+                  (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3)    = mfbab;
+                  (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3)    = mfbba;
+                  (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3)   = mfaab;
+                  (*this->localDistributions)(D3Q27System::ET_NW,x1p,x2,  x3)   = mfcab;
+                  (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3)   = mfaba;
+                  (*this->localDistributions)(D3Q27System::ET_TW,x1p,x2,  x3)   = mfcba;
+                  (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3)   = mfbaa;
+                  (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2p,x3)   = mfbca;
+                  (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3)  = mfaaa;
+                  (*this->localDistributions)(D3Q27System::ET_TNW,x1p,x2,  x3)  = mfcaa;
+                  (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2p,x3)  = mfaca;
+                  (*this->localDistributions)(D3Q27System::ET_TSW,x1p,x2p,x3)  = mfcca;
+
+                  (*this->nonLocalDistributions)(D3Q27System::ET_W,x1p,x2,  x3    ) = mfcbb;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2p,x3    ) = mfbcb;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3p  ) = mfbbc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1p,x2p,x3   ) = mfccb;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2p,x3   ) = mfacb;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1p,x2,  x3p ) = mfcbc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3p ) = mfabc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2p,x3p ) = mfbcc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3p ) = mfbac;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1p,x2p,x3p) = mfccc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2p,x3p) = mfacc;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1p,x2,  x3p) = mfcac;
+                  (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3p) = mfaac;
+
+                  (*this->zeroDistributions)(x1,x2,x3) = mfbbb;
+               }
+               //////////////////////////////////////////////////////////////////////////
+
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelETD3Q27CCLBex::getCallculationTime()
+{
+   //return timer.getDuration();
+   return timer.getTotalTime();
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex.h
new file mode 100644
index 0000000000000000000000000000000000000000..43778df2b5bc70ea4d314fd8446d63fb19caf016
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex.h
@@ -0,0 +1,74 @@
+//Cascaded Cumulant LBM
+
+#ifndef LBMKernelETD3Q27CCLBEX_H
+#define LBMKernelETD3Q27CCLBEX_H
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+#include "Grid3D.h"
+
+class LBMKernelETD3Q27CCLBex;
+typedef boost::shared_ptr<LBMKernelETD3Q27CCLBex> LBMKernelETD3Q27CCLBexPtr;
+
+
+class LBMKernelETD3Q27CCLBex :  public LBMKernelETD3Q27
+{
+public:
+   LBMKernelETD3Q27CCLBex();
+   LBMKernelETD3Q27CCLBex(int nx1, int nx2, int nx3, int option, Grid3DPtr grid);
+   ~LBMKernelETD3Q27CCLBex(void);
+   void calculate();
+   LBMKernel3DPtr clone();
+   double getCallculationTime();
+
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+      ar & OxyyMxzz; 
+   }
+
+   void collideAll();  
+   void init();
+   void setNewDistributions(int x1, int x2, int x3);
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal rho, vx, vy, vz, durchrho;
+   LBMReal w1,w2,w3,w4,w5,w6,w7,w8,w9,w10;
+   LBMReal s9,c1o27,c2o3;
+
+   LBMReal mu200, mu020, mu002,mu110, mu101,mu011,mu210,mu120,mu102,mu111, 
+      mu201,mu021,mu012,mu220,mu121,mu202,mu211,mu112,mu022,mu221,mu122,mu212,mu222,mu000,mu100,mu010,mu001;
+   LBMReal vx_sq, vy_sq, vz_sq, vx_vy, vx_vz, vy_vz, vx_vy_vz;
+
+   UbTimer timer;
+
+   LBMReal OxyyMxzz;
+   int option;
+
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributions;
+
+   mu::value_type muX1,muX2,muX3;
+   mu::value_type muDeltaT;
+   mu::value_type muNue;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+   Grid3DPtr grid;
+   int lX1, lX2, lX3;
+   int bX1;
+   int bX2;
+   int bX3;
+   int level;
+   UbTupleInt3 blockNX;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex2.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..53754250c6cbead476416dacde9e0cbee8649c61
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex2.cpp
@@ -0,0 +1,1079 @@
+#include "LBMKernelETD3Q27CCLBex2.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+
+#include <math.h>
+
+#define PROOF_CORRECTNESS
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBex2::LBMKernelETD3Q27CCLBex2()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBex2::LBMKernelETD3Q27CCLBex2(int nx1, int nx2, int nx3, int option, Grid3DPtr grid) 
+   : LBMKernelETD3Q27(nx1, nx2, nx3),
+     option(option),
+     grid(grid)
+{
+   this->compressible = false;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CCLBex2::~LBMKernelETD3Q27CCLBex2(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBex2::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   int tnx1=nx1;
+   int tnx2=nx2;
+   int tnx3=nx3;
+   bX1=block.lock()->getX1();
+   bX2=block.lock()->getX2();
+   bX3=block.lock()->getX3();
+   level = block.lock()->getLevel();
+   if(!grid->getBlock(bX1+1,bX2,bX3,level) && !grid->isPeriodicX1()) tnx1++;
+   if(!grid->getBlock(bX1,bX2+1,bX3,level) && !grid->isPeriodicX2()) tnx2++;
+   if(!grid->getBlock(bX1,bX2,bX3+1,level) && !grid->isPeriodicX3()) tnx3++;
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSoA(tnx1, tnx2, tnx3, 0.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27CCLBex2::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27CCLBex2(nx1, nx2, nx3, option, grid));
+   kernel->setBlock(this->getBlock());
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBex2>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   if (option == 0)
+   {
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBex2>(kernel)->OxyyMxzz = 1.0;
+   }
+   else if (option == 1)
+   {
+      boost::dynamic_pointer_cast<LBMKernelETD3Q27CCLBex2>(kernel)->OxyyMxzz = 2.0 +(-collFactor);
+   }
+   
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBex2::calculate()
+{
+   timer.resetAndStart();
+   collideAll();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBex2::setNewDistributions(int x1, int x2, int x3)
+{
+   int gX1 = bX1 * nx1 + x1-1;
+   int gX2 = bX2 * nx2 + x2-1;
+   int gX3 = bX3 * nx3 + x3-1;
+
+   int nbX1 = (gX1 + 1) / nx1;
+   int nbX2 = (gX2 + 1) / nx2;
+   int nbX3 = (gX3 + 1) / nx3;
+
+   lX1 = (gX1 + 1) - nbX1 * nx1;
+   lX2 = (gX2 + 1) - nbX2 * nx2;
+   lX3 = (gX3 + 1) - nbX3 * nx3;
+
+   Block3DPtr nblock = grid->getBlock(nbX1,nbX2,nbX3,level);
+
+   if (nblock)
+   {
+      d = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSoA>(nblock->getKernel()->getDataSet()->getFdistributions())->getDistributions();
+   }
+   else
+   {
+      d = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSoA>(dataSet->getFdistributions())->getDistributions();
+      lX1 = x1;
+      lX2 = x2;
+      lX3 = x3;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CCLBex2::collideAll()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dx",&muDeltaT);
+      muForcingX2.DefineVar("dx",&muDeltaT);
+      muForcingX3.DefineVar("dx",&muDeltaT);
+
+      muNue = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nue",&muNue);
+      muForcingX2.DefineVar("nue",&muNue);
+      muForcingX3.DefineVar("nue",&muNue);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   s9 = - collFactor;
+   c1o27=1.0/27.0;
+   c2o3=2.0/3.0;
+   w2=-1.0; //MXXpMYYpMZZ bulk viscosity
+   w7=-1.0;//s9; //ORDER 4 Isotropic
+   w9=-1.0;
+   w10=-1.0;//s9;//-1.0; // ORDER 6 Isotropic
+   w1=s9;
+   // wenn es mal an den Ecken nicht gut aussieht -2.0-s9 probieren
+   w3=-1.0;//-2.0-s9;//-1.0;//MXXYpMYZZ
+   w4=-1.0;//-2.0-s9;//-1.0;//MXXYmMYZZ
+   w5=-1.0;//-2.0-s9;//-1.0;//MYXZ
+   w6=-1.0; //MXXYYpm2p
+   w8=-1.0; //M_zXXYZ 
+
+
+   d = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSoA>(dataSet->getFdistributions())->getDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+
+   int minX1 = 0; //ghostLayerWidth;
+   int minX2 = 0; //ghostLayerWidth;
+   int minX3 = 0; //ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1; //-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2; //-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3; //-ghostLayerWidth;
+
+   int maxX1m = bcArrayMaxX1-1;
+   int maxX2m = bcArrayMaxX2-1;
+   int maxX3m = bcArrayMaxX3-1;
+
+   LBMReal mfaaa;
+   LBMReal mfaab;
+   LBMReal mfaac;
+   LBMReal mfaba;
+   LBMReal mfabb;
+   LBMReal mfabc;
+   LBMReal mfbaa;
+   LBMReal mfbab;
+   LBMReal mfbac;
+   LBMReal mfbba;
+   LBMReal mfbbb;
+   LBMReal mfbbc;
+   LBMReal mfaca;
+   LBMReal mfacb;
+   LBMReal mfacc;
+   LBMReal mfcaa;
+   LBMReal mfcab;
+   LBMReal mfcac;
+   LBMReal mfcca;
+   LBMReal mfccb;
+   LBMReal mfccc;
+   LBMReal mfbca;
+   LBMReal mfbcb;
+   LBMReal mfbcc;
+   LBMReal mfcba;
+   LBMReal mfcbb;
+   LBMReal mfcbc;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               //E   N  T
+               //c   c  c
+               //////////
+               //W   S  B
+               //a   a  a
+
+               //Rest ist b
+               //////////////////////////////////////////////////////////////////////////
+               int x1p = x1 + 1;
+               int x2p = x2 + 1;
+               int x3p = x3 + 1;
+               if (x1 == maxX1m || x2 == maxX2m || x3 == maxX3m)
+               {
+                  setNewDistributions(x1p, x2p, x3p);
+                  mfaaa = (*d.BSW)(lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1p, x2p, x3);
+                  mfaab = (*d.SW)(lX1,lX2,lX3);
+                  mfaac = (*d.TSW)(lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1p, x2, x3p);
+                  mfaba = (*d.BW)(lX1,lX2,lX3);
+                  mfaca = (*d.BNW)(lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1p, x2, x3);
+                  mfabb = (*d.W)(lX1,lX2,lX3);
+                  mfabc = (*d.TW)(lX1,lX2,lX3);
+                  mfacb = (*d.NW)(lX1,lX2,lX3);
+                  mfacc = (*d.TNW)(lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1, x2p, x3p);
+                  mfbaa = (*d.BS)(lX1,lX2,lX3);
+                  mfcaa = (*d.BSE)(lX1,lX2,lX3);
+                  
+                  setNewDistributions(x1, x2p, x3);
+                  mfbab = (*d.S)(lX1,lX2,lX3);
+                  mfbac = (*d.TS)(lX1,lX2,lX3);
+                  mfcac = (*d.TSE)(lX1,lX2,lX3);
+                  mfcab = (*d.SE)(lX1,lX2,lX3);
+
+                  setNewDistributions(x1, x2, x3p);
+                  mfbba = (*d.B)(lX1,lX2,lX3);
+                  mfcca = (*d.BNE)(lX1,lX2,lX3);
+                  mfbca = (*d.BN)(lX1,lX2,lX3);
+                  mfcba = (*d.BE)(lX1,lX2,lX3);
+
+                  d = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSoA>(dataSet->getFdistributions())->getDistributions();
+                  mfbbc = (*d.T)(x1,x2,x3);
+                  mfccb = (*d.NE)(x1,x2,x3);
+                  mfccc = (*d.TNE)(x1,x2,x3);
+                  mfbcb = (*d.N)(x1,x2,x3); 
+                  mfbcc = (*d.TN)(x1,x2,x3);
+                  mfcbb = (*d.E)(x1,x2,x3);
+                  mfcbc = (*d.TE)(x1,x2,x3);
+                  mfbbb = (*d.ZERO)(x1,x2,x3);
+               }
+               else
+               {
+                  //d = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSoA>(dataSet->getFdistributions())->getDistributions();
+                  mfaaa = (*d.BSW)(x1p,x2p,x3p); 
+                  mfaab = (*d.SW)(x1p,x2p,x3 );
+                  mfaac = (*d.TSW)(x1p,x2p,x3);
+                  mfaba = (*d.BW)(x1p,x2,x3p );
+                  mfabb = (*d.W)(x1p,x2,x3  );
+                  mfabc = (*d.TW)(x1p,x2,x3);
+                  mfbaa = (*d.BS)(x1,x2p,x3p );
+                  mfbab = (*d.S)(x1,x2p,x3  );
+                  mfbac = (*d.TS)(x1,x2p,x3);
+                  mfbba = (*d.B)(x1,x2,x3p  );
+                  mfbbb = (*d.ZERO)(x1,x2,x3);
+                  mfbbc = (*d.T)(x1,x2,x3);
+                  mfaca = (*d.BNW)(x1p,x2,x3p);
+                  mfacb = (*d.NW)(x1p,x2,x3);
+                  mfacc = (*d.TNW)(x1p,x2,x3);
+                  mfcaa = (*d.BSE)(x1,x2p,x3p);
+                  mfcab = (*d.SE)(x1,x2p,x3 );
+                  mfcac = (*d.TSE)(x1,x2p,x3);
+                  mfcca = (*d.BNE)(x1,x2,x3p);
+                  mfccb = (*d.NE)(x1,x2,x3);
+                  mfccc = (*d.TNE)(x1,x2,x3);
+                  mfbca = (*d.BN)(x1,x2,x3p );
+                  mfbcb = (*d.N)(x1,x2,x3); 
+                  mfbcc = (*d.TN)(x1,x2,x3);
+                  mfcba = (*d.BE)(x1,x2,x3p );
+                  mfcbb = (*d.E)(x1,x2,x3);
+                  mfcbc = (*d.TE)(x1,x2,x3);
+               }
+               LBMReal m0, m1, m2;
+
+
+               LBMReal rho=(mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb;
+
+               LBMReal vvx    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfcaa-mfacc) + (mfcca-mfaac))) +
+                  (((mfcba-mfabc) + (mfcbc-mfaba)) + ((mfcab-mfacb) + (mfccb-mfaab))) +
+                  (mfcbb-mfabb));
+               LBMReal vvy    =((((mfccc-mfaaa) + (mfaca-mfcac)) + ((mfacc-mfcaa) + (mfcca-mfaac))) +
+                  (((mfbca-mfbac) + (mfbcc-mfbaa)) + ((mfacb-mfcab) + (mfccb-mfaab))) +
+                  (mfbcb-mfbab));
+               LBMReal vvz    =((((mfccc-mfaaa) + (mfcac-mfaca)) + ((mfacc-mfcaa) + (mfaac-mfcca))) +
+                  (((mfbac-mfbca) + (mfbcc-mfbaa)) + ((mfabc-mfcba) + (mfcbc-mfaba))) +
+                  (mfbbc-mfbba));
+
+               //forcing 
+               ///////////////////////////////////////////////////////////////////////////////////////////
+               if (withForcing)
+               {
+                  muX1 = static_cast<double>(x1+ix1*bcArrayMaxX1);
+                  muX2 = static_cast<double>(x2+ix2*bcArrayMaxX2);
+                  muX3 = static_cast<double>(x3+ix3*bcArrayMaxX3);
+
+                  forcingX1 = muForcingX1.Eval();
+                  forcingX2 = muForcingX2.Eval();
+                  forcingX3 = muForcingX3.Eval();
+
+                  vvx += forcingX1*0.5; // X
+                  vvy += forcingX2*0.5; // Y
+                  vvz += forcingX3*0.5; // Z
+               }
+               ///////////////////////////////////////////////////////////////////////////////////////////               
+
+               LBMReal oMdrho;
+               {
+                  oMdrho=mfccc+mfaaa;
+                  m0=mfaca+mfcac;
+                  m1=mfacc+mfcaa;
+                  m2=mfaac+mfcca;
+                  oMdrho+=m0;
+                  m1+=m2;
+                  oMdrho+=m1;
+                  m0=mfbac+mfbca;
+                  m1=mfbaa+mfbcc;
+                  m0+=m1;
+                  m1=mfabc+mfcba;
+                  m2=mfaba+mfcbc;
+                  m1+=m2;
+                  m0+=m1;
+                  m1=mfacb+mfcab;
+                  m2=mfaab+mfccb;
+                  m1+=m2;
+                  m0+=m1;
+                  oMdrho+=m0;
+                  m0=mfabb+mfcbb;
+                  m1=mfbab+mfbcb;
+                  m2=mfbba+mfbbc;
+                  m0+=m1+m2;
+                  m0+=mfbbb; //hat gefehlt
+                  oMdrho = 1. - (oMdrho + m0);
+               }
+               LBMReal vx2;
+               LBMReal vy2;
+               LBMReal vz2;
+
+               vx2=vvx*vvx;
+               vy2=vvy*vvy;
+               vz2=vvz*vvz;
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal wadjust;
+               LBMReal qudricLimit = 0.01;
+               //LBMReal s9 = minusomega;
+               //test
+               //s9 = 0.;
+               ////////////////////////////////////////////////////////////////////////////////////
+               //Hin
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36  Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m2    = mfaaa + mfaac;
+               m1    = mfaac - mfaaa;
+               m0    = m2          + mfaab;
+               mfaaa = m0;
+               m0   += c1o36 * oMdrho;   
+               mfaab = m1 -        m0 * vvz;
+               mfaac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfabc;
+               m1    = mfabc  - mfaba;
+               m0    = m2          + mfabb;
+               mfaba = m0;
+               m0   += c1o9 * oMdrho;
+               mfabb = m1 -        m0 * vvz;
+               mfabc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfacc;
+               m1    = mfacc  - mfaca;
+               m0    = m2          + mfacb;
+               mfaca = m0;
+               m0   += c1o36 * oMdrho;
+               mfacb = m1 -        m0 * vvz;
+               mfacc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbac;
+               m1    = mfbac - mfbaa;
+               m0    = m2          + mfbab;
+               mfbaa = m0;
+               m0   += c1o9 * oMdrho;
+               mfbab = m1 -        m0 * vvz;
+               mfbac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbba  + mfbbc;
+               m1    = mfbbc  - mfbba;
+               m0    = m2          + mfbbb;
+               mfbba = m0;
+               m0   += c4o9 * oMdrho;
+               mfbbb = m1 -        m0 * vvz;
+               mfbbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbca  + mfbcc;
+               m1    = mfbcc  - mfbca;
+               m0    = m2          + mfbcb;
+               mfbca = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcb = m1 -        m0 * vvz;
+               mfbcc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcac;
+               m1    = mfcac - mfcaa;
+               m0    = m2          + mfcab;
+               mfcaa = m0;
+               m0   += c1o36 * oMdrho;
+               mfcab = m1 -        m0 * vvz;
+               mfcac = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcba  + mfcbc;
+               m1    = mfcbc  - mfcba;
+               m0    = m2          + mfcbb;
+               mfcba = m0;
+               m0   += c1o9 * oMdrho;
+               mfcbb = m1 -        m0 * vvz;
+               mfcbc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcca  + mfccc;
+               m1    = mfccc  - mfcca;
+               m0    = m2          + mfccb;
+               mfcca = m0;
+               m0   += c1o36 * oMdrho;
+               mfccb = m1 -        m0 * vvz;
+               mfccc = m2 - 2. *   m1 * vvz + vz2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit  1/6, 0, 1/18, 2/3, 0, 2/9, 1/6, 0, 1/18 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m2    = mfaaa + mfaca;
+               m1    = mfaca - mfaaa;
+               m0    = m2          + mfaba;
+               mfaaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfaba = m1 -        m0 * vvy;
+               mfaca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab  + mfacb;
+               m1    = mfacb  - mfaab;
+               m0    = m2          + mfabb;
+               mfaab = m0;
+               mfabb = m1 -        m0 * vvy;
+               mfacb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac  + mfacc;
+               m1    = mfacc  - mfaac;
+               m0    = m2          + mfabc;
+               mfaac = m0;
+               m0   += c1o18 * oMdrho;
+               mfabc = m1 -        m0 * vvy;
+               mfacc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbaa + mfbca;
+               m1    = mfbca - mfbaa;
+               m0    = m2          + mfbba;
+               mfbaa = m0;
+               m0   += c2o3 * oMdrho;
+               mfbba = m1 -        m0 * vvy;
+               mfbca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbab  + mfbcb;
+               m1    = mfbcb  - mfbab;
+               m0    = m2          + mfbbb;
+               mfbab = m0;
+               mfbbb = m1 -        m0 * vvy;
+               mfbcb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfbac  + mfbcc;
+               m1    = mfbcc  - mfbac;
+               m0    = m2          + mfbbc;
+               mfbac = m0;
+               m0   += c2o9 * oMdrho;
+               mfbbc = m1 -        m0 * vvy;
+               mfbcc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcaa + mfcca;
+               m1    = mfcca - mfcaa;
+               m0    = m2          + mfcba;
+               mfcaa = m0;
+               m0   += c1o6 * oMdrho;
+               mfcba = m1 -        m0 * vvy;
+               mfcca = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcab  + mfccb;
+               m1    = mfccb  - mfcab;
+               m0    = m2          + mfcbb;
+               mfcab = m0;
+               mfcbb = m1 -        m0 * vvy;
+               mfccb = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfcac  + mfccc;
+               m1    = mfccc  - mfcac;
+               m0    = m2          + mfcbc;
+               mfcac = m0;
+               m0   += c1o18 * oMdrho;
+               mfcbc = m1 -        m0 * vvy;
+               mfccc = m2 - 2. *   m1 * vvy + vy2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               // mit     1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9            Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m2    = mfaaa + mfcaa;
+               m1    = mfcaa - mfaaa;
+               m0    = m2          + mfbaa;
+               mfaaa = m0;
+               m0   += 1. * oMdrho;
+               mfbaa = m1 -        m0 * vvx;
+               mfcaa = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaba  + mfcba;
+               m1    = mfcba  - mfaba;
+               m0    = m2          + mfbba;
+               mfaba = m0;
+               mfbba = m1 -        m0 * vvx;
+               mfcba = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaca  + mfcca;
+               m1    = mfcca  - mfaca;
+               m0    = m2          + mfbca;
+               mfaca = m0;
+               m0   += c1o3 * oMdrho;
+               mfbca = m1 -        m0 * vvx;
+               mfcca = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaab + mfcab;
+               m1    = mfcab - mfaab;
+               m0    = m2          + mfbab;
+               mfaab = m0;
+               mfbab = m1 -        m0 * vvx;
+               mfcab = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabb  + mfcbb;
+               m1    = mfcbb  - mfabb;
+               m0    = m2          + mfbbb;
+               mfabb = m0;
+               mfbbb = m1 -        m0 * vvx;
+               mfcbb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacb  + mfccb;
+               m1    = mfccb  - mfacb;
+               m0    = m2          + mfbcb;
+               mfacb = m0;
+               mfbcb = m1 -        m0 * vvx;
+               mfccb = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfaac + mfcac;
+               m1    = mfcac - mfaac;
+               m0    = m2          + mfbac;
+               mfaac = m0;
+               m0   += c1o3 * oMdrho;
+               mfbac = m1 -        m0 * vvx;
+               mfcac = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfabc  + mfcbc;
+               m1    = mfcbc  - mfabc;
+               m0    = m2          + mfbbc;
+               mfabc = m0;
+               mfbbc = m1 -        m0 * vvx;
+               mfcbc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m2    = mfacc  + mfccc;
+               m1    = mfccc  - mfacc;
+               m0    = m2          + mfbcc;
+               mfacc = m0;
+               m0   += c1o9 * oMdrho;
+               mfbcc = m1 -        m0 * vvx;
+               mfccc = m2 - 2. *   m1 * vvx + vx2 * m0;
+               ////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Cumulants
+               ////////////////////////////////////////////////////////////////////////////////////
+               LBMReal OxxPyyPzz = 1.;
+               LBMReal OxyyPxzz  = 1.;//-s9;//2+s9;//
+               //LBMReal OxyyMxzz  = 1.;//2+s9;//
+               LBMReal O4        = 1.;
+               LBMReal O5        = 1.;
+               LBMReal O6        = 1.;
+
+               //Cum 4.
+               LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               LBMReal CUMbcb = mfbcb - ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               LBMReal CUMbbc = mfbbc - ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               LBMReal CUMcca = mfcca - (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMcac = mfcac - (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               LBMReal CUMacc = mfacc - (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //Cum 5.
+               LBMReal CUMbcc = (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) - c1o3 * (mfbca + mfbac) * oMdrho;
+               LBMReal CUMcbc = (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) - c1o3 * (mfcba + mfabc) * oMdrho;
+               LBMReal CUMccb = (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) - c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //Cum 6.
+               LBMReal CUMccc = mfccc  +((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) +c1o27*oMdrho;
+
+               //2.
+               // linear combinations
+               LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac;
+               LBMReal mxxMyy    = mfcaa - mfaca;
+               LBMReal mxxMzz         = mfcaa - mfaac;
+
+               {
+                  LBMReal dxux = c1o2 * (s9 *(mxxMyy + mxxMzz) + (mfaaa - mxxPyyPzz));
+                  LBMReal dyuy = dxux - s9 * c3o2 * mxxMyy;
+                  LBMReal dzuz = dxux - s9 * c3o2 * mxxMzz;
+
+                  //relax
+                  mxxPyyPzz += OxxPyyPzz*(mfaaa  - mxxPyyPzz)- 3. * (1. - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+                  mxxMyy    += -s9 * (-mxxMyy) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vy2 * dyuy);
+                  mxxMzz    += -s9 * (-mxxMzz) - 3. * (1. + c1o2 * s9) * (vx2 * dxux + vz2 * dzuz);
+               }
+               mfabb     += -s9 * (-mfabb);
+               mfbab     += -s9 * (-mfbab);
+               mfbba     += -s9 * (-mfbba);
+
+               // linear combinations back
+               mfcaa = c1o3 * (       mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaca = c1o3 * (-2. *  mxxMyy +      mxxMzz + mxxPyyPzz);
+               mfaac = c1o3 * (       mxxMyy - 2. * mxxMzz + mxxPyyPzz);
+
+               //3.
+               // linear combinations
+               LBMReal mxxyPyzz = mfcba + mfabc;
+               LBMReal mxxyMyzz = mfcba - mfabc;
+
+               LBMReal mxxzPyyz = mfcab + mfacb;
+               LBMReal mxxzMyyz = mfcab - mfacb;
+
+               LBMReal mxyyPxzz = mfbca + mfbac;
+               LBMReal mxyyMxzz = mfbca - mfbac;
+
+               //relax
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mfbbb)/(fabs(mfbbb)+qudricLimit);
+               mfbbb     += wadjust * (-mfbbb);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxyPyzz)/(fabs(mxxyPyzz)+qudricLimit);
+               mxxyPyzz  += wadjust * (-mxxyPyzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxyMyzz)/(fabs(mxxyMyzz)+qudricLimit);
+               mxxyMyzz  += wadjust * (-mxxyMyzz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxxzPyyz)/(fabs(mxxzPyyz)+qudricLimit);
+               mxxzPyyz  += wadjust * (-mxxzPyyz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxxzMyyz)/(fabs(mxxzMyyz)+qudricLimit);
+               mxxzMyyz  += wadjust * (-mxxzMyyz);
+               wadjust    = OxyyPxzz+(1.-OxyyPxzz)*fabs(mxyyPxzz)/(fabs(mxyyPxzz)+qudricLimit);
+               mxyyPxzz  += wadjust * (-mxyyPxzz);
+               wadjust    = OxyyMxzz+(1.-OxyyMxzz)*fabs(mxyyMxzz)/(fabs(mxyyMxzz)+qudricLimit);
+               mxyyMxzz  += wadjust * (-mxyyMxzz);
+
+               // linear combinations back
+               mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+               mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+               mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+               mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+               mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+               mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+               //4.
+               CUMacc += O4 * (-CUMacc);
+               CUMcac += O4 * (-CUMcac);
+               CUMcca += O4 * (-CUMcca);
+
+               CUMbbc += O4 * (-CUMbbc);
+               CUMbcb += O4 * (-CUMbcb);
+               CUMcbb += O4 * (-CUMcbb);
+
+               //5.
+               CUMbcc += O5 * (-CUMbcc);
+               CUMcbc += O5 * (-CUMcbc);
+               CUMccb += O5 * (-CUMccb);
+
+               //6.
+               CUMccc += O6 * (-CUMccc);
+
+               //back cumulants to central moments
+               //4.
+               mfcbb = CUMcbb + ((mfcaa + c1o3 * oMdrho) * mfabb + 2. * mfbba * mfbab);
+               mfbcb = CUMbcb + ((mfaca + c1o3 * oMdrho) * mfbab + 2. * mfbba * mfabb);
+               mfbbc = CUMbbc + ((mfaac + c1o3 * oMdrho) * mfbba + 2. * mfbab * mfabb);
+
+               mfcca = CUMcca + (mfcaa * mfaca + 2. * mfbba * mfbba) + c1o3 * (mfcaa + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfcac = CUMcac + (mfcaa * mfaac + 2. * mfbab * mfbab) + c1o3 * (mfcaa + mfaac) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+               mfacc = CUMacc + (mfaac * mfaca + 2. * mfabb * mfabb) + c1o3 * (mfaac + mfaca) * oMdrho + c1o9*(oMdrho-1)*oMdrho;
+
+               //5.
+               mfbcc = CUMbcc + (mfaac * mfbca + mfaca * mfbac + 4. * mfabb * mfbbb + 2. * (mfbab * mfacb + mfbba * mfabc)) + c1o3 * (mfbca + mfbac) * oMdrho;
+               mfcbc = CUMcbc + (mfaac * mfcba + mfcaa * mfabc + 4. * mfbab * mfbbb + 2. * (mfabb * mfcab + mfbba * mfbac)) + c1o3 * (mfcba + mfabc) * oMdrho;
+               mfccb = CUMccb + (mfcaa * mfacb + mfaca * mfcab + 4. * mfbba * mfbbb + 2. * (mfbab * mfbca + mfabb * mfcba)) + c1o3 * (mfacb + mfcab) * oMdrho;
+
+               //6.
+               mfccc = CUMccc  -((-4. *  mfbbb * mfbbb 
+                  -       (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+                  -  4. * (mfabb * mfcbb + mfbac * mfbca + mfbba * mfbbc)
+                  -  2. * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb))
+                  +( 4. * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                  +  2. * (mfcaa * mfaca * mfaac)
+                  + 16. *  mfbba * mfbab * mfabb)
+                  - c1o3* (mfacc + mfcac + mfcca) * oMdrho  -c1o9*oMdrho*oMdrho
+                  - c1o9* (mfcaa + mfaca + mfaac) * oMdrho*(1.-2.* oMdrho)- c1o27* oMdrho * oMdrho*(-2.* oMdrho)
+                  +( 2. * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                  +       (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa)) * c2o3*oMdrho) -c1o27*oMdrho;
+               
+               ////////////////////////////////////////////////////////////////////////////////////
+               //forcing
+               mfbaa=-mfbaa;
+               mfaba=-mfaba;
+               mfaab=-mfaab;
+               //////////////////////////////////////////////////////////////////////////////////////
+
+               ////////////////////////////////////////////////////////////////////////////////////
+               //back
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Z - Dir
+               m0 =  mfaac * c1o2 +      mfaab * (vvz - c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfaac        - 2. * mfaab *  vvz         +  mfaaa                * (1. - vz2)              - 1. * oMdrho * vz2;
+               m2 =  mfaac * c1o2 +      mfaab * (vvz + c1o2) + (mfaaa + 1. * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaaa = m0;
+               mfaab = m1;
+               mfaac = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfabc * c1o2 +      mfabb * (vvz - c1o2) + mfaba * (     vz2 - vvz) * c1o2;
+               m1 = -mfabc        - 2. * mfabb *  vvz         + mfaba * (1. - vz2);
+               m2 =  mfabc * c1o2 +      mfabb * (vvz + c1o2) + mfaba * (     vz2 + vvz) * c1o2;
+               mfaba = m0;
+               mfabb = m1;
+               mfabc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfacb * (vvz - c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfacc        - 2. * mfacb *  vvz         +  mfaca                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfacc * c1o2 +      mfacb * (vvz + c1o2) + (mfaca + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfaca = m0;
+               mfacb = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbac * c1o2 +      mfbab * (vvz - c1o2) + mfbaa * (     vz2 - vvz) * c1o2;
+               m1 = -mfbac        - 2. * mfbab *  vvz         + mfbaa * (1. - vz2);
+               m2 =  mfbac * c1o2 +      mfbab * (vvz + c1o2) + mfbaa * (     vz2 + vvz) * c1o2;
+               mfbaa = m0;
+               mfbab = m1;
+               mfbac = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbbc * c1o2 +      mfbbb * (vvz - c1o2) + mfbba * (     vz2 - vvz) * c1o2;
+               m1 = -mfbbc        - 2. * mfbbb *  vvz         + mfbba * (1. - vz2);
+               m2 =  mfbbc * c1o2 +      mfbbb * (vvz + c1o2) + mfbba * (     vz2 + vvz) * c1o2;
+               mfbba = m0;
+               mfbbb = m1;
+               mfbbc = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbcb * (vvz - c1o2) + mfbca * (     vz2 - vvz) * c1o2;
+               m1 = -mfbcc        - 2. * mfbcb *  vvz         + mfbca * (1. - vz2);
+               m2 =  mfbcc * c1o2 +      mfbcb * (vvz + c1o2) + mfbca * (     vz2 + vvz) * c1o2;
+               mfbca = m0;
+               mfbcb = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfcab * (vvz - c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfcac        - 2. * mfcab *  vvz         +  mfcaa                  * (1. - vz2)              - c1o3 * oMdrho * vz2;
+               m2 =  mfcac * c1o2 +      mfcab * (vvz + c1o2) + (mfcaa + c1o3 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcaa = m0;
+               mfcab = m1;
+               mfcac = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfcbb * (vvz - c1o2) + mfcba * (     vz2 - vvz) * c1o2;
+               m1 = -mfcbc        - 2. * mfcbb *  vvz         + mfcba * (1. - vz2);
+               m2 =  mfcbc * c1o2 +      mfcbb * (vvz + c1o2) + mfcba * (     vz2 + vvz) * c1o2;
+               mfcba = m0;
+               mfcbb = m1;
+               mfcbc = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfccb * (vvz - c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 - vvz) * c1o2;
+               m1 = -mfccc        - 2. * mfccb *  vvz         +  mfcca                  * (1. - vz2)              - c1o9 * oMdrho * vz2;
+               m2 =  mfccc * c1o2 +      mfccb * (vvz + c1o2) + (mfcca + c1o9 * oMdrho) * (     vz2 + vvz) * c1o2;
+               mfcca = m0;
+               mfccb = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // Y - Dir
+               m0 =  mfaca * c1o2 +      mfaba * (vvy - c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfaca        - 2. * mfaba *  vvy         +  mfaaa                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfaca * c1o2 +      mfaba * (vvy + c1o2) + (mfaaa + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaaa = m0;
+               mfaba = m1;
+               mfaca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacb * c1o2 +      mfabb * (vvy - c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacb        - 2. * mfabb *  vvy         +  mfaab                  * (1. - vy2)              - c2o3 * oMdrho * vy2;
+               m2 =  mfacb * c1o2 +      mfabb * (vvy + c1o2) + (mfaab + c2o3 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaab = m0;
+               mfabb = m1;
+               mfacb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfacc * c1o2 +      mfabc * (vvy - c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfacc        - 2. * mfabc *  vvy         +  mfaac                  * (1. - vy2)              - c1o6 * oMdrho * vy2;
+               m2 =  mfacc * c1o2 +      mfabc * (vvy + c1o2) + (mfaac + c1o6 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfaac = m0;
+               mfabc = m1;
+               mfacc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfbca * c1o2 +      mfbba * (vvy - c1o2) + mfbaa * (     vy2 - vvy) * c1o2;
+               m1 = -mfbca        - 2. * mfbba *  vvy         + mfbaa * (1. - vy2);
+               m2 =  mfbca * c1o2 +      mfbba * (vvy + c1o2) + mfbaa * (     vy2 + vvy) * c1o2;
+               mfbaa = m0;
+               mfbba = m1;
+               mfbca = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcb * c1o2 +      mfbbb * (vvy - c1o2) + mfbab * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcb        - 2. * mfbbb *  vvy         + mfbab * (1. - vy2);
+               m2 =  mfbcb * c1o2 +      mfbbb * (vvy + c1o2) + mfbab * (     vy2 + vvy) * c1o2;
+               mfbab = m0;
+               mfbbb = m1;
+               mfbcb = m2;
+               /////////b//////////////////////////////////////////////////////////////////////////
+               m0 =  mfbcc * c1o2 +      mfbbc * (vvy - c1o2) + mfbac * (     vy2 - vvy) * c1o2;
+               m1 = -mfbcc        - 2. * mfbbc *  vvy         + mfbac * (1. - vy2);
+               m2 =  mfbcc * c1o2 +      mfbbc * (vvy + c1o2) + mfbac * (     vy2 + vvy) * c1o2;
+               mfbac = m0;
+               mfbbc = m1;
+               mfbcc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfcba * (vvy - c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfcca        - 2. * mfcba *  vvy         +  mfcaa                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfcca * c1o2 +      mfcba * (vvy + c1o2) + (mfcaa + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcaa = m0;
+               mfcba = m1;
+               mfcca = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfcbb * (vvy - c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccb        - 2. * mfcbb *  vvy         +  mfcab                  * (1. - vy2)              - c2o9 * oMdrho * vy2;
+               m2 =  mfccb * c1o2 +      mfcbb * (vvy + c1o2) + (mfcab + c2o9 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcab = m0;
+               mfcbb = m1;
+               mfccb = m2;
+               /////////c//////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfcbc * (vvy - c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 - vvy) * c1o2;
+               m1 = -mfccc        - 2. * mfcbc *  vvy         +  mfcac                   * (1. - vy2)              - c1o18 * oMdrho * vy2;
+               m2 =  mfccc * c1o2 +      mfcbc * (vvy + c1o2) + (mfcac + c1o18 * oMdrho) * (     vy2 + vvy) * c1o2;
+               mfcac = m0;
+               mfcbc = m1;
+               mfccc = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
+               ////////////////////////////////////////////////////////////////////////////////////
+               // X - Dir
+               m0 =  mfcaa * c1o2 +      mfbaa * (vvx - c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcaa        - 2. * mfbaa *  vvx         +  mfaaa                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcaa * c1o2 +      mfbaa * (vvx + c1o2) + (mfaaa + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaaa = m0;
+               mfbaa = m1;
+               mfcaa = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcba * c1o2 +      mfbba * (vvx - c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcba        - 2. * mfbba *  vvx         +  mfaba                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcba * c1o2 +      mfbba * (vvx + c1o2) + (mfaba + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaba = m0;
+               mfbba = m1;
+               mfcba = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcca * c1o2 +      mfbca * (vvx - c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcca        - 2. * mfbca *  vvx         +  mfaca                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcca * c1o2 +      mfbca * (vvx + c1o2) + (mfaca + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaca = m0;
+               mfbca = m1;
+               mfcca = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcab * c1o2 +      mfbab * (vvx - c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcab        - 2. * mfbab *  vvx         +  mfaab                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcab * c1o2 +      mfbab * (vvx + c1o2) + (mfaab + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaab = m0;
+               mfbab = m1;
+               mfcab = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbb * c1o2 +      mfbbb * (vvx - c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbb        - 2. * mfbbb *  vvx         +  mfabb                  * (1. - vx2)              - c4o9 * oMdrho * vx2;
+               m2 =  mfcbb * c1o2 +      mfbbb * (vvx + c1o2) + (mfabb + c4o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabb = m0;
+               mfbbb = m1;
+               mfcbb = m2;
+               ///////////b////////////////////////////////////////////////////////////////////////
+               m0 =  mfccb * c1o2 +      mfbcb * (vvx - c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccb        - 2. * mfbcb *  vvx         +  mfacb                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfccb * c1o2 +      mfbcb * (vvx + c1o2) + (mfacb + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacb = m0;
+               mfbcb = m1;
+               mfccb = m2;
+               ////////////////////////////////////////////////////////////////////////////////////
+               ////////////////////////////////////////////////////////////////////////////////////
+               m0 =  mfcac * c1o2 +      mfbac * (vvx - c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcac        - 2. * mfbac *  vvx         +  mfaac                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfcac * c1o2 +      mfbac * (vvx + c1o2) + (mfaac + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfaac = m0;
+               mfbac = m1;
+               mfcac = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfcbc * c1o2 +      mfbbc * (vvx - c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfcbc        - 2. * mfbbc *  vvx         +  mfabc                  * (1. - vx2)              - c1o9 * oMdrho * vx2;
+               m2 =  mfcbc * c1o2 +      mfbbc * (vvx + c1o2) + (mfabc + c1o9 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfabc = m0;
+               mfbbc = m1;
+               mfcbc = m2;
+               ///////////c////////////////////////////////////////////////////////////////////////
+               m0 =  mfccc * c1o2 +      mfbcc * (vvx - c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 - vvx) * c1o2;
+               m1 = -mfccc        - 2. * mfbcc *  vvx         +  mfacc                   * (1. - vx2)              - c1o36 * oMdrho * vx2;
+               m2 =  mfccc * c1o2 +      mfbcc * (vvx + c1o2) + (mfacc + c1o36 * oMdrho) * (     vx2 + vvx) * c1o2;
+               mfacc = m0;
+               mfbcc = m1;
+               mfccc = m2;
+
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+#ifdef  PROOF_CORRECTNESS
+               LBMReal rho_post = (mfaaa+mfaac+mfaca+mfcaa+mfacc+mfcac+mfccc+mfcca)
+                  +(mfaab+mfacb+mfcab+mfccb)+(mfaba+mfabc+mfcba+mfcbc)+(mfbaa+mfbac+mfbca+mfbcc)
+                  +(mfabb+mfcbb)+(mfbab+mfbcb)+(mfbba+mfbbc)+mfbbb; 
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho="+UbSystem::toString(rho)+", rho_post="+UbSystem::toString(rho_post)
+                                       +" dif="+UbSystem::toString(dif)
+                                       +" rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27CCLB::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+#endif
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               if (x1 == maxX1m || x2 == maxX2m || x3 == maxX3m)
+               {
+                  setNewDistributions(x1p, x2, x3);
+                  (*d.NW)(lX1,lX2,lX3) = mfcab;
+                  (*d.TW)(lX1,lX2,lX3) = mfcba;
+                  (*d.TNW)(lX1,lX2,lX3) = mfcaa;
+                  (*d.W)(lX1,lX2,lX3) = mfcbb;
+
+                  setNewDistributions(x1, x2p, x3);
+                  (*d.TS)(lX1,lX2,lX3) = mfbca;
+                  (*d.TSE)(lX1,lX2,lX3) = mfaca;
+                  (*d.S)(lX1,lX2,lX3) = mfbcb;
+                  (*d.SE)(lX1,lX2,lX3) = mfacb;
+
+                  setNewDistributions(x1p, x2p, x3);
+                  (*d.TSW)(lX1,lX2,lX3) = mfcca;
+                  (*d.SW)(lX1,lX2,lX3) = mfccb;
+
+                  setNewDistributions(x1p, x2, x3p);
+                  (*d.BW)(lX1,lX2,lX3) = mfcbc;  
+                  (*d.BNW)(lX1,lX2,lX3) = mfcac;
+
+                  setNewDistributions(x1, x2, x3p);
+                  (*d.B)(lX1,lX2,lX3) = mfbbc;
+                  (*d.BE)(lX1,lX2,lX3) = mfabc;
+                  (*d.BN)(lX1,lX2,lX3) = mfbac;
+                  (*d.BNE)(lX1,lX2,lX3) = mfaac;
+
+                  setNewDistributions(x1, x2p, x3p);
+                  (*d.BS)(lX1,lX2,lX3) = mfbcc;
+                  (*d.BSE)(lX1,lX2,lX3) = mfacc;
+
+                  setNewDistributions(x1p, x2p, x3p);
+                  (*d.BSW)(lX1,lX2,lX3) = mfccc;
+
+                  d = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSoA>(dataSet->getFdistributions())->getDistributions();
+                  (*d.E)(x1,x2,x3) = mfabb;
+                  (*d.N)(x1,x2,x3) = mfbab;
+                  (*d.T)(x1,x2,x3) = mfbba;
+                  (*d.NE)(x1,x2,x3) = mfaab;
+                  (*d.TE)(x1,x2,x3) = mfaba;
+                  (*d.TN)(x1,x2,x3) = mfbaa;
+                  (*d.TNE)(x1,x2,x3) = mfaaa;
+
+                  (*d.ZERO)(x1,x2,x3) = mfbbb;
+               }
+               else
+               {
+                  //d = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSoA>(dataSet->getFdistributions())->getDistributions();
+                  (*d.E)(x1,  x2,  x3)    = mfabb;
+                  (*d.N)(x1,  x2,  x3)    = mfbab;
+                  (*d.T)(x1,  x2,  x3)    = mfbba;
+                  (*d.NE)(x1,  x2,  x3)   = mfaab;
+                  (*d.NW)(x1p,x2,  x3)   = mfcab;
+                  (*d.TE)(x1,  x2,  x3)   = mfaba;
+                  (*d.TW)(x1p,x2,  x3)   = mfcba;
+                  (*d.TN)(x1,  x2,  x3)   = mfbaa;
+                  (*d.TS)(x1,  x2p,x3)   = mfbca;
+                  (*d.TNE)(x1,  x2,  x3)  = mfaaa;
+                  (*d.TNW)(x1p,x2,  x3)  = mfcaa;
+                  (*d.TSE)(x1,  x2p,x3)  = mfaca;
+                  (*d.TSW)(x1p,x2p,x3)  = mfcca;
+
+                  (*d.W)(x1p,x2,  x3    ) = mfcbb;
+                  (*d.S)(x1,  x2p,x3    ) = mfbcb;
+                  (*d.B)(x1,  x2,  x3p  ) = mfbbc;
+                  (*d.SW)(x1p,x2p,x3   ) = mfccb;
+                  (*d.SE)(x1,  x2p,x3   ) = mfacb;
+                  (*d.BW)(x1p,x2,  x3p ) = mfcbc;
+                  (*d.BE)(x1,  x2,  x3p ) = mfabc;
+                  (*d.BS)(x1,  x2p,x3p ) = mfbcc;
+                  (*d.BN)(x1,  x2,  x3p ) = mfbac;
+                  (*d.BSW)(x1p,x2p,x3p) = mfccc;
+                  (*d.BSE)(x1,  x2p,x3p) = mfacc;
+                  (*d.BNW)(x1p,x2,  x3p) = mfcac;
+                  (*d.BNE)(x1,  x2,  x3p) = mfaac;
+
+                  (*d.ZERO)(x1,x2,x3) = mfbbb;
+               }
+               //////////////////////////////////////////////////////////////////////////
+
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelETD3Q27CCLBex2::getCallculationTime()
+{
+   //return timer.getDuration();
+   return timer.getTotalTime();
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex2.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex2.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cb2896a63eb985925b1456045a7f2ae41fdd7c0
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CCLBex2.h
@@ -0,0 +1,73 @@
+//Cascaded Cumulant LBM
+
+#ifndef LBMKernelETD3Q27CCLBEX2_H
+#define LBMKernelETD3Q27CCLBEX2_H
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+#include "Grid3D.h"
+#include "D3Q27EsoTwist3DSoA.h"
+
+class LBMKernelETD3Q27CCLBex2;
+typedef boost::shared_ptr<LBMKernelETD3Q27CCLBex2> LBMKernelETD3Q27CCLBex2Ptr;
+
+
+class LBMKernelETD3Q27CCLBex2 :  public LBMKernelETD3Q27
+{
+public:
+   LBMKernelETD3Q27CCLBex2();
+   LBMKernelETD3Q27CCLBex2(int nx1, int nx2, int nx3, int option, Grid3DPtr grid);
+   ~LBMKernelETD3Q27CCLBex2(void);
+   void calculate();
+   LBMKernel3DPtr clone();
+   double getCallculationTime();
+
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+      ar & OxyyMxzz; 
+   }
+
+   void collideAll();  
+   void init();
+   void setNewDistributions(int x1, int x2, int x3);
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal rho, vx, vy, vz, durchrho;
+   LBMReal w1,w2,w3,w4,w5,w6,w7,w8,w9,w10;
+   LBMReal s9,c1o27,c2o3;
+
+   LBMReal mu200, mu020, mu002,mu110, mu101,mu011,mu210,mu120,mu102,mu111, 
+      mu201,mu021,mu012,mu220,mu121,mu202,mu211,mu112,mu022,mu221,mu122,mu212,mu222,mu000,mu100,mu010,mu001;
+   LBMReal vx_sq, vy_sq, vz_sq, vx_vy, vx_vz, vy_vz, vx_vy_vz;
+
+   UbTimer timer;
+
+   LBMReal OxyyMxzz;
+   int option;
+
+   Distributions d;
+
+   mu::value_type muX1,muX2,muX3;
+   mu::value_type muDeltaT;
+   mu::value_type muNue;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+   Grid3DPtr grid;
+   int lX1, lX2, lX3;
+   int bX1;
+   int bX2;
+   int bX3;
+   int level;
+   UbTupleInt3 blockNX;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27Cascaded.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27Cascaded.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dfa8bb27fa5aee04623293cf70387cf81dbaca09
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27Cascaded.cpp
@@ -0,0 +1,516 @@
+#include "LBMKernelETD3Q27Cascaded.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+
+
+//BOOST_CLASS_EXPORT(LBMKernelETD3Q27Cascaded)
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27Cascaded::LBMKernelETD3Q27Cascaded()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27Cascaded::LBMKernelETD3Q27Cascaded(int nx1, int nx2, int nx3) 
+   : LBMKernelETD3Q27(nx1, nx2, nx3)
+{
+   this->compressible = true;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27Cascaded::~LBMKernelETD3Q27Cascaded(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27Cascaded::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+2, nx2+2, nx3+2, -999.0));
+   dataSet->setFdistributions(d);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27Cascaded::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27Cascaded(nx1, nx2, nx3));
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27Cascaded>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setWithForcing(withForcing);
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27Cascaded::calculate()
+{
+   timer.resetAndStart();
+   collideAll();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27Cascaded::collideAll()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   if (withForcing)
+   {
+      muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+      muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+      muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+
+      muDeltaT = deltaT;
+
+      muForcingX1.DefineVar("dx",&muDeltaT);
+      muForcingX2.DefineVar("dx",&muDeltaT);
+      muForcingX3.DefineVar("dx",&muDeltaT);
+
+      muNue = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+      muForcingX1.DefineVar("nue",&muNue);
+      muForcingX2.DefineVar("nue",&muNue);
+      muForcingX3.DefineVar("nue",&muNue);
+
+      LBMReal forcingX1 = 0;
+      LBMReal forcingX2 = 0;
+      LBMReal forcingX3 = 0;
+   }
+   /////////////////////////////////////
+
+   s9 = - collFactor;
+   c1o27=1.0/27.0;
+   c2o3=2.0/3.0;
+   w2=-1.0; //MXXpMYYpMZZ bulk viscosity
+   w7=-1.0;//s9; //ORDER 4 Isotropic
+   w9=-1.0;
+   w10=-1.0;//s9;//-1.0; // ORDER 6 Isotropic
+   w1=s9;
+   // wenn es mal an den Ecken nicht gut aussieht -2.0-s9 probieren
+   w3=-1.0;//-2.0-s9;//-1.0;//MXXYpMYZZ
+   w4=-1.0;//-2.0-s9;//-1.0;//MXXYmMYZZ
+   w5=-1.0;//-2.0-s9;//-1.0;//MYXZ
+   w6=-1.0; //MXXYYpm2p
+   w8=-1.0; //M_zXXYZ 
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+   
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               f[ZERO] = (*this->zeroDistributions)(x1,x2,x3);
+
+               f[E] = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               f[N] = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3);  
+               f[T] = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               f[NE] = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               f[NW] = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3);
+               f[TE] = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               f[TW] = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3);
+               f[TN] = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               f[TS] = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3);
+               f[TNE] = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               f[TNW] = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3);
+               f[TSE] = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3);
+               f[TSW] = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+
+               f[W ] = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3  );
+               f[S ] = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3  );
+               f[B ] = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1  );
+               f[SW] = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+               f[SE] = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 );
+               f[BW] = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+               f[BE] = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 );
+               f[BS] = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+               f[BN] = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 );
+               f[BSW] = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+               f[BSE] = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+               f[BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+               f[BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1);
+               //////////////////////////////////////////////////////////////////////////
+
+
+               //////////////////////////////////////////////////////////////////////////
+               //compute collision
+               //////////////////////////////////////////////////////////////////////////
+               rho = f[ZERO] + f[E] + f[W] + f[N] + f[S] + f[T] + f[B] 
+               + f[NE] + f[SW] + f[SE] + f[NW] + f[TE] + f[BW] + f[BE]
+               + f[TW] + f[TN] + f[BS] + f[BN] + f[TS] + f[TNE] + f[TSW]
+               + f[TSE] + f[TNW] + f[BNE] + f[BSW] + f[BSE] + f[BNW];
+
+               vx = f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] - f[BW]
+               + f[BE] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+               + f[BSE] - f[BNW]; 
+
+               vy = f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+               - f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+               + f[BNW]; 
+
+               vz = f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+               + f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+               - f[BNW];
+
+               vx/=rho;
+               vy/=rho;
+               vz/=rho;
+                  
+               durchrho=1.0/rho;
+
+               //forcing 
+               /////////////////////////////////////////////////////////////////////////////////////////////
+               if (withForcing)
+               {
+                  muX1 = static_cast<double>(x1+ix1*bcArrayMaxX1);
+                  muX2 = static_cast<double>(x2+ix2*bcArrayMaxX2);
+                  muX3 = static_cast<double>(x3+ix3*bcArrayMaxX3);
+
+                  forcingX1 = muForcingX1.Eval();
+                  forcingX2 = muForcingX2.Eval();
+                  forcingX3 = muForcingX3.Eval();
+
+                  //mu100 += forcingX1; 
+                  vx += forcingX1*0.5; // X
+                  //mu010 += forcingX2; 
+                  vy += forcingX2*0.5; // Y
+                  //mu001 += forcingX3; 
+                  vz += forcingX3*0.5; // Z
+               }
+               /////////////////////////////////////////////////////////////////////////////////////////////
+
+
+               M_zXX=0.0;     M_zYY=0.0;     M_zZZ=0.0;     M_zXY=0.0;    M_zXZ=0.0;  M_zYZ=0.0;
+               M_zXXY=0.0;    M_zXYY=0.0;    M_zXXZ=0.0;    M_zXZZ=0.0;   M_zYYZ=0.0;  M_zYZZ=0.0;  M_zXYZ=0.0;
+               M_zXXYY=0.0;   M_zXXZZ=0.0;   M_zYYZZ=0.0;   M_zXXYZ=0.0;  M_zXYYZ=0.0;  M_zXYZZ=0.0;
+               M_zXXYYZ=0.0;  M_zXXYZZ=0.0;  M_zXYYZZ=0.0;  M_zXXYYZZ=0.0;
+
+               vx_sq=vx*vx;
+               vy_sq=vy*vy;
+               vz_sq=vz*vz;
+               vx_vy=vx*vy;
+               vx_vz=vx*vz;
+               vy_vz=vy*vz;
+               vx_vy_vz=vx_vy*vz;
+
+               mu200=(f[E]+f[W]+f[NE]+f[SW]+f[SE]+f[NW]+f[TE]+f[BW]+f[BE]+f[TW]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu020=(f[N]+f[S]+f[NE]+f[SW]+f[SE]+f[NW]+f[TN]+f[BS]+f[BN]+f[TS]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu002=(f[T]+f[B]+f[TE]+f[BW]+f[BE]+f[TW]+f[TN]+f[BS]+f[BN]+f[TS]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu110=(f[NE]-f[SE]+f[SW]-f[NW]+f[TNE]-f[TSE]+f[BNE]-f[BSE]+f[TSW]-f[TNW]+f[BSW]-f[BNW])*durchrho;
+               mu101=(f[TE]+f[BW]-f[BE]-f[TW]+f[TNE]-f[BNE]+f[TSE]-f[BSE]-f[TNW]+f[BNW]-f[TSW]+f[BSW])*durchrho;
+               mu011=(f[TN]+f[BS]-f[BN]-f[TS]+f[TNE]-f[BNE]-f[TSE]+f[BSE]+f[TNW]-f[BNW]-f[TSW]+f[BSW])*durchrho;
+               mu210=(f[NE]-f[SW]-f[SE]+f[NW]+f[TNE]+f[BNE]-f[TSE]-f[BSE]+f[TNW]+f[BNW]-f[TSW]-f[BSW])*durchrho;
+               mu120=(f[NE]-f[SW]+f[SE]-f[NW]+f[TNE]-f[TNW]+f[BNE]-f[BNW]+f[TSE]-f[TSW]+f[BSE]-f[BSW])*durchrho;
+               mu102=(f[TE]-f[BW]+f[BE]-f[TW]+f[TNE]-f[TNW]+f[BNE]-f[BNW]+f[TSE]-f[TSW]+f[BSE]-f[BSW])*durchrho;
+               mu111=(f[TNE]-f[BNE]-f[TSE]+f[BSE]-f[TNW]+f[BNW]+f[TSW]-f[BSW])*durchrho;
+               mu201=(f[TE]-f[BW]-f[BE]+f[TW]+f[TNE]-f[BNE]+f[TSE]-f[BSE]+f[TNW]-f[BNW]+f[TSW]-f[BSW])*durchrho;
+               mu021=(f[TN]-f[BS]-f[BN]+f[TS]+f[TNE]-f[BNE]+f[TSE]-f[BSE]+f[TNW]-f[BNW]+f[TSW]-f[BSW])*durchrho;
+               mu012=(f[TN]-f[BS]+f[BN]-f[TS]+f[TNE]+f[BNE]-f[TSE]-f[BSE]+f[TNW]+f[BNW]-f[TSW]-f[BSW])*durchrho;
+               mu220=(f[NE]+f[SW]+f[SE]+f[NW]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu121=(f[TNE]-f[BNE]+f[TSE]-f[BSE]-f[TNW]+f[BNW]-f[TSW]+f[BSW])*durchrho;
+               mu202=(f[TE]+f[BW]+f[BE]+f[TW]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu211=(f[TNE]-f[BNE]-f[TSE]+f[BSE]+f[TNW]-f[BNW]-f[TSW]+f[BSW])*durchrho;
+               mu112=(f[TNE]+f[BNE]-f[TSE]-f[BSE]-f[TNW]-f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu022=(f[TN]+f[BS]+f[BN]+f[TS]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu221=(f[TNE]-f[BNE]+f[TSE]-f[BSE]+f[TNW]-f[BNW]+f[TSW]-f[BSW])*durchrho;
+               mu122=(f[TNE]-f[TNW]+f[BNE]-f[BNW]+f[TSE]-f[TSW]+f[BSE]-f[BSW])*durchrho;
+               mu212=(f[TNE]+f[BNE]-f[TSE]-f[BSE]+f[TNW]+f[BNW]-f[TSW]-f[BSW])*durchrho;
+               mu222=(f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu000=1.0;
+               mu100=vx;
+               mu010=vy; 
+               mu001=vz;
+
+               M_zYZ= -vy_vz  +mu011 ;
+               M_zZZ= -vz_sq  +mu002 ; 
+               M_zYY= -vy_sq  +mu020 ;
+               M_zXX= -vx_sq  +mu200 ;
+               M_zXY= -vx_vy  +mu110 ;          
+               M_zXZ =-vx_vz  +mu101 ;
+
+               M_zYYZ=mu021-(mu020*vz + 2.0*vy*M_zYZ);          
+               M_zYZZ=mu012-(vy*mu002 + 2.0*vz*M_zYZ);
+               M_zXZZ=mu102-(vx*mu002 + 2.0*vz*M_zXZ);
+               M_zXXZ=mu201-(mu200*vz + 2.0*vx*M_zXZ );
+               M_zXXY=mu210-(mu200*vy + 2.0*vx*M_zXY );
+               M_zXYY=mu120-(vx*mu020 + 2.0*vy*M_zXY);
+               M_zXYZ=mu111-(vx_vy_vz + vx*M_zYZ + vy*M_zXZ + vz*M_zXY);
+
+               M_zXYYZ=mu121-(vz*mu120+ 2.0*vx_vy*M_zYZ+vx*M_zYYZ+vy_sq*M_zXZ+2.0*vy*M_zXYZ); 
+               M_zXYZZ=mu112-(vy*mu102+ 2.0*vx_vz*M_zYZ+vx*M_zYZZ+vz_sq*M_zXY+2.0*vz*M_zXYZ);
+               M_zXXYZ=mu211-(vz*mu210+ 2.0*vx_vy*M_zXZ+vy*M_zXXZ+vx_sq*M_zYZ+2.0*vx*M_zXYZ); 
+
+
+               M_zXXYY=mu220-( vx_sq*mu020+ 4.0*vx_vy*M_zXY + 2.0*vx*M_zXYY + vy_sq*M_zXX + 2.0*vy*M_zXXY); 
+               M_zYYZZ=mu022-( vy_sq*mu002+ 4.0*vy_vz*M_zYZ + 2.0*vy*M_zYZZ + vz_sq*M_zYY + 2.0*vz*M_zYYZ);
+               M_zXXZZ=mu202-( vx_sq*mu002+ 4.0*vx_vz*M_zXZ + 2.0*vx*M_zXZZ + vz_sq*M_zXX + 2.0*vz*M_zXXZ); 
+
+               M_zXXYYZ=mu221-(vz*mu220+
+                  2.0*vx_sq*vy*M_zYZ  + vx_sq*M_zYYZ + 2.0*vx*vy_sq*M_zXZ  +4.0*vx_vy*M_zXYZ+ 
+                  2.0*vx*M_zXYYZ  +    vy_sq*M_zXXZ  + 2.0*vy*M_zXXYZ);
+               M_zXYYZZ=mu122-(vx*mu022 
+                  + 2.0*vy_sq*vz*M_zXZ + vy_sq*M_zXZZ + 
+                  2.0*vy*vz_sq*M_zXY + 4.0*vy_vz*M_zXYZ + 2.0*vy*M_zXYZZ +vz_sq*M_zXYY + 2.0*vz*M_zXYYZ);
+               M_zXXYZZ=mu212-(vy*mu202
+                  + 2.0*vx_sq*vz*M_zYZ +vx_sq*M_zYZZ  + 2.0*vx*vz_sq*M_zXY + 4.0*vx_vz*M_zXYZ 
+                  + 2.0*vx*M_zXYZZ  + vz_sq*M_zXXY +  2.0*vz*M_zXXYZ);
+
+               M_zXXYYZZ=mu222-(vx_sq*mu022 
+                  + 4.0* vx*vy_sq*vz*M_zXZ   + 
+                  2.0* vx*vy_sq*M_zXZZ + 4.0* vx_vy*vz_sq*M_zXY+ 
+                  8.0* vx_vy_vz*M_zXYZ + 4.0* vx_vy*M_zXYZZ + 
+                  2.0* vx*vz_sq*M_zXYY + 4.0* vx_vz*M_zXYYZ + 2.0*vx*M_zXYYZZ + 
+                  vy_sq*vz_sq*M_zXX + 2.0* vy_sq*vz*M_zXXZ  + 
+                  vy_sq*M_zXXZZ     + 2.0* vy*vz_sq*M_zXXY  + 4.0*vy_vz*M_zXXYZ + 
+                  2.0* vy*M_zXXYZZ + vz_sq*M_zXXYY +2.0* vz*M_zXXYYZ);
+
+               ////////lin kombi bilden:
+               MXXpMYYpMZZ = M_zXX + M_zYY + M_zZZ;
+               MXXmMYY = M_zXX - M_zYY;
+               MXXmMZZ = M_zXX - M_zZZ;
+
+               MXXYpMYZZ  =  M_zXXY+M_zYZZ;
+               MXXYmMYZZ  =  M_zXXY-M_zYZZ;
+               MXXZpMYYZ  =  M_zXXZ+M_zYYZ;
+               MXXZmMYYZ  =  M_zXXZ-M_zYYZ;
+               MXYYpMXZZ  =  M_zXYY+M_zXZZ;
+               MXYYmMXZZ  =  M_zXYY-M_zXZZ;
+
+               MXXYYppp  = M_zXXYY + M_zXXZZ + M_zYYZZ;
+               MXXYYpm2p = M_zXXYY - 2.0*M_zXXZZ + M_zYYZZ;
+               MXXYYppm2 = M_zXXYY + M_zXXZZ - 2.0*M_zYYZZ;
+
+
+               //relaxation: 
+               MXXpMYYpMZZ -= w2*(1.0-MXXpMYYpMZZ);
+               MXXmMYY +=     w1*(    MXXmMYY); 
+               MXXmMZZ +=     w1*(    MXXmMZZ); 
+
+               MXXYpMYZZ  +=  w3*(MXXYpMYZZ); 
+               MXXYmMYZZ  +=  w4*(MXXYmMYZZ); 
+               MXXZpMYYZ  +=  w3*(MXXZpMYYZ); 
+               MXXZmMYYZ  +=  w4*(MXXZmMYYZ); 
+               MXYYpMXZZ  +=  w3*(MXYYpMXZZ); 
+               MXYYmMXZZ  +=  w4*(MXYYmMXZZ); 
+
+               MXXYYppp  -= w7*(c1o3 -MXXYYppp );
+               MXXYYpm2p += w6*(MXXYYpm2p);
+               MXXYYppm2 += w6*(MXXYYppm2);
+
+
+               M_zXXYYZZ-=w10*(c1o27-M_zXXYYZZ);
+               M_zXZ+=w1*(  M_zXZ    );
+               M_zYZ+=w1*(  M_zYZ    );
+               M_zXY+=w1*(  M_zXY    );
+
+               M_zXYZ+=w5*(  M_zXYZ   );
+
+               M_zXYYZ+=w8*(  M_zXYYZ  );
+               M_zXYZZ+=w8*(  M_zXYZZ  );
+               M_zXXYZ+=w8*(  M_zXXYZ  );
+
+               M_zXXYYZ+=w9*( M_zXXYYZ );
+               M_zXXYZZ+=w9*( M_zXXYZZ );
+               M_zXYYZZ+=w9*( M_zXYYZZ );
+
+               ////////von Lin Kombis zurueck:
+               M_zXX = c1o3 *MXXmMYY + c1o3 *MXXmMZZ +  c1o3* MXXpMYYpMZZ; 
+               M_zYY = -c2o3* MXXmMYY+ c1o3* MXXmMZZ +  c1o3* MXXpMYYpMZZ; 
+               M_zZZ = c1o3   * MXXmMYY -c2o3 *MXXmMZZ +  c1o3* MXXpMYYpMZZ; 
+
+               M_zXXY = (MXXYmMYZZ + MXXYpMYZZ)*0.5; 
+               M_zYZZ = 0.5*(-MXXYmMYZZ + MXXYpMYZZ); 
+               M_zXYY =(MXYYmMXZZ + MXYYpMXZZ)*0.5; 
+               M_zXZZ = 0.5*(-MXYYmMXZZ + MXYYpMXZZ); 
+               M_zXXZ = (MXXZmMYYZ + MXXZpMYYZ)*0.5; 
+               M_zYYZ = 0.5*(-MXXZmMYYZ + MXXZpMYYZ);
+
+               M_zXXYY =  c1o3* MXXYYpm2p + c1o3* MXXYYppm2 +  0.33333333*MXXYYppp; 
+               M_zXXZZ = -c1o3* MXXYYpm2p + c1o3* MXXYYppp; 
+               M_zYYZZ = -c1o3* MXXYYppm2 + c1o3* MXXYYppp;
+
+               //forcing 
+               /////////////////////////////////////////////////////////////////////////////////////////////
+               if (withForcing)
+               {
+                  mu100 += forcingX1*0.5; 
+                  vx += forcingX1*0.5; // X
+                  mu010 += forcingX2*0.5; 
+                  vy += forcingX2*0.5; // Y
+                  mu001 += forcingX3*0.5; 
+                  vz += forcingX3*0.5; // Z
+                  vx_sq=vx*vx;
+                  vy_sq=vy*vy;
+                  vz_sq=vz*vz;
+                  vx_vy=vx*vy;
+                  vx_vz=vx*vz;
+                  vy_vz=vy*vz;
+                  vx_vy_vz=vx_vy*vz;
+               }
+               /////////////////////////////////////////////////////////////////////////////////////////////
+                  
+               mu011=  vy_vz + M_zYZ;
+               mu002= vz_sq + M_zZZ; 
+               mu020= vy_sq + M_zYY ;
+               mu200=   vx_sq + M_zXX;
+               mu110= vx_vy+ M_zXY;          
+               mu101 =vx_vz + M_zXZ;
+
+               mu021=mu020*vz + 2.0*vy*M_zYZ  + M_zYYZ;          
+               mu012=vy*mu002 + 2.0*vz*M_zYZ + M_zYZZ;
+               mu102=vx*mu002 + 2.0*vz*M_zXZ + M_zXZZ;
+               mu112=vy*mu102 + 2.0*vx_vz*M_zYZ+vx*M_zYZZ+vz_sq*M_zXY+2.0*vz*M_zXYZ+M_zXYZZ;
+
+               mu201=mu200*vz + 2.0*vx*M_zXZ  + M_zXXZ;
+               mu210=mu200*vy + 2.0*vx*M_zXY  + M_zXXY;
+               mu211=vz*mu210 + 2.0*vx_vy*M_zXZ+vy*M_zXXZ+vx_sq*M_zYZ+2.0*vx*M_zXYZ+M_zXXYZ; 
+
+               mu120=vx*mu020 + 2.0*vy*M_zXY + M_zXYY;
+               mu121=vz*mu120 + 2.0*vx_vy*M_zYZ+vx*M_zYYZ+vy_sq*M_zXZ+2.0*vy*M_zXYZ+ M_zXYYZ; 
+
+               mu111=vx_vy_vz + vx*M_zYZ + vy*M_zXZ + vz*M_zXY+M_zXYZ;
+
+               mu220=vx_sq*mu020 + 4.0*vx_vy*M_zXY + 2.0*vx*M_zXYY  + vy_sq*M_zXX + 2.0*vy*M_zXXY +  M_zXXYY; 
+
+               mu221=vz*mu220 + 2.0*vx_sq*vy*M_zYZ  + vx_sq*M_zYYZ + 2.0*vx*vy_sq*M_zXZ  +4.0*vx_vy*M_zXYZ+ 
+                  2.0*vx*M_zXYYZ  +    vy_sq*M_zXXZ  + 2.0*vy*M_zXXYZ  + M_zXXYYZ;
+
+               mu022= vy_sq*mu002 + 4.0*vy_vz*M_zYZ  +2.0*vy*M_zYZZ+ vz_sq*M_zYY+ 2.0*vz*M_zYYZ +  M_zYYZZ;
+
+               mu122=vx*mu022 + 2.0*vy_sq*vz*M_zXZ + vy_sq*M_zXZZ + 
+                  2.0*vy*vz_sq*M_zXY + 4.0*vy_vz*M_zXYZ + 2.0*vy*M_zXYZZ +vz_sq*M_zXYY + 2.0*vz*M_zXYYZ + M_zXYYZZ;
+
+               mu202= vx_sq*mu002 + 4.0*vx_vz*M_zXZ+ 2.0*vx*M_zXZZ + vz_sq*M_zXX+ 2.0*vz*M_zXXZ + M_zXXZZ; 
+
+               mu212=vy*mu202 + 2.0*vx_sq*vz*M_zYZ +vx_sq*M_zYZZ  + 2.0*vx*vz_sq*M_zXY + 4.0*vx_vz*M_zXYZ 
+                  + 2.0*vx*M_zXYZZ  + vz_sq*M_zXXY +  2.0*vz*M_zXXYZ + M_zXXYZZ;
+
+               mu222=vx_sq*mu022 
+                  + 4.0* vx*vy_sq*vz*M_zXZ   + 
+                  2.0* vx*vy_sq*M_zXZZ + 4.0* vx_vy*vz_sq*M_zXY+ 
+                  8.0* vx_vy_vz*M_zXYZ + 4.0* vx_vy*M_zXYZZ + 
+                  2.0* vx*vz_sq*M_zXYY + 4.0* vx_vz*M_zXYYZ + 2.0*vx*M_zXYYZZ + 
+                  vy_sq*vz_sq*M_zXX + 2.0* vy_sq*vz*M_zXXZ  + 
+                  vy_sq*M_zXXZZ     + 2.0* vy*vz_sq*M_zXXY  + 4.0*vy_vz*M_zXXYZ + 
+                  2.0* vy*M_zXXYZZ + vz_sq*M_zXXYY +2.0* vz*M_zXXYYZ + M_zXXYYZZ;
+
+               f[E] =0.5* (mu200 -  mu220 + mu222 - mu202 - mu120 + mu122 - mu102 +mu100) *(rho);
+               f[W] =0.5* (mu200 - mu220 + mu222 - mu202 + mu120 - mu122 + mu102 -mu100)*  (rho);
+               f[N] =0.5* (-mu210 - mu220 + mu222 + mu212 + mu020 - mu022 - mu012 +mu010)* (rho);
+               f[S] =0.5* (mu210 -  mu220 + mu222 - mu212 + mu020 - mu022 + mu012 -mu010)* (rho);
+               f[T] =0.5* (mu221 +  mu222 - mu201 - mu202 - mu021 - mu022 + mu002 +mu001)* (rho);
+               f[B] =0.5* (-mu221 + mu222 + mu201  - mu202 + mu021 - mu022 + mu002-mu001)* (rho);
+               f[NE] =0.25*( mu210  + mu220- mu222 - mu212 + mu110+ mu120- mu122 -mu112)*  (rho); 
+               f[SW] =0.25*(-mu210 + mu220- mu222 + mu212 + mu110- mu120+ mu122 -mu112)*  (rho); 
+               f[SE] =0.25*(-mu210 + mu220- mu222 + mu212 - mu110+ mu120- mu122 +mu112)*  (rho); 
+               f[NW] =0.25*( mu210  + mu220- mu222 - mu212 - mu110- mu120+ mu122 + mu112)* (rho); 
+               f[TE]=0.25*(-mu221 - mu222 + mu201 + mu202 - mu121 - mu122 + mu101 + mu102)*(rho); 
+               f[BW]=0.25*( mu221  -mu222 - mu201 + mu202 - mu121 + mu122 + mu101 - mu102)*(rho);
+
+               f[BE]=0.25*(mu221 - mu222 - mu201 + mu202 + mu121 - mu122 - mu101 +mu102)*  (rho);
+               f[TW]=0.25*(-mu221 - mu222 + mu201 + mu202 + mu121 + mu122 - mu101 -mu102)* (rho); 
+               f[TN]=0.25*(-mu221 - mu222 - mu211 - mu212 + mu021 + mu022 + mu011+mu012)*  (rho);
+               f[BS]=0.25*( mu221 - mu222 - mu211 + mu212 - mu021 + mu022 + mu011 - mu012)*(rho);
+               f[BN]=0.25*( mu221 - mu222 + mu211 - mu212 - mu021 + mu022 - mu011 + mu012)*(rho);
+               f[TS]=0.25*(-mu221 - mu222 + mu211 + mu212 + mu021 + mu022 - mu011 -mu012)* (rho); 
+               f[ZERO]=     (-mu200 + mu220 - mu222 + mu202 - mu020 + mu022 - mu002 + mu000)*(rho);
+               f[TNE]=0.125*( mu221 + mu222 + mu211 + mu212 + mu121 + mu122 + mu111 + mu112)*  (rho); 
+               f[BNE]=0.125*(-mu221 + mu222 -mu211 + mu212 -mu121 + mu122 -mu111 + mu112)*     (rho);
+               f[TSE]=0.125*( mu221 + mu222 - mu211 - mu212 + mu121 + mu122 - mu111 - mu112)*  (rho); 
+               f[BSE]=0.125*(-mu221 + mu222 +mu211 - mu212 -mu121 + mu122 +mu111 - mu112)*     (rho); 
+               f[TNW]=0.125*( mu221 + mu222 + mu211 + mu212 - mu121 - mu122 - mu111 - mu112)*  (rho); 
+               f[BNW]=0.125*(-mu221 + mu222 -mu211 + mu212 +mu121 - mu122 +mu111 - mu112)*     (rho); 
+               f[TSW]=0.125*( mu221 + mu222 - mu211 - mu212 - mu121 - mu122 + mu111 + mu112)*  (rho); 
+               f[BSW]=0.125*(-mu221 + mu222+mu211 - mu212+mu121 - mu122-mu111 + mu112)*        (rho);
+               //////////////////////////////////////////////////////////////////////////
+               //proof correctness
+               //////////////////////////////////////////////////////////////////////////
+               LBMReal rho_post = f[ZERO] + f[E] + f[W] + f[N] + f[S] + f[T] + f[B] 
+               + f[NE] + f[SW] + f[SE] + f[NW] + f[TE] + f[BW] + f[BE]
+               + f[TW] + f[TN] + f[BS] + f[BN] + f[TS] + f[TNE] + f[TSW]
+               + f[TSE] + f[TNW] + f[BNE] + f[BSW] + f[BSE] + f[BNW];
+               //LBMReal dif = fabs(rho - rho_post);
+               LBMReal dif = rho - rho_post;
+#ifdef SINGLEPRECISION
+               if(dif > 10.0E-7 || dif < -10.0E-7)
+#else
+               if(dif > 10.0E-15 || dif < -10.0E-15)
+#endif
+               {
+                  UB_THROW(UbException(UB_EXARGS,"rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3)));
+                  //UBLOG(logERROR,"LBMKernelETD3Q27Cascaded::collideAll(): rho is not correct for node "+UbSystem::toString(x1)+","+UbSystem::toString(x2)+","+UbSystem::toString(x3));
+                  //exit(EXIT_FAILURE);
+               }
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::INV_E];
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::INV_N];
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::INV_T];
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::INV_NE];
+               (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::INV_NW];
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::INV_TE];
+               (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::INV_TW];
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::INV_TN];
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::INV_TS];
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::INV_TNE];
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::INV_TNW];
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::INV_TSE];
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::INV_TSW];
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::INV_W ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::INV_S ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::INV_B ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::INV_SW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::INV_SE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::INV_BW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::INV_BS];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BN];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::INV_BSW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::INV_BSE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::INV_BNW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::INV_BNE];
+
+               (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO];
+               //////////////////////////////////////////////////////////////////////////
+               
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelETD3Q27Cascaded::getCallculationTime()
+{
+   //return timer.getDuration();
+   return timer.getTotalTime();
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27Cascaded.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27Cascaded.h
new file mode 100644
index 0000000000000000000000000000000000000000..1305ca669ddadabc5f0581e097a45db94233fc48
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27Cascaded.h
@@ -0,0 +1,65 @@
+#ifndef LBMKERNELETD3Q27CASCADED_H
+#define LBMKERNELETD3Q27CASCADED_H
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+
+class LBMKernelETD3Q27Cascaded;
+typedef boost::shared_ptr<LBMKernelETD3Q27Cascaded> LBMKernelETD3Q27CascadedPtr;
+
+
+class LBMKernelETD3Q27Cascaded :  public LBMKernelETD3Q27
+{
+public:
+   LBMKernelETD3Q27Cascaded();
+   LBMKernelETD3Q27Cascaded(int nx1, int nx2, int nx3);
+   ~LBMKernelETD3Q27Cascaded(void);
+   void calculate();
+   LBMKernel3DPtr clone();
+   double getCallculationTime();
+
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+   }
+   
+   void collideAll();   
+   void init();
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal rho, vx, vy, vz, durchrho;
+   LBMReal w1,w2,w3,w4,w5,w6,w7,w8,w9,w10;
+   LBMReal s9,c1o27,c2o3;
+
+   LBMReal M_zXX, M_zYY, M_zZZ, M_zXY,    M_zXZ,  M_zYZ,
+          M_zXXY,    M_zXYY,    M_zXXZ,    M_zXZZ,   M_zYYZ,  M_zYZZ,  M_zXYZ,
+          M_zXXYY,   M_zXXZZ,   M_zYYZZ,   M_zXXYZ,  M_zXYYZ,  M_zXYZZ,
+          M_zXXYYZ,  M_zXXYZZ,  M_zXYYZZ,  M_zXXYYZZ;
+   LBMReal mu200, mu020, mu002,mu110, mu101,mu011,mu210,mu120,mu102,mu111, 
+           mu201,mu021,mu012,mu220,mu121,mu202,mu211,mu112,mu022,mu221,mu122,mu212,mu222,mu000,mu100,mu010,mu001;
+   LBMReal vx_sq, vy_sq, vz_sq, vx_vy, vx_vz, vy_vz, vx_vy_vz;
+   LBMReal MXXpMYYpMZZ,MXXmMYY, MXXmMZZ,
+            MXXYpMYZZ,MXXZpMYYZ,MXYYpMXZZ,  MXXYmMYZZ,MXXZmMYYZ,MXYYmMXZZ,
+            MXXYYppp,MXXYYpm2p, MXXYYppm2;
+   UbTimer timer;
+
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributions;
+
+   mu::value_type muX1,muX2,muX3;
+   mu::value_type muDeltaT;
+   mu::value_type muNue;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CascadedTI.cpp b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CascadedTI.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..963f847e439dbdfe2bd52115948f5e806e81c578
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CascadedTI.cpp
@@ -0,0 +1,500 @@
+#include "LBMKernelETD3Q27CascadedTI.h"
+#include "D3Q27System.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27DensityBCAdapter.h"
+#include "D3Q27VelocityBCAdapter.h"
+#include "SimulationParameters.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "D3Q27EsoTwist3DSplittedVector.h"
+
+
+//BOOST_CLASS_EXPORT(LBMKernelETD3Q27CascadedVorticity)
+
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CascadedTI::LBMKernelETD3Q27CascadedTI()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CascadedTI::LBMKernelETD3Q27CascadedTI(int nx1, int nx2, int nx3) 
+   : LBMKernelETD3Q27(nx1, nx2, nx3)
+{
+   this->compressible = true;
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernelETD3Q27CascadedTI::~LBMKernelETD3Q27CascadedTI(void)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CascadedTI::init()
+{
+   //DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+ghostLayerWitdh*2, nx2+ghostLayerWitdh*2, nx3+ghostLayerWitdh*2, -999.0));
+   DistributionArray3DPtr d(new D3Q27EsoTwist3DSplittedVector(nx1+2, nx2+2, nx3+2, -999.0));
+   dataSet->setFdistributions(d);
+   //TODO move averageValues to another place
+   //averageValues = AverageValuesArray3DPtr(new AverageValuesArray3D(nx1+1, nx2+1, nx3+1, 4, 0.0));
+   //dataSet->setAverageValues(averageValues);
+}
+//////////////////////////////////////////////////////////////////////////
+LBMKernel3DPtr LBMKernelETD3Q27CascadedTI::clone()
+{
+   LBMKernel3DPtr kernel(new LBMKernelETD3Q27CascadedTI(nx1, nx2, nx3));
+   boost::dynamic_pointer_cast<LBMKernelETD3Q27CascadedTI>(kernel)->init();
+   kernel->setCollisionFactor(this->collFactor);
+   kernel->setBCProcessor(bcProcessor->clone(kernel));
+   kernel->setForcingX1(muForcingX1);
+   kernel->setForcingX2(muForcingX2);
+   kernel->setForcingX3(muForcingX3);
+   kernel->setIndex(ix1, ix2, ix3);
+   kernel->setDeltaT(deltaT);
+   return kernel;
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CascadedTI::calculate()
+{
+   timer.resetAndStart();
+   collideAll();
+   timer.stop();
+}
+//////////////////////////////////////////////////////////////////////////
+void LBMKernelETD3Q27CascadedTI::collideAll()
+{
+   using namespace D3Q27System;
+
+   //initializing of forcing stuff 
+   mu::value_type muX1,muX2,muX3;
+   muForcingX1.DefineVar("x1",&muX1); muForcingX1.DefineVar("x2",&muX2); muForcingX1.DefineVar("x3",&muX3);
+   muForcingX2.DefineVar("x1",&muX1); muForcingX2.DefineVar("x2",&muX2); muForcingX2.DefineVar("x3",&muX3);
+   muForcingX3.DefineVar("x1",&muX1); muForcingX3.DefineVar("x2",&muX2); muForcingX3.DefineVar("x3",&muX3);
+   
+   mu::value_type muDeltaT = deltaT;
+
+   muForcingX1.DefineVar("dx",&muDeltaT);
+   muForcingX2.DefineVar("dx",&muDeltaT);
+   muForcingX3.DefineVar("dx",&muDeltaT);
+
+   mu::value_type muNue = (1.0/3.0)*(1.0/collFactor - 1.0/2.0);
+
+   muForcingX1.DefineVar("nue",&muNue);
+   muForcingX2.DefineVar("nue",&muNue);
+   muForcingX3.DefineVar("nue",&muNue);
+
+   LBMReal forcingX1 = 0;
+   LBMReal forcingX2 = 0;
+   LBMReal forcingX3 = 0;
+   /////////////////////////////////////
+
+   s9 = - collFactor;
+   c1o27=1.0/27.0;
+   c2o3=2.0/3.0;
+   w2=-1.0;//s9;//-1.0;
+   w7=-1.0;//s9;
+   w9=-1.0;
+   w10=-1.0;//s9;//-1.0;
+   w1=s9;
+   w3=-1.0;
+   w4=-1.0;
+   w5=-1.0;
+   w6=-1.0;//s9;
+   w8=-1.0;//s9;
+
+   localDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions();
+   nonLocalDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions();
+   zeroDistributions = boost::dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions();
+
+   BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(this->getBCProcessor())->getBCArray();
+   D3Q27BoundaryConditionPtr bcPtr;
+
+   const int bcArrayMaxX1 = (int)bcArray.getNX1();
+   const int bcArrayMaxX2 = (int)bcArray.getNX2();
+   const int bcArrayMaxX3 = (int)bcArray.getNX3();
+   
+   int minX1 = ghostLayerWidth;
+   int minX2 = ghostLayerWidth;
+   int minX3 = ghostLayerWidth;
+   int maxX1 = bcArrayMaxX1-ghostLayerWidth;
+   int maxX2 = bcArrayMaxX2-ghostLayerWidth;
+   int maxX3 = bcArrayMaxX3-ghostLayerWidth;
+
+   for(int x3 = minX3; x3 < maxX3; x3++)
+   {
+      for(int x2 = minX2; x2 < maxX2; x2++)
+      {
+         for(int x1 = minX1; x1 < maxX1; x1++)
+         {
+            if(!bcArray.isSolid(x1,x2,x3) && !bcArray.isUndefined(x1,x2,x3))
+            {
+               //////////////////////////////////////////////////////////////////////////
+               //read distribution
+               ////////////////////////////////////////////////////////////////////////////
+               f[ZERO] = (*this->zeroDistributions)(x1,x2,x3);
+
+               f[E] = (*this->localDistributions)(D3Q27System::ET_E, x1,x2,x3);
+               f[N] = (*this->localDistributions)(D3Q27System::ET_N,x1,x2,x3);  
+               f[T] = (*this->localDistributions)(D3Q27System::ET_T,x1,x2,x3);
+               f[NE] = (*this->localDistributions)(D3Q27System::ET_NE,x1,x2,x3);
+               f[NW] = (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,x3);
+               f[TE] = (*this->localDistributions)(D3Q27System::ET_TE,x1,x2,x3);
+               f[TW] = (*this->localDistributions)(D3Q27System::ET_TW, x1+1,x2,x3);
+               f[TN] = (*this->localDistributions)(D3Q27System::ET_TN,x1,x2,x3);
+               f[TS] = (*this->localDistributions)(D3Q27System::ET_TS,x1,x2+1,x3);
+               f[TNE] = (*this->localDistributions)(D3Q27System::ET_TNE,x1,x2,x3);
+               f[TNW] = (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,x3);
+               f[TSE] = (*this->localDistributions)(D3Q27System::ET_TSE,x1,x2+1,x3);
+               f[TSW] = (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3);
+
+               f[W ] = (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,x3  );
+               f[S ] = (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,x2+1,x3  );
+               f[B ] = (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,x2,x3+1  );
+               f[SW] = (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3 );
+               f[SE] = (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,x2+1,x3 );
+               f[BW] = (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,x3+1 );
+               f[BE] = (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,x2,x3+1 );
+               f[BS] = (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,x2+1,x3+1 );
+               f[BN] = (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,x2,x3+1 );
+               f[BSW] = (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1);
+               f[BSE] = (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,x2+1,x3+1);
+               f[BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,x3+1);
+               f[BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,x2,x3+1);
+               //////////////////////////////////////////////////////////////////////////
+
+
+               //////////////////////////////////////////////////////////////////////////
+               //compute collision
+               //////////////////////////////////////////////////////////////////////////
+               rho = f[ZERO] + f[E] + f[W] + f[N] + f[S] + f[T] + f[B] 
+               + f[NE] + f[SW] + f[SE] + f[NW] + f[TE] + f[BW] + f[BE]
+               + f[TW] + f[TN] + f[BS] + f[BN] + f[TS] + f[TNE] + f[TSW]
+               + f[TSE] + f[TNW] + f[BNE] + f[BSW] + f[BSE] + f[BNW];
+
+               vx = f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] - f[BW]
+               + f[BE] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+               + f[BSE] - f[BNW]; 
+
+               vy = f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+               - f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+               + f[BNW]; 
+
+               vz = f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+               + f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+               - f[BNW];
+
+               vx/=rho;
+               vy/=rho;
+               vz/=rho;
+                  
+               durchrho=1.0/rho;
+
+               //forcing 
+               /////////////////////////////////////////////////////////////////////////////////////////////
+               muX1 = static_cast<double>(x1+ix1*bcArrayMaxX1);
+               muX2 = static_cast<double>(x2+ix2*bcArrayMaxX2);
+               muX3 = static_cast<double>(x3+ix3*bcArrayMaxX3);
+
+               forcingX1 = muForcingX1.Eval();
+               forcingX2 = muForcingX2.Eval();
+               forcingX3 = muForcingX3.Eval();
+
+               //mu100 += forcingX1; 
+               vx += forcingX1*0.5; // X
+               //mu010 += forcingX2; 
+               vy += forcingX2*0.5; // Y
+               //mu001 += forcingX3; 
+               vz += forcingX3*0.5; // Z
+               //////////////////////////////////////////////////////////////////////////
+
+               M_zXX=0.0;     M_zYY=0.0;     M_zZZ=0.0;     M_zXY=0.0;    M_zXZ=0.0;  M_zYZ=0.0;
+               M_zXXY=0.0;    M_zXYY=0.0;    M_zXXZ=0.0;    M_zXZZ=0.0;   M_zYYZ=0.0;  M_zYZZ=0.0;  M_zXYZ=0.0;
+               M_zXXYY=0.0;   M_zXXZZ=0.0;   M_zYYZZ=0.0;   M_zXXYZ=0.0;  M_zXYYZ=0.0;  M_zXYZZ=0.0;
+               M_zXXYYZ=0.0;  M_zXXYZZ=0.0;  M_zXYYZZ=0.0;  M_zXXYYZZ=0.0;
+
+               vx_sq=vx*vx;
+               vy_sq=vy*vy;
+               vz_sq=vz*vz;
+               vx_vy=vx*vy;
+               vx_vz=vx*vz;
+               vy_vz=vy*vz;
+               vx_vy_vz=vx_vy*vz;
+
+               mu200=(f[E]+f[W]+f[NE]+f[SW]+f[SE]+f[NW]+f[TE]+f[BW]+f[BE]+f[TW]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu020=(f[N]+f[S]+f[NE]+f[SW]+f[SE]+f[NW]+f[TN]+f[BS]+f[BN]+f[TS]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu002=(f[T]+f[B]+f[TE]+f[BW]+f[BE]+f[TW]+f[TN]+f[BS]+f[BN]+f[TS]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu110=(f[NE]-f[SE]+f[SW]-f[NW]+f[TNE]-f[TSE]+f[BNE]-f[BSE]+f[TSW]-f[TNW]+f[BSW]-f[BNW])*durchrho;
+               mu101=(f[TE]+f[BW]-f[BE]-f[TW]+f[TNE]-f[BNE]+f[TSE]-f[BSE]-f[TNW]+f[BNW]-f[TSW]+f[BSW])*durchrho;
+               mu011=(f[TN]+f[BS]-f[BN]-f[TS]+f[TNE]-f[BNE]-f[TSE]+f[BSE]+f[TNW]-f[BNW]-f[TSW]+f[BSW])*durchrho;
+               mu210=(f[NE]-f[SW]-f[SE]+f[NW]+f[TNE]+f[BNE]-f[TSE]-f[BSE]+f[TNW]+f[BNW]-f[TSW]-f[BSW])*durchrho;
+               mu120=(f[NE]-f[SW]+f[SE]-f[NW]+f[TNE]-f[TNW]+f[BNE]-f[BNW]+f[TSE]-f[TSW]+f[BSE]-f[BSW])*durchrho;
+               mu102=(f[TE]-f[BW]+f[BE]-f[TW]+f[TNE]-f[TNW]+f[BNE]-f[BNW]+f[TSE]-f[TSW]+f[BSE]-f[BSW])*durchrho;
+               mu111=(f[TNE]-f[BNE]-f[TSE]+f[BSE]-f[TNW]+f[BNW]+f[TSW]-f[BSW])*durchrho;
+               mu201=(f[TE]-f[BW]-f[BE]+f[TW]+f[TNE]-f[BNE]+f[TSE]-f[BSE]+f[TNW]-f[BNW]+f[TSW]-f[BSW])*durchrho;
+               mu021=(f[TN]-f[BS]-f[BN]+f[TS]+f[TNE]-f[BNE]+f[TSE]-f[BSE]+f[TNW]-f[BNW]+f[TSW]-f[BSW])*durchrho;
+               mu012=(f[TN]-f[BS]+f[BN]-f[TS]+f[TNE]+f[BNE]-f[TSE]-f[BSE]+f[TNW]+f[BNW]-f[TSW]-f[BSW])*durchrho;
+               mu220=(f[NE]+f[SW]+f[SE]+f[NW]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu121=(f[TNE]-f[BNE]+f[TSE]-f[BSE]-f[TNW]+f[BNW]-f[TSW]+f[BSW])*durchrho;
+               mu202=(f[TE]+f[BW]+f[BE]+f[TW]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu211=(f[TNE]-f[BNE]-f[TSE]+f[BSE]+f[TNW]-f[BNW]-f[TSW]+f[BSW])*durchrho;
+               mu112=(f[TNE]+f[BNE]-f[TSE]-f[BSE]-f[TNW]-f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu022=(f[TN]+f[BS]+f[BN]+f[TS]+f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu221=(f[TNE]-f[BNE]+f[TSE]-f[BSE]+f[TNW]-f[BNW]+f[TSW]-f[BSW])*durchrho;
+               mu122=(f[TNE]-f[TNW]+f[BNE]-f[BNW]+f[TSE]-f[TSW]+f[BSE]-f[BSW])*durchrho;
+               mu212=(f[TNE]+f[BNE]-f[TSE]-f[BSE]+f[TNW]+f[BNW]-f[TSW]-f[BSW])*durchrho;
+               mu222=(f[TNE]+f[BNE]+f[TSE]+f[BSE]+f[TNW]+f[BNW]+f[TSW]+f[BSW])*durchrho;
+               mu000=1.0;
+               mu100=vx;
+               mu010=vy; 
+               mu001=vz;
+
+               M_zYZ= -vy_vz  +mu011 ;
+               M_zZZ= -vz_sq  +mu002 ; 
+               M_zYY= -vy_sq  +mu020 ;
+               M_zXX= -vx_sq  +mu200 ;
+               M_zXY= -vx_vy  +mu110 ;          
+               M_zXZ =-vx_vz  +mu101 ;
+
+               M_zYYZ=mu021-(mu020*vz + 2.0*vy*M_zYZ);          
+               M_zYZZ=mu012-(vy*mu002 + 2.0*vz*M_zYZ);
+               M_zXZZ=mu102-(vx*mu002 + 2.0*vz*M_zXZ);
+               M_zXXZ=mu201-(mu200*vz + 2.0*vx*M_zXZ );
+               M_zXXY=mu210-(mu200*vy + 2.0*vx*M_zXY );
+               M_zXYY=mu120-(vx*mu020 + 2.0*vy*M_zXY);
+               M_zXYZ=mu111-(vx_vy_vz + vx*M_zYZ + vy*M_zXZ + vz*M_zXY);
+
+               M_zXYYZ=mu121-(vz*mu120+ 2.0*vx_vy*M_zYZ+vx*M_zYYZ+vy_sq*M_zXZ+2.0*vy*M_zXYZ); 
+               M_zXYZZ=mu112-(vy*mu102+ 2.0*vx_vz*M_zYZ+vx*M_zYZZ+vz_sq*M_zXY+2.0*vz*M_zXYZ);
+               M_zXXYZ=mu211-(vz*mu210+ 2.0*vx_vy*M_zXZ+vy*M_zXXZ+vx_sq*M_zYZ+2.0*vx*M_zXYZ); 
+
+
+               M_zXXYY=mu220-( vx_sq*mu020+ 4.0*vx_vy*M_zXY + 2.0*vx*M_zXYY + vy_sq*M_zXX + 2.0*vy*M_zXXY); 
+               M_zYYZZ=mu022-( vy_sq*mu002+ 4.0*vy_vz*M_zYZ + 2.0*vy*M_zYZZ + vz_sq*M_zYY + 2.0*vz*M_zYYZ);
+               M_zXXZZ=mu202-( vx_sq*mu002+ 4.0*vx_vz*M_zXZ + 2.0*vx*M_zXZZ + vz_sq*M_zXX + 2.0*vz*M_zXXZ); 
+
+               M_zXXYYZ=mu221-(vz*mu220+
+                  2.0*vx_sq*vy*M_zYZ  + vx_sq*M_zYYZ + 2.0*vx*vy_sq*M_zXZ  +4.0*vx_vy*M_zXYZ+ 
+                  2.0*vx*M_zXYYZ  +    vy_sq*M_zXXZ  + 2.0*vy*M_zXXYZ);
+               M_zXYYZZ=mu122-(vx*mu022 
+                  + 2.0*vy_sq*vz*M_zXZ + vy_sq*M_zXZZ + 
+                  2.0*vy*vz_sq*M_zXY + 4.0*vy_vz*M_zXYZ + 2.0*vy*M_zXYZZ +vz_sq*M_zXYY + 2.0*vz*M_zXYYZ);
+               M_zXXYZZ=mu212-(vy*mu202
+                  + 2.0*vx_sq*vz*M_zYZ +vx_sq*M_zYZZ  + 2.0*vx*vz_sq*M_zXY + 4.0*vx_vz*M_zXYZ 
+                  + 2.0*vx*M_zXYZZ  + vz_sq*M_zXXY +  2.0*vz*M_zXXYZ);
+
+               M_zXXYYZZ=mu222-(vx_sq*mu022 
+                  + 4.0* vx*vy_sq*vz*M_zXZ   + 
+                  2.0* vx*vy_sq*M_zXZZ + 4.0* vx_vy*vz_sq*M_zXY+ 
+                  8.0* vx_vy_vz*M_zXYZ + 4.0* vx_vy*M_zXYZZ + 
+                  2.0* vx*vz_sq*M_zXYY + 4.0* vx_vz*M_zXYYZ + 2.0*vx*M_zXYYZZ + 
+                  vy_sq*vz_sq*M_zXX + 2.0* vy_sq*vz*M_zXXZ  + 
+                  vy_sq*M_zXXZZ     + 2.0* vy*vz_sq*M_zXXY  + 4.0*vy_vz*M_zXXYZ + 
+                  2.0* vy*M_zXXYZZ + vz_sq*M_zXXYY +2.0* vz*M_zXXYYZ);
+
+               ////////lin kombi bilden:
+               MXXpMYYpMZZ = M_zXX + M_zYY + M_zZZ;
+               MXXmMYY = M_zXX - M_zYY;
+               MXXmMZZ = M_zXX - M_zZZ;
+
+               MXXYpMYZZ  =  M_zXXY+M_zYZZ;
+               MXXYmMYZZ  =  M_zXXY-M_zYZZ;
+               MXXZpMYYZ  =  M_zXXZ+M_zYYZ;
+               MXXZmMYYZ  =  M_zXXZ-M_zYYZ;
+               MXYYpMXZZ  =  M_zXYY+M_zXZZ;
+               MXYYmMXZZ  =  M_zXYY-M_zXZZ;
+
+               MXXYYppp  = M_zXXYY + M_zXXZZ + M_zYYZZ;
+               MXXYYpm2p = M_zXXYY - 2.0*M_zXXZZ + M_zYYZZ;
+               MXXYYppm2 = M_zXXYY + M_zXXZZ - 2.0*M_zYYZZ;
+
+
+               //relaxation: 
+               MXXpMYYpMZZ -= w2*(1.0-MXXpMYYpMZZ);
+               MXXmMYY +=     w1*(    MXXmMYY); 
+               MXXmMZZ +=     w1*(    MXXmMZZ); 
+
+               MXXYpMYZZ  +=  w3*(MXXYpMYZZ); 
+               MXXYmMYZZ  +=  w4*(MXXYmMYZZ); 
+               MXXZpMYYZ  +=  w3*(MXXZpMYYZ); 
+               MXXZmMYYZ  +=  w4*(MXXZmMYYZ); 
+               MXYYpMXZZ  +=  w3*(MXYYpMXZZ); 
+               MXYYmMXZZ  +=  w4*(MXYYmMXZZ); 
+
+               MXXYYppp  -= w7*(c1o3 -MXXYYppp );
+               MXXYYpm2p += w6*(MXXYYpm2p);
+               MXXYYppm2 += w6*(MXXYYppm2);
+
+
+               M_zXXYYZZ-=w10*(c1o27-M_zXXYYZZ);
+               M_zXZ+=w1*(  M_zXZ    );
+               M_zYZ+=w1*(  M_zYZ    );
+               M_zXY+=w1*(  M_zXY    );
+
+               M_zXYZ+=w5*(  M_zXYZ   );
+
+               M_zXYYZ+=w8*(  M_zXYYZ  );
+               M_zXYZZ+=w8*(  M_zXYZZ  );
+               M_zXXYZ+=w8*(  M_zXXYZ  );
+
+               M_zXXYYZ+=w9*( M_zXXYYZ );
+               M_zXXYZZ+=w9*( M_zXXYZZ );
+               M_zXYYZZ+=w9*( M_zXYYZZ );
+
+               ////////von Lin Kombis zurueck:
+               M_zXX = c1o3 *MXXmMYY + c1o3 *MXXmMZZ +  c1o3* MXXpMYYpMZZ; 
+               M_zYY = -c2o3* MXXmMYY+ c1o3* MXXmMZZ +  c1o3* MXXpMYYpMZZ; 
+               M_zZZ = c1o3   * MXXmMYY -c2o3 *MXXmMZZ +  c1o3* MXXpMYYpMZZ; 
+
+               M_zXXY = (MXXYmMYZZ + MXXYpMYZZ)*0.5; 
+               M_zYZZ = 0.5*(-MXXYmMYZZ + MXXYpMYZZ); 
+               M_zXYY =(MXYYmMXZZ + MXYYpMXZZ)*0.5; 
+               M_zXZZ = 0.5*(-MXYYmMXZZ + MXYYpMXZZ); 
+               M_zXXZ = (MXXZmMYYZ + MXXZpMYYZ)*0.5; 
+               M_zYYZ = 0.5*(-MXXZmMYYZ + MXXZpMYYZ);
+
+               M_zXXYY =  c1o3* MXXYYpm2p + c1o3* MXXYYppm2 +  0.33333333*MXXYYppp; 
+               M_zXXZZ = -c1o3* MXXYYpm2p + c1o3* MXXYYppp; 
+               M_zYYZZ = -c1o3* MXXYYppm2 + c1o3* MXXYYppp;
+
+               //forcing 
+               /////////////////////////////////////////////////////////////////////////////////////////////
+               mu100 += forcingX1*0.5; 
+               vx += forcingX1*0.5; // X
+               mu010 += forcingX2*0.5; 
+               vy += forcingX2*0.5; // Y
+               mu001 += forcingX3*0.5; 
+               vz += forcingX3*0.5; // Z
+               vx_sq=vx*vx;
+               vy_sq=vy*vy;
+               vz_sq=vz*vz;
+               vx_vy=vx*vy;
+               vx_vz=vx*vz;
+               vy_vz=vy*vz;
+               vx_vy_vz=vx_vy*vz;
+               /////////////////////////////////////////////////////////////////////////////////////////////
+                  
+               mu011=  vy_vz + M_zYZ;
+               mu002= vz_sq + M_zZZ; 
+               mu020= vy_sq + M_zYY ;
+               mu200=   vx_sq + M_zXX;
+               mu110= vx_vy+ M_zXY;          
+               mu101 =vx_vz + M_zXZ;
+
+               mu021=mu020*vz + 2.0*vy*M_zYZ  + M_zYYZ;          
+               mu012=vy*mu002 + 2.0*vz*M_zYZ + M_zYZZ;
+               mu102=vx*mu002 + 2.0*vz*M_zXZ + M_zXZZ;
+               mu112=vy*mu102 + 2.0*vx_vz*M_zYZ+vx*M_zYZZ+vz_sq*M_zXY+2.0*vz*M_zXYZ+M_zXYZZ;
+
+               mu201=mu200*vz + 2.0*vx*M_zXZ  + M_zXXZ;
+               mu210=mu200*vy + 2.0*vx*M_zXY  + M_zXXY;
+               mu211=vz*mu210 + 2.0*vx_vy*M_zXZ+vy*M_zXXZ+vx_sq*M_zYZ+2.0*vx*M_zXYZ+M_zXXYZ; 
+
+               mu120=vx*mu020 + 2.0*vy*M_zXY + M_zXYY;
+               mu121=vz*mu120 + 2.0*vx_vy*M_zYZ+vx*M_zYYZ+vy_sq*M_zXZ+2.0*vy*M_zXYZ+ M_zXYYZ; 
+
+               mu111=vx_vy_vz + vx*M_zYZ + vy*M_zXZ + vz*M_zXY+M_zXYZ;
+
+               mu220=vx_sq*mu020 + 4.0*vx_vy*M_zXY + 2.0*vx*M_zXYY  + vy_sq*M_zXX + 2.0*vy*M_zXXY +  M_zXXYY; 
+
+               mu221=vz*mu220 + 2.0*vx_sq*vy*M_zYZ  + vx_sq*M_zYYZ + 2.0*vx*vy_sq*M_zXZ  +4.0*vx_vy*M_zXYZ+ 
+                  2.0*vx*M_zXYYZ  +    vy_sq*M_zXXZ  + 2.0*vy*M_zXXYZ  + M_zXXYYZ;
+
+               mu022= vy_sq*mu002 + 4.0*vy_vz*M_zYZ  +2.0*vy*M_zYZZ+ vz_sq*M_zYY+ 2.0*vz*M_zYYZ +  M_zYYZZ;
+
+               mu122=vx*mu022 + 2.0*vy_sq*vz*M_zXZ + vy_sq*M_zXZZ + 
+                  2.0*vy*vz_sq*M_zXY + 4.0*vy_vz*M_zXYZ + 2.0*vy*M_zXYZZ +vz_sq*M_zXYY + 2.0*vz*M_zXYYZ + M_zXYYZZ;
+
+               mu202= vx_sq*mu002 + 4.0*vx_vz*M_zXZ+ 2.0*vx*M_zXZZ + vz_sq*M_zXX+ 2.0*vz*M_zXXZ + M_zXXZZ; 
+
+               mu212=vy*mu202 + 2.0*vx_sq*vz*M_zYZ +vx_sq*M_zYZZ  + 2.0*vx*vz_sq*M_zXY + 4.0*vx_vz*M_zXYZ 
+                  + 2.0*vx*M_zXYZZ  + vz_sq*M_zXXY +  2.0*vz*M_zXXYZ + M_zXXYZZ;
+
+               mu222=vx_sq*mu022 
+                  + 4.0* vx*vy_sq*vz*M_zXZ   + 
+                  2.0* vx*vy_sq*M_zXZZ + 4.0* vx_vy*vz_sq*M_zXY+ 
+                  8.0* vx_vy_vz*M_zXYZ + 4.0* vx_vy*M_zXYZZ + 
+                  2.0* vx*vz_sq*M_zXYY + 4.0* vx_vz*M_zXYYZ + 2.0*vx*M_zXYYZZ + 
+                  vy_sq*vz_sq*M_zXX + 2.0* vy_sq*vz*M_zXXZ  + 
+                  vy_sq*M_zXXZZ     + 2.0* vy*vz_sq*M_zXXY  + 4.0*vy_vz*M_zXXYZ + 
+                  2.0* vy*M_zXXYZZ + vz_sq*M_zXXYY +2.0* vz*M_zXXYYZ + M_zXXYYZZ;
+
+               f[E] =0.5* (mu200 -  mu220 + mu222 - mu202 - mu120 + mu122 - mu102 +mu100) *(rho);
+               f[W] =0.5* (mu200 - mu220 + mu222 - mu202 + mu120 - mu122 + mu102 -mu100)*  (rho);
+               f[N] =0.5* (-mu210 - mu220 + mu222 + mu212 + mu020 - mu022 - mu012 +mu010)* (rho);
+               f[S] =0.5* (mu210 -  mu220 + mu222 - mu212 + mu020 - mu022 + mu012 -mu010)* (rho);
+               f[T] =0.5* (mu221 +  mu222 - mu201 - mu202 - mu021 - mu022 + mu002 +mu001)* (rho);
+               f[B] =0.5* (-mu221 + mu222 + mu201  - mu202 + mu021 - mu022 + mu002-mu001)* (rho);
+               f[NE] =0.25*( mu210  + mu220- mu222 - mu212 + mu110+ mu120- mu122 -mu112)*  (rho); 
+               f[SW] =0.25*(-mu210 + mu220- mu222 + mu212 + mu110- mu120+ mu122 -mu112)*  (rho); 
+               f[SE] =0.25*(-mu210 + mu220- mu222 + mu212 - mu110+ mu120- mu122 +mu112)*  (rho); 
+               f[NW] =0.25*( mu210  + mu220- mu222 - mu212 - mu110- mu120+ mu122 + mu112)* (rho); 
+               f[TE]=0.25*(-mu221 - mu222 + mu201 + mu202 - mu121 - mu122 + mu101 + mu102)*(rho); 
+               f[BW]=0.25*( mu221  -mu222 - mu201 + mu202 - mu121 + mu122 + mu101 - mu102)*(rho);
+
+               f[BE]=0.25*(mu221 - mu222 - mu201 + mu202 + mu121 - mu122 - mu101 +mu102)*  (rho);
+               f[TW]=0.25*(-mu221 - mu222 + mu201 + mu202 + mu121 + mu122 - mu101 -mu102)* (rho); 
+               f[TN]=0.25*(-mu221 - mu222 - mu211 - mu212 + mu021 + mu022 + mu011+mu012)*  (rho);
+               f[BS]=0.25*( mu221 - mu222 - mu211 + mu212 - mu021 + mu022 + mu011 - mu012)*(rho);
+               f[BN]=0.25*( mu221 - mu222 + mu211 - mu212 - mu021 + mu022 - mu011 + mu012)*(rho);
+               f[TS]=0.25*(-mu221 - mu222 + mu211 + mu212 + mu021 + mu022 - mu011 -mu012)* (rho); 
+               f[ZERO]=     (-mu200 + mu220 - mu222 + mu202 - mu020 + mu022 - mu002 + mu000)*(rho);
+               f[TNE]=0.125*( mu221 + mu222 + mu211 + mu212 + mu121 + mu122 + mu111 + mu112)*  (rho); 
+               f[BNE]=0.125*(-mu221 + mu222 -mu211 + mu212 -mu121 + mu122 -mu111 + mu112)*     (rho);
+               f[TSE]=0.125*( mu221 + mu222 - mu211 - mu212 + mu121 + mu122 - mu111 - mu112)*  (rho); 
+               f[BSE]=0.125*(-mu221 + mu222 +mu211 - mu212 -mu121 + mu122 +mu111 - mu112)*     (rho); 
+               f[TNW]=0.125*( mu221 + mu222 + mu211 + mu212 - mu121 - mu122 - mu111 - mu112)*  (rho); 
+               f[BNW]=0.125*(-mu221 + mu222 -mu211 + mu212 +mu121 - mu122 +mu111 - mu112)*     (rho); 
+               f[TSW]=0.125*( mu221 + mu222 - mu211 - mu212 - mu121 - mu122 + mu111 + mu112)*  (rho); 
+               f[BSW]=0.125*(-mu221 + mu222+mu211 - mu212+mu121 - mu122-mu111 + mu112)*        (rho);
+
+//#ifdef _DEBUG
+               LBMReal rho_post = f[ZERO] + f[E] + f[W] + f[N] + f[S] + f[T] + f[B] 
+               + f[NE] + f[SW] + f[SE] + f[NW] + f[TE] + f[BW] + f[BE]
+               + f[TW] + f[TN] + f[BS] + f[BN] + f[TS] + f[TNE] + f[TSW]
+               + f[TSE] + f[TNW] + f[BNE] + f[BSW] + f[BSE] + f[BNW];
+               LBMReal dif = fabs(rho - rho_post);
+               assert(dif < 10.0E-15);
+//#endif  
+
+               //////////////////////////////////////////////////////////////////////////
+               //write distribution
+               //////////////////////////////////////////////////////////////////////////
+               (*this->localDistributions)(D3Q27System::ET_E,x1,  x2,  x3) = f[D3Q27System::INV_E];
+               (*this->localDistributions)(D3Q27System::ET_N,x1,  x2,  x3) = f[D3Q27System::INV_N];
+               (*this->localDistributions)(D3Q27System::ET_T,x1,  x2,  x3) = f[D3Q27System::INV_T];
+               (*this->localDistributions)(D3Q27System::ET_NE,x1,  x2,  x3) = f[D3Q27System::INV_NE];
+               (*this->localDistributions)(D3Q27System::ET_NW,x1+1,x2,  x3) = f[D3Q27System::INV_NW];
+               (*this->localDistributions)(D3Q27System::ET_TE,x1,  x2,  x3) = f[D3Q27System::INV_TE];
+               (*this->localDistributions)(D3Q27System::ET_TW,x1+1,x2,  x3) = f[D3Q27System::INV_TW];
+               (*this->localDistributions)(D3Q27System::ET_TN,x1,  x2,  x3) = f[D3Q27System::INV_TN];
+               (*this->localDistributions)(D3Q27System::ET_TS,x1,  x2+1,x3) = f[D3Q27System::INV_TS];
+               (*this->localDistributions)(D3Q27System::ET_TNE,x1,  x2,  x3) = f[D3Q27System::INV_TNE];
+               (*this->localDistributions)(D3Q27System::ET_TNW,x1+1,x2,  x3) = f[D3Q27System::INV_TNW];
+               (*this->localDistributions)(D3Q27System::ET_TSE,x1,  x2+1,x3) = f[D3Q27System::INV_TSE];
+               (*this->localDistributions)(D3Q27System::ET_TSW,x1+1,x2+1,x3) = f[D3Q27System::INV_TSW];
+
+               (*this->nonLocalDistributions)(D3Q27System::ET_W,x1+1,x2,  x3    ) = f[D3Q27System::INV_W ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_S,x1,  x2+1,x3    ) = f[D3Q27System::INV_S ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_B,x1,  x2,  x3+1  ) = f[D3Q27System::INV_B ];
+               (*this->nonLocalDistributions)(D3Q27System::ET_SW,x1+1,x2+1,x3   ) = f[D3Q27System::INV_SW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_SE,x1,  x2+1,x3   ) = f[D3Q27System::INV_SE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BW,x1+1,x2,  x3+1 ) = f[D3Q27System::INV_BW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BE,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BS,x1,  x2+1,x3+1 ) = f[D3Q27System::INV_BS];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BN,x1,  x2,  x3+1 ) = f[D3Q27System::INV_BN];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSW,x1+1,x2+1,x3+1) = f[D3Q27System::INV_BSW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BSE,x1,  x2+1,x3+1) = f[D3Q27System::INV_BSE];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNW,x1+1,x2,  x3+1) = f[D3Q27System::INV_BNW];
+               (*this->nonLocalDistributions)(D3Q27System::ET_BNE,x1,  x2,  x3+1) = f[D3Q27System::INV_BNE];
+
+               (*this->zeroDistributions)(x1,x2,x3) = f[D3Q27System::ZERO];
+               //////////////////////////////////////////////////////////////////////////
+               
+            }
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+double LBMKernelETD3Q27CascadedTI::getCallculationTime()
+{
+   //return timer.getDuration();
+   return timer.getTotalTime();
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CascadedTI.h b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CascadedTI.h
new file mode 100644
index 0000000000000000000000000000000000000000..f87e225f2b09723a117cd43bf8983a461fc570a9
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMKernelETD3Q27CascadedTI.h
@@ -0,0 +1,63 @@
+#ifndef LBMKernelETD3Q27CascadedTI_H
+#define LBMKernelETD3Q27CascadedTI_H
+
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "D3Q27System.h"
+#include <boost/serialization/export.hpp>
+#include "basics/utilities/UbTiming.h"
+#include "basics/container/CbArray4D.h"
+#include "basics/container/CbArray3D.h"
+
+class LBMKernelETD3Q27CascadedTI;
+typedef boost::shared_ptr<LBMKernelETD3Q27CascadedTI> LBMKernelETD3Q27CascadedTiPtr;
+
+//Kernel with turbulent intensity 
+
+class LBMKernelETD3Q27CascadedTI :  public LBMKernelETD3Q27
+{
+public:
+   LBMKernelETD3Q27CascadedTI();
+   LBMKernelETD3Q27CascadedTI(int nx1, int nx2, int nx3);
+   ~LBMKernelETD3Q27CascadedTI(void);
+   void calculate();
+   LBMKernel3DPtr clone();
+   double getCallculationTime();
+
+protected:
+   friend class boost::serialization::access;
+   template<class Archive>
+   void serialize(Archive & ar, const unsigned int version)
+   {
+      ar & boost::serialization::base_object<LBMKernelETD3Q27>(*this);
+      //ar & averageValues;
+   }
+   
+   void collideAll();   
+   void init();
+   LBMReal f[D3Q27System::ENDF+1];
+   LBMReal rho, vx, vy, vz, durchrho;
+   LBMReal w1,w2,w3,w4,w5,w6,w7,w8,w9,w10;
+   LBMReal s9,c1o27,c2o3;
+
+   LBMReal M_zXX, M_zYY, M_zZZ, M_zXY,    M_zXZ,  M_zYZ,
+          M_zXXY,    M_zXYY,    M_zXXZ,    M_zXZZ,   M_zYYZ,  M_zYZZ,  M_zXYZ,
+          M_zXXYY,   M_zXXZZ,   M_zYYZZ,   M_zXXYZ,  M_zXYYZ,  M_zXYZZ,
+          M_zXXYYZ,  M_zXXYZZ,  M_zXYYZZ,  M_zXXYYZZ;
+   LBMReal mu200, mu020, mu002,mu110, mu101,mu011,mu210,mu120,mu102,mu111, 
+           mu201,mu021,mu012,mu220,mu121,mu202,mu211,mu112,mu022,mu221,mu122,mu212,mu222,mu000,mu100,mu010,mu001;
+   LBMReal vx_sq, vy_sq, vz_sq, vx_vy, vx_vz, vy_vz, vx_vy_vz;
+   LBMReal MXXpMYYpMZZ,MXXmMYY, MXXmMZZ,
+            MXXYpMYZZ,MXXZpMYYZ,MXYYpMXZZ,  MXXYmMYZZ,MXXZmMYYZ,MXYYmMXZZ,
+            MXXYYppp,MXXYYpm2p, MXXYYppm2;
+   UbTimer timer;
+
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr localDistributions;
+   CbArray4D<LBMReal,IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions;
+   CbArray3D<LBMReal,IndexerX3X2X1>::CbArray3DPtr   zeroDistributions;
+
+   //AverageValuesArray3DPtr averageValues;
+   //int averageCount;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/LBM/LBMSystem.cpp b/source/VirtualFluidsCore/LBM/LBMSystem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccb9838072e9a5e30c6d78e127ade7b6e9c01f44
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMSystem.cpp
@@ -0,0 +1,6 @@
+#include "LBMSystem.h"
+
+namespace LBMSystem
+{
+   real SMAG_CONST = REAL_CAST(0.18);
+}
diff --git a/source/VirtualFluidsCore/LBM/LBMSystem.h b/source/VirtualFluidsCore/LBM/LBMSystem.h
new file mode 100644
index 0000000000000000000000000000000000000000..9cfe7a15c5f47578b31af35d3ead642c188e8696
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMSystem.h
@@ -0,0 +1,83 @@
+#ifndef LBMSYSTEM_H
+#define LBMSYSTEM_H
+
+#include <cmath>
+#include <string>
+#include <iostream>
+
+#ifdef RCF_USE_SF_SERIALIZATION
+#include <SF/Serializer.hpp>
+
+#if CAB_RCF <= 903
+#include <SF/SerializeEnum.hpp>   
+#endif
+#endif //RCF_USE_SF_SERIALIZATION
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbSystem.h>
+
+/*=========================================================================*/
+/*  LBMSystem                                                            */
+/*                                                                         */
+/**
+namespace for global system-functions
+<BR><BR>
+@author <A HREF="mailto:geller@irmb.tu-bs.de">S. Geller</A>
+@version 1.0 - 07.01.11
+*/ 
+
+/*
+usage: ...
+*/
+
+namespace LBMSystem
+{
+#ifndef SWIG
+   using namespace UbMath;
+#endif
+
+//#define SINGLEPRECISION
+
+#ifdef SINGLEPRECISION
+   typedef float real;
+   #define REAL_CAST(x) ( (LBMSystem::real)(x) )
+#else
+   typedef double real;
+   #define REAL_CAST(x) ( x )
+#endif
+
+   extern real SMAG_CONST;
+
+   //////////////////////////////////////////////////////////////////////////
+   //!get LBM deltaT is equal LBM DeltaX
+   //!deltaT is dependent from grid level 
+   //!for first grid level is deltaT = 1.0
+   //!for next grid level 1/2 etc.
+   static real getDeltaT(int level)
+   {
+      return REAL_CAST(1.0/REAL_CAST(1<<level)); 
+   }
+
+   //////////////////////////////////////////////////////////////////////////
+   //!calculate collision factor omega = 1.0/(3.0*viscosity/deltaT+0.5)
+   //!deltaT is dependent from grid level 
+   //!for first grid level is deltaT = 1.0
+   //!for next grid level 1/2 etc.
+   static real calcCollisionFactor(real viscosity, int level)
+   {
+      //return REAL_CAST(1.0/(3.0*viscosity/deltaT+0.5));
+      return REAL_CAST(1.0/(3.0*viscosity/(1.0/REAL_CAST(1<<level))+0.5));
+   }
+}
+
+//some typedefs for global namespace
+typedef LBMSystem::real LBMReal;
+
+//#define LBMSystem::real LBMReal
+
+
+
+#endif
+
diff --git a/source/VirtualFluidsCore/LBM/LBMSystems.h b/source/VirtualFluidsCore/LBM/LBMSystems.h
new file mode 100644
index 0000000000000000000000000000000000000000..a8dc14507804a4dd2422958c57915f73d06918b6
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMSystems.h
@@ -0,0 +1,372 @@
+#ifndef D3Q27SYSTEM_H
+#define D3Q27SYSTEM_H
+
+#include <cmath>
+#include <string>
+#include <iostream>
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbTuple.h>
+#include <basics/utilities/UbMath.h>
+#include <basics/utilities/UbSystem.h>
+#include "Patch3DSystem.h"
+#include "LBMSystem.h"
+
+
+class LBMSystems
+{
+   //////////////////////////////////////////////////////////////////////////
+
+
+   //////////////////////////////////////////////////////////////////////////
+   //MACROSCOPIC VALUES                  
+   /*=====================================================================*/
+   static LBMReal getDensity(const LBMReal* const& f/*[27]*/)
+   {
+      return  f[ZERO] + f[E] + f[W] + f[N] + f[S] + f[T] + f[B] 
+      + f[NE] + f[SW] + f[SE] + f[NW] + f[TE] + f[BW] + f[BE]
+      + f[TW] + f[TN] + f[BS] + f[BN] + f[TS] + f[TNE] + f[TSW]
+      + f[TSE] + f[TNW] + f[BNE] + f[BSW] + f[BSE] + f[BNW];
+   }
+   /*=====================================================================*/
+   //ACHTUNG: gilt nicht fuer alle modelle -> praedikat verwenden anstelle static! toDo
+   static LBMReal getPressure(const LBMReal* const& f/*[27]*/)
+   {
+      return  REAL_CAST( c1o3 )*getDensity(f);
+   }
+   /*=====================================================================*/
+   static LBMReal getIncompVelocityX1(const LBMReal* const& f/*[27]*/)
+   {
+      return f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] 
+      + f[BE] - f[BW] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+      + f[BSE] - f[BNW];  
+   }
+   /*=====================================================================*/
+   static LBMReal getIncompVelocityX2(const LBMReal* const& f/*[27]*/)
+   {
+      return f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+      - f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+      + f[BNW];  
+   }
+   /*=====================================================================*/
+   static LBMReal getIncompVelocityX3(const LBMReal* const& f/*[27]*/)
+   {
+      return f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+      + f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+      - f[BNW];
+   }
+   /*=====================================================================*/
+   static void calcDensity(const LBMReal* const& f/*[27]*/, LBMReal& rho)
+   {
+      rho = f[ZERO] + f[E] + f[W] + f[N] + f[S] + f[T] + f[B] 
+      + f[NE] + f[SW] + f[SE] + f[NW] + f[TE] + f[BW] + f[BE]
+      + f[TW] + f[TN] + f[BS] + f[BN] + f[TS] + f[TNE] + f[TSW]
+      + f[TSE] + f[TNW] + f[BNE] + f[BSW] + f[BSE] + f[BNW];
+   }
+   /*=====================================================================*/
+   static void calcIncompVelocityX1(const LBMReal* const& f/*[27]*/, LBMReal& vx1)
+   {
+      vx1 = f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] - f[BW]
+      + f[BE] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+      + f[BSE] - f[BNW];  
+   }
+   /*=====================================================================*/
+   static void calcIncompVelocityX2(const LBMReal* const& f/*[27]*/, LBMReal& vx2)
+   {
+      vx2 = f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+      - f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+      + f[BNW];  
+   }
+   /*=====================================================================*/
+   static void calcIncompVelocityX3(const LBMReal* const& f/*[27]*/, LBMReal& vx3)
+   {
+      vx3 = f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+      + f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+      - f[BNW];
+   }
+   /*=====================================================================*/
+   static LBMReal getCompVelocityX1(const LBMReal* const& f/*[27]*/)
+   {
+      return (f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] - f[BW]
+      + f[BE] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+      + f[BSE] - f[BNW])/getDensity(f);  
+   }
+   /*=====================================================================*/
+   static LBMReal getCompVelocityX2(const LBMReal* const& f/*[27]*/)
+   {
+      return (f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+      - f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+      + f[BNW])/getDensity(f);  
+   }
+   /*=====================================================================*/
+   static LBMReal getCompVelocityX3(const LBMReal* const& f/*[27]*/)
+   {
+      return (f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+      + f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+      - f[BNW])/getDensity(f);
+   }
+   /*=====================================================================*/
+   static void calcCompVelocityX1(const LBMReal* const& f/*[27]*/, LBMReal& vx1)
+   {
+      vx1 = (f[E] - f[W] + f[NE] - f[SW] + f[SE] - f[NW] + f[TE] - f[BW]
+      + f[BE] - f[TW] + f[TNE] - f[TSW] + f[TSE] - f[TNW] + f[BNE] - f[BSW]
+      + f[BSE] - f[BNW])/getDensity(f);  
+   }
+   /*=====================================================================*/
+   static void calcCompVelocityX2(const LBMReal* const& f/*[27]*/, LBMReal& vx2)
+   {
+      vx2 = (f[N] - f[S] + f[NE] - f[SW] - f[SE] + f[NW] + f[TN] - f[BS] + f[BN]
+      - f[TS] + f[TNE] - f[TSW] - f[TSE] + f[TNW] + f[BNE] - f[BSW] - f[BSE] 
+      + f[BNW])/getDensity(f);  
+   }
+   /*=====================================================================*/
+   static void calcCompVelocityX3(const LBMReal* const& f/*[27]*/, LBMReal& vx3)
+   {
+      vx3 = (f[T] - f[B] + f[TE] - f[BW] - f[BE] + f[TW] + f[TN] - f[BS] - f[BN] 
+      + f[TS] + f[TNE] + f[TSW] + f[TSE] + f[TNW] - f[BNE] - f[BSW] - f[BSE] 
+      - f[BNW])/getDensity(f);
+   }
+   /*=====================================================================*/
+   static void calcIncompMacroscopicValues(const LBMReal* const& f/*[27]*/, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3)
+   {
+      D3Q27System::calcDensity(f, rho);
+      D3Q27System::calcIncompVelocityX1(f, vx1);
+      D3Q27System::calcIncompVelocityX2(f, vx2);
+      D3Q27System::calcIncompVelocityX3(f, vx3);
+   }
+
+   /*=====================================================================*/
+   static void calcCompMacroscopicValues(const LBMReal* const& f/*[27]*/, LBMReal& rho, LBMReal& vx1, LBMReal& vx2, LBMReal& vx3)
+   {
+      D3Q27System::calcDensity(f, rho);
+      D3Q27System::calcIncompVelocityX1(f, vx1);
+      D3Q27System::calcIncompVelocityX2(f, vx2);
+      D3Q27System::calcIncompVelocityX3(f, vx3);
+      vx1/=rho;
+      vx2/=rho;
+      vx3/=rho;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static LBMReal getCompFeqForDirection(const int& direction, const LBMReal& rho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3)
+   {
+      LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+      switch(direction)    
+      {
+      case ZERO : return REAL_CAST( c8o27*rho*(1.0-cu_sq));
+      case E : return REAL_CAST(  c2o27*rho*(1.0+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq));
+      case W : return REAL_CAST(  c2o27*rho*(1.0+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq));
+      case N : return REAL_CAST(  c2o27*rho*(1.0+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq));
+      case S : return REAL_CAST(  c2o27*rho*(1.0+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq));
+      case T : return REAL_CAST(  c2o27*rho*(1.0+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq));
+      case B : return REAL_CAST(  c2o27*rho*(1.0+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq));
+      case NE : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq));
+      case SW : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq));
+      case SE : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq));
+      case NW : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq));
+      case TE : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq));
+      case BW : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq));
+      case BE : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq));
+      case TW : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq));
+      case TN : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq));
+      case BS : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq));
+      case BN : return REAL_CAST( c1o54*rho*(1.0+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq));
+      case TS : return REAL_CAST( c1o54*rho*(1.0+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq));
+      case TNE : return REAL_CAST(c1o216*rho*(1.0+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq));
+      case BSW : return REAL_CAST(c1o216*rho*(1.0+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq));
+      case BNE : return REAL_CAST(c1o216*rho*(1.0+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq));
+      case TSW : return REAL_CAST(c1o216*rho*(1.0+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq));
+      case TSE : return REAL_CAST(c1o216*rho*(1.0+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq));
+      case BNW : return REAL_CAST(c1o216*rho*(1.0+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq));
+      case BSE : return REAL_CAST(c1o216*rho*(1.0+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq));
+      case TNW : return REAL_CAST(c1o216*rho*(1.0+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq));
+      default: throw UbException(UB_EXARGS,"unknown dir");
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void calcCompFeq(LBMReal* const& feq/*[27]*/,const LBMReal& rho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3)	
+   {
+      LBMReal cu_sq=1.5*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+      feq[ZERO] =  c8o27*rho*(1.0-cu_sq);
+      feq[E] =   c2o27*rho*(1.0+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq);
+      feq[W] =   c2o27*rho*(1.0+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq);
+      feq[N] =   c2o27*rho*(1.0+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq);
+      feq[S] =   c2o27*rho*(1.0+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq);
+      feq[T] =   c2o27*rho*(1.0+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq);
+      feq[B] =   c2o27*rho*(1.0+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq);
+      feq[NE] =  c1o54*rho*(1.0+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq);
+      feq[SW] =  c1o54*rho*(1.0+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq);
+      feq[SE] =  c1o54*rho*(1.0+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq);
+      feq[NW] =  c1o54*rho*(1.0+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq);
+      feq[TE] =  c1o54*rho*(1.0+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq);
+      feq[BW] =  c1o54*rho*(1.0+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq);
+      feq[BE] =  c1o54*rho*(1.0+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq);
+      feq[TW] =  c1o54*rho*(1.0+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq);
+      feq[TN] =  c1o54*rho*(1.0+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq);
+      feq[BS] =  c1o54*rho*(1.0+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq);
+      feq[BN] =  c1o54*rho*(1.0+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq);
+      feq[TS] =  c1o54*rho*(1.0+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq);
+      feq[TNE] = c1o216*rho*(1.0+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq);
+      feq[BSW] = c1o216*rho*(1.0+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq);
+      feq[BNE] = c1o216*rho*(1.0+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq);
+      feq[TSW] = c1o216*rho*(1.0+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq);
+      feq[TSE] = c1o216*rho*(1.0+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq);
+      feq[BNW] = c1o216*rho*(1.0+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq);
+      feq[BSE] = c1o216*rho*(1.0+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq);
+      feq[TNW] = c1o216*rho*(1.0+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq);
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static LBMReal getIncompFeqForDirection(const int& direction,const LBMReal& drho, const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3)	
+   {	
+      LBMReal cu_sq=1.5f*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+      switch(direction)    
+      {		 
+      case ZERO : return REAL_CAST( c8o27*(drho-cu_sq));
+      case E : return REAL_CAST( c2o27*(drho+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq));
+      case W : return REAL_CAST( c2o27*(drho+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq));
+      case N : return REAL_CAST( c2o27*(drho+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq));
+      case S : return REAL_CAST( c2o27*(drho+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq));
+      case T : return REAL_CAST( c2o27*(drho+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq));
+      case B : return REAL_CAST( c2o27*(drho+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq));
+      case NE : return REAL_CAST( c1o54*(drho+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq));
+      case SW : return REAL_CAST( c1o54*(drho+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq));
+      case SE : return REAL_CAST( c1o54*(drho+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq));
+      case NW : return REAL_CAST( c1o54*(drho+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq));
+      case TE : return REAL_CAST( c1o54*(drho+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq));
+      case BW : return REAL_CAST( c1o54*(drho+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq));
+      case BE : return REAL_CAST( c1o54*(drho+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq));
+      case TW : return REAL_CAST( c1o54*(drho+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq));
+      case TN : return REAL_CAST( c1o54*(drho+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq));
+      case BS : return REAL_CAST( c1o54*(drho+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq));
+      case BN : return REAL_CAST( c1o54*(drho+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq));
+      case TS : return REAL_CAST( c1o54*(drho+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq));
+      case TNE : return REAL_CAST(c1o216*(drho+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq));
+      case BSW : return REAL_CAST(c1o216*(drho+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq));
+      case BNE : return REAL_CAST(c1o216*(drho+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq));
+      case TSW : return REAL_CAST(c1o216*(drho+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq));
+      case TSE : return REAL_CAST(c1o216*(drho+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq));
+      case BNW : return REAL_CAST(c1o216*(drho+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq));
+      case BSE : return REAL_CAST(c1o216*(drho+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq));
+      case TNW : return REAL_CAST(c1o216*(drho+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq));
+      default: throw UbException(UB_EXARGS,"unknown dir");
+      }
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static void calcIncompFeq(LBMReal* const& feq/*[27]*/,const LBMReal& drho,const LBMReal& vx1,const LBMReal& vx2,const LBMReal& vx3)	
+   {
+      LBMReal cu_sq=1.5f*(vx1*vx1+vx2*vx2+vx3*vx3);
+
+      feq[ZERO] =  c8o27*(drho-cu_sq);
+      feq[E] =  c2o27*(drho+3.0*( vx1   )+c9o2*( vx1   )*( vx1   )-cu_sq);
+      feq[W] =  c2o27*(drho+3.0*(-vx1   )+c9o2*(-vx1   )*(-vx1   )-cu_sq);
+      feq[N] =  c2o27*(drho+3.0*(    vx2)+c9o2*(    vx2)*(    vx2)-cu_sq);
+      feq[S] =  c2o27*(drho+3.0*(   -vx2)+c9o2*(   -vx2)*(   -vx2)-cu_sq);
+      feq[T] =  c2o27*(drho+3.0*( vx3   )+c9o2*(    vx3)*(    vx3)-cu_sq);
+      feq[B] =  c2o27*(drho+3.0*(   -vx3)+c9o2*(   -vx3)*(   -vx3)-cu_sq);
+      feq[NE] =  c1o54*(drho+3.0*( vx1+vx2)+c9o2*( vx1+vx2)*( vx1+vx2)-cu_sq);
+      feq[SW] =  c1o54*(drho+3.0*(-vx1-vx2)+c9o2*(-vx1-vx2)*(-vx1-vx2)-cu_sq);
+      feq[SE] =  c1o54*(drho+3.0*( vx1-vx2)+c9o2*( vx1-vx2)*( vx1-vx2)-cu_sq);
+      feq[NW] =  c1o54*(drho+3.0*(-vx1+vx2)+c9o2*(-vx1+vx2)*(-vx1+vx2)-cu_sq);
+      feq[TE] =  c1o54*(drho+3.0*( vx1+vx3)+c9o2*( vx1+vx3)*( vx1+vx3)-cu_sq);
+      feq[BW] =  c1o54*(drho+3.0*(-vx1-vx3)+c9o2*(-vx1-vx3)*(-vx1-vx3)-cu_sq);
+      feq[BE] =  c1o54*(drho+3.0*( vx1-vx3)+c9o2*( vx1-vx3)*( vx1-vx3)-cu_sq);
+      feq[TW] =  c1o54*(drho+3.0*(-vx1+vx3)+c9o2*(-vx1+vx3)*(-vx1+vx3)-cu_sq);
+      feq[TN] =  c1o54*(drho+3.0*( vx2+vx3)+c9o2*( vx2+vx3)*( vx2+vx3)-cu_sq);
+      feq[BS] =  c1o54*(drho+3.0*(-vx2-vx3)+c9o2*(-vx2-vx3)*(-vx2-vx3)-cu_sq);
+      feq[BN] =  c1o54*(drho+3.0*( vx2-vx3)+c9o2*( vx2-vx3)*( vx2-vx3)-cu_sq);
+      feq[TS] =  c1o54*(drho+3.0*(-vx2+vx3)+c9o2*(-vx2+vx3)*(-vx2+vx3)-cu_sq);
+      feq[TNE] = c1o216*(drho+3.0*( vx1+vx2+vx3)+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq);
+      feq[BSW] = c1o216*(drho+3.0*(-vx1-vx2-vx3)+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq);
+      feq[BNE] = c1o216*(drho+3.0*( vx1+vx2-vx3)+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq);
+      feq[TSW] = c1o216*(drho+3.0*(-vx1-vx2+vx3)+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq);
+      feq[TSE] = c1o216*(drho+3.0*( vx1-vx2+vx3)+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq);
+      feq[BNW] = c1o216*(drho+3.0*(-vx1+vx2-vx3)+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq);
+      feq[BSE] = c1o216*(drho+3.0*( vx1-vx2-vx3)+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq);
+      feq[TNW] = c1o216*(drho+3.0*(-vx1+vx2+vx3)+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq);   
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static inline float getBoundaryVelocityForDirection(const int& direction, const float& bcVelocityX1,const float& bcVelocityX2,const float& bcVelocityX3)
+   {
+      switch(direction) 
+      {          
+      case E:   return (float)( UbMath::c4o9*(+bcVelocityX1) );
+      case W:   return (float)( UbMath::c4o9*(-bcVelocityX1) );
+      case N:   return (float)( UbMath::c4o9*(+bcVelocityX2) );
+      case S:   return (float)( UbMath::c4o9*(-bcVelocityX2) );
+      case T:   return (float)( UbMath::c4o9*(+bcVelocityX3) );
+      case B:   return (float)( UbMath::c4o9*(-bcVelocityX3) );
+      case NE:  return (float)( UbMath::c1o9*(+bcVelocityX1+bcVelocityX2             ) );
+      case SW:  return (float)( UbMath::c1o9*(-bcVelocityX1-bcVelocityX2             ) );
+      case SE:  return (float)( UbMath::c1o9*(+bcVelocityX1-bcVelocityX2             ) );
+      case NW:  return (float)( UbMath::c1o9*(-bcVelocityX1+bcVelocityX2             ) );
+      case TE:  return (float)( UbMath::c1o9*(+bcVelocityX1             +bcVelocityX3) );
+      case BW:  return (float)( UbMath::c1o9*(-bcVelocityX1             -bcVelocityX3) );
+      case BE:  return (float)( UbMath::c1o9*(+bcVelocityX1             -bcVelocityX3) );
+      case TW:  return (float)( UbMath::c1o9*(-bcVelocityX1             +bcVelocityX3) );
+      case TN:  return (float)( UbMath::c1o9*(             +bcVelocityX2+bcVelocityX3) );
+      case BS:  return (float)( UbMath::c1o9*(             -bcVelocityX2-bcVelocityX3) );
+      case BN:  return (float)( UbMath::c1o9*(             +bcVelocityX2-bcVelocityX3) );
+      case TS:  return (float)( UbMath::c1o9*(             -bcVelocityX2+bcVelocityX3) );
+      case TNE: return (float)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2+bcVelocityX3) );
+      case BSW: return (float)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2-bcVelocityX3) );
+      case BNE: return (float)( UbMath::c1o36*(+bcVelocityX1+bcVelocityX2-bcVelocityX3) );
+      case TSW: return (float)( UbMath::c1o36*(-bcVelocityX1-bcVelocityX2+bcVelocityX3) );
+      case TSE: return (float)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2+bcVelocityX3) );
+      case BNW: return (float)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2-bcVelocityX3) );
+      case BSE: return (float)( UbMath::c1o36*(+bcVelocityX1-bcVelocityX2-bcVelocityX3) );
+      case TNW: return (float)( UbMath::c1o36*(-bcVelocityX1+bcVelocityX2+bcVelocityX3) );
+      default: throw UbException(UB_EXARGS,"unknown direction"); 
+      }
+   }
+   /*=====================================================================*/
+   static const int& getInvertDirection(const int& direction)
+   {  
+#ifdef _DEBUG
+      if(direction<STARTDIR || direction>ENDDIR) 
+         throw UbException(UB_EXARGS,"unknown direction");
+#endif
+      return INVDIR[direction];
+   }
+   /*=====================================================================*/
+   static std::vector<int> getFDirs()
+   {
+      std::vector<int> D3Q27_f_Dirs;
+      D3Q27_f_Dirs.resize(ENDF+1);
+      for(int dir=STARTF; dir<=ENDF; ++dir)
+         D3Q27_f_Dirs[dir] = dir;
+
+      return D3Q27_f_Dirs;
+   }
+   /*=====================================================================*/
+   static std::vector<int> getDirs(const bool& onlyLBdirs)
+   {
+      std::vector<int> D3Q27Dirs;
+      if(onlyLBdirs) /*FSTARTDIR->FENDDIR*/
+      {
+         D3Q27Dirs.resize(FENDDIR+1);
+         for(int dir=FSTARTDIR; dir<=FENDDIR; ++dir)
+            D3Q27Dirs[dir] = dir;
+      }
+      else /*STARTDIR->ENDDIR*/
+      {
+         D3Q27Dirs.resize(ENDDIR+1);
+         for(int dir=STARTDIR; dir<=ENDDIR; ++dir)
+            D3Q27Dirs[dir] = dir;
+      }
+      return D3Q27Dirs;
+   }
+   //////////////////////////////////////////////////////////////////////////
+   static LBMReal calcCollisionFactor(LBMReal viscosity, LBMReal deltaX)
+   {
+      return 1.0/(3.0*viscosity/deltaX+0.5);
+   }
+
+
+
+
+};
+
+#endif
+
diff --git a/source/VirtualFluidsCore/LBM/LBMUnitConverter.h b/source/VirtualFluidsCore/LBM/LBMUnitConverter.h
new file mode 100644
index 0000000000000000000000000000000000000000..47de7303b1557cdbe356fdd8f1b5c0e8d5ca4ddd
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/LBMUnitConverter.h
@@ -0,0 +1,215 @@
+#ifndef LBMUNITCONVERTER_H
+#define LBMUNITCONVERTER_H
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+
+#include "LBMUnitConverter.h"
+
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbFileInput.h>
+#include <basics/utilities/UbFileOutput.h>
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/serialization/serialization.hpp>
+
+// LBMUnitConverter conv(  100 /*L_World*/, 1484/*cs_water*/    , 1000/*rho_water*/
+//                         , 1000/*L_LB*/   , 1./srqt(3.)/*cs_Lb*/, 1/*rho_Lb*/ );
+// cout<<conv.toString()<<endl;
+// 
+// cout<<"100m       = "<< 100  * conv.getFactorLentghWToLb()   << "dx    " << std::endl;
+// cout<<"1000dx     = "<< 1000 * conv.getFactorLentghLbToW()   << "m     " << std::endl;
+// 
+// cout<<"25m/s      = "<< 25   * conv.getFactorVelocityWToLb() << "dx/dt " << std::endl;
+// cout<<"0.04 dx/dt = "<< 0.04 * conv.getFactorVelocityLbToW() << "m/s   " << std::endl;
+//
+//alternativ
+// LBMUnitConverter conv(, 100 /*L_World*/, LBMUnitConverter::WATER, 1000/*L_LB*/  );
+
+class LBMUnitConverter;
+typedef boost::shared_ptr<LBMUnitConverter> LBMUnitConverterPtr;
+
+class LBMUnitConverter
+{
+public:
+
+   enum WORLD_MATERIAL { WATER  = 0, SEAWWATER  = 1, AIR_20C  = 2, OIL  = 3  }; 
+
+   LBMUnitConverter() :  factorLengthLbToW(1.0),
+                         factorTimeLbToW(1.0),
+                         factorMassLbToW(1.0), 
+                         refRhoLb(1.0),
+                         factorVelocityLbToW(1.0), 
+                         factorViscosityLbToW(1.0),
+                         factorDensityLbToW(1.0),
+                         factorPressureLbToW(1.0)
+   {
+
+   }
+
+   LBMUnitConverter(   const double& refLengthWorld, const double& csWorld, const double& rhoWorld
+      , const double& refLengthLb   , const double& csLb = 1.0/std::sqrt(3.0)  , const double& rhoLb = 1.0   )
+   {
+      this->init(  refLengthWorld, csWorld, rhoWorld, csWorld, refLengthLb, rhoLb, csLb  );
+
+   }
+
+   LBMUnitConverter(  const double& refLengthWorld, WORLD_MATERIAL worldMaterial
+      , const double& refLengthLb   , const double& csLb = 1.0/std::sqrt(3.0) , const double& rhoLb = 1.0    )
+   {
+      double csWorld;
+      double rhoWorld;  
+
+      if     ( worldMaterial == WATER    ) { csWorld = 1484/*m/s*/; rhoWorld =  1000/*kg/m^3*/;  }
+      else if( worldMaterial == SEAWWATER) { csWorld = 1500/*m/s*/; rhoWorld =  1025/*kg/m^3*/;  }
+      else if( worldMaterial == AIR_20C  ) { csWorld =  343/*m/s*/; rhoWorld = 1.290/*kg/m^3*/;  }
+      else if( worldMaterial == OIL      ) { csWorld = 1740/*m/s*/; rhoWorld =  830/*kg/m^3*/;   }
+      else                                  throw UbException(UB_EXARGS,"unknown material");
+
+      this->init(  refLengthWorld, csWorld, rhoWorld, csWorld, refLengthLb, rhoLb, csLb  );
+
+   }
+
+   LBMUnitConverter(int dummy, double uReal, double uLB, double nuReal, double nuLB) 
+   {
+      factorVelocityLbToW = uReal/uLB;
+      factorViscosityLbToW = nuReal/nuLB;
+      factorDensityLbToW = factorViscosityLbToW * factorVelocityLbToW * factorVelocityLbToW;
+      factorPressureLbToW = factorDensityLbToW;
+   }
+
+   virtual ~LBMUnitConverter() {}
+
+   double  getRefRhoLb()             { return refRhoLb; }
+
+   double  getFactorLentghLbToW()    { return factorLengthLbToW;                                                       }
+   double  getFactorLentghWToLb()    { return 1.0/this->getFactorLentghLbToW();                                        }
+
+   double  getFactorTimeLbToW()      { return factorTimeLbToW;                                                         }
+   double  getFactorTimeWToLb()      { return 1.0/this->getFactorTimeLbToW();                                          }
+
+   double  getFactorVelocityLbToW()  { return factorLengthLbToW/factorTimeLbToW;                                       }
+   double  getFactorVelocityWToLb()  { return 1.0/this->getFactorVelocityLbToW();                                      }
+
+   double  getFactorViscosityLbToW() { return factorLengthLbToW*factorLengthLbToW/factorTimeLbToW;                     }
+   double  getFactorViscosityWToLb() { return 1.0/this->getFactorViscosityLbToW();                                     }
+
+   double  getFactorDensityLbToW()   { return this->factorMassLbToW/std::pow(factorLengthLbToW,3.0);                   }
+   double  getFactorDensityWToLb()   { return 1.0/this->getFactorDensityLbToW();                                       }
+
+   double  getFactorPressureLbToW()  { return this->factorMassLbToW/(std::pow(factorTimeLbToW,2.0)*factorLengthLbToW); }
+   double  getFactorPressureWToLb()  { return 1.0/this->getFactorPressureLbToW();                                      }
+
+   double  getFactorMassLbToW()      { return this->factorMassLbToW;                                                   }
+   double  getFactorMassWToLb()      { return 1.0/this->getFactorMassLbToW();                                          }
+
+   double  getFactorForceLbToW()     { return factorMassLbToW*factorLengthLbToW/(factorTimeLbToW*factorTimeLbToW);     }
+   double  getFactorForceWToLb()     { return 1.0/this->getFactorForceLbToW();                                         }
+
+   double  getFactorAccLbToW()       { return factorLengthLbToW/(factorTimeLbToW*factorTimeLbToW);                     }
+   double  getFactorAccWToLb()       { return 1.0/this->getFactorAccLbToW();                                           }
+
+   double  getFactorTimeLbToW(double deltaX)        const { return factorTimeWithoutDx * deltaX;             }
+   //////////////////////////////////////////////////////////////////////////
+   double  getFactorVelocityLbToW2() { return factorVelocityLbToW; }
+   double  getFactorDensityLbToW2()  { return factorDensityLbToW;  }
+   double  getFactorPressureLbToW2() { return factorPressureLbToW; }
+   
+
+
+   /*==========================================================*/
+   friend inline std::ostream& operator << (std::ostream& os, LBMUnitConverter c) 
+   {
+      os<<c.toString();
+      return os;
+   }
+   /*==========================================================*/
+   std::string toString() 
+   {
+      std::ostringstream out;
+      out<<"LB --> WORLD" << std::endl;
+      out<<" * lentgh 1[dx  ] = " << std::setw(12) << this->getFactorLentghLbToW()    << " [m   ] " << std::endl;
+      out<<" * time   1[dt  ] = " << std::setw(12) << this->getFactorTimeLbToW()      << " [s   ] " << std::endl;
+      out<<" * mass   1[mass] = " << std::setw(12) << this->getFactorMassLbToW()      << " [kg  ] " << std::endl;
+      out<<std::endl;                                                       
+      out<<"WORLD --> LB" << std::endl;                                     
+      out<<" * lentgh 1[m   ] = " << std::setw(12) << this->getFactorLentghWToLb()    << " [dx  ] " << std::endl;
+      out<<" * time   1[s   ] = " << std::setw(12) << this->getFactorTimeWToLb()      << " [dt  ] " << std::endl;
+      out<<" * mass   1[kg  ] = " << std::setw(12) << this->getFactorMassWToLb()      << " [mass] " << std::endl;
+      out<<std::endl;
+      out<<"LB --> WORLD (combined units)" << std::endl;
+      out<<" * velocity     1 [dx/dt    ] = " << std::setw(12) << this->getFactorVelocityLbToW()  << " [m/s      ]" << std::endl;
+      out<<" * density      1 [mass/dx^3] = " << std::setw(12) << this->getFactorDensityLbToW()   << " [kg/m^3   ]" << std::endl;
+      out<<" * pressure     1 [F_lb/dx^2] = " << std::setw(12) << this->getFactorPressureLbToW()  << " [N/m^2    ]" << std::endl;
+      out<<" * viscosity    1 [dx^2/dt  ] = " << std::setw(12) << this->getFactorViscosityLbToW() << " [m^2/s    ]" << std::endl;
+      out<<" * force        1 [F_lb     ] = " << std::setw(12) << this->getFactorForceLbToW()     << " [N        ]" << std::endl;
+      out<<" * acceleration 1 [dx/dt^2  ] = " << std::setw(12) << this->getFactorAccLbToW()       << " [m/s^2    ]" << std::endl;
+      out<<std::endl;                                                                       
+      out<<"WORLD --> LB (combined units)" << std::endl;                                    
+      out<<" * velocity     1 [m/s      ] = " << std::setw(12) << this->getFactorVelocityWToLb()  << " [dx/dt    ]" << std::endl;
+      out<<" * density      1 [kg/m^3   ] = " << std::setw(12) << this->getFactorDensityWToLb()   << " [mass/dx^3]" << std::endl;
+      out<<" * pressure     1 [N/m^2    ] = " << std::setw(12) << this->getFactorPressureWToLb()  << " [F_lb/dx^2]" << std::endl;
+      out<<" * viscosity    1 [m^2/s    ] = " << std::setw(12) << this->getFactorViscosityWToLb() << " [dx^2/dt  ]" << std::endl;
+      out<<" * force        1 [N        ] = " << std::setw(12) << this->getFactorForceWToLb()     << " [F_lb     ]" << std::endl;
+      out<<" * acceleration 1 [m/s^2    ] = " << std::setw(12) << this->getFactorAccWToLb()       << " [dx/dt^2  ]" << std::endl;
+
+      return out.str();
+   }
+   /*==========================================================*/
+   virtual void write(UbFileOutput* out)
+   {
+      out->writeDouble(factorLengthLbToW);
+      out->writeDouble(factorTimeLbToW  );
+      out->writeDouble(factorMassLbToW  );
+   }
+   /*==========================================================*/
+   virtual void read(UbFileInput* in)
+   {
+      factorLengthLbToW = in->readDouble();
+      factorTimeLbToW   = in->readDouble();
+      factorMassLbToW   = in->readDouble();
+   }
+
+
+
+   void init(  const double& refLengthWorld, const double& csWorld, const double& rhoWorld, const double& vWorld, 
+               const double& refLengthLb, const double& rhoLb, const double& vLb  )
+   {
+      factorLengthLbToW = refLengthWorld / refLengthLb;
+      factorTimeLbToW   = vLb / vWorld * factorLengthLbToW;
+      factorMassLbToW   = rhoWorld/rhoLb*factorLengthLbToW*factorLengthLbToW*factorLengthLbToW;
+      factorTimeWithoutDx=vLb/vWorld;
+      this->refRhoLb = rhoLb;
+   }
+   protected:
+   double factorLengthLbToW;
+   double factorTimeLbToW;
+   double factorMassLbToW;
+   double refRhoLb;
+   double factorTimeWithoutDx;
+   
+   double factorVelocityLbToW;
+   double factorViscosityLbToW;
+   double factorDensityLbToW;
+   double factorPressureLbToW;
+
+   private:
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int version)
+      {
+         ar & factorLengthLbToW;
+         ar & factorTimeLbToW;
+         ar & factorMassLbToW;
+         ar & refRhoLb;
+         ar & factorTimeWithoutDx;
+         ar & factorVelocityLbToW;
+         ar & factorViscosityLbToW;
+         ar & factorDensityLbToW;
+         ar & factorPressureLbToW;
+      }
+};
+
+#endif //LBMUNITCONVERTER_H
diff --git a/source/VirtualFluidsCore/LBM/SimulationParameters.cpp b/source/VirtualFluidsCore/LBM/SimulationParameters.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..710cb0b3e38d6ad5d060d9e00d5717e9aa5a5a30
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/SimulationParameters.cpp
@@ -0,0 +1,98 @@
+#include "SimulationParameters.h"
+
+SimulationParametersPtr SimulationParameters::instanz;
+
+SimulationParameters::SimulationParameters()
+{
+   _collisionModel = UNDEFINED;
+   _viscosity = 0.0;
+   _rho = 0.0;
+   _vx1 = 0.0;
+   _vx3 = 0.0;
+}
+//////////////////////////////////////////////////////////////////////////
+SimulationParameters::~SimulationParameters()
+{}
+//////////////////////////////////////////////////////////////////////////
+SimulationParametersPtr SimulationParameters::getInstanz()
+{
+   if( instanz == 0 )
+      instanz = SimulationParametersPtr(new SimulationParameters());
+   return instanz;
+}
+//////////////////////////////////////////////////////////////////////////
+SimulationParameters::CollisionModelType  SimulationParameters::getCollisionModelType()
+{ 
+   return _collisionModel;           
+}
+//////////////////////////////////////////////////////////////////////////
+void SimulationParameters::setCollisionModelType(SimulationParameters::CollisionModelType collisionModel)  
+{ 
+   _collisionModel = collisionModel; 
+}
+//////////////////////////////////////////////////////////////////////////
+bool SimulationParameters::isCompressibleModel()
+{
+   if(_collisionModel == COMPRESSIBLE) 
+      return true;
+   else
+      return false;
+}
+//////////////////////////////////////////////////////////////////////////
+bool SimulationParameters::isIncompressibleModel()
+{
+   if(_collisionModel == INCOMPRESSIBLE) 
+      return true;
+   else
+      return false;
+}
+//////////////////////////////////////////////////////////////////////////
+void SimulationParameters::setViscosity( double viscosity)
+{
+   _viscosity = viscosity;
+}
+//////////////////////////////////////////////////////////////////////////
+double SimulationParameters::getViscosity()
+{
+   return _viscosity;
+}
+//////////////////////////////////////////////////////////////////////////
+void SimulationParameters::setRho( double rho)
+{
+   _rho = rho;
+}
+//////////////////////////////////////////////////////////////////////////
+double SimulationParameters::getRho()
+{
+   return _rho;
+}
+//////////////////////////////////////////////////////////////////////////
+void SimulationParameters::setVelocityX( double velocity)
+{
+   _vx1 = velocity;
+}
+//////////////////////////////////////////////////////////////////////////
+double SimulationParameters::getVelocityX()
+{
+   return _vx1;
+}
+//////////////////////////////////////////////////////////////////////////
+void SimulationParameters::setVelocityY( double velocity)
+{
+   _vx2 = velocity;
+}
+//////////////////////////////////////////////////////////////////////////
+double SimulationParameters::getVelocityY()
+{
+   return _vx2;
+}
+//////////////////////////////////////////////////////////////////////////
+void SimulationParameters::setVelocityZ( double velocity)
+{
+   _vx3 = velocity;
+}
+//////////////////////////////////////////////////////////////////////////
+double SimulationParameters::getVelocityZ()
+{
+   return _vx3;
+}
diff --git a/source/VirtualFluidsCore/LBM/SimulationParameters.h b/source/VirtualFluidsCore/LBM/SimulationParameters.h
new file mode 100644
index 0000000000000000000000000000000000000000..2096994fcc3edeabe593ef0f8d29e86e3c8b5031
--- /dev/null
+++ b/source/VirtualFluidsCore/LBM/SimulationParameters.h
@@ -0,0 +1,44 @@
+#ifndef SIMULATIONPARAMETERS_H 
+#define SIMULATIONPARAMETERS_H
+
+#include <boost/shared_ptr.hpp>
+class SimulationParameters;
+typedef boost::shared_ptr<SimulationParameters> SimulationParametersPtr;
+
+//TODO move to LBMKernel
+
+class SimulationParameters
+{
+public:
+   enum CollisionModelType { UNDEFINED, INCOMPRESSIBLE, COMPRESSIBLE};
+public:
+   ~SimulationParameters();
+   static SimulationParametersPtr getInstanz();
+   CollisionModelType  getCollisionModelType();
+   void setCollisionModelType(CollisionModelType collisionModel);
+   bool isCompressibleModel();
+   bool isIncompressibleModel();
+   void setViscosity(double viscosity);
+   double getViscosity();
+   void setRho(double rho);
+   double getRho();
+   void setVelocityX(double velocity);
+   double getVelocityX();
+   void setVelocityY(double velocity);
+   double getVelocityY();
+   void setVelocityZ(double velocity);
+   double getVelocityZ();
+protected:
+private:
+   static SimulationParametersPtr instanz;
+   SimulationParameters();
+   //SimulationParameters(const SimulationParameters&);
+   CollisionModelType _collisionModel;
+   double _viscosity;
+   double _rho;
+   double _vx1;
+   double _vx2;
+   double _vx3;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/BlocksDistributor.cpp b/source/VirtualFluidsCore/Parallel/BlocksDistributor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d741a82dc9a45a9befea6709b4e215d2d71d2d00
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/BlocksDistributor.cpp
@@ -0,0 +1,7 @@
+#include "BlocksDistributor.h"
+
+BlocksDistributor::BlocksDistributor(Grid3DPtr grid, CommunicatorPtr comm) : grid(grid), comm(comm)
+{
+
+}
+
diff --git a/source/VirtualFluidsCore/Parallel/BlocksDistributor.h b/source/VirtualFluidsCore/Parallel/BlocksDistributor.h
new file mode 100644
index 0000000000000000000000000000000000000000..52063ff9bc7e147560c4d2f684705df3da97092a
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/BlocksDistributor.h
@@ -0,0 +1,26 @@
+#ifndef BlocksDistributor_H
+#define BlocksDistributor_H
+
+#include "Communicator.h"
+#include "Grid3D.h"
+
+#include <boost/shared_ptr.hpp>
+
+class BlocksDistributor;
+typedef boost::shared_ptr<BlocksDistributor> BlocksDistributorPtr;
+
+class BlocksDistributor
+{
+public:
+   BlocksDistributor(Grid3DPtr grid, CommunicatorPtr comm);
+   ~BlocksDistributor();
+
+protected:
+private:
+   Grid3DPtr grid;
+   CommunicatorPtr comm;
+};
+
+#endif
+
+
diff --git a/source/VirtualFluidsCore/Parallel/CMakePackage.txt b/source/VirtualFluidsCore/Parallel/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Parallel/Communicator.cpp b/source/VirtualFluidsCore/Parallel/Communicator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b0b8951a90eaeb14b6cd85ea738c7b2b331e740
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/Communicator.cpp
@@ -0,0 +1,12 @@
+#include "Communicator.h"
+#include <basics/utilities/UbException.h>
+
+CommunicatorPtr Communicator::instance = CommunicatorPtr();
+//////////////////////////////////////////////////////////////////////////
+CommunicatorPtr Communicator::getInstance()
+{
+   if( !instance )
+      UB_THROW(UbException(UB_EXARGS,"Communicator isn't initialized correctly! You can not create a new instance of abstract Communicator class!"));
+   return instance;
+}
+
diff --git a/source/VirtualFluidsCore/Parallel/Communicator.h b/source/VirtualFluidsCore/Parallel/Communicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..a22e0d9187946cb5d644060bfb43167a9b03c0fb
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/Communicator.h
@@ -0,0 +1,51 @@
+#ifndef COMMUNICATOR_H
+#define COMMUNICATOR_H
+
+#include <vector>
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+class Communicator;
+typedef boost::shared_ptr<Communicator> CommunicatorPtr;
+
+class Communicator
+{
+public:
+   virtual ~Communicator(){}
+   static CommunicatorPtr getInstance();
+   virtual int getBundleID() = 0;
+   virtual int getNumberOfBundles() = 0;
+   virtual int getProcessID() = 0;
+   virtual int getProcessID(int bundle, int rank) = 0;
+   virtual int getNumberOfProcesses() = 0;
+   virtual void* getNativeCommunicator() = 0;
+
+   virtual void sendSerializedObject(std::stringstream& ss, int target) = 0;
+   virtual void receiveSerializedObject(std::stringstream& ss, int source) = 0;
+
+   virtual int getRoot() = 0;
+   virtual int getBundleRoot() = 0;
+   virtual int getProcessRoot() = 0;
+   virtual int getNumberOfProcessesInBundle(int bundle) = 0;
+   virtual void barrier() = 0;
+
+   virtual std::vector<std::string> gather(const std::string& str) = 0;
+   virtual std::vector<int> gather(std::vector<int>& values) = 0;
+   virtual std::vector<float> gather(std::vector<float>& values) = 0;
+   virtual std::vector<double> gather(std::vector<double>& values) = 0;
+
+   virtual void allGather(std::vector<int>& svalues, std::vector<int>& rvalues) = 0;
+   virtual void allGather(std::vector<float>& svalues, std::vector<float>& rvalues) = 0;
+   virtual void allGather(std::vector<double>& svalues, std::vector<double>& rvalues) = 0;
+   
+   virtual void broadcast(std::vector<int>& values) = 0;
+   virtual void broadcast(std::vector<float>& values) = 0;
+   virtual void broadcast(std::vector<double>& values) = 0;
+protected:
+   Communicator(){}
+   static CommunicatorPtr instance;
+private:
+};
+
+#endif
+
diff --git a/source/VirtualFluidsCore/Parallel/LoadBalancer.cpp b/source/VirtualFluidsCore/Parallel/LoadBalancer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4b3f2049b70b9ea34d737057cf407f3957c724b4
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/LoadBalancer.cpp
@@ -0,0 +1,507 @@
+#if defined VF_MPI
+
+#include "LoadBalancer.h"
+#include <boost/foreach.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/algorithm/string.hpp>
+#include "MPICommunicator.h"
+#include "MathUtil.hpp"
+
+//#include "BoostSerializationClassExportHelper.h"
+
+LoadBalancer::LoadBalancer(Grid3DPtr grid, CommunicatorPtr comm, const int& endDir) : 
+grid(grid),   
+comm(comm),
+endDir(endDir)
+{
+   mpi_comm = *((MPI_Comm*) comm->getNativeCommunicator());
+   processID = comm->getProcessID();
+   int size = comm->getNumberOfProcesses();
+   converged.resize(size,0);
+}
+//////////////////////////////////////////////////////////////////////////
+LoadBalancer::~LoadBalancer()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+bool LoadBalancer::balance()
+{
+   if (!isConverged())
+   {
+      //std::cout << "is not converged" << std::endl;
+      if(processID == 0)
+         UBLOG(logINFO,"is not converged");
+      collectData();
+      collectNeighboursLoad();
+      prepareToSendLoad();
+      prepareToRecieveLoad();
+      sendRecieveLoad();
+      saveRecievedLoad();
+      //MPI_Barrier(mpi_comm);
+      //std::cout<< "MPI_Barrier: PID = " << processID <<std::endl;
+      return false;
+   }
+   else
+   {
+      //std::cout << "is converged" << std::endl;
+      if(processID == 0)
+         UBLOG(logINFO,"is converged");
+      return true;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::prepareToSendLoad()
+{
+   sendBuffer.clear();
+   removeBlocksSend.resize(0);
+   int conv = 1;
+   BOOST_FOREACH(NeighbourProcess neighbProzess, neighbourProcesses)
+   {
+      if (this->load != neighbProzess.load)
+      {
+         if(neighbProzess.load < this->load)
+         {
+            //std::cout<<"rank = " << comm->getProcessID() << " : send Abweichung =  " << (this->load/neighbProzess.load - 1.0)*100.0 <<std::endl;
+            if ((static_cast<double>(this->load)/static_cast<double>(neighbProzess.load) - 1.0)*100.0 > 3.0)
+            {
+               //if(processID == 0)
+                  UBLOG(logINFO,"rank = " << comm->getProcessID() << " : send Abweichung =  " << (this->load/neighbProzess.load - 1.0)*100.0);
+               double  transLoad = (this->load - neighbProzess.load)/2;
+               prepareToSendLoad(neighbProzess.processID, transLoad, conv);
+            }
+         }
+      }
+   }
+   setConverged(conv);
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::prepareToSendLoad(const int& nProcessID, const double& transLoad, int& conv)
+{
+   if((itnMap = neighboursMap.find(nProcessID)) != neighboursMap.end())
+   {
+      TransferBuffer sbuf;
+      std::vector<Block3DPtr> sendBlocks;
+      BBlocks &boundaryBlocks = itnMap->second;
+      TBlocks tBlocks;
+      std::stringstream  ss_out;
+
+      std::string str_out;
+
+      BOOST_FOREACH(LoadBalancer::BBlocks::value_type b, boundaryBlocks)
+      {
+         TransferBlock &tBlock = b.second;
+         tBlocks.insert(std::make_pair(tBlock.weight, tBlock));
+      }
+
+      double lsum = 0;
+      BOOST_FOREACH(LoadBalancer::TBlocks::value_type t, tBlocks)
+      {
+         TransferBlock &tBlock = t.second;
+         lsum += tBlock.load;
+
+         if(lsum >= transLoad)
+            break;
+
+         sendBlocks.push_back(tBlock.block);
+         BOOST_FOREACH(BBlocksMap::value_type &bbm, neighboursMap)
+            bbm.second.erase(tBlock.block);
+
+         //if(lsum >= transLoad)
+         //   break;
+      }
+      if (sendBlocks.size() > 0)
+      {
+         boost::archive::text_oarchive oa(ss_out);
+         oa.register_type<Block3D>();
+
+         BOOST_FOREACH(Block3DPtr b, sendBlocks)
+         {
+            oa << b;
+         }
+
+         sbuf.sbuffer = ss_out.str();
+         sbuf.sbufferSize = static_cast<int> (sbuf.sbuffer.length()); 
+         sbuf.blocksSize = static_cast<int>(sendBlocks.size());
+
+         sbuf.comFlag = 1;
+         sendBuffer.insert(std::make_pair(nProcessID, sbuf));
+
+         BOOST_FOREACH(Block3DPtr b, sendBlocks)
+         {
+            b->deleteKernel();
+            b->setRank(nProcessID);
+            b->deleteConnectors();
+            //b->deleteInterpolationConnectors();
+
+            removeBlocksSend.push_back(b->getX1());
+            removeBlocksSend.push_back(b->getX2());
+            removeBlocksSend.push_back(b->getX3());
+            removeBlocksSend.push_back(b->getLevel());
+            removeBlocksSend.push_back(b->getRank());
+
+            //std::cout<< "Send: PID = " << processID << " block: " <<b->toString()<<std::endl;
+         }
+         conv *= 0;
+      } 
+      else
+      {
+         sbuf.comFlag = 0;
+         sendBuffer.insert(std::make_pair(nProcessID, sbuf));
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::prepareToRecieveLoad()
+{
+   recieveBuffer.clear();
+   int conv = 1;
+   BOOST_FOREACH(NeighbourProcess neighbProzess, neighbourProcesses)
+   {
+      if (this->load != neighbProzess.load)
+      {
+         if(neighbProzess.load > this->load)
+         {
+            //std::cout<<"rank = " << comm->getProcessID() << " : recieve Abweichung =  " << (static_cast<double>(neighbProzess.load)/static_cast<double>(this->load) - 1.0)*100.0 <<std::endl;
+            if ((static_cast<double>(neighbProzess.load)/static_cast<double>(this->load) - 1.0)*100.0 > 3.0)
+            {
+               //if(processID == 0)
+                  UBLOG(logINFO,"rank = " << comm->getProcessID() << " : recieve Abweichung =  " << (static_cast<double>(neighbProzess.load)/static_cast<double>(this->load) - 1.0)*100.0);
+               conv *= 0;
+               TransferBuffer rbuf;
+               recieveBuffer.insert(std::make_pair(neighbProzess.processID, rbuf));
+            }
+         }
+      }
+   }
+   setConverged(conv);
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::sendRecieveLoad()
+{
+   std::vector<MPI_Request> request;
+   request.resize(0);
+   int rcount = 0;
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, recieveBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &rbuf = tb.second;
+      request.push_back(0);
+      MPI_Irecv(&rbuf.comFlag, 1, MPI_INT, nProcessID, 0, mpi_comm, &request[rcount]);
+      rcount++;
+   }
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, sendBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &sbuf = tb.second;
+      request.push_back(0);
+      MPI_Isend(&sbuf.comFlag, 1, MPI_INT, nProcessID, 0, mpi_comm, &request[rcount]);
+      rcount++;
+   }
+   if(request.size() > 0)
+      MPI_Waitall(static_cast<int>(request.size()), &request[0], MPI_STATUSES_IGNORE);
+
+   //UBLOG(logINFO,"rank = " << comm->getProcessID() << "sendRecieveLoad comFlag" );
+   //////////////////////////////////////////////////////////////////////////
+   request.resize(0);
+   rcount = 0;
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, recieveBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &rbuf = tb.second;
+      if (rbuf.comFlag == 1)
+      {
+         request.push_back(0);
+         MPI_Irecv(&rbuf.blocksSize, 1, MPI_INT, nProcessID, 0, mpi_comm, &request[rcount]);
+         rcount++;
+      }
+   }
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, sendBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &sbuf = tb.second;
+      if (sbuf.comFlag == 1)
+      {
+         request.push_back(0);
+         MPI_Isend(&sbuf.blocksSize, 1, MPI_INT, nProcessID, 0, mpi_comm, &request[rcount]);
+         rcount++;
+      }
+   }
+   if(request.size() > 0)
+      MPI_Waitall(static_cast<int>(request.size()), &request[0], MPI_STATUSES_IGNORE);
+   
+   //UBLOG(logINFO,"rank = " << comm->getProcessID() << "sendRecieveLoad blocksSize" );
+   //////////////////////////////////////////////////////////////////////////
+   request.resize(0);
+   rcount = 0;
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, recieveBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &rbuf = tb.second;
+      if (rbuf.comFlag == 1)
+      {
+         request.push_back(0);
+         MPI_Irecv(&rbuf.sbufferSize, 1, MPI_INT, nProcessID, 0, mpi_comm, &request[rcount]);
+         rcount++;
+      }
+   }
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, sendBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &sbuf = tb.second;
+      if (sbuf.comFlag == 1)
+      {
+         request.push_back(0);
+         MPI_Isend(&sbuf.sbufferSize,1,MPI_INT,nProcessID,0,mpi_comm,&request[rcount]);
+         rcount++;
+      }
+   }
+   if(request.size() > 0)
+      MPI_Waitall(static_cast<int>(request.size()), &request[0], MPI_STATUSES_IGNORE);
+
+   //UBLOG(logINFO,"rank = " << comm->getProcessID() << "sendRecieveLoad sbufferSize" );
+   //////////////////////////////////////////////////////////////////////////
+   request.resize(0);
+   rcount = 0;
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, recieveBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &rbuf = tb.second;
+      if (rbuf.comFlag == 1)
+      {
+         request.push_back(0);
+         rbuf.sbuffer.resize(rbuf.sbufferSize);
+         MPI_Irecv((char *)rbuf.sbuffer.c_str(),rbuf.sbufferSize,MPI_CHAR,nProcessID,0,mpi_comm,&request[rcount]);
+         rcount++;
+      }
+   }
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, sendBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &sbuf = tb.second;
+      if (sbuf.comFlag == 1)
+      {
+         request.push_back(0);
+         MPI_Isend((char *)sbuf.sbuffer.c_str(),sbuf.sbufferSize,MPI_CHAR,nProcessID,0,mpi_comm,&request[rcount]);
+         rcount++;
+      }
+   }
+   if(request.size() > 0)
+      MPI_Waitall(static_cast<int>(request.size()), &request[0], MPI_STATUSES_IGNORE);
+
+   //UBLOG(logINFO,"rank = " << comm->getProcessID() << "sendRecieveLoad sbuffer" );
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::sendRecieveChanges()
+{
+   std::vector<int> removeBlocksRecieve;
+
+   //////////////////////////////////////////////////////////////////////////
+   //UBLOG(logINFO,"rank = " << comm->getProcessID() << "sendRecieveChanges" );
+   
+   comm->allGather(removeBlocksSend, removeBlocksRecieve);
+   
+   //////////////////////////////////////////////////////////////////////////
+   //UBLOG(logINFO,"rank = " << comm->getProcessID() << "allGatherInts removeBlocksRecieve" );
+
+   if(removeBlocksRecieve.size() >= 4)
+   {
+      for (int i = 0; i < removeBlocksRecieve.size(); i+=5)
+      {
+         Block3DPtr block = grid->getBlock(removeBlocksRecieve[i], removeBlocksRecieve[i+1], removeBlocksRecieve[i+2], removeBlocksRecieve[i+3]);
+         block->setRank(removeBlocksRecieve[i+4]);
+         //std::cout<< "RecieveChanges: PID = " << processID << " block: " <<block->toString()<<std::endl;
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::saveRecievedLoad()
+{
+   BOOST_FOREACH(TransferBufferMap::value_type &tb, recieveBuffer)
+   {
+      int nProcessID = tb.first;
+      TransferBuffer &rbuf = tb.second;
+
+      if (rbuf.comFlag == 1)
+      {
+         std::stringstream  ss_in;
+         ss_in.str(rbuf.sbuffer);
+
+         boost::archive::text_iarchive ia(ss_in);
+         ia.register_type<Block3D>();
+
+         for(int i = 0; i < rbuf.blocksSize; i++)
+         {
+            Block3DPtr block;
+            ia >> block;
+            block->setRank(this->processID);
+            grid->replaceBlock(block);
+            //std::cout<< "Receive: PID = " << processID << " block: " <<block->toString()<<std::endl;
+         }
+      }
+   }
+   sendRecieveChanges();
+}
+//////////////////////////////////////////////////////////////////////////
+bool LoadBalancer::isConverged()
+{
+   int conv = 1;
+   BOOST_FOREACH(int c, converged)
+      conv *= c;
+   
+   if(conv)
+      return true;
+   else
+      return false;
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::setConverged(int value)
+{
+   //UBLOG(logINFO,"rank = " << comm->getProcessID() << " setConverged start" );
+   converged.resize(comm->getNumberOfProcesses());
+   MPI_Allgather( &value, 1, MPI_INT, &converged[0], 1, MPI_INT, mpi_comm);
+   //UBLOG(logINFO,"rank = " << comm->getProcessID() << " setConverged end" );
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::collectData()
+{
+   neighboursMap.clear();
+
+   int weightScaleFactor = 8;
+
+   int blockRank = 0;
+   this->load = 0;
+
+   int gridRank = grid->getRank();
+
+   int minInitLevel = this->grid->getCoarsestInitializedLevel();
+   int maxInitLevel = this->grid->getFinestInitializedLevel();
+
+   for(int level = minInitLevel; level<=maxInitLevel;level++)
+   {
+      std::vector<Block3DPtr> blockVector;
+      grid->getBlocks(level, gridRank, true, blockVector);
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         if (block)
+         {
+            this->load += block->getWorkLoad();
+            blockRank  = block->getRank();
+            
+            //search  for parent block
+            Block3DPtr parentBlock = grid->getSuperBlock(block);
+            if(parentBlock)
+            {
+               int parentRank = parentBlock->getRank();
+               if(parentRank != blockRank && parentBlock->isActive())
+               {
+                  block->addWeight(parentRank, weightScaleFactor);
+                  addTransferBlock(block, parentRank);
+               }
+            }
+
+            //search for child blocks
+            std::vector<Block3DPtr> childBlocks;
+            grid->getSubBlocks(block, 1, childBlocks);
+            BOOST_FOREACH(Block3DPtr b, childBlocks)
+            {
+               int childRank = b->getRank();
+               if(childRank != blockRank && b->isActive())
+               {
+                  block->addWeight(childRank, weightScaleFactor);
+                  addTransferBlock(block, childRank);
+               }
+            }
+
+            //search for neighbor blocks
+            for( int dir = 0; dir <= endDir; dir++)
+            { 
+               Block3DPtr neighBlock = (grid->getNeighborBlock(dir, block->getX1(), block->getX2(), block->getX3(), block->getLevel()));
+               if(neighBlock)
+               {
+                  int neighBlockRank = neighBlock->getRank();
+                  if(blockRank != neighBlockRank && neighBlock->isActive())
+                  {
+                     addTransferBlock(block, neighBlockRank);
+                  }
+               }
+            }
+         }
+      }
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::collectNeighboursLoad()
+{
+   loadThreshold = 0;
+   neighbourProcesses.resize(0);
+   BOOST_FOREACH(BBlocksMap::value_type b,  neighboursMap)
+   {
+      int neighbourProcessID = b.first;
+      NeighbourProcess nProc;
+      nProc.processID = neighbourProcessID;
+      neighbourProcesses.push_back(nProc);
+   }
+   //std::cout<<"rank = " << comm->getProcessID() << " : this->load =  " << this->load <<std::endl;
+   //if(processID == 0)
+      UBLOG(logINFO, "rank = " << comm->getProcessID() << " : this->load =  " << this->load);
+
+   std::vector<MPI_Request> request;
+   request.resize(0);
+   int rcount = 0;
+
+   BOOST_FOREACH(NeighbourProcess &np, neighbourProcesses)
+   {
+      request.push_back(0);
+      MPI_Irecv(&np.load, 1, MPI_DOUBLE, np.processID, 0, mpi_comm, &request[rcount]);
+      rcount++;
+      //UBLOG(logINFO,"rank = " << comm->getProcessID() << " : MPI_Irecv from " << np.processID);
+      request.push_back(0);
+      MPI_Isend(&load, 1, MPI_DOUBLE, np.processID, 0, mpi_comm, &request[rcount]);
+      rcount++;
+      //UBLOG(logINFO,"rank = " << comm->getProcessID() << " : MPI_Isend to " << np.processID);
+   }
+   
+   if(request.size() > 0)
+      MPI_Waitall(static_cast<int>(request.size()), &request[0], MPI_STATUSES_IGNORE);
+
+   BOOST_FOREACH(NeighbourProcess &np, neighbourProcesses)
+   {
+      loadThreshold += np.load;
+      //std::cout<<"rank = " << comm->getProcessID() << " : neighbor process load =  " << np.load <<std::endl;
+      //UBLOG(logINFO,"rank = " << comm->getProcessID() << " : neighbor process load =  " << np.load);
+   }
+   loadThreshold += this->load;
+   //int allLoad = loadThreshold;
+   loadThreshold /= (static_cast<int>(neighbourProcesses.size()) + 1);
+   //loadThresholdP = MathUtil::cint(static_cast<double>(loadThreshold)*100.0/static_cast<double>(allLoad));
+   //loadP = MathUtil::cint(static_cast<double>(load)*100.0/static_cast<double>(allLoad));
+
+   //std::cout<<"rank = " << comm->getProcessID() << " : this->loadThresholdP =  " << this->loadThresholdP <<std::endl;
+   //std::cout<<"rank = " << comm->getProcessID() << " : this->loadP =  " << this->loadP <<std::endl;
+   //std::cout<<"rank = " << comm->getProcessID() << " : allLoad =  " << allLoad <<std::endl;
+}
+//////////////////////////////////////////////////////////////////////////
+void LoadBalancer::addTransferBlock(Block3DPtr block, int neighBlockRank)
+{
+   TransferBlock tBlock;
+   tBlock.block = block;
+   tBlock.load = block->getWorkLoad();
+   tBlock.weight = block->getWeight(neighBlockRank);
+
+   if((itnMap = neighboursMap.find(neighBlockRank)) == neighboursMap.end())
+   {
+      BBlocks boundaryBlocks;
+      boundaryBlocks.insert(std::make_pair(block, tBlock));
+      neighboursMap.insert(std::make_pair(neighBlockRank, boundaryBlocks));
+   }
+   else
+   {
+      BBlocks &boundaryBlocks = itnMap->second;
+      boundaryBlocks.insert(std::make_pair(block, tBlock));
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/LoadBalancer.h b/source/VirtualFluidsCore/Parallel/LoadBalancer.h
new file mode 100644
index 0000000000000000000000000000000000000000..f770554887e98515a74228f537c9df07923a219c
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/LoadBalancer.h
@@ -0,0 +1,103 @@
+#ifndef LOADBALANCER_H
+#define LOADBALANCER_H
+
+#if defined VF_MPI
+
+#include <vector>
+#include <map>
+#include "Block3D.h"
+#include "Communicator.h"
+#include "MPICommunicator.h"
+#include "Grid3D.h"
+
+struct NeighbourProcess
+{
+   int processID;
+   double load;
+};
+
+struct ltweight
+{
+   bool operator()(const int l1, const int l2) const
+   {
+      return (l1 > l2);
+   }
+};
+
+struct TransferBuffer
+{
+   int comFlag; //communication on = 1, communication off = 0
+   int blocksSize;
+   int sbufferSize;
+   std::string sbuffer;
+};
+
+struct  TransferBlock
+{
+   double load;
+   int weight;
+   Block3DPtr block;
+};
+
+#include <boost/smart_ptr.hpp>
+class LoadBalancer;
+typedef boost::shared_ptr<LoadBalancer> LoadBalancerPtr;
+
+class LoadBalancer
+{
+public:
+   // boundary blocks:    block, load
+   //typedef std::map< Block3DPtr, int> BBlocks;
+   typedef std::map< Block3DPtr, TransferBlock> BBlocks;
+   //typedef std::set< TransferBlock > BBlocks;
+   //           neighbor, boundary blocks
+   typedef std::map< int, BBlocks > BBlocksMap;
+   //transfer blocks: weight, transfer block, sort function
+   typedef std::multimap< int, TransferBlock, ltweight> TBlocks;
+   //          neighbor,buffer    
+   typedef std::map<int, TransferBuffer> TransferBufferMap;
+public:
+   LoadBalancer(Grid3DPtr grid, CommunicatorPtr comm, const int& endDir);
+   virtual ~LoadBalancer();
+   bool balance();
+
+protected:
+private:
+   void callculateLoad();
+   void collectData();
+   void collectNeighboursLoad();
+   void prepareToSendLoad();
+   void prepareToSendLoad(const int& nProcessID, const double& transLoad, int& conv);
+   void prepareToRecieveLoad();
+   void sendRecieveLoad();
+   void saveRecievedLoad();
+   void sendRecieveChanges();
+   bool isConverged();
+   void setConverged(int value);
+   void addTransferBlock(Block3DPtr block, int neighBlockRank);
+   double load;
+   int processID;
+   double loadThreshold;
+   int loadThresholdP;
+   int loadP;
+   std::vector<NeighbourProcess> neighbourProcesses;
+   Grid3DPtr grid;
+   CommunicatorPtr comm;
+   BBlocksMap neighboursMap;
+   BBlocksMap::iterator itnMap;
+   BBlocks::iterator itbBlocks;
+   int endDir;
+
+   MPI_Comm mpi_comm;
+
+   TransferBufferMap sendBuffer;
+   TransferBufferMap recieveBuffer;
+
+   std::vector<int> removeBlocksSend;
+   
+   std::vector<int> converged;
+};
+
+#endif
+
+#endif 
diff --git a/source/VirtualFluidsCore/Parallel/MPICommunicator.cpp b/source/VirtualFluidsCore/Parallel/MPICommunicator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..75fa561c4e29ce6045996915e4690b049db67d16
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/MPICommunicator.cpp
@@ -0,0 +1,200 @@
+#if defined VF_MPI
+
+#include "MPICommunicator.h"
+#include <mpi.h>
+#include <boost/foreach.hpp>
+#include <sstream>
+using namespace std;
+//////////////////////////////////////////////////////////////////////////
+MPICommunicator::MPICommunicator()
+{
+   //proof if MPI is initialized 
+   int mpiInitialized = (int)false;
+   MPI_Initialized(&mpiInitialized);
+   if (!mpiInitialized)
+   {
+      //MPI_Init(0, 0);	
+      MPI_Init_thread(NULL, NULL, MPI_THREAD_FUNNELED, NULL);
+   }
+   MPI_Comm_rank(MPI_COMM_WORLD, &PID);
+   MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
+   comm = MPI_COMM_WORLD;
+   root = 0;
+}
+//////////////////////////////////////////////////////////////////////////
+MPICommunicator::~MPICommunicator()
+{
+   //proof if MPI is finalized
+   int _mpiFinalized = (int)false;
+   MPI_Finalized(&_mpiFinalized);
+   if (!_mpiFinalized)
+   {
+      MPI_Finalize();
+   }
+ }
+//////////////////////////////////////////////////////////////////////////
+CommunicatorPtr MPICommunicator::getInstance()
+{
+   if( !Communicator::instance )
+      Communicator::instance = CommunicatorPtr(new MPICommunicator());
+   return Communicator::instance;
+}
+////////////////////////////////////////////////////////////////////////////
+vector<string> MPICommunicator::gather(const string& str)
+{
+   vector<string> parts;
+   vector<string> strings;
+   int scount;
+   vector<char> rbuf(1);
+   vector<int> rcounts(1);
+   MPI_Status status;
+
+   if (PID == root)
+   {
+      rcounts.resize(numprocs - 1);
+      strings.push_back(str);
+
+      for (int i = 1; i < numprocs; i++)
+      {
+         MPI_Recv(&rcounts[i-1], 1, MPI_INT, i, 0, comm, &status);
+      }
+      for (int i = 1; i < numprocs; i++)
+      {
+         rbuf.resize(rcounts[i-1]);
+         MPI_Recv(&rbuf[0], rcounts[i-1], MPI_CHAR, i, 0, comm, &status);
+         string s(&rbuf[0], rcounts[i-1]);
+         if (s != "") strings.push_back(s);
+      }
+   }
+   else
+   {
+      scount = (int)str.length();
+      MPI_Send(&scount, 1, MPI_INT, root, 0, comm);
+      MPI_Send((char *)str.c_str(), scount, MPI_CHAR, root, 0, comm);
+   }
+   return strings;
+}
+//////////////////////////////////////////////////////////////////////////
+vector<int> MPICommunicator::gather(vector<int>& values)
+{
+   return gather<int>(values);
+}
+//////////////////////////////////////////////////////////////////////////
+vector<float> MPICommunicator::gather(vector<float>& values)
+{
+   return gather<float>(values);
+}
+//////////////////////////////////////////////////////////////////////////
+vector<double> MPICommunicator::gather(vector<double>& values)
+{
+   return gather<double>(values);
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getProcessID()
+{
+   return PID;
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getProcessID(int bundle, int rank)
+{
+   return PID;
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getNumberOfProcesses()
+{
+   return numprocs;
+}
+//////////////////////////////////////////////////////////////////////////
+void* MPICommunicator::getNativeCommunicator()
+{
+   return &comm;
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getBundleID()
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getNumberOfBundles()
+{
+   return 1;
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getRoot() 
+{
+   return root;
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getBundleRoot() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getProcessRoot() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getNumberOfProcessesInBundle(int bundle)
+{
+   return numprocs;
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::sendSerializedObject( std::stringstream& ss, int target)
+{
+   string str = ss.str();
+   int scount = static_cast<int> (str.length());
+   MPI_Send(&scount,1,MPI_INT,target,0,comm);
+   MPI_Send((char *)str.c_str(),scount,MPI_CHAR,target,0,comm);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::receiveSerializedObject( std::stringstream& ss, int source )
+{
+   vector<char> rbuf;
+   int rcount;
+   MPI_Status status;
+   MPI_Recv(&rcount,1,MPI_INT,source,0,comm,&status);
+   rbuf.resize(rcount);
+   MPI_Recv(&rbuf[0],rcount,MPI_CHAR,source,0,comm,&status);
+   ss.rdbuf()->pubsetbuf(&rbuf[0],rcount);
+   string str (&rbuf[0]);
+   ss.str(str);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::barrier()
+{
+   MPI_Barrier(comm);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::allGather(std::vector<int>& svalues, std::vector<int>& rvalues)
+{
+   allGather<int>(svalues, rvalues);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::allGather(std::vector<float>& svalues, std::vector<float>& rvalues)
+{
+   allGather<float>(svalues, rvalues);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::allGather(std::vector<double>& svalues, std::vector<double>& rvalues)
+{
+   allGather<double>(svalues, rvalues);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(std::vector<int>& values)
+{
+   broadcast<int>(values);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(std::vector<float>& values)
+{
+   broadcast<float>(values);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(std::vector<double>& values)
+{
+   broadcast<double>(values);
+}
+//////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/MPICommunicator.h b/source/VirtualFluidsCore/Parallel/MPICommunicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..207c5ed6ef47b109be03964fefbaaf393eb49907
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/MPICommunicator.h
@@ -0,0 +1,162 @@
+#if defined VF_MPI
+
+#ifndef MPICOMMUNICATOR_H
+#define MPICOMMUNICATOR_H
+
+#include <mpi.h>
+#include <vector>
+#include <string>
+#include <boost/shared_ptr.hpp>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbLogger.h>
+#include "Communicator.h"
+
+class MPICommunicator;
+typedef boost::shared_ptr<MPICommunicator> MPICommunicatorPtr;
+
+//! \brief A class uses MPI library to communication.
+//! \details Support MPI communication. Implements singleton pattern.
+//! \author K. Kutscher
+
+class MPICommunicator : public Communicator
+{
+private:
+   MPICommunicator();
+public:
+   ~MPICommunicator();
+   static CommunicatorPtr getInstance();
+   int getBundleID();
+   int getNumberOfBundles();
+   int getProcessID();
+   int getProcessID(int bundle, int rank);
+   int getNumberOfProcesses();
+   void* getNativeCommunicator();
+   int getRoot();
+   int getBundleRoot();
+   int getProcessRoot();
+   int getNumberOfProcessesInBundle(int bundle);
+
+   void sendSerializedObject(std::stringstream& ss, int target);
+   void receiveSerializedObject(std::stringstream& ss, int source);
+
+   void barrier();
+
+   std::vector<std::string> gather(const std::string& str);
+   std::vector<int> gather(std::vector<int>& values);
+   std::vector<float> gather(std::vector<float>& values);
+   std::vector<double> gather(std::vector<double>& values);
+
+   void allGather(std::vector<int>& svalues, std::vector<int>& rvalues);
+   void allGather(std::vector<float>& svalues, std::vector<float>& rvalues);
+   void allGather(std::vector<double>& svalues, std::vector<double>& rvalues);
+
+   void broadcast(std::vector<int>& values);
+   void broadcast(std::vector<float>& values);
+   void broadcast(std::vector<double>& values);
+
+   template <class T>
+   std::vector<T> gather(std::vector<T>& values);
+
+   template <class T>
+   void allGather(std::vector<T>& svalues, std::vector<T>& rvalues);
+
+   template <class T>
+   void broadcast(std::vector<T>& values);
+private:
+   int numprocs, PID;
+   MPI_Comm comm;
+   int root;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+std::vector<T> MPICommunicator::gather(std::vector<T>& values)
+{
+   MPI_Datatype mpiDataType;
+   if ((std::string)typeid(T).name()==(std::string)typeid(double).name()) mpiDataType = MPI_DOUBLE;
+   else if ((std::string)typeid(T).name()==(std::string)typeid(float).name()) mpiDataType = MPI_FLOAT;
+   else if ((std::string)typeid(T).name()==(std::string)typeid(int).name()) mpiDataType = MPI_INT;
+   else throw UbException(UB_EXARGS, "no MpiDataType for T"+(std::string)typeid(T).name());
+
+   int count = static_cast<int> (values.size());
+   std::vector<T> rvalues(1);
+
+   if (PID == root)
+   {
+      rvalues.resize(numprocs*count);
+   }
+
+   MPI_Gather(&values[0], count, mpiDataType, &rvalues[0], count, mpiDataType, root, comm);
+
+   return rvalues;
+}
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void MPICommunicator::allGather(std::vector<T>& svalues, std::vector<T>& rvalues)
+{
+   MPI_Datatype mpiDataType;
+   if ((std::string)typeid(T).name()==(std::string)typeid(double).name()) mpiDataType = MPI_DOUBLE;
+   else if ((std::string)typeid(T).name()==(std::string)typeid(float).name()) mpiDataType = MPI_FLOAT;
+   else if ((std::string)typeid(T).name()==(std::string)typeid(int).name()) mpiDataType = MPI_INT;
+   else throw UbException(UB_EXARGS, "no MpiDataType for T"+(std::string)typeid(T).name());
+
+   int scount;
+   std::vector<int> displs, rcounts;
+
+   scount = (int)(svalues.size());
+
+   rcounts.resize(numprocs);
+   MPI_Allgather(&scount, 1, MPI_INT, &rcounts[0], 1, MPI_INT, comm);
+   displs.resize(numprocs);
+
+   displs[0] = 0;
+   for (int i=1; i<numprocs; ++i)
+   {
+      displs[i] = displs[i-1]+rcounts[i-1];
+   }
+
+   rvalues.resize(displs[numprocs-1]+rcounts[numprocs-1]);
+
+   if (rvalues.size() == 0)
+   {
+      rvalues.resize(1);
+      rvalues[0] = -999;
+   }
+   if (scount == 0)
+   {
+      svalues.resize(1);
+      svalues[0] = -999;
+   }
+
+   MPI_Allgatherv(&svalues[0], scount, mpiDataType, &rvalues[0], &rcounts[0], &displs[0], mpiDataType, comm);
+}
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void MPICommunicator::broadcast(std::vector<T>& values)
+{
+   MPI_Datatype mpiDataType;
+   if ((std::string)typeid(T).name()==(std::string)typeid(double).name()) mpiDataType = MPI_DOUBLE;
+   else if ((std::string)typeid(T).name()==(std::string)typeid(float).name()) mpiDataType = MPI_FLOAT;
+   else if ((std::string)typeid(T).name()==(std::string)typeid(int).name()) mpiDataType = MPI_INT;
+   else throw UbException(UB_EXARGS, "no MpiDataType for T"+(std::string)typeid(T).name());
+
+   int rcount;
+   if (this->PID == this->root)
+   {
+      rcount = (int)values.size();
+   }
+
+   MPI_Bcast(&rcount, 1, MPI_INT, this->root, comm);
+
+   if (this->PID != this->root)
+   {
+      values.resize(rcount);
+   }
+
+   MPI_Bcast(&values[0], (int)values.size(), mpiDataType, this->root, comm);
+}
+//////////////////////////////////////////////////////////////////////////
+
+#endif
+
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/MetisPartitioner.cpp b/source/VirtualFluidsCore/Parallel/MetisPartitioner.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2da4d4c7cf464b6d8f683b293eebdda0874ed171
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/MetisPartitioner.cpp
@@ -0,0 +1,68 @@
+#if defined VF_METIS
+
+#include "MetisPartitioner.h"
+
+
+MetisPartitioner::MetisPartitioner()
+{
+   METIS_SetDefaultOptions(options);
+   options[METIS_OPTION_NUMBERING] = 0;
+}
+//////////////////////////////////////////////////////////////////////////
+MetisPartitioner::~MetisPartitioner()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+idx_t* MetisPartitioner::getMetisOptions()
+{
+   return options;
+}
+//////////////////////////////////////////////////////////////////////////
+int MetisPartitioner::partition(int nofParts, MetisPartitioner::PartType ptype)
+{
+   int rc;
+   idx_t nvtxs = (idx_t)xadj.size()-1;  // number of nodes
+   idx_t ncon = (idx_t)vwgt.size()/nvtxs; // number Of node constraints;
+
+   part.resize(nvtxs);
+   int edgecutCount = 0;
+
+   switch (ptype)
+   {
+   case MetisPartitioner::RECURSIVE: 
+      if     ( nofParts <  1 ) UB_THROW( UbException(UB_EXARGS,"invalid nofParts<1") );
+      else if (nofParts == 1) { part.resize(nvtxs, 0); return 0; }
+      //else if( nofParts >  8 ) UBLOG(logWARNING, "MetisPartitioner::Recursive: !!!Warning!!!  best for nofParts<=8 --> Kway is maybe a better option");
+      
+      rc = METIS_PartGraphRecursive(&nvtxs, &ncon, &xadj[0], &adjncy[0],
+                                    &vwgt[0], &vsize[0], &adjwgt[0], &nofParts, 
+                                    &tpwgts[0], &ubvec[0], options, &edgecutCount, &part[0]);
+   	break;
+   case MetisPartitioner::KWAY: 
+      if     ( nofParts <  1 ) UB_THROW( UbException(UB_EXARGS,"invalid nofParts<1") );
+      else if (nofParts == 1) { part.resize(nvtxs, 0); return 0; }
+      //else if( nofParts <  9 ) UBLOG(logWARNING, "MetisPartitioner::Kway: !!!Warning!!!  best for nofParts>8 --> Recursive is maybe a better option");
+
+      rc = METIS_PartGraphKway(&nvtxs, &ncon, &xadj[0], &adjncy[0],
+                                &vwgt[0], &vsize[0], &adjwgt[0], &nofParts,
+                                &tpwgts[0], &ubvec[0], options, &edgecutCount, &part[0]);
+      break;
+   }
+
+   switch (rc)
+   {
+   case METIS_ERROR_INPUT:
+      throw UbException(UB_EXARGS,"METIS: input error");
+   	break;
+   case METIS_ERROR_MEMORY:
+      throw UbException(UB_EXARGS,"METIS: it could not allocate the required memory");
+      break;
+   case METIS_ERROR:
+      throw UbException(UB_EXARGS,"METIS: error");
+      break;
+   }
+
+   return edgecutCount;
+}
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/MetisPartitioner.h b/source/VirtualFluidsCore/Parallel/MetisPartitioner.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce889edfc3d0b2c0e12c569a9e221e05032f4975
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/MetisPartitioner.h
@@ -0,0 +1,61 @@
+/**
+* @file MetisPartitioner.h
+* @brief Class use METIS library for graph-based partitioning.
+* @author Kostyantyn Kucher
+* @date 22.09.2011
+*/
+
+#ifndef METISPARTITIONER_H
+#define METISPARTITIONER_H
+
+#if defined VF_METIS
+
+#include "metis.h"
+#include <vector>
+#include <string>
+#include <boost/shared_ptr.hpp>
+#include "basics/utilities/UbLogger.h"
+#include "basics/utilities/UbSystem.h"
+
+class MetisPartitioner;
+typedef boost::shared_ptr<MetisPartitioner> MetisPartitionerPtr;
+
+class MetisPartitioner
+{
+public:
+   enum PartType { RECURSIVE, KWAY };
+public:
+   MetisPartitioner();
+   virtual ~MetisPartitioner();
+   idx_t* getMetisOptions();
+   int partition(int nofParts, PartType ptype);
+public:
+   std::vector<idx_t> xadj;    // adjncy offset of nodes 
+   //(size = n+1, n=nofNodes)
+   std::vector<idx_t> adjncy;  // array that stores the adjacency lists of nodes 
+   //(size = m*2, m= nofEdged, factor 2 because edge A->B AND B->A has to be stored)
+   std::vector<idx_t> vwgt;    // vertex weights (size=n*ncon, ncon=nofNodeWeightsPerNode)
+   std::vector<idx_t> adjwgt;  // array that stores the weights of the adjacency lists 
+   // (size=2*m)
+   std::vector<idx_t> vsize;   // array that stores the computation weights per node
+   // (size=n)
+
+   std::vector<real_t> tpwgts; // holds the wished fratcion of segment i, e.g. tpwgts={0.2, 0.2, 0.6} 
+   // -> patisions 0 and one will get 20% of the weight each and part 3 60%!
+   // (size=nofPartitions)  sum of tpwgts must be 1.0
+
+   std::vector<real_t> ubvec;  //This is an array of size ncon that specifies the allowed load imbalance tolerance for each constraint.
+   //For the ith partition and jth constraint the allowed weight is the ubvec[j]*tpwgts[i*ncon+j] fraction
+   //of the jth’s constraint total weight. The load imbalances must be greater than 1.0.
+   //A NULL value can be passed indicating that the load imbalance tolerance for each constraint should
+   //be 1.001 (for ncon=1) or 1.01 (for ncon¿1).
+
+   std::vector<idx_t> part;   // This is a vector of size n that upon successful completion stores the partition vector of the graph. 
+   // The numbering of this vector starts from 0 
+private:
+   idx_t options[METIS_NOPTIONS];
+};
+
+#endif
+
+#endif 
diff --git a/source/VirtualFluidsCore/Parallel/NullCommunicator.cpp b/source/VirtualFluidsCore/Parallel/NullCommunicator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..527dc8753bf57c7ddfb4039c61b66aab96a75889
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/NullCommunicator.cpp
@@ -0,0 +1,74 @@
+#include "NullCommunicator.h"
+
+NullCommunicator::NullCommunicator()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+NullCommunicator::~NullCommunicator()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+int NullCommunicator::getBundleID() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int NullCommunicator::getNumberOfBundles() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int NullCommunicator::getProcessID() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int NullCommunicator::getNumberOfProcesses()
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+void* NullCommunicator::getNativeCommunicator()
+{
+   return NULL;
+}
+//////////////////////////////////////////////////////////////////////////
+int NullCommunicator::getRoot() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int NullCommunicator::getBundleRoot() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+int NullCommunicator::getProcessRoot() 
+{
+   return 0;
+}
+//////////////////////////////////////////////////////////////////////////
+std::vector<std::string> NullCommunicator::gather(const std::string& str)
+{
+   return std::vector<std::string>();
+}
+//////////////////////////////////////////////////////////////////////////
+std::vector<double> NullCommunicator::gatherDoubles(std::vector<double>& values) 
+{
+   return std::vector<double>();
+}
+//////////////////////////////////////////////////////////////////////////
+void NullCommunicator::allGatherInts(std::vector<int>& svalues, std::vector<int>& rvalues)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void NullCommunicator::sendSerializedObject(std::stringstream& ss, int target) 
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void NullCommunicator::receiveSerializedObject(std::stringstream& ss, int source) 
+{
+
+}
diff --git a/source/VirtualFluidsCore/Parallel/NullCommunicator.h b/source/VirtualFluidsCore/Parallel/NullCommunicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..9378f16cb6a5f1390c12afa07091f89ec8d810f0
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/NullCommunicator.h
@@ -0,0 +1,33 @@
+#ifndef NullCommunicator_H
+#define NullCommunicator_H
+
+#include "Communicator.h"
+
+#include <boost/shared_ptr.hpp>
+
+class NullCommunicator;
+typedef boost::shared_ptr<NullCommunicator> NullCommunicatorPtr;
+
+class NullCommunicator : public Communicator
+{
+public:
+   NullCommunicator();
+   ~NullCommunicator();
+   int getBundleID();
+   int getNumberOfBundles();
+   int getProcessID();
+   int getNumberOfProcesses();
+   void* getNativeCommunicator();
+   int getRoot();
+   int getBundleRoot();
+   int getProcessRoot();
+   std::vector<std::string> gather(const std::string& str);
+   std::vector<double> gatherDoubles(std::vector<double>& values); 
+   void allGatherInts(std::vector<int>& svalues, std::vector<int>& rvalues);
+   void sendSerializedObject(std::stringstream& ss, int target);
+   void receiveSerializedObject(std::stringstream& ss, int source);
+protected:
+private:
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/PriorityQueueDecompositor.cpp b/source/VirtualFluidsCore/Parallel/PriorityQueueDecompositor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..31083a2321fab5aa27522a396b2b97c521f9ee22
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/PriorityQueueDecompositor.cpp
@@ -0,0 +1,2 @@
+#include "PriorityQueueDecompositor.h"
+
diff --git a/source/VirtualFluidsCore/Parallel/PriorityQueueDecompositor.h b/source/VirtualFluidsCore/Parallel/PriorityQueueDecompositor.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b51c311631ac17b151a8ad0ab0a484d060d5779
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/PriorityQueueDecompositor.h
@@ -0,0 +1,68 @@
+/**
+* @file PriorityQueueDecompositor.h
+* @brief Priority Queue for threads decomposition.
+* @author Kostyantyn Kucher
+* @date 06/06/2011
+*/
+#ifndef PRIORITYQUEUEDECOMPOSITOR_H
+#define PRIORITYQUEUEDECOMPOSITOR_H
+
+#include <algorithm>
+#include <vector>
+#include <map>
+
+struct sortMinMax {
+   bool operator() (int i,int j) { return (i<j);}
+};
+
+struct sortMaxMin {
+   bool operator() (int i,int j) { return (i>j);}
+};
+
+template <class T>
+class PriorityQueueDecompositor
+{
+public:
+   PriorityQueueDecompositor(const std::vector<T>& objcts, const std::vector<int>& weights, const int& numberOfParts)
+   {
+      for (int i = 0; i < (int)objcts.size(); i++)
+      {
+         objects.insert(std::pair<int, T>(weights[i], objcts[i]));
+      }
+      for (int i = 0; i < numberOfParts; i++)
+      {
+         std::vector<T> part;
+         parts.insert(std::pair<int,std::vector<T> >(0, part));
+      }
+   }
+   virtual ~PriorityQueueDecompositor()
+   {
+
+   }
+   void getDecomposition(std::vector< std::vector<T> >& prts)
+   {
+      for( itOb=objects.begin() ; itOb != objects.end(); itOb++)
+      {
+         itP = parts.begin();
+         int weight = (*itP).first;
+         std::vector<T> obj = (*itP).second;
+         parts.erase(itP);
+         weight += (*itOb).first;
+         obj.push_back((*itOb).second);
+         parts.insert(std::pair<int,std::vector<T> >(weight, obj));
+      }
+
+      for( itP=parts.begin() ; itP != parts.end(); itP++)
+      {
+         prts.push_back((*itP).second);
+      }
+   }
+protected:
+private:
+   std::multimap<int, T, sortMaxMin> objects;
+   typename std::multimap<int, T, sortMaxMin>::iterator itOb;
+   std::multimap<int, std::vector<T>, sortMinMax> parts;
+   typename std::multimap<int, std::vector<T>, sortMinMax>::iterator itP;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/SimpleGeometricPartitioner.h b/source/VirtualFluidsCore/Parallel/SimpleGeometricPartitioner.h
new file mode 100644
index 0000000000000000000000000000000000000000..414b0a179e3072d978720095ef50b6a2acde354a
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/SimpleGeometricPartitioner.h
@@ -0,0 +1,97 @@
+/**
+* @file SimpleGeometricPartitioner.h
+* @author Kostyantyn Kucher
+* @date 06/06/2011
+*
+* @section DESCRIPTION
+*
+* This class make simple geometric partitioning.
+*/
+
+#ifndef SIMPLEGEOMETRICPARTITIONER_H 
+#define SIMPLEGEOMETRICPARTITIONER_H
+
+#include "basics/utilities/UbTuple.h"
+#include "basics/utilities/UbException.h"
+#include "MathUtil.hpp"
+
+class SimpleGeometricPartitioner
+{
+public:
+   static UbTupleInt3 createDimensions(const int& x, const int& y, const int& z, const int& numberOfProcess)
+   {
+      int xyz = x*y*z;
+
+      int p = numberOfProcess;
+
+      if (p == 1)
+         return UbTupleInt3(1, 1, 1);
+
+      double a = pow(p*pow(x,3.0)/xyz,1.0/3.0);
+      double b = pow(p*pow(y,3.0)/xyz,1.0/3.0);
+      double c = pow(p*pow(z,3.0)/xyz,1.0/3.0);
+
+      MaxDim maxDim;
+ 
+      if(c >= a && c >= b)
+         maxDim = cDim;
+      if(b >= a && b >= c)
+         maxDim = bDim;
+      if(a >= b && a >= c)
+         maxDim = aDim;
+
+      int dim1, dim2, dim3;
+      dim1 = (int)Utilities::cint(a);
+      dim2 = (int)Utilities::cint(b);
+      dim3 = (int)Utilities::cint(c);
+      if(dim1 <= 0) dim1 = 1;
+      if(dim2 <= 0) dim2 = 1;
+      if(dim3 <= 0) dim3 = 1;
+
+      switch (maxDim)
+      {
+      case aDim: 
+         dim1 = p/(dim2*dim3);
+         if (dim1*dim2*dim3 != p)
+         {
+            dim2 = 1;
+            dim3 = 1;
+            dim1 = p;
+         }
+         break;
+      case bDim: 
+         dim2 = p/(dim1*dim3);
+         if (dim1*dim2*dim3 != p)
+         {
+            dim1 = 1;
+            dim3 = 1;
+            dim2 = p;
+         }
+         break;
+      case cDim: 
+         dim3 = p/(dim1*dim2);
+         if (dim1*dim2*dim3 != p)
+         {
+            dim1 = 1;
+            dim2 = 1;
+            dim3 = p;
+         }
+         break;
+      }
+
+      if (dim1>x || dim2>y || dim3>z)
+      {
+         UB_THROW( UbException(UB_EXARGS,"Patch3DSegmentationHelper::createDimensions: Segmentation fault - bad number of prozess") );
+      }
+
+      UbTupleInt3 dims(dim1, dim2, dim3);
+      
+      return dims;
+   }
+
+protected:
+private:
+   enum MaxDim {aDim,bDim,cDim};
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/Synchronizer.h b/source/VirtualFluidsCore/Parallel/Synchronizer.h
new file mode 100644
index 0000000000000000000000000000000000000000..ae12bc862f5a9b7957240f0d4c71cbd098f620cd
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/Synchronizer.h
@@ -0,0 +1,67 @@
+#ifndef SYNCHRONIZER_H
+#define SYNCHRONIZER_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+
+
+class Synchronizer;
+typedef boost::shared_ptr<Synchronizer> SynchronizerPtr;
+
+class Synchronizer
+{
+public:
+   Synchronizer()
+      : threshold(0), count(0), generation(0)
+   {}
+
+   Synchronizer(int count)
+      : threshold(count), count(count), generation(0)
+   {}
+
+   ~Synchronizer() {}
+
+   void incNumberOfThreads()
+   {
+      threshold++;
+      count++;
+   }
+
+   void setNumberOfThreads(int count)
+   {
+      this->threshold = count;
+      this->count     = count;
+   }
+
+   bool wait()
+   {
+      boost::mutex::scoped_lock lock(mutex);
+      unsigned int gen = generation;
+
+      if (--count == 0)
+      {
+         generation++;
+         count = threshold;
+         cond.notify_all();
+         return true;
+      }
+
+      while (gen == generation)
+         cond.wait(lock);
+      return false;
+   }
+
+   boost::mutex               gmtx;
+private:
+   boost::mutex              mutex;
+   boost::condition_variable cond;
+
+   unsigned int threshold;
+   unsigned int count;
+   unsigned int generation;
+};
+
+
+#endif 
diff --git a/source/VirtualFluidsCore/Parallel/ZoltanPartitioner.cpp b/source/VirtualFluidsCore/Parallel/ZoltanPartitioner.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6935ab415852c84aff36aa28c99beec49e959bc5
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/ZoltanPartitioner.cpp
@@ -0,0 +1,203 @@
+#if defined VF_ZOLTAN && defined VF_MPI
+
+#include "ZoltanPartitioner.h"
+#include "StringUtil.hpp"
+#include <iostream>
+#include <stdlib.h>
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////
+ZoltanPartitioner::ZoltanPartitioner(MPI_Comm comm, int rank, int numberOfLocalParts): 
+                                    comm(comm), rank(rank), numberOfLocalParts(numberOfLocalParts),lb_approach("PARTITION")
+{
+   int rc;
+   float ver;
+
+   rc = Zoltan_Initialize(0, NULL, &ver);
+
+   if (rc != ZOLTAN_OK){
+      cout<<"Sorry, Zoltan can't be initialized\n"<<endl;
+      MPI_Finalize();
+      exit(0);
+   } 
+   /******************************************************************
+   ** Create a Zoltan library structure for this instance of load
+   ** balancing.  Set the parameters and query functions that will
+   ** govern the library's calculation.  See the Zoltan User's
+   ** Guide for the definition of these and many other parameters.
+   ******************************************************************/
+
+   zz = Zoltan_Create(comm);
+}
+//////////////////////////////////////////////////////////////////////////
+ZoltanPartitioner::~ZoltanPartitioner()
+{
+  Zoltan_Destroy(&zz);
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioner::partition()
+{
+   //General parameters
+   Zoltan_Set_Param(zz, "DEBUG_LEVEL", "0");
+   Zoltan_Set_Param(zz, "LB_METHOD", "GRAPH");
+   Zoltan_Set_Param(zz, "LB_APPROACH", lb_approach.c_str());
+   Zoltan_Set_Param(zz, "NUM_GID_ENTRIES", "1"); 
+   Zoltan_Set_Param(zz, "NUM_LID_ENTRIES", "1");
+   Zoltan_Set_Param(zz, "RETURN_LISTS", "ALL");
+   string nparts(StringUtil::toString<int>(numberOfLocalParts));
+   Zoltan_Set_Param(zz, "NUM_LOCAL_PARTS", nparts.c_str());
+
+   /* Query functions - defined in simpleQueries.h */
+
+   Zoltan_Set_Num_Obj_Fn(zz, get_number_of_vertices, &graph);
+   Zoltan_Set_Obj_List_Fn(zz, get_vertex_list, &graph);
+   Zoltan_Set_Num_Edges_Multi_Fn(zz, get_num_edges_list, &graph);
+   Zoltan_Set_Edge_List_Multi_Fn(zz, get_edge_list, &graph);
+   
+   /******************************************************************
+   ** Zoltan can now partition the graph.
+   ** In this case, we assume the number of partitions is
+   ** equal to the number of processes.  Process rank 0 will own
+   ** partition 0, process rank 1 will own partition 1, and so on.
+   ******************************************************************/
+
+   int rc = Zoltan_LB_Partition(zz, /* input (all remaining fields are output) */
+      &changes,        /* 1 if partitioning was changed, 0 otherwise */ 
+      &numGidEntries,  /* Number of integers used for a global ID */
+      &numLidEntries,  /* Number of integers used for a local ID */
+      &numImport,      /* Number of vertices to be sent to me */
+      &importGlobalGids,  /* Global IDs of vertices to be sent to me */
+      &importLocalGids,   /* Local IDs of vertices to be sent to me */
+      &importProcs,    /* Process rank for source of each incoming vertex */
+      &importToPart,   /* New partition for each incoming vertex */
+      &numExport,      /* Number of vertices I must send to other processes*/
+      &exportGlobalGids,  /* Global IDs of the vertices I must send */
+      &exportLocalGids,   /* Local IDs of the vertices I must send */
+      &exportProcs,    /* Process to which I send each of the vertices */
+      &exportToPart);  /* Partition to which each vertex will belong */
+
+
+
+   if (rc != ZOLTAN_OK){
+      cout << "Partitioning failed on process " << rank <<"\n" << endl;
+      MPI_Finalize();
+      Zoltan_Destroy(&zz);
+      exit(0);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioner::setLB_APPROACH(std::string lb_approach)
+{
+   this->lb_approach = lb_approach;
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioner::setNumberOfLocalParts(int numberOfLocalParts)
+{
+   this->numberOfLocalParts = numberOfLocalParts;
+}
+//////////////////////////////////////////////////////////////////////////
+// Application defined query functions //
+//////////////////////////////////////////////////////////////////////////
+int ZoltanPartitioner::get_number_of_vertices(void *data, int *ierr)
+{
+   ZoltanGraph *graph = (ZoltanGraph *)data;
+   *ierr = ZOLTAN_OK;
+   return graph->numLocalVertices;
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioner::get_vertex_list(void *data, int sizeGID, int sizeLID,
+                                        ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
+                                        int wgt_dim, float *obj_wgts, int *ierr)
+{
+   ZoltanGraph *graph = (ZoltanGraph *)data;
+   *ierr = ZOLTAN_OK;
+
+   /* In this case, return the IDs of our vertices, but no weights.
+   * Zoltan will assume equally weighted vertices.
+   */
+
+   for (int i=0; i<graph->numLocalVertices; i++){
+      globalID[i] = graph->vvertexGID[i];
+      localID[i] = i;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioner::get_num_edges_list(void *data, int sizeGID, int sizeLID,
+                                           int num_obj,
+                                           ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
+                                           int *numEdges, int *ierr)
+{
+   ZoltanGraph *graph = (ZoltanGraph *)data;
+
+   if ( (sizeGID != 1) || (sizeLID != 1) || (num_obj != graph->numLocalVertices)){
+      *ierr = ZOLTAN_FATAL;
+      return;
+   }
+
+   for (int i=0;  i < num_obj ; i++){
+      numEdges[i] = graph->vnumEdges[i];
+   }
+
+   *ierr = ZOLTAN_OK;
+   return;
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioner::get_edge_list(void *data, int sizeGID, int sizeLID,
+                                      int num_obj, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
+                                      int *num_edges,
+                                      ZOLTAN_ID_PTR nborGID, int *nborProc,
+                                      int wgt_dim, float *ewgts, int *ierr)
+{
+   int *nextNbor, *nextProc;
+
+   ZoltanGraph *graph = (ZoltanGraph *)data;
+   *ierr = ZOLTAN_OK;
+
+   if ( (sizeGID != 1) || (sizeLID != 1) || 
+      (num_obj != graph->numLocalVertices)||
+      (wgt_dim != 0)){
+         *ierr = ZOLTAN_FATAL;
+         return;
+   }
+
+   nextNbor = (int *)nborGID;
+   nextProc = nborProc;
+   
+   int n=0;
+   for (int i=0; i < num_obj; i++){
+
+      /*
+      * In this case, we are not setting edge weights.  Zoltan will
+      * set each edge to weight 1.0.
+      */
+
+      for (int j=0; j < num_edges[i]; j++){
+         nborGID[n] = graph->vnborGID[n];
+         nborProc[n] = graph->vnborProc[n];
+         n++;
+      }
+   }
+   return;
+}
+//////////////////////////////////////////////////////////////////////////
+ZoltanGraph* ZoltanPartitioner::getGraphData()
+{
+   return &graph;
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioner::getExportData(vector<int>& exportGlobalGids, vector<int>& exportToPart, vector<int>& exportProcs)
+{
+   for (int i = 0; i < this->numExport; i++)
+   {
+      exportGlobalGids.push_back(static_cast<int> (this->exportGlobalGids[i]));
+      exportToPart.push_back(this->exportToPart[i]);
+      exportProcs.push_back(this->exportProcs[i]);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+ bool ZoltanPartitioner::areChanges()
+ {
+     return static_cast<bool>(this->changes);
+ }
+#endif
diff --git a/source/VirtualFluidsCore/Parallel/ZoltanPartitioner.h b/source/VirtualFluidsCore/Parallel/ZoltanPartitioner.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f5d70d15bacaddb1d7ebcff0025c10b98218a4b
--- /dev/null
+++ b/source/VirtualFluidsCore/Parallel/ZoltanPartitioner.h
@@ -0,0 +1,74 @@
+/**
+* @file ZoltanPartitioner.h
+* @brief Class use Zoltan library for graph-based partitioning.
+* @author Kostyantyn Kucher
+* @date 10.06.2011
+*/
+
+#ifndef ZOLTANPARTITIONER_H
+#define ZOLTANPARTITIONER_H
+
+#if defined VF_ZOLTAN && defined VF_MPI
+
+#include "zoltan.h"
+#include <vector>
+#include <string>
+
+/* Structure to hold graph data */
+
+struct ZoltanGraph{
+   int numLocalVertices;        // total vertices in in this partition
+   std::vector<int> vvertexGID; // global ID of each of my vertices
+   std::vector<int> vnumEdges;  // number of Edges 
+   std::vector<int> vnborGID;   // global ID of neighbors
+   std::vector<int> vnborProc;  // process owning each nbor in nborGID
+};
+
+struct Zoltan_Output{
+   ZOLTAN_ID_PTR importGlobalGids, importLocalGids, exportGlobalGids, exportLocalGids;
+   int *importProcs, *importToPart, *exportProcs, *exportToPart;
+   int changes, numGidEntries, numLidEntries, numImport, numExport;
+};
+
+class ZoltanPartitioner
+{
+public:
+   ZoltanPartitioner(MPI_Comm comm , int rank, int numberOfLocalParts);
+   virtual ~ZoltanPartitioner();
+   void partition();
+   ZoltanGraph* getGraphData();
+   void setLB_APPROACH(std::string lb_approach);
+   void setNumberOfLocalParts(int numberOfLocalParts);
+   void getExportData(std::vector<int>& exportGlobalGids, std::vector<int>& exportToPart, std::vector<int>& exportProcs);
+   bool areChanges();
+
+protected:
+   static int get_number_of_vertices(void *data, int *ierr);
+   static void get_vertex_list(void *data, int sizeGID, int sizeLID,
+                  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
+                  int wgt_dim, float *obj_wgts, int *ierr);
+   static void get_num_edges_list(void *data, int sizeGID, int sizeLID,
+                     int num_obj,
+                     ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
+                     int *numEdges, int *ierr);
+   static void get_edge_list(void *data, int sizeGID, int sizeLID,
+               int num_obj, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
+               int *num_edges,
+               ZOLTAN_ID_PTR nborGID, int *nborProc,
+               int wgt_dim, float *ewgts, int *ierr);
+
+private:
+   MPI_Comm comm;
+   int rank;
+   int numberOfLocalParts;
+   struct Zoltan_Struct *zz;
+   std::string lb_approach;
+   ZOLTAN_ID_PTR importGlobalGids, importLocalGids, exportGlobalGids, exportLocalGids;
+   int *importProcs, *importToPart, *exportProcs, *exportToPart;
+   int changes, numGidEntries, numLidEntries, numImport, numExport;
+   ZoltanGraph graph;
+};
+
+#endif
+
+#endif 
diff --git a/source/VirtualFluidsCore/Utilities/CMakePackage.txt b/source/VirtualFluidsCore/Utilities/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Utilities/ChangeRandomQs.hpp b/source/VirtualFluidsCore/Utilities/ChangeRandomQs.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a4adf5a266d0ffd9f38eba5200aa51aa0eb29620
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/ChangeRandomQs.hpp
@@ -0,0 +1,51 @@
+#ifndef ChangeRandomQs_h__
+#define ChangeRandomQs_h__
+
+#include "LBMKernel3D.h"
+#include "D3Q27IntegrateValuesHelper.h"
+#include "D3Q27BoundaryCondition.h"
+#include "BCArray3D.h"
+#include "D3Q27ETBCProcessor.h"
+
+namespace Utilities
+{
+   void ChangeRandomQs(D3Q27IntegrateValuesHelperPtr integrateValues)
+   {
+      std::vector<CalcNodes> cnodes = integrateValues->getCNodes();
+      
+      BOOST_FOREACH(CalcNodes cn, cnodes)
+      {
+         LBMKernel3DPtr kernel = cn.block->getKernel();
+         BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+         BOOST_FOREACH(UbTupleInt3 node, cn.nodes)
+         {
+            D3Q27BoundaryConditionPtr bc = bcArray.getBC(val<1>(node), val<2>(node), val<3>(node));
+            if (bc)
+            {
+	            for (int fdir=D3Q27System::FSTARTDIR; fdir<=D3Q27System::FENDDIR; fdir++)
+	            {
+                  if (bc->hasNoSlipBoundaryFlag(fdir))
+                  {
+                     const int invDir = D3Q27System::INVDIR[fdir];
+                     float q = bc->getQ(invDir);
+                     //double r = (double)UbRandom::rand(-50, 50);
+                     float r = (float)UbRandom::rand(-10, 10);
+                     float q_temp = q + q/r;
+                     if (q_temp < 0.0)
+                     {
+                        q_temp = 0.0001f;
+                     }
+                     else if (q_temp > 1.0)
+                     {
+                        q_temp = 0.9999f;
+                     }
+                     bc->setQ(q_temp, fdir);
+                  }
+	            }
+            }
+         }
+      }
+   }
+
+}
+#endif // ChangeRandomQs_h__
diff --git a/source/VirtualFluidsCore/Utilities/ConfigFileReader.cpp b/source/VirtualFluidsCore/Utilities/ConfigFileReader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cd894b9a8ea08bf424437bc21e8aae96ebdb6b96
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/ConfigFileReader.cpp
@@ -0,0 +1,195 @@
+#include "ConfigFileReader.h"
+#include "StringUtil.hpp"
+#include <errno.h>
+#include <algorithm>
+#include <sstream>
+#include <iostream>
+#include <string>
+
+
+ConfigFileReader::ConfigFileReader( const char *strConfigFile ) 
+{
+   if ( strConfigFile )
+      m_sConfigFile = strConfigFile;
+}
+ConfigFileReader::~ConfigFileReader()
+{
+}
+bool ConfigFileReader::read() 
+{
+   m_in.open(m_sConfigFile.c_str(),std::ios::in);
+   if (m_in.fail())
+   {
+      return false;
+   }
+   while (!m_in.eof())
+   {
+      //--------------------------------------------------------
+      // Get a token and value.
+      // This gives values to member vars: m_token and m_value.
+      //----------------------------------------------------------
+      get_token_and_value();
+      if ( m_token.length() )
+         m_ConfigEntries.insert( String_Pair(m_token, m_value) );
+   }
+   m_in.close();
+   return true;
+}
+void ConfigFileReader::get_token_and_value(void)
+{
+   char token[1024];
+   char ch;
+   bool found_equal=false;
+   int i=0;
+   eat_white_and_comments();
+   while(!(m_in.get(ch)).fail())
+   {
+      if ((ch != '\t'))
+      {
+         if ( (ch == '=') || (ch == ' ') || (ch == '\n') || (ch == '\r') || 
+            (ch == '\t'))
+         {
+            if (ch == '=')found_equal=true;
+            break;
+         }
+         token[i++]=ch;
+      }
+   }
+   if (i==0)
+   {
+      // It didn’t find a token, in this case.
+      m_token="";
+      m_value="";
+      return;
+   }
+   // Null-terminate the token that was found.
+   token[i++]='\0';
+   m_token = token;
+   makeLower(m_token);
+   // Advance to the equal sign, if need be.
+   if (!found_equal)
+   {
+      if (!advance_to_equal_sign_on_line())
+      {
+         // The token had no value.
+         m_token="";
+         m_value="";
+         return;
+      }
+   }
+   // Get the token’s value.
+   i=0;
+   char c = eat_white_and_comments(false);
+   if ( c != '\n' )
+   {
+      i=0;
+      while(!(m_in.get(ch)).fail())
+      {
+         if ((ch == '\t') || (ch == '\r') ||  (ch == '\n') || (ch == '#') )
+         {
+            while (ch!='\n')
+            {
+               if (m_in.get(ch).fail()) break;
+            }
+            break;
+         }
+         else
+         {
+            token[i++]=ch;
+         }
+      }
+   }
+   if (i==0)
+   {
+      // This token had no value.
+      m_value="";
+   }
+   else
+   {
+      token[i++]='\0';
+      m_value=token;
+      // Remove leading/trailing spaces.
+      m_value = StringUtil::trim(m_value);
+      // Strip leading and trailing quotes, if there are any.
+      if ( m_value[0] == '"' )
+         m_value = m_value.substr( 1 );
+      if ( m_value[ m_value.length() -1 ] == '"' )
+         m_value = m_value.substr( 0, m_value.length()-1 );
+   }
+}
+bool ConfigFileReader::advance_to_equal_sign_on_line()
+{
+   char ch;
+   bool found_equal=false;
+   while ( !(m_in.get(ch)).fail() )
+   {
+      if ((ch=='\r')||(ch=='\n')) break;
+      if (ch == '=')
+      {
+         found_equal=true;
+         break;
+      }
+   }
+   return found_equal;
+}
+char ConfigFileReader::eat_white_and_comments(bool traverse_newlines)
+{
+   char ch;
+   bool in_comment;
+   in_comment = false;
+   while (!(m_in.get(ch)).fail())
+      if (ch == '#')
+         in_comment = true;
+      else if (ch == '\n')
+      {
+         in_comment = false;
+         if (!traverse_newlines)
+         {
+            return(ch); // Stop eating.
+         }
+      }
+      else if ((!in_comment) && (ch != ' ') &&
+         (ch != '\t') && (ch != '\r'))
+      {
+         m_in.putback(ch);
+         return 0;
+      }
+      return 0;
+}
+void ConfigFileReader::makeLower(std::string &instring)
+{
+   for(unsigned i=0; i < instring.size();
+      i++)
+   {
+      instring[i] = tolower(instring[i]);
+   }
+}
+bool ConfigFileReader::hasValue( const char *key ) 
+{
+   bool bRet = false;
+   std::string sKey = key;
+   makeLower( sKey );
+   if ( m_ConfigEntries.find( sKey.c_str() ) != m_ConfigEntries.end() )
+   {
+      bRet = true;
+   }
+   return bRet;
+}
+std::string ConfigFileReader::getValue( const char *key )
+{
+   std::string sKey = key;
+   makeLower( sKey );
+   if ( m_ConfigEntries.find( sKey.c_str() ) != m_ConfigEntries.end() )
+   {
+      std::map<std::string, std::string>::iterator iter;
+      iter =  m_ConfigEntries.find(sKey.c_str());
+      return (*iter).second;
+   }
+   return "";
+}
+void ConfigFileReader::setValue( const char *key, const char *value )
+{
+   std::string sKey = key;
+   makeLower( sKey );
+   m_ConfigEntries[sKey] = value;
+}
diff --git a/source/VirtualFluidsCore/Utilities/ConfigFileReader.h b/source/VirtualFluidsCore/Utilities/ConfigFileReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f2caa5d7b7263b2bc403cf045ae9f95aec4ef1b
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/ConfigFileReader.h
@@ -0,0 +1,31 @@
+#ifndef CONFIGFILE_H
+#define CONFIGFILE_H
+#include <string>
+#include <vector>
+#include <fstream>
+#include <map>
+#include <list>
+
+class ConfigFileReader
+{
+public:
+   ConfigFileReader(const char *strFileName);
+   virtual ~ConfigFileReader(void);
+   bool read(void);
+   bool hasValue( const char *key );
+   std::string getValue( const char *key );
+   void setValue( const char *key, const char *value );
+protected:
+   virtual void get_token_and_value();
+   virtual char eat_white_and_comments(bool traverse_newlines=true);
+   virtual bool advance_to_equal_sign_on_line();
+   virtual void makeLower(std::string &instring);
+protected:
+   std::fstream m_in;
+   std::string m_token;
+   std::string m_value;
+   std::string m_sConfigFile;
+   typedef std::pair <std::string, std::string> String_Pair;
+   std::map<std::string, std::string> m_ConfigEntries;
+};
+#endif
diff --git a/source/VirtualFluidsCore/Utilities/ConfigurationFile.hpp b/source/VirtualFluidsCore/Utilities/ConfigurationFile.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..03f84c5c2135647d0e4f677f15853f5b7cd6ad5c
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/ConfigurationFile.hpp
@@ -0,0 +1,234 @@
+#ifndef Configuration_h__
+#define Configuration_h__
+
+#include <map>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <stdlib.h>
+
+//! \brief  Simple configuration file
+//! \details The Configuration class presented here can read and keep values of any configuration file written in a format like this:
+//!#
+//!# Simulation parameters
+//!#
+//!
+//!nbDimensions    = 2
+//!temperature     = 25.001
+//!epsilon         = 1.013e-14
+//!writeLogFile    = false      # NOTE: Set to "true" in debug mode only.
+//!                             #       Logging slows down the program.
+//!errorMessage    = the simulation failed
+//!origin          = 0.0 0.0 0.0 # x, y, z of origin
+//!
+//!Example how to use it:
+//!
+//!Configuration   config;
+//!config.load(configname);
+//!
+//!int            nbDimensions = config.getInt("nbDimensions");
+//!float          temperature  = config.getFloat("temperature");
+//!double         epsilon      = config.getDouble("epsilon");
+//!bool           writeLogFile = config.getBool("writeLogFile");
+//!string         errorMessage = config.getString("pathname");
+//!vector<double> origin       = config.getVector<double>("origin");
+//!            
+//! \author  Konstantin Kutscher
+
+class ConfigurationFile
+{
+public:
+   // clear all values
+   void clear();
+
+   // load a configuration file
+   bool load(const std::string& File);
+
+   // check if value associated with given key exists
+   bool contains(const std::string& key) const;
+
+   // get value associated with given key
+   
+   int    getInt(const std::string& key) const;
+   long   getLong(const std::string& key) const;
+   float  getFloat(const std::string& key) const;
+   double getDouble(const std::string& key) const;
+   bool   getBool(const std::string& key) const;
+   std::string  getString(const std::string& key) const;
+   template<class T>
+   std::vector<T> getVector(const std::string& Key) const;
+
+   template<class T>
+   T get(const std::string& Key) const;
+
+private:
+   // the container
+   std::map<std::string, std::string> data;
+
+   // remove leading and trailing tabs and spaces
+   static std::string trim(const std::string& str);
+
+   template<class T>
+   T fromString(const std::string& str) const;
+};
+
+
+// ----------------------------------
+// method implementations
+// ----------------------------------
+
+void ConfigurationFile::clear()
+{
+   data.clear();
+}
+
+bool ConfigurationFile::load(const std::string& file)
+{
+   std::ifstream inFile(file.c_str());
+
+   if (!inFile.good())
+   {
+      UB_THROW(UbException(UB_EXARGS, "Cannot read configuration file "+file+"!"));
+   }
+
+   while (inFile.good() && ! inFile.eof())
+   {
+      std::string line;
+      getline(inFile, line);
+
+      // filter out comments
+      if (!line.empty())
+      {
+         size_t pos = line.find('#');
+
+         if (pos != std::string::npos)
+         {
+            line = line.substr(0, pos);
+         }
+      }
+
+      // split line into key and value
+      if (!line.empty())
+      {
+         size_t pos = line.find('=');
+
+         if (pos != std::string::npos)
+         {
+            std::string key = trim(line.substr(0, pos));
+            std::string value = trim(line.substr(pos + 1));
+
+            if (!key.empty() && !value.empty())
+            {
+               data[key] = value;
+            }
+         }
+      }
+   }
+
+   return true;
+}
+
+bool ConfigurationFile::contains(const std::string& key) const
+{
+   return data.find(key) != data.end();
+}
+
+std::string ConfigurationFile::getString(const std::string& key) const
+{
+   std::map<std::string, std::string>::const_iterator iter = data.find(key);
+
+   if (iter != data.end())
+   {
+      std::string value = iter->second;
+      return value;
+   }
+   else
+   {
+      UB_THROW(UbException(UB_EXARGS, "The parameter \"" + key + "\" is missing!"));
+   }
+}
+
+int ConfigurationFile::getInt(const std::string& key) const
+{
+   std::string str = getString(key);
+   int value = std::atoi(str.c_str());
+   return value;
+}
+
+long ConfigurationFile::getLong(const std::string& key) const
+{
+   std::string str = getString(key);
+   long value = std::atol(str.c_str());
+   return value;
+}
+
+float ConfigurationFile::getFloat(const std::string& key) const
+{
+   std::string str = getString(key);
+   float value = (float)std::atof(str.c_str());
+   return value;
+}
+
+double ConfigurationFile::getDouble(const std::string& key) const
+{
+   std::string str = getString(key);
+   double value = std::atof(str.c_str());
+   return value;
+}
+
+bool ConfigurationFile::getBool(const std::string& key) const
+{
+   std::string str = getString(key);
+   bool value = (str == "true");
+   return value;
+}
+
+std::string ConfigurationFile::trim(const std::string& str)
+{
+   size_t first = str.find_first_not_of(" \t\n\r");
+
+   if (first != std::string::npos)
+   {
+      size_t last = str.find_last_not_of(" \t\n\r");
+
+      return str.substr(first, last - first + 1);
+   }
+   else
+   {
+      return "";
+   }
+}
+
+template<class T>
+std::vector<T> ConfigurationFile::getVector(const std::string& key) const
+{
+   std::string str = getString(key);
+   std::vector<T> v;
+   std::vector<std::string> strings;
+   boost::algorithm::split(strings, str, boost::algorithm::is_any_of("\t\n\r;, "));
+   BOOST_FOREACH(std::string s, strings)
+   {
+      if (s != "")
+      {
+         v.push_back(fromString<T>(s));
+      }
+   }
+   return v;
+}
+
+template<class T>
+T ConfigurationFile::fromString(const std::string& str) const
+{
+   //boolean hack
+   if (str == "true")
+      return true;
+   else if (str == "false")
+      return false;
+   //////////////
+   std::istringstream stream(str);
+   T t;
+   stream >> t;
+   return t;
+}
+
+#endif // Configuration_h__
diff --git a/source/VirtualFluidsCore/Utilities/MathUtil.hpp b/source/VirtualFluidsCore/Utilities/MathUtil.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..56e4e81e87e7a010ca3acf8c2e6d7dc2b4e13b7b
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/MathUtil.hpp
@@ -0,0 +1,89 @@
+#ifndef MATHUTIL_H
+#define MATHUTIL_H
+
+#include <math.h>
+#include "MuParser/include/muParser.h"
+
+namespace Utilities
+{
+   static bool isEven( int integer )
+   {
+      if ( integer % 2 == 0 )
+         return true;
+      else
+         return false;
+   }
+
+   static bool isOdd( int integer )
+   {
+      if ( integer % 2 != 0 )
+         return true;
+      else
+         return false;
+   }
+
+   //convert from double to int
+   static int cint(double x)
+   {
+      double intpart;
+      if (modf(x,&intpart)>=.5)
+         return static_cast<int> (floor(x)+1);
+      else
+         return static_cast<int> (floor(x));
+   }
+
+   //create new mu parser for duct parabolic profile
+   //inflow in X
+   static mu::Parser getDuctParaboloidX(double Cy, double Hy, double Cz, double Hz, double V)
+   {
+      mu::Parser fct;
+      fct.SetExpr("V*(((-(x2-Cy)^2.0+(Hy/2.0)^2.0)/(Hy/2.0)^2.0)*((-(x3-Cz)^2.0+(Hz/2.0)^2.0)/(Hz/2.0)^2.0))" );
+      fct.DefineConst("Cy", Cy);
+      fct.DefineConst("Hy", Hy);
+      fct.DefineConst("Cz", Cz);
+      fct.DefineConst("Hz", Hz);
+      fct.DefineConst("V" , V );
+      return fct;
+   }
+   //inflow in Y
+   static mu::Parser getDuctParaboloidY(double Cx, double Hx, double Cz, double Hz, double V)
+   {
+      mu::Parser fct;
+      fct.SetExpr("V*(((-(x1-Cx)^2.0+(Hx/2.0)^2.0)/(Hx/2.0)^2.0)*((-(x3-Cz)^2.0+(Hz/2.0)^2.0)/(Hz/2.0)^2.0))" );
+      fct.DefineConst("Cx", Cx);
+      fct.DefineConst("Hx", Hx);
+      fct.DefineConst("Cz", Cz);
+      fct.DefineConst("Hz", Hz);
+      fct.DefineConst("V" , V );
+      return fct;
+   }
+   //inflow in Z
+   static mu::Parser getDuctParaboloidZ(double Cx, double Hx, double Cy, double Hy, double V)
+   {
+      mu::Parser fct;
+      fct.SetExpr("V*(((-(x1-Cx)^2.0+(Hx/2.0)^2.0)/(Hx/2.0)^2.0)*((-(x2-Cy)^2.0+(Hy/2.0)^2.0)/(Hy/2.0)^2.0))" );
+      fct.DefineConst("Cx", Cx);
+      fct.DefineConst("Hx", Hx);
+      fct.DefineConst("Cy", Cy);
+      fct.DefineConst("Hy", Hy);
+      fct.DefineConst("V" , V );
+      return fct;
+   }
+   //hash function
+   static unsigned int RSHash(const std::string& str)
+   {
+      unsigned int b    = 378551;
+      unsigned int a    = 63689;
+      unsigned int hash = 0;
+
+      for(std::size_t i = 0; i < str.length(); i++)
+      {
+         hash = hash * a + str[i];
+         a    = a * b;
+      }
+
+      return hash;
+   }
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Utilities/MemoryUtil.h b/source/VirtualFluidsCore/Utilities/MemoryUtil.h
new file mode 100644
index 0000000000000000000000000000000000000000..c19d62e80e8da4ae7beea40295ccd6eb3cd59c48
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/MemoryUtil.h
@@ -0,0 +1,110 @@
+#ifndef _MEMORYUTIL_H_
+#define _MEMORYUTIL_H_
+
+#if defined(_WIN32) || defined(_WIN64)
+   #define MEMORYUTIL_WINDOWS
+   #include "windows.h"
+   #include "psapi.h"
+   #pragma comment(lib, "psapi.lib")
+#elif (defined(__amd64) || defined(__amd64__) || defined(__unix__) || defined(__CYGWIN__)) && !defined(__AIX__) 
+   #define MEMORYUTIL_LINUX
+   #include "sys/types.h"
+   #include "sys/sysinfo.h"
+   #include "stdlib.h"
+   #include "stdio.h"
+   #include "string.h"
+#else
+   #error "MemoryUtil::UnknownMachine"
+#endif
+//////////////////////////////////////////////////////////////////////////
+//MemoryUtil
+//////////////////////////////////////////////////////////////////////////
+namespace Utilities
+{
+//////////////////////////////////////////////////////////////////////////
+   static long long getTotalPhysMem()
+   {
+      #if defined MEMORYUTIL_WINDOWS
+         MEMORYSTATUSEX memInfo;
+         memInfo.dwLength = sizeof(MEMORYSTATUSEX);
+         GlobalMemoryStatusEx(&memInfo);
+         DWORDLONG totalPhysMem = memInfo.ullTotalPhys;            
+      #elif defined(MEMORYUTIL_LINUX)
+         struct sysinfo memInfo;
+         sysinfo (&memInfo);
+         long long totalPhysMem = memInfo.totalram;
+         //Multiply in next statement to avoid int overflow on right hand side...
+         totalPhysMem *= memInfo.mem_unit;
+      #else
+      #error "MemoryUtil::getTotalPhysMem - UnknownMachine"
+      #endif
+
+      return (long long)totalPhysMem;
+   }
+//////////////////////////////////////////////////////////////////////////
+   static long long getPhysMemUsed()
+   {
+      #if defined MEMORYUTIL_WINDOWS
+         MEMORYSTATUSEX memInfo;
+         memInfo.dwLength = sizeof(MEMORYSTATUSEX);
+         GlobalMemoryStatusEx(&memInfo);
+         DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;          
+      #elif defined(MEMORYUTIL_LINUX)
+         struct sysinfo memInfo;
+         sysinfo (&memInfo);
+         long long physMemUsed = memInfo.totalram - memInfo.freeram;
+         //Multiply in next statement to avoid int overflow on right hand side...
+         physMemUsed *= memInfo.mem_unit;
+      #else
+      #error "MemoryUtil::getPhysMemUsed - UnknownMachine"
+      #endif
+
+      return (long long)physMemUsed;
+   }
+//////////////////////////////////////////////////////////////////////////
+#if defined(MEMORYUTIL_LINUX)
+   static int parseLine(char* line){
+      int i = strlen(line);
+      while (*line < '0' || *line > '9') line++;
+      line[i-3] = '\0';
+      i = atoi(line);
+      return i;
+   }
+
+   static int getValue(){ //Note: this value is in KB!
+      FILE* file = fopen("/proc/self/status", "r");
+      int result = -1;
+      char line[128];
+
+
+      while (fgets(line, 128, file) != NULL){
+         if (strncmp(line, "VmRSS:", 6) == 0){
+            result = parseLine(line);
+            break;
+         }
+      }
+      fclose(file);
+      return result;
+   }
+#endif
+//////////////////////////////////////////////////////////////////////////
+   static long long getPhysMemUsedByMe()
+   {
+      #if defined MEMORYUTIL_WINDOWS
+         PROCESS_MEMORY_COUNTERS pmc;
+         GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
+         SIZE_T physMemUsedByMe = pmc.WorkingSetSize;          
+      #elif defined(MEMORYUTIL_LINUX)
+         long long physMemUsedByMe = (long long)getValue() * (long long)1024;
+      #else
+         #error "MemoryUtil::getPhysMemUsedByMe - UnknownMachine"
+      #endif
+
+      return (long long)physMemUsedByMe;
+   }
+//////////////////////////////////////////////////////////////////////////
+
+}
+
+#endif
+
diff --git a/source/VirtualFluidsCore/Utilities/StringUtil.hpp b/source/VirtualFluidsCore/Utilities/StringUtil.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..790e9d47f69c45cbb1a465e079034c530d74e918
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/StringUtil.hpp
@@ -0,0 +1,305 @@
+#ifndef STRINGUTIL_H
+#define STRINGUTIL_H
+#include <errno.h>
+#include <algorithm>
+#include <sstream>
+#include <iostream>
+#include <string>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+
+template <class T>
+bool from_string(T &t, const std::string &s, std::ios_base &(*f)(std::ios_base&))
+{
+   std::istringstream iss(s);
+   return !(iss>>f>>t).fail();
+}
+class StringUtil 
+{
+public:
+   StringUtil() {}
+   ~StringUtil() {}
+   // Find the given string in the source string and replace it with the
+   // "replace" string, everywhere instances of that string exist.
+   static void findandreplace( std::string& source, const std::string& find, const std::string& replace )
+   {
+      size_t j;
+      for (;(j = source.find( find )) 
+         != std::string::npos;)
+      {
+         source.replace( j, 
+            find.length(), replace );
+      }
+   }
+   // The following function returns a string with all-uppercase characters.
+   static std::string makeUpper( const std::string& instring)
+   {
+      std::string temp=instring;
+      transform( temp.begin(), temp.end(), temp.begin(), ::toupper );
+      return temp;
+   }
+   // The following function returns a string with all-lowercase characters.
+   static std::string makeLower( const std::string& instring)
+   {
+      std::string temp;
+      transform( temp.begin(), temp.end(), temp.begin(), ::tolower );
+      return temp;
+   }
+   static bool contains( const std::string& source, const char *find )
+   {
+      return ( 0!=strstr(source.c_str(),find) );
+   }
+   static std::string pad( const std::string& instring, char padchar, int length )
+   {
+      std::string outstring = instring;
+      for ( int i=(int)outstring.length(); i<length; ++i )
+         outstring += padchar;
+      return outstring;
+   }
+   // Trim the given characters from the beginning and end of a string.
+   // the default is to trim whitespace. If the string is empty or contains
+   // only the trim characters, an empty string is returned.
+   static std::string trim( const std::string &instring, const std::string &trimstring=std::string(" \t\n"))
+   {
+      if (trimstring.size()==0) 
+         return instring;
+      std::string temp="";
+      std::string::size_type begpos=instring.find_first_not_of (trimstring);
+      if (begpos==std::string::npos)
+      {
+         return temp;
+      }
+      else
+      {
+         std::string::size_type endpos=instring.find_last_not_of (trimstring);
+         temp=instring.substr(begpos, endpos-begpos+1);
+      }
+      return temp;
+   }
+   // Convert the string to an int. Note that a string exception is thrown if
+   // it is invalid.
+   static int toInt(const std::string & myInString)
+   {
+      int i=0;
+      std::string inString = trim(myInString);
+      if( !from_string<int>(i, inString, std::dec) )
+      {
+         std::string exceptionText = "StringUtil::toInt() - Not an integer: " + inString;
+         throw exceptionText;
+      }
+      // Time to run some more checks.
+      for (unsigned int j=0; j < inString.length(); j++)
+      {
+         if ( !isNumeric(inString[j]) )
+         {
+            if (j==0 && inString[j] =='-')
+            {
+               continue;
+            }
+            else
+            {
+               std::string exceptionText = "StringUtil::toInt() - Not an integer: " + inString;
+               throw exceptionText;
+            }
+         }
+      }
+      return (i);
+   }
+   // Convert the string to a float. Note: A string exception is thrown if
+   // it is invalid.
+   static float toFloat(const std::string & myInString)
+   {
+      float f=0;
+      std::string inString = trim(myInString);
+      if( !from_string<float>(f, inString, std::dec) )
+      {
+         std::string exceptionText = "StringUtil::toFloat() - Not a float: " + inString;
+         throw exceptionText;
+      }
+      // Now it runs some more checks.
+      int dec_count=0;
+      int e_count=0;
+      for (unsigned int j=0; j < inString.length(); j++)
+      {
+         if ( !isNumeric(inString[j]) )
+         {
+            if ((j==0 || inString[j-1] == 'e' || inString[j-1] == 'E') && inString[j] =='-')
+            {
+               continue;
+            }
+            else if (inString[j]=='.')
+            {
+               dec_count++;
+               if (dec_count > 1)
+               {
+                  std::string exceptionText = "StringUtil::toFloat() - Not a float: " + inString;
+                  throw exceptionText;
+               }
+               continue;
+            }
+            else if (inString[j] == 'e' || inString[j] == 'E')
+            {
+               e_count++;
+               if (e_count > 1)
+               {
+                  std::string exceptionText = "StringUtil::toFloat() - Not a float: " + inString;
+                  throw exceptionText;
+               }
+               continue;
+            }
+            else
+            {
+               std::string exceptionText = "StringUtil::toFloat() - Not a float: " + inString;
+               throw exceptionText;
+            }
+         }
+      }
+      return (f);
+   }
+   // Convert the string to a double. Note: A string exception is thrown if
+   // it is invalid.
+   static double toDouble(const std::string & myInString)
+   {
+	   double d=0;
+	   std::string inString = trim(myInString);
+	   if( !from_string<double>(d, inString, std::dec) )
+	   {
+		   std::string exceptionText = "StringUtil::toDouble() - Not a double: " + inString;
+		   throw exceptionText;
+	   }
+	   // Now it runs some more checks.
+      int dec_count=0;
+      int e_count=0;
+      for (unsigned int j=0; j < inString.length(); j++)
+      {
+         if ( !isNumeric(inString[j]) )
+         {
+            if ((j==0 || inString[j-1] == 'e' || inString[j-1] == 'E') && inString[j] =='-')
+            {
+               continue;
+            }
+            else if (inString[j]=='.')
+            {
+               dec_count++;
+               if (dec_count > 1)
+               {
+                  std::string exceptionText = "StringUtil::toDouble() - Not a double: " + inString;
+                  throw exceptionText;
+               }
+               continue;
+            }
+            else if (inString[j] == 'e' || inString[j] == 'E')
+            {
+               e_count++;
+               if (e_count > 1)
+               {
+                  std::string exceptionText = "StringUtil::toDouble() - Not a double: " + inString;
+                  throw exceptionText;
+               }
+               continue;
+            }
+            else
+            {
+               std::string exceptionText = "StringUtil::toDouble() - Not a double: " + inString;
+               throw exceptionText;
+            }
+         }
+      }
+	   return (d);
+   }
+   // Convert the string to a boolean. Note: A string exception is thrown if
+   // it is invalid.
+   static bool toBool(const std::string & myInString)
+   {
+      bool b=0;
+      std::string inString = trim(myInString);
+      if( !from_string<bool>(b, inString, std::boolalpha) )
+      {
+         std::string exceptionText = "StringUtil::toBool() - Not a bool: " + inString;
+         throw exceptionText;
+      }
+      return (b);
+   }
+   // Returns true if the character is numeric.
+   static bool isNumeric(char c)
+   {
+      return ('0' <= c && c <= '9');
+   }
+   // Replace environment variables in the string with their values.
+   // Note: environment variables must be of the form ${ENVVAR}.
+   //static std::string substituteEnvVar( const std::string &myInString )
+   //{
+   //   std::string outString="";
+   //   char variable[512];
+   //   const char *s = myInString.c_str();
+   //   while(*s!=0)
+   //   {
+   //      if (*s=='$' && *(s+1)=='{')
+   //      {
+   //         // When you've found beginning of variable, find the end.
+   //         //strcpy(variable,s+2);
+   //         strcpy_s(variable, s+2);
+   //         char *end = strchr (variable,'}');
+   //         if (end)
+   //         {
+   //            *end='\0';
+   //            //char *cp = (char *)getenv(variable);
+   //            char *cp;
+   //            size_t len;
+   //            _dupenv_s(&cp, &len, variable );
+   //            if (cp)
+   //               //outString += (char *) getenv(variable);
+   //               outString += (char *) cp;
+   //            s = strchr(s,'}');
+   //         }
+   //         else
+   //         {
+   //            outString += *s;
+   //         }
+   //      }
+   //      else
+   //      {
+   //         outString += *s;
+   //      }
+   //      s++;
+   //   }
+   //   return outString;
+   //}
+   template<class T>
+   static std::vector<T> toVector(const std::string& s)
+   {
+      std::vector<T> v;
+      std::vector<std::string> strings;
+      boost::algorithm::split(strings, s,  boost::algorithm::is_any_of("\t\n "));
+      BOOST_FOREACH(std::string s, strings){
+         if (s != "")
+         {
+            v.push_back(fromString<T>(s));
+         }
+      }
+      return v;
+   }
+   template<class T>
+ 	static std::string toString(const T& t)
+	{
+		std::ostringstream stream;
+		stream << t;
+		return stream.str();
+	}
+   template<class T>
+   static T fromString(const std::string& s)
+   {
+      //boolean hack
+      if(s == "true")
+         return true;
+      else if(s == "false")
+         return false;
+      //////////////
+      std::istringstream stream (s);
+      T t;
+      stream >> t;
+      return t;
+   }
+};
+#endif //STRINGUTIL_H
+
diff --git a/source/VirtualFluidsCore/Utilities/VoxelMatrixUtil.hpp b/source/VirtualFluidsCore/Utilities/VoxelMatrixUtil.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..216209ef3e64e5b9d7e939e5c859e4b8ea67be4a
--- /dev/null
+++ b/source/VirtualFluidsCore/Utilities/VoxelMatrixUtil.hpp
@@ -0,0 +1,50 @@
+#ifndef VoxelMatrixUtil_h__
+#define VoxelMatrixUtil_h__
+
+#include "GbCuboid3D.h"
+#include "D3Q27NoSlipBCAdapter.h"
+#include "D3Q27Interactor.h"
+#include "SetSolidOrTransBlockVisitor.h"
+#include "Block3D.h"
+#include "Grid3D.h"
+
+
+namespace Utilities
+{
+   void voxelMatrixDiscretisation(GbVoxelMatrix3DPtr matrix, std::string& pathname, int myid, int fileCounter, Grid3DPtr grid, int bounceBackOption, bool vmFile)
+   {
+      D3Q27BoundaryConditionAdapterPtr noSlipPM(new D3Q27NoSlipBCAdapter(bounceBackOption));
+      D3Q27InteractorPtr vmInt = D3Q27InteractorPtr(new D3Q27Interactor(matrix, grid, noSlipPM, Interactor3D::SOLID));
+
+      if (vmFile)
+      {
+         if (myid == 0) matrix->writeToVTKImageDataASCII(pathname + "/geo/vmatrix" + UbSystem::toString(fileCounter));
+      } 
+
+      GbCuboid3DPtr vmBox(new GbCuboid3D(matrix->getX1Minimum(), matrix->getX2Minimum(), matrix->getX3Minimum(), matrix->getX1Maximum(), matrix->getX2Maximum(), matrix->getX3Maximum()));
+      if (myid == 0) GbSystem3D::writeGeoObject(vmBox.get(), pathname + "/geo/vmbox" + UbSystem::toString(fileCounter), WbWriterVtkXmlASCII::getInstance());
+      D3Q27InteractorPtr vmBoxInt = D3Q27InteractorPtr(new D3Q27Interactor(vmBox, grid, noSlipPM, Interactor3D::SOLID));
+      SetSolidOrTransBlockVisitor v1(vmBoxInt, SetSolidOrTransBlockVisitor::SOLID);
+      grid->accept(v1);
+      SetSolidOrTransBlockVisitor v2(vmBoxInt, SetSolidOrTransBlockVisitor::TRANS);
+      grid->accept(v2);
+
+      std::vector<Block3DPtr> blocks;
+      std::vector<Block3DPtr>& sb = vmBoxInt->getSolidBlockSet();
+      if (myid == 0) UBLOG(logINFO, "number of solid blocks = " << sb.size());
+      blocks.insert(blocks.end(), sb.begin(), sb.end());
+      std::vector<Block3DPtr>& tb = vmBoxInt->getTransBlockSet();
+      if (myid == 0) UBLOG(logINFO, "number of trans blocks = " << tb.size());
+      blocks.insert(blocks.end(), tb.begin(), tb.end());
+
+      if (myid == 0) UBLOG(logINFO, "number of blocks = " << blocks.size());
+
+      BOOST_FOREACH(Block3DPtr block, blocks)
+      {
+         block->setActive(true);
+         vmInt->setDifferencesToGbObject3D(block);
+      }
+   }
+}
+#endif // VoxelMatrixUtil_h__
+
diff --git a/source/VirtualFluidsCore/Visitors/Block3DVisitor.h b/source/VirtualFluidsCore/Visitors/Block3DVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..3460a9b2cae46126c09f79cd5c15b435651d644c
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/Block3DVisitor.h
@@ -0,0 +1,58 @@
+#ifndef Block3DVisitor_h
+#define Block3DVisitor_h
+
+#include <boost/shared_ptr.hpp>
+class Block3DVisitor;
+typedef boost::shared_ptr<Block3DVisitor> Block3DVisitorPtr;
+
+#include "Grid3D.h"
+#include "Block3D.h"
+
+class Block3DVisitor
+{
+public:
+   Block3DVisitor() : startLevel(-1), stopLevel(-1)
+   {
+   }
+
+   Block3DVisitor(int startLevel, int stopLevel) : startLevel(startLevel), stopLevel(stopLevel)
+   {
+   }
+
+	virtual ~Block3DVisitor()
+   {
+   }
+	
+   virtual void visit(Grid3DPtr grid, Block3DPtr block)=0;
+   
+   int  getStartLevel() const; 
+   int  getStopLevel() const;
+   void setStartLevel(int level);
+   void setStopLevel(int level);
+
+private:
+   int  startLevel;
+   int  stopLevel;
+};
+//////////////////////////////////////////////////////////////////////////
+inline int  Block3DVisitor::getStartLevel() const
+{ 
+   return this->startLevel;  
+}
+//////////////////////////////////////////////////////////////////////////
+inline int  Block3DVisitor::getStopLevel() const
+{ 
+   return this->stopLevel;   
+}
+//////////////////////////////////////////////////////////////////////////
+inline void Block3DVisitor::setStartLevel(int level)
+{ 
+   this->startLevel = level; 
+}
+//////////////////////////////////////////////////////////////////////////
+inline void Block3DVisitor::setStopLevel(int level) 
+{ 
+   this->stopLevel = level;  
+}
+
+#endif 
diff --git a/source/VirtualFluidsCore/Visitors/BoundaryConditionBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/BoundaryConditionBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..45ac0f046784e6216fa079645720327500df06d0
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/BoundaryConditionBlockVisitor.cpp
@@ -0,0 +1,122 @@
+#include "BoundaryConditionBlockVisitor.h"
+#include "LBMKernelETD3Q27.h"
+#include "D3Q27ETBCProcessor.h"
+#include "Grid3DSystem.h"
+
+BoundaryConditionBlockVisitor::BoundaryConditionBlockVisitor() :
+Block3DVisitor(0, Grid3DSystem::MAXLEVEL)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+BoundaryConditionBlockVisitor::~BoundaryConditionBlockVisitor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void BoundaryConditionBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if (block->getRank() == grid->getRank())
+   {
+      LBMKernel3DPtr kernel = block->getKernel();
+      D3Q27ETBCProcessorPtr bcProcessor = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor());
+      velocity = bcProcessor->getBC(BoundaryCondition::Velocity);
+      density = bcProcessor->getBC(BoundaryCondition::Density);
+      noSlip = bcProcessor->getBC(BoundaryCondition::NoSlip);
+      slip = bcProcessor->getBC(BoundaryCondition::Slip);
+      BCArray3D<D3Q27BoundaryCondition>& bcArray = bcProcessor->getBCArray();
+      bool compressible = kernel->getCompressible();
+      double collFactor = kernel->getCollisionFactor();
+      int level = block->getLevel();
+
+      if (velocity) velocity->setCompressible(compressible);
+      if (density) density->setCompressible(compressible);
+      if (noSlip) noSlip->setCompressible(compressible);
+      if (slip) slip->setCompressible(compressible);
+
+      int minX1 = 0;
+      int minX2 = 0;
+      int minX3 = 0;
+      int maxX1 = (int)bcArray.getNX1();
+      int maxX2 = (int)bcArray.getNX2();
+      int maxX3 = (int)bcArray.getNX3();
+      D3Q27BoundaryConditionPtr bcPtr;
+
+      int vCount = 0;
+      int dCount = 0;
+      int nsCount = 0;
+      int sCount = 0;
+
+      EsoTwist3DPtr distributions = boost::dynamic_pointer_cast<EsoTwist3D>(kernel->getDataSet()->getFdistributions());
+
+      for (int x3 = minX3; x3 < maxX3; x3++)
+      {
+         for (int x2 = minX2; x2 < maxX2; x2++)
+         {
+            for (int x1 = minX1; x1 < maxX1; x1++)
+            {
+               if (!bcArray.isSolid(x1, x2, x3) && !bcArray.isUndefined(x1, x2, x3))
+               {
+                  if ((bcPtr = bcArray.getBC(x1, x2, x3)) != NULL)
+                  {
+                     //velocity boundary condition
+                     if (bcPtr->hasVelocityBoundary() && velocity)
+                     {
+                        velocity->addNode(x1, x2, x3);
+                        velocity->addBcPointer(bcPtr);
+                        vCount++;
+                     }
+                     //density boundary condition
+                     else if (bcPtr->hasDensityBoundary() && density)
+                     {
+                        density->addNode(x1, x2, x3);
+                        density->addBcPointer(bcPtr);
+                        dCount++;
+                     }
+                     //no slip boundary condition
+                     else if (bcPtr->hasNoSlipBoundary() && noSlip)
+                     {
+                        noSlip->addNode(x1, x2, x3);
+                        noSlip->addBcPointer(bcPtr);
+                        nsCount++;
+                     }
+                     //slip boundary condition
+                     else if (bcPtr->hasSlipBoundary() && slip)
+                     {
+                        slip->addNode(x1, x2, x3);
+                        slip->addBcPointer(bcPtr);
+                        sCount++;
+                     }
+                  }
+               }
+            }
+         }
+      }
+      if (vCount > 0)
+      {
+         //velocity->addNnode(vCount);
+         velocity->addDistributions(distributions);
+         velocity->setCollFactor(collFactor);
+      }
+      if (dCount > 0)
+      {
+         //density->addNnode(dCount);
+         density->addDistributions(distributions);
+         density->setCollFactor(collFactor);
+      }
+      if (nsCount > 0)
+      {
+         //noSlip->addNnode(nsCount);
+         noSlip->addDistributions(distributions);
+         noSlip->setCollFactor(collFactor);
+      }
+      if (sCount > 0)
+      {
+         //slip->addNnode(sCount);
+         slip->addDistributions(distributions);
+         slip->setCollFactor(collFactor);
+      }
+   }
+}
+
+
diff --git a/source/VirtualFluidsCore/Visitors/BoundaryConditionBlockVisitor.h b/source/VirtualFluidsCore/Visitors/BoundaryConditionBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..b15c70ed70d195951121b8151b4a79f8daa1e9f7
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/BoundaryConditionBlockVisitor.h
@@ -0,0 +1,20 @@
+#ifndef BoundaryConditionBlockVisitor_h__
+#define BoundaryConditionBlockVisitor_h__
+
+#include "Block3DVisitor.h"
+#include "BoundaryConditionProcessor.h"
+
+class BoundaryConditionBlockVisitor : public Block3DVisitor
+{
+public:
+   BoundaryConditionBlockVisitor();
+   virtual ~BoundaryConditionBlockVisitor();
+   void visit(Grid3DPtr grid, Block3DPtr block);
+protected:
+private:
+   BoundaryConditionPtr velocity;
+   BoundaryConditionPtr density;
+   BoundaryConditionPtr noSlip;
+   BoundaryConditionPtr slip;
+};
+#endif // BoundaryConditionBlockVisitor_h__
diff --git a/source/VirtualFluidsCore/Visitors/CMakePackage.txt b/source/VirtualFluidsCore/Visitors/CMakePackage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9354d3d0084922c7abd6f1b22823c5c47e0befb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/CMakePackage.txt
@@ -0,0 +1,2 @@
+GET_FILENAME_COMPONENT( CURRENT_DIR  ${CMAKE_CURRENT_LIST_FILE} PATH) 
+COLLECT_PACKAGE_DATA_WITH_OPTION(${CURRENT_DIR} ALL_SOURCES)
diff --git a/source/VirtualFluidsCore/Visitors/ChangeBoundaryDensityBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/ChangeBoundaryDensityBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0908da0a46fc661c3f8ebde6224778ad7a7528b3
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/ChangeBoundaryDensityBlockVisitor.cpp
@@ -0,0 +1,58 @@
+#include "ChangeBoundaryDensityBlockVisitor.h"
+#include "LBMKernelETD3Q27.h"
+#include "Grid3DSystem.h"
+#include "D3Q27BoundaryCondition.h"
+
+ChangeBoundaryDensityBlockVisitor::ChangeBoundaryDensityBlockVisitor(float oldBoundaryDensity, float newBoundaryDensity) :
+Block3DVisitor(0, Grid3DSystem::MAXLEVEL), 
+oldBoundaryDensity(oldBoundaryDensity), 
+newBoundaryDensity(newBoundaryDensity)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+ChangeBoundaryDensityBlockVisitor::~ChangeBoundaryDensityBlockVisitor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void ChangeBoundaryDensityBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if (block->getRank() == grid->getRank())
+   {
+      LBMKernel3DPtr kernel = block->getKernel();
+      BCArray3D<D3Q27BoundaryCondition>& bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+      int minX1 = 0;
+      int minX2 = 0;
+      int minX3 = 0;
+      int maxX1 = (int)bcArray.getNX1();
+      int maxX2 = (int)bcArray.getNX2();
+      int maxX3 = (int)bcArray.getNX3();
+
+      for (int x3 = minX3; x3 < maxX3; x3++)
+      {
+         for (int x2 = minX2; x2 < maxX2; x2++)
+         {
+            for (int x1 = minX1; x1 < maxX1; x1++)
+            {
+               if (!bcArray.isSolid(x1, x2, x3) && !bcArray.isUndefined(x1, x2, x3))
+               {
+                  bcPtr = bcArray.getBC(x1, x2, x3);
+                  if (bcPtr)
+                  {
+                     if (bcPtr->hasDensityBoundary())
+                     {
+                        float bcDensity = bcPtr->getBoundaryDensity();
+                        if (bcDensity == oldBoundaryDensity)
+                        {
+                           bcPtr->setBoundaryDensity(newBoundaryDensity);
+                        }
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+}
diff --git a/source/VirtualFluidsCore/Visitors/ChangeBoundaryDensityBlockVisitor.h b/source/VirtualFluidsCore/Visitors/ChangeBoundaryDensityBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ec36c3fc4068a3a938dd96a227f2b923ee9fbe5
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/ChangeBoundaryDensityBlockVisitor.h
@@ -0,0 +1,19 @@
+#ifndef ChangeBoundaryDensityBlockVisitor_h__
+#define ChangeBoundaryDensityBlockVisitor_h__
+
+#include "Block3DVisitor.h"
+#include "D3Q27BoundaryCondition.h"
+
+class ChangeBoundaryDensityBlockVisitor : public Block3DVisitor
+{
+public:
+   ChangeBoundaryDensityBlockVisitor(float oldBoundaryDensity, float newBoundaryDensity);
+   virtual ~ChangeBoundaryDensityBlockVisitor();
+   virtual void visit(Grid3DPtr grid, Block3DPtr block);
+protected:
+private:
+   float oldBoundaryDensity; 
+   float newBoundaryDensity;
+   D3Q27BoundaryConditionPtr bcPtr;
+};
+#endif // ChangeBoundaryDensityBlockVisitor_h__
diff --git a/source/VirtualFluidsCore/Visitors/ConnectorBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/ConnectorBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..32e3d4cf7a5609ad56dcdf4a95a1ea098c8181dc
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/ConnectorBlockVisitor.cpp
@@ -0,0 +1,476 @@
+#include "ConnectorBlockVisitor.h"
+#include "Grid3DSystem.h"
+#include "D3Q27ETDirectConnector.h"
+#include <basics/transmitter/TbTransmitterLocal.h>
+
+#include "D3Q27ETFullVectorConnector.h"
+#include "D3Q27ETFullDirectConnector2.h"
+#include "CoarseToFineNodeSetBlock3DConnector.h"
+#include "FineToCoarseNodeSetBlock3DConnector.h"
+
+
+ConnectorBlockVisitor::ConnectorBlockVisitor(CommunicatorPtr comm, LBMReal nu, D3Q27InterpolationProcessorPtr iProcessor, ConnectorFactoryPtr cFactory) :
+   Block3DVisitor(0, Grid3DSystem::MAXLEVEL),
+   comm(comm),
+   nu(nu),
+   iProcessor(iProcessor),
+   cFactory(cFactory)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+ConnectorBlockVisitor::~ConnectorBlockVisitor(void)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void ConnectorBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if (!block) return;
+
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::visit() - start");
+   UBLOG(logDEBUG5, block->toString());
+
+   gridRank = comm->getProcessID();
+   grid->setRank(gridRank);
+
+   setSameLevelConnectors(grid, block);
+
+   if (grid->getFinestInitializedLevel() > grid->getCoarsestInitializedLevel())
+      setInterpolationConnectors(grid, block);
+
+   if (block->getGlobalID()==2234)
+   {
+      UBLOG(logINFO, block->toString());
+   }
+
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::visit() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void ConnectorBlockVisitor::setSameLevelConnectors(Grid3DPtr grid, Block3DPtr block)
+{
+   if (block->getGlobalID()==2234)
+   {
+      UBLOG(logINFO, block->toString());
+   }
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::setSameLevelConnectors() - start");
+   int blockRank = block->getRank();
+   if (gridRank == blockRank && block->isActive())
+   {
+      block->clearWeight();
+      std::vector<Block3DPtr> neighbors;
+      int ix1 = block->getX1();
+      int ix2 = block->getX2();
+      int ix3 = block->getX3();
+      int level = block->getLevel();
+
+      for (int dir = 0; dir < D3Q27System::ENDDIR; dir++)
+      {
+         Block3DPtr neighBlock = grid->getNeighborBlock(dir, ix1, ix2, ix3, level);
+
+         if (neighBlock)
+         {
+            int neighBlockRank = neighBlock->getRank();
+            if (blockRank == neighBlockRank && neighBlock->isActive())
+            {
+               Block3DConnectorPtr connector;
+               connector = cFactory->createSameLevelDirectConnector(block, neighBlock, dir);
+               block->setConnector(connector);
+            }
+            else if (blockRank != neighBlockRank && neighBlock->isActive())
+            {
+               setRemoteConnectors(block, neighBlock, dir);
+            }
+         }
+      }
+   }
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::setSameLevelConnectors() - end");
+   if (block->getGlobalID()==2234)
+   {
+      UBLOG(logINFO, block->toString());
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void ConnectorBlockVisitor::setRemoteConnectors(Block3DPtr sblock, Block3DPtr tblock, int dir)
+{
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::setRemoteConnectors() - start");
+   CreateTransmittersHelper helper;
+   CreateTransmittersHelper::TransmitterPtr sender, receiver;
+   helper.createTransmitters(sblock, tblock, dir, CreateTransmittersHelper::NONE, sender, receiver, comm, CreateTransmittersHelper::MPI);
+
+
+   Block3DConnectorPtr connector;
+   connector = cFactory->createSameLevelVectorConnector(sblock, sender, receiver, dir);
+   sblock->setConnector(connector);
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::setRemoteConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void ConnectorBlockVisitor::setInterpolationConnectors(Grid3DPtr grid, Block3DPtr block)
+{
+   if (block->getGlobalID()==2234)
+   {
+      UBLOG(logINFO, block->toString());
+   }
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::setInterpolationConnectors() - start");
+   int blockRank = block->getRank();
+
+   //search for all blocks with different ranks
+   if (block->hasInterpolationFlagCF() && block->isActive())
+   {
+      int fbx1 = block->getX1() << 1;
+      int fbx2 = block->getX2() << 1;
+      int fbx3 = block->getX3() << 1;
+      int level = block->getLevel() + 1;
+
+      if (block->hasInterpolationFlagCF(D3Q27System::E))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2+1, fbx3, level);
+         Block3DPtr fblock01 = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblock11 = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::E);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::W))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblock01 = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblock11 = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::W);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::N))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2+1, fbx3, level);
+         Block3DPtr fblock01 = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock11 = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::N);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2, fbx3, level);
+         Block3DPtr fblock01 = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblock11 = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::S);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::T))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblock01 = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock11 = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::T);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::B))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2, fbx3, level);
+         Block3DPtr fblock01 = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblock11 = grid->getBlock(fbx1+1, fbx2+1, fbx3, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::B);
+      }
+
+      //////NE-NW-SE-SW
+      if (block->hasInterpolationFlagCF(D3Q27System::NE)&&!block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::E))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::NE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::SW)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::SW);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::SE)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2, fbx3+0, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::SE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::NW)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::W))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::NW);
+      }
+
+      /////////TE-BW-BE-TW 1-0
+      if (block->hasInterpolationFlagCF(D3Q27System::TE)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::T))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2+0, fbx3+1, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::TE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BW)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::B))
+      {
+
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2+0, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::BW);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BE)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::B))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2+0, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2+1, fbx3, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::BE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::TW)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::T))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2+0, fbx3+1, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::TW);
+      }
+
+      //////TN-BS-BN-TS
+      if (block->hasInterpolationFlagCF(D3Q27System::TN)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::T))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+0, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::TN);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BS)&& !block->hasInterpolationFlagCF(D3Q27System::S) && !block->hasInterpolationFlagCF(D3Q27System::B))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+0, fbx2, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2, fbx3, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::BS);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BN)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::B))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+0, fbx2+1, fbx3, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2+1, fbx3, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::BN);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::TS)&& !block->hasInterpolationFlagCF(D3Q27System::S) && !block->hasInterpolationFlagCF(D3Q27System::T))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+0, fbx2, fbx3+1, level);
+         Block3DPtr fblock10 = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblock01;
+         Block3DPtr fblock11;
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::TS);
+      }
+
+
+
+
+      //////corners
+      if (block->hasInterpolationFlagCF(D3Q27System::TNE)&&!block->hasInterpolationFlagCF(D3Q27System::TE)&&!block->hasInterpolationFlagCF(D3Q27System::TN)&&!block->hasInterpolationFlagCF(D3Q27System::NE)&&!block->hasInterpolationFlagCF(D3Q27System::T)&&!block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::E))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock10;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblock01;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock11;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::TNE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::TSW)&&!block->hasInterpolationFlagCF(D3Q27System::TW)&&!block->hasInterpolationFlagCF(D3Q27System::TS)&& !block->hasInterpolationFlagCF(D3Q27System::SW)&& !block->hasInterpolationFlagCF(D3Q27System::T)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblock10;// = grid->getBlock(fbx1, fbx2, fbx3, level);
+         Block3DPtr fblock01;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblock11;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::TSW);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::TSE)&&!block->hasInterpolationFlagCF(D3Q27System::TE)&&!block->hasInterpolationFlagCF(D3Q27System::TS)&& !block->hasInterpolationFlagCF(D3Q27System::SE)&& !block->hasInterpolationFlagCF(D3Q27System::T)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblock10;// = grid->getBlock(fbx1+1, fbx2, fbx3+0, level);
+         Block3DPtr fblock01;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblock11;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::TSE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::TNW)&&!block->hasInterpolationFlagCF(D3Q27System::TW)&&!block->hasInterpolationFlagCF(D3Q27System::TN)&& !block->hasInterpolationFlagCF(D3Q27System::NW)&& !block->hasInterpolationFlagCF(D3Q27System::T)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::W))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock10;// = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblock01;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock11;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::TNW);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BNE)&&!block->hasInterpolationFlagCF(D3Q27System::BE)&&!block->hasInterpolationFlagCF(D3Q27System::BN)&& !block->hasInterpolationFlagCF(D3Q27System::NE)&&!block->hasInterpolationFlagCF(D3Q27System::B)&&!block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::E))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblock10;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblock01;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock11;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::BNE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BSW)&& !block->hasInterpolationFlagCF(D3Q27System::BS)&& !block->hasInterpolationFlagCF(D3Q27System::BW)&& !block->hasInterpolationFlagCF(D3Q27System::SW)&& !block->hasInterpolationFlagCF(D3Q27System::B)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2, fbx3+0, level);
+         Block3DPtr fblock10;// = grid->getBlock(fbx1, fbx2, fbx3, level);
+         Block3DPtr fblock01;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblock11;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::BSW);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BSE)&& !block->hasInterpolationFlagCF(D3Q27System::BS)&& !block->hasInterpolationFlagCF(D3Q27System::BE)&& !block->hasInterpolationFlagCF(D3Q27System::SE)&& !block->hasInterpolationFlagCF(D3Q27System::B)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1+1, fbx2, fbx3, level);
+         Block3DPtr fblock10;// = grid->getBlock(fbx1+1, fbx2, fbx3+0, level);
+         Block3DPtr fblock01;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblock11;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::BSE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BNW)&& !block->hasInterpolationFlagCF(D3Q27System::BN)&& !block->hasInterpolationFlagCF(D3Q27System::BW)&& !block->hasInterpolationFlagCF(D3Q27System::NW)&& !block->hasInterpolationFlagCF(D3Q27System::B)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::W))
+      {
+         Block3DPtr fblock00 = grid->getBlock(fbx1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblock10;// = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblock01;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblock11;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblock00, fblock10, fblock01, fblock11, block, D3Q27System::BNW);
+      }
+
+   }
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::setInterpolationConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+
+void ConnectorBlockVisitor::setInterpolationConnectors(Block3DPtr fblock00, Block3DPtr fblock10, Block3DPtr fblock01, Block3DPtr fblock11, Block3DPtr cBlock, int dir)
+{
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::setInterpolationConnectors(...) - start");
+   int fblock00Rank = -999, fblock10Rank = -999, fblock01Rank = -999, fblock11Rank = -999;
+   if (fblock00) fblock00Rank = fblock00->getRank();
+   if (fblock01) fblock01Rank = fblock01->getRank();
+   if (fblock10) fblock10Rank = fblock10->getRank();
+   if (fblock11) fblock11Rank = fblock11->getRank();
+   int cBlockRank = cBlock->getRank();
+
+   LBMReal omegaF;
+   if (fblock00) omegaF = LBMSystem::calcCollisionFactor(nu, fblock00->getLevel());
+   if (fblock01) omegaF = LBMSystem::calcCollisionFactor(nu, fblock01->getLevel());
+   if (fblock10) omegaF = LBMSystem::calcCollisionFactor(nu, fblock10->getLevel());
+   if (fblock11) omegaF = LBMSystem::calcCollisionFactor(nu, fblock11->getLevel());
+   LBMReal omegaC = LBMSystem::calcCollisionFactor(nu, cBlock->getLevel());
+   iProcessor->setOmegas(omegaC, omegaF);
+
+   D3Q27InterpolationProcessorPtr cIProcessor(iProcessor->clone());
+   D3Q27InterpolationProcessorPtr fIProcessor00(iProcessor->clone());
+   D3Q27InterpolationProcessorPtr fIProcessor10(iProcessor->clone());
+   D3Q27InterpolationProcessorPtr fIProcessor01(iProcessor->clone());
+   D3Q27InterpolationProcessorPtr fIProcessor11(iProcessor->clone());
+
+   CreateTransmittersHelper::TransmitterPtr senderCF00, receiverCF00,
+                                             senderCF01, receiverCF01,
+                                             senderCF10, receiverCF10,
+                                             senderCF11, receiverCF11,
+                                             senderFC00, receiverFC00,
+                                             senderFC01, receiverFC01,
+                                             senderFC10, receiverFC10,
+                                             senderFC11, receiverFC11;
+
+   if (fblock00) createTransmitters(cBlock, fblock00, dir, CreateTransmittersHelper::SW, senderCF00, receiverCF00, senderFC00, receiverFC00);
+   if (fblock01) createTransmitters(cBlock, fblock01, dir, CreateTransmittersHelper::NW, senderCF01, receiverCF01, senderFC01, receiverFC01);
+   if (fblock10) createTransmitters(cBlock, fblock10, dir, CreateTransmittersHelper::SE, senderCF10, receiverCF10, senderFC10, receiverFC10);
+   if (fblock11) createTransmitters(cBlock, fblock11, dir, CreateTransmittersHelper::NE, senderCF11, receiverCF11, senderFC11, receiverFC11);
+
+   if (cBlockRank == gridRank)
+   {
+      Block3DConnectorPtr connector = cFactory->createCoarseToFineConnector(cBlock,
+         senderCF00, receiverCF00, senderCF01, receiverCF01,
+         senderCF10, receiverCF10, senderCF11, receiverCF11,
+         dir, cIProcessor);
+      cBlock->setConnector(connector);
+   }
+   if (fblock00 && fblock00Rank == gridRank)
+   {
+      Block3DConnectorPtr connector = cFactory->createFineToCoarseConnector(fblock00,
+         senderFC00, receiverFC00, dir, fIProcessor00, FineToCoarseBlock3DConnector::Type00);
+      fblock00->setConnector(connector);
+   }
+   if (fblock01 && fblock01Rank == gridRank)
+   {
+      Block3DConnectorPtr connector = cFactory->createFineToCoarseConnector(fblock01,
+         senderFC01, receiverFC01, dir, fIProcessor01, FineToCoarseBlock3DConnector::Type01);
+      fblock01->setConnector(connector);
+   }
+   if (fblock10 && fblock10Rank == gridRank)
+   {
+      Block3DConnectorPtr connector = cFactory->createFineToCoarseConnector(fblock10,
+         senderFC10, receiverFC10, dir, fIProcessor10, FineToCoarseBlock3DConnector::Type10);
+      fblock10->setConnector(connector);
+   }
+   if (fblock11 && fblock11Rank == gridRank)
+   {
+      Block3DConnectorPtr connector = cFactory->createFineToCoarseConnector(fblock11,
+         senderFC11, receiverFC11, dir, fIProcessor11, FineToCoarseBlock3DConnector::Type11);
+      fblock11->setConnector(connector);
+   }
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::setInterpolationConnectors(...) - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void ConnectorBlockVisitor::createTransmitters(Block3DPtr cBlock, Block3DPtr fBlock, int dir,
+   CreateTransmittersHelper::IBlock ib,
+   CreateTransmittersHelper::TransmitterPtr& senderCF,
+   CreateTransmittersHelper::TransmitterPtr& receiverCF,
+   CreateTransmittersHelper::TransmitterPtr& senderFC,
+   CreateTransmittersHelper::TransmitterPtr& receiverFC)
+{
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::createTransmitters(...) - start");
+   CreateTransmittersHelper helper;
+   bool MPIpool = true;
+   bool orthogonal = false;
+   int fBlockRank = fBlock->getRank();
+   int cBlockRank = cBlock->getRank();
+   if (fBlockRank == cBlockRank && fBlockRank == gridRank)
+   {
+      senderCF = receiverFC = CreateTransmittersHelper::TransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+      senderFC = receiverCF = CreateTransmittersHelper::TransmitterPtr(new TbLocalTransmitter< CbVector< LBMReal > >());
+   }
+   else if (cBlockRank == gridRank)
+   {
+      helper.createTransmitters(cBlock, fBlock, dir, ib, senderCF, receiverCF, comm, CreateTransmittersHelper::MPI);
+   }
+   else if (fBlockRank == gridRank)
+   {
+      helper.createTransmitters(fBlock, cBlock, dir, ib, senderFC, receiverFC, comm, CreateTransmittersHelper::MPI);
+   }
+   UBLOG(logDEBUG5, "ConnectorBlockVisitor::createTransmitters(...) - end");
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/ConnectorBlockVisitor.h b/source/VirtualFluidsCore/Visitors/ConnectorBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..10f6a5a04c043e590730fca1c5f8728349df44b6
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/ConnectorBlockVisitor.h
@@ -0,0 +1,37 @@
+#ifndef ConnectorBlockVisitor_H
+#define ConnectorBlockVisitor_H
+
+#include "Block3DVisitor.h"
+#include "D3Q27System.h"
+#include "Communicator.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "CreateTransmittersHelper.h"
+#include "ConnectorFactory.h"
+
+class ConnectorBlockVisitor : public Block3DVisitor
+{
+public:
+   ConnectorBlockVisitor(CommunicatorPtr comm, LBMReal nu, D3Q27InterpolationProcessorPtr iProcessor, ConnectorFactoryPtr cFactory);
+   virtual ~ConnectorBlockVisitor();
+   void visit(Grid3DPtr grid, Block3DPtr block);
+   //////////////////////////////////////////////////////////////////////////
+protected:
+   void setSameLevelConnectors(Grid3DPtr grid, Block3DPtr block);
+   void setRemoteConnectors(Block3DPtr sblock, Block3DPtr tblock, int dir);
+   void setInterpolationConnectors(Grid3DPtr grid, Block3DPtr block);
+   void setInterpolationConnectors(Block3DPtr fBlockSW, Block3DPtr fBlockSE, Block3DPtr fBlockNW, Block3DPtr fBlockNE, Block3DPtr cBlock, int dir);
+   void createTransmitters(Block3DPtr cBlock, Block3DPtr fBlock, int dir,
+      CreateTransmittersHelper::IBlock ib,
+      CreateTransmittersHelper::TransmitterPtr& senderCF,
+      CreateTransmittersHelper::TransmitterPtr& receiverCF,
+      CreateTransmittersHelper::TransmitterPtr& senderFC,
+      CreateTransmittersHelper::TransmitterPtr& receiverFC);
+   CommunicatorPtr comm;
+   int gridRank;
+   LBMReal nu;
+   D3Q27InterpolationProcessorPtr iProcessor;
+   ConnectorFactoryPtr cFactory;
+};
+
+#endif //ConnectorBlockVisitor_H
+
diff --git a/source/VirtualFluidsCore/Visitors/CreateTransmittersHelper.cpp b/source/VirtualFluidsCore/Visitors/CreateTransmittersHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9127d0baeeb81687143f3adff3a11d797ad500ad
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/CreateTransmittersHelper.cpp
@@ -0,0 +1,156 @@
+#include "CreateTransmittersHelper.h"
+#include <D3Q27System.h>
+#include <Communicator.h>
+#include <StringUtil.hpp>
+#include <basics/transmitter/TbTransmitterMpi.h>
+#include <basics/transmitter/TbTransmitterMpiPoolEx.h>
+#ifdef VF_FETOL
+   #include <FETOLTransmitterBondPool.h>
+#endif
+#include <MathUtil.hpp>
+
+unsigned CreateTransmittersHelper::vKey = 0;
+
+//////////////////////////////////////////////////////////////////////////
+CreateTransmittersHelper::CreateTransmittersHelper()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void CreateTransmittersHelper::createTransmitters(Block3DPtr sblock, Block3DPtr tblock, int dir, IBlock ib,
+                                                        TransmitterPtr& sender, TransmitterPtr& receiver, CommunicatorPtr comm, TransmitterType tType)
+{
+   //SourceBlock
+   int srcLevel = sblock->getLevel();
+   int srcID    = sblock->getGlobalID();   
+ 
+   //TargetBlock 
+   int tgtLevel = tblock->getLevel();
+   int tgtID    = tblock->getGlobalID();
+
+   int invDir = D3Q27System::INVDIR[dir];
+
+   if( srcLevel != tgtLevel ) invDir = dir;
+
+   int srcRank = 0;
+   int tgtRank = 0;
+
+   if (tType == MPI)
+   {
+      srcRank  = sblock->getRank();
+      tgtRank  = tblock->getRank();
+   } 
+#ifdef VF_FETOL
+   else if (tType == MPI2BOND)
+   {
+      srcRank  = sblock->getLocalRank();
+      tgtRank  = tblock->getLocalRank();
+   }
+#endif
+
+   if (tType == MPI 
+#ifdef VF_FETOL
+      || tType == MPI2BOND
+#endif
+      )
+   {
+      unsigned int sendPoolKey = generatePoolKey(srcRank, srcLevel, tgtRank, tgtLevel);
+      unsigned int receivePoolKey = generatePoolKey(tgtRank, tgtLevel, srcRank, srcLevel);
+
+      TbCbVectorMpiPool <LBMReal>::MpiPoolPtr sendPool = TbCbVectorMpiPool <LBMReal>::getTbCbVectorMpiPool(sendPoolKey   );
+      TbCbVectorMpiPool <LBMReal>::MpiPoolPtr recvPool = TbCbVectorMpiPool <LBMReal>::getTbCbVectorMpiPool(receivePoolKey);
+
+      MPI_Comm mpi_comm = *((MPI_Comm*) comm->getNativeCommunicator());
+
+      if( !sendPool ) sendPool = TbCbVectorMpiPool <LBMReal>::createTbCbVectorMpiPool(sendPoolKey   ,tgtRank, generateMPITag(srcLevel, tgtLevel), mpi_comm);
+      if( !recvPool ) recvPool = TbCbVectorMpiPool <LBMReal>::createTbCbVectorMpiPool(receivePoolKey,tgtRank, generateMPITag(tgtLevel, srcLevel), mpi_comm);
+
+      TbCbVectorMpiPool <LBMReal>::CbVectorKey keyOfSendCbVectorKey = generateVectorKey(sblock->getX1(), sblock->getX2(), sblock->getX3()/*tgtID*/, dir, ib);
+      TbCbVectorMpiPool <LBMReal>::CbVectorKey keyOfRecvCbVectorKey = generateVectorKey(tblock->getX1(), tblock->getX2(), tblock->getX3()/*srcID*/, invDir, ib);
+
+      //create sender-/receiver
+      sender   = TransmitterPtr( new TbCbVectorSenderMpiPool< LBMReal >(keyOfSendCbVectorKey,sendPool.get()) );
+      receiver = TransmitterPtr( new TbCbVectorReceiverMpiPool< LBMReal >(keyOfRecvCbVectorKey,recvPool.get()) );
+   }
+#ifdef VF_FETOL
+   if (tType == BOND)
+   {
+      int srcBondRank  = sblock->getRank();
+      int tgtBondRank  = tblock->getRank();
+
+      int sendBondPoolKey    = generatePoolKey(srcBondRank,srcLevel,tgtBondRank,tgtLevel);
+      int receiveBondPoolKey = generatePoolKey(tgtBondRank,tgtLevel,srcBondRank,srcLevel);
+
+      TbCbVectorBondPool <LBMReal>::BondPoolPtr sendPool = TbCbVectorBondPool <LBMReal>::getTbCbVectorBondPool(sendBondPoolKey   );
+      TbCbVectorBondPool <LBMReal>::BondPoolPtr recvPool = TbCbVectorBondPool <LBMReal>::getTbCbVectorBondPool(receiveBondPoolKey);
+
+      if( !sendPool ) sendPool = TbCbVectorBondPool <LBMReal>::createTbCbVectorBondPool(sendBondPoolKey   ,tgtBondRank, generateMPITag(srcLevel, tgtLevel));
+      if( !recvPool ) recvPool = TbCbVectorBondPool <LBMReal>::createTbCbVectorBondPool(receiveBondPoolKey,tgtBondRank, generateMPITag(tgtLevel, srcLevel));
+
+      TbCbVectorBondPool <LBMReal>::CbVectorKey keyOfSendCbVectorKey = generateVectorKey(tgtID, dir, ib);     
+      TbCbVectorBondPool <LBMReal>::CbVectorKey keyOfRecvCbVectorKey = generateVectorKey(srcID, invDir, ib);  
+
+      //create sender-/receiver 
+      sender   = TransmitterPtr( new TbCbVectorSenderBondPool< LBMReal >(keyOfSendCbVectorKey,sendPool.get()) );
+      receiver = TransmitterPtr( new TbCbVectorReceiverBondPool< LBMReal >(keyOfRecvCbVectorKey,recvPool.get()) );
+   }
+#endif
+}
+//////////////////////////////////////////////////////////////////////////
+int CreateTransmittersHelper::generateMPITag(int srcLevel, int tgtLevel)
+{
+   //The MPI standard guarantees that integers 0-32767 can be used as tags
+   if (srcLevel == tgtLevel)
+   {
+      return srcLevel;
+   }
+   else
+   {
+      srcLevel++;
+      tgtLevel++;
+      std::string str = UbSystem::toString<int>(srcLevel) + UbSystem::toString<int>(tgtLevel);
+      int r = UbSystem::stringTo<int>(str);
+      return r;
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+unsigned int CreateTransmittersHelper::generatePoolKey(int srcRank, int srcLevel, int tgtRank, int tgtLevel)
+{
+   std::string str;
+   str = StringUtil::toString<int>(srcLevel);
+   str += "#";
+   str += StringUtil::toString<int>(tgtLevel);
+   str += "#";
+   str += StringUtil::toString<int>(srcRank);
+   str += "#";
+   str += StringUtil::toString<int>(tgtRank);
+
+   unsigned int key = Utilities::RSHash(str); //by more as 900 000 elements is collision
+
+   return key;
+}
+//////////////////////////////////////////////////////////////////////////
+unsigned int CreateTransmittersHelper::generateVectorKey(int x1, int x2, int x3,/*int id,*/ int dir, IBlock ib)
+{
+   std::string str;
+   //str += StringUtil::toString<int>(id);
+   str += StringUtil::toString<int>(x1);
+   str += "#";
+   str += StringUtil::toString<int>(x2);
+   str += "#";
+   str += StringUtil::toString<int>(x3);
+   str += "#";
+   str += StringUtil::toString<int>(dir);
+   str += "#";
+   str += StringUtil::toString<int>(ib);
+
+   unsigned int key = Utilities::RSHash(str);
+
+   return key;
+
+   //return str;
+   //vKey++;
+   //return vKey;
+}
+
+
diff --git a/source/VirtualFluidsCore/Visitors/CreateTransmittersHelper.h b/source/VirtualFluidsCore/Visitors/CreateTransmittersHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff59207619e584b987ebdeda4ad8b6a87515f7e9
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/CreateTransmittersHelper.h
@@ -0,0 +1,36 @@
+#ifndef CREATETRANSMITTERSHELPER_H 
+#define CREATETRANSMITTERSHELPER_H
+
+#include "Block3D.h"
+#include "Communicator.h"
+
+#include <basics/transmitter/TbTransmitter.h>
+#include <basics/transmitter/TbTransmitterMpiPool.h>
+#include <basics/container/CbVector.h>
+
+//! \brief The class helps to create Transmitters. 
+//! \details It is created two types of Transmitters: MPI and BOND
+//! \author K. Kucher
+class CreateTransmittersHelper
+{
+public:
+   //! Switch between same level and interpolation Connectors. NONE - for same level Connectors; SW, NW, NE, SE - source/target fine blocks in grid interface   
+   enum IBlock {NONE, SW, NW, NE, SE};
+   //! Switch between MPI and BOND Transmitters
+   enum TransmitterType {MPI, BOND, MPI2BOND};
+public:
+   typedef CbVector <LBMReal> DataType;
+   typedef boost::shared_ptr< TbTransmitter< DataType > > TransmitterPtr;
+public:
+   CreateTransmittersHelper();
+   void createTransmitters(const Block3DPtr sblock, const Block3DPtr tblock, int dir, IBlock ib,
+                                 TransmitterPtr& sender, TransmitterPtr& receiver, CommunicatorPtr comm, TransmitterType tType);
+protected:
+private:
+   unsigned int generatePoolKey(int srcRank, int srcLevel, int tgtRank, int tgtLevel);
+   unsigned int  generateVectorKey(int x1, int x2, int x3,/*int id,*/ int dir, IBlock ib);
+   int generateMPITag(int srcLevel, int tgtLevel);
+   static unsigned int vKey;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/D3Q27ETInitDistributionsBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/D3Q27ETInitDistributionsBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a4be9cab5d6326c44110b82182f4579ada28baa1
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/D3Q27ETInitDistributionsBlockVisitor.cpp
@@ -0,0 +1,305 @@
+#include "D3Q27ETInitDistributionsBlockVisitor.h"
+#include "LBMKernel3D.h"
+#include "D3Q27ETBCProcessor.h"
+#include "Grid3DSystem.h"
+
+D3Q27ETInitDistributionsBlockVisitor::D3Q27ETInitDistributionsBlockVisitor() 
+   : Block3DVisitor(0, Grid3DSystem::MAXLEVEL)
+{
+   this->setVx1(0.0);
+   this->setVx2(0.0);
+   this->setVx3(0.0);
+   this->setRho(0.0);
+}
+//////////////////////////////////////////////////////////////////////////
+//D3Q27ETInitDistributionsBlockVisitor::D3Q27ETInitDistributionsBlockVisitor(LBMReal rho, LBMReal vx1, LBMReal vx2, LBMReal vx3)
+//   : Block3DVisitor(0, Grid3DSystem::MAXLEVEL)
+//{
+//   this->setVx1(vx1);
+//   this->setVx2(vx2);
+//   this->setVx3(vx3);
+//   this->setRho(rho);
+//}
+//////////////////////////////////////////////////////////////////////////
+D3Q27ETInitDistributionsBlockVisitor::D3Q27ETInitDistributionsBlockVisitor( LBMReal nu, LBMReal rho, LBMReal vx1, LBMReal vx2, LBMReal vx3)
+   : Block3DVisitor(0, Grid3DSystem::MAXLEVEL)
+{
+   this->setVx1(vx1);
+   this->setVx2(vx2);
+   this->setVx3(vx3);
+   this->setRho(rho);
+   this->setNu(nu);
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx1( const mu::Parser& parser)  
+{ 
+   this->checkFunction(parser); 
+   this->muVx1 = parser;  
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx2( const mu::Parser& parser)
+{ 
+   this->checkFunction(parser); 
+   this->muVx2 = parser;  
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx3( const mu::Parser& parser)  
+{ 
+   this->checkFunction(parser); 
+   this->muVx3 = parser;  
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setRho( const mu::Parser& parser)  
+{ 
+   this->checkFunction(parser); 
+   this->muRho = parser;  
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx1( const std::string& muParserString)  
+{ 
+   this->muVx1.SetExpr(muParserString); 
+   this->checkFunction(muVx1); 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx2( const std::string& muParserString) 
+{ 
+   this->muVx2.SetExpr(muParserString); 
+   this->checkFunction(muVx2); 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx3( const std::string& muParserString)  
+{ 
+   this->muVx3.SetExpr(muParserString); 
+   this->checkFunction(muVx3); 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setRho( const std::string& muParserString)  
+{ 
+   this->muRho.SetExpr(muParserString); 
+   this->checkFunction(muRho); 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx1( LBMReal vx1 ) 
+{ 
+   this->muVx1.SetExpr( UbSystem::toString(vx1,D3Q27RealLim::digits10) );  
+   this->checkFunction(muVx1); 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx2( LBMReal vx2 ) 
+{ 
+   this->muVx2.SetExpr( UbSystem::toString(vx2,D3Q27RealLim::digits10) );  
+   this->checkFunction(muVx2); 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setVx3( LBMReal vx3 ) 
+{ 
+   this->muVx3.SetExpr( UbSystem::toString(vx3,D3Q27RealLim::digits10) );  
+   this->checkFunction(muVx3); 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setRho( LBMReal rho ) 
+{ 
+   this->muRho.SetExpr( UbSystem::toString(rho,D3Q27RealLim::digits10) );  
+   this->checkFunction(muRho); 
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::visit(const Grid3DPtr grid, Block3DPtr block) 
+{
+   using namespace D3Q27System;
+
+   if(!block) UB_THROW( UbException(UB_EXARGS,"block is not exist") );
+
+   UbTupleDouble3 blockLengths = grid->getBlockLengths(block);
+   UbTupleDouble3 nodeOffset   = grid->getNodeOffset(block);
+   double dx = grid->getDeltaX(block);
+   LBMReal o  = LBMSystem::calcCollisionFactor(nu, block->getLevel());
+   
+
+   //define vars for functions
+   mu::value_type x1,x2,x3;
+   this->muVx1.DefineVar("x1",&x1); this->muVx1.DefineVar("x2",&x2); this->muVx1.DefineVar("x3",&x3);
+   this->muVx2.DefineVar("x1",&x1); this->muVx2.DefineVar("x2",&x2); this->muVx2.DefineVar("x3",&x3);
+   this->muVx3.DefineVar("x1",&x1); this->muVx3.DefineVar("x2",&x2); this->muVx3.DefineVar("x3",&x3);
+   this->muRho.DefineVar("x1",&x1); this->muRho.DefineVar("x2",&x2); this->muRho.DefineVar("x3",&x3);
+
+   //Funktionszeiger
+   typedef void (*CalcFeqsFct)(LBMReal* const& /*feq[27]*/,const LBMReal& /*(d)rho*/,const LBMReal& /*vx1*/,const LBMReal& /*vx2*/,const LBMReal& /*vx3*/);
+   CalcFeqsFct   calcFeqsFct   = NULL;
+   
+   LBMReal vx1,vx2,vx3,rho;
+
+   int gridRank = grid->getRank();
+   int blockRank = block->getRank();
+
+   if (blockRank == gridRank && block->isActive())
+   {
+      LBMKernel3DPtr kernel = block->getKernel();
+      if (!kernel)
+         throw UbException(UB_EXARGS, "The LBM kernel isn't exist in block: "+block->toString());
+
+      if(kernel->getCompressible()) 
+         calcFeqsFct   = &D3Q27System::calcCompFeq; 
+      else                                                        
+         calcFeqsFct   = &D3Q27System::calcIncompFeq; 
+
+      UbTupleDouble3 org = grid->getBlockWorldCoordinates(block);
+
+      BCArray3D<D3Q27BoundaryCondition> bcArray = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+      EsoTwist3DPtr           distributions     = boost::dynamic_pointer_cast<EsoTwist3D>(kernel->getDataSet()->getFdistributions());     
+
+      LBMReal f[D3Q27System::ENDF+1];
+
+      size_t nx1 = distributions->getNX1();
+      size_t nx2 = distributions->getNX2();
+      size_t nx3 = distributions->getNX3();
+
+      for(int ix3=0; ix3<bcArray.getNX3(); ix3++)
+         for(int ix2=0; ix2<bcArray.getNX2(); ix2++)
+            for(int ix1=0; ix1<bcArray.getNX1(); ix1++)
+            {
+               UbTupleDouble3 coords = grid->getNodeCoordinates(block, ix1, ix2, ix3);
+               x1 = val<1>(coords);
+               x2 = val<2>(coords);
+               x3 = val<3>(coords);
+
+               vx1 = muVx1.Eval();
+               vx2 = muVx2.Eval();
+               vx3 = muVx3.Eval();
+               rho = muRho.Eval();
+
+               //x-derivative
+               double deltaX=dx*0.5;
+               x1 = val<1>(coords)+deltaX;
+               double vx1Plusx1 = muVx1.Eval();
+               double vx2Plusx1 = muVx2.Eval();
+               double vx3Plusx1 = muVx3.Eval();
+
+               x1 = val<1>(coords)-deltaX;
+               double vx1Minusx1 = muVx1.Eval();
+               double vx2Minusx1 = muVx2.Eval();
+               double vx3Minusx1 = muVx3.Eval();
+
+               //y-derivative
+               x1 = val<1>(coords);
+               x2 = val<2>(coords)+deltaX;
+               double vx1Plusx2 = muVx1.Eval();
+               double vx2Plusx2 = muVx2.Eval();
+               double vx3Plusx2 = muVx3.Eval();
+
+               x2 = val<2>(coords)-deltaX;
+               double vx1Minusx2 = muVx1.Eval();
+               double vx2Minusx2 = muVx2.Eval();
+               double vx3Minusx2 = muVx3.Eval();
+
+               //z-derivative
+               x2 = val<2>(coords);
+               x3 = val<3>(coords)+deltaX;
+               double vx1Plusx3 = muVx1.Eval();
+               double vx2Plusx3 = muVx2.Eval();
+               double vx3Plusx3 = muVx3.Eval();
+
+               x3 = val<3>(coords)-deltaX;
+               double vx1Minusx3 = muVx1.Eval();
+               double vx2Minusx3 = muVx2.Eval();
+               double vx3Minusx3 = muVx3.Eval();
+
+               double ax=(vx1Plusx1-vx1Minusx1)/(2.0*deltaX)*dx;
+               double bx=(vx2Plusx1-vx2Minusx1)/(2.0*deltaX)*dx;
+               double cx=(vx3Plusx1-vx3Minusx1)/(2.0*deltaX)*dx;
+
+               double ay=(vx1Plusx2-vx1Minusx2)/(2.0*deltaX)*dx;
+               double by=(vx2Plusx2-vx2Minusx2)/(2.0*deltaX)*dx;
+               double cy=(vx3Plusx2-vx3Minusx2)/(2.0*deltaX)*dx;
+
+               double az=(vx1Plusx3-vx1Minusx3)/(2.0*deltaX)*dx;
+               double bz=(vx2Plusx3-vx2Minusx3)/(2.0*deltaX)*dx;
+               double cz=(vx3Plusx3-vx3Minusx3)/(2.0*deltaX)*dx;
+               double eps_new=1.0;
+               LBMReal op = 1.;
+
+               LBMReal feq[27];
+
+               calcFeqsFct(feq,rho,vx1,vx2,vx3);
+
+               double f_E    = eps_new *((5.*ax*o + 5.*by*o + 5.*cz*o - 8.*ax*op + 4.*by*op + 4.*cz*op)/(54.*o*op));
+               double f_N    = f_E + eps_new *((2.*(ax - by))/(9.*o));
+               double f_T    = f_E + eps_new *((2.*(ax - cz))/(9.*o));
+               double f_NE   = eps_new *(-(5.*cz*o + 3.*(ay + bx)*op - 2.*cz*op + ax*(5.*o + op) + by*(5.*o + op))/(54.*o*op));
+               double f_SE   = f_NE + eps_new *((  ay + bx )/(9.*o));
+               double f_TE   = eps_new *(-(5.*cz*o + by*(5.*o - 2.*op) + 3.*(az + cx)*op + cz*op + ax*(5.*o + op))/(54.*o*op));
+               double f_BE   = f_TE + eps_new *((  az + cx )/(9.*o));
+               double f_TN   = eps_new *(-(5.*ax*o + 5.*by*o + 5.*cz*o - 2.*ax*op + by*op + 3.*bz*op + 3.*cy*op + cz*op)/(54.*o*op));
+               double f_BN   = f_TN + eps_new *((  bz + cy )/(9.*o));
+               double f_ZERO = eps_new *((5.*(ax + by + cz))/(9.*op));
+               double f_TNE  = eps_new *(-(ay + az + bx + bz + cx + cy)/(72.*o));
+               double f_TSW  = - eps_new *((ay + bx)/(36.*o)) - f_TNE;
+               double f_TSE  = - eps_new *((az + cx)/(36.*o)) - f_TNE;
+               double f_TNW  = - eps_new *((bz + cy)/(36.*o)) - f_TNE;
+
+
+               f[E]    = f_E    + feq[E];
+               f[W]    = f_E    + feq[W];
+               f[N]    = f_N    + feq[N];
+               f[S]    = f_N    + feq[S];
+               f[T]    = f_T    + feq[T];
+               f[B]    = f_T    + feq[B];
+               f[NE]   = f_NE   + feq[NE];
+               f[SW]   = f_NE   + feq[SW];
+               f[SE]   = f_SE   + feq[SE];
+               f[NW]   = f_SE   + feq[NW];
+               f[TE]   = f_TE   + feq[TE];
+               f[BW]   = f_TE   + feq[BW];
+               f[BE]   = f_BE   + feq[BE];
+               f[TW]   = f_BE   + feq[TW];
+               f[TN]   = f_TN   + feq[TN];
+               f[BS]   = f_TN   + feq[BS];
+               f[BN]   = f_BN   + feq[BN];
+               f[TS]   = f_BN   + feq[TS];
+               f[TNE]  = f_TNE  + feq[TNE];
+               f[TNW]  = f_TNW  + feq[TNW];
+               f[TSE]  = f_TSE  + feq[TSE];
+               f[TSW]  = f_TSW  + feq[TSW];
+               f[BNE]  = f_TSW  + feq[BNE];
+               f[BNW]  = f_TSE  + feq[BNW];
+               f[BSE]  = f_TNW  + feq[BSE];
+               f[BSW]  = f_TNE  + feq[BSW];
+               f[ZERO] = f_ZERO + feq[ZERO];
+
+               //calcFeqsFct(f,rho,vx1,vx2,vx3);
+               distributions->setDistribution(f, ix1, ix2, ix3);
+               distributions->setDistributionInv(f, ix1, ix2, ix3);
+            }
+   }
+
+   //variablen der functions loeschen, da die verwiesenen Objecte nach dem verlassen des scopes ungueltig sind!
+   this->muVx1.ClearVar();
+   this->muVx2.ClearVar();
+   this->muVx3.ClearVar();
+   this->muRho.ClearVar();
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::checkFunction(mu::Parser fct)
+{
+   double x1=1.0,x2=1.0,x3=1.0;
+   fct.DefineVar("x1",&x1); 
+   fct.DefineVar("x2",&x2); 
+   fct.DefineVar("x3",&x3);
+
+   try
+   {
+      fct.Eval();
+      fct.ClearVar();
+   }
+   catch(mu::ParserError& e)
+   {
+      throw UbException(UB_EXARGS,"function: "+e.GetExpr() + (std::string)"error: "+e.GetMsg()
+         +(std::string)", only x1,x2,x3 are allowed as variables" );
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27ETInitDistributionsBlockVisitor::setNu( LBMReal nu )
+{
+   this->nu = nu;
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/D3Q27ETInitDistributionsBlockVisitor.h b/source/VirtualFluidsCore/Visitors/D3Q27ETInitDistributionsBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..893bab67b1abddb7fdef8a6de491deb41a01c6e9
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/D3Q27ETInitDistributionsBlockVisitor.h
@@ -0,0 +1,85 @@
+#ifndef D3Q27ETInitDistributionsBlockVisitor_H
+#define D3Q27ETInitDistributionsBlockVisitor_H
+
+#include <boost/foreach.hpp>
+
+#include "Block3DVisitor.h"
+#include "D3Q27System.h"
+#include "Block3D.h"
+
+#include <MuParser/include/muParser.h>
+
+/*================================================================================*/
+/*  D3Q27ETInitDistributionsBlockVisitor                                             */
+/*                                                                                */
+/**
+more flexible way to initialize flow area
+you can define functions to calculate macroscopic values for feq 
+!!! x1,x2,x3 are automatically defined via this adapter and are the real world
+vertex coordinates !!!
+
+if function is invalid an UbException with detailed information is thrown
+
+<BR><BR>
+@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
+@version 1.0 - 19.04.08
+*/ 
+
+//! \details example:<BR>
+//! D3Q27InitDistributionsBlockVisitor init(1.0,0.0,0.0,0.0);<BR>
+//! Bem.: rho=0.0 bei inkompressibel<BR>
+//! init.setVx1("0.01*x2");<BR>
+//! init.setVx1("0.01*x2^2");<BR>
+//! patch.adaptByPatchCriterion(init);
+
+
+
+class D3Q27ETInitDistributionsBlockVisitor : public Block3DVisitor
+{
+public:
+   typedef std::numeric_limits<LBMReal> D3Q27RealLim;
+
+public:
+   D3Q27ETInitDistributionsBlockVisitor();
+   //D3Q27ETInitDistributionsBlockVisitor(LBMReal rho, LBMReal vx1=0.0, LBMReal vx2=0.0, LBMReal vx3=0.0);
+   //! Constructor
+   //! \param nu - viscosity
+   //! \param rho - density
+   //! \param vx1 - velocity in x
+   //! \param vx2 - velocity in y
+   //! \param vx3 - velocity in z
+   D3Q27ETInitDistributionsBlockVisitor( LBMReal nu, LBMReal rho, LBMReal vx1=0.0, LBMReal vx2=0.0, LBMReal vx3=0.0);
+   //////////////////////////////////////////////////////////////////////////
+   //automatic vars are: x1,x2, x3
+   //ussage example: setVx1("x1*0.01+x2*0.003")
+   //////////////////////////////////////////////////////////////////////////
+   void setVx1( const mu::Parser& parser);
+   void setVx2( const mu::Parser& parser);
+   void setVx3( const mu::Parser& parser);
+   void setRho( const mu::Parser& parser);
+
+   void setVx1( const std::string& muParserString);
+   void setVx2( const std::string& muParserString);
+   void setVx3( const std::string& muParserString);
+   void setRho( const std::string& muParserString);
+   //////////////////////////////////////////////////////////////////////////
+   void setVx1( LBMReal vx1 );
+   void setVx2( LBMReal vx2 );
+   void setVx3( LBMReal vx3 );
+   void setRho( LBMReal rho );
+   void setNu( LBMReal nu );
+
+   void visit(Grid3DPtr grid, Block3DPtr block);
+
+protected:
+   void checkFunction(mu::Parser fct);
+
+private:
+   mu::Parser muVx1;
+   mu::Parser muVx2;
+   mu::Parser muVx3;
+   mu::Parser muRho;
+   LBMReal nu;
+};
+
+#endif //D3Q27INITDISTRIBUTIONSPATCHVISITOR_H
diff --git a/source/VirtualFluidsCore/Visitors/D3Q27SetConnectorsBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/D3Q27SetConnectorsBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0e8a948bf989a610ab73e15b3e1d341ea189d3ad
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/D3Q27SetConnectorsBlockVisitor.cpp
@@ -0,0 +1,503 @@
+#include "D3Q27SetConnectorsBlockVisitor.h"
+#include "D3Q27ETFullVectorConnector.h"
+#include "D3Q27ETFullDirectConnector.h"
+#include "D3Q27ETFullDirectConnector2.h"
+#include "D3Q27ETFullVectorConnector.h"
+#include "D3Q27ETCFVectorConnector.h"
+#include "D3Q27ETFCVectorConnector.h"
+#include "D3Q27ETCFOffVectorConnector.h"
+#include "D3Q27ETFCOffVectorConnector.h"
+#include "Grid3DSystem.h"
+#include "D3Q27ETDirectConnector.h"
+#include <basics/transmitter/TbTransmitterLocal.h>
+
+D3Q27SetConnectorsBlockVisitor::D3Q27SetConnectorsBlockVisitor(CommunicatorPtr comm, bool fullConnector, int dirs, 
+															   LBMReal nue, D3Q27InterpolationProcessorPtr iProcessor) :
+Block3DVisitor(0, Grid3DSystem::MAXLEVEL), 
+	comm(comm),
+	fullConnector(fullConnector),
+	dirs(dirs),
+	nue(nue),
+	iProcessor(iProcessor)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+D3Q27SetConnectorsBlockVisitor::~D3Q27SetConnectorsBlockVisitor(void)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27SetConnectorsBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+	if(!block) return;
+
+	UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::visit() - start");
+   UBLOG(logDEBUG5, block->toString());
+
+	gridRank = comm->getProcessID();
+	grid->setRank(gridRank);
+
+	setSameLevelConnectors(grid, block);
+
+	if(grid->getFinestInitializedLevel() > grid->getCoarsestInitializedLevel())
+		setInterpolationConnectors(grid, block);
+
+	UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::visit() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27SetConnectorsBlockVisitor::setSameLevelConnectors(Grid3DPtr grid, Block3DPtr block)
+{
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setSameLevelConnectors() - start");
+	int blockRank = block->getRank();
+	if (gridRank == blockRank && block->isActive())
+	{
+		block->clearWeight();
+		std::vector<Block3DPtr> neighbors; 
+		int ix1 = block->getX1();
+		int ix2 = block->getX2();
+		int ix3 = block->getX3();
+		int level = block->getLevel();
+		//grid->getAllNeighbors(ix1, ix2, ix3, level, level, neighbors);
+
+      //if (block->getGlobalID()==2512)
+      //{
+      //   int test = 0;
+      //}
+
+		for( int dir = 0; dir < dirs; dir++)
+		{
+			Block3DPtr neighBlock = grid->getNeighborBlock(dir, ix1, ix2, ix3, level);
+
+			if(neighBlock)
+			{
+				int neighBlockRank = neighBlock->getRank();
+				if(blockRank == neighBlockRank && neighBlock->isActive())
+				{
+					Block3DConnectorPtr connector;
+
+					//if(block->hasInterpolationFlag())
+					////connector = Block3DConnectorPtr(new ETOrthoFullDirectConnector( block, neighBlock, dir, dirs));
+					connector = Block3DConnectorPtr(new D3Q27ETFullDirectConnector2( block, neighBlock, dir));
+					//else
+					//connector = Block3DConnectorPtr(new D3Q27ETDirectConnector( block, neighBlock, dir));
+					//D3Q27CreateTransmittersHelper helper;
+					//D3Q27CreateTransmittersHelper::TransmitterPtr sender, receiver;
+					//sender = receiver = D3Q27CreateTransmittersHelper::TransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+					//connector = Block3DConnectorPtr(new D3Q27ETFullVectorConnector< TbTransmitter< CbVector< LBMReal > > >(block, sender, receiver, dir));
+
+					block->setConnector(connector);
+				}
+				else if(blockRank != neighBlockRank && neighBlock->isActive())
+				{
+					setRemoteConnectors(block, neighBlock, dir, fullConnector);  
+
+					if(dir >=0 && dir<=5)
+					{
+						int weight = block->getWeight(neighBlockRank);
+						weight++;
+						block->setWeight(neighBlockRank, weight);
+					}
+				}
+			}
+		}
+      
+      //if (block->getGlobalID()==2794)
+      //{
+      //   UBLOG(logINFO, block->toString());
+      //}
+		
+      int weight = block->getNumberOfLocalConnectorsForSurfaces();
+		weight = 6 - weight;
+		block->addWeightForAll(weight);
+	}
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setSameLevelConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27SetConnectorsBlockVisitor::setRemoteConnectors(Block3DPtr sblock, Block3DPtr tblock, int dir, bool fullConnector)
+{
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setRemoteConnectors() - start");
+	CreateTransmittersHelper helper;
+	CreateTransmittersHelper::TransmitterPtr sender, receiver;
+	helper.createTransmitters(sblock, tblock, dir, CreateTransmittersHelper::NONE, sender, receiver, comm, CreateTransmittersHelper::MPI);
+
+
+	Block3DConnectorPtr connector;
+	//if(fullConnector)
+	//connector = Block3DConnectorPtr(new ETOrthoFullVectorConnector< TbTransmitter< CbVector< LBMReal > > >(sblock, sender, receiver, dir, dirs));
+	connector = Block3DConnectorPtr(new D3Q27ETFullVectorConnector(sblock, sender, receiver, dir));
+	//connector = Block3DConnectorPtr(new D3Q27ETFullVectorConnector< TbTransmitter< std::vector< LBMReal > > >(sblock, sender, receiver, dir));
+	//else
+	//   connector = Block3DConnectorPtr(new D3Q27ETVectorConnector< TbTransmitter< CbVector< LBMReal > > >(sblock, sender, receiver, dir));
+	sblock->setConnector(connector);
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setRemoteConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27SetConnectorsBlockVisitor::setInterpolationConnectors(Grid3DPtr grid, Block3DPtr block)
+{
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setInterpolationConnectors() - start");
+	int blockRank = block->getRank();
+	if (block->getGlobalID()==394)
+	{
+		int test=0;
+	}
+
+	//search for all blocks with different ranks
+	if (block->hasInterpolationFlagCF() && block->isActive())
+	{
+		int fbx1 = block->getX1() << 1;
+		int fbx2 = block->getX2() << 1;
+		int fbx3 = block->getX3() << 1;
+		int level = block->getLevel() + 1;
+
+		if( block->hasInterpolationFlagCF(D3Q27System::E))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+1,fbx2,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3,level);
+			Block3DPtr fblockNW = grid->getBlock(fbx1+1,fbx2,fbx3+1,level);
+			Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::E);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::W))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1,fbx2+1,fbx3,level);
+			Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2,fbx3+1,level);
+			Block3DPtr fblockNE = grid->getBlock(fbx1,fbx2+1,fbx3+1,level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::W);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::N))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2+1,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3,level);
+			Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2+1,fbx3+1,level);
+			Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::N);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::S))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3,level);
+			Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2,fbx3+1,level);
+			Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2,fbx3+1,level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::S);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::T))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3+1,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3+1,level);
+			Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2+1,fbx3+1,level);
+			Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::T);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::B))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3,level);
+			Block3DPtr fblockNW = grid->getBlock(fbx1,fbx2+1,fbx3,level);
+			Block3DPtr fblockNE = grid->getBlock(fbx1+1,fbx2+1,fbx3,level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::B);
+		}
+
+		//////NE-NW-SE-SW
+		if( block->hasInterpolationFlagCF(D3Q27System::NE)&&!block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::E))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+1,fbx2+1,fbx3+0,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::NE);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::SW)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::S))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1,fbx2,fbx3+1,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::SW);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::SE)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::S))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+1,fbx2,fbx3+0,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3+1,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::SE);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::NW)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::W))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2+1,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1,fbx2+1,fbx3+1,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::NW);
+		}
+
+		/////////TE-BW-BE-TW 1-0
+		if( block->hasInterpolationFlagCF(D3Q27System::TE)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::T))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+1,fbx2+0,fbx3+1,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+1, fbx2+0, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::TE);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::BW)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::B))
+		{
+
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2+0,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1,fbx2+1,fbx3,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1, fbx2+0, fbx3, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::BW);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::BE)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::B))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+1,fbx2+0,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+1, fbx2+0, fbx3, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::BE);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::TW)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::T))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1,fbx2+0,fbx3+1,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1,fbx2+1,fbx3+1,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1, fbx2+0, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::TW);
+		}
+
+		//////TN-BS-BN-TS
+		if( block->hasInterpolationFlagCF(D3Q27System::TN)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::T))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+0,fbx2+1,fbx3+1,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3+1,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+0, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::TN);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::BS)&& !block->hasInterpolationFlagCF(D3Q27System::S) && !block->hasInterpolationFlagCF(D3Q27System::B))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+0,fbx2,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+0, fbx2, fbx3, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2, fbx3, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::BS);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::BN)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::B))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+0,fbx2+1,fbx3,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2+1,fbx3,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+0, fbx2+1, fbx3, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::BN);
+		}
+		if( block->hasInterpolationFlagCF(D3Q27System::TS)&& !block->hasInterpolationFlagCF(D3Q27System::S) && !block->hasInterpolationFlagCF(D3Q27System::T))
+		{
+			Block3DPtr fblockSW = grid->getBlock(fbx1+0,fbx2,fbx3+1,level);
+			Block3DPtr fblockSE = grid->getBlock(fbx1+1,fbx2,fbx3+1,level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+0, fbx2, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+
+			setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::TS);
+		}
+
+
+
+
+      //////corners
+      if (block->hasInterpolationFlagCF(D3Q27System::TNE)&&!block->hasInterpolationFlagCF(D3Q27System::TE)&&!block->hasInterpolationFlagCF(D3Q27System::TN)&&!block->hasInterpolationFlagCF(D3Q27System::NE)&&!block->hasInterpolationFlagCF(D3Q27System::T)&&!block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::E))
+      {
+         Block3DPtr fblockSW = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockSE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::TNE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::TSW)&&!block->hasInterpolationFlagCF(D3Q27System::TW)&&!block->hasInterpolationFlagCF(D3Q27System::TS)&& !block->hasInterpolationFlagCF(D3Q27System::SW)&& !block->hasInterpolationFlagCF(D3Q27System::T)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblockSW = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblockSE;// = grid->getBlock(fbx1, fbx2, fbx3, level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::TSW);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::TSE)&&!block->hasInterpolationFlagCF(D3Q27System::TE)&&!block->hasInterpolationFlagCF(D3Q27System::TS)&& !block->hasInterpolationFlagCF(D3Q27System::SE)&& !block->hasInterpolationFlagCF(D3Q27System::T)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblockSW = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblockSE;// = grid->getBlock(fbx1+1, fbx2, fbx3+0, level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::TSE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::TNW)&&!block->hasInterpolationFlagCF(D3Q27System::TW)&&!block->hasInterpolationFlagCF(D3Q27System::TN)&& !block->hasInterpolationFlagCF(D3Q27System::NW)&& !block->hasInterpolationFlagCF(D3Q27System::T)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::W))
+      {
+         Block3DPtr fblockSW = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockSE;// = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::TNW);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BNE)&&!block->hasInterpolationFlagCF(D3Q27System::BE)&&!block->hasInterpolationFlagCF(D3Q27System::BN)&& !block->hasInterpolationFlagCF(D3Q27System::NE)&&!block->hasInterpolationFlagCF(D3Q27System::B)&&!block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::E))
+      {
+         Block3DPtr fblockSW = grid->getBlock(fbx1+1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblockSE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::BNE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BSW)&& !block->hasInterpolationFlagCF(D3Q27System::BS)&& !block->hasInterpolationFlagCF(D3Q27System::BW)&& !block->hasInterpolationFlagCF(D3Q27System::SW)&& !block->hasInterpolationFlagCF(D3Q27System::B)&& !block->hasInterpolationFlagCF(D3Q27System::W) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblockSW = grid->getBlock(fbx1, fbx2, fbx3+0, level);
+         Block3DPtr fblockSE;// = grid->getBlock(fbx1, fbx2, fbx3, level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::BSW);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BSE)&& !block->hasInterpolationFlagCF(D3Q27System::BS)&& !block->hasInterpolationFlagCF(D3Q27System::BE)&& !block->hasInterpolationFlagCF(D3Q27System::SE)&& !block->hasInterpolationFlagCF(D3Q27System::B)&& !block->hasInterpolationFlagCF(D3Q27System::E) && !block->hasInterpolationFlagCF(D3Q27System::S))
+      {
+         Block3DPtr fblockSW = grid->getBlock(fbx1+1, fbx2, fbx3, level);
+         Block3DPtr fblockSE;// = grid->getBlock(fbx1+1, fbx2, fbx3+0, level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1+1, fbx2, fbx3+1, level);
+
+         setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::BSE);
+      }
+      if (block->hasInterpolationFlagCF(D3Q27System::BNW)&& !block->hasInterpolationFlagCF(D3Q27System::BN)&& !block->hasInterpolationFlagCF(D3Q27System::BW)&& !block->hasInterpolationFlagCF(D3Q27System::NW)&& !block->hasInterpolationFlagCF(D3Q27System::B)&& !block->hasInterpolationFlagCF(D3Q27System::N) && !block->hasInterpolationFlagCF(D3Q27System::W))
+      {
+         Block3DPtr fblockSW = grid->getBlock(fbx1, fbx2+1, fbx3+0, level);
+         Block3DPtr fblockSE;// = grid->getBlock(fbx1, fbx2+1, fbx3, level);
+         Block3DPtr fblockNW;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+         Block3DPtr fblockNE;// = grid->getBlock(fbx1, fbx2+1, fbx3+1, level);
+
+         setInterpolationConnectors(fblockSW, fblockSE, fblockNW, fblockNE, block, D3Q27System::BNW);
+      }
+
+	}
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setInterpolationConnectors() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27SetConnectorsBlockVisitor::setInterpolationConnectors(Block3DPtr fBlockSW, Block3DPtr fBlockSE, Block3DPtr fBlockNW, Block3DPtr fBlockNE, Block3DPtr cBlock, int dir)
+{
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setInterpolationConnectors(...) - start");
+	int fBlockSWRank = -999, fBlockSERank = -999, fBlockNWRank = -999, fBlockNERank = -999;
+	if(fBlockSW) fBlockSWRank = fBlockSW->getRank();
+	if(fBlockNW) fBlockNWRank = fBlockNW->getRank();
+	if(fBlockSE) fBlockSERank = fBlockSE->getRank();
+	if(fBlockNE) fBlockNERank = fBlockNE->getRank();
+	int cBlockRank   = cBlock->getRank();
+
+	LBMReal omegaF;
+	if(fBlockSW) omegaF =LBMSystem::calcCollisionFactor(nue, fBlockSW->getLevel());
+	if(fBlockNW) omegaF =LBMSystem::calcCollisionFactor(nue, fBlockNW->getLevel());
+	if(fBlockSE) omegaF =LBMSystem::calcCollisionFactor(nue, fBlockSE->getLevel());
+	if(fBlockNE) omegaF =LBMSystem::calcCollisionFactor(nue, fBlockNE->getLevel());
+	LBMReal omegaC = LBMSystem::calcCollisionFactor(nue, cBlock->getLevel());
+	iProcessor->setOmegas(omegaC, omegaF);
+
+	D3Q27InterpolationProcessorPtr cIProcessor(iProcessor->clone());
+	D3Q27InterpolationProcessorPtr fIProcessorSW(iProcessor->clone());
+	D3Q27InterpolationProcessorPtr fIProcessorSE(iProcessor->clone());
+	D3Q27InterpolationProcessorPtr fIProcessorNW(iProcessor->clone());
+	D3Q27InterpolationProcessorPtr fIProcessorNE(iProcessor->clone());
+
+	CreateTransmittersHelper::TransmitterPtr senderCFevenEvenSW, receiverCFevenEvenSW, 
+		senderCFevenOddNW,  receiverCFevenOddNW, 
+		senderCFoddEvenSE,  receiverCFoddEvenSE, 
+		senderCFoddOddNE,   receiverCFoddOddNE,
+		senderFCevenEvenSW, receiverFCevenEvenSW, 
+		senderFCevenOddNW,  receiverFCevenOddNW, 
+		senderFCoddEvenSE,  receiverFCoddEvenSE, 
+		senderFCoddOddNE,   receiverFCoddOddNE;
+
+	if(fBlockSW) createTransmitters(cBlock, fBlockSW, dir, CreateTransmittersHelper::SW, senderCFevenEvenSW, receiverCFevenEvenSW, senderFCevenEvenSW, receiverFCevenEvenSW);
+	if(fBlockNW) createTransmitters(cBlock, fBlockNW, dir, CreateTransmittersHelper::NW, senderCFevenOddNW, receiverCFevenOddNW, senderFCevenOddNW, receiverFCevenOddNW);
+	if(fBlockSE) createTransmitters(cBlock, fBlockSE, dir, CreateTransmittersHelper::SE, senderCFoddEvenSE, receiverCFoddEvenSE, senderFCoddEvenSE, receiverFCoddEvenSE);
+	if(fBlockNE) createTransmitters(cBlock, fBlockNE, dir, CreateTransmittersHelper::NE, senderCFoddOddNE, receiverCFoddOddNE, senderFCoddOddNE, receiverFCoddOddNE);
+
+	if(cBlockRank == gridRank)
+	{
+      Block3DConnectorPtr connector(new D3Q27ETCFOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(cBlock,
+			senderCFevenEvenSW, receiverCFevenEvenSW, senderCFevenOddNW,  receiverCFevenOddNW, 
+			senderCFoddEvenSE,  receiverCFoddEvenSE,  senderCFoddOddNE,   receiverCFoddOddNE, 
+			dir, cIProcessor) );
+		cBlock->setConnector(connector);
+	}
+	if(fBlockSW && fBlockSWRank == gridRank)
+	{
+		Block3DConnectorPtr connector( new D3Q27ETFCOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(fBlockSW, 
+			senderFCevenEvenSW, receiverFCevenEvenSW, dir, fIProcessorSW, EvenEvenSW) );
+		fBlockSW->setConnector(connector);
+	}
+	if(fBlockNW && fBlockNWRank == gridRank)
+	{
+		Block3DConnectorPtr connector( new D3Q27ETFCOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(fBlockNW, 
+			senderFCevenOddNW, receiverFCevenOddNW, dir, fIProcessorNW, EvenOddNW) );
+		fBlockNW->setConnector(connector);
+	}
+	if(fBlockSE && fBlockSERank == gridRank)
+	{
+		Block3DConnectorPtr connector( new D3Q27ETFCOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(fBlockSE, 
+			senderFCoddEvenSE, receiverFCoddEvenSE, dir, fIProcessorSE, OddEvenSE) );
+		fBlockSE->setConnector(connector);
+	}
+	if(fBlockNE && fBlockNERank == gridRank)
+	{
+		Block3DConnectorPtr connector( new D3Q27ETFCOffVectorConnector< TbTransmitter< CbVector< LBMReal > > >(fBlockNE, 
+			senderFCoddOddNE, receiverFCoddOddNE, dir, fIProcessorNE, OddOddNE) );
+		fBlockNE->setConnector(connector);
+	}
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::setInterpolationConnectors(...) - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27SetConnectorsBlockVisitor::createTransmitters(Block3DPtr cBlock, Block3DPtr fBlock, int dir, 
+                                                        CreateTransmittersHelper::IBlock ib, 
+														              CreateTransmittersHelper::TransmitterPtr& senderCF, 
+														              CreateTransmittersHelper::TransmitterPtr& receiverCF, 
+														              CreateTransmittersHelper::TransmitterPtr& senderFC, 
+														              CreateTransmittersHelper::TransmitterPtr& receiverFC)
+{
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::createTransmitters(...) - start");
+	CreateTransmittersHelper helper;
+	bool MPIpool = true;
+	bool orthogonal = false;
+	int fBlockRank = fBlock->getRank();
+	int cBlockRank = cBlock->getRank();
+	if(fBlockRank == cBlockRank && fBlockRank == gridRank)
+	{
+		senderCF = receiverFC = CreateTransmittersHelper::TransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+		senderFC = receiverCF = CreateTransmittersHelper::TransmitterPtr( new TbLocalTransmitter< CbVector< LBMReal > >());
+	}
+	else if(cBlockRank == gridRank)
+	{
+		helper.createTransmitters(cBlock, fBlock, dir, ib, senderCF, receiverCF, comm, CreateTransmittersHelper::MPI);
+	}
+	else if(fBlockRank == gridRank)
+	{
+		helper.createTransmitters(fBlock, cBlock, dir, ib, senderFC, receiverFC, comm, CreateTransmittersHelper::MPI);
+	}
+   UBLOG(logDEBUG5, "D3Q27SetConnectorsBlockVisitor::createTransmitters(...) - end");
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/D3Q27SetConnectorsBlockVisitor.h b/source/VirtualFluidsCore/Visitors/D3Q27SetConnectorsBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa9ccccff80d5e4c686c39fac0c6742a89d5b4dd
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/D3Q27SetConnectorsBlockVisitor.h
@@ -0,0 +1,36 @@
+#ifndef D3Q27SETCONNECTORSBLOCKVISITOR_H
+#define D3Q27SETCONNECTORSBLOCKVISITOR_H
+
+#include "Block3DVisitor.h"
+#include "D3Q27System.h"
+#include "Communicator.h"
+#include "D3Q27InterpolationProcessor.h"
+#include "CreateTransmittersHelper.h"
+
+class D3Q27SetConnectorsBlockVisitor : public Block3DVisitor
+{
+public:
+	D3Q27SetConnectorsBlockVisitor(CommunicatorPtr comm, bool fullConnector, int dirs, LBMReal nue, D3Q27InterpolationProcessorPtr iProcessor);
+	virtual ~D3Q27SetConnectorsBlockVisitor();
+	void visit(Grid3DPtr grid, Block3DPtr block);
+	//////////////////////////////////////////////////////////////////////////
+protected:
+	void setSameLevelConnectors(Grid3DPtr grid, Block3DPtr block);
+	void setRemoteConnectors(Block3DPtr sblock, Block3DPtr tblock, int dir, bool fullConnector);
+	void setInterpolationConnectors(Grid3DPtr grid, Block3DPtr block);
+	void setInterpolationConnectors(Block3DPtr fBlockSW, Block3DPtr fBlockSE, Block3DPtr fBlockNW, Block3DPtr fBlockNE, Block3DPtr cBlock, int dir);
+	void createTransmitters(Block3DPtr cBlock, Block3DPtr fBlock, int dir,
+      CreateTransmittersHelper::IBlock ib,
+		CreateTransmittersHelper::TransmitterPtr& senderCF, 
+		CreateTransmittersHelper::TransmitterPtr& receiverCF, 
+		CreateTransmittersHelper::TransmitterPtr& senderFC, 
+		CreateTransmittersHelper::TransmitterPtr& receiverFC);
+	CommunicatorPtr comm;
+	bool fullConnector;
+	int dirs;
+	int gridRank;
+	LBMReal nue;
+	D3Q27InterpolationProcessorPtr iProcessor;
+};
+
+#endif //D3Q27SETCONNECTORSVISITOR_H
diff --git a/source/VirtualFluidsCore/Visitors/D3Q27SetUndefinedNodesBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/D3Q27SetUndefinedNodesBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9caf47d6aa64e41da49e2fc499176458230b2b33
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/D3Q27SetUndefinedNodesBlockVisitor.cpp
@@ -0,0 +1,665 @@
+#include "D3Q27SetUndefinedNodesBlockVisitor.h"
+#include "BCArray3D.h"
+#include "D3Q27BoundaryCondition.h"
+#include "D3Q27ETBCProcessor.h"
+#include "Grid3DSystem.h"
+#include "D3Q27System.h"
+
+#include <boost/pointer_cast.hpp>
+
+D3Q27SetUndefinedNodesBlockVisitor::D3Q27SetUndefinedNodesBlockVisitor() : 
+                                    Block3DVisitor(0, Grid3DSystem::MAXLEVEL) 
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27SetUndefinedNodesBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if(!block->hasInterpolationFlag()) return;
+
+   LBMKernel3DPtr kernel = block->getKernel();
+
+   if(!kernel && (block->getRank() != grid->getRank())) return;
+
+   //width of ghost layer 
+   //int gl = kernel->getGhostLayerWidth();
+   int gl = 0;
+   
+   BCArray3D<D3Q27BoundaryCondition>& bcMatrix = boost::dynamic_pointer_cast<D3Q27ETBCProcessor>(kernel->getBCProcessor())->getBCArray();
+
+   int minX1 = gl;
+   int minX2 = gl;
+   int minX3 = gl;
+
+   int maxX1 = static_cast<int>(bcMatrix.getNX1())-1-gl;
+   int maxX2 = static_cast<int>(bcMatrix.getNX2())-1-gl;
+   int maxX3 = static_cast<int>(bcMatrix.getNX3())-1-gl;
+
+   //int offset = 2;
+   int offset = 3;
+
+   if(block->hasInterpolationFlag(D3Q27System::E))
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::W))
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::N))
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::S))
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::T))
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::B))
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::NE))
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::SW))
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::SE))
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::NW))  
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::TE))  
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::BW))  
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::BE)) 
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::TW))  
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::TN)) 
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::BS))  
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::BN))  
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::TS))  
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::TNE)) 
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::TNW)) 
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::TSE)) 
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::TSW)) 
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = maxX3;
+      int endix3   = maxX3;
+      if(block->hasInterpolationFlagCF()) startix3 = startix3-offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::BNE)) 
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::BNW))
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = maxX2;
+      int endix2   = maxX2;
+      if(block->hasInterpolationFlagCF()) startix2 = startix2-offset;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::BSE)) 
+   {
+      int startix1 = maxX1;
+      int endix1   = maxX1;
+      if(block->hasInterpolationFlagCF()) startix1 = startix1-offset;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlag(D3Q27System::BSW)) 
+   {
+      int startix1 = minX1;
+      int endix1   = minX1;
+      if(block->hasInterpolationFlagCF()) endix1 = endix1+offset;
+      int startix2 = minX2;
+      int endix2   = minX2;
+      if(block->hasInterpolationFlagCF()) endix2 = endix2+offset;
+      int startix3 = minX3;
+      int endix3   = minX3;
+      if(block->hasInterpolationFlagCF()) endix3 = endix3+offset;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+
+
+
+	//////////////////////////////////////////////////////////////////////////
+   int offset2 = 1;
+   int ll = 0;
+
+   minX1 = ll;
+   minX2 = ll;
+   minX3 = ll;
+
+   maxX1 = static_cast<int>(bcMatrix.getNX1())-1-ll;
+   maxX2 = static_cast<int>(bcMatrix.getNX2())-1-ll;
+   maxX3 = static_cast<int>(bcMatrix.getNX3())-1-ll;
+
+   if(block->hasInterpolationFlagFC(D3Q27System::E))
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::W))
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::N))
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::S))
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::T))
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::B))
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::NE))
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::SW))
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::SE))
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::NW))  
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = minX3; 
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::TE))  
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::BW))  
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::BE)) 
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::TW))  
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = minX2;
+      int endix2   = maxX2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::TN)) 
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::BS))  
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::BN))  
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::TS))  
+   {
+      int startix1 = minX1;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::TNE)) 
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::TNW)) 
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::TSE)) 
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::TSW)) 
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = maxX3-offset2;
+      int endix3   = maxX3;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::BNE)) 
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::BNW))
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = maxX2-offset2;
+      int endix2   = maxX2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::BSE)) 
+   {
+      int startix1 = maxX1-offset2;
+      int endix1   = maxX1;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   if(block->hasInterpolationFlagFC(D3Q27System::BSW)) 
+   {
+      int startix1 = minX1;
+      int endix1   = minX1+offset2;
+      int startix2 = minX2;
+      int endix2   = minX2+offset2;
+      int startix3 = minX3;
+      int endix3   = minX3+offset2;
+      this->setNodesUndefined(startix1, endix1, startix2, endix2, startix3, endix3, bcMatrix);
+   }
+   
+   //invert scaleCF blocks
+   if(block->hasInterpolationFlagCF())
+   {
+      if(block->hasInterpolationFlagFC()) 
+         throw UbException(UB_EXARGS, "block "+block->toString()+" has CF and FC");
+
+      minX1 = gl;
+      minX2 = gl;
+      minX3 = gl;
+
+      maxX1 = static_cast<int>(bcMatrix.getNX1())-1-gl;
+      maxX2 = static_cast<int>(bcMatrix.getNX2())-1-gl;
+      maxX3 = static_cast<int>(bcMatrix.getNX3())-1-gl;
+
+      for (int ix3=minX3; ix3<=maxX3; ix3++)
+         for (int ix2=minX2; ix2<=maxX2; ix2++)
+            for (int ix1=minX1; ix1<=maxX1; ix1++)
+            {
+               if(bcMatrix.isUndefined(ix1, ix2, ix3)) bcMatrix.setFluid(ix1, ix2, ix3);
+               else                                    bcMatrix.setUndefined(ix1, ix2, ix3);
+            }
+            return;
+   }
+
+}
+//////////////////////////////////////////////////////////////////////////
+void D3Q27SetUndefinedNodesBlockVisitor::setNodesUndefined( int startix1, int endix1, int startix2, int endix2, int startix3, int endix3, BCArray3D<D3Q27BoundaryCondition>& bcMatrix )
+{
+   for (int ix3=startix3; ix3<=endix3; ix3++)
+      for (int ix2=startix2; ix2<=endix2; ix2++)
+         for (int ix1=startix1; ix1<=endix1; ix1++)
+         {
+            bcMatrix.setUndefined(ix1, ix2, ix3);
+         }
+}
diff --git a/source/VirtualFluidsCore/Visitors/D3Q27SetUndefinedNodesBlockVisitor.h b/source/VirtualFluidsCore/Visitors/D3Q27SetUndefinedNodesBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..5a878454ffca03a2568f84e342370dc1772d1e42
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/D3Q27SetUndefinedNodesBlockVisitor.h
@@ -0,0 +1,22 @@
+#ifndef D3Q27SetUndefinedNodesBlockVisitor_h
+#define D3Q27SetUndefinedNodesBlockVisitor_h
+
+#include "Block3DVisitor.h"
+#include "LBMKernel3D.h"
+#include "BCArray3D.h"
+#include "D3Q27BoundaryCondition.h"
+#include "D3Q27ETBCProcessor.h"
+
+class D3Q27SetUndefinedNodesBlockVisitor : public Block3DVisitor
+{
+public:
+   D3Q27SetUndefinedNodesBlockVisitor();
+
+   virtual ~D3Q27SetUndefinedNodesBlockVisitor() {}
+
+   void visit(Grid3DPtr grid, Block3DPtr block);
+
+private:
+   void setNodesUndefined( int startix1, int endix1, int startix2, int endix2, int startix3, int endix3, BCArray3D<D3Q27BoundaryCondition>& bcMatix );
+};
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.cpp b/source/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..59b6fc67fdf27f383c4fa97927b75a87ee266dfc
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.cpp
@@ -0,0 +1,109 @@
+#include "GenBlocksGridVisitor.h"
+#include "Grid3DSystem.h"
+#include <boost/foreach.hpp>
+
+GenBlocksGridVisitor::GenBlocksGridVisitor(GbObject3DPtr boundingBox) :
+   boundingBox(boundingBox),
+   nx1(0),
+   nx2(0),
+   nx3(0),
+   withDeltaX(true)
+{
+
+}
+GenBlocksGridVisitor::GenBlocksGridVisitor(int nx1, int nx2, int nx3) :
+   nx1(nx1),
+   nx2(nx2),
+   nx3(nx3),
+   withDeltaX(false)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void GenBlocksGridVisitor::visit( const Grid3DPtr grid )
+{
+   findOrigin(grid);
+   UbTupleInt3 blockNX = grid->getBlockNX();
+   double blockLentghX1, blockLentghX2, blockLentghX3; 
+   double dx;
+   double geoMaxX1 = boundingBox->getX1Maximum();
+   double geoMaxX2 = boundingBox->getX2Maximum();
+   double geoMaxX3 = boundingBox->getX3Maximum();
+
+   if (withDeltaX)
+   {
+      dx = grid->getDeltaX(0);
+      blockLentghX1 = (double)val<1>(blockNX)*dx;
+      blockLentghX2 = (double)val<2>(blockNX)*dx;
+      blockLentghX3 = (double)val<3>(blockNX)*dx;
+   } 
+   else
+   {
+      int gNX1 = grid->getNX1();
+      dx = boundingBox->getLengthX1()/double(val<1>(blockNX)*gNX1);
+      grid->setDeltaX(dx);
+      blockLentghX1 = val<1>(blockNX)*dx;
+      blockLentghX2 = val<2>(blockNX)*dx;
+      blockLentghX3 = val<3>(blockNX)*dx;
+   }
+
+   CoordinateTransformation3DPtr trafo(new CoordinateTransformation3D(orgX1,orgX2,orgX3,blockLentghX1,blockLentghX2,blockLentghX3));
+   grid->setCoordinateTransformator(trafo);
+   genBlocks(grid);
+
+
+}
+//////////////////////////////////////////////////////////////////////////
+void GenBlocksGridVisitor::fillExtentWithBlocks( Grid3DPtr grid )
+{
+   for(int x3 =  val<3>(minInd); x3 <  val<3>(maxInd); x3++)
+   {
+      for(int x2 =  val<2>(minInd); x2 <  val<2>(maxInd); x2++)
+      {
+         for(int x1 =  val<1>(minInd); x1 <  val<1>(maxInd); x1++)
+         {
+            Block3DPtr block( new Block3D(x1,x2,x3,0) );
+            grid->addBlock(block);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void GenBlocksGridVisitor::genBlocks(Grid3DPtr grid)
+{
+   minInd = grid->getBlockIndexes(boundingBox->getX1Minimum(), boundingBox->getX2Minimum(), boundingBox->getX3Minimum());
+   double geoMaxX1 = boundingBox->getX1Maximum();
+   double geoMaxX2 = boundingBox->getX2Maximum();
+   double geoMaxX3 = boundingBox->getX3Maximum();
+   maxInd = grid->getBlockIndexes(geoMaxX1, geoMaxX2, geoMaxX3);
+   UbTupleDouble3 blockCoord = grid->getBlockWorldCoordinates(static_cast<int>(val<1>(maxInd)), static_cast<int>(val<2>(maxInd)), static_cast<int>(val<3>(maxInd)), 0);
+   if(geoMaxX1 >  val<1>(blockCoord))
+      val<1>(maxInd) += 1;
+   if(geoMaxX2 >  val<2>(blockCoord))
+      val<2>(maxInd) += 1;
+   if(geoMaxX3 >  val<3>(blockCoord))
+      val<3>(maxInd) += 1;
+
+   this->fillExtentWithBlocks(grid);
+
+   grid->setNX1(val<1>(maxInd));
+   grid->setNX2(val<2>(maxInd));
+   grid->setNX3(val<3>(maxInd));
+}
+//////////////////////////////////////////////////////////////////////////
+void GenBlocksGridVisitor::findOrigin( Grid3DPtr grid )
+{
+   orgX1 = boundingBox->getX1Minimum();
+   orgX2 = boundingBox->getX2Minimum();
+   orgX3 = boundingBox->getX3Minimum();
+
+   //double minX1, minX2, minX3;
+
+   //minX1 = boundingBox->getX1Minimum();
+   //minX2 = boundingBox->getX2Minimum();
+   //minX3 = boundingBox->getX3Minimum();
+
+   //if(minX1 <= orgX1) orgX1 = minX1;
+   //if(minX2 <= orgX2) orgX2 = minX2;
+   //if(minX3 <= orgX3) orgX3 = minX3;
+}
diff --git a/source/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.h b/source/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..9fcf298bf1898bbe543f8628a3d2d957421a9eb4
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/GenBlocksGridVisitor.h
@@ -0,0 +1,27 @@
+#ifndef GenBlocksGridVisitor_h
+#define GenBlocksGridVisitor_h
+
+#include "Grid3DVisitor.h" 
+#include <numerics/geometry3d/GbObject3D.h>
+
+class GenBlocksGridVisitor : public Grid3DVisitor
+{
+public:
+   GenBlocksGridVisitor(GbObject3DPtr boundingBox);
+   GenBlocksGridVisitor(int nx1, int nx2, int nx3);
+   virtual ~GenBlocksGridVisitor(){}
+
+   void visit(Grid3DPtr grid);
+
+private:
+   double orgX1, orgX2, orgX3;
+   UbTupleInt3 minInd, maxInd;
+   int nx1, nx2, nx3;
+   bool withDeltaX;
+   GbObject3DPtr boundingBox;
+   void fillExtentWithBlocks(Grid3DPtr grid);
+   void findOrigin(Grid3DPtr grid);
+   void genBlocks(Grid3DPtr grid);
+};
+
+#endif 
diff --git a/source/VirtualFluidsCore/Visitors/Grid3DVisitor.h b/source/VirtualFluidsCore/Visitors/Grid3DVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..7e576074f4d534e4109a3999f65e13598b59af31
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/Grid3DVisitor.h
@@ -0,0 +1,19 @@
+#ifndef Grid3DVisitor_h
+#define Grid3DVisitor_h
+
+#include <boost/shared_ptr.hpp>
+class Grid3DVisitor;
+typedef boost::shared_ptr<Grid3DVisitor> Grid3DVisitorPtr;
+
+#include "Grid3D.h" 
+
+class Grid3DVisitor
+{
+public:
+   Grid3DVisitor() {}
+   virtual ~Grid3DVisitor() {}
+
+   virtual void visit(Grid3DPtr grid)=0;
+};
+
+#endif 
diff --git a/source/VirtualFluidsCore/Visitors/MetisPartitioningGridVisitor.cpp b/source/VirtualFluidsCore/Visitors/MetisPartitioningGridVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2485bf1de29d897dedf772315a4b3aa1441528b6
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/MetisPartitioningGridVisitor.cpp
@@ -0,0 +1,297 @@
+#if defined VF_METIS && defined VF_MPI
+
+#include "MetisPartitioningGridVisitor.h"
+#include <math.h>
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+MetisPartitioningGridVisitor::MetisPartitioningGridVisitor(CommunicatorPtr comm, GraphType graphType, int numOfDirs, MetisPartitioner::PartType partType, bool threads, int numberOfThreads)
+    :  Grid3DVisitor(),
+       numberOfThreads(numberOfThreads),
+       numOfDirs(numOfDirs),
+       comm(comm),
+       threads(threads),
+       graphType(graphType),
+       partType(partType)
+{  
+
+}
+//////////////////////////////////////////////////////////////////////////
+MetisPartitioningGridVisitor::~MetisPartitioningGridVisitor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void MetisPartitioningGridVisitor::visit(Grid3DPtr grid)
+{
+    UBLOG(logDEBUG1, "MetisPartitioningGridVisitor::visit() - start");
+
+    this->clear();
+
+    bundleRoot = comm->getBundleRoot();
+    bundleID = comm->getBundleID();
+    numberOfBundles = comm->getNumberOfBundles();
+    if (numberOfBundles > 1)
+    {
+        if (bundleRoot == bundleID && processRoot == processID)
+            collectData(grid, numberOfBundles, BUNDLE);
+        comm->broadcast(blockID);
+        comm->broadcast(parts);
+        distributePartitionData(grid, BUNDLE);
+        this->clear();
+    }
+
+    processRoot = comm->getProcessRoot();
+    processID = comm->getProcessID();
+    int numberOfProcesses = comm->getNumberOfProcesses();
+    if (numberOfProcesses > 1)
+    {
+       int temp = bundleID;
+       for (int i = 0; i < numberOfBundles; i++)
+       {
+          if (bundleRoot == bundleID && processRoot == processID)
+          {
+             bundleID = i;
+             numberOfProcesses = comm->getNumberOfProcessesInBundle(i);
+             collectData(grid, numberOfProcesses, PROCESS);
+             bundleID = temp;
+          }
+          comm->broadcast(blockID);
+          //UBLOG(logINFO, "blockID="<<blockID.size());
+          comm->broadcast(parts);
+          //UBLOG(logINFO, "parts="<<parts.size());
+          distributePartitionData(grid, PROCESS);
+       }
+    }
+
+    if (threads)
+    {
+        if (numberOfThreads > 1)
+        {
+            collectData(grid, numberOfThreads, THREAD);
+            distributePartitionData(grid, THREAD);
+        }
+    }
+    UBLOG(logDEBUG1, "MetisPartitioningGridVisitor::visit() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void MetisPartitioningGridVisitor::collectData(Grid3DPtr grid, int nofSegments, PartLevel level)
+{
+    clear();
+
+    switch (graphType)
+    {
+    case LevelIntersected: 
+      buildMetisGraphLevelIntersected(grid, nofSegments, level);
+    	break;
+    case LevelBased: 
+      buildMetisGraphLevelBased(grid, nofSegments, level);
+      break;
+    }
+}
+//////////////////////////////////////////////////////////////////////////
+void MetisPartitioningGridVisitor::distributePartitionData(Grid3DPtr grid, PartLevel level)
+{
+    Block3DPtr block;
+
+    for(size_t p=0; p<parts.size(); p++)
+    {
+        block = grid->getBlock(blockID[p]);
+        if (block)
+        {
+            switch (level)
+            {
+            case BUNDLE:
+                block->setBundle(parts[p]);
+                break;
+            case PROCESS:
+                if (numberOfBundles == 1)
+                {
+                   block->setRank(parts[p]);
+                } 
+                else
+                {
+                   block->setLocalRank(parts[p]);
+                   block->setRank(comm->getProcessID(block->getBundle(),parts[p]));
+                }
+                break;
+            case THREAD:
+                block->setPart(parts[p]);
+                break;
+            }
+        }
+    }
+}
+//////////////////////////////////////////////////////////////////////////
+void MetisPartitioningGridVisitor::buildMetisGraphLevelIntersected(Grid3DPtr grid, int nofSegments, PartLevel level)
+{
+    int edges = 0;
+    const int edgeWeight= 1;
+    const int edgeWeightChildFactor = 8;
+    int n = 0;
+
+    BOOST_FOREACH(Grid3D::BlockIDMap::value_type b,  grid->getBlockIDs())
+    { 
+        Block3DPtr block = b.second;
+        if (this->getPartitionCondition(block, level))
+        {
+            block->setLocalID(n);
+            blockID.push_back(block->getGlobalID());
+            n++;
+        }
+    }
+
+    MetisPartitioner metis;
+
+    BOOST_FOREACH(Grid3D::BlockIDMap::value_type b,  grid->getBlockIDs())
+    { 
+        const Block3DPtr block = b.second;
+        if (this->getPartitionCondition(block, level))
+        {
+           metis.xadj.push_back(edges);
+            //the weights of the vertices are 2^level of grid (1, 2, 4, 8 .....) 1<<level 
+            metis.vwgt.push_back((idx_t)(1<<block->getLevel())); 
+
+            for( int dir = 0; dir <= numOfDirs; dir++)
+            {
+                Block3DPtr neighBlock = grid->getNeighborBlock(dir, block);
+                if(neighBlock)
+                {
+                    if (this->getPartitionCondition(neighBlock, level))
+                    {
+                        edges++;
+                        metis.adjwgt.push_back(edgeWeight);
+                        metis.adjncy.push_back(neighBlock->getLocalID());
+                    }
+                }
+            }
+            vector<Block3DPtr> subBlocks;
+            grid->getSubBlocks(block, 1, subBlocks);
+            BOOST_FOREACH(Block3DPtr subBlock, subBlocks)
+            {
+                if (subBlock)
+                {
+                    if (this->getPartitionCondition(subBlock, level))
+                    {
+                        edges++;
+                        metis.adjwgt.push_back(edgeWeight*edgeWeightChildFactor);
+                        metis.adjncy.push_back(subBlock->getLocalID());
+                    }
+                }
+            }
+        }
+    }
+
+    metis.xadj.push_back(static_cast<idx_t>(metis.adjncy.size()));
+    if ((metis.adjncy.size()%2)!=0)
+        throw UbException(UB_EXARGS,"number of edges is odd - probable adjncy-vector doesn't contain all pairs (A->B) and (B->A)!!!" );
+
+    
+    metis.partition(nofSegments, partType);
+    parts = metis.part;
+}
+//////////////////////////////////////////////////////////////////////////
+void MetisPartitioningGridVisitor::buildMetisGraphLevelBased(Grid3DPtr grid, int nofSegments, PartLevel level)
+{
+    int minInitLevel = grid->getCoarsestInitializedLevel();
+    int maxInitLevel = grid->getFinestInitializedLevel();
+
+    for(int l = minInitLevel; l<=maxInitLevel;l++)
+    {
+        int n = 0;
+        vector<Block3DPtr> blockVector;
+        grid->getBlocks(l, blockVector);
+        vector<Block3DPtr> tBlockID;
+
+        BOOST_FOREACH(Block3DPtr block, blockVector)
+        { 
+            if (this->getPartitionCondition(block, level))
+            {
+                block->setLocalID(n);
+                blockID.push_back(block->getGlobalID());
+                tBlockID.push_back(block);
+                n++;
+            }
+        }
+
+        if (tBlockID.size() == 0)
+        {
+           UB_THROW(UbException(UB_EXARGS,"Blocks for decomposition don't exist!"));
+        }
+
+        MetisPartitioner metis;
+
+        const int vertexWeight = 1;
+        int edges = 0;
+        const int edgeWeight= 1;
+
+        BOOST_FOREACH(Block3DPtr block, tBlockID)
+        {
+            metis.xadj.push_back(edges);
+            metis.vwgt.push_back(vertexWeight);
+
+            for( int dir = 0; dir <= numOfDirs; dir++)
+            {
+                Block3DPtr neighBlock = grid->getNeighborBlock(dir, block);
+                if(neighBlock)
+                {
+                    if (this->getPartitionCondition(neighBlock, level))
+                    {
+                        edges++;
+                        metis.adjwgt.push_back(edgeWeight);
+                        metis.adjncy.push_back(neighBlock->getLocalID());
+                    }
+                }
+            }
+        }
+        metis.xadj.push_back(static_cast<idx_t>(metis.adjncy.size()));
+        if ((metis.adjncy.size()%2)!=0)
+            throw UbException(UB_EXARGS,"number of edges is odd - probable adjncy-vector doesn't contain all pairs (A->B) and (B->A)!!!" );
+
+        int nofBlocks = grid->getNumberOfBlocks(l);
+        int tnofSegments = nofSegments;
+        if (nofBlocks < nofSegments)
+        {
+           tnofSegments = nofBlocks;
+        }
+        metis.partition(tnofSegments, partType);
+
+        BOOST_FOREACH(idx_t p, metis.part)
+        {
+            parts.push_back(p);
+        }
+    }
+}
+//////////////////////////////////////////////////////////////////////////
+bool MetisPartitioningGridVisitor::getPartitionCondition(Block3DPtr block, PartLevel level)
+{
+    if (level == BUNDLE)
+    {
+       return true;
+    }
+    else if(level == PROCESS)
+    {
+       if (block->getBundle() == bundleID)
+       {
+          return true;
+       }
+    }
+    else if(level == THREAD)
+    {
+      if (block->getBundle() == bundleID && block->getRank() == processID)
+      {
+         return true;
+      }
+    }
+
+    return false;
+}
+//////////////////////////////////////////////////////////////////////////
+void MetisPartitioningGridVisitor::clear()
+{
+    blockID.clear();
+    parts.clear();
+}
+//////////////////////////////////////////////////////////////////////////
+#endif  //VF_METIS
diff --git a/source/VirtualFluidsCore/Visitors/MetisPartitioningGridVisitor.h b/source/VirtualFluidsCore/Visitors/MetisPartitioningGridVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..34bfbe82f46cde9e663a83488d1f70b3df240a9f
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/MetisPartitioningGridVisitor.h
@@ -0,0 +1,62 @@
+#ifndef MetisPartitioningGridVisitor_h 
+#define MetisPartitioningGridVisitor_h
+
+#if defined VF_METIS && defined VF_MPI
+
+#include <vector>
+
+#include "MetisPartitioner.h"
+#include "Grid3DVisitor.h"
+#include "LBMSystem.h"
+#include "Block3D.h"
+#include "Communicator.h"
+
+#include <boost/shared_ptr.hpp>
+class MetisPartitioningGridVisitor;
+typedef boost::shared_ptr<MetisPartitioningGridVisitor> PartitionMetisGridVisitorPtr;
+
+////////////////////////////////////////////////////////////////////////
+//! \brief The class implements domain decomposition with METIS library
+//! \author Kostyantyn Kucher
+//////////////////////////////////////////////////////////////////////////
+class MetisPartitioningGridVisitor : public Grid3DVisitor
+{                                             
+public:
+   //! This describe different types of decomposition   
+   enum GraphType{LevelIntersected, LevelBased};
+public:
+   //! Constructor
+   //! \param comm - communicator
+   //! \param graphType - type of decomposition
+   //! \param numOfDirs - maximum number of neighbors for each process
+   //! \param threads - on/off decomposition for threads
+   //! \param numberOfThreads - number of threads
+   MetisPartitioningGridVisitor(CommunicatorPtr comm, GraphType graphType, int numOfDirs, MetisPartitioner::PartType partType = MetisPartitioner::KWAY, bool threads = false, int numberOfThreads = 0);
+   virtual ~MetisPartitioningGridVisitor();
+   void visit(Grid3DPtr grid);
+protected:
+   enum PartLevel {BUNDLE, PROCESS, THREAD};
+   void collectData(Grid3DPtr grid, int nofSegments, PartLevel level);
+   void buildMetisGraphLevelIntersected(Grid3DPtr grid, int nofSegments, PartLevel level);
+   void buildMetisGraphLevelBased(Grid3DPtr grid, int nofSegments, PartLevel level);
+   bool getPartitionCondition(Block3DPtr block, PartLevel level);
+   void distributePartitionData(Grid3DPtr grid, PartLevel level);
+   void clear();
+   int  nofSegments;
+   int numOfDirs;
+   std::vector<int> blockID;
+   std::vector<idx_t> parts;
+   CommunicatorPtr comm;
+   int bundleRoot;
+   int processRoot;
+   int bundleID;
+   int processID;
+   int numberOfBundles;
+   int numberOfThreads;
+   bool threads;
+   GraphType graphType;
+   MetisPartitioner::PartType partType;
+};
+
+#endif  //VF_MPI
+#endif 
diff --git a/source/VirtualFluidsCore/Visitors/OverlapBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/OverlapBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b11a42bdb05ae448e4a0e3b93bd37cd0ae9bd90e
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/OverlapBlockVisitor.cpp
@@ -0,0 +1,58 @@
+#include "OverlapBlockVisitor.h"
+#include "Grid3DSystem.h"
+
+OverlapBlockVisitor::OverlapBlockVisitor(int levelDepth/*shut be maxGridLevel*/, bool includeNotActiveBlocks)
+   :   Block3DVisitor(0, Grid3DSystem::MAXLEVEL)
+   , levelDepth(levelDepth)
+   , includeNotActiveBlocks(includeNotActiveBlocks)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void OverlapBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   int ix1, ix2, ix3, level;
+   ix1 = block->getX1();
+   ix2 = block->getX2();
+   ix3 = block->getX3();
+   level = block->getLevel();
+
+   int nix1, nix2,nix3, nlev;
+   int neighix1, neighix2, neighix3, neighlev;
+   std::vector<Block3DPtr> neighbors;
+   grid->getAllNeighbors(ix1, ix2, ix3, level, this->levelDepth, neighbors);
+   bool hasAdded = false;
+   for(size_t i=0; i<neighbors.size(); i++)
+   {
+      if(   ( neighbors[i]->isActive() || includeNotActiveBlocks )
+         && neighbors[i]->getLevel() > level) 
+      {
+         neighix1 = neighbors[i]->getX1();
+         neighix2 = neighbors[i]->getX2();
+         neighix3 = neighbors[i]->getX3();
+         neighlev = neighbors[i]->getLevel();
+         nix1 = neighix1>>1;
+         nix2 = neighix2>>1;
+         nix3 = neighix3>>1;
+         nlev = neighlev-1;
+
+         if(nlev != level) 
+         {
+            throw UbException(UB_EXARGS, "OverlapBlockVisitor::adaptBlock - leveldifferenz passt nicht, block: " + block->toString());
+         }
+         Block3DPtr newBlock = grid->getBlock(nix1,nix2,nix3,nlev);
+         if(!newBlock)
+         {
+            newBlock = Block3DPtr(new Block3D(nix1,nix2,nix3,nlev));
+            grid->addBlock(newBlock);
+            hasAdded=true;
+         }
+      }
+   }
+}
+
+//////////////////////////////////////////////////////////////////////////
+std::string OverlapBlockVisitor::getSpecificDescription()
+{
+   std::string str("Overlap:");
+   return str;
+}
diff --git a/source/VirtualFluidsCore/Visitors/OverlapBlockVisitor.h b/source/VirtualFluidsCore/Visitors/OverlapBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..e3411acc02f4758e792f0bd7d169096449724de2
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/OverlapBlockVisitor.h
@@ -0,0 +1,26 @@
+#ifndef OverlapBlockVisitor_H
+#define OverlapBlockVisitor_H
+
+#include "Block3DVisitor.h"
+
+class OverlapBlockVisitor : public Block3DVisitor
+{
+public:
+   OverlapBlockVisitor(int levelDepth, bool includeNotActiveBlocks = true);
+   
+   virtual ~OverlapBlockVisitor(){}
+
+   bool isIterative()   { return false; }
+
+   std::string getSpecificDescription();
+
+   void visit(Grid3DPtr grid, Block3DPtr block);
+
+protected:
+
+private:
+   int  levelDepth;
+   bool includeNotActiveBlocks;
+};
+
+#endif //OverlapBlockVisitor_H
diff --git a/source/VirtualFluidsCore/Visitors/PQueuePartitioningGridVisitor.cpp b/source/VirtualFluidsCore/Visitors/PQueuePartitioningGridVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..16c54f2d07ea3f33c1e635310f2e49f6a0eeaee5
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/PQueuePartitioningGridVisitor.cpp
@@ -0,0 +1,51 @@
+#include "PQueuePartitioningGridVisitor.h"
+#include "PriorityQueueDecompositor.h"
+#include <vector>
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+PQueuePartitioningGridVisitor::PQueuePartitioningGridVisitor(int numOfParts) : numOfParts(numOfParts)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void PQueuePartitioningGridVisitor::visit(Grid3DPtr grid)
+{
+   UBLOG(logDEBUG5, "PQueuePartitioningGridVisitor::visit() - start");
+   vector<Block3DPtr> blocks;
+   vector<int> weights;
+   vector< vector <Block3DPtr> > parts;
+   int gridRank = grid->getRank();
+
+   int minInitLevel = grid->getCoarsestInitializedLevel();
+   int maxInitLevel = grid->getFinestInitializedLevel();
+
+   for(int level = minInitLevel; level<=maxInitLevel; level++)
+   {
+      vector<Block3DPtr> blockVector;
+      grid->getBlocks(level, gridRank, true, blockVector);
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         if (block)
+         {
+            blocks.push_back(block);
+            weights.push_back(block->getNumberOfLocalConnectors()*(1<<block->getLevel()));
+         }
+      }
+   }
+   PriorityQueueDecompositor <Block3DPtr> dec = PriorityQueueDecompositor <Block3DPtr> (blocks, weights, numOfParts);
+   dec.getDecomposition(parts);
+
+   int i = 0;
+   BOOST_FOREACH(vector<Block3DPtr> p, parts)
+   {
+      BOOST_FOREACH(Block3DPtr block, p)
+      {
+         block->setPart(i);
+      }
+      i++;
+      
+   }
+   UBLOG(logDEBUG5, "PQueuePartitioningGridVisitor::visit() - end");
+}
diff --git a/source/VirtualFluidsCore/Visitors/PQueuePartitioningGridVisitor.h b/source/VirtualFluidsCore/Visitors/PQueuePartitioningGridVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..efb0c6eedd74a68ff9bccd20cad1003dd4e4669f
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/PQueuePartitioningGridVisitor.h
@@ -0,0 +1,23 @@
+/**
+* @file PQueuePartitioningPatchVisitor.h
+* @brief Visitor class which apply Priority Queue for threads decomposition.
+* @author Kostyantyn Kucher
+* @date 06.06.2011
+*/
+#ifndef PQUEUEPARTITIONINGPATCHVISITOR_H 
+#define PQUEUEPARTITIONINGPATCHVISITOR_H
+
+#include "Grid3DVisitor.h"
+
+class PQueuePartitioningGridVisitor : public Grid3DVisitor
+{
+public:
+   PQueuePartitioningGridVisitor(int numOfParts);
+   void visit(Grid3DPtr grid);
+
+protected:
+private:
+   int numOfParts;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/RatioBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/RatioBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e88520d8b32dec2666a0a623cc3db201c65a21dd
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RatioBlockVisitor.cpp
@@ -0,0 +1,127 @@
+#include "RatioBlockVisitor.h"
+#include "Grid3DSystem.h"
+
+RatioBlockVisitor::RatioBlockVisitor(int levelDepth, bool includeNotActiveBlocks)
+   :   Block3DVisitor(0, Grid3DSystem::MAXLEVEL)
+   , maxLevelRatio(1)
+   , expandBlocks(true)
+   , levelDepth(levelDepth)
+   , includeNotActiveBlocks(includeNotActiveBlocks)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   int ix1, ix2, ix3, level;
+   ix1 = block->getX1();
+   ix2 = block->getX2();
+   ix3 = block->getX3();
+   level = block->getLevel();
+
+   if( block->isActive()  || includeNotActiveBlocks )
+   {
+      if(this->expandBlocks)
+      {
+         if(this->lookForExpand(grid,ix1, ix2, ix3, level))
+         {
+            grid->expandBlock(ix1, ix2, ix3, level);
+         }
+      }
+      else
+      {
+         if(this->lookForCollapse(grid,ix1, ix2, ix3, level))
+         {
+            grid->collapseBlock(ix1, ix2, ix3, level, levelDepth);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+bool RatioBlockVisitor::lookForExpand(Grid3DPtr grid, const int& ix1, const int& ix2, const int& ix3, const int& level)
+{
+   std::vector<Block3DPtr> neighbors;
+   grid->getAllNeighbors(ix1, ix2, ix3, level, this->levelDepth, neighbors);
+   for(size_t i=0; i<neighbors.size(); i++)
+   {
+      if(   ( neighbors[i]->isActive() || includeNotActiveBlocks )
+         && neighbors[i]->getLevel() > level+this->maxLevelRatio) 
+      {
+         return true;
+      }
+   }
+
+   return false;
+}
+//////////////////////////////////////////////////////////////////////////
+bool RatioBlockVisitor::lookForCollapse(Grid3DPtr grid, const int& ix1, const int& ix2, const int& ix3, const int& level)
+{
+   std::vector<Block3DPtr> neighbors;
+   grid->getAllNeighbors(ix1, ix2,ix3, level, this->levelDepth, neighbors);
+   for(size_t i=0; i<neighbors.size(); i++)
+   {     
+      if(    ( neighbors[i]->isActive() || includeNotActiveBlocks )
+         &&  neighbors[i]->getLevel() < level-this->maxLevelRatio) 
+      {
+         return true;
+      }
+   }
+
+   return false;
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioBlockVisitor::setExpandByAdaptation(bool expandBlocks)
+{
+   if(this->expandBlocks != expandBlocks)
+   {
+      this->expandBlocks = expandBlocks;
+
+      int l1 = Block3DVisitor::getStartLevel();
+      int l2 = Block3DVisitor::getStopLevel();
+
+      if(expandBlocks) { if(l1 < l2) { Block3DVisitor::setStartLevel(l2); Block3DVisitor::setStopLevel(l1); } }
+      else             { if(l2 < l1) { Block3DVisitor::setStartLevel(l2); Block3DVisitor::setStopLevel(l1); } }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioBlockVisitor::setLevelRatio(int ratio)
+{
+   if(ratio < 1) throw UbException(UB_EXARGS,"illegal ratio specified");
+   this->maxLevelRatio = ratio;
+}
+//////////////////////////////////////////////////////////////////////////
+std::string RatioBlockVisitor::getSpecificDescription()
+{
+   std::string str("Ratio:");
+   return str;
+}
+//////////////////////////////////////////////////////////////////////////
+int RatioBlockVisitor::getStartLevel()
+{
+   int l1 = Block3DVisitor::getStartLevel();
+   int l2 = Block3DVisitor::getStopLevel();
+
+   if(this->expandBlocks) { if(l2 < l1) return(l1); else return(l2); }
+   else                   { if(l2 < l1) return(l2); else return(l1); }
+}
+//////////////////////////////////////////////////////////////////////////
+int RatioBlockVisitor::getStopLevel()
+{
+   int l1 = Block3DVisitor::getStartLevel();
+   int l2 = Block3DVisitor::getStopLevel();
+
+   if(this->expandBlocks) { if(l2 < l1) return(l2); else return(l1); }
+   else                   { if(l2 < l1) return(l1); else return(l2); }
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioBlockVisitor::setStartLevel(int level)
+{
+   if(this->expandBlocks) { if(level >= Block3DVisitor::getStopLevel()) Block3DVisitor::setStartLevel(level); }
+   else                   { if(level <= Block3DVisitor::getStopLevel()) Block3DVisitor::setStartLevel(level); }
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioBlockVisitor::setStopLevel(int level)
+{
+   if(this->expandBlocks) { if(level <= Block3DVisitor::getStartLevel()) Block3DVisitor::setStopLevel(level); }
+   else                   { if(level >= Block3DVisitor::getStartLevel()) Block3DVisitor::setStopLevel(level); }
+}
diff --git a/source/VirtualFluidsCore/Visitors/RatioBlockVisitor.h b/source/VirtualFluidsCore/Visitors/RatioBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..e258808914e6adca011b18223fc020fe160a7e26
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RatioBlockVisitor.h
@@ -0,0 +1,43 @@
+#ifndef RatioBlockVisitor_H
+#define RatioBlockVisitor_H
+
+#include "Block3DVisitor.h"
+
+class RatioBlockVisitor : public Block3DVisitor
+{
+public:
+   RatioBlockVisitor(int levelDepth, bool includeNotActiveBlocks = false);
+
+   virtual ~RatioBlockVisitor() {}
+
+   bool expandsByAdaptation() { return this->expandBlocks; }
+
+   void setExpandByAdaptation(bool expandBlocks);
+
+   int  getLevelRatio() { return this->maxLevelRatio; }
+   bool isIterative()   { return true;                }
+
+   void setLevelRatio(int ratio);
+
+   int  getStartLevel();
+   int  getStopLevel();
+
+   void setStartLevel(int level);
+   void setStopLevel(int level);
+
+   std::string getSpecificDescription();
+
+   void visit(Grid3DPtr grid, Block3DPtr block);
+
+protected:
+   bool lookForExpand(Grid3DPtr grid, const int& ix1, const int& ix2, const int& ix3, const int& level);
+   bool lookForCollapse(Grid3DPtr grid, const int& ix1, const int& ix2, const int& ix3, const int& level);
+
+private:
+   int  maxLevelRatio;
+   bool expandBlocks;
+   int  levelDepth;
+   bool includeNotActiveBlocks;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/RatioSmoothBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/RatioSmoothBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..efa836b4ab903c9de4f45ebde6c71a2b5141235e
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RatioSmoothBlockVisitor.cpp
@@ -0,0 +1,143 @@
+#include "RatioSmoothBlockVisitor.h"
+#include "Grid3DSystem.h"
+
+RatioSmoothBlockVisitor::RatioSmoothBlockVisitor(int levelDepth, bool includeNotActiveBlocks)
+   :   Block3DVisitor(Grid3DSystem::MAXLEVEL, 0)
+   , maxLevelRatio(1)
+   , expandBlocks(true)
+   , levelDepth(levelDepth)
+   , includeNotActiveBlocks(includeNotActiveBlocks)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioSmoothBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   int ix1, ix2, ix3, level;
+   ix1 = block->getX1();
+   ix2 = block->getX2();
+   ix3 = block->getX3();
+   level = block->getLevel();
+
+   if( block->isActive()  || includeNotActiveBlocks )
+   {
+      if(this->expandBlocks)
+      {
+         if(this->lookForExpand(grid,ix1, ix2, ix3, level))
+         {
+            grid->expandBlock(ix1, ix2, ix3, level);
+         }
+      }
+      else
+      {
+         if(this->lookForCollapse(grid,ix1, ix2, ix3, level))
+         {
+            grid->collapseBlock(ix1, ix2, ix3, level, levelDepth);
+         }
+      }
+   }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool RatioSmoothBlockVisitor::lookForExpand(Grid3DPtr grid, const int& ix1, const int& ix2, const int& ix3, const int& level)
+{
+   std::vector<Block3DPtr> neighbors;
+   grid->getAllNeighbors(ix1, ix2, ix3, level, this->levelDepth, neighbors);
+   int nix1, nix2,nix3, nlev;
+   for(size_t i=0; i<neighbors.size(); i++)
+   {
+      if(   ( neighbors[i]->isActive() || includeNotActiveBlocks )
+         && neighbors[i]->getLevel() > level) 
+      {
+         nix1 = (neighbors)[i]->getX1();
+         nix2 = (neighbors)[i]->getX2();
+         nix3 = (neighbors)[i]->getX3();
+         nlev = (neighbors)[i]->getLevel();
+
+         std::vector<Block3DPtr> neighbors1;
+         grid->getAllNeighbors(nix1, nix2, nix3, nlev, nlev+1, neighbors1);
+         for(size_t j=0; j<neighbors1.size(); j++)
+         {
+            if(   ( neighbors1[j]->isActive() || includeNotActiveBlocks )
+               && neighbors1[j]->getLevel() > level+this->maxLevelRatio) 
+            {
+               return true;
+            }
+         }
+      }
+   }
+   return false;
+}
+//////////////////////////////////////////////////////////////////////////
+bool RatioSmoothBlockVisitor::lookForCollapse(Grid3DPtr grid, const int& ix1, const int& ix2, const int& ix3, const int& level)
+{
+   std::vector<Block3DPtr> neighbors;
+   grid->getAllNeighbors(ix1, ix2,ix3, level, this->levelDepth, neighbors);
+   for(size_t i=0; i<neighbors.size(); i++)
+   {     
+      if(    ( neighbors[i]->isActive() || includeNotActiveBlocks )
+         &&  neighbors[i]->getLevel() < level-this->maxLevelRatio) 
+      {
+         throw UbException(UB_EXARGS," not implemented till now");
+         return true;
+      }
+   }
+
+   return false;
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioSmoothBlockVisitor::setExpandByAdaptation(bool expandBlocks)
+{
+   if(this->expandBlocks != expandBlocks)
+   {
+      this->expandBlocks = expandBlocks;
+
+      int l1 = Block3DVisitor::getStartLevel();
+      int l2 = Block3DVisitor::getStopLevel();
+
+      if(expandBlocks) { if(l1 < l2) { Block3DVisitor::setStartLevel(l2); Block3DVisitor::setStopLevel(l1); } }
+      else             { if(l2 < l1) { Block3DVisitor::setStartLevel(l2); Block3DVisitor::setStopLevel(l1); } }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioSmoothBlockVisitor::setLevelRatio(int ratio)
+{
+   if(ratio < 1) throw UbException(UB_EXARGS,"illegal ratio specified");
+   this->maxLevelRatio = ratio;
+}
+//////////////////////////////////////////////////////////////////////////
+std::string RatioSmoothBlockVisitor::getSpecificDescription()
+{
+   std::string str("Ratio:");
+   return str;
+}
+//////////////////////////////////////////////////////////////////////////
+int RatioSmoothBlockVisitor::getStartLevel()
+{
+   int l1 = Block3DVisitor::getStartLevel();
+   int l2 = Block3DVisitor::getStopLevel();
+
+   if(this->expandBlocks) { if(l2 < l1) return(l1); else return(l2); }
+   else                   { if(l2 < l1) return(l2); else return(l1); }
+}
+//////////////////////////////////////////////////////////////////////////
+int RatioSmoothBlockVisitor::getStopLevel()
+{
+   int l1 = Block3DVisitor::getStartLevel();
+   int l2 = Block3DVisitor::getStopLevel();
+
+   if(this->expandBlocks) { if(l2 < l1) return(l2); else return(l1); }
+   else                   { if(l2 < l1) return(l1); else return(l2); }
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioSmoothBlockVisitor::setStartLevel(int level)
+{
+   if(this->expandBlocks) { if(level >= Block3DVisitor::getStopLevel()) Block3DVisitor::setStartLevel(level); }
+   else                   { if(level <= Block3DVisitor::getStopLevel()) Block3DVisitor::setStartLevel(level); }
+}
+//////////////////////////////////////////////////////////////////////////
+void RatioSmoothBlockVisitor::setStopLevel(int level)
+{
+   if(this->expandBlocks) { if(level <= Block3DVisitor::getStartLevel()) Block3DVisitor::setStopLevel(level); }
+   else                   { if(level >= Block3DVisitor::getStartLevel()) Block3DVisitor::setStopLevel(level); }
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/RatioSmoothBlockVisitor.h b/source/VirtualFluidsCore/Visitors/RatioSmoothBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..247576414176481ec0a6dcfbffdb3d28ad11ac53
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RatioSmoothBlockVisitor.h
@@ -0,0 +1,44 @@
+#ifndef RatioSmoothBlockVisitor_H
+#define RatioSmoothBlockVisitor_H
+
+#include "Block3DVisitor.h"
+
+class RatioSmoothBlockVisitor : public Block3DVisitor
+{
+public:
+   RatioSmoothBlockVisitor(int levelDepth, bool includeNotActiveBlocks = false);
+
+   virtual ~RatioSmoothBlockVisitor() {}
+
+   bool expandsByAdaptation() { return this->expandBlocks; }
+
+   void setExpandByAdaptation(bool expandBlocks);
+
+   int  getLevelRatio() { return this->maxLevelRatio; }
+   bool isIterative()   { return true;                }
+
+   void setLevelRatio(int ratio);
+
+   int  getStartLevel();
+   int  getStopLevel();
+
+   void setStartLevel(int level);
+   void setStopLevel(int level);
+
+   std::string getSpecificDescription();
+
+   void visit(Grid3DPtr grid, Block3DPtr block);
+
+protected:
+   bool lookForExpand(Grid3DPtr grid, const int& ix1, const int& ix2, const int& ix3, const int& level);
+   bool lookForCollapse(Grid3DPtr grid, const int& ix1, const int& ix2, const int& ix3, const int& level);
+
+private:
+   int  maxLevelRatio;
+   bool expandBlocks;
+   int  levelDepth;
+   bool includeNotActiveBlocks;
+
+};
+
+#endif //RatioSmoothBlockVisitor_H
diff --git a/source/VirtualFluidsCore/Visitors/RefineAroundGbObjectHelper.cpp b/source/VirtualFluidsCore/Visitors/RefineAroundGbObjectHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..766acb3e5260a6ab86a973735fa0f11df1083a12
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RefineAroundGbObjectHelper.cpp
@@ -0,0 +1,53 @@
+#include "RefineAroundGbObjectHelper.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include <D3Q27System.h>
+
+
+RefineAroundGbObjectHelper::RefineAroundGbObjectHelper(Grid3DPtr grid, int refineLevel, D3Q27TriFaceMeshInteractorPtr objectIter, double startDistance, double stopDistance, CommunicatorPtr comm) :
+   grid(grid),
+   refineLevel(refineLevel),
+   objectIter(objectIter),
+   startDistance(startDistance), 
+   stopDistance(stopDistance),
+   comm(comm)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+RefineAroundGbObjectHelper::~RefineAroundGbObjectHelper(void)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void RefineAroundGbObjectHelper::refine()
+{
+   UBLOG(logDEBUG5,"RefineCrossAndInsideGbObjectHelper: refine - start");	
+
+   int rank = grid->getRank();
+   grid->setRank(0);
+
+   objectIter->refineBlockGridToLevel(refineLevel, startDistance, stopDistance);
+
+   RatioBlockVisitor ratioVisitor(refineLevel);
+   grid->accept(ratioVisitor);
+
+   RatioSmoothBlockVisitor ratioSmoothVisitor(refineLevel);
+   grid->accept(ratioSmoothVisitor);
+
+   OverlapBlockVisitor overlapVisitor(refineLevel);
+   grid->accept(overlapVisitor);
+
+   std::vector<int> dirs;
+   for (int i=D3Q27System::E; i<=D3Q27System::TS; i++)
+   {
+      dirs.push_back(i);
+   }
+   SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+   grid->accept(interDirsVisitor);
+
+   grid->setRank(rank);
+
+   UBLOG(logDEBUG5,"RefineCrossAndInsideGbObjectHelper: refine - end");	
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/RefineAroundGbObjectHelper.h b/source/VirtualFluidsCore/Visitors/RefineAroundGbObjectHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..0aff400e40d47134ad0df11cdce827f828ff9a10
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RefineAroundGbObjectHelper.h
@@ -0,0 +1,33 @@
+#ifndef RefineAroundGbObjectHelper_H
+#define RefineAroundGbObjectHelper_H
+
+#include <vector>
+
+#include <Grid3D.h>
+#include <D3Q27TriFaceMeshInteractor.h>
+
+//! \brief Refine blocks on base of bounding boxes.
+//! \details You need to use <i>addGbObject()</i> to add corresponding bounding boxes. Then call <i>refine()</i>.
+//! \author K. Kucher
+class RefineAroundGbObjectHelper
+{
+public:
+   //! Constructor
+   //! \param grid a smart pointer to the grid object
+   //! \param maxRefineLevel an integer for maximal refinement level
+   //! \param objectIter a D3Q27TriFaceMeshInteractor object - represent geometry which should be refinement
+   //! \param startDistance start distance from geometry for refinement
+   //! \param stopDistance stop distance from geometry for refinement
+   RefineAroundGbObjectHelper(Grid3DPtr grid, int maxRefineLevel, D3Q27TriFaceMeshInteractorPtr objectIter, double startDistance, double stopDistance, CommunicatorPtr comm);
+   virtual ~RefineAroundGbObjectHelper(void);
+   //! start refinement
+   void refine();
+private:
+   Grid3DPtr grid;
+   D3Q27TriFaceMeshInteractorPtr objectIter;
+   int refineLevel;
+   double startDistance, stopDistance;
+   CommunicatorPtr comm;
+};
+
+#endif 
diff --git a/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ffbeaea0d29260eff5a501247ddda002b9aed569
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectBlockVisitor.cpp
@@ -0,0 +1,38 @@
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+
+RefineCrossAndInsideGbObjectBlockVisitor::RefineCrossAndInsideGbObjectBlockVisitor()
+:  Block3DVisitor() , notActive(true)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+RefineCrossAndInsideGbObjectBlockVisitor::RefineCrossAndInsideGbObjectBlockVisitor(GbObject3DPtr geoObject, int refineLevel)
+   : Block3DVisitor(0,refineLevel-1), geoObject(geoObject), notActive(true)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+RefineCrossAndInsideGbObjectBlockVisitor::~RefineCrossAndInsideGbObjectBlockVisitor()
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void RefineCrossAndInsideGbObjectBlockVisitor::visit(const Grid3DPtr grid, Block3DPtr block)
+{
+   int level = block->getLevel();
+   if( notActive && block->isNotActive() ) return;
+   if( level > this->getStopLevel() ) return;
+
+   UbTupleDouble3 coords = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 deltas = grid->getBlockLengths(block);
+   if(geoObject->isCellInsideOrCuttingGbObject3D(  val<1>(coords) 
+      , val<2>(coords)
+      , val<3>(coords)
+      , val<1>(coords)+val<1>(deltas)
+      , val<2>(coords)+val<2>(deltas)
+      , val<3>(coords)+val<3>(deltas)) ) 
+   {
+      grid->expandBlock(block->getX1(),block->getX2(),block->getX3(),level); 
+   } 
+
+   return;
+}
+//////////////////////////////////////////////////////////////////////////
diff --git a/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectBlockVisitor.h b/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..765c8cbfb9d0d9987ca70a5e66fdb20f92c95487
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectBlockVisitor.h
@@ -0,0 +1,27 @@
+#ifndef RefineCrossAndInsideGbObjectBlockVisitor_H
+#define RefineCrossAndInsideGbObjectBlockVisitor_H
+
+#include "Block3DVisitor.h"
+#include <numerics/geometry3d/GbObject3D.h>
+
+//! \brief Refine blocks on base of bounding box which is defined with <i>geoObject</i>
+//! \details The class uses a geometry object for define a bounding box. Inside and across this bounding box will be grid on block basis refinement.
+//! \author K. Kucher
+class RefineCrossAndInsideGbObjectBlockVisitor : public Block3DVisitor
+{
+public:
+   //! A default constructor
+   RefineCrossAndInsideGbObjectBlockVisitor();
+   //! A constructor
+   //! \param geoObject a smart pointer to bounding box
+   //! \param refineLevel an integer for refine on this level
+   RefineCrossAndInsideGbObjectBlockVisitor(GbObject3DPtr geoObject, int refineLevel);
+   virtual ~RefineCrossAndInsideGbObjectBlockVisitor();
+   void visit(Grid3DPtr grid, Block3DPtr block);
+   //////////////////////////////////////////////////////////////////////////
+protected:
+   GbObject3DPtr geoObject;
+   bool notActive;
+};
+
+#endif 
diff --git a/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectHelper.cpp b/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b48829751f17e236d526f864dbf2b7da7e2d4b92
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectHelper.cpp
@@ -0,0 +1,56 @@
+#include "RefineCrossAndInsideGbObjectHelper.h"
+#include "RefineCrossAndInsideGbObjectBlockVisitor.h"
+#include "RatioBlockVisitor.h"
+#include "RatioSmoothBlockVisitor.h"
+#include "OverlapBlockVisitor.h"
+#include "SetInterpolationDirsBlockVisitor.h"
+#include <D3Q27System.h>
+
+
+RefineCrossAndInsideGbObjectHelper::RefineCrossAndInsideGbObjectHelper(Grid3DPtr grid, int maxRefineLevel) :
+                                    grid(grid),
+                                    maxRefineLevel(maxRefineLevel)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+RefineCrossAndInsideGbObjectHelper::~RefineCrossAndInsideGbObjectHelper(void)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+void RefineCrossAndInsideGbObjectHelper::refine()
+{
+   UBLOG(logDEBUG5,"RefineCrossAndInsideGbObjectHelper: refine - start");	
+   
+   int size = (int)objects.size();
+
+   for (int i = 0; i < size; i++)
+   {
+      RefineCrossAndInsideGbObjectBlockVisitor refVisitor(objects[i], levels[i]);
+      grid->accept(refVisitor);
+   }
+
+   RatioBlockVisitor ratioVisitor(maxRefineLevel);
+   grid->accept(ratioVisitor);
+
+   RatioSmoothBlockVisitor ratioSmoothVisitor(maxRefineLevel);
+   grid->accept(ratioSmoothVisitor);
+
+   OverlapBlockVisitor overlapVisitor(maxRefineLevel);
+   grid->accept(overlapVisitor);
+
+   std::vector<int> dirs;
+
+   for (int i=D3Q27System::E; i<D3Q27System::ENDDIR; i++)
+   {
+      dirs.push_back(i);
+   }
+   SetInterpolationDirsBlockVisitor interDirsVisitor(dirs);
+   grid->accept(interDirsVisitor);
+   UBLOG(logDEBUG5,"RefineCrossAndInsideGbObjectHelper: refine - end");	
+}
+//////////////////////////////////////////////////////////////////////////
+void RefineCrossAndInsideGbObjectHelper::addGbObject( GbObject3DPtr object, int refineLevel )
+{
+   objects.push_back(object);
+   levels.push_back(refineLevel);
+}
diff --git a/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectHelper.h b/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f9e2158784af8df7165170cb58f08440fc15420
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RefineCrossAndInsideGbObjectHelper.h
@@ -0,0 +1,33 @@
+#ifndef RefineCrossAndInsideGbObjectHelper_H
+#define RefineCrossAndInsideGbObjectHelper_H
+
+#include <vector>
+
+#include <Grid3D.h>
+#include <GbObject3D.h>
+
+//! \brief Refine blocks on base of bounding boxes.
+//! \details You need to use <i>addGbObject()</i> to add corresponding bounding boxes. Then call <i>refine()</i>.
+//! \author K. Kucher
+class RefineCrossAndInsideGbObjectHelper
+{
+public:
+   //! Constructor
+   //! \param grid a smart pointer to the grid object
+   //! \param maxRefineLevel an integer for maximal refinement level
+   RefineCrossAndInsideGbObjectHelper(Grid3DPtr grid, int maxRefineLevel);
+   virtual ~RefineCrossAndInsideGbObjectHelper(void);
+   //! add geometric object
+   //! \param object a smart pointer to bounding box
+   //! \param refineLevel a value of refinement level for corresponding bounding box
+   void addGbObject(GbObject3DPtr object, int refineLevel);
+   //! start refinement
+   void refine();
+private:
+   Grid3DPtr grid;
+   std::vector<GbObject3DPtr> objects;
+   std::vector<int> levels;
+   int maxRefineLevel;
+};
+
+#endif 
diff --git a/source/VirtualFluidsCore/Visitors/RefineInterGbObjectsVisitor.cpp b/source/VirtualFluidsCore/Visitors/RefineInterGbObjectsVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ae9f76adb868741e55fac1177787519dbb86cc4
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RefineInterGbObjectsVisitor.cpp
@@ -0,0 +1,63 @@
+#include "RefineInterGbObjectsVisitor.h"
+
+RefineInterGbObjectsBlockVisitor::RefineInterGbObjectsBlockVisitor() 
+   : Block3DVisitor(-1, -1)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+RefineInterGbObjectsBlockVisitor::RefineInterGbObjectsBlockVisitor(GbObject3DPtr includeGbObject3D, GbObject3DPtr excludeGbObject3D, int startlevel, int stoplevel)
+   : Block3DVisitor(startlevel, stoplevel)
+{
+   this->includeGbObjects3D.push_back(includeGbObject3D);
+   this->excludeGbObjects3D.push_back(excludeGbObject3D);
+}
+//////////////////////////////////////////////////////////////////////////
+RefineInterGbObjectsBlockVisitor::RefineInterGbObjectsBlockVisitor(std::vector<GbObject3DPtr> includeGbObjects3D, std::vector<GbObject3DPtr> excludeGbObjects3D, int startlevel, int stoplevel)
+   : Block3DVisitor(startlevel, stoplevel)
+{
+   this->includeGbObjects3D = includeGbObjects3D;
+   this->excludeGbObjects3D = excludeGbObjects3D;
+}
+//////////////////////////////////////////////////////////////////////////
+void RefineInterGbObjectsBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   UbTupleDouble3 coords = grid->getBlockWorldCoordinates(block);
+   UbTupleDouble3 delta  = grid->getBlockLengths(block);
+
+   double cellMinX1 = val<1>(coords);
+   double cellMinX2 = val<2>(coords);
+   double cellMinX3 = val<3>(coords);
+   double cellMaxX1 = val<1>(coords)+val<1>(delta);
+   double cellMaxX2 = val<2>(coords)+val<2>(delta);
+   double cellMaxX3 = val<3>(coords)+val<3>(delta);
+
+   bool insideInclude = false;
+   for(size_t i=0; i<includeGbObjects3D.size(); i++)
+   {
+      if(   includeGbObjects3D[i]->isCellInsideOrCuttingGbObject3D(cellMinX1,cellMinX2,cellMinX3,cellMaxX1,cellMaxX2,cellMaxX3) )
+      {
+         insideInclude = true;
+         break;
+      }
+   }
+
+   bool insideExclude = false;
+   for(size_t e=0; e<excludeGbObjects3D.size(); e++)
+   {
+      if(excludeGbObjects3D[e]->isCellInsideGbObject3D(cellMinX1, cellMinX2, cellMinX3, cellMaxX1, cellMaxX2, cellMaxX3)) 
+      {
+         insideExclude = true;
+         break;
+      }
+   }
+
+   if(insideInclude && !insideExclude)         
+   {
+      int ix1, ix2, ix3, level;
+      ix1 = block->getX1();
+      ix2 = block->getX2();
+      ix3 = block->getX3();
+      level = block->getLevel();
+      grid->expandBlock(ix1,ix2,ix3,level); 
+   }
+}
diff --git a/source/VirtualFluidsCore/Visitors/RefineInterGbObjectsVisitor.h b/source/VirtualFluidsCore/Visitors/RefineInterGbObjectsVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa90f34cac1438fdaa7c88f3c1be942fba21f32c
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RefineInterGbObjectsVisitor.h
@@ -0,0 +1,23 @@
+#ifndef RefineInterGbObjectsVisirtor_H
+#define RefineInterGbObjectsVisirtor_H
+
+#include <vector>
+
+#include "Block3DVisitor.h"
+#include <numerics/geometry3d/GbObject3D.h>
+
+//////////////////////////////////////////////////////////////////////////
+class RefineInterGbObjectsBlockVisitor : public Block3DVisitor
+{
+public:
+   RefineInterGbObjectsBlockVisitor();
+   RefineInterGbObjectsBlockVisitor(GbObject3DPtr includeGbObject3D, GbObject3DPtr excludeGbObject3D, int startlevel, int stoplevel);
+   RefineInterGbObjectsBlockVisitor(std::vector<GbObject3DPtr> includeGbObjects3D, std::vector<GbObject3DPtr> excludeGbObjects3D, int startlevel, int stoplevel);
+   void visit(Grid3DPtr grid, Block3DPtr block);
+
+private:
+   std::vector<GbObject3DPtr> includeGbObjects3D;
+   std::vector<GbObject3DPtr> excludeGbObjects3D;
+};
+
+#endif //RefineInterGbObjectsVisirtor_H
diff --git a/source/VirtualFluidsCore/Visitors/RenumberBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/RenumberBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e6a8e42ee094ee20701a930f934fae2b49d1465
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RenumberBlockVisitor.cpp
@@ -0,0 +1,20 @@
+#include "RenumberBlockVisitor.h"
+#include "Grid3DSystem.h"
+#include "LBMSystem.h"
+
+int RenumberBlockVisitor::counter = 0;
+
+RenumberBlockVisitor::RenumberBlockVisitor() :
+Block3DVisitor(0, Grid3DSystem::MAXLEVEL)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void RenumberBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   block->setGlobalID(counter);
+   Grid3D::BlockIDMap blockIdMap = grid->getBlockIDs();
+   blockIdMap.insert(std::make_pair(counter, block));
+   counter++;
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/RenumberBlockVisitor.h b/source/VirtualFluidsCore/Visitors/RenumberBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..126a929d0c629a129332ebcef9b878298c54842e
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/RenumberBlockVisitor.h
@@ -0,0 +1,30 @@
+/**
+* @file RenumberBlockVisitor.h
+* @brief Visitor class which renumber blocks.
+* @author Konstantin Kutscher
+* @date 06.06.2011
+*/
+
+#ifndef RenumberBlockVisitor_h
+#define RenumberBlockVisitor_h
+
+#include "Block3DVisitor.h"
+#include "LBMKernel3D.h"
+
+//! \brief  Visitor class which renumber blocks.
+//! \details Visitor class which renumber blocks.            
+//! \author  Konstantin Kutscher 
+class RenumberBlockVisitor : public Block3DVisitor
+{
+public:
+   RenumberBlockVisitor();
+
+   virtual ~RenumberBlockVisitor() {}
+
+   virtual void visit(Grid3DPtr grid, Block3DPtr block);
+
+private:
+   static int counter;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/SetForcingBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/SetForcingBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a83046c5c122e724f01dcf120f57ab2e8581003c
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetForcingBlockVisitor.cpp
@@ -0,0 +1,64 @@
+#include "SetForcingBlockVisitor.h"
+#include "Grid3DSystem.h"
+#include "LBMSystem.h"
+
+SetForcingBlockVisitor::SetForcingBlockVisitor(LBMReal forcingX1, LBMReal forcingX2, LBMReal forcingX3) : 
+                        Block3DVisitor(0, Grid3DSystem::MAXLEVEL), forcingX1(forcingX1), 
+                                                                   forcingX2(forcingX2),
+                                                                   forcingX3(forcingX3)
+{
+   ftype = 0;
+}
+//////////////////////////////////////////////////////////////////////////
+SetForcingBlockVisitor::SetForcingBlockVisitor(const mu::Parser& muForcingX1, const mu::Parser& muForcingX2, const mu::Parser& muForcingX3) : 
+                                              Block3DVisitor(0, Grid3DSystem::MAXLEVEL), muForcingX1(muForcingX1),
+                                                                                         muForcingX2(muForcingX2),
+                                                                                         muForcingX3(muForcingX3)
+
+{
+   ftype = 1;
+}
+//////////////////////////////////////////////////////////////////////////
+SetForcingBlockVisitor::SetForcingBlockVisitor(const std::string& sForcingX1, const std::string& sForcingX2, const std::string& sForcingX3) : 
+                                             Block3DVisitor(0, Grid3DSystem::MAXLEVEL), sForcingX1(sForcingX1),
+                                                                                        sForcingX2(sForcingX2),
+                                                                                        sForcingX3(sForcingX3)
+
+{
+   ftype = 2;
+}
+//////////////////////////////////////////////////////////////////////////
+void SetForcingBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if(block->getRank() == grid->getRank())
+   {
+      switch (ftype)
+      {
+      case 0:
+         block->getKernel()->setForcingX1(forcingX1);
+         block->getKernel()->setForcingX2(forcingX2);
+         block->getKernel()->setForcingX3(forcingX3);
+         block->getKernel()->setWithForcing(true);
+         break;
+      case 1:
+         block->getKernel()->setForcingX1(muForcingX1);
+         block->getKernel()->setForcingX2(muForcingX2);
+         block->getKernel()->setForcingX3(muForcingX3);
+         block->getKernel()->setWithForcing(true);
+         break;
+      case 2:
+         block->getKernel()->setForcingX1(sForcingX1);
+         block->getKernel()->setForcingX2(sForcingX2);
+         block->getKernel()->setForcingX3(sForcingX3);
+         block->getKernel()->setWithForcing(true);
+         break;
+      default:
+         block->getKernel()->setForcingX1(0.0);
+         block->getKernel()->setForcingX2(0.0);
+         block->getKernel()->setForcingX3(0.0);
+         block->getKernel()->setWithForcing(false);
+         break;
+      }
+   }
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/SetForcingBlockVisitor.h b/source/VirtualFluidsCore/Visitors/SetForcingBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..46f7f76c24759f2f72b363f33ba220a324a7c52e
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetForcingBlockVisitor.h
@@ -0,0 +1,36 @@
+#ifndef SetForcingBlockVisitor_h
+#define SetForcingBlockVisitor_h
+
+#include "Block3DVisitor.h"
+#include "LBMKernel3D.h"
+
+//! \brief Set forcing for all kernels of grid
+//! \details This visitor is useful if you need to set or reset forcing in kernels (e.g. after restart because forcing is not serializable). 
+//! \author K. Kucher
+class SetForcingBlockVisitor : public Block3DVisitor
+{
+public:
+   SetForcingBlockVisitor(LBMReal forcingX1, LBMReal forcingX2, LBMReal forcingX3);
+   
+   SetForcingBlockVisitor(const mu::Parser& muForcingX1, const mu::Parser& muForcingX2, const mu::Parser& muForcingX3);
+
+   SetForcingBlockVisitor(const std::string& sForcingX1, const std::string& sForcingX2, const std::string& sForcingX3);
+
+   virtual ~SetForcingBlockVisitor() {}
+
+   virtual void visit(Grid3DPtr grid, Block3DPtr block);
+
+private:
+   int ftype;
+   LBMReal forcingX1;
+   LBMReal forcingX2;
+   LBMReal forcingX3;
+   mu::Parser muForcingX1;
+   mu::Parser muForcingX2;
+   mu::Parser muForcingX3;
+   std::string sForcingX1;
+   std::string sForcingX2;
+   std::string sForcingX3;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/SetInterpolationDirsBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/SetInterpolationDirsBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d8c294f172908da696a2aaf1f71ad60f3d2c8e4f
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetInterpolationDirsBlockVisitor.cpp
@@ -0,0 +1,145 @@
+#include "SetInterpolationDirsBlockVisitor.h"
+#include "Grid3DSystem.h"
+#include <D3Q27System.h>
+#include <boost/foreach.hpp>
+
+SetInterpolationDirsBlockVisitor::SetInterpolationDirsBlockVisitor(std::vector<int>& dirs) : 
+   Block3DVisitor(0, Grid3DSystem::MAXLEVEL), dirs(dirs)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void SetInterpolationDirsBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   int ix1, ix2, ix3, level;
+   ix1 = block->getX1();
+   ix2 = block->getX2();
+   ix3 = block->getX3();
+   level = block->getLevel();
+   using namespace D3Q27System;
+   if(level==0) return;
+
+   Block3DPtr parentblock = grid->getSuperBlock(ix1,ix2,ix3,level);
+   if(!parentblock) return;
+
+   BOOST_FOREACH(int dir, dirs)
+   {
+      Block3DPtr nblock = grid->getNeighborBlock(dir, ix1, ix2, ix3, level);
+      if(!nblock)
+      {
+         Block3DPtr p_nblock = grid->getNeighborBlock(dir, parentblock);
+
+         if (p_nblock)
+         {
+            bool flagDir;
+            switch (dir)
+            {
+            case NE: 
+               checkFlagDir(grid, E, N, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case SW: 
+               checkFlagDir(grid, W, S, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case SE: 
+               checkFlagDir(grid, E, S, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case NW: 
+               checkFlagDir(grid, W, N, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case TE: 
+               checkFlagDir(grid, E, T, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir)continue;
+               break;
+            case BW: 
+               checkFlagDir(grid, W, B, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case BE: 
+               checkFlagDir(grid, E, B, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case TW: 
+               checkFlagDir(grid, W, T, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case TN: 
+               checkFlagDir(grid, N, T, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case BS: 
+               checkFlagDir(grid, S, B, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case BN: 
+               checkFlagDir(grid, N, B, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case TS: 
+               checkFlagDir(grid, S, T, flagDir, ix1, ix2, ix3, level);
+               if(!flagDir) continue;
+               break;
+            case TNE:
+               checkFlagDir(grid, E, N, T, flagDir, ix1, ix2, ix3, level);
+               if (!flagDir) continue;
+               break;
+            case TSW:
+               checkFlagDir(grid, W, S, T, flagDir, ix1, ix2, ix3, level);
+               if (!flagDir) continue;
+               break;
+            case TSE:
+               checkFlagDir(grid, E, S, T, flagDir, ix1, ix2, ix3, level);
+               if (!flagDir) continue;
+               break;
+            case TNW:
+               checkFlagDir(grid, W, N, T, flagDir, ix1, ix2, ix3, level);
+               if (!flagDir) continue;
+               break;
+            case BNE:
+               checkFlagDir(grid, E, N, B, flagDir, ix1, ix2, ix3, level);
+               if (!flagDir) continue;
+               break;
+            case BSW:
+               checkFlagDir(grid, W, S, B, flagDir, ix1, ix2, ix3, level);
+               if (!flagDir) continue;
+               break;
+            case BSE:
+               checkFlagDir(grid, E, S, B, flagDir, ix1, ix2, ix3, level);
+               if (!flagDir) continue;
+               break;
+            case BNW:
+               checkFlagDir(grid, W, N, B, flagDir, ix1, ix2, ix3, level);
+               if (!flagDir) continue;
+               break;
+            }
+
+            block->setInterpolationFlagFC(dir);
+            parentblock->setInterpolationFlagCF(dir);
+         }
+      }
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void SetInterpolationDirsBlockVisitor::checkFlagDir(Grid3DPtr grid, int dir1, int dir2, bool &flagDirection, int ix1, int ix2, int ix3, int level)
+{
+   Block3DPtr block1 = grid->getNeighborBlock(dir1, ix1, ix2, ix3, level);
+   Block3DPtr block2 = grid->getNeighborBlock(dir2, ix1, ix2, ix3, level);
+   if (!((block1 && block2)  ||  (!block1 && !block2)))
+      flagDirection = false;
+   else
+      flagDirection = true;
+}
+//////////////////////////////////////////////////////////////////////////
+void SetInterpolationDirsBlockVisitor::checkFlagDir(Grid3DPtr grid, int dir1, int dir2, int dir3, bool &flagDirection, int ix1, int ix2, int ix3, int level)
+{
+   Block3DPtr block1 = grid->getNeighborBlock(dir1, ix1, ix2, ix3, level);
+   Block3DPtr block2 = grid->getNeighborBlock(dir2, ix1, ix2, ix3, level);
+   Block3DPtr block3 = grid->getNeighborBlock(dir3, ix1, ix2, ix3, level);
+   if (!((block1 && block2 && block3)  ||  (!block1 && !block2 && !block3)))
+      flagDirection=false;
+   else 
+      flagDirection=true;
+}
diff --git a/source/VirtualFluidsCore/Visitors/SetInterpolationDirsBlockVisitor.h b/source/VirtualFluidsCore/Visitors/SetInterpolationDirsBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..84a23dcef6c703b4de47784cfe1d91ec01c08615
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetInterpolationDirsBlockVisitor.h
@@ -0,0 +1,23 @@
+#ifndef SetInterpolationDirsBlockVisitor_h
+#define SetInterpolationDirsBlockVisitor_h
+
+#include "Block3DVisitor.h"
+#include "LBMKernel3D.h"
+
+
+class SetInterpolationDirsBlockVisitor : public Block3DVisitor
+{
+public:
+   SetInterpolationDirsBlockVisitor(std::vector<int>& dirs);
+
+   virtual ~SetInterpolationDirsBlockVisitor() {}
+
+   virtual void visit(Grid3DPtr grid, Block3DPtr block);
+
+private:
+   std::vector<int> dirs;
+   void checkFlagDir(Grid3DPtr grid, int dir1, int dir2, bool &flagDirection, int ix1, int ix2, int ix3, int level);
+   void checkFlagDir(Grid3DPtr grid, int dir1, int dir2, int dir3, bool &flagDirection, int ix1, int ix2, int ix3, int level);
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4da48ba57a90c38e34696484b4d849d3b696eb00
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.cpp
@@ -0,0 +1,64 @@
+#include "SetKernelBlockVisitor.h"
+#include "Grid3DSystem.h"
+#include "LBMSystem.h"
+
+//SetKernelBlockVisitor::SetKernelBlockVisitor(LBMKernel3DPtr kernel, LBMReal nue) : 
+//                        Block3DVisitor(0, Grid3DSystem::MAXLEVEL), kernel(kernel), nue(nue)
+//{
+//
+//}
+//////////////////////////////////////////////////////////////////////////
+//SetKernelBlockVisitor::SetKernelBlockVisitor( LBMKernel3DPtr kernel, LBMReal nue, double availMem, double needMem ) : 
+//                                              Block3DVisitor(0, Grid3DSystem::MAXLEVEL), kernel(kernel), nue(nue)
+//{
+//   if (needMem > availMem)
+//   {
+//      throw UbException(UB_EXARGS,"SetKernelBlockVisitor: Not enough memory!!!");
+//   }
+//}
+//////////////////////////////////////////////////////////////////////////
+SetKernelBlockVisitor::SetKernelBlockVisitor(LBMKernel3DPtr kernel, LBMReal nue, double availMem, double needMem, SetKernelBlockVisitor::Action action /*= SetKernelBlockVisitor::New*/) :
+                                             Block3DVisitor(0, Grid3DSystem::MAXLEVEL), kernel(kernel), nue(nue), action(action)
+{
+   if (needMem > availMem)
+   {
+      throw UbException(UB_EXARGS, "SetKernelBlockVisitor: Not enough memory!!!");
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void SetKernelBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if(kernel && (block->getRank() == grid->getRank()))
+   {
+      LBMReal collFactor = LBMSystem::calcCollisionFactor(nue, block->getLevel());
+      kernel->setCollisionFactor(collFactor);
+      kernel->setIndex(block->getX1(), block->getX2(), block->getX3());
+      kernel->setDeltaT(LBMSystem::getDeltaT(block->getLevel()));
+      kernel->setBlock(block);
+      LBMKernel3DPtr newKernel = kernel->clone();
+
+      switch (action)
+      {
+      case SetKernelBlockVisitor::New:
+         block->setKernel(newKernel);
+         break;
+      case SetKernelBlockVisitor::Change:
+         DataSet3DPtr dataSet = block->getKernel()->getDataSet();
+         if (!dataSet)
+         {
+            UB_THROW(UbException(UB_EXARGS, "It is not possible to change a DataSet in kernel! Old DataSet is not exist!"));
+         }
+         newKernel->setDataSet(dataSet);
+         BCProcessorPtr bcProc = block->getKernel()->getBCProcessor();
+         if (!bcProc)
+         {
+            UB_THROW(UbException(UB_EXARGS, "It is not possible to change a BCProcessor in kernel! Old BCProcessor is not exist!"));
+         }
+         newKernel->setBCProcessor(bcProc);
+         block->setKernel(newKernel);
+         break;
+      }
+
+   }
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.h b/source/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..2b8bcca338a23ba5fa4f44b3c11f8c157bc923dd
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetKernelBlockVisitor.h
@@ -0,0 +1,29 @@
+#ifndef SetKernelBlockVisitor_h
+#define SetKernelBlockVisitor_h
+
+#include "Block3DVisitor.h"
+#include "LBMKernel3D.h"
+
+
+class SetKernelBlockVisitor : public Block3DVisitor
+{
+public:
+   enum Action { New, Change };
+public:
+   //SetKernelBlockVisitor(LBMKernel3DPtr kernel, LBMReal nue);
+   
+   //SetKernelBlockVisitor(LBMKernel3DPtr kernel, LBMReal nue, double availMem, double needMem);
+
+   SetKernelBlockVisitor(LBMKernel3DPtr kernel, LBMReal nue, double availMem, double needMem, SetKernelBlockVisitor::Action action = SetKernelBlockVisitor::New);
+
+   virtual ~SetKernelBlockVisitor() {}
+
+   virtual void visit(Grid3DPtr grid, Block3DPtr block);
+
+private:
+   LBMKernel3DPtr kernel;
+   LBMReal nue;
+   Action action;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/SetSolidOrTransBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/SetSolidOrTransBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e53c5d16ec3806a6e6ba9bc3713c246ce01d7054
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetSolidOrTransBlockVisitor.cpp
@@ -0,0 +1,30 @@
+#include "SetSolidOrTransBlockVisitor.h"
+#include "Grid3DSystem.h"
+
+SetSolidOrTransBlockVisitor::SetSolidOrTransBlockVisitor(Interactor3DPtr interactor, BlockType type) : 
+   Block3DVisitor(0, Grid3DSystem::MAXLEVEL), interactor(interactor),
+   type(type)
+{
+
+
+}
+//////////////////////////////////////////////////////////////////////////
+void SetSolidOrTransBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if(block->getRank() == grid->getRank())
+   {
+      if (block->isActive())
+      {
+         switch (type)
+         {
+         case SOLID:
+            interactor->setSolidBlock(block);
+            break;
+         case TRANS:
+            interactor->setTransBlock(block);
+            break;
+         }
+      }
+   }
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/SetSolidOrTransBlockVisitor.h b/source/VirtualFluidsCore/Visitors/SetSolidOrTransBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..457ae9910fff4dd0edb4a2f37eea35e4cbcba97a
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetSolidOrTransBlockVisitor.h
@@ -0,0 +1,25 @@
+#ifndef SetSolidOrTransBlockVisitor_h
+#define SetSolidOrTransBlockVisitor_h
+
+#include "Block3DVisitor.h"
+#include "Interactor3D.h"
+
+
+class SetSolidOrTransBlockVisitor : public Block3DVisitor
+{
+public:
+   enum BlockType{SOLID, TRANS};
+public:
+   SetSolidOrTransBlockVisitor(Interactor3DPtr interactor, BlockType type);
+
+   virtual ~SetSolidOrTransBlockVisitor() {}
+
+   virtual void visit(Grid3DPtr grid, Block3DPtr block);
+
+private:
+   Interactor3DPtr interactor;
+   BlockType type;
+};
+
+#endif
+
diff --git a/source/VirtualFluidsCore/Visitors/SetSpongeLayerBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/SetSpongeLayerBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f85d6d8b65320da656020a55ee8980ebd6e73b17
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetSpongeLayerBlockVisitor.cpp
@@ -0,0 +1,24 @@
+#include "SetSpongeLayerBlockVisitor.h"
+#include "Grid3DSystem.h"
+#include "LBMSystem.h"
+
+SetSpongeLayerBlockVisitor::SetSpongeLayerBlockVisitor( const mu::Parser& spongeLayer ) : Block3DVisitor(0, Grid3DSystem::MAXLEVEL), spongeLayer(spongeLayer)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+SetSpongeLayerBlockVisitor::~SetSpongeLayerBlockVisitor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void SetSpongeLayerBlockVisitor::visit( Grid3DPtr grid, Block3DPtr block )
+{
+   if(block->getRank() == grid->getRank())
+   {
+      block->getKernel()->setWithSpongeLayer(true);
+      block->getKernel()->setSpongeLayer(spongeLayer);
+   }
+}
+
+
diff --git a/source/VirtualFluidsCore/Visitors/SetSpongeLayerBlockVisitor.h b/source/VirtualFluidsCore/Visitors/SetSpongeLayerBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..a7f802707dff11a4de0a32d63ddfca5094d9d124
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/SetSpongeLayerBlockVisitor.h
@@ -0,0 +1,22 @@
+#ifndef SetSpongeLayerBlockVisitor_h__
+#define SetSpongeLayerBlockVisitor_h__
+
+#include "Block3DVisitor.h"
+#include "LBMKernel3D.h"
+
+//! \brief Set sponge layer for all kernels of grid
+//! \details This visitor is useful if you need to set or reset sponge layer in kernels (e.g. after restart because sponge layer is not serializable). 
+//! \author K. Kucher
+
+class SetSpongeLayerBlockVisitor : public Block3DVisitor
+{
+public:
+   SetSpongeLayerBlockVisitor(const mu::Parser& spongeLayer);
+   virtual ~SetSpongeLayerBlockVisitor();
+   virtual void visit(Grid3DPtr grid, Block3DPtr block);
+protected:
+private:
+   mu::Parser spongeLayer;
+};
+
+#endif // SetSpongeLayerBlockVisitor_h__
diff --git a/source/VirtualFluidsCore/Visitors/ViscosityBlockVisitor.cpp b/source/VirtualFluidsCore/Visitors/ViscosityBlockVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..61795457e9dcba95ea1b6327c578051e7220acc6
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/ViscosityBlockVisitor.cpp
@@ -0,0 +1,19 @@
+#include "ViscosityBlockVisitor.h"
+#include "Grid3DSystem.h"
+#include "LBMSystem.h"
+
+ViscosityBlockVisitor::ViscosityBlockVisitor(LBMReal nu) :
+Block3DVisitor(0, Grid3DSystem::MAXLEVEL), nu(nu)
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void ViscosityBlockVisitor::visit(Grid3DPtr grid, Block3DPtr block)
+{
+   if (block->getRank() == grid->getRank())
+   {
+      LBMReal collFactor = LBMSystem::calcCollisionFactor(nu, block->getLevel());
+      block->getKernel()->setCollisionFactor(collFactor);
+   }
+}
+
diff --git a/source/VirtualFluidsCore/Visitors/ViscosityBlockVisitor.h b/source/VirtualFluidsCore/Visitors/ViscosityBlockVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab485c83ad112f602a21045c1e1e7dc5c717191a
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/ViscosityBlockVisitor.h
@@ -0,0 +1,21 @@
+#ifndef ViscosityBlockVisitor_h
+#define ViscosityBlockVisitor_h
+
+#include "Block3DVisitor.h"
+#include "LBMKernel3D.h"
+
+
+class ViscosityBlockVisitor : public Block3DVisitor
+{
+public:
+   ViscosityBlockVisitor(LBMReal nu);
+
+   virtual ~ViscosityBlockVisitor() {}
+
+   virtual void visit(Grid3DPtr grid, Block3DPtr block);
+
+private:
+   LBMReal nu;
+};
+
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/ZoltanPartitioningGridVisitor.cpp b/source/VirtualFluidsCore/Visitors/ZoltanPartitioningGridVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cc354f0e461f2b7178db5981613f042cdce30228
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/ZoltanPartitioningGridVisitor.cpp
@@ -0,0 +1,144 @@
+#if defined VF_ZOLTAN && defined VF_MPI
+
+#include "ZoltanPartitioningGridVisitor.h"
+#include <vector>
+
+using namespace std;
+
+ZoltanPartitioningGridVisitor::ZoltanPartitioningGridVisitor(CommunicatorPtr comm, int numOfDirs, int numOfLocalParts) :
+comm(comm), 
+numOfDirs(numOfDirs), 
+numOfLocalParts(numOfLocalParts)
+{
+}
+//////////////////////////////////////////////////////////////////////////
+ZoltanPartitioningGridVisitor::~ZoltanPartitioningGridVisitor()
+{
+
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioningGridVisitor::visit(Grid3DPtr grid)
+{
+   UBLOG(logDEBUG5, "ZoltanPartitioningPatchVisitor::visit() - start");
+
+   //MPI_Comm mpi_comm = *((MPI_Comm*) comm->getNativeCommunicator());
+
+   //ZoltanPartitioner zp(mpi_comm, comm->getProcessID(), numOfLocalParts);
+   //
+   //graph = zp.getGraphData();
+   
+   collectData(grid);
+
+   //zp.partition();
+
+   //repartGrid(grid, zp);
+
+   UBLOG(logDEBUG5, "ZoltanPartitioningPatchVisitor::visit() - end");
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioningGridVisitor::collectData(Grid3DPtr grid)
+{
+   int myRank = comm->getProcessID();
+   int numOfProc = comm->getNumberOfProcesses();
+
+   if (numOfProc < 2)
+   {
+      return;
+   }
+
+   int minInitLevel = grid->getCoarsestInitializedLevel();
+   int maxInitLevel = grid->getFinestInitializedLevel();
+
+   for (int l = minInitLevel; l<=maxInitLevel; l++)
+   {
+      MPI_Comm mpi_comm = *((MPI_Comm*)comm->getNativeCommunicator());
+      ZoltanPartitioner zp(mpi_comm, comm->getProcessID(), numOfLocalParts);
+      graph = zp.getGraphData();
+
+      int n = 0;
+      vector<Block3DPtr> blockVector;
+      grid->getBlocks(l, blockVector);
+
+      if (blockVector.size() == 0)
+      {
+         UB_THROW(UbException(UB_EXARGS, "Blocks for decomposition don't exist!"));
+      }
+
+      //Verteilung von Ranks
+      int rank = 0;
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         block->setRank(rank);
+         block->setPart(rank);
+         rank++;
+         if (rank > numOfProc - 1)
+            rank = 0;
+      }
+
+      int vertices = 0;
+
+      BOOST_FOREACH(Block3DPtr block, blockVector)
+      {
+         if (block->getRank() == myRank)
+         {
+            vertices++;
+
+            vertexGID.push_back(block->getGlobalID());
+
+            int edges = 0;
+            for (int dir = 0; dir <= numOfDirs; dir++)
+            {
+               Block3DPtr neighBlock = (grid->getNeighborBlock(dir,
+                  block->getX1(), block->getX2(), block->getX3(), l));
+
+               if (neighBlock)
+               {
+                  edges++;
+                  nborGID.push_back(neighBlock->getGlobalID());
+                  nborProc.push_back(neighBlock->getRank());
+               }
+            }
+            numEdges.push_back(edges);
+         }
+      }
+      graph->numLocalVertices = vertices;
+      graph->vnumEdges = numEdges;
+      graph->vvertexGID = vertexGID;
+      graph->vnborGID = nborGID;
+      graph->vnborProc = nborProc;
+
+      zp.partition();
+      repartGrid(grid, zp);
+   }
+}
+//////////////////////////////////////////////////////////////////////////
+void ZoltanPartitioningGridVisitor::repartGrid(Grid3DPtr grid, ZoltanPartitioner& zp)
+{
+   if (zp.areChanges())
+   {
+      UBLOG(logDEBUG5, "ZoltanPartitioningPatchVisitor::repartGrid - start" );
+      vector<int> sExportGlobalGids, sExportToPart, sExportProcs;
+      vector<int> rExportGlobalGids, rExportToPart, rExportProcs;
+
+      zp.getExportData(sExportGlobalGids, sExportToPart, sExportProcs);
+
+      comm->allGather(sExportGlobalGids, rExportGlobalGids);
+      comm->allGather(sExportToPart, rExportToPart);
+      comm->allGather(sExportProcs, rExportProcs);
+
+      for (int i = 0; i < (int)rExportGlobalGids.size(); i++)
+      {
+         if (rExportGlobalGids[i] != -1)
+         {
+            Block3DPtr block = grid->getBlock(rExportGlobalGids[i]);
+            if(block)
+            {
+               block->setRank(rExportProcs[i]);
+               block->setPart(rExportToPart[i]);
+            }
+         }
+      }
+      UBLOG(logDEBUG5, "ZoltanPartitioningPatchVisitor::repartGrid - end" );
+   }
+}
+#endif
diff --git a/source/VirtualFluidsCore/Visitors/ZoltanPartitioningGridVisitor.h b/source/VirtualFluidsCore/Visitors/ZoltanPartitioningGridVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..5fb4eac8271f15ad3b71dfbc7fe1a3b54fd2a0fb
--- /dev/null
+++ b/source/VirtualFluidsCore/Visitors/ZoltanPartitioningGridVisitor.h
@@ -0,0 +1,38 @@
+/**
+* @file ZoltanPartitioningPatchVisitor.h
+* @brief Visitor class wich apply Zoltan library partitioning.
+* @author Kostyantyn Kucher
+* @date 10.06.2011
+*/
+
+#ifndef ZoltanPartitioningGridVisitor_H
+#define ZoltanPartitioningGridVisitor_H
+
+#if defined VF_ZOLTAN && defined VF_MPI
+
+#include "Grid3DVisitor.h"
+#include "Communicator.h"
+#include "ZoltanPartitioner.h"
+
+class ZoltanPartitioningGridVisitor : public Grid3DVisitor
+{
+public:
+   ZoltanPartitioningGridVisitor(CommunicatorPtr comm, int numOfDirs, int numOfLocalParts = 1);
+   ~ZoltanPartitioningGridVisitor();
+   void visit(Grid3DPtr grid);
+protected:
+   void collectData(Grid3DPtr grid);
+   void repartGrid(Grid3DPtr grid, ZoltanPartitioner& zp);
+private:
+   CommunicatorPtr comm;
+   int numOfDirs;
+   int numOfLocalParts;
+   ZoltanGraph *graph;
+   std::vector<int> vertexGID;
+   std::vector<int> numEdges;
+   std::vector<int> nborGID;
+   std::vector<int> nborProc;
+};
+
+#endif
+#endif