Une MAJ de sécurité est nécessaire sur notre version actuelle. Elle sera effectuée lundi 02/08 entre 12h30 et 13h. L'interruption de service devrait durer quelques minutes (probablement moins de 5 minutes).

Commit 54582706 authored by BRAMAS Berenger's avatar BRAMAS Berenger
Browse files

Improve parallel validation, and add a new method for remote P2P

parent c8df5f72
......@@ -99,6 +99,19 @@ public:
ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
ContainerClass* const directNeighborsParticles[27], const int size) = 0;
/**
* P2P
* Particles to particles
* @param inLeafPosition tree coordinate of the leaf
* @param targets current boxe targets particles
* @param sources current boxe sources particles (can be == to targets)
* @param directNeighborsParticles the particles from direct neighbors (this is an array of list)
* @param size the number of direct neighbors
*/
virtual void P2PRemote(const FTreeCoordinate& inLeafPosition,
ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
ContainerClass* const directNeighborsParticles[27], const int size) { std::cout << "Error, implement P2PRemote!" << std::endl; };
};
......
......@@ -66,6 +66,13 @@ public:
}
/** Do nothing */
virtual void P2PRemote(const FTreeCoordinate& ,
ContainerClass* const FRestrict , const ContainerClass* const FRestrict ,
ContainerClass* const [27], const int ){
}
};
......
......@@ -113,6 +113,27 @@ public:
}
}
/** After Downward */
void P2PRemote(const FTreeCoordinate& ,
ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
ContainerClass* const directNeighborsParticles[27], const int ){
// Each particles targeted is impacted by the particles sources
long long int inc = 0;
for(int idx = 0 ; idx < 27 ; ++idx){
if( directNeighborsParticles[idx] ){
inc += directNeighborsParticles[idx]->getSize();
}
}
typename ContainerClass::BasicIterator iter(*targets);
while( iter.hasNotFinished() ){
iter.data().setDataDown(iter.data().getDataDown() + inc);
iter.gotoNext();
}
}
};
......
......@@ -915,7 +915,12 @@ private:
/////////////////////////////////////////////////////////////////////////////
// Direct
/////////////////////////////////////////////////////////////////////////////
struct LeafData{
MortonIndex index;
CellClass* cell;
ContainerClass* targets;
ContainerClass* sources;
};
/** P2P */
void directPass(){
FTRACE( FTrace::FFunction functionTrace(__FUNCTION__, "Fmm" , __FILE__ , __LINE__) );
......@@ -946,6 +951,7 @@ private:
memset(globalReceiveMap, 0, sizeof(int) * nbProcess * nbProcess);
FBoolArray leafsNeedOther(this->numberOfLeafs);
int countNeedOther = 0;
{
FTRACE( FTrace::FRegion regionTrace( "Preprocess" , __FUNCTION__ , __FILE__ , __LINE__) );
......@@ -1008,6 +1014,7 @@ private:
if(needOther){
leafsNeedOther.set(idxLeaf,true);
++countNeedOther;
}
}
......@@ -1059,15 +1066,9 @@ private:
int shapeLeaf[SizeShape];
memset(shapeLeaf,0,SizeShape*sizeof(int));
struct LeafData{
MortonIndex index;
CellClass* cell;
ContainerClass* targets;
ContainerClass* sources;
};
LeafData* const leafsDataArray = new LeafData[this->numberOfLeafs];
FBoolArray leafsNeedOtherShaped(this->numberOfLeafs);
FVector<LeafData> leafsNeedOtherData(countNeedOther);
// split data
{
......@@ -1106,7 +1107,7 @@ private:
leafsDataArray[startPosAtShape[shapePosition]].cell = myLeafs[idxInArray].getCurrentCell();
leafsDataArray[startPosAtShape[shapePosition]].targets = myLeafs[idxInArray].getCurrentListTargets();
leafsDataArray[startPosAtShape[shapePosition]].sources = myLeafs[idxInArray].getCurrentListSrc();
if( leafsNeedOther.get(idxLeaf) ) leafsNeedOtherShaped.set(startPosAtShape[shapePosition], true);
if( leafsNeedOther.get(idxLeaf) ) leafsNeedOtherData.push(leafsDataArray[startPosAtShape[shapePosition]]);
++startPosAtShape[shapePosition];
}
......@@ -1133,17 +1134,15 @@ private:
for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){
const int endAtThisShape = shapeLeaf[idxShape] + previous;
#pragma omp for schedule(dynamic)
#pragma omp for
for(int idxLeafs = previous ; idxLeafs < endAtThisShape ; ++idxLeafs){
if(!leafsNeedOtherShaped.get(idxLeafs)){
LeafData& currentIter = leafsDataArray[idxLeafs];
myThreadkernels.L2P(currentIter.cell, currentIter.targets);
// need the current particles and neighbors particles
const int counter = tree->getLeafsNeighbors(neighbors, currentIter.cell->getCoordinate(), LeafIndex);
myThreadkernels.P2P( currentIter.cell->getCoordinate(),currentIter.targets,
currentIter.sources, neighbors, counter);
}
LeafData& currentIter = leafsDataArray[idxLeafs];
myThreadkernels.L2P(currentIter.cell, currentIter.targets);
// need the current particles and neighbors particles
const int counter = tree->getLeafsNeighbors(neighbors, currentIter.cell->getCoordinate(), LeafIndex);
myThreadkernels.P2P( currentIter.cell->getCoordinate(),currentIter.targets,
currentIter.sources, neighbors, counter);
}
previous = endAtThisShape;
......@@ -1199,48 +1198,37 @@ private:
KernelClass& myThreadkernels = (*kernels[omp_get_thread_num()]);
// There is a maximum of 26 neighbors
ContainerClass* neighbors[27];
int previous = 0;
MortonIndex indexesNeighbors[27];
int indexArray[26];
// Box limite
const int limite = 1 << (this->OctreeHeight - 1);
const int nbLeafToProceed = leafsNeedOtherData.getSize();
for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){
const int endAtThisShape = shapeLeaf[idxShape] + previous;
#pragma omp for schedule(dynamic)
for(int idxLeafs = previous ; idxLeafs < endAtThisShape ; ++idxLeafs){
// Maybe need also data from other?
if(leafsNeedOtherShaped.get(idxLeafs)){
LeafData& currentIter = leafsDataArray[idxLeafs];
myThreadkernels.L2P(currentIter.cell, currentIter.targets);
memset( neighbors, 0, sizeof(ContainerClass*) * 27);
// need the current particles and neighbors particles
int counter = tree->getLeafsNeighbors(neighbors, currentIter.cell->getCoordinate(), LeafIndex);
#pragma omp for
for(int idxLeafs = 0 ; idxLeafs < nbLeafToProceed ; ++idxLeafs){
LeafData currentIter = leafsNeedOtherData[idxLeafs];
// Take possible data
MortonIndex indexesNeighbors[27];
int indexArray[26];
const int nbNeigh = getNeighborsIndexes(currentIter.index, limite, indexesNeighbors, indexArray);
// need the current particles and neighbors particles
int counter = 0;
memset( neighbors, 0, sizeof(ContainerClass*) * 27);
// Take possible data
const int nbNeigh = getNeighborsIndexes(currentIter.index, limite, indexesNeighbors, indexArray);
for(int idxNeigh = 0 ; idxNeigh < nbNeigh ; ++idxNeigh){
if(indexesNeighbors[idxNeigh] < intervals[idProcess].min || intervals[idProcess].max < indexesNeighbors[idxNeigh]){
ContainerClass*const hypotheticNeighbor = otherP2Ptree.getLeafSrc(indexesNeighbors[idxNeigh]);
if(hypotheticNeighbor){
neighbors[ indexArray[idxNeigh] ] = hypotheticNeighbor;
++counter;
}
}
for(int idxNeigh = 0 ; idxNeigh < nbNeigh ; ++idxNeigh){
if(indexesNeighbors[idxNeigh] < intervals[idProcess].min || intervals[idProcess].max < indexesNeighbors[idxNeigh]){
ContainerClass*const hypotheticNeighbor = otherP2Ptree.getLeafSrc(indexesNeighbors[idxNeigh]);
if(hypotheticNeighbor){
neighbors[ indexArray[idxNeigh] ] = hypotheticNeighbor;
++counter;
}
myThreadkernels.P2P( currentIter.cell->getCoordinate(), currentIter.targets,
currentIter.sources, neighbors, counter);
}
}
previous = endAtThisShape;
myThreadkernels.P2PRemote( currentIter.cell->getCoordinate(), currentIter.targets,
currentIter.sources, neighbors, counter);
}
}
for(int idxProc = 0 ; idxProc < nbProcess ; ++idxProc){
......
......@@ -998,11 +998,15 @@ private:
}
/////////////////////////////////////////////////////////////////////////////
// Direct
/////////////////////////////////////////////////////////////////////////////
struct LeafData{
MortonIndex index;
CellClass* cell;
ContainerClass* targets;
ContainerClass* sources;
};
/** P2P */
void directPass(){
FTRACE( FTrace::FFunction functionTrace(__FUNCTION__, "Fmm" , __FILE__ , __LINE__) );
......@@ -1033,6 +1037,7 @@ private:
memset(globalReceiveMap, 0, sizeof(int) * nbProcess * nbProcess);
FBoolArray leafsNeedOther(this->numberOfLeafs);
int countNeedOther = 0;
{
FTRACE( FTrace::FRegion regionTrace( "Preprocess" , __FUNCTION__ , __FILE__ , __LINE__) );
......@@ -1059,7 +1064,7 @@ private:
int alreadySent[nbProcess];
MortonIndex indexesNeighbors[26];
int uselessIndexInArray[26];
int uselessIndexArray[26];
for(int idxLeaf = 0 ; idxLeaf < this->numberOfLeafs ; ++idxLeaf){
FTreeCoordinate center;
......@@ -1068,9 +1073,9 @@ private:
memset(alreadySent, 0, sizeof(int) * nbProcess);
bool needOther = false;
const int nbNeigh = getNeighborsIndexes(iterArray[idxLeaf].getCurrentGlobalCoordinate(), limite, indexesNeighbors, uselessIndexInArray);
const int neighCount = getNeighborsIndexes(iterArray[idxLeaf].getCurrentGlobalCoordinate(), limite, indexesNeighbors, uselessIndexArray);
for(int idxNeigh = 0 ; idxNeigh < nbNeigh ; ++idxNeigh){
for(int idxNeigh = 0 ; idxNeigh < neighCount ; ++idxNeigh){
if(indexesNeighbors[idxNeigh] < intervals[idProcess].min || intervals[idProcess].max < indexesNeighbors[idxNeigh]){
needOther = true;
......@@ -1095,6 +1100,7 @@ private:
if(needOther){
leafsNeedOther.set(idxLeaf,true);
++countNeedOther;
}
}
......@@ -1132,7 +1138,6 @@ private:
}
}
delete[] toSend;
}
FDEBUG(prepareCounter.tac());
......@@ -1148,15 +1153,9 @@ private:
int shapeLeaf[SizeShape];
memset(shapeLeaf,0,SizeShape*sizeof(int));
struct LeafData{
MortonIndex index;
CellClass* cell;
ContainerClass* targets;
ContainerClass* sources;
};
LeafData* const leafsDataArray = new LeafData[this->numberOfLeafs];
FBoolArray leafsNeedOtherShaped(this->numberOfLeafs);
FVector<LeafData> leafsNeedOtherData(countNeedOther);
// split data
{
......@@ -1195,7 +1194,7 @@ private:
leafsDataArray[startPosAtShape[shapePosition]].cell = myLeafs[idxInArray].getCurrentCell();
leafsDataArray[startPosAtShape[shapePosition]].targets = myLeafs[idxInArray].getCurrentListTargets();
leafsDataArray[startPosAtShape[shapePosition]].sources = myLeafs[idxInArray].getCurrentListSrc();
if( leafsNeedOther.get(idxLeaf) ) leafsNeedOtherShaped.set(startPosAtShape[shapePosition], true);
if( leafsNeedOther.get(idxLeaf) ) leafsNeedOtherData.push(leafsDataArray[startPosAtShape[shapePosition]]);
++startPosAtShape[shapePosition];
}
......@@ -1222,17 +1221,15 @@ private:
for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){
const int endAtThisShape = shapeLeaf[idxShape] + previous;
#pragma omp for schedule(dynamic)
#pragma omp for
for(int idxLeafs = previous ; idxLeafs < endAtThisShape ; ++idxLeafs){
if(!leafsNeedOtherShaped.get(idxLeafs)){
LeafData& currentIter = leafsDataArray[idxLeafs];
myThreadkernels.L2P(currentIter.cell, currentIter.targets);
// need the current particles and neighbors particles
const int counter = tree->getPeriodicLeafsNeighbors(neighbors, currentIter.cell->getCoordinate(), LeafIndex);
myThreadkernels.P2P( currentIter.cell->getCoordinate(), currentIter.targets,
currentIter.sources, neighbors, counter);
}
LeafData& currentIter = leafsDataArray[idxLeafs];
myThreadkernels.L2P(currentIter.cell, currentIter.targets);
// need the current particles and neighbors particles
const int counter = tree->getPeriodicLeafsNeighbors(neighbors, currentIter.cell->getCoordinate(), LeafIndex);
myThreadkernels.P2P( currentIter.cell->getCoordinate(), currentIter.targets,
currentIter.sources, neighbors, counter);
}
previous = endAtThisShape;
......@@ -1288,56 +1285,37 @@ private:
KernelClass& myThreadkernels = (*kernels[omp_get_thread_num()]);
// There is a maximum of 26 neighbors
ContainerClass* neighbors[27];
MortonIndex indexesNeighbors[26];
int indexInArray[26];
int previous = 0;
MortonIndex indexesNeighbors[27];
int indexArray[26];
// Box limite
const int limite = 1 << (this->OctreeHeight - 1);
const int nbLeafToProceed = leafsNeedOtherData.getSize();
for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){
const int endAtThisShape = shapeLeaf[idxShape] + previous;
#pragma omp for
for(int idxLeafs = 0 ; idxLeafs < nbLeafToProceed ; ++idxLeafs){
LeafData currentIter = leafsNeedOtherData[idxLeafs];
#pragma omp for schedule(dynamic)
for(int idxLeafs = previous ; idxLeafs < endAtThisShape ; ++idxLeafs){
// Maybe need also data from other?
if(leafsNeedOtherShaped.get(idxLeafs)){
LeafData& currentIter = leafsDataArray[idxLeafs];
myThreadkernels.L2P(currentIter.cell, currentIter.targets);
// need the current particles and neighbors particles
int counter = 0;
memset( neighbors, 0, sizeof(ContainerClass*) * 27);
memset( neighbors, 0, sizeof(ContainerClass*) * 27);
// Take possible data
const int nbNeigh = getNeighborsIndexes(currentIter.cell->getCoordinate(), limite, indexesNeighbors, indexArray);
// need the current particles and neighbors particles
// int counter = tree->getLeafsNeighbors(neighbors, neighborsIndex, currentIter.index, LeafIndex);
int counter = 0;
memset(neighbors, 0, 27 * sizeof(ContainerClass*));
// Take possible data
const int nbNeigh = getNeighborsIndexes(currentIter.cell->getCoordinate(), limite, indexesNeighbors, indexInArray);
for(int idxNeigh = 0 ; idxNeigh < nbNeigh ; ++idxNeigh){
if(indexesNeighbors[idxNeigh] < intervals[idProcess].min || intervals[idProcess].max < indexesNeighbors[idxNeigh]){
ContainerClass*const hypotheticNeighbor = otherP2Ptree.getLeafSrc(indexesNeighbors[idxNeigh]);
if(hypotheticNeighbor){
neighbors[ indexInArray[idxNeigh] ] = hypotheticNeighbor;
++counter;
}
}
else{
ContainerClass*const hypotheticNeighbor = tree->getLeafSrc(indexesNeighbors[idxNeigh]);
if(hypotheticNeighbor){
neighbors[ indexInArray[idxNeigh] ] = hypotheticNeighbor;
++counter;
}
}
for(int idxNeigh = 0 ; idxNeigh < nbNeigh ; ++idxNeigh){
if(indexesNeighbors[idxNeigh] < intervals[idProcess].min || intervals[idProcess].max < indexesNeighbors[idxNeigh]){
ContainerClass*const hypotheticNeighbor = otherP2Ptree.getLeafSrc(indexesNeighbors[idxNeigh]);
if(hypotheticNeighbor){
neighbors[ indexArray[idxNeigh] ] = hypotheticNeighbor;
++counter;
}
myThreadkernels.P2P( currentIter.cell->getCoordinate(), currentIter.targets,
currentIter.sources, neighbors, counter);
}
}
previous = endAtThisShape;
myThreadkernels.P2PRemote( currentIter.cell->getCoordinate(), currentIter.targets,
currentIter.sources, neighbors, counter);
}
}
for(int idxProc = 0 ; idxProc < nbProcess ; ++idxProc){
......
......@@ -204,17 +204,44 @@ public:
ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
ContainerClass* const directNeighborsParticles[27], const int /*size*/){
if( periodicLevels == 0 && targets == sources ){
P2PNoTsm(targets, directNeighborsParticles);
if( periodicLevels == 0 ){
P2PNoPeriodic(targets, sources, directNeighborsParticles);
}
else if(periodicLevels == 0 /* && targets != sources */) {
P2PTsm(targets, sources, directNeighborsParticles);
}
else if( targets == sources /* && periodicLevels != 0 */){
P2PNoTsmPeriodic(inLeafPosition, targets, directNeighborsParticles);
else {
P2PPeriodic(inLeafPosition, targets, sources, directNeighborsParticles);
}
else { // if(periodicLevels != 0 && periodicLevels != 0 ) {
P2PTsmPeriodic(inLeafPosition, targets, sources, directNeighborsParticles);
}
/** This P2P has to be used when target != sources
* It will proceed an direct interation no mutual
*
* It takes all the target particles from the current leaf,
* then it computes the sources/targets interaction in this leaf,
* then it computes the sources/targets inteactions between this leaf and the
* neighbors.
*/
void P2PRemote(const FTreeCoordinate& ,
ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict ,
ContainerClass* const directNeighborsParticles[27], const int /*size*/){
// TODO manage for periodic
for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < 27 ; ++idxDirectNeighbors){
if( directNeighborsParticles[idxDirectNeighbors] ){
// For all particles in current leaf
typename ContainerClass::BasicIterator iterTarget(*targets);
while( iterTarget.hasNotFinished() ){
ParticleClass target( iterTarget.data() );
// For all the particles in the other leaf
typename ContainerClass::BasicIterator iterSource(*directNeighborsParticles[idxDirectNeighbors]);
while( iterSource.hasNotFinished() ){
directInteraction(&target, iterSource.data());
iterSource.gotoNext();
}
// Set data and progress
iterTarget.setData(target);
iterTarget.gotoNext();
}
}
}
}
......@@ -232,27 +259,27 @@ private:
* then it computes the sources/targets inteactions between this leaf and the
* neighbors.
*/
void P2PTsm(ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
void P2PNoPeriodic(ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
ContainerClass* const directNeighborsParticles[27]){
const bool isNotTsm = (targets != sources);
if( isNotTsm ) { // Compute interaction in this leaf
{
typename ContainerClass::BasicIterator iterTarget(*targets);
while( iterTarget.hasNotFinished() ){
// We copy the target particle to work with a particle in the heap
ParticleClass target( iterTarget.data() );
{ // Compute interaction in this leaf
typename ContainerClass::BasicIterator iterTarget(*targets);
while( iterTarget.hasNotFinished() ){
// We copy the target particle to work with a particle in the heap
ParticleClass target( iterTarget.data() );
// For all the source particles in the same leaf
typename ContainerClass::ConstBasicIterator iterSameBox(*sources);
while( iterSameBox.hasNotFinished() ){
directInteraction(&target, iterSameBox.data());
iterSameBox.gotoNext();
// For all the source particles in the same leaf
typename ContainerClass::ConstBasicIterator iterSameBox(*sources);
while( iterSameBox.hasNotFinished() ){
directInteraction(&target, iterSameBox.data());
iterSameBox.gotoNext();
}
// Set data and progress
iterTarget.setData(target);
iterTarget.gotoNext();
}
// Set data and progress
iterTarget.setData(target);
iterTarget.gotoNext();
}
}
{ // Compute interactions with other leaves
// For all the neigbors leaves
for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < 27 ; ++idxDirectNeighbors){
if( directNeighborsParticles[idxDirectNeighbors] ){
......@@ -273,37 +300,25 @@ private:
}
}
}
}
else { // Compute interaction in this leaf
{
typename ContainerClass::BasicIterator iterTarget(*targets);
while( iterTarget.hasNotFinished() ){
// We copy the target particle to work with a particle in the heap
ParticleClass target( iterTarget.data() );
/** This P2P has to be used when target == sources
* It will proceed a direct interation >> mutual
*
* It takes all the particles from the current leaf,
* then it computes the interactions in this leaf,
* then it computes the inteactions between this leaf and the
* neighbors.
*/
void P2PNoTsm(ContainerClass* const FRestrict targets,
ContainerClass* const directNeighborsParticles[27] ){
{ // Compute interaction in this leaf
typename ContainerClass::BasicIterator iterTarget(*targets);
while( iterTarget.hasNotFinished() ){
// We copy the target particle to work with a particle in the heap
ParticleClass target( iterTarget.data() );
// For all particles after the current one
typename ContainerClass::BasicIterator iterSameBox = iterTarget;
iterSameBox.gotoNext();
while( iterSameBox.hasNotFinished() ){
directInteractionMutual(&target, &iterSameBox.data());
// For all particles after the current one
typename ContainerClass::BasicIterator iterSameBox = iterTarget;
iterSameBox.gotoNext();
while( iterSameBox.hasNotFinished() ){
directInteractionMutual(&target, &iterSameBox.data());
iterSameBox.gotoNext();
}
// Set data and progress
iterTarget.setData(target);
iterTarget.gotoNext();
}
// Set data and progress
iterTarget.setData(target);
iterTarget.gotoNext();
}
}
{ // Compute interactions with other leaves
// For all the neigbors leaves
for(int idxDirectNeighbors = 0 ; idxDirectNeighbors <= 13 ; ++idxDirectNeighbors){
if( directNeighborsParticles[idxDirectNeighbors] ){
......@@ -315,7 +330,6 @@ private:
typename ContainerClass::BasicIterator iterSource(*directNeighborsParticles[idxDirectNeighbors]);
while( iterSource.hasNotFinished() ){
directInteractionMutual(&target, &iterSource.data());
iterSource.gotoNext();
}
// Set data and progress
......@@ -336,14 +350,15 @@ private:
* then it computes the sources/targets inteactions between this leaf and the
* neighbors.
*/
void P2PTsmPeriodic(const FTreeCoordinate& inLeafPosition,
void P2PPeriodic(const FTreeCoordinate& inLeafPosition,
ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
ContainerClass* const directNeighborsParticles[27]){
const int limite = FMath::pow2(treeHeight-1) - 1;
if( inLeafPosition.getX() == 0 || inLeafPosition.getX() == limite ||
inLeafPosition.getY() == 0 || inLeafPosition.getY() == limite ||
inLeafPosition.getZ() == 0 || inLeafPosition.getZ() == limite){
{ // Compute interaction in this leaf
const bool isNotTsm = (targets != sources);
if( isNotTsm ) { // Compute interaction in this leaf
typename ContainerClass::BasicIterator iterTarget(*targets);
while( iterTarget.hasNotFinished() ){
// We copy the target particle to work with a particle in the heap
......@@ -360,84 +375,7 @@ private:
iterTarget.gotoNext();
}
}
{ // Compute interactions with other leaves
// For all the neigbors leaves
for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < 27 ; ++idxDirectNeighbors){
if( directNeighborsParticles[idxDirectNeighbors] ){
const int zrelatif = (idxDirectNeighbors%3) - 1;
const int yrelatif = ((idxDirectNeighbors%(3*3))/3)-1;
const int xrelatif = (idxDirectNeighbors / (3*3))-1;