Attention une mise à jour du service Gitlab va être effectuée le mardi 18 janvier (et non lundi 17 comme annoncé précédemment) entre 18h00 et 18h30. Cette mise à jour va générer une interruption du service dont nous ne maîtrisons pas complètement la durée mais qui ne devrait pas excéder quelques minutes.

Commit 2d9785c7 authored by BRAMAS Berenger's avatar BRAMAS Berenger
Browse files
parents 902e39ad 52fab931
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
#ifndef FMPIBUFFERREADER_HPP
#define FMPIBUFFERREADER_HPP
#include "../Utils/FMpi.hpp"
/** @author Cyrille Piacibello
* This class provide the same features as FBufferWriter using MPI_Pack system
*
* Put some data
* then insert back if needed
* finally use data pointer as you like
*/
class FMpiBufferReader {
private:
//Classe FMpiVector, used only by FMpiBuffer
template<class ObjectType>
class FMpiVector {
protected :
static const int DefaultSize = 10;
ObjectType* array; //memory area
int capacity; //Capacity of the array
long int index; //current position in Byte !!
public:
FMpiVector():
array(0),
capacity(DefaultSize),
index(0){
array = reinterpret_cast<ObjectType*>(new char[sizeof(ObjectType)* DefaultSize]);
}
FMpiVector(const int inCapa):
array(0),
capacity(inCapa),
index(0){
array = reinterpret_cast<ObjectType*>(new char[sizeof(ObjectType)* inCapa]);
}
virtual ~FMpiVector(){
delete[] reinterpret_cast< char* >(array);
}
//To get the capacity
const int getCapacity() const{
return this->capacity;
}
//To get the array
ObjectType * data(){
return array;
}
const ObjectType * data() const{
return array;
}
//To delete all the element stored of the array
void clear(){
while(0 < index){
(&array[--index])->~ObjectType();
}
}
//To get how much space is used
long int getSize() const{
return this->index;
}
//To get how many objects are stored
int getObjectsSize(){
return (this->index / sizeof(ObjectType));
}
//To inc the index
//Usually used with array.incIndex(sizeof(my_object_stored));
void incIndex(const int inInc){
if(index + inInc > capacity){
fprintf(stderr,"Aborting : index array out of range\n");
exit(0);
}
else{
this->index+=inInc;
}
}
//To set the index
void setIndex(const int inInd){
if(inInd>capacity){
fprintf(stderr,"Aborting : index array out of range\n");
exit(0);
}
else{
this->index = inInd;
}
}
};
MPI_Comm comm;
FMpiVector<char> array;
public :
FMpiBufferReader(MPI_Comm inComm, const int inCapacity = 0):
comm(inComm),
array(inCapacity)
{}
/** Destructor
*/
virtual ~FMpiBufferReader(){
delete &array;
}
/** Get the memory area */
char* data(){
return array.data();
}
/** Get the memory area */
const char* data() const {
return array.data();
}
/** Size of the memory initialized */
int getSize() const{
return array.getSize();
}
/** Move the read index to a position */
void seek(const int inIndex){
array.setIndex(inIndex);
}
/** Get the read position */
int tell() const {
return array.getSize();
}
/** Get a value with memory cast */
template <class ClassType>
ClassType getValue(){
ClassType value;
long int currentIndex = array.getSize();
array.incIndex(sizeof(value));
MPI_Unpack(array.data(),sizeof(ClassType),&currentIndex,&value,1,FMpi::GetType(value),*comm);
return value;
}
/** Fill a value with memory cast */
template <class ClassType>
void fillValue(ClassType* const inValue){
int currentIndex = array.getSize();
array.incIndex(sizeof(ClassType));
MPI_Pack(inValue,1,FMpi::GetType(inValue),array.data(),array.getCapacity(),&currentIndex,*comm);
}
/** Fill one/many value(s) with memcpy */
template <class ClassType>
void fillArray(ClassType* const inArray, const int inSize){
int currentIndex = array.getSize();
array.incIndex(sizeof(ClassType) * inSize);
MPI_Pack(inArray,inSize,FMpi::GetType(inArray),array.data(),array.getCapacity(),&currentIndex,*comm);
}
/** Same as fillValue */
template <class ClassType>
FBufferReader& operator>>(ClassType& object){
fillValue(&object);
return *this;
}
};
#endif
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
#ifndef FMPIBUFFERWRITER_HPP
#define FMPIBUFFERWRITER_HPP
#include "../Utils/FMpi.hpp"
/** @author Cyrille Piacibello
* This class provide the same features as FBufferWriter using MPI_Pack system
*
* Put some data
* then insert back if needed
* finally use data pointer as you like
*/
class FMpiBufferWriter {
private :
//Classe FMpiVector, used only by FMpiBuffer.
template<class ObjectType>
class FMpiVector {
protected :
static const int DefaultSize = 10;
ObjectType* array; //memory area
int capacity; //Capacity of the array
long int index; //current position in Byte !!
public:
FMpiVector():
array(0),
capacity(DefaultSize),
index(0){
array = reinterpret_cast<ObjectType*>(new char[sizeof(ObjectType)* DefaultSize]);
}
FMpiVector(const int inCapa):
array(0),
capacity(inCapa),
index(0){
array = reinterpret_cast<ObjectType*>(new char[sizeof(ObjectType)* inCapa]);
}
virtual ~FMpiVector(){
delete[] reinterpret_cast< char* >(array);
}
//To get the capacity
const int getCapacity() const{
return this->capacity;
}
//To get the array
ObjectType * data(){
return array;
}
const ObjectType * data() const{
return array;
}
//To delete all the element stored of the array
void clear(){
while(0 < index){
(&array[--index])->~ObjectType();
}
}
//To get how much space is used
long int getSize() const{
return this->index;
}
//To get how many objects are stored
int getObjectsSize(){
return (this->index / sizeof(ObjectType));
}
//To inc the index
//Usually used with array.incIndex(sizeof(my_object_stored));
void incIndex(const int inInc){
if(index + inInc > capacity){
fprintf(stderr,"Aborting : index array out of range\n");
exit(0);
}
else{
this->index+=inInc;
}
}
//To set the index
void setIndex(const int inInd){
if(inInd>capacity){
fprintf(stderr,"Aborting : index array out of range\n");
exit(0);
}
else{
this->index = inInd;
}
}
};
const MPI_Comm comm; // Communicator needed by MPI_Pack functions
FMpiVector<char> array;
public:
/** Constructor with a default capacity of 512 bytes */
FMpiBufferWriter(const MPI_Comm inComm, const int inCapacity = 512):
comm(inComm),
array(inCapacity)
{}
/** Destructor */
virtual ~FMpiBufferWriter(){
delete &array;
}
/** Get allocated memory pointer */
char* data(){
return array.data();
}
/** Get allocated memory pointer */
const char* data() const {
return array.data();
}
/** Get the filled space */
int getSize() const {
return array.getSize();
}
/** Write data by packing cpy */
template <class ClassType>
void write(const ClassType& object){
// buffer.memocopy(reinterpret_cast<const char*>(&object), int(sizeof(ClassType)));
int currentIndex = array.getSize();
array.incIndex(sizeof(ClassType));
MPI_Pack(const_cast<ClassType*>(&object),1,FMpi::GetType(object),array.data(),array.getCapacity(),&currentIndex,comm);
}
/**
* Allow to pass rvalue to write
*/
template <class ClassType>
void write(const ClassType&& object){
// buffer.memocopy(reinterpret_cast<const char*>(&object), int(sizeof(ClassType)));
int currentIndex = array.getSize();
array.incIndex(sizeof(ClassType));
MPI_Pack(const_cast<ClassType*>(&object),1,FMpi::GetType(object),array.data(),array.getCapacity(),&currentIndex,comm);
}
/** Write back, position + sizeof(object) has to be < size */
template <class ClassType>
void writeAt(const int position, const ClassType& object){
//(*reinterpret_cast<ClassType*>(&buffer[position])) = object;
if(position < array.getSize()){
fprintf(stderr,"Aborting : writeAt is overwritting data\n");
}
else{
int temp = position;
if(position + FMpi::GetType(object) < array.getCapacity()){
MPI_Pack(&object,1,FMpi::GetType(object),array.data(),array.getCapacity(),&temp,comm);
}
array.setIndex(temp);
}
}
/** Write an array
* Warning : inSize is a number of ClassType object to write, not a size in bytes
*/
template <class ClassType>
void write(const ClassType* const objects, const int inSize){
int currentIndex = array.getSize();
array.incIndex(sizeof(ClassType) * inSize);
MPI_Pack(objects,inSize,FMpi::GetType(*objects),array.data(),array.getCapacity(),&currentIndex,comm);
}
/** Equivalent to write */
template <class ClassType>
FMpiBufferWriter& operator<<(const ClassType& object){
write(object);
return *this;
}
/** Reset the writing index, but do not change the capacity */
void reset(){
array.clear();
}
};
#endif // FBUFFERWRITER_HPP
......@@ -21,7 +21,7 @@
#include "../Utils/FGlobal.hpp"
#include "../Containers/FBufferReader.hpp"
#include "../Containers/FBufferWriter.hpp"
#include "../Utils/FMath.hpp"
/**
* @author Berenger Bramas (berenger.bramas@inria.fr)
......@@ -272,6 +272,157 @@ public:
}
return str;
}
/* @brief Compute the index of the cells in neighborhood of a given cell
* @param OtreeHeight Height of the Octree
* @param indexes target array to store the MortonIndexes computed
* @param indexInArray store
*/
int getNeighborsIndexes(const int OctreeHeight, MortonIndex indexes[26], int indexInArray[26]) const{
int idxNeig = 0;
int limite = 1 << (OctreeHeight - 1);
// We test all cells around
for(int idxX = -1 ; idxX <= 1 ; ++idxX){
if(!FMath::Between(this->getX() + idxX,0, limite)) continue;
for(int idxY = -1 ; idxY <= 1 ; ++idxY){
if(!FMath::Between(this->getY() + idxY,0, limite)) continue;
for(int idxZ = -1 ; idxZ <= 1 ; ++idxZ){
if(!FMath::Between(this->getZ() + idxZ,0, limite)) continue;
// if we are not on the current cell
if( idxX || idxY || idxZ ){
const FTreeCoordinate other(this->getX() + idxX, this->getY() + idxY, this->getZ() + idxZ);
indexes[ idxNeig ] = other.getMortonIndex(OctreeHeight - 1);
indexInArray[ idxNeig ] = ((idxX+1)*3 + (idxY+1)) * 3 + (idxZ+1);
++idxNeig;
}
}
}
}
return idxNeig;
}
/* @brief Compute the indexes of the neighborhood of the calling cell
* @param OtreeHeight Height of the Octree
* @param indexes target array to store the MortonIndexes computed
*/
int getNeighborsIndexes(const int OctreeHeight, MortonIndex indexes[26]) const{
int idxNeig = 0;
int limite = 1 << (OctreeHeight - 1);
// We test all cells around
for(int idxX = -1 ; idxX <= 1 ; ++idxX){
if(!FMath::Between(this->getX() + idxX,0, limite)) continue;
for(int idxY = -1 ; idxY <= 1 ; ++idxY){
if(!FMath::Between(this->getY() + idxY,0, limite)) continue;
for(int idxZ = -1 ; idxZ <= 1 ; ++idxZ){
if(!FMath::Between(this->getZ() + idxZ,0, limite)) continue;
// if we are not on the current cell
if( idxX || idxY || idxZ ){
const FTreeCoordinate other(this->getX() + idxX, this->getY() + idxY, this->getZ() + idxZ);
indexes[ idxNeig ] = other.getMortonIndex(OctreeHeight - 1);
++idxNeig;
}
}
}
}
return idxNeig;
}
int getInteractionNeighbors(const int inLevel, MortonIndex inNeighbors[189], int inNeighborsPosition[189]) const{
// Then take each child of the parent's neighbors if not in directNeighbors
// Father coordinate
const FTreeCoordinate parentCell(this->getX()>>1,this->getY()>>1,this->getZ()>>1);
// Limite at parent level number of box (split by 2 by level)
const int limite = FMath::pow2(inLevel-1);
int idxNeighbors = 0;
// We test all cells around
for(int idxX = -1 ; idxX <= 1 ; ++idxX){
if(!FMath::Between(parentCell.getX() + idxX,0,limite)) continue;
for(int idxY = -1 ; idxY <= 1 ; ++idxY){
if(!FMath::Between(parentCell.getY() + idxY,0,limite)) continue;
for(int idxZ = -1 ; idxZ <= 1 ; ++idxZ){
if(!FMath::Between(parentCell.getZ() + idxZ,0,limite)) continue;
// if we are not on the current cell
if( idxX || idxY || idxZ ){
const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ);
const MortonIndex mortonOther = otherParent.getMortonIndex(inLevel-1);
// For each child
for(int idxCousin = 0 ; idxCousin < 8 ; ++idxCousin){
const int xdiff = ((otherParent.getX()<<1) | ( (idxCousin>>2) & 1)) - this->getX();
const int ydiff = ((otherParent.getY()<<1) | ( (idxCousin>>1) & 1)) - this->getY();
const int zdiff = ((otherParent.getZ()<<1) | (idxCousin&1)) - this->getZ();
// Test if it is a direct neighbor
if(FMath::Abs(xdiff) > 1 || FMath::Abs(ydiff) > 1 || FMath::Abs(zdiff) > 1){
// add to neighbors
inNeighborsPosition[idxNeighbors] = ((( (xdiff+3) * 7) + (ydiff+3))) * 7 + zdiff + 3;
inNeighbors[idxNeighbors++] = (mortonOther << 3) | idxCousin;
}
}
}
}
}
}
return idxNeighbors;
}
int getInteractionNeighbors(const int inLevel, MortonIndex inNeighbors[189]) const{
// Then take each child of the parent's neighbors if not in directNeighbors
// Father coordinate
const FTreeCoordinate parentCell(this->getX()>>1,this->getY()>>1,this->getZ()>>1);
// Limite at parent level number of box (split by 2 by level)
const int limite = FMath::pow2(inLevel-1);
int idxNeighbors = 0;
// We test all cells around
for(int idxX = -1 ; idxX <= 1 ; ++idxX){
if(!FMath::Between(parentCell.getX() + idxX,0,limite)) continue;
for(int idxY = -1 ; idxY <= 1 ; ++idxY){
if(!FMath::Between(parentCell.getY() + idxY,0,limite)) continue;
for(int idxZ = -1 ; idxZ <= 1 ; ++idxZ){
if(!FMath::Between(parentCell.getZ() + idxZ,0,limite)) continue;
// if we are not on the current cell
if( idxX || idxY || idxZ ){
const FTreeCoordinate otherParent(parentCell.getX() + idxX,parentCell.getY() + idxY,parentCell.getZ() + idxZ);
const MortonIndex mortonOther = otherParent.getMortonIndex(inLevel-1);
// For each child
for(int idxCousin = 0 ; idxCousin < 8 ; ++idxCousin){
const int xdiff = ((otherParent.getX()<<1) | ( (idxCousin>>2) & 1)) - this->getX();
const int ydiff = ((otherParent.getY()<<1) | ( (idxCousin>>1) & 1)) - this->getY();
const int zdiff = ((otherParent.getZ()<<1) | (idxCousin&1)) - this->getZ();
// Test if it is a direct neighbor
if(FMath::Abs(xdiff) > 1 || FMath::Abs(ydiff) > 1 || FMath::Abs(zdiff) > 1){
// add to neighbors
inNeighbors[idxNeighbors++] = (mortonOther << 3) | idxCousin;
}
}
}
}
}
}
return idxNeighbors;
}
};
......
......@@ -507,11 +507,10 @@ private:
// Which cell potentialy needs other data and in the same time
// are potentialy needed by other
int neighborsPosition[189];
MortonIndex neighborsIndexes[189];
for(int idxCell = 0 ; idxCell < numberOfCells ; ++idxCell){
// Find the M2L neigbors of a cell
const int counter = getInteractionNeighbors(iterArray[idxCell].getCurrentGlobalCoordinate(), idxLevel, neighborsIndexes, neighborsPosition);
const int counter = iterArray[idxCell].getCurrentGlobalCoordinate().getInteractionNeighbors(idxLevel, neighborsIndexes);
memset(alreadySent, false, sizeof(bool) * nbProcess);
bool needOther = false;
......@@ -739,7 +738,7 @@ private:
for(int idxCell = 0 ; idxCell < numberOfCells ; ++idxCell){
// compute indexes
memset(neighbors, 0, 343 * sizeof(CellClass*));
const int counterNeighbors = getInteractionNeighbors(iterArray[idxCell].getCurrentGlobalCoordinate(), idxLevel, neighborsIndex, neighborsPosition);
const int counterNeighbors = iterArray[idxCell].getCurrentGlobalCoordinate().getInteractionNeighbors(idxLevel, neighborsIndex, neighborsPosition);
int counter = 0;
// does we receive this index from someone?
......@@ -985,7 +984,7 @@ private:
}
// Number of cells max
const int limite = 1 << (this->OctreeHeight - 1);
//const int limite = 1 << (this->OctreeHeight - 1);
// pointer to send
FVector<typename OctreeClass::Iterator>*const toSend = new FVector<typename OctreeClass::Iterator>[nbProcess];
......@@ -999,14 +998,13 @@ private:
//Will store the indexes of the neighbors of current cell
MortonIndex indexesNeighbors[26];
//Obviously unused
int uselessIndexArray[26];
//int uselessIndexArray[26];
for(int idxLeaf = 0 ; idxLeaf < this->numberOfLeafs ; ++idxLeaf){
memset(alreadySent, 0, sizeof(int) * nbProcess);
bool needOther = false;
//Get the neighbors of current cell in indexesNeighbors, and their number in neighCount
const int neighCount = getNeighborsIndexes(iterArray[idxLeaf].getCurrentGlobalCoordinate(), limite,
indexesNeighbors, uselessIndexArray);