Attention une mise à jour du serveur va être effectuée le lundi 17 mai entre 13h et 13h30. Cette mise à jour va générer une interruption du service de quelques minutes.

Commit fc133b46 authored by COULAUD Olivier's avatar COULAUD Olivier

Resolved merge conflict by incorporating both suggestions.

parents 54a989b4 cc9a9b37
......@@ -4,7 +4,8 @@
#include <memory>
#include "FAbstractBuffer.hpp"
#include "../Utils/FAssert.hpp"
#include "FBufferWriter.hpp"
#include "Utils/FAssert.hpp"
/**
* \brief Provides memory management and conversion to basic type
......@@ -38,6 +39,23 @@ public :
{
FAssertLF(array, "Cannot allocate array");
}
/**
* \brief Construct the reader
*
* \param capacity Buffer capacity in bytes
*/
explicit FBufferReader( FBufferWriter& buf)
: arrayCapacity(buf.getCapacity() )
{
this->cleanAndResize(arrayCapacity) ;
std::unique_ptr<char[]> arraytmp(new char[arrayCapacity]);
std::copy(buf.data(),buf.data()+arrayCapacity, arraytmp.get());
array = std::move(arraytmp);
currentIndex = buf.getSize() ;
FAssertLF(array, "Cannot allocate array");
}
virtual ~FBufferReader() = default;
......
......@@ -98,6 +98,9 @@ public:
return array.get();
}
std::unique_ptr<char[]>* ptrData(){
return &array;
}
/**
* \brief Return the written memory size
*/
......
#ifndef FNEIGHBORINDEXES_HPP
#define FNEIGHBORINDEXES_HPP
#include "../Utils/FGlobal.hpp"
#include "Utils/FGlobal.hpp"
/**
* @brief The FAbstractNeighborIndex class is an abstraction of
......
......@@ -184,8 +184,9 @@ public:
}
}
/** Remove a leaf from its morton index
* @param indexToRemove the index of the leaf to remove
/** Create a leaf from its morton index
* @param indexToCreate the Morton index of the leaf to create
* @return a pointer on the leaf
*/
LeafClass* createLeaf(const MortonIndex indexToCreate ){
const FTreeCoordinate host(indexToCreate);
......@@ -1398,7 +1399,7 @@ public:
return idxNeighbors;
}
#ifdef TOTO
/** This function fill an array with the neighbors of a cell
* @param inNeighbors the array to store the elements
* @param inIndex the index of the element we want the neighbors
......@@ -1440,7 +1441,7 @@ public:
return idxNeighbors;
}
#endif
/** This function fill an array with the neighbors of a cell
* @param inNeighbors the array to store the elements
* @param inIndex the index of the element we want the neighbors
......@@ -1483,7 +1484,7 @@ public:
return idxNeighbors;
}
#ifdef TOTO
/** This function fill an array with the neighbors of a cell. The cell is set by its FTreeCordinate center
*
* @param[out] outNeighbors the array to store the elements
......@@ -1496,7 +1497,7 @@ public:
int getPeriodicLeafsNeighbors(ContainerClass* outNeighbors[27], FTreeCoordinate outOffsets[27],
bool* const isPeriodic,
const FTreeCoordinate& center, const int inLevel, const int inDirection){
std::cout << " FOCTREE::getPeriodicLeafsNeighbors "<< std::endl;
std::cout << " FOCTREE::getPeriodicLeafsNeighbors ?????? "<< std::endl;
const int boxLimite = FMath::pow2(inLevel);
if( center.getX() != 0 && center.getY() != 0 && center.getZ() != 0 &&
......@@ -1580,8 +1581,8 @@ public:
return idxNeighbors;
}
/** This function fill an array with the neighbors of a cell in the tree.
#endif
/** This function fill an array with the non empty adjacents cells of a cell in the tree.
* In the parallel case, we return only cells of the local octree.
*
* This method is used in the P2P operator in sequential or parallel periodic algorithm
......@@ -1600,18 +1601,22 @@ public:
* @param[in] inLevel the level of the element
* @return the number of neighbors */
//template< class ARRAY1, class ARRAY2, class ARRAY3 >
// int getPeriodicLeafsNeighbors(ARRAY1 outNeighbors, ARRAY2 outNeighborPositions,
// ARRAY3 outOffsets, bool*const isPeriodic,
int getPeriodicLeafsNeighbors(ContainerClass* outNeighbors[26], int outNeighborPositions[26],
FTreeCoordinate outOffsets[26], bool & isPeriodic,
// int getPeriodicLeafsNeighbors(ARRAY1&outNeighbors, ARRAY2 &outNeighborPositions,
// ARRAY3 &outOffsets, bool*const isPeriodic,
int getPeriodicLeafsNeighbors(ContainerClass* outNeighbors[26],
int outNeighborPositions[26],
FTreeCoordinate outOffsets[26], bool & isPeriodic,
const FTreeCoordinate& center, const int inLevel, const int inDirection){
std::cout << " FOCTREE::getPeriodicLeafsNeighbors "<< center.getMortonIndex() <<std::endl;
#ifdef SCALFMM_DEBUG_P2P_PERIODIQUE
std::cout << " FOCTREE::getPeriodicLeafsNeighbors ARRAY "<< center.getMortonIndex() <<std::endl;
#endif
const int boxLimite = FMath::pow2(inLevel);
if( center.getX() != 0 && center.getY() != 0 && center.getZ() != 0 &&
center.getX() != boxLimite - 1 && center.getY() != boxLimite - 1 && center.getZ() != boxLimite - 1 ){
#ifdef SCALFMM_DEBUG_P2P_PERIODIQUE
std::cout << " No periodic conditions the cell is not near the boundary " << std::endl;
#endif
isPeriodic = false;
return getLeafsNeighbors(outNeighbors, outNeighborPositions, center, inLevel);
}
......@@ -1673,15 +1678,18 @@ public:
// get the particle structure of the leaf
ContainerClass* const leaf = getLeafSrc(mortonOther);
// add to list if the cell exists i.e. the pointer is not null
if(leaf){
#ifdef SCALFMM_DEBUG_P2P_PERIODIQUE
std::cout << "mortonOther " <<mortonOther << " idx " <<idxX << " idyY " << idxY << " idxZ " <<idxZ
<< " " << (((idxX + 1) * 3) + (idxY +1)) * 3 + idxZ + 1 <<std::endl;
#endif
outNeighbors[idxNeighbors] = leaf;
outOffsets[idxNeighbors].setPosition(xoffset,yoffset,zoffset);
outNeighborPositions[idxNeighbors] = (((idxX + 1) * 3) + (idxY +1)) * 3 + idxZ + 1;
++idxNeighbors;
} // if(leaf)
}
} // if( idxX || idxY || idxZ )
}
}
......
......@@ -6,6 +6,7 @@
#include "../Utils/FGlobal.hpp"
#include <cstring>
#include <vector>
/**
* @author Berenger Bramas (berenger.bramas@inria.fr)
......@@ -89,9 +90,9 @@ public:
// clear current element
clear();
// alloc bigger if needed
if(capacity < other.getSize()){
if(capacity < other.size()){
delete [] reinterpret_cast< char* >(array);
capacity = FSize(double(other.getSize()) * 1.5);
capacity = FSize(double(other.size()) * 1.5);
array = reinterpret_cast< ObjectType* >( new char[sizeof(ObjectType) * capacity]);
}
......@@ -119,7 +120,20 @@ public:
}
return (*this);
}
/**
*@brief Copy operator
*/
FVector& operator=(std::vector<ObjectType> && other){
if(&other != this){
clear();
delete [] reinterpret_cast< char* >(array);
array = other.data();
capacity = other.capacity();
index = other.size();
other.clear();
}
return (*this);
}
/**
*@brief destructor
*/
......@@ -136,7 +150,6 @@ public:
FSize getCapacity() const{
return capacity;
}
/**
*@brief Set the buffer capacity
*@param inCapacity to change the capacity
......@@ -209,9 +222,17 @@ public:
* @return The number of element added into the vector
* This is not the capcity
*/
// [[gnu::deprecated]]
FSize getSize() const{
return index;
}
/**
* @return The number of element added into the vector
* This is not the capcity
*/
FSize size() const{
return index;
}
/**
* @brief pop the first value
......
......@@ -14,6 +14,7 @@
#include "Utils/FMemUtils.hpp"
#include "Utils/FEnv.hpp"
#include "Containers/FVector.hpp"
#include "Containers/FBoolArray.hpp"
#include "Containers/FOctree.hpp"
#include "Containers/FLightOctree.hpp"
......@@ -129,7 +130,7 @@ public:
{
#pragma omp critical (InitFFmmAlgorithmThreadProcPeriodic)
{
this->kernels[omp_get_thread_num()] = new KernelClass(*inKernels);
this->kernels[omp_get_thread_num()] = new KernelClass(*inKernels);
}
}
}
......@@ -151,10 +152,10 @@ public:
* An assert is launched if one of the arguments is null
*/
FFmmAlgorithmThreadProcPeriodic(const FMpi::FComm& inComm,
OctreeClass* const inTree,
const int inUpperLevel = 2,
const int inUserChunkSize = 10,
const int inLeafLevelSeperationCriteria = 1)
OctreeClass* const inTree,
const int inUpperLevel = 2,
const int inUserChunkSize = 10,
const int inLeafLevelSeperationCriteria = 1)
: tree(inTree) ,
kernels(nullptr),
comm(inComm),
......@@ -184,8 +185,8 @@ public:
/** Default destructor */
virtual ~FFmmAlgorithmThreadProcPeriodic(){
for(int idxThread = 0 ; idxThread < MaxThreads ; ++idxThread){
delete this->kernels[idxThread];
}
delete this->kernels[idxThread];
}
delete [] this->kernels;
delete [] intervals;
......@@ -197,46 +198,46 @@ public:
long long int theoricalRepetition() const {
if( nbLevelsAboveRoot == -1 ){
// we know it is 3 (-1;+1)
return 3;
}
// we know it is 3 (-1;+1)
return 3;
}
// Else we find the repetition in one dir and double it
return 6 * (1<<(nbLevelsAboveRoot));
}
//
//
//
//
void repetitionsIntervals(FTreeCoordinate*const min, FTreeCoordinate*const max) const {
if( nbLevelsAboveRoot == -1 ){
// We know it is (-1;1)
min->setPosition(-1,-1,-1);
max->setPosition(1,1,1);
}
// We know it is (-1;1)
min->setPosition(-1,-1,-1);
max->setPosition(1,1,1);
}
else{
const int halfRepeated = int(theoricalRepetition()/2);
min->setPosition(-halfRepeated,-halfRepeated,-halfRepeated);
// if we repeat the box 8 times, we go from [-4 to 3]
max->setPosition(halfRepeated-1,halfRepeated-1,halfRepeated-1);
}
const int halfRepeated = int(theoricalRepetition()/2);
min->setPosition(-halfRepeated,-halfRepeated,-halfRepeated);
// if we repeat the box 8 times, we go from [-4 to 3]
max->setPosition(halfRepeated-1,halfRepeated-1,halfRepeated-1);
}
}
FReal extendedBoxWidth() const {
if( nbLevelsAboveRoot == -1 ){
return tree->getBoxWidth()*2;
}
return tree->getBoxWidth()*2;
}
else{
return tree->getBoxWidth() * FReal(4<<(nbLevelsAboveRoot));
}
return tree->getBoxWidth() * FReal(4<<(nbLevelsAboveRoot));
}
}
FReal extendedBoxWidthBoundary() const {
if( nbLevelsAboveRoot == -1 ){
return tree->getBoxWidth()*4;
}
return tree->getBoxWidth()*4;
}
else{
return tree->getBoxWidth() * FReal(8<<(nbLevelsAboveRoot));
}
return tree->getBoxWidth() * FReal(8<<(nbLevelsAboveRoot));
}
}
/** This function has to be used to init the kernel with correct args
......@@ -250,41 +251,41 @@ public:
*/
FPoint<FReal> extendedBoxCenter() const {
if( nbLevelsAboveRoot == -1 ){
const FReal originalBoxWidth = tree->getBoxWidth();
const FPoint<FReal> originalBoxCenter = tree->getBoxCenter();
const FReal originalBoxWidthDiv2 = originalBoxWidth/2.0;
return FPoint<FReal>( originalBoxCenter.getX() + originalBoxWidthDiv2,
originalBoxCenter.getY() + originalBoxWidthDiv2,
originalBoxCenter.getZ() + originalBoxWidthDiv2);
} else {
const FReal originalBoxWidth = tree->getBoxWidth();
const FReal originalBoxWidthDiv2 = originalBoxWidth/2.0;
const FPoint<FReal> originalBoxCenter = tree->getBoxCenter();
const FReal offset = extendedBoxWidth()/FReal(2.0);
return FPoint<FReal>( originalBoxCenter.getX() - originalBoxWidthDiv2 + offset,
originalBoxCenter.getY() - originalBoxWidthDiv2 + offset,
originalBoxCenter.getZ() - originalBoxWidthDiv2 + offset);
}
const FReal originalBoxWidth = tree->getBoxWidth();
const FPoint<FReal> originalBoxCenter = tree->getBoxCenter();
const FReal originalBoxWidthDiv2 = originalBoxWidth/2.0;
return FPoint<FReal>( originalBoxCenter.getX() + originalBoxWidthDiv2,
originalBoxCenter.getY() + originalBoxWidthDiv2,
originalBoxCenter.getZ() + originalBoxWidthDiv2);
} else {
const FReal originalBoxWidth = tree->getBoxWidth();
const FReal originalBoxWidthDiv2 = originalBoxWidth/2.0;
const FPoint<FReal> originalBoxCenter = tree->getBoxCenter();
const FReal offset = extendedBoxWidth()/FReal(2.0);
return FPoint<FReal>( originalBoxCenter.getX() - originalBoxWidthDiv2 + offset,
originalBoxCenter.getY() - originalBoxWidthDiv2 + offset,
originalBoxCenter.getZ() - originalBoxWidthDiv2 + offset);
}
}
FPoint<FReal> extendedBoxCenterBoundary() const {
if( nbLevelsAboveRoot == -1 ){
const FReal originalBoxWidth = tree->getBoxWidth();
const FPoint<FReal> originalBoxCenter = tree->getBoxCenter();
const FReal originalBoxWidthDiv2 = originalBoxWidth/2.0;
return FPoint<FReal>( originalBoxCenter.getX() + originalBoxWidthDiv2,
originalBoxCenter.getY() + originalBoxWidthDiv2,
originalBoxCenter.getZ() + originalBoxWidthDiv2);
} else {
const FReal originalBoxWidth = tree->getBoxWidth();
const FReal originalBoxWidthDiv2 = originalBoxWidth/2.0;
const FPoint<FReal> originalBoxCenter = tree->getBoxCenter();
return FPoint<FReal>( originalBoxCenter.getX() + originalBoxWidthDiv2,
originalBoxCenter.getY() + originalBoxWidthDiv2,
originalBoxCenter.getZ() + originalBoxWidthDiv2);
}
const FReal originalBoxWidth = tree->getBoxWidth();
const FPoint<FReal> originalBoxCenter = tree->getBoxCenter();
const FReal originalBoxWidthDiv2 = originalBoxWidth/2.0;
return FPoint<FReal>( originalBoxCenter.getX() + originalBoxWidthDiv2,
originalBoxCenter.getY() + originalBoxWidthDiv2,
originalBoxCenter.getZ() + originalBoxWidthDiv2);
} else {
const FReal originalBoxWidth = tree->getBoxWidth();
const FReal originalBoxWidthDiv2 = originalBoxWidth/2.0;
const FPoint<FReal> originalBoxCenter = tree->getBoxCenter();
return FPoint<FReal>( originalBoxCenter.getX() + originalBoxWidthDiv2,
originalBoxCenter.getY() + originalBoxWidthDiv2,
originalBoxCenter.getZ() + originalBoxWidthDiv2);
}
}
/** This function has to be used to init the kernel with correct args
......@@ -313,18 +314,18 @@ protected:
*/
void executeCore(const unsigned operationsToProceed) override {
// Count leaf
// Build the data distribution
// Build the data distribution
this->numberOfLeafs = 0;
{
Interval myFullInterval;
{//Building the interval with the first and last leaves (and count the number of leaves)
typename OctreeClass::Iterator octreeIterator(tree);
octreeIterator.gotoBottomLeft();
myFullInterval.leftIndex = octreeIterator.getCurrentGlobalIndex();
do{
++this->numberOfLeafs;
} while(octreeIterator.moveRight());
myFullInterval.rightIndex = octreeIterator.getCurrentGlobalIndex();
typename OctreeClass::Iterator octreeIterator(tree);
octreeIterator.gotoBottomLeft();
myFullInterval.leftIndex = octreeIterator.getCurrentGlobalIndex();
do{
++this->numberOfLeafs;
} while(octreeIterator.moveRight());
myFullInterval.rightIndex = octreeIterator.getCurrentGlobalIndex();
}
// Allocate a number to store the pointer of the cells at a level
iterArray = new typename OctreeClass::Iterator[numberOfLeafs];
......@@ -342,53 +343,53 @@ protected:
// We can estimate the interval for each level by using the parent/child relation
for(int idxLevel = OctreeHeight - 2 ; idxLevel >= 0 ; --idxLevel){
myIntervals[idxLevel].leftIndex = myIntervals[idxLevel+1].leftIndex >> 3;
myIntervals[idxLevel].rightIndex = myIntervals[idxLevel+1].rightIndex >> 3;
}
myIntervals[idxLevel].leftIndex = myIntervals[idxLevel+1].leftIndex >> 3;
myIntervals[idxLevel].rightIndex = myIntervals[idxLevel+1].rightIndex >> 3;
}
// Process 0 uses the estimates as real intervals, but other processes
// should remove cells that belong to others
if(idProcess != 0){
//We test for each level if process on left (idProcess-1) own cell I thought I owned
typename OctreeClass::Iterator octreeIterator(tree);
octreeIterator.gotoBottomLeft();
octreeIterator.moveUp();
// At h-1 the working limit is the parent of the right cell of the proc on the left
MortonIndex workingLimitAtLevel = intervals[idProcess-1].rightIndex >> 3;
// We check if we have no more work to do
int nullIntervalFromLevel = 0;
for(int idxLevel = OctreeHeight - 2 ; idxLevel >= 1 && nullIntervalFromLevel == 0 ; --idxLevel){
while(octreeIterator.getCurrentGlobalIndex() <= workingLimitAtLevel){
if( !octreeIterator.moveRight() ){
// We cannot move right we are not owner of any more cell
nullIntervalFromLevel = idxLevel;
break;
}
}
// If we are responsible for some cells at this level keep the first index
if(nullIntervalFromLevel == 0){
myIntervals[idxLevel].leftIndex = octreeIterator.getCurrentGlobalIndex();
octreeIterator.moveUp();
workingLimitAtLevel >>= 3;
}
}
// In case we are not responsible for any cells we put the leftIndex = rightIndex+1
for(int idxLevel = nullIntervalFromLevel ; idxLevel >= 1 ; --idxLevel){
myIntervals[idxLevel].leftIndex = myIntervals[idxLevel].rightIndex + 1;
}
}
//We test for each level if process on left (idProcess-1) own cell I thought I owned
typename OctreeClass::Iterator octreeIterator(tree);
octreeIterator.gotoBottomLeft();
octreeIterator.moveUp();
// At h-1 the working limit is the parent of the right cell of the proc on the left
MortonIndex workingLimitAtLevel = intervals[idProcess-1].rightIndex >> 3;
// We check if we have no more work to do
int nullIntervalFromLevel = 0;
for(int idxLevel = OctreeHeight - 2 ; idxLevel >= 1 && nullIntervalFromLevel == 0 ; --idxLevel){
while(octreeIterator.getCurrentGlobalIndex() <= workingLimitAtLevel){
if( !octreeIterator.moveRight() ){
// We cannot move right we are not owner of any more cell
nullIntervalFromLevel = idxLevel;
break;
}
}
// If we are responsible for some cells at this level keep the first index
if(nullIntervalFromLevel == 0){
myIntervals[idxLevel].leftIndex = octreeIterator.getCurrentGlobalIndex();
octreeIterator.moveUp();
workingLimitAtLevel >>= 3;
}
}
// In case we are not responsible for any cells we put the leftIndex = rightIndex+1
for(int idxLevel = nullIntervalFromLevel ; idxLevel >= 1 ; --idxLevel){
myIntervals[idxLevel].leftIndex = myIntervals[idxLevel].rightIndex + 1;
}
}
// We get the leftIndex/rightIndex indexes from each procs
FMpi::MpiAssert( MPI_Allgather( myIntervals.get(), int(sizeof(Interval)) * OctreeHeight, MPI_BYTE,
workingIntervalsPerLevel, int(sizeof(Interval)) * OctreeHeight, MPI_BYTE, comm.getComm()), __LINE__ );
workingIntervalsPerLevel, int(sizeof(Interval)) * OctreeHeight, MPI_BYTE, comm.getComm()), __LINE__ );
}
tree->forEachCell([this](CellClass* node){
node->setLevel(node->getLevel() + offsetRealTree);
});
node->setLevel(node->getLevel() + offsetRealTree);
});
//
// run the FMM algoritm
//
......@@ -414,8 +415,8 @@ protected:
Timers[NearTimer].tac();
tree->forEachCell([this](CellClass* node){
node->setLevel(node->getLevel() - offsetRealTree);
});
node->setLevel(node->getLevel() - offsetRealTree);
});
// delete array
delete [] iterArray;
......@@ -443,8 +444,8 @@ protected:
octreeIterator.gotoBottomLeft();
int leafs = 0;
do{
iterArray[leafs++] = octreeIterator;
} while(octreeIterator.moveRight());
iterArray[leafs++] = octreeIterator;
} while(octreeIterator.moveRight());
FLOG(computationCounter.tic());
#pragma omp parallel num_threads(MaxThreads)
......@@ -454,16 +455,16 @@ protected:
// Parallel iteration on the leaves
#pragma omp for nowait schedule(dynamic, userChunkSize)
for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs) {
multipole_t* leaf_multipole
= &(iterArray[idxLeafs].getCurrentCell()->getMultipoleData());
const symbolic_data_t* leaf_symbolic
= iterArray[idxLeafs].getCurrentCell();
myThreadkernels->P2M(
leaf_multipole,
leaf_symbolic,
iterArray[idxLeafs].getCurrentListSrc()
);
}
multipole_t* leaf_multipole
= &(iterArray[idxLeafs].getCurrentCell()->getMultipoleData());
const symbolic_data_t* leaf_symbolic
= iterArray[idxLeafs].getCurrentCell();
myThreadkernels->P2M(
leaf_multipole,
leaf_symbolic,
iterArray[idxLeafs].getCurrentListSrc()
);
}
}
FLOG(computationCounter.tac());
FLOG( FLog::Controller << "\tFinished (@Bottom Pass (P2M) = " << counterTime.tacAndElapsed() << " s)\n" );
......@@ -513,234 +514,234 @@ protected:
// We work from height-1 to 1
for(int idxLevel = OctreeHeight - 2 ; idxLevel > 0 ; --idxLevel ){
// const int fakeLevel = idxLevel + offsetRealTree;
// Does my cells are covered by my neighbors working interval and so I have no more work?
const bool noMoreWorkForMe = (idProcess != 0 && !procHasWorkAtLevel(idxLevel+1, idProcess));
if(noMoreWorkForMe){
FAssertLF(procHasWorkAtLevel(idxLevel, idProcess) == false);
break;
}
// Copy and count ALL the cells (even the ones outside the working interval)
int totalNbCellsAtLevel = 0;
do{
iterArray[totalNbCellsAtLevel++] = octreeIterator;
} while(octreeIterator.moveRight());
avoidGotoLeftIterator.moveUp();
octreeIterator = avoidGotoLeftIterator;
int iterMpiRequests = 0; // The iterator for send/recv requests
int iterMpiRequestsSize = 0; // The iterator for send/recv requests
int nbCellsToSkip = 0; // The number of cells to send
// Skip all the cells that are out of my working interval
while(nbCellsToSkip < totalNbCellsAtLevel && iterArray[nbCellsToSkip].getCurrentGlobalIndex() < getWorkingInterval(idxLevel, idProcess).leftIndex){
++nbCellsToSkip;
}
// We need to know if we will recv something in order to know if threads skip the last cell