diff --git a/program/source/grid/marker.cc b/program/source/grid/marker.cc
index 3ec9ad273ed7cad0f1240c14a1928d42ac25ec2b..1a6f38c75b8623cd1fbd7bdca337cf7dd00e5c33 100644
--- a/program/source/grid/marker.cc
+++ b/program/source/grid/marker.cc
@@ -467,7 +467,7 @@ Boundary_Marker::Boundary_Marker ( Unstructured_grid* ug_ ) : Marker ( ug_ )
 		else  {
 			Set_marker<quadrangleEl> ( id, yes_mark );
 			for ( int i=0; i<4; ++i )
-				Set_marker<edgeEl> ( quad->Give_id_edge ( ( dir2D ) i ), yes_mark );
+                Set_marker<edgeEl> ( quad->Give_id_edge ( ( dir2D ) i ), yes_mark );
 			for ( int i=0; i<4; ++i )
 				Set_marker<pointEl> ( quad->Give_id_corner ( ( dir2D_sons ) i ), yes_mark );
 		}
diff --git a/program/source/interpol/interpol.cc b/program/source/interpol/interpol.cc
index 17d6ecef3629342f71cba0c78f81d83596cc5921..1c4a441db51a44866367654a65b36112b36b4d05 100644
--- a/program/source/interpol/interpol.cc
+++ b/program/source/interpol/interpol.cc
@@ -61,6 +61,14 @@ bool contained_in_tet_strong(D3vector lam) {
   if(lam.x + lam.y + lam.z > 1+limit)  return false;
   return true;
 }
+bool contained_in_tet_direct(D3vector lam) {
+    double limit = 0.0; // 0.2
+  if(lam.x < -limit)                 return false;
+  if(lam.y < -limit)                 return false;
+  if(lam.z < -limit)                 return false;
+  if(lam.x + lam.y + lam.z > 1+limit)  return false;
+  return true;
+}
 
 bool new_lam_better(D3vector lam_old, D3vector lam_new) {
 
@@ -1637,13 +1645,47 @@ void PointInterpolator::smoothGrid()
         {
             for (int k = 1 ; k < nz -1 ; k++)
             {
-                data[i    +nx*(j    +ny* k)] =  (2.0 * data[i    +nx*(j    +ny* k)]
-                                                    + data[i+1  +nx*(j    +ny* k)]
-                                                    + data[i-1  +nx*(j    +ny* k)]
-                                                    + data[i+1  +nx*(j+1  +ny* k)]
-                                                    + data[i+1  +nx*(j-1  +ny* k)]
-                                                    + data[i+1  +nx*(j    +ny* k+1)]
-                                                    + data[i+1  +nx*(j    +ny* k-1)]) / 8.0;
+                double div = 0;
+                double sum = 0;
+                if (data[i    +nx*(j    +ny* k)] != defaultInterpolation)
+                {
+                    sum += 2.0*data[i    +nx*(j    +ny* k)] ;
+                    div++;div++;
+                }
+                if (data[i+1    +nx*(j    +ny* k)] != defaultInterpolation)
+                {
+                    sum += data[i+1    +nx*(j    +ny* k)] ;
+                    div++;
+                }
+                if (data[i    +nx*(j +1   +ny* k)] != defaultInterpolation)
+                {
+                    sum += data[i    +nx*(j +1   +ny* k)] ;
+                    div++;
+                }
+                if (data[i   +nx*(j    +ny* (k+1 ))] != defaultInterpolation)
+                {
+                    sum += data[i   +nx*(j    +ny* (k+1 ))] ;
+                    div++;
+                }
+                if (data[i-1    +nx*(j    +ny* k)] != defaultInterpolation)
+                {
+                    sum += data[i-1    +nx*(j    +ny* k)] ;
+                    div++;
+                }
+                if (data[i    +nx*(j -1   +ny* k)] != defaultInterpolation)
+                {
+                    sum += data[i    +nx*(j -1   +ny* k)] ;
+                    div++;
+                }
+                if (data[i   +nx*(j    +ny* (k-1 ))] != defaultInterpolation)
+                {
+                    sum += data[i   +nx*(j    +ny* (k-1 ))] ;
+                    div++;
+                }
+                if (div >0)
+                {
+                    data[i    +nx*(j    +ny* k)] =  sum / div;
+                }
 
             }
         }
@@ -1882,6 +1924,7 @@ void Interpolate_direct::init()
 {
     arrayBoxWSDENT.resize(blockgrid->Give_unstructured_grid()->Give_number_hexahedra());
     array_box_boundary.resize(blockgrid->Give_unstructured_grid()->Give_number_hexahedra());
+    isOuterBoundaryFlag.resize(blockgrid->Give_unstructured_grid()->Give_number_hexahedra());
 
     int counter = 0;
     int counterTwoNeighbours = 0;
@@ -1894,11 +1937,13 @@ void Interpolate_direct::init()
         int Nz = blockgrid->Give_Nz_hexahedron(id_hex);
         arrayBoxWSDENT.at(id_hex).resize(Nx*Ny*Nz);
         array_box_boundary.at(id_hex).resize(Nx*Ny*Nz);
+
     }
+
+
     std::vector<std::vector<std::vector<int> > >addToIndex;
     addToIndex.resize(blockgrid->Give_unstructured_grid()->Give_number_hexahedra());
 
-
     for (int id_hex = 0 ; id_hex < blockgrid->Give_unstructured_grid()->Give_number_hexahedra() ; id_hex++)
     {
         int Nx = blockgrid->Give_Nx_hexahedron(id_hex); // now without +1, since for ( n gridpoints, only n-1 surrounding blocks exist!)
@@ -2210,7 +2255,56 @@ void Interpolate_direct::init()
     }
     }
 
-//    cout << "counter " << counter << endl;
+
+    for (int idHex = 0 ; idHex < blockgrid->Give_unstructured_grid()->Give_number_hexahedra() ; idHex++)
+    {
+        int Nx = blockgrid->Give_Nx_hexahedron(idHex);
+        int Ny = blockgrid->Give_Ny_hexahedron(idHex);
+        int Nz = blockgrid->Give_Nz_hexahedron(idHex);
+        isOuterBoundaryFlag.at(idHex).resize((Nx+1)*(Ny+1)*(Nz+1));
+
+        for (int i = Nx/2 ; i < Nx+1; i = i + Nx) for (int j = Ny/2 ; j < Ny+1; j = j + Ny) for (int k = 0 ; k < Nz+1; k = k + Nz)
+        {
+            int convertedLocalIndex = i    +(Nx+1)*(j    +(Ny+1)* k);
+            if (blockgrid->Give_blockgrid_coordinates()->blockgrid_hexa_boundary.at(idHex).at(convertedLocalIndex).empty())
+            {
+                for (int iInner = 0 ; iInner < Nx+1; iInner++) for (int jInner = 0 ; jInner < Ny+1; jInner++)
+                {
+                    int convertedLocalIndex = iInner    +(Nx+1)*(jInner    +(Ny+1)* k);
+                    isOuterBoundaryFlag.at(idHex).at(convertedLocalIndex) = true;
+                }
+            }
+        }
+        for (int i = Nx/2 ; i < Nx+1; i = i + Nx) for (int j = 0 ; j < Ny+1; j = j + Ny) for (int k = Nz/2 ; k < Nz+1; k = k + Nz)
+        {
+            int convertedLocalIndex = i    +(Nx+1)*(j    +(Ny+1)* k);
+            if (blockgrid->Give_blockgrid_coordinates()->blockgrid_hexa_boundary.at(idHex).at(convertedLocalIndex).empty())
+            {
+                for (int iInner = 0 ; iInner < Nx+1; iInner++) for (int kInner = 0 ; kInner < Nz+1; kInner++)
+                {
+                    int convertedLocalIndex = iInner    +(Nx+1)*(j    +(Ny+1)* kInner);
+                    isOuterBoundaryFlag.at(idHex).at(convertedLocalIndex) = true;
+                }
+            }
+
+        }
+        for (int i = 0 ; i < Nx+1; i = i + Nx) for (int j = Ny/2 ; j < Ny+1; j = j + Ny) for (int k = Nz/2 ; k < Nz+1; k = k + Nz)
+        {
+            int convertedLocalIndex = i    +(Nx+1)*(j    +(Ny+1)* k);
+            if (blockgrid->Give_blockgrid_coordinates()->blockgrid_hexa_boundary.at(idHex).at(convertedLocalIndex).empty())
+            {
+                for (int jInner = 0 ; jInner < Ny+1; jInner++) for (int kInner = 0 ; kInner < Nz+1; kInner++)
+                {
+                    int convertedLocalIndex = i    +(Nx+1)*(jInner    +(Ny+1)* kInner);
+                    isOuterBoundaryFlag.at(idHex).at(convertedLocalIndex) = true;
+                }
+            }
+
+        }
+    }
+
+
+    cout << "counter " << counter << endl;
 //    cout << "boundary boxes " << counterBoxesAtBoundary<< endl;
 //    cout << "counterTwoNeighbours " << counterTwoNeighbours << endl;
 //    cout << "counterTwoNeighbours " << counterTwoNeighbours << endl;
@@ -2915,6 +3009,8 @@ std::vector<int> Interpolate_direct::calculateNeighbourIndex(std::vector<std::ve
     iTemp = iTemp + relation.at(0).at(1);
     jTemp = jTemp + relation.at(0).at(2);
     kTemp = kTemp + relation.at(0).at(3);
+
+
     //mark, which one was changed --> invert sign
     if (relation.at(0).at(1) != 0)
     {    iTemp = -iTemp;    }
@@ -3418,7 +3514,186 @@ void Interpolate_direct::find_cell(D3vector v)
     setPrevPrevIndex();
     setPrevPrevPrevIndex();
     counterSlow++;
-   // cout << "slow version"<<endl;
+    // cout << "slow version"<<endl;
+}
+
+void Interpolate_direct::find_surface_cell(D3vector v)
+{
+//    vPrevPrev = vPrev;
+//    vPrev = vNow;
+    if (v == vNow)
+    {
+        counterSamePoint++;
+        return;
+    }
+            badLambdaFound = false;
+            bool badIsBestLambda = false;
+            bool previousBadLambda = false;
+            idHexNow = -1;
+            vNow = v;
+            lambda = D3vector(-1,-1,-1);
+
+
+
+            D3vector boxWSD, boxENT;
+
+            //cout << "looking for new cell!" << endl;
+
+            int Nx, Ny, Nz;
+            // prev
+            if (checkBoxSurface(idHexPrev,iPrev, jPrev, kPrev, v) != -1){
+                if (!badLambdaFound)
+                {
+                    counterFastest++;
+                    setPrevIndex();
+                    return;
+                }
+                else
+                {
+                    previousBadLambda = true;
+                    //std::cout << "should be in next or is at boundary!" << std::endl;
+                }
+            }
+            //std::cout << idHexPrev<< " " <<iPrev<< " " << jPrev<< " " << kPrev << std::endl;
+            if (checkBoxSurroundingSurface(idHexPrev,iPrev, jPrev, kPrev, v) != -1)
+            {
+                if ((previousBadLambda && badLambdaFound ) || !badLambdaFound)
+                {
+                    //will stay bad : probably at the boundary!
+                    counterFast++;
+                    setPrevIndex();
+                    return;
+                }
+
+
+            }
+            // prev prev
+            if (checkBoxSurface(idHexPrevPrev,iPrevPrev, jPrevPrev, kPrevPrev, v) != -1)
+            {
+                if (!badLambdaFound)
+                {
+                    setPrevIndex();
+                    setPrevPrevIndex();
+                    //cout << " n.: " << idHexNow << " " << kNow << " " << jNow << " " << kNow << endl;
+                    counterSecondTry++;
+                    return;
+                }
+                else
+                {
+                    previousBadLambda = true;
+                    //std::cout << "should be in next or is at boundary!" << std::endl;
+                }
+
+            }
+
+            if (checkBoxSurroundingSurface(idHexPrevPrev,iPrevPrev, jPrevPrev, kPrevPrev, v) != -1)
+            {
+                if ((previousBadLambda && badLambdaFound ) || !badLambdaFound)
+                {
+                    setPrevIndex();
+                    setPrevPrevIndex();
+                    //cout << " n.: " << idHexNow << " " << kNow << " " << jNow << " " << kNow << endl;
+                    counterSecondTry++;
+                    return;
+                }
+
+            }
+            // prev prev prev
+            if (checkBoxSurface(idHexPrevPrevPrev,iPrevPrevPrev, jPrevPrevPrev, kPrevPrevPrev, v) != -1)
+            {
+                if (!badLambdaFound)
+                {
+                    setPrevIndex();
+                    setPrevPrevIndex();
+                    setPrevPrevPrevIndex();
+                    //cout << " n.: " << idHexNow << " " << kNow << " " << jNow << " " << kNow << endl;
+                    counterThirdTry++;
+                    return;
+                }
+                else
+                {
+                    previousBadLambda = true;
+                    //std::cout << "should be in next or is at boundary!" << std::endl;
+                }
+
+
+            }
+
+            if (checkBoxSurroundingSurface(idHexPrevPrevPrev,iPrevPrevPrev, jPrevPrevPrev, kPrevPrevPrev, v) != -1)
+            {
+                if ((previousBadLambda && badLambdaFound ) || !badLambdaFound)
+                {
+                    setPrevIndex();
+                    setPrevPrevIndex();
+                    setPrevPrevPrevIndex();
+                    //cout << " n.: " << idHexNow << " " << kNow << " " << jNow << " " << kNow << endl;
+                    counterThirdTry++;
+                    return;
+                }
+
+            }
+
+
+
+    for(int id_hex=0;id_hex<blockgrid->Give_unstructured_grid()->Give_number_hexahedra();++id_hex) {
+        Nx = blockgrid->Give_Nx_hexahedron(id_hex);
+        Ny = blockgrid->Give_Ny_hexahedron(id_hex);
+        Nz = blockgrid->Give_Nz_hexahedron(id_hex);
+
+        for(int k=0;k<Nz;k+=(Nz-1))
+      for(int j=0;j<Ny;++j)
+        for(int i=0;i<Nx;++i) {
+            if (0 < checkBoxSurface(id_hex,i, j, k, v))
+            {
+                if (abs(iNow - iPrev) < 2 && abs(jNow - jPrev) < 2 && abs(kNow - kPrev) < 2)
+                {
+                    std::cout<<std::endl;
+                    std::cout << "why not found?!\n";
+                }
+            }
+        }
+        for(int k=0;k<Nz;++k)
+      for(int j=0;j<Ny;j+=(Ny-1))
+        for(int i=0;i<Nx;++i) {
+            if (0 < checkBoxSurface(id_hex,i, j, k, v))
+            {
+                if (abs(iNow - iPrev) < 2 && abs(jNow - jPrev) < 2 && abs(kNow - kPrev) < 2)
+                {
+                    std::cout<<std::endl;
+                    std::cout << "why not found?!\n";
+                }
+            }
+        }
+        for(int k=0;k<Nz;++k)
+      for(int j=0;j<Ny;++j)
+        for(int i=0;i<Nx;i+=(Nx-1)) {
+            if (0 < checkBoxSurface(id_hex,i, j, k, v))
+            {
+                if (abs(iNow - iPrev) < 2 && abs(jNow - jPrev) < 2 && abs(kNow - kPrev) < 2)
+                {
+                    std::cout<<std::endl;
+                    std::cout << "why not found?!\n";
+                }
+            }
+        }
+    }
+    if (badLambdaFound)
+    {
+        if (MIN(lambda) < 0 ||  MAX(lambda)>1)
+        {
+        }
+        else
+        {
+            assert(false && "must not happen!");
+        }
+        //lambda.Print();std::cout<<std::flush;
+    }
+
+    setPrevIndex();
+    setPrevPrevIndex();
+    setPrevPrevPrevIndex();
+    counterSlow++;
+    // cout << "slow version"<<endl;
 }
 
 void Interpolate_direct::setPrevIndex()
@@ -3528,7 +3803,6 @@ int Interpolate_direct::checkBox(int id_Hex, int i, int j, int k, D3vector v)
         cENT = blockgrid->Give_coord_hexahedron(id_Hex,i+1,j+1,k+1);
 
 
-
         D3vector lam, lamTemp ;
 
 
@@ -3637,39 +3911,331 @@ int Interpolate_direct::checkBox(int id_Hex, int i, int j, int k, D3vector v)
     return typ;
 }
 
-int Interpolate_direct::checkBoxSurrounding(int idHex, int i, int j, int k, D3vector v)
-{
-    int iterationPerSurrounding = 0;
-    for(int kIter=k-1;kIter<k+2;++kIter)
-      for(int jIter=j-1;jIter<j+2;++jIter)
-        for(int iIter=i-1;iIter<i+2;++iIter) {
-          if (checkBox(idHex,iIter, jIter, kIter, v) != -1){
-              //counterFast++;
-              //setPrevIndex();
-              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
-              return 0;}
-          else { iterationPerSurrounding++;}
-      }
-    return -1;
-}
-
-int Interpolate_direct::checkBoxSurroundingOptimized(int idHex, int i, int j, int k, D3vector v, bool neglectBadLambda)
+int Interpolate_direct::checkBoxSurface(int id_Hex, int i, int j, int k, D3vector v)
 {
-    bool temp = badLambdaFound;
-    badLambdaFound = false;
-    int iterationPerSurrounding = 0;
-    //std::vector<
-    for(int kIter=k+1;kIter>k-2;kIter-=2){
-          if (checkBox(idHex,i, j, kIter, v) != -1 && !badLambdaFound){//cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
-              return 0;}
-          else { iterationPerSurrounding++;}
-      }
-    if (badLambdaFound && !neglectBadLambda)
+    if (id_Hex < 0 )
     {
-        if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+       return -1;
     }
-
-    for(int iIter=i-1;iIter<i+2;iIter+=2){
+    int Nx = blockgrid->Give_Nx_hexahedron(id_Hex);
+    int Ny = blockgrid->Give_Ny_hexahedron(id_Hex);
+    int Nz = blockgrid->Give_Nz_hexahedron(id_Hex);
+    if ((i < -1 && j < -1 && k < -1 ) ||  (i > Nx && j > Ny && k > Nz ) ||  ( (i == -1 || i == Nx ) && (j == -1 || j == Ny) && (k == -1 || k == Nz) ) )
+    {
+       return -1;
+    }
+    int typ = -1;
+    if ( (i == -1 || j == -1 || k == -1 ) ||  (i == Nx || j == Ny || k == Nz ) )
+    {
+        typ = checkForHexaNeighboursSurface(id_Hex, i, j, k, v);
+        if ( -1 !=typ)
+        {
+             return typ;
+        }
+    }
+
+    // figure out, whether intersection with other hex is true;
+
+
+
+    if ( id_Hex< 0 || i < 0 || j < 0 || k < 0)
+    {
+        return -1;
+    }
+    if (i >= Nx || j >= Ny || k >= Nz )
+    {
+        return -1;
+    }
+    checkCounter++;
+//    D3vector cWSD, cESD;
+//    D3vector cWND, cEND;
+
+//    D3vector cWST, cEST;
+//    D3vector cWNT, cENT;
+
+    D3vector boxWSD, boxENT;
+
+    D3vector ploc;
+
+    if ( i    +Nx*(j    +Ny* k)  >= Nx*Ny*Nz)
+    {
+        cout << "Nx " << Nx << endl;
+        cout << "Ny " << Ny << endl;
+        cout << "i " << i << endl;
+        cout << "j " << j << endl;
+        cout << "k " << k << endl;
+        cout << "id of array: " << i    +Nx*(j    +Ny* k) << endl;
+    }
+    boxWSD =  arrayBoxWSDENT.at(id_Hex).at(i    +Nx*(j    +Ny* k)).at(0);
+    boxENT =  arrayBoxWSDENT.at(id_Hex).at(i    +Nx*(j    +Ny* k)).at(1);
+
+   // writeBox(boxWSD,boxENT,std::string("box"));
+
+
+    if (boxENT>=v && boxWSD<=v)
+    {
+
+        if (debugTest)
+        {
+            //cout << "debug " << endl;
+        }
+      // cout << "inside box!" << endl;
+        cWSD = blockgrid->Give_coord_hexahedron(id_Hex,i,  j,  k  );
+        cESD = blockgrid->Give_coord_hexahedron(id_Hex,i+1,j  ,k  );
+        cWND = blockgrid->Give_coord_hexahedron(id_Hex,i,  j+1,k  );
+        cEND = blockgrid->Give_coord_hexahedron(id_Hex,i+1,j+1,k  );
+
+        cWST = blockgrid->Give_coord_hexahedron(id_Hex,i,  j,  k+1);
+        cEST = blockgrid->Give_coord_hexahedron(id_Hex,i+1,j  ,k+1);
+        cWNT = blockgrid->Give_coord_hexahedron(id_Hex,i,  j+1,k+1);
+        cENT = blockgrid->Give_coord_hexahedron(id_Hex,i+1,j+1,k+1);
+
+        bool cWSDFlag = isOuterBoundaryFlag.at(id_Hex).at((i+0)    +(Nx+1)*((j+0)    +(Ny+1)* (k+0)));
+        bool cESDFlag = isOuterBoundaryFlag.at(id_Hex).at((i+1)    +(Nx+1)*((j+0)    +(Ny+1)* (k+0)));
+        bool cWNDFlag = isOuterBoundaryFlag.at(id_Hex).at((i+0)    +(Nx+1)*((j+1)    +(Ny+1)* (k+0)));
+        bool cENDFlag = isOuterBoundaryFlag.at(id_Hex).at((i+1)    +(Nx+1)*((j+1)    +(Ny+1)* (k+0)));
+
+        bool cWSTFlag = isOuterBoundaryFlag.at(id_Hex).at((i+0)    +(Nx+1)*((j+0)    +(Ny+1)* (k+1)));
+        bool cESTFlag = isOuterBoundaryFlag.at(id_Hex).at((i+1)    +(Nx+1)*((j+0)    +(Ny+1)* (k+1)));
+        bool cWNTFlag = isOuterBoundaryFlag.at(id_Hex).at((i+0)    +(Nx+1)*((j+1)    +(Ny+1)* (k+1)));
+        bool cENTFlag = isOuterBoundaryFlag.at(id_Hex).at((i+1)    +(Nx+1)*((j+1)    +(Ny+1)* (k+1)));
+
+
+        bool sideD = false, sideT = false, sideN = false, sideS = false, sideE = false, sideW = false;
+        if ( cWSDFlag && cESDFlag && cWNDFlag && cENDFlag )
+        {
+            sideD = true;
+        }
+        else if ( cWSTFlag && cESTFlag && cWNTFlag && cENTFlag )
+        {
+        sideT = true;
+        }
+        else if ( cWSDFlag && cWNDFlag && cWSTFlag && cWNTFlag )
+        {
+            sideW = true;
+        }
+        else if ( cESDFlag && cENDFlag && cESTFlag && cENTFlag )
+        {
+            sideE = true;
+        }
+        else if ( cWNDFlag && cENDFlag && cWNTFlag && cENTFlag )
+        {
+            sideN = true;
+        }
+        else if ( cWSDFlag && cESDFlag && cWSTFlag && cESTFlag )
+        {
+            sideS = true;
+        }
+        else
+        {
+            std::cout << "error in checkBoxBoundary\n";
+        }
+
+
+
+
+
+        D3vector lam, lamTemp ;
+
+
+            //std::cout << "\n\nstart of tet search\n\n";
+//            if (sideW || sideT)
+//            {
+//                lam = lambda_of_p_in_tet(v,cWND,cWNT,cWST,cEST);
+//                if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=0;typCounter0++;lamTemp = lam;}
+//            }
+
+//            //std::cout << "new best : "; lamTemp.Print();
+//            if (sideS)
+//            {
+//                lam = lambda_of_p_in_tet(v,cEST,cWND,cWST,cESD);
+//                if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=1;typCounter1++;lamTemp = lam;}
+
+//            }
+//            if (sideW || sideD || sideS)
+//            {
+//                std::cout << std::setprecision(15);
+//                lam = lambda_of_p_in_tet(v,cWND,cWSD,cWST,cESD);
+//                interpolate_in_tet_D3vector(lam,cWND,cWSD,cWST,cESD).Print();std::cout<<std::flush;
+//                std::cout << interpolate_in_tet(lam,5.0,4.0,4.0,4.0);std::cout<<std::flush;
+//                std::cout << interpolate_in_tet(lam,4.0,4.0,5.0,4.0);std::cout<<std::flush;
+//                lam.y = 0;
+//                interpolate_in_tet_D3vector(lam,cWND,cWSD,cWST,cESD).Print();std::cout<<std::flush;
+//                std::cout << interpolate_in_tet(lam,5.0,4.0,4.0,4.0);std::cout<<std::flush;
+//                std::cout << interpolate_in_tet(lam,4.0,4.0,5.0,4.0);std::cout<<std::flush;
+//                if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=2;typCounter2++;lamTemp = lam;}
+//            }
+
+//            if (sideE || sideD)
+//            {
+//                lam = lambda_of_p_in_tet(v,cEST,cWND,cESD,cEND);
+
+//                interpolate_in_tet_D3vector(lam,cEST,cWND,cESD,cEND).Print();std::cout<<std::flush;
+//                std::cout << interpolate_in_tet(lam,5.0,4.0,4.0,4.0);std::cout<<std::flush;
+//                interpolate_in_tet_D3vector(lam,cEST,cWND,cESD,cEND).Print();std::cout<<std::flush;
+//                std::cout << interpolate_in_tet(lam,5.0,4.0,4.0,4.0);std::cout<<std::flush;
+//                if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=3;typCounter3++;lamTemp = lam;}
+
+//            }
+
+//            if (sideE || sideT || sideN)
+//            {
+//                lam = lambda_of_p_in_tet(v,cENT,cWNT,cEST,cEND);
+//                if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=4;typCounter4++;lamTemp = lam;}
+
+//            }
+
+//            if (sideN)
+//            {
+//                lam = lambda_of_p_in_tet(v,cWNT,cWND,cEST,cEND);
+//                if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=5;typCounter5++;lamTemp = lam;}
+//            }
+
+        lamTemp = lambda;
+        D3vector zero(0,0,0);
+        D3vector lam2;
+        D3vector lamTrilinear;
+        if (sideN)
+        {
+            lam = lambda_of_p_in_tet(v,cWND,cWNT,cEND,zero);
+            lam2 = lambda_of_p_in_tet(v,cENT,cWNT,cEND,zero);
+            if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=0;typCounter0++;lamTemp = lam;}
+        }
+
+        //std::cout << "new best : "; lamTemp.Print();
+        if (sideS)
+        {
+            lam = lambda_of_p_in_tet(v,cESD,cWSD,cEST,zero);
+            lam2 = lambda_of_p_in_tet(v,cWST,cWSD,cEST,zero);
+            if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=1;typCounter1++;lamTemp = lam;}
+
+        }
+        if (sideE)
+        {
+            lam = lambda_of_p_in_tet(v,cEST,cESD,cENT,zero);
+            lam2 = lambda_of_p_in_tet(v,cEND,cESD,cENT,zero);
+            lam.z = 0;
+            lam2.z = 0;
+            if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=7;typCounter2++;lamTemp = lam;}
+            if (contained_in_tet_strong(lam2) && new_lam_better(lamTemp,lam2)){typ=8;typCounter2++;lamTemp = lam2;}
+        }
+
+        if (sideW)
+        {
+            lam = lambda_of_p_in_tet(v,cEST,cWND,cESD,cEND);
+
+            interpolate_in_tet_D3vector(lam,cEST,cWND,cESD,cEND).Print();std::cout<<std::flush;
+            std::cout << interpolate_in_tet(lam,5.0,4.0,4.0,4.0);std::cout<<std::flush;
+            interpolate_in_tet_D3vector(lam,cEST,cWND,cESD,cEND).Print();std::cout<<std::flush;
+            std::cout << interpolate_in_tet(lam,5.0,4.0,4.0,4.0);std::cout<<std::flush;
+            if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=3;typCounter3++;lamTemp = lam;}
+
+        }
+
+        if (sideT)
+        {
+
+            lam = lambda_of_p_in_tet(v,cENT,cWNT,cEST,zero);
+            lam2 = lambda_of_p_in_tet(v,cWST,cWNT,cEST,zero);
+            lam.z = 0;
+            lam2.z = 0;
+
+            if (false && (contained_in_tet_direct(lam) || contained_in_tet_direct(lam2)) && false)
+            {
+               lamTrilinear = bilinearInterpolation(v,cENT,cWNT,cEST,cWST);
+               lamTemp = lamTrilinear;
+               typ = 14;
+            }
+            else
+            {
+
+                if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=11;typCounter2++;lamTemp = lam;}
+                if (contained_in_tet_strong(lam2) && new_lam_better(lamTemp,lam2)){typ=12;typCounter2++;lamTemp = lam2;}
+            }
+
+        }
+
+        if (sideD)
+        {
+            lam = lambda_of_p_in_tet(v,cWND,cEND,cWSD,zero);
+            lam2= lambda_of_p_in_tet(v,cESD,cEND,cWSD,zero);
+            lam.z = 0;
+            lam2.z = 0;
+            if (false && (contained_in_tet_direct(lam) || contained_in_tet_direct(lam2)) && false)
+            {
+               lamTrilinear = bilinearInterpolation(v,cWND,cEND,cWSD,cESD);
+               lamTemp = lamTrilinear;
+               typ = 13;
+            }
+            else
+            {
+                if (contained_in_tet_strong(lam) && new_lam_better(lamTemp,lam)){typ=9;typCounter2++;lamTemp = lam;}
+                if (contained_in_tet_strong(lam2) && new_lam_better(lamTemp,lam2)){typ=10;typCounter2++;lamTemp = lam2;}
+            }
+        }
+            //std::cout << "new best : "; lamTemp.Print();
+            if( typ != -1 && new_lam_better(lambda,lamTemp))
+            {
+               if (MIN(lamTemp) < 0.0 || MAX(lamTemp) >1.0 )
+               {
+                   badLambdaFound = true;
+                   //lamTemp.Print();
+               }
+               else
+               {
+                   badLambdaFound = false;
+               }
+
+                lambda = lamTemp;
+                typ_tet = typ;
+                idHexNow = id_Hex;
+                iNow = i;
+                jNow = j;
+                kNow = k;
+
+
+
+            }
+
+
+
+    }
+    return typ;
+}
+
+int Interpolate_direct::checkBoxSurrounding(int idHex, int i, int j, int k, D3vector v)
+{
+    int iterationPerSurrounding = 0;
+    for(int kIter=k-1;kIter<k+2;++kIter)
+      for(int jIter=j-1;jIter<j+2;++jIter)
+        for(int iIter=i-1;iIter<i+2;++iIter) {
+          if (checkBox(idHex,iIter, jIter, kIter, v) != -1){
+              //counterFast++;
+              //setPrevIndex();
+              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+              return 0;}
+          else { iterationPerSurrounding++;}
+      }
+    return -1;
+}
+
+int Interpolate_direct::checkBoxSurroundingOptimized(int idHex, int i, int j, int k, D3vector v, bool neglectBadLambda)
+{
+    bool temp = badLambdaFound;
+    badLambdaFound = false;
+    int iterationPerSurrounding = 0;
+    //std::vector<
+    for(int kIter=k+1;kIter>k-2;kIter-=2){
+          if (checkBox(idHex,i, j, kIter, v) != -1 && !badLambdaFound){//cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+              return 0;}
+          else { iterationPerSurrounding++;}
+      }
+    if (badLambdaFound && !neglectBadLambda)
+    {
+        if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+    }
+
+    for(int iIter=i-1;iIter<i+2;iIter+=2){
           if (checkBox(idHex,iIter, j, k, v) != -1 && !badLambdaFound){//cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
               return 0;}
           else { iterationPerSurrounding++;}
@@ -3688,69 +4254,260 @@ int Interpolate_direct::checkBoxSurroundingOptimized(int idHex, int i, int j, in
         if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
     }
 
-    for(int kIter=k-1;kIter<k+2;kIter+=2)
-      for(int jIter=j-1;jIter<j+2;jIter+=2) {
-          if (checkBox(idHex,i, jIter, kIter, v) != -1 && !badLambdaFound){
-              //counterFast++;
+    for(int kIter=k-1;kIter<k+2;kIter+=2)
+      for(int jIter=j-1;jIter<j+2;jIter+=2) {
+          if (checkBox(idHex,i, jIter, kIter, v) != -1 && !badLambdaFound){
+              //counterFast++;
+
+              //setPrevIndex();
+              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+              return 0;}
+          else { iterationPerSurrounding++;}
+      }
+    if (badLambdaFound && !neglectBadLambda)
+    {
+        if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+    }
+    for(int kIter=k-1;kIter<k+2;kIter+=2)
+        for(int iIter=i-1;iIter<i+2;iIter+=2) {
+          if (checkBox(idHex,iIter, j, kIter, v) != -1 && !badLambdaFound){ //here
+              //counterFast++;
+
+              //setPrevIndex();
+              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+              return 0;}
+          else { iterationPerSurrounding++;}
+      }
+    if (badLambdaFound && !neglectBadLambda)
+    {
+        if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+    }
+      for(int jIter=j-1;jIter<j+2;jIter+=2)
+        for(int iIter=i-1;iIter<i+2;iIter+=2) {
+          if (checkBox(idHex,iIter, jIter, k, v) != -1 && !badLambdaFound){
+              //counterFast++;
+
+              //setPrevIndex();
+              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+              return 0;}
+          else { iterationPerSurrounding++;}
+      }
+      if (badLambdaFound && !neglectBadLambda)
+      {
+          if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+      }
+
+
+    for(int kIter=k-1;kIter<k+2;kIter+=2)
+      for(int jIter=j-1;jIter<j+2;jIter+=2)
+        for(int iIter=i-1;iIter<i+2;iIter+=2) {
+          if (checkBox(idHex,iIter, jIter, kIter, v) != -1 && !badLambdaFound){
+              //counterFast++;
+              //setPrevIndex();
+              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+              return 0;}
+          else { iterationPerSurrounding++;}
+      }
+    if (badLambdaFound && !neglectBadLambda)
+    {
+        if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+    }
+
+
+
+    badLambdaFound = temp;
+    return -1;
+}
+
+
+
+
+int Interpolate_direct::checkBoxSurroundingSurface(int idHex, int i, int j, int k, D3vector v, bool neglectBadLambda)
+{
+
+      bool temp = badLambdaFound;
+      badLambdaFound = false;
+      int iterationPerSurrounding = 0;
+      //std::vector<
+
+
+      for(int iIter=i-1;iIter<i+2;iIter+=2){
+            if (checkBoxSurface(idHex,iIter, j, k, v) != -1){//cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+                return 0;}
+            else { iterationPerSurrounding++;}
+        }
+      if (badLambdaFound && !neglectBadLambda)
+      {
+          if (checkBoxSurroundingSurface(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+      }
+      for(int jIter=j-1;jIter<j+2;jIter+=2){
+            if (checkBoxSurface(idHex,i, jIter, k, v) != -1){//cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+                return 0;}
+            else { iterationPerSurrounding++;}
+        }
+      if (badLambdaFound && !neglectBadLambda)
+      {
+          if (checkBoxSurroundingSurface(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+      }
+      for(int jIter=j-1;jIter<j+2;jIter+=2)
+        for(int iIter=i-1;iIter<i+2;iIter+=2) {
+          if (checkBoxSurface(idHex,iIter, jIter, k, v) != -1){
+              //counterFast++;
+
+              //setPrevIndex();
+              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+              return 0;}
+          else { iterationPerSurrounding++;}
+      }
+      if (badLambdaFound && !neglectBadLambda)
+      {
+          if (checkBoxSurroundingSurface(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+      }
+      for(int kIter=k+1;kIter>k-2;kIter-=2){
+            if (checkBoxSurface(idHex,i, j, kIter, v) != -1){//cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+                return 0;}
+            else { iterationPerSurrounding++;}
+        }
+      if (badLambdaFound && !neglectBadLambda)
+      {
+          if (checkBoxSurroundingSurface(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+      }
+
+      for(int kIter=k-1;kIter<k+2;kIter+=2)
+        for(int jIter=j-1;jIter<j+2;jIter+=2) {
+            if (checkBoxSurface(idHex,i, jIter, kIter, v) != -1){
+                //counterFast++;
+
+                //setPrevIndex();
+                //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+                return 0;}
+            else { iterationPerSurrounding++;}
+        }
+      if (badLambdaFound && !neglectBadLambda)
+      {
+          if (checkBoxSurroundingSurface(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+      }
+      for(int kIter=k-1;kIter<k+2;kIter+=2)
+          for(int iIter=i-1;iIter<i+2;iIter+=2) {
+            if (checkBoxSurface(idHex,iIter, j, kIter, v) != -1){ //here
+                //counterFast++;
+
+                //setPrevIndex();
+                //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+                return 0;}
+            else { iterationPerSurrounding++;}
+        }
+      if (badLambdaFound && !neglectBadLambda)
+      {
+          if (checkBoxSurroundingSurface(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+      }
+
+      for(int kIter=k-1;kIter<k+2;kIter+=2)
+        for(int jIter=j-1;jIter<j+2;jIter+=2)
+          for(int iIter=i-1;iIter<i+2;iIter+=2) {
+            if (checkBoxSurface(idHex,iIter, jIter, kIter, v) != -1){
+                //counterFast++;
+                //setPrevIndex();
+                //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
+                return 0;}
+            else { iterationPerSurrounding++;}
+        }
+      if (badLambdaFound && !neglectBadLambda)
+      {
+          if (checkBoxSurroundingSurface(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+      }
+
+
+      return -1;
+
+}
+
+
+int Interpolate_direct::checkCornerSurface(int idHex, int i, int j, int k, D3vector v)
+{
+    int typ;
+
+    int Nx = blockgrid->Give_Nx_hexahedron(idHex);
+    int Ny = blockgrid->Give_Ny_hexahedron(idHex);
+    int Nz = blockgrid->Give_Nz_hexahedron(idHex);
+
+    int index = i    +(Ny)*(j    +(Nx)* k);
+    index = i    +Nx*(j    +Ny* k);
+
+    if (array_box_boundary.at(idHex).at(index).empty())
+        return -1;
+    int idHexCorner1 = array_box_boundary.at(idHex).at(index).at(0);
+    int iCorner1     = array_box_boundary.at(idHex).at(index).at(1);
+    int jCorner1     = array_box_boundary.at(idHex).at(index).at(2);
+    int kCorner1     = array_box_boundary.at(idHex).at(index).at(3);
+
+
+    D3vector boxWSDInner =  arrayBoxWSDENT.at(idHex).at(i    +Nx*(j    +Ny* k)).at(0);
+    D3vector boxENTInner =  arrayBoxWSDENT.at(idHex).at(i    +Nx*(j    +Ny* k)).at(1);
+
+    int NxCorner1 = blockgrid->Give_Nx_hexahedron(idHexCorner1);
+    int NyCorner1 = blockgrid->Give_Ny_hexahedron(idHexCorner1);
+    int NzCorner1 = blockgrid->Give_Nz_hexahedron(idHexCorner1);
+
+    D3vector boxWSDOuter =  arrayBoxWSDENT.at(idHexCorner1).at(iCorner1    +NxCorner1*(jCorner1    +NyCorner1* kCorner1)).at(0);
+    D3vector boxENTOuter =  arrayBoxWSDENT.at(idHexCorner1).at(iCorner1    +NxCorner1*(jCorner1    +NyCorner1* kCorner1)).at(1);
+    //writeBox(boxWSDInner, boxENTInner, std::string("boxCorner"));
+    //writeBox(boxWSDOuter, boxENTOuter, std::string("boxCorner"));
+
+    if (!checkOverlapOfBoxes(boxWSDInner, boxENTInner, boxWSDOuter, boxENTOuter))
+    {
+        writeBox(boxWSDInner, boxENTInner, std::string("box1"));
+        writeBox(boxWSDOuter, boxENTOuter, std::string("box1"));
+        cout << "surrounding box is wrong!" << endl;
+    }
+
+    //cout << "corner box 1 : ";
+
+    //cout << "id: " << idHexCorner1 << " " << iCorner1 << " " << jCorner1 << " " << kCorner1 << endl;
+    //boxWSDOuter.Print();cout << endl;
+    //boxENTOuter.Print();cout << endl;
+
+    typ = checkBoxSurface(idHexCorner1, iCorner1, jCorner1, kCorner1, v);
+    if (typ != -1)
+    {
+        counterCorner++;
+        return typ;
+    }
+
+    if (array_box_boundary.at(idHex).at(index).size() < 5)
+        return -1;
+
+    int idHexCorner2 = array_box_boundary.at(idHex).at(i    +(Nx)*(j    +(Ny)* k)).at(4);
+    int iCorner2 = array_box_boundary.at(idHex).at(i    +(Nx)*(j    +(Ny)* k)).at(5);
+    int jCorner2 = array_box_boundary.at(idHex).at(i    +(Nx)*(j    +(Ny)* k)).at(6);
+    int kCorner2 = array_box_boundary.at(idHex).at(i    +(Nx)*(j    +(Ny)* k)).at(7);
+
+    int NxCorner2 = blockgrid->Give_Nx_hexahedron(idHexCorner2);
+    int NyCorner2 = blockgrid->Give_Ny_hexahedron(idHexCorner2);
+    int NzCorner2 = blockgrid->Give_Nz_hexahedron(idHexCorner2);
+
+    boxWSDOuter =  arrayBoxWSDENT.at(idHexCorner2).at(iCorner2    +NxCorner2*(jCorner2    +NyCorner2* kCorner2)).at(0);
+    boxENTOuter =  arrayBoxWSDENT.at(idHexCorner2).at(iCorner2    +NxCorner2*(jCorner2    +NyCorner2* kCorner2)).at(1);
+
 
-              //setPrevIndex();
-              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
-              return 0;}
-          else { iterationPerSurrounding++;}
-      }
-    if (badLambdaFound && !neglectBadLambda)
-    {
-        if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
-    }
-    for(int kIter=k-1;kIter<k+2;kIter+=2)
-        for(int iIter=i-1;iIter<i+2;iIter+=2) {
-          if (checkBox(idHex,iIter, j, kIter, v) != -1 && !badLambdaFound){ //here
-              //counterFast++;
 
-              //setPrevIndex();
-              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
-              return 0;}
-          else { iterationPerSurrounding++;}
-      }
-    if (badLambdaFound && !neglectBadLambda)
+    if (!checkOverlapOfBoxes(boxWSDInner, boxENTInner, boxWSDOuter, boxENTOuter))
     {
-        if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+        writeBox(boxWSDInner, boxENTInner, std::string("box1"));
+        writeBox(boxWSDOuter, boxENTOuter, std::string("box1"));
+        cout << "surrounding box is wrong!" << endl;
     }
-      for(int jIter=j-1;jIter<j+2;jIter+=2)
-        for(int iIter=i-1;iIter<i+2;iIter+=2) {
-          if (checkBox(idHex,iIter, jIter, k, v) != -1 && !badLambdaFound){
-              //counterFast++;
-
-              //setPrevIndex();
-              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
-              return 0;}
-          else { iterationPerSurrounding++;}
-      }
-      if (badLambdaFound && !neglectBadLambda)
-      {
-          if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
-      }
 
 
-    for(int kIter=k-1;kIter<k+2;kIter+=2)
-      for(int jIter=j-1;jIter<j+2;jIter+=2)
-        for(int iIter=i-1;iIter<i+2;iIter+=2) {
-          if (checkBox(idHex,iIter, jIter, kIter, v) != -1 && !badLambdaFound){
-              //counterFast++;
-              //setPrevIndex();
-              //cout << "iterationPerSurrounding " << iterationPerSurrounding+1<< endl;
-              return 0;}
-          else { iterationPerSurrounding++;}
-      }
-    if (badLambdaFound && !neglectBadLambda)
+    typ = checkBoxSurface(idHexCorner2, iCorner2, jCorner2, kCorner2, v);
+    if (typ != -1)
     {
-        if (checkBoxSurroundingOptimized(idHexNow,iNow, jNow, kNow, v,true) != -1) return 0; else return -1;
+        counterCorner++;
+        return typ;
     }
 
+    return typ;
 
-
-    badLambdaFound = temp;
-    return -1;
 }
 
 int Interpolate_direct::checkCorner(int idHex, int i, int j, int k, D3vector v)
@@ -3840,6 +4597,64 @@ int Interpolate_direct::checkCorner(int idHex, int i, int j, int k, D3vector v)
 
 }
 
+
+int Interpolate_direct::checkEdgeSurface(int idHex, int i, int j, int k, D3vector v)
+{
+
+    int typ;
+
+    int Nx = blockgrid->Give_Nx_hexahedron(idHex);
+    int Ny = blockgrid->Give_Ny_hexahedron(idHex);
+    int Nz = blockgrid->Give_Nz_hexahedron(idHex);
+
+    int index = i    +(Nx)*(j    +(Nx)* k);
+    index = (i)+Nx*(j    +Ny*(k));
+    if (array_box_boundary.at(idHex).at(index).empty())
+        return -1;
+    int idHexEdge = array_box_boundary.at(idHex).at(index).at(0);
+    int iEdge = array_box_boundary.at(idHex).at(index).at(1);
+    int jEdge = array_box_boundary.at(idHex).at(index).at(2);
+    int kEdge = array_box_boundary.at(idHex).at(index).at(3);
+
+    D3vector boxWSDInner =  arrayBoxWSDENT.at(idHex).at(i    +Nx*(j    +Ny* k)).at(0);
+    D3vector boxENTInner =  arrayBoxWSDENT.at(idHex).at(i    +Nx*(j    +Ny* k)).at(1);
+
+    int NxInner = blockgrid->Give_Nx_hexahedron(idHexEdge);
+    int NyInner = blockgrid->Give_Ny_hexahedron(idHexEdge);
+    int NzInner = blockgrid->Give_Nz_hexahedron(idHexEdge);
+
+    int indexInner = iEdge    +NxInner*(jEdge    +NyInner* kEdge);
+    //int indexInnerTest = iEdge    +NyInner*(jEdge    +NxInner* kEdge);
+
+    D3vector boxWSDOuter =  arrayBoxWSDENT.at(idHexEdge).at(indexInner).at(0);
+    D3vector boxENTOuter =  arrayBoxWSDENT.at(idHexEdge).at(indexInner).at(1);
+
+    //writeBox(boxWSDInner, boxENTInner, std::string("boxEdge"));
+    //writeBox(boxWSDOuter, boxENTOuter, std::string("boxEdge"));
+
+    if (!checkOverlapOfBoxes(boxWSDInner, boxENTInner, boxWSDOuter, boxENTOuter))
+    {
+        writeBox(boxWSDInner, boxENTInner, std::string("box1"));
+        writeBox(boxWSDOuter, boxENTOuter, std::string("box2"));
+        cout << "surrounding box is wrong!" << endl;
+    }
+
+    //cout << "edge box     : ";
+    //cout << "id: " << idHexEdge << " " << iEdge << " " << jEdge << " " << kEdge << endl;
+    //boxWSDOuter.Print();cout << endl;
+    //boxENTOuter.Print();cout << endl;
+
+    typ = checkBoxSurface(idHexEdge, iEdge, jEdge, kEdge, v);
+    if (typ != -1)
+    {
+        counterEdge++;
+        return typ;
+    }
+
+    return typ;
+
+}
+
 int Interpolate_direct::checkEdge(int idHex, int i, int j, int k, D3vector v)
 {
 
@@ -4057,6 +4872,127 @@ void Interpolate_direct::writeInterpolationEfficiency()
     }
 
 }
+
+D3vector Interpolate_direct::bilinearInterpolation(D3vector v, D3vector x1, D3vector x2, D3vector x3, D3vector x4)
+{
+
+
+    //P = A + x*b + y*C + xy*D
+    D3vector A = x1; // 100 - 000
+    D3vector B = x2-x1; // 100 - 000
+    D3vector C = x3-x1; // 010 - 000
+    D3vector D = x4-x2+x1-x3; // 001 - 000
+    //std::cout << "to be implemented" << std::endl;
+
+    D3vector normalTD = cross_product(x1,B);
+    D3vector normalTDOPP = cross_product(x3 , x4-x3);
+    //D3vector normalTDOPP2 = cross_product(cENT-cEST ,cWNT - cENT);
+    D3vector normalNS = cross_product(x1,C);
+    D3vector normalNSOPP = cross_product(x2,x4-x2);
+    //D3vector normalNSOPP2 = cross_product(cESD-cEST,cESD - cWSD);
+    normalTD = normalTD / D3VectorNorm(normalTD);
+    normalTDOPP = normalTDOPP / D3VectorNorm(normalTDOPP);
+    normalNS = normalNS / D3VectorNorm(normalNS);
+    normalNSOPP = normalNSOPP / D3VectorNorm(normalNSOPP);
+    double eta = 0.4;
+    double xi  = 0.5;
+    double phi = 0.5;
+    bool fixEta = false;
+    bool fixXi = false;
+    bool fixPhi = false;
+
+    double distTD0 = product(normalTD,x1);
+    double distTD1 = product(normalTDOPP,x1);
+    double distTDMid  = distTD0-product(normalTD,v);
+    double distTDMid2 = distTD1-product(normalTDOPP,v);
+
+    double distNS0 = product(normalNS,x4);
+    double distNS1 = product(normalNSOPP,x4);
+    double distNSMid = distNS0-product(normalNS,v);
+    double distNSMid2 = distNS1 -product(normalNSOPP,v);
+
+
+
+    //coord.Print();std::cout<<std::endl;
+    D3vector coord(0.5);
+    coord.x = 0.45;
+    coord.y = 0.55;
+    if (fabs(angle_between_vectors(normalTD,normalTDOPP)-180) < 0.5)
+    {
+        double delta = (distTD1 - distTD0);
+        phi = (distTDMid + delta - distTDMid2) /delta/ 2.0;
+        coord.z = phi;
+        fixPhi = true;
+    }
+    if (fabs(angle_between_vectors(normalNS,normalNSOPP)-180) < 0.5)
+    {
+        double delta = (distNS1 - distNS0);
+        eta = (distNSMid + delta - distNSMid2) /delta / 2.0;
+        coord.x = eta;
+        fixEta = true;
+    }
+
+
+
+
+
+    D3vector R = A    + B * coord.x + C * coord.y + D * coord.x * coord.y;
+
+    {
+        double factorJac = 0.8;
+        for (int iter = 0 ; iter < 20 ; iter++)
+        {
+            D3vector partialX = B + D * coord.y;
+            D3vector partialY =  C + D * coord.x;
+
+            D3matrix jac2(partialX,partialY,D3vector(0.0,0.0,1.0));
+            jac2.transpose();
+            jac2.invert_gauss_elimination();
+
+            R = A    + B * coord.x + C * coord.y + D * coord.x * coord.y -v;
+
+
+            //std::cout << "residuum f_xn" <<D3VectorNorm(R)<<std::endl;
+            if (D3VectorNormSquared(R) < 1e-10)
+            {
+                iter = 1000;
+            }
+
+            coord = coord - jac2.vectorMultiply(R) * factorJac;
+            if (MAX(coord) > 1.0 || MIN(coord)<0)
+            {
+                factorJac = factorJac * 0.5;
+                if (coord.x < 0.0)
+                    coord.x = 0.1;
+                if (coord.y < 0.0)
+                    coord.y = 0.15;
+                if (coord.z < 0.0)
+                    coord.z = 0.0;
+                if (coord.x > 1.0)
+                    coord.x = 0.95;
+                if (coord.y > 1.0)
+                    coord.y = 0.9;
+                if (coord.z > 1.0)
+                    coord.z = 1.0;
+            }
+            //coord.Print();std::cout<<std::endl;
+
+        }
+    }
+
+
+    D3vector x = A    + B * coord.x + C * coord.y + D * coord.x * coord.y;
+//    X.Print();
+//    std::cout << "tirlinear interp \n";
+//    x.Print();
+//    std::cout << std::flush;
+
+    if (MAX(coord) > 1.01 || MIN(coord) < -0.01)
+    {
+        return D3vector{-1,-1,-1};
+    }
+    return coord;
+}
 bool isInRange(double d0, double d1)
 {
     if (d0 * d1 >=0 )
@@ -4304,6 +5240,75 @@ D3vector Interpolate_direct::trilinarInterpolation(D3vector X, int id_Hex, int i
 }
 
 
+
+int Interpolate_direct::checkForHexaNeighboursSurface(int idHex, int i, int j, int k, D3vector v)
+{
+    counterHexa++;
+    int Nx = blockgrid->Give_Nx_hexahedron(idHex);
+    int Ny = blockgrid->Give_Ny_hexahedron(idHex);
+    int Nz = blockgrid->Give_Nz_hexahedron(idHex);
+
+    int typ = -1;
+    if ( i == -1 || i == Nx )
+    {
+        if ( j == -1 || j == Ny )
+        {
+            int Tj = (j<0) ? (Tj = j + 1 ) : (Tj = j - 1 );
+            int Ti = (i<0) ? (Ti = i + 1) : (Ti = i - 1);
+            debugTest = true;
+            typ = checkCornerSurface(idHex, Ti, Tj, k, v);
+            debugTest = false;
+            if (typ != -1 ) return typ;
+
+        }
+        else if (k == -1 || k == Nz )
+        {
+            int Tk = (k<0) ? (Tk = k + 1) : (Tk = k - 1);
+            int Ti = (i<0) ? (Ti = i + 1) : (Ti = i - 1);
+            debugTest = true;
+            typ = checkCornerSurface(idHex, Ti, j, Tk, v);
+            debugTest = false;
+            if (typ != -1 ) return typ;
+        }
+        else
+        {
+            int Ti = (i<0) ? (Ti = i + 1) : (Ti = i - 1);
+            typ = checkEdgeSurface(idHex, Ti, j, k, v);
+            if (typ != -1 ) return typ;
+        }
+    }
+    else if ( j == -1 || j == Ny )
+    {
+        /*if ( i == -1)
+        {
+            checkCorner(id_Hex, i, j, k, v);
+        }
+        else */if (k == -1 || k == Nz )
+        {
+            int Tk = (k<0) ? (Tk = k + 1) : (Tk = k - 1);
+            int Tj = (j<0) ? (Tj = j + 1) : (Tj = j - 1);
+            debugTest = true;
+            typ = checkCornerSurface(idHex, i, Tj, Tk, v);
+            debugTest = false;
+            if (typ != -1 ) return typ;
+        }
+        else
+        {
+            int Tj = (j<0) ? (Tj = j + 1) : (Tj = j - 1);
+            typ = checkEdgeSurface(idHex, i, Tj, k, v);
+            if (typ != -1 ) return typ;
+        }
+    }
+    else if ( k == -1 || k == Nz )
+    {
+            int Tk = (k<0) ? (Tk = k + 1) : (Tk = k - 1);
+            typ = checkEdgeSurface(idHex, i, j, Tk, v);
+            if (typ != -1 ) return typ;
+    }
+    counterHexa--;
+    return typ;
+}
+
 int Interpolate_direct::checkForHexaNeighbours(int idHex, int i, int j, int k, D3vector v)
 {
     counterHexa++;
diff --git a/program/source/interpol/interpol.h b/program/source/interpol/interpol.h
index 1f6bd95b774c983432edb0a7a2e96aeecfd29f78..f581b48579140cee3a7569ba56d2a12ae78857e4 100644
--- a/program/source/interpol/interpol.h
+++ b/program/source/interpol/interpol.h
@@ -418,6 +418,7 @@ class Interpolate_direct {
      *
     **/
     void find_cell(D3vector v);
+    void find_surface_cell(D3vector v);
     /**
      * Print a vtk file with a box, surrounding the cell.
     **/
@@ -457,9 +458,12 @@ class Interpolate_direct {
     int getTet(){return typ_tet;}
     int getHex(){return idHexNow;}
 
+    D3vector bilinearInterpolation(D3vector v,D3vector a,D3vector b,D3vector c,D3vector d);
     D3vector trilinarInterpolation(D3vector v, int id_Hex,int i,  int j,  int k );
         bool vectorInBox(D3vector vWSD, D3vector vENT, D3vector v, double eps = 1e-10);
         int checkBox(int idHex, int i, int j, int k, D3vector v);
+        int checkBoxSurface(int idHex, int i, int j, int k, D3vector v);
+
     private:
       int idHexPrev{-1}, iPrev{-1}, jPrev{-1}, kPrev{-1};
       int idHexPrevPrevPrev{-1}, iPrevPrevPrev{-1}, jPrevPrevPrev{-1}, kPrevPrevPrev{-1};
@@ -477,6 +481,7 @@ class Interpolate_direct {
       D3vector cWNT, cENT;
       Blockgrid    *blockgrid;
       std::vector<std::vector<std::vector<D3vector> > > arrayBoxWSDENT;
+      std::vector<std::vector<bool > > isOuterBoundaryFlag;
 
       std::vector<std::vector<std::vector<int> > > array_box_boundary;
       std::vector<std::vector<std::vector<int> > > array_point_boundary;
@@ -502,10 +507,14 @@ private:
       void setPrevPrevIndex();
       void setPrevPrevPrevIndex();
       int checkForHexaNeighbours(int idHex, int i, int j, int k, D3vector v);
+      int checkForHexaNeighboursSurface(int idHex, int i, int j, int k, D3vector v);
       int checkBoxSurrounding(int idHex, int i, int j, int k, D3vector v);
       int checkBoxSurroundingOptimized(int idHex, int i, int j, int k, D3vector v, bool neglectBadLambda = false);
+      int checkBoxSurroundingSurface(int idHex, int i, int j, int k, D3vector v, bool neglectBadLambda = false);
       int checkCorner(int idHex, int i, int j, int k, D3vector v);
+      int checkCornerSurface(int idHex, int i, int j, int k, D3vector v);
       int checkEdge(int idHex, int i, int j, int k, D3vector v);
+      int checkEdgeSurface(int idHex, int i, int j, int k, D3vector v);
       bool checkOverlapOfBoxes(D3vector vWSD, D3vector vENT, D3vector wWSD, D3vector wENT);
       double calculateOverlapOfBoxes(D3vector vWSD, D3vector vENT, D3vector wWSD, D3vector wENT);
 
@@ -553,6 +562,19 @@ DTyp Interpolate_direct::evaluate(Variable<DTyp> &u)
                               du.WNT(),du.WND(),du.EST(),du.END());
      if(typ==6) returnVal = interpolate_in_tet_trilinear(lambda,du.END(),du.ESD(),du.WSD(),du.WND(),
                                                            du.WNT(),du.WST(),du.EST(),du.ENT());
+     if(typ==7) returnVal = interpolate_in_tet(lambda,du.EST(),du.ESD(),du.ENT(),0.0);
+     if(typ==8) returnVal = interpolate_in_tet(lambda,du.END(),du.ESD(),du.ENT(),0.0);
+     if(typ==9) returnVal = interpolate_in_tet(lambda,du.WND(),du.END(),du.WSD(),0.0);
+     if(typ==10) returnVal = interpolate_in_tet(lambda,du.ESD(),du.END(),du.WSD(),0.0);
+     if(typ==11) returnVal = interpolate_in_tet(lambda,du.ENT(),du.WNT(),du.EST(),0.0);
+     if(typ==12) returnVal = interpolate_in_tet(lambda,du.WST(),du.WNT(),du.EST(),0.0);
+     if(typ==13) returnVal = interpolate_in_tet_bilinear(lambda,du.WND(),du.END(),du.WSD(),du.ESD());
+     if(typ==14) returnVal = interpolate_in_tet_bilinear(lambda,du.ENT(),du.WNT(),du.WST(),du.EST());
+
+
+
+
+
    }
    //    D3vector cWSD = {1,1,0};      // 1,1,0 : x2
    //    D3vector cESD = {2,0,-1};     // 1,0,0 : x1
diff --git a/program/source/math_lib/math_lib.cc b/program/source/math_lib/math_lib.cc
index 350dff42728f40b558290cf65a1b8f67d95045d9..7563dc803aadcd15654ba903371a19e4d0f1f2d1 100644
--- a/program/source/math_lib/math_lib.cc
+++ b/program/source/math_lib/math_lib.cc
@@ -54,6 +54,34 @@ double calc_maximal_face_angle(const D3vector& v0,
 		 angle_between_faces(v0,v1,v3,v2)));
 }
 
+D3matrix rotationMatrix(D3vector vIn, D3vector vOut)
+{
+  //calculates rotation matrix, which rotates vIn, such that is points into direction vOut
+    if (D3VectorNorm(vIn) == 0 || D3VectorNorm(vOut) == 0)
+    {
+        return D3matrix();
+    }
+    D3vector cross = cross_product(vOut,vIn);
+    double normed = D3VectorNorm(cross_product(vOut,vIn));
+    D3vector orthogonal = cross / normed;
+    double alpha = atan2(normed,product(vOut,vIn));
+
+    double s = sin(alpha);
+    double c = cos(alpha);
+    double mc = 1.0 - c;
+    double x = orthogonal.x;
+    double y = orthogonal.y;
+    double z  = orthogonal.z;
+
+
+    D3vector cx(c + x * x * mc,x * y * mc + z * s,x * z * mc - y * s); // first column
+    D3vector cy(x * y * mc - z * s,c + y * y * mc,y * z * mc + x * s); // second column
+    D3vector cz(x * z * mc + y * s,y * z * mc - x * s,c + z * z * mc); // third column
+
+    D3matrix ret(cx,cy,cz);
+    ret.transpose();
+    return ret;
+}
 
 ////////////////////////////////////
 //    lambda of p in tet
@@ -72,6 +100,7 @@ D3vector lambda_of_p_in_tet(D3vector p,
 }
 
 
+
 ////////////////////////////////////
 //    D3vector
 ////////////////////////////////////
diff --git a/program/source/math_lib/math_lib.h b/program/source/math_lib/math_lib.h
index dfc3f6453a9d92c2f9b3582563226f29511058cf..419718c880637f7c911d26eefd369ceb5505c723 100644
--- a/program/source/math_lib/math_lib.h
+++ b/program/source/math_lib/math_lib.h
@@ -153,7 +153,12 @@ class D3matrix {
   D3matrix(D3vector cx, D3vector cy, D3vector cz) : 
     x1(cx.x), y1(cy.x), z1(cz.x),
     x2(cx.y), y2(cy.y), z2(cz.y),
-    x3(cx.z), y3(cy.z), z3(cz.z)   {};
+    x3(cx.z), y3(cy.z), z3(cz.z)   {}
+
+  D3matrix() :
+    x1(1), y1(0), z1(0),
+    x2(0), y2(1), z2(0),
+    x3(0), y3(0), z3(1)   {}
 
   double Determinante() {
     return   (x1 * (y2*z3 - y3*z2) - y1 * (x2*z3 - x3*z2) + z1 * (x2*y3 - x3*y2));
@@ -225,6 +230,9 @@ class D3matrix {
       return D3matrix(cx,cy,cz);
 
   }
+
+
+
   D3vector vectorMultiply(D3vector m)
   {
 //      D3vector res = {x1 * m.x + x2 * m.x + x3 * m.x,
@@ -300,7 +308,7 @@ class D3matrix {
              for (int i = order - 1; i > 0; i--) {
 
                   //Swapping each and every element of the two rows
-                 if (a[i - 1][0] < a[i][0] &&  a[i][0]!=0)
+                 if (a[i - 1][0] < a[i][0])// &&  a[i][0]!=0)
                   for (int j = 0; j < 2 * order; j++) {
 
                          // Swapping of the row, if above
@@ -335,6 +343,10 @@ class D3matrix {
                          for (int k = 0; k < 2 * order; k++) {
 
                              a[j][k] -= a[i][k] * temp;
+//                             if (fabs(a[j][k]) < 1e-20 )
+//                             {
+//                                 std::cout << "is small???";
+//                             }
                          }
                      }
                  }
@@ -343,14 +355,18 @@ class D3matrix {
              // Multiply each row by a nonzero integer.
              // Divide row element by the diagonal element
              for (int i = 0; i < order; i++) {
-                 if (a[i][i] == 0)
-                 {
-                     std::cout << "debug here";
-                 }
+//                 if (a[i][i] == 0)
+//                 {
+//                     std::cout << "debug here";
+//                 }
                  temp = a[i][i];
                  for (int j = 0; j < 2 * order; j++) {
 
                      a[i][j] = a[i][j] / temp;
+//                     if (a[i][j] == 0)
+//                     {
+//                         std::cout << "is zero here";
+//                     }
                  }
              }
 //             std::cout << "inverted matrix : " << std::endl;
@@ -392,10 +408,17 @@ D3vector lambda_of_p_in_tet(D3vector p,
 template <class DTyp>
 DTyp interpolate_in_tet(D3vector lambda,
 			DTyp vA, DTyp vB,
-			DTyp vC, DTyp vD) {
+            DTyp vC, DTyp vD) {
+  return vA + (vB-vA) * lambda.x + (vC-vA) * lambda.y + (vD-vA) * lambda.z;
+}
+
+inline D3vector interpolate_in_tet_D3vector(D3vector lambda,
+            D3vector vA, D3vector vB,
+            D3vector vC, D3vector vD) {
   return vA + (vB-vA) * lambda.x + (vC-vA) * lambda.y + (vD-vA) * lambda.z;
 }
 
+
 template <class DTyp>
 DTyp interpolate_in_tet_trilinear(D3vector lambda,
                                   DTyp x0, DTyp x1,
@@ -417,6 +440,20 @@ DTyp interpolate_in_tet_trilinear(D3vector lambda,
   //  return vA + (vB-vA) * lambda.x + (vC-vA) * lambda.y + (vD-vA) * lambda.z;
 }
 
+template <class DTyp>
+DTyp interpolate_in_tet_bilinear(D3vector lambda,
+                                 DTyp x1, DTyp x2,
+                                 DTyp x3, DTyp x4)
+{
+    DTyp A = x1;
+    DTyp B = x2-x1;
+    DTyp C = x3-x1;
+    DTyp D = x4-x2+x1-x3;
+    DTyp R = A + lambda.x * B + lambda.y * C + lambda.x * lambda.y * D;
+    return R;
+}
+
+
 //////////////////////////////////////////////////////////////////////
 // 3. geometric operators for 3D vectors
 
@@ -483,6 +520,7 @@ inline double angle_between_vectors_rad(const D3vector& va,
     return acos(var);
 }
 
+
 inline double max_interior_angel_of_triangle(const D3vector& va,
 					     const D3vector& vb,
 					     const D3vector& vc) {
@@ -513,6 +551,7 @@ double calc_maximal_face_angle(const D3vector& va,
 
 
 
+D3matrix rotationMatrix(D3vector vIn, D3vector vOut);
 
 //////////////////////////////////////////////
 // Implementierung einiger Memberfunktionen