diff --git a/Src/Files/FMpiTreeBuilder.hpp b/Src/Files/FMpiTreeBuilder.hpp
index a8cad4a61ed16c2b4fe05a9575bd55eac21e4baf..6a132c81c252072be411f87cb87d1e14d77e2fb3 100644
--- a/Src/Files/FMpiTreeBuilder.hpp
+++ b/Src/Files/FMpiTreeBuilder.hpp
@@ -324,6 +324,7 @@ public:
         return true;
     }
 
+
     template <class OctreeClass>
     static bool IntervalsToTree(OctreeClass& realTree, OctreeClass& treeInterval, const int myNbParticlesCounter){
         const int rank = MpiGetRank();
@@ -333,28 +334,13 @@ public:
         // We inform the master proc about the data we have
         //////////////////////////////////////////////////////////////////////////////////
 
-        FVector<ParticlesGroup> groups;
-        ParticleClass*const realParticles = myNbParticlesCounter?new ParticleClass[myNbParticlesCounter]:0;
-
         int nbLeafs = 0;
 
         // we might now have any particles in our interval
         if(myNbParticlesCounter){
             typename OctreeClass::Iterator octreeIterator(&treeInterval);
             octreeIterator.gotoBottomLeft();
-            int indexPart = 0;
             do{
-                typename ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets());
-                const MortonIndex indexAtThisLeaf = octreeIterator.getCurrentGlobalIndex();
-
-                groups.push(ParticlesGroup(octreeIterator.getCurrentListTargets()->getSize(),indexPart, indexAtThisLeaf));
-
-                while( iter.hasNotFinished() ){
-                    realParticles[indexPart] = iter.data();
-                    ++indexPart;
-                    iter.gotoNext();
-                }
-
                 ++nbLeafs;
             } while(octreeIterator.moveRight());
         }
@@ -412,150 +398,235 @@ public:
         const bool iDoNotHaveEnoughtToSendRight = myRightLeaf < leftLeafs;
         const bool iDoNotHaveEnoughtToSendLeft = leftLeafs + nbLeafs < myLeftLeaf;
 
-        ParticleClass* rpart(0);
-        int rpartSize(0);
 
-        // Do I need to send to right?
-        if(iNeedToSendToRight){
-            int iNeedToSend = leftLeafs + nbLeafs - myRightLeaf;
-            int iCanSend = nbLeafs;
-            int idxSend (0);
+        const int iNeedToSendLeftCount = myLeftLeaf - leftLeafs;
+        const int iCanSendToLeft = nbLeafs;
 
-            MPI_Send(&iNeedToSend, sizeof(int), MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
+        const int iNeedToSendRightCount = leftLeafs + nbLeafs - myRightLeaf;
+        const int iCanSendToRight = nbLeafs;
 
-            while(idxSend < iNeedToSend && idxSend < iCanSend){
-                MPI_Send(&groups[nbLeafs - idxSend - 1].number, sizeof(int), MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
-                MPI_Send(&realParticles[groups[nbLeafs - idxSend - 1].positionInArray], sizeof(ParticleClass) * groups[nbLeafs - idxSend - 1].number,
-                         MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
+        MPI_Request requests[10];
+        int iterRequest = 0;
 
-                ++idxSend;
-            }
-            // I need to wait (idxSend == iCanSend && idxSend < iNeedToSend)
-            if( iDoNotHaveEnoughtToSendRight ){ // I need to wait
-                int nbLeafsToRead(0);
-                receiveDataFromTag(sizeof(int), 0, &nbLeafsToRead);
-                for(int idxToRead = 0 ; idxToRead < nbLeafsToRead ; ++idxToRead){
-                    int nbPartToRead(0);
-                    receiveDataFromTag(sizeof(int), 0, &nbPartToRead);
-
-                    if(rpartSize < nbPartToRead){
-                        rpartSize = nbPartToRead;
-                        delete [] (reinterpret_cast<char*>(rpart));
-                        rpart = reinterpret_cast<ParticleClass*>(new char[nbPartToRead*sizeof(ParticleClass)]);
-                    }
+        int hasBeenSentToLeft = 0;
+        int hasBeenSentToRight = 0;
 
-                    receiveDataFromTag(nbPartToRead*sizeof(ParticleClass), 0, rpart);
-                    if(idxSend < iNeedToSend){
-                        MPI_Send(&nbPartToRead, sizeof(int), MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
-                        MPI_Send(rpart, sizeof(ParticleClass) * nbPartToRead, MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
+        char* particlesToSend = 0;
 
-                        ++idxSend;
-                    }
-                    else{
-                        //insert into tree
-                        for(int idxPart = 0 ; idxPart < nbPartToRead ; ++idxPart){
-                            realTree.insert(rpart[idxPart]);
-                        }
-                    }
+        ///////////////////////////////
+        // Manage data we already have
+        ///////////////////////////////
+
+        if(myNbParticlesCounter){
+            particlesToSend = new char[sizeof(ParticleClass) * myNbParticlesCounter + sizeof(int) * nbLeafs];
+            int idxWriteParticles = 0;
+
+            typename OctreeClass::Iterator octreeIterator(&treeInterval);
+            octreeIterator.gotoBottomLeft();
+
+            //Send to Left (the first leaves
+            if(iNeedToSendToLeft){
+                for(int idxLeaf = 0 ; idxLeaf < iNeedToSendLeftCount && idxLeaf < iCanSendToLeft ; ++idxLeaf){
+                    *(int*)&particlesToSend[idxWriteParticles] = octreeIterator.getCurrentListTargets()->getSize();
+                    idxWriteParticles += sizeof(int);
+
+                    memcpy(&particlesToSend[idxWriteParticles], octreeIterator.getCurrentListTargets()->data(), sizeof(ParticleClass) * octreeIterator.getCurrentListTargets()->getSize());
+                    idxWriteParticles += sizeof(ParticleClass) * octreeIterator.getCurrentListTargets()->getSize();
+
+                    octreeIterator.moveRight();
                 }
+
+                hasBeenSentToLeft = FMath::Min(iNeedToSendLeftCount, iCanSendToLeft);
+                MPI_Send(particlesToSend, idxWriteParticles, MPI_BYTE , rank - 1, 0, MPI_COMM_WORLD);
             }
-        }
-        // will I receive from left
-        if(iNeedToSendToLeft){
-            int iNeedToSend = myLeftLeaf - leftLeafs;
-            int iCanSend = nbLeafs;
-            int idxSend (0);
 
-            MPI_Send(&iNeedToSend, sizeof(int), MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
+            // Insert the particles I host and that belong to me
+            const int beginForMe = (iNeedToSendToLeft ? FMath::Min(iNeedToSendLeftCount,iCanSendToLeft) : 0);
+            const int endForMe = nbLeafs - (iNeedToSendToRight ? FMath::Min(iNeedToSendRightCount,iCanSendToRight) : 0);
+            for(int idxLeaf = beginForMe ; idxLeaf < endForMe ; ++idxLeaf){
+                typename ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets());
 
-            while(idxSend < iNeedToSend && idxSend < iCanSend){
-                MPI_Send(&groups[idxSend].number, sizeof(int), MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
-                MPI_Send(&realParticles[groups[idxSend].positionInArray], sizeof(ParticleClass) * groups[idxSend].number,
-                         MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
+                while( iter.hasNotFinished() ){
+                    realTree.insert(iter.data());
+                    iter.gotoNext();
+                }
 
-                ++idxSend;
+                octreeIterator.moveRight();
             }
-            // Can I do it now?
-            if( iDoNotHaveEnoughtToSendLeft ){
-                int nbLeafsToRead(0);
-                receiveDataFromTag(sizeof(int), 1, &nbLeafsToRead);
-                for(int idxToRead = 0 ; idxToRead < nbLeafsToRead ; ++idxToRead){
-                    int nbPartToRead(0);
-                    receiveDataFromTag(sizeof(int), 1, &nbPartToRead);
-
-                    if(rpartSize < nbPartToRead){
-                        rpartSize = nbPartToRead;
-                        delete [] (reinterpret_cast<char*>(rpart));
-                        rpart = reinterpret_cast<ParticleClass*>(new char[nbPartToRead*sizeof(ParticleClass)]);
-                    }
 
-                    receiveDataFromTag(nbPartToRead*sizeof(ParticleClass), 1, rpart);
-                    if(idxSend < iNeedToSend){
-                        MPI_Send(&nbPartToRead, sizeof(int), MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
-                        MPI_Send(rpart, sizeof(ParticleClass) * nbPartToRead, MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
+            //Send to Right (the right-est leaves
+            if(iNeedToSendToRight){
+                const int beginWriteIndex = idxWriteParticles;
 
-                        ++idxSend;
-                    }
-                    else{
-                        for(int idxPart = 0 ; idxPart < nbPartToRead ; ++idxPart){
-                            realTree.insert(rpart[idxPart]);
-                        }
-                    }
+                for(int idxLeaf = 0 ; idxLeaf < iNeedToSendRightCount && idxLeaf < iCanSendToRight ; ++idxLeaf){
+                    *(int*)&particlesToSend[idxWriteParticles] = octreeIterator.getCurrentListTargets()->getSize();
+                    idxWriteParticles += sizeof(int);
+
+                    memcpy(&particlesToSend[idxWriteParticles], octreeIterator.getCurrentListTargets()->data(), sizeof(ParticleClass) * octreeIterator.getCurrentListTargets()->getSize());
+                    idxWriteParticles += sizeof(ParticleClass) * octreeIterator.getCurrentListTargets()->getSize();
+
+                    octreeIterator.moveRight();
                 }
+
+                hasBeenSentToRight = FMath::Min(iNeedToSendRightCount, iCanSendToRight);
+                MPI_Isend( &particlesToSend[beginWriteIndex], idxWriteParticles - beginWriteIndex, MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD, &requests[iterRequest++]);
             }
         }
 
-        // If i will receive from left and I did no already have
-        if(!(iNeedToSendToRight && iDoNotHaveEnoughtToSendRight) && iWillReceiveFromLeft){
-            int nbLeafsToRead(0);
-            receiveDataFromTag(sizeof(int), 0, &nbLeafsToRead);
-            for(int idxToRead = 0 ; idxToRead < nbLeafsToRead ; ++idxToRead){
-                int nbPartToRead(0);
-                receiveDataFromTag(sizeof(int), 0, &nbPartToRead);
-                //printf("%d I will receive %d particles\n",rank, nbPartToRead);
-                if(rpartSize < nbPartToRead){
-                    rpartSize = nbPartToRead;
-                    delete [] (reinterpret_cast<char*>(rpart));
-                    rpart = reinterpret_cast<ParticleClass*>(new char[nbPartToRead*sizeof(ParticleClass)]);
-                }
+        char* toRecvFromLeft = 0;
+        char* toRecvFromRight = 0;
+        int countReceive = int(iWillReceiveFromLeft) + int(iWillReceiveFromRight);
+        int bytesRecvFromLeft = 0;
+        int bytesRecvFromRight = 0;
 
-                receiveDataFromTag(nbPartToRead*sizeof(ParticleClass), 0, rpart);
-                for(int idxPart = 0 ; idxPart < nbPartToRead ; ++idxPart){
-                    realTree.insert(rpart[idxPart]);
-                }
+        // Now prepare to receive data
+        while(countReceive--){
+            MPI_Status status;
+            MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
+            // receive from left
+            if(status.MPI_SOURCE == rank - 1){
+                MPI_Get_count( &status,  MPI_BYTE, &bytesRecvFromLeft);
+                toRecvFromLeft = new char[bytesRecvFromLeft];
+                MPI_Irecv(toRecvFromLeft, bytesRecvFromLeft, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, &requests[iterRequest++]);
+            }
+            // receive from right
+            else{
+                MPI_Get_count( &status,  MPI_BYTE, &bytesRecvFromRight);
+                toRecvFromRight = new char[bytesRecvFromRight];
+                MPI_Irecv(toRecvFromRight, bytesRecvFromRight, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, &requests[iterRequest++]);
             }
         }
-        // If i will receive from right and I did no already have
-        if(!(iNeedToSendToLeft && iDoNotHaveEnoughtToSendLeft) && iWillReceiveFromRight){
-            int nbLeafsToRead(0);
-            receiveDataFromTag(sizeof(int), 1, &nbLeafsToRead);
-            for(int idxToRead = 0 ; idxToRead < nbLeafsToRead ; ++idxToRead){
-                int nbPartToRead(0);
-                receiveDataFromTag(sizeof(int), 1, &nbPartToRead);
-                //printf("%d I will receive %d particles\n",rank, nbPartToRead);
-                if(rpartSize < nbPartToRead){
-                    rpartSize = nbPartToRead;
-                    delete [] (reinterpret_cast<char*>(rpart));
-                    rpart = reinterpret_cast<ParticleClass*>(new char[nbPartToRead*sizeof(ParticleClass)]);
+
+        ///////////////////////////////
+        // Wait send receive
+        ///////////////////////////////
+        MPI_Waitall(iterRequest, requests, 0);
+        // We can delete the buffer use to send our particles only
+        delete[] particlesToSend;
+        particlesToSend = 0;
+
+        ///////////////////////////////
+        // Process received data
+        // and transfer if needed
+        ///////////////////////////////
+        // We have to receive from right and transfere to left
+        int hasToBeReceivedFromLeft = leftLeafs - myLeftLeaf;
+        int hasToBeReceivedFromRight = myRightLeaf - (leftLeafs + nbLeafs);
+        int arrayIdxRight = 0;
+        int arrayIdxLeft = 0;
+
+        if(iDoNotHaveEnoughtToSendLeft){
+            do{
+                arrayIdxRight = 0;
+                while(arrayIdxRight < bytesRecvFromRight && hasBeenSentToLeft < iNeedToSendLeftCount){
+                    const int particlesInThisLeaf = *(int*)&toRecvFromRight[arrayIdxRight];
+                    arrayIdxRight += sizeof(int) + sizeof(ParticleClass) * particlesInThisLeaf;
+                    --hasToBeReceivedFromRight;
+                }
+                MPI_Send(toRecvFromRight, arrayIdxRight, MPI_BYTE , rank - 1, 0, MPI_COMM_WORLD);
+                if(hasBeenSentToLeft < iNeedToSendLeftCount){
+                    MPI_Status status;
+                    MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
+                    int status_size = 0;
+                    MPI_Get_count( &status,  MPI_BYTE, &status_size);
+                    if(bytesRecvFromRight < status_size){
+                        bytesRecvFromRight = status_size;
+                        delete[] toRecvFromRight;
+                        toRecvFromRight = new char[status_size];
+                    }
+                    MPI_Recv(toRecvFromRight, status_size, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                 }
+            } while(hasBeenSentToLeft < iNeedToSendLeftCount);
+        }
+        // We have to receive from left and transfere to right
+        else if(iDoNotHaveEnoughtToSendRight){
+            do{
+                arrayIdxLeft = 0;
+                while(arrayIdxLeft < bytesRecvFromLeft && hasBeenSentToRight < iNeedToSendRightCount){
+                    const int particlesInThisLeaf = *(int*)&toRecvFromLeft[arrayIdxLeft];
+                    arrayIdxLeft += sizeof(int) + sizeof(ParticleClass) * particlesInThisLeaf;
+                    --hasToBeReceivedFromLeft;
+                }
+                MPI_Send(toRecvFromLeft, arrayIdxLeft, MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
+                if(hasBeenSentToRight < iNeedToSendRightCount){
+                    MPI_Status status;
+                    MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
+                    int status_size = 0;
+                    MPI_Get_count( &status,  MPI_BYTE, &status_size);
+                    if(bytesRecvFromLeft < status_size){
+                        bytesRecvFromLeft = status_size;
+                        delete[] toRecvFromLeft;
+                        toRecvFromLeft = new char[status_size];
+                    }
+                    MPI_Recv(toRecvFromLeft, status_size, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+                }
+            } while(hasBeenSentToRight < iNeedToSendRightCount);
+        }
+
+        if(iWillReceiveFromLeft ){ // I need to wait
+            do{
+                while(arrayIdxLeft < bytesRecvFromLeft){
+                    const int particlesInThisLeaf = *(int*)&toRecvFromLeft[arrayIdxLeft];
+                    arrayIdxLeft += sizeof(int);
+                    ParticleClass*const particles = reinterpret_cast<ParticleClass*>(&toRecvFromLeft[arrayIdxLeft]);
+                    arrayIdxLeft += sizeof(ParticleClass) * particlesInThisLeaf;
+
+                    for( int idxPart = 0 ; idxPart < particlesInThisLeaf ; ++idxPart){
+                        realTree.insert( particles[ idxPart ] );
+                    }
 
-                receiveDataFromTag(nbPartToRead*sizeof(ParticleClass), 1, rpart);
-                for(int idxPart = 0 ; idxPart < nbPartToRead ; ++idxPart){
-                    realTree.insert(rpart[idxPart]);
+                    --hasToBeReceivedFromLeft;
                 }
-            }
+                arrayIdxLeft = 0;
+
+                if(hasToBeReceivedFromLeft){
+                    MPI_Status status;
+                    MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
+                    int status_size = 0;
+                    MPI_Get_count( &status,  MPI_BYTE, &status_size);
+                    if(bytesRecvFromLeft < status_size){
+                        bytesRecvFromLeft = status_size;
+                        delete[] toRecvFromLeft;
+                        toRecvFromLeft = new char[status_size];
+                    }
+                    MPI_Recv(toRecvFromLeft, status_size, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+                }
+            } while(hasToBeReceivedFromLeft);
         }
+        if(iWillReceiveFromRight){
+            do{
+                while(arrayIdxRight < bytesRecvFromRight){
+                    const int particlesInThisLeaf = *(int*)&toRecvFromRight[arrayIdxRight];
+                    arrayIdxRight += sizeof(int);
+                    ParticleClass*const particles = reinterpret_cast<ParticleClass*>(&toRecvFromRight[arrayIdxRight]);
+                    arrayIdxRight += sizeof(ParticleClass) * particlesInThisLeaf;
+
+                    for( int idxPart = 0 ; idxPart < particlesInThisLeaf ; ++idxPart){
+                        realTree.insert( particles[ idxPart ] );
+                    }
 
-        // insert the particles we already have
-        if(leftLeafs != totalNbLeafs){
-            for(int idxLeafInsert = FMath::Max(myLeftLeaf-leftLeafs,0) ; idxLeafInsert <  totalNbLeafs - rightLeafs - leftLeafs - FMath::Max(0,leftLeafs + nbLeafs - myRightLeaf) ; ++idxLeafInsert){
-                for(int idxPart = 0 ; idxPart < groups[idxLeafInsert].number ; ++idxPart){
-                    realTree.insert(realParticles[groups[idxLeafInsert].positionInArray + idxPart]);
+                    --hasToBeReceivedFromRight;
                 }
-            }
+                arrayIdxRight = 0;
+
+                if(hasToBeReceivedFromRight){
+                    MPI_Status status;
+                    MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
+                    int status_size = 0;
+                    MPI_Get_count( &status,  MPI_BYTE, &status_size);
+                    if(bytesRecvFromRight < status_size){
+                        bytesRecvFromRight = status_size;
+                        delete[] toRecvFromRight;
+                        toRecvFromRight = new char[status_size];
+                    }
+                    MPI_Recv(toRecvFromRight, status_size, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+                }
+            } while(hasToBeReceivedFromRight);
         }
 
-        delete [] reinterpret_cast<char*>(rpart);
+        // Delete reception buffers
+        delete[] toRecvFromLeft;
+        delete[] toRecvFromRight;
 
         return true;
     }