Maj terminée. Pour consulter la release notes associée voici le lien :
https://about.gitlab.com/releases/2021/07/07/critical-security-release-gitlab-14-0-4-released/

Commit 6ed537c1 authored by BLANCHARD Pierre's avatar BLANCHARD Pierre
Browse files

Merge branch 'master' into PB_tensorialFMM

Conflicts:
	Src/Kernels/Uniform/FUnifTensorialM2LHandler.hpp
parents 1c8ab4a7 2e1c9711
......@@ -54,6 +54,7 @@ OPTION( ScalFMM_ATTACHE_SOURCE "Set to ON to compile with -g"
OPTION( ScalFMM_USE_ADDONS "Set to ON to compile add ons" OFF )
OPTION( ScalFMM_USE_SSE "Set to ON to compile with SSE support" ON )
OPTION( ScalFMM_USE_ASSERT "Set to ON to enable safe tests during execution" ON )
OPTION( ScalFMM_USE_MIC_NATIVE "Set to ON to compile in native mode for MIC" OFF )
# Set scalfmm to default libraries
SET(SCALFMM_LIBRARIES "")
#
......@@ -70,7 +71,14 @@ if(OPENMP_FOUND)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif(OPENMP_FOUND)
MESSAGE(STATUS "ScalFMM_BUILD_DEBUG = ${ScalFMM_BUILD_DEBUG}" )
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(FLAGS_64bits "-m64")
else()
SET(FLAGS_64bits "")
endif()
#
# Debug
#
if( ScalFMM_BUILD_DEBUG )
#
# Compile Debug flags
......@@ -80,12 +88,7 @@ if( ScalFMM_BUILD_DEBUG )
IF( APPLE )
SET(SCALFMM_FLAGS_OPTI_DEBUG "-m64 -funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
ELSE(APPLE)
# Test if not apple and 64bits
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(SCALFMM_FLAGS_OPTI_DEBUG "-m64 -march=native -funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
else()
SET(SCALFMM_FLAGS_OPTI_DEBUG "-march=native -funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
endif()
SET(SCALFMM_FLAGS_OPTI_DEBUG "${FLAGS_64bits} -fp-model strict -march=native -funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
ENDIF(APPLE)
# ADD_DEFINITIONS(${SCALFMM_FLAGS_OPTI_DEBUG})
SET(ScaLFMM_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} ${SCALFMM_FLAGS_OPTI_DEBUG}")
......@@ -106,14 +109,14 @@ else()
IF( APPLE )
SET(SCALFMM_FLAGS_OPTI_RELEASE "-m64 -funroll-loops" CACHE STRING "Set your optimization flags for release mode.")
ELSE(APPLE)
# Test if not apple and 64bits
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(SCALFMM_FLAGS_OPTI_RELEASE "-m64 -ffast-math -flto -march=native -funroll-loops -ftree-vectorize" CACHE STRING "Set your optimization flags for release mode.")
# Not apple system - Check the compilater flags
if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
SET(SCALFMM_FLAGS_OPTI_RELEASE "${FLAGS_64bits} -fp-model precise -fp-model source -fimf-precision=low -march=native -funroll-loops -ftree-vectorize" CACHE STRING "Set your optimization flags for release mode.")
else()
SET(SCALFMM_FLAGS_OPTI_RELEASE "-ffast-math -flto -march=native -funroll-loops -ftree-vectorize" CACHE STRING "Set your optimization flags for release mode.")
SET(SCALFMM_FLAGS_OPTI_RELEASE "${FLAGS_64bits} -ffast-math -flto -march=native -funroll-loops -ftree-vectorize" CACHE STRING "Set your optimization flags for release mode.")
endif()
ENDIF(APPLE)
# ADD_DEFINITIONS(${SCALFMM_FLAGS_OPTI_RELEASE})
#
SET(ScaLFMM_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} ${SCALFMM_FLAGS_OPTI_RELEASE}")
endif()
#
......@@ -187,12 +190,15 @@ CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/Src/ScalFmmConfig.h.cmake
MESSAGE( STATUS "ScalFMM_USE_SSE = ${ScalFMM_USE_SSE}" )
if( ScalFMM_USE_SSE )
IF(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -axAVX")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -vec -axAVX")
ELSE()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse -msse2 -msse3 -mfpmath=sse")
ENDIF()
endif()
if( ScalFMM_USE_MIC_NATIVE )
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmic")
ENDIF()
# Use Mem stats
MESSAGE( STATUS "ScalFMM_USE_MEM_STATS = ${ScalFMM_USE_MEM_STATS}" )
......@@ -281,5 +287,6 @@ INCLUDE(CPack)
#
# OUTPUT
#
MESSAGE(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
MESSAGE(STATUS "ScaLFMM_CXX_FLAGS = ${ScaLFMM_CXX_FLAGS}")
MESSAGE(STATUS "SCALFMM_LIBRARIES = ${SCALFMM_LIBRARIES}")
This diff is collapsed.
NaCl (10x10x10 unit cell) crystal
2 1 2000 -0.4269175E+06 3
2 1 2000 -0.4269175E+06
40.00
Na 1
-0.3909861360E-25 -0.3909861360E-25 -0.3909861360E-25
......
......@@ -4,4 +4,7 @@
* \section Periodic-1 Periodicity in usual FMM
* \subsection limitation
* support only cubic box
*/
This diff is collapsed.
......@@ -382,17 +382,25 @@ The kernel should be able to proceed usual FMM operator in a tree of height of s
\section{Results}
\subsection{Ewald summation comparisons}
The energy computed by molecular dynamics codes is given by
The energy computed by molecular dynamics codes for a finite system is given by
$$
U = \frac{1}{4 \pi\epsilon_0}\sum_{i=0}^{N}{\sum_{j<i}{\frac{q_i q_j}{\|x_i-x_j\|}}}
$$
and the force on atom $x_i$
and the force on atom $x_i$ is
$$
f(x_i) = \frac{q_i }{4 \pi\epsilon_0}\sum_{j=0,i\neq j}^{N}{q_j\frac{x_i-x_j}{\|x_i-x_j\|^3}}
$$
Now consider a periodic system, the energy computed by molecular dynamics codes atypically by Ewald method is
$$
U = \frac{1}{8 \pi\epsilon_0}\sum_{|n|=0}^{\infty}{\sum_{i,j}^{N}{\sum_{j<i}{'\frac{q_i q_j}{\|x_i-x_j + n L \| }}}}
$$
where $L$ is the box size and ${'}$ specifies that for $n=0$ the omit i equal $j$ in the sum. The force on atom $x_i$ is
$$
f(x_i) = \frac{q_i}{8 \pi\epsilon_0}\sum_{|n|=0}^{\infty}{\sum_{i,j}^{N}{'q_j\frac{x_i-x_j}{\|x_i-x_j + n L\|^3}}}
$$
In the Ewald method, to original box is replicated up to the infinity, and then the method is equivalent to consider a surrounding conductor ($\epsilon=\infty$).
The Ewald method is equivalent to consider a surrounding conductor ($\epsilon=\infty$). The method described in this document and implemented in ScalFMM consider a finite set of the original box surrounded by a vacuum with dielectric constant $\epsilon=1$. The results by these two approaches are different \cite{DeLeeuw1980, Heyes1981} and for a very large sphere surrounding all boxes we have the following equation
The method described in this document and implemented in ScalFMM consider a finite set of the original box surrounded by a vacuum with dielectric constant $\epsilon=1$. The results by these two approaches are different \cite{DeLeeuw1980, Heyes1981} and for a very large sphere surrounding all boxes we have the following equation
\begin{equation}
E_{Ewald} = E_{FMM} -\frac{2\pi}{3V}|\sum_{i=1}^{N}{q_i x_i}|^2.
\end{equation}
......@@ -400,6 +408,20 @@ By tacking the gradient of this equation, the relationship between FMM forces an
\begin{equation}
F_{Ewald}(x_k) = -\nabla_k E_{Ewald} = F_{FMM}(x_k) + \frac{4\pi}{3V} q_k \sum_{i=1}^{N}{q_i x_i}.
\end{equation}
If we denote by $\mathbf{D}= \sum_{i=1}^{N}{q_i x_i}$ the dipole moment of the system then the periodic energy is
\begin{equation}
E_{Ewald} = E_{FMM} - \frac{2\pi}{3V}\mathbf{D}.\mathbf{D} =\sum_{i=1}^{N}{q_i V_i^{Ewald}}
\end{equation}
the potential
\begin{equation}
V^{Ewald}(r) = V^{FMM}(r) - \frac{4\pi}{3V} r.\mathbf{D}
\end{equation}
and the forces are
\begin{equation}
F_{Ewald}(x_k) = -\nabla_k E_{Ewald} = F_{FMM}(x_k) + \frac{4\pi}{3V} q_k \mathbf{D}.
\end{equation}
\subsubsection{DL\_Poly comparisons}
DL\_POLY\_2 uses the following internal molecular units \\
......@@ -502,14 +524,14 @@ struct MDParticle {
\end{verbatim}
We save the direct evaluation of the forces in a binary file. To read the file you should proceed as follow
\begin{verbatim}
std::ifstream fileout(filenameOut,
std::ifstream filein(filename,
std::ifstream::in| std::ios::binary);
file.seekg (std::ios::beg);
1 file.read( (char*)(&nbParticles), sizeof(int));
2 fileout.read( (char*)(&boxsize[0]), sizeof(double)*3);
3 fileout.read((char*)&PER[0],sizeof(int)*4);
4 fileout.read( (char*)(&denergy), sizeof(denergy));
filein.seekg (std::ios::beg);
1 filein.read( (char*)(&nbParticles), sizeof(int));
2 filein.read( (char*)(&boxsize[0]), sizeof(double)*3);
3 filein.read((char*)&PER[0],sizeof(int)*4);
4 filein.read( (char*)(&denergy), sizeof(denergy));
//
particles = new MDParticle[nbParticles*2];
fileout.read((char*)&particles[0], sizeof(MDParticle)*nbParticles);
......
// ===================================================================================
// 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 FABSTRACTBALANCEALGORITHM_H
#define FABSTRACTBALANCEALGORITHM_H
/**
* @author Cyrille Piacibello
* @class FAbstractBalanceAlgorithm
*
* @brief This class provide the methods that are used to balance a
* tree FMpiTreeBuilder::EqualizeAndFillTree
*/
class FAbstractBalanceAlgorithm{
public:
virtual ~FAbstractBalanceAlgorithm(){
}
/**
* @brief Give the right leaves (ie the min) of the interval that
* will be handle by idxOfProc
* @param numberOfLeaves Total number of leaves that exist.
* @param numberOfPartPerLeaf Array of lenght numberOfLeaves containing the number of particles in each leaf
* @param numberOfPart Number of particles in the whole field
* @param idxOfLeaves Array of lenght numberOfLeaves containing the Morton Index of each Leaf
* @param numberOfProc Number of MPI processus that will handle the Octree
* @param idxOfProc Idx of the proc calling.
*/
virtual FSize getRight(const FSize numberOfLeaves, const int*numberOfPartPerLeaf, const FSize numberOfPart, const MortonIndex* idxOfLeaves,
const int numberOfProc, const int idxOfProc) = 0;
/**
* @brief Give the Leaft leaves (ie the max) of the interval that
* will be handle by idxOfProc
* @param numberOfLeaves Total number of leaves that exist.
* @param numberOfPartPerLeaf Array of lenght numberOfLeaves containing the number of particles in each leaf
* @param numberOfPart Number of particles in the whole field
* @param idxOfLeaves Array of lenght numberOfLeaves containing the Morton Index of each Leaf
* @param numberOfProc Number of MPI processus that will handle the Octree
* @param idxOfProc Idx of the proc calling.
*/
virtual FSize getLeft(const FSize numberOfLeaves, const int*numberOfPartPerLeaf, const FSize numberOfPart, const MortonIndex* idxOfLeaves,
const int numberOfProc, const int idxOfProc) = 0;
};
#endif //FABSTRACTBALANCEALGORITHM_H
// ===================================================================================
// 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 FLEAFBALANCE_H
#define FLEAFBALANCE_H
#include "./FAbstractBalanceAlgorithm.hpp"
#include "../Utils/FMath.hpp"
/**
* @author Cyrille Piacibello
* @class FLeafBalance
*
* @brief This class inherits from FAbstractBalanceAlgorithm. It
* provides balancing methods based on leaf numbers only.
*/
class FLeafBalance : public FAbstractBalanceAlgorithm{
public:
/**
* Does not need the number of particles. Just divide the leaves
* over processus
*/
FSize getRight(const FSize numberOfLeaves, const int*numberOfPartPerLeaf, const FSize numberOfPart, const MortonIndex* idxOfLeaves,
const int numberOfProc, const int idxOfProc){
const double step = (double(numberOfLeaves) / double(numberOfProc));
const FSize res = FSize(FMath::Ceil(step * double(idxOfProc+1)));
if(res > numberOfLeaves) return numberOfLeaves;
else return res;
}
/**
* Does not need the number of particles. Just divide the leaves
* over processus
*/
FSize getLeft(const FSize numberOfLeaves, const int*numberOfPartPerLeaf, const FSize numberOfPart, const MortonIndex* idxOfLeaves,
const int numberOfProc, const int idxOfProc){
const double step = (double(numberOfLeaves) / double(numberOfProc));
return FSize(FMath::Ceil(step * double(idxOfProc)));
}
};
#endif // FLEAFBALANCE_H
// ===================================================================================
// 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 FPARTICLESBALANCE_H
#define FPARTICLESBALANCE_H
#include "./FAbstractBalanceAlgorithm.hpp"
#include "../Utils/FMath.hpp"
/**
* @author Cyrille Piacibello
* @class FLeafBalance
*
* @brief This class inherits from FAbstractBalanceAlgorithm. It
* provides balancing methods based on particles distribution.
*/
class FParticlesBalance : public FAbstractBalanceAlgorithm{
public:
/**
* getRight interval based on particles distribution
*/
FSize getRight(const FSize numberOfLeaves, const int*numberOfPartPerLeaf, const FSize numberOfPart, const MortonIndex* idxOfLeaves,
const int numberOfProc, const int idxOfProc){
int acc = 0;
FSize i = 0;
const double step = (double(numberOfPart) / double(numberOfProc));
FSize aimRight = FSize(FMath::Ceil(step * double(idxOfProc+1)));
if(aimRight > numberOfPart) aimRight = numberOfPart;
while(acc < aimRight){
acc+=numberOfPartPerLeaf[i];
++i;
}
if(FMath::Abs(aimRight-acc) < FMath::Abs(aimRight-(acc-numberOfPartPerLeaf[i]))) return i;
else
return i-1;
}
/**
* get left interval based on particles distribution
*/
FSize getLeft(const FSize numberOfLeaves, const int*numberOfPartPerLeaf, const FSize numberOfPart, const MortonIndex* idxOfLeaves,
const int numberOfProc, const int idxOfProc){
int acc = 0;
FSize i = 0;
const double step = (double(numberOfPart) / double(numberOfProc));
const FSize aimLeft = FSize(FMath::Ceil(step * double(idxOfProc)));
while (acc < aimLeft){
acc+=numberOfPartPerLeaf[i];
++i;
}
if(FMath::Abs(aimLeft-acc) < FMath::Abs(aimLeft-(acc-numberOfPartPerLeaf[i]))) return i;
else
return i-1;
}
};
#endif // FPARTICLESBALANCE_H
......@@ -49,7 +49,7 @@ protected:
* @brief GetSize returns the size of the current block (in order to prepare the buffer)
* @return
*/
static int GetSize(){
static constexpr int GetSize(){
return 0;
}
......
......@@ -76,7 +76,7 @@ public:
buffer >> dataDown >> dataUp;
}
static size_t GetSize(){
static constexpr int GetSize(){
return sizeof(long long int)*2;
}
......
......@@ -62,7 +62,7 @@
template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass>
class FFmmAlgorithmThreadProc : public FAbstractAlgorithm {
const int MaxSizePerCell = CellClass::GetSize();
// const static int MaxSizePerCell = CellClass::GetSize();
OctreeClass* const tree; //< The octree to work on
KernelClass** kernels; //< The kernels
......@@ -246,7 +246,7 @@ private:
}
FLOG(computationCounter.tac());
FLOG( FLog::Controller << "\tFinished (@Bottom Pass (P2M) = " << counterTime.tacAndElapsed() << "s)\n" );
FLOG( FLog::Controller << "\tFinished (@Bottom Pass (P2M) = " << counterTime.tacAndElapsed() << " s)\n" );
FLOG( FLog::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" );
}
......@@ -257,6 +257,7 @@ private:
/** M2M */
void upwardPass(){
const int MaxSizePerCell = CellClass::GetSize();
FTRACE( FTrace::FFunction functionTrace(__FUNCTION__, "Fmm" , __FILE__ , __LINE__) );
FLOG( FLog::Controller.write("\tStart Upward Pass\n").write(FLog::Flush); );
FLOG(FTic counterTime);
......@@ -433,7 +434,7 @@ private:
}
FLOG( FLog::Controller << "\tFinished (@Upward Pass (M2M) = " << counterTime.tacAndElapsed() << "s)\n" );
FLOG( FLog::Controller << "\tFinished (@Upward Pass (M2M) = " << counterTime.tacAndElapsed() << " s)\n" );
FLOG( FLog::Controller << "\t\t Computation : " << computationCounter.cumulated() << " s\n" );
FLOG( FLog::Controller << "\t\t Prepare : " << prepareCounter.cumulated() << " s\n" );
FLOG( FLog::Controller << "\t\t Wait : " << waitCounter.cumulated() << " s\n" );
......@@ -445,6 +446,7 @@ private:
/** M2L */
void transferPass(){
const int MaxSizePerCell = CellClass::GetSize();
FTRACE( FTrace::FFunction functionTrace(__FUNCTION__, "Fmm" , __FILE__ , __LINE__) );
FLOG( FLog::Controller.write("\tStart Downward Pass (M2L)\n").write(FLog::Flush); );
......@@ -786,7 +788,7 @@ private:
delete[] requests;
delete[] status;
FLOG( FLog::Controller << "\tFinished (@Downward Pass (M2L) = " << counterTime.tacAndElapsed() << "s)\n" );
FLOG( FLog::Controller << "\tFinished (@Downward Pass (M2L) = " << counterTime.tacAndElapsed() << " s)\n" );
FLOG( FLog::Controller << "\t\t Computation : " << computationCounter.cumulated() << " s\n" );
FLOG( FLog::Controller << "\t\t Send : " << sendCounter.cumulated() << " s\n" );
FLOG( FLog::Controller << "\t\t Receive : " << receiveCounter.cumulated() << " s\n" );
......@@ -799,6 +801,7 @@ private:
//////////////////////////////////////////////////////////////////
void downardPass(){ // second L2L
const int MaxSizePerCell = CellClass::GetSize();
FTRACE( FTrace::FFunction functionTrace(__FUNCTION__, "Fmm" , __FILE__ , __LINE__) );
FLOG( FLog::Controller.write("\tStart Downward Pass (L2L)\n").write(FLog::Flush); );
FLOG(FTic counterTime);
......@@ -922,7 +925,7 @@ private:
delete[] requests;
delete[] status;
FLOG( FLog::Controller << "\tFinished (@Downward Pass (L2L) = " << counterTime.tacAndElapsed() << "s)\n" );
FLOG( FLog::Controller << "\tFinished (@Downward Pass (L2L) = " << counterTime.tacAndElapsed() << " s)\n" );
FLOG( FLog::Controller << "\t\t Computation : " << computationCounter.cumulated() << " s\n" );
FLOG( FLog::Controller << "\t\t Prepare : " << prepareCounter.cumulated() << " s\n" );
FLOG( FLog::Controller << "\t\t Wait : " << waitCounter.cumulated() << " s\n" );
......@@ -1088,7 +1091,6 @@ private:
(*sendBuffer[idxProc]) << toSend[idxProc][idxLeaf].getCurrentGlobalIndex();
toSend[idxProc][idxLeaf].getCurrentListSrc()->save(*sendBuffer[idxProc]);
}
//TEST BERENGER
//if(sendBuffer[idxProc]->getSize() != partsToSend[idxProc]){
FMpi::MpiAssert( MPI_Isend( sendBuffer[idxProc]->data(), sendBuffer[idxProc]->getSize() , MPI_PACKED ,
......@@ -1289,7 +1291,7 @@ private:
FLOG(computation2Counter.tac());
FLOG( FLog::Controller << "\tFinished (@Direct Pass (L2P + P2P) = " << counterTime.tacAndElapsed() << "s)\n" );
FLOG( FLog::Controller << "\tFinished (@Direct Pass (L2P + P2P) = " << counterTime.tacAndElapsed() << " s)\n" );
FLOG( FLog::Controller << "\t\t Computation L2P + P2P : " << computationCounter.elapsed() << " s\n" );
FLOG( FLog::Controller << "\t\t Computation P2P 2 : " << computation2Counter.elapsed() << " s\n" );
FLOG( FLog::Controller << "\t\t Prepare P2P : " << prepareCounter.elapsed() << " s\n" );
......
......@@ -30,8 +30,8 @@
* Please read the license
*
* Load a file with a format like :
* NB_particles Box_width Box_X Box_Y Box_Z // init
* X Y Z // one particle by line
* NB_particles Box_width Center_X Center_Y Center_Z // init
* X Y Z PhysicalValue // one particle by line
* ....
* <code>
* FFmaBinLoader<FBasicParticle> loader("../Adir/Tests/particles.basic.txt"); <br>
......
......@@ -30,8 +30,8 @@
* Please read the license
*
* Load a file with a format like :
* NB_particles Box_width Box_X Box_Y Box_Z // init
* X Y Z // one particle by line
* NB_particles Box_width Center_X Center_Y Center_Z // init
* X Y Z PhysicalValue // one particle by line
* ....
* @code
* FFmaLoader<FBasicParticle> loader("../ADir/Tests/particles.basic.txt"); <br>
......
This diff is collapsed.
......@@ -45,7 +45,7 @@ public:
FRandomLoader(const size_t inNbParticles, const FReal inBoxWidth = 1.0,
const FPoint& inCenterOfBox = FPoint(0,0,0), const unsigned int inSeed = static_cast<unsigned int>(0))
: nbParticles(inNbParticles), boxWidth(inBoxWidth), centerOfBox(inCenterOfBox) {
srand(inSeed);
srand48(inSeed);
}
/**
......@@ -99,7 +99,7 @@ public:
/** Get a random number between 0 & 1 */
FReal getRandom() const{
return FReal(rand())/FReal(RAND_MAX);
return FReal(drand48());
}
};
......
#ifndef FGROUPATTACHEDLEAF_HPP
#define FGROUPATTACHEDLEAF_HPP
#include "../Utils/FGlobal.hpp"
#include "../Utils/FAssert.hpp"
/**
* This class is "attached" to a buffer.
* It is a wrapper/interface to a memory area that stores all the particles info.
* The idea is to hidde the group allocation from the group tree but
* to keep the same interface than the FBasicParticlesContainer.
*/
template <unsigned NbAttributesPerParticle, class AttributeClass = FReal>
class FGroupAttachedLeaf {
protected:
//< Nb of particles in the current leaf
const int nbParticles;
//< Pointers to the positions of the particles
FReal* positionsPointers[3];
//< Pointers to the attributes of the particles
AttributeClass* attributes[NbAttributesPerParticle];
public:
/** Empty constructor to point to nothing */
FGroupAttachedLeaf() : nbParticles(-1) {
memset(positionsPointers, 0, sizeof(FReal*) * 3);
memset(attributes, 0, sizeof(AttributeClass*) * NbAttributesPerParticle);
}
/**
* @brief FGroupAttachedLeaf
* @param inNbParticles the number of particles in the leaf
* @param inPositionBuffer the memory address of the X array of particls
* @param inLeadingPosition each position is access by inPositionBuffer + in bytes inLeadingPosition*idx
* @param inAttributesBuffer the memory address of the first attribute
* @param inLeadingAttributes each attribute is access by inAttributesBuffer + in bytes inLeadingAttributes*idx
*/
FGroupAttachedLeaf(const int inNbParticles, FReal* inPositionBuffer, const size_t inLeadingPosition,
AttributeClass* inAttributesBuffer, const size_t inLeadingAttributes)
: nbParticles(inNbParticles){
// Redirect pointers to position
positionsPointers[0] = inPositionBuffer;
positionsPointers[1] = reinterpret_cast<FReal*>(reinterpret_cast<unsigned char*>(inPositionBuffer) + inLeadingPosition);
positionsPointers[2] = reinterpret_cast<FReal*>(reinterpret_cast<unsigned char*>(inPositionBuffer) + inLeadingPosition*2);
// Redirect pointers to data
for(unsigned idxAttribute = 0 ; idxAttribute < NbAttributesPerParticle ; ++idxAttribute){
attributes[idxAttribute] = reinterpret_cast<AttributeClass*>(reinterpret_cast<unsigned char*>(inAttributesBuffer) + idxAttribute*inLeadingAttributes);
}
}
/** Copy the attached group to another one (copy the pointer not the content!) */
FGroupAttachedLeaf(const FGroupAttachedLeaf& other) : nbParticles(other.nbParticles) {
positionsPointers[0] = other.positionsPointers[0];
positionsPointers[1] = other.positionsPointers[1];
positionsPointers[2] = other.positionsPointers[2];
// Redirect pointers to data
for(unsigned idxAttribute = 0 ; idxAttribute < NbAttributesPerParticle ; ++idxAttribute){
attributes[idxAttribute] = other.attributes[idxAttribute];
}
}
/** Copy the attached group to another one (copy the pointer not the content!) */
FGroupAttachedLeaf& operator=(const FGroupAttachedLeaf& other){
nbParticles = (other.nbParticles);
positionsPointers[0] = other.positionsPointers[0];
positionsPointers[1] = other.positionsPointers[1];
positionsPointers[2] = other.positionsPointers[2];
// Redirect pointers to data
for(unsigned idxAttribute = 0 ; idxAttribute < NbAttributesPerParticle ; ++idxAttribute){
attributes[idxAttribute] = other.attributes[idxAttribute];
}
return (*this);
}
/**
* @brief getNbParticles
* @return the number of particles in the leaf