Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
solverstack
ScalFMM
Commits
c0c6ca00
Commit
c0c6ca00
authored
Mar 26, 2015
by
COULAUD Olivier
Browse files
Merge branch 'master' of
git+ssh://scm.gforge.inria.fr//gitroot/scalfmm/scalfmm
parents
d83c641f
b854d3b8
Changes
74
Expand all
Hide whitespace changes
Inline
Side-by-side
Addons/CKernelApi/CMakeLists.txt
View file @
c0c6ca00
...
...
@@ -4,8 +4,8 @@ if(insource)
MESSAGE
(
FATAL_ERROR
"
${
PROJECT_NAME
}
requires an out of source build. Goto ./Build and tapes cmake ../"
)
endif
(
insource
)
project
(
A
ddons_ckernelapi_scalfmm
CXX C
)
set
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
${
S
ca
LFMM_CXX_FLAGS
}
"
)
project
(
A
DDONS_CKERNELAPI_SCALFMM
CXX C
)
set
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
${
S
CA
LFMM_CXX_FLAGS
}
"
)
# Active language
# -----------------------
...
...
@@ -14,7 +14,7 @@ MESSAGE(STATUS " CXX ${CMAKE_CXX_COMPILER_ID}" )
# if ask to build addon
if
(
S
cal
FMM_ADDON_CKERNELAPI
)
if
(
S
CAL
FMM_ADDON_CKERNELAPI
)
# first build lib scalfmmckernelapi
set
(
LIBRARY_OUTPUT_PATH ../lib/
${
CMAKE_BUILD_TYPE
}
)
...
...
@@ -58,7 +58,7 @@ if(ScalFMM_ADDON_CKERNELAPI)
foreach
(
fuse_key
${
FUSE_LIST
}
)
file
(
STRINGS
"
${
exec
}
"
lines_fuse REGEX
"@FUSE_
${
fuse_key
}
"
)
if
(
lines_fuse
)
if
(
NOT S
cal
FMM_USE_
${
fuse_key
}
)
if
(
NOT S
CAL
FMM_USE_
${
fuse_key
}
)
MESSAGE
(
STATUS
"This needs
${
fuse_key
}
=
${
exec
}
"
)
set
(
compile_exec
"FALSE"
)
endif
()
...
...
Addons/FmmApi/CMakeLists.txt
View file @
c0c6ca00
...
...
@@ -60,7 +60,7 @@ if(SCALFMM_ADDON_FMMAPI)
foreach
(
fuse_key
${
FUSE_LIST
}
)
file
(
STRINGS
"
${
exec
}
"
lines_fuse REGEX
"@FUSE_
${
fuse_key
}
"
)
if
(
lines_fuse
)
if
(
NOT S
cal
FMM_USE_
${
fuse_key
}
)
if
(
NOT S
CAL
FMM_USE_
${
fuse_key
}
)
MESSAGE
(
STATUS
"This needs
${
fuse_key
}
=
${
exec
}
"
)
set
(
compile_exec
"FALSE"
)
endif
()
...
...
Addons/FmmApi/Src/ScalfmmApiCore.cpp
View file @
c0c6ca00
...
...
@@ -24,7 +24,7 @@
#include
"../../Src/Components/FBasicParticleContainer.hpp"
#ifdef S
cal
FMM_USE_MPI
#ifdef S
CAL
FMM_USE_MPI
#include
"../../Src/Utils/FMpi.hpp"
#endif
...
...
@@ -268,7 +268,7 @@ struct ScalFmmCoreHandle {
int
treeHeight
;
// hombre de niveaux de l'arbre (int)
FReal
boxWidth
;
// taille de la boîte racine (FReal)
FReal
boxCenter
[
3
];
// position du centre de la boîte racine (FReal[3])
#ifdef S
cal
FMM_USE_MPI
#ifdef S
CAL
FMM_USE_MPI
MPI_Comm
mpiCom
;
// communicateur MPI (MPI_Comm)
#endif
int
nbThreads
;
// nombre de threads (int)
...
...
@@ -304,7 +304,7 @@ int FmmCore_isParameterUsed(void */*fmmCore*/, int *name, int *flag){
case
FMMCORE_ROOT_BOX_WIDTH
:
case
FMMCORE_ROOT_BOX_CENTER
:
case
FMMCORE_TREE_HEIGHT
:
#ifdef S
cal
FMM_USE_MPI
#ifdef S
CAL
FMM_USE_MPI
case
FMMCORE_MPI_COMMUNICATOR
:
#endif
case
FMMCORE_THREADS_NUMBER
:
...
...
@@ -343,7 +343,7 @@ int FmmCore_setParameter(void *fmmCore, int *name, void*value){
case
FMMCORE_ROOT_BOX_CENTER
:
memcpy
(
corehandle
->
config
.
boxCenter
,
value
,
sizeof
(
FReal
)
*
3
);
break
;
#ifdef S
cal
FMM_USE_MPI
#ifdef S
CAL
FMM_USE_MPI
case
FMMCORE_MPI_COMMUNICATOR
:
corehandle
->
config
.
mpiCom
=
*
(
MPI_Comm
*
)
value
;
break
;
...
...
@@ -388,7 +388,7 @@ int FmmCore_getParameter(void *fmmCore, int *name, void*value){
case
FMMCORE_ROOT_BOX_CENTER
:
memcpy
(
value
,
corehandle
->
config
.
boxCenter
,
sizeof
(
FReal
)
*
3
);
break
;
#ifdef S
cal
FMM_USE_MPI
#ifdef S
CAL
FMM_USE_MPI
case
FMMCORE_MPI_COMMUNICATOR
:
*
(
MPI_Comm
*
)
value
=
corehandle
->
config
.
mpiCom
;
break
;
...
...
CMakeLists.txt
View file @
c0c6ca00
This diff is collapsed.
Click to expand it.
Doc/CMakeLists.txt
View file @
c0c6ca00
# add a target to generate API documentation with Doxygen
OPTION
(
ScalFMM_BUILD_DOC
"Set to ON to build the Doxygen documentation "
OFF
)
IF
(
ScalFMM_BUILD_DOC
)
find_package
(
Doxygen
)
if
(
DOXYGEN_FOUND
)
find_package
(
Doxygen
)
if
(
DOXYGEN_FOUND
)
configure_file
(
${
CMAKE_CURRENT_SOURCE_DIR
}
/Doxyfile.in
${
CMAKE_CURRENT_BINARY_DIR
}
/Doxyfile @ONLY
)
add_custom_target
(
doc
${
DOXYGEN_EXECUTABLE
}
${
CMAKE_CURRENT_BINARY_DIR
}
/Doxyfile
WORKING_DIRECTORY
${
CMAKE_CURRENT_BINARY_DIR
}
COMMENT
"Generating API documentation with Doxygen"
VERBATIM
)
# INSTALL(FILES ${ScalFMM_BINARY_DIR}/Doc/scalfmm.tag
# DESTINATION doc/
# )
# INSTALL(DIRECTORY ${ScalFMM_BINARY_DIR}/Doc/html
# DESTINATION doc/
# )
endif
(
DOXYGEN_FOUND
)
endif
(
ScalFMM_BUILD_DOC
)
doc
${
DOXYGEN_EXECUTABLE
}
${
CMAKE_CURRENT_BINARY_DIR
}
/Doxyfile
WORKING_DIRECTORY
${
CMAKE_CURRENT_BINARY_DIR
}
COMMENT
"Generating API documentation with Doxygen"
VERBATIM
)
# INSTALL(FILES ${SCALFMM_BINARY_DIR}/Doc/scalfmm.tag DESTINATION doc/ )
# INSTALL(DIRECTORY ${SCALFMM_BINARY_DIR}/Doc/html DESTINATION doc/ )
else
()
message
(
WARNING
"You ask to enable the doc generation but Doxygen cannot be found."
)
endif
(
DOXYGEN_FOUND
)
Doc/Site_dox/FDownload.dox
View file @
c0c6ca00
...
...
@@ -22,8 +22,9 @@
* <ul>
* <li> CMake for compiling, ccmake for configuring the build. Version 2.8.12.1 or later </li>
* <li> Open MP </li>
* <li> MPI, if you want to use distributed version of the algorithm </li>
* <li> MPI, if you want to use distributed version of the algorithm
(Optional)
</li>
* <li> A compiler supporting C++ 2011 </li>
* <li> BLAS, FFTW, ... (Optionals) </li>
* </ul>
*
* \section build Build
...
...
@@ -32,7 +33,7 @@
* <li> Go to scalfmm/Build directory </li>
* <li> type <b> $> cmake .. </b>
* <ul>
* <li> If you want to enable MPI, use <b> $> cmake .. -DS
ca
LFMM_USE_MPI=ON </b> </li>
* <li> If you want to enable MPI, use <b> $> cmake .. -DS
CA
LFMM_USE_MPI=ON </b> </li>
* </ul>
* </li>
* <li> then configure your build with <b> $> ccmake .. </b> if needed </li>
...
...
@@ -40,8 +41,8 @@
* </ul>
*
* an example : <br>
* <b> cmake -DS
cal
FMM_USE_BLAS=ON -DS
cal
FMM_USE_MKL_AS_BLAS=ON \ <br>
* -DS
cal
FMM_USE_SSE=OFF -DS
cal
FMM_USE_AVX=ON ../ </b>
* <b> cmake -DS
CAL
FMM_USE_BLAS=ON -DS
CAL
FMM_USE_MKL_AS_BLAS=ON \ <br>
* -DS
CAL
FMM_USE_SSE=OFF -DS
CAL
FMM_USE_AVX=ON ../ </b>
*
* \subsection conf Configuration of the build
*
...
...
@@ -49,33 +50,29 @@
*
* <ul>
* <li> CMAKE_INSTALL_PREFIX : to choose where to install ScalFmm </li>
* <li> ScalFMM_USE_MPI : to use and enable MPI. Warning, you need to use this parameter at the first cmake command you write. </li>
* <li> ScalFMM_ATTACHE_SOURCE : to build with -g </li>
* <li> SScalFMM_BUILD_TESTS : to build the text and the examples </li>
* <li> ScalFMM_BUILD_UTESTS : to build the unit tests </li>
* <li> ScalFMM_USE_ADDONS : to activate add ons </li>
* <li> SCALFMM_USE_MPI : to use and enable MPI. Warning, you need to use this parameter at the first cmake command you write. </li>
* <li> SCALFMM_ATTACHE_SOURCE : to build with -g (which enables debugging with release binaries)</li>
* <li> SCALFMM_BUILD_EXAMPLES : to build the examples </li>
* <li> SCALFMM_BUILD_TESTS : to build the tests </li>
* <li> SCALFMM_BUILD_UTESTS : to build the unit tests </li>
* <li> SCALFMM_BUILD_DOC : to enable make doc to generate the documentation </li>
* <li> SCALFMM_USE_ADDONS : to activate add ons </li>
* <ul>
* <li> SCALFMM_ADDON_FMMAPI : to build Fmm Api </li>
* </ul>
* <li> ScalFMM_USE_DOUBLE_PRECISION : to build in double precision </li>
* <li> ScalFMMUSE_MEM_STATS : to use memory stats (which count any new/delete done during a simulation) </li>
* <li> S
cal
FMM_USE_BLAS : to enable BLAS (needed by Chebyshev interpolation kernel) </li>
* <li> S
CAL
FMM_USE_BLAS : to enable BLAS (needed by Chebyshev interpolation kernel) </li>
* <ul>
* <li> SCALFMM_USE_MKL_AS_BLAS : to use MKL as blas </li>
* </ul>
* <li> S
cal
FMM_USE_FFT : Use FFTW needed
for
uniform
point for
interpolation kernel</li>
* <li> S
CAL
FMM_USE_FFT : Use FFTW needed
by the
uniform interpolation kernel</li>
* <ul>
* <li> ( S
cal
FMM_USE_MKL_AS_FFTW : to use MKL as FFTW </li>
* <li> ( S
CAL
FMM_USE_MKL_AS_FFTW : to use MKL as FFTW
)
</li>
* </ul>
* <li> ScalFMM_USE_TRACE : to create trace </li>
* <ul>
* <li> ScalFMM_USE_ITAC : to use Intel ITAC tool as trace generator </li>
* </ul>
* <li> ScalFMM_USE_LOG to print output debug information
* <li> ScalFMM_USE_ASSERT enable safe tests during execution
* <li> ScalFMM_USE_MEM_STATS to profile memory
* <li> ScalFMM_USE_SSE compile with SEE support
* <li> ScalFMM_USE_AVX compile with AVX support
* <li> SCALFMM_USE_LOG to print output debug information during the execution
* <li> SCALFMM_USE_ASSERT enable safe tests during execution
* <li> SCALFMM_USE_SSE compile with SEE support
* <li> SCALFMM_USE_AVX compile with AVX support
* <li>
* </ul>
*
...
...
@@ -86,6 +83,10 @@
* The whole project is documented using Doxygen. You can build the doc
* by typing <b> $> make doc </b> in the Build directory.
* Notice that if you would like to create you own executable and rely on ScalFMM you can simply create
* a .cpp file and store it inside the Tests/Utils directory. Then by running cmake one more time (cmake ..)
* you will be able to compile your file without the need to change CMake files.
*
*
*/
Doc/Site_dox/FQuick.dox
View file @
c0c6ca00
/*! \page quick Quick Start
* In this section, we present the data structure organization and the
* classes design to understand fully ScalFmm and customize
d
it.
* classes design to understand fully ScalFmm and
to
customize it.
* Remark : There is a big difference between the versions 1.0 and
2.0
* Remark
1.2
: There is a big difference between the versions 1.0 and
1.2
* since we do not store array of particles anymore but rather several arrays.
* This was needed in order to be able to vectorize the P2P code.
* We would like to inform users that are not familiar with 'C++' and
* who are familiar with 'C' and would like to create a kernel
* (and do not want to work on the parallelization),
* that an C API have been made for them.
* Remark 1.3 : There is a big difference between the versions 1.2 and 1.3
* The precision is choosen with template (usually called FReal) and no more
* during the configure.
* We would like to inform users who want to create a kernel and who are not familiar with 'C++'
* but are familiar with 'C' that an C API have been made for them.
* In order to get access to this API, go in Addons/CKernelApi.
* (To compile, enable the addons and then the CKernelApi).
* (To compile, enable the addons and then the CKernelApi
in the CMake stage
).
* However, to have access to all the features of ScalFmm it is required to use C++
* as described in this QuickStart.
...
...
Examples/CMakeLists.txt
View file @
c0c6ca00
...
...
@@ -4,7 +4,7 @@ if(insource)
MESSAGE
(
FATAL_ERROR
"
${
PROJECT_NAME
}
requires an out of source build. Goto scalfmm/Build and tapes cmake ../"
)
endif
(
insource
)
project
(
E
xamples_scalfmm
CXX
)
project
(
E
XAMPLES_SCALFMM
CXX
)
set
(
EXECUTABLE_OUTPUT_PATH
${
CMAKE_BUILD_TYPE
}
)
ADD_DEFINITIONS
(
${
ScaLFMM_CXX_FLAGS
}
)
# Find all code files
...
...
@@ -36,7 +36,7 @@ foreach(exec ${source_tests_files})
foreach
(
fuse_key
${
FUSE_LIST
}
)
file
(
STRINGS
"
${
exec
}
"
lines_fuse REGEX
"@FUSE_
${
fuse_key
}
"
)
if
(
lines_fuse
)
if
(
NOT S
cal
FMM_USE_
${
fuse_key
}
)
if
(
NOT S
CAL
FMM_USE_
${
fuse_key
}
)
MESSAGE
(
STATUS
"This needs
${
fuse_key
}
=
${
exec
}
"
)
set
(
compile_exec
"FALSE"
)
endif
()
...
...
Examples/ChebyshevInterpolationMPIFMM.cpp
View file @
c0c6ca00
...
...
@@ -59,11 +59,11 @@
int
main
(
int
argc
,
char
*
argv
[])
{
FHelpDescribeAndExit
(
argc
,
argv
,
"Driver for Chebyshev Interpolation kernel using MPI (1/r kernel). "
"Usully run using : mpirun -np nb_proc_needed ./ChebyshevInterpolationAlgorithm [params]."
,
FParameterDefinitions
::
InputFile
,
FParameterDefinitions
::
OctreeHeight
,
FParameterDefinitions
::
OctreeSubHeight
,
FParameterDefinitions
::
InputFile
,
FParameterDefinitions
::
NbThreads
);
"Driver for Chebyshev Interpolation kernel using MPI (1/r kernel). "
"Usully run using : mpirun -np nb_proc_needed ./ChebyshevInterpolationAlgorithm [params]."
,
FParameterDefinitions
::
InputFile
,
FParameterDefinitions
::
OctreeHeight
,
FParameterDefinitions
::
OctreeSubHeight
,
FParameterDefinitions
::
InputFile
,
FParameterDefinitions
::
NbThreads
);
const
std
::
string
defaultFile
(
/*SCALFMMDataPath+*/
"../Data/test20k.fma"
);
const
std
::
string
filename
=
FParameters
::
getStr
(
argc
,
argv
,
FParameterDefinitions
::
InputFile
.
options
,
defaultFile
.
c_str
());
...
...
@@ -71,184 +71,181 @@ int main(int argc, char* argv[])
const
unsigned
int
SubTreeHeight
=
FParameters
::
getValue
(
argc
,
argv
,
FParameterDefinitions
::
OctreeSubHeight
.
options
,
2
);
const
unsigned
int
NbThreads
=
FParameters
::
getValue
(
argc
,
argv
,
FParameterDefinitions
::
NbThreads
.
options
,
1
);
#ifdef _OPENMP
omp_set_num_threads
(
NbThreads
);
std
::
cout
<<
"
\n
>> Using "
<<
omp_get_max_threads
()
<<
" threads.
\n
"
<<
std
::
endl
;
#else
std
::
cout
<<
"
\n
>> Sequential version.
\n
"
<<
std
::
endl
;
#endif
//
std
::
cout
<<
"Parameters "
<<
std
::
endl
<<
" Octree Depth "
<<
TreeHeight
<<
std
::
endl
<<
" SubOctree depth "
<<
SubTreeHeight
<<
std
::
endl
<<
" Input file name: "
<<
filename
<<
std
::
endl
<<
" Thread number: "
<<
NbThreads
<<
std
::
endl
<<
std
::
endl
;
//init values for MPI
FMpi
app
(
argc
,
argv
);
//
// init timer
FTic
time
;
omp_set_num_threads
(
NbThreads
);
std
::
cout
<<
"
\n
>> Using "
<<
omp_get_max_threads
()
<<
" threads.
\n
"
<<
std
::
endl
;
//
std
::
cout
<<
"Parameters "
<<
std
::
endl
<<
" Octree Depth "
<<
TreeHeight
<<
std
::
endl
<<
" SubOctree depth "
<<
SubTreeHeight
<<
std
::
endl
<<
" Input file name: "
<<
filename
<<
std
::
endl
<<
" Thread number: "
<<
NbThreads
<<
std
::
endl
<<
std
::
endl
;
//init values for MPI
FMpi
app
(
argc
,
argv
);
//
// init timer
FTic
time
;
typedef
double
FReal
;
FMpiFmaGenericLoader
<
FReal
>
loader
(
filename
,
app
.
global
());
if
(
!
loader
.
isOpen
())
throw
std
::
runtime_error
(
"Particle file couldn't be opened!"
)
;
////////////////////////////////////////////////////////////////////
if
(
!
loader
.
isOpen
())
throw
std
::
runtime_error
(
"Particle file couldn't be opened!"
)
;
////////////////////////////////////////////////////////////////////
// begin spherical kernel
// accuracy
const
unsigned
int
ORDER
=
7
;
// typedefs
// accuracy
const
unsigned
int
ORDER
=
7
;
// typedefs
typedef
FP2PParticleContainerIndexed
<
FReal
>
ContainerClass
;
typedef
FSimpleLeaf
<
FReal
,
ContainerClass
>
LeafClass
;
typedef
FChebCell
<
FReal
,
ORDER
>
CellClass
;
typedef
FOctree
<
FReal
,
CellClass
,
ContainerClass
,
LeafClass
>
OctreeClass
;
typedef
FInterpMatrixKernelR
<
FReal
>
MatrixKernelClass
;
const
MatrixKernelClass
MatrixKernel
;
const
MatrixKernelClass
MatrixKernel
;
typedef
FChebSymKernel
<
FReal
,
CellClass
,
ContainerClass
,
MatrixKernelClass
,
ORDER
>
KernelClass
;
//
typedef
FFmmAlgorithmThreadProc
<
OctreeClass
,
CellClass
,
ContainerClass
,
KernelClass
,
LeafClass
>
FmmClassProc
;
// init oct-tree
OctreeClass
tree
(
TreeHeight
,
SubTreeHeight
,
loader
.
getBoxWidth
(),
loader
.
getCenterOfBox
());
{
// -----------------------------------------------------
if
(
app
.
global
().
processId
()
==
0
){
std
::
cout
<<
"Creating & Inserting "
<<
loader
.
getNumberOfParticles
()
<<
" particles ..."
<<
std
::
endl
;
std
::
cout
<<
"
\t
Height : "
<<
TreeHeight
<<
"
\t
sub-height : "
<<
SubTreeHeight
<<
std
::
endl
;
}
time
.
tic
();
//
struct
TestParticle
{
FSize
index
;
FPoint
<
FReal
>
position
;
FReal
physicalValue
;
const
FPoint
<
FReal
>&
getPosition
(){
return
position
;
}
};
TestParticle
*
particles
=
new
TestParticle
[
loader
.
getMyNumberOfParticles
()];
memset
(
particles
,
0
,
(
unsigned
int
)
(
sizeof
(
TestParticle
)
*
loader
.
getMyNumberOfParticles
()));
//idx (in file) of the first part that will be used by this proc.
FSize
idxStart
=
loader
.
getStart
();
printf
(
"Proc %d idxStart %lld
\n
"
,
app
.
global
().
processId
(),
idxStart
);
for
(
FSize
idxPart
=
0
;
idxPart
<
loader
.
getMyNumberOfParticles
()
;
++
idxPart
){
//Storage of the index (in the original file) of each part.
particles
[
idxPart
].
index
=
idxPart
+
idxStart
;
// Read particles from file
loader
.
fillParticle
(
&
particles
[
idxPart
].
position
,
&
particles
[
idxPart
].
physicalValue
);
}
FVector
<
TestParticle
>
finalParticles
;
FLeafBalance
balancer
;
// FMpiTreeBuilder< FReal,TestParticle >::ArrayToTree(app.global(), particles, loader.getMyNumberOfParticles(),
// tree.getBoxCenter(),
// tree.getBoxWidth(),
// tree.getHeight(), &finalParticles,&balancer);
FMpiTreeBuilder
<
FReal
,
TestParticle
>::
DistributeArrayToContainer
(
app
.
global
(),
particles
,
loader
.
getMyNumberOfParticles
(),
tree
.
getBoxCenter
(),
tree
.
getBoxWidth
(),
tree
.
getHeight
(),
&
finalParticles
,
&
balancer
);
for
(
int
idx
=
0
;
idx
<
finalParticles
.
getSize
();
++
idx
){
tree
.
insert
(
finalParticles
[
idx
].
position
,
finalParticles
[
idx
].
index
,
finalParticles
[
idx
].
physicalValue
);
}
printf
(
"%d parts have been inserted in Tree
\n
"
,
finalParticles
.
getSize
());
delete
[]
particles
;
time
.
tac
();
double
timeUsed
=
time
.
elapsed
();
double
minTime
,
maxTime
;
std
::
cout
<<
"Done "
<<
"(@Reading and Inserting Particles = "
<<
time
.
elapsed
()
<<
"s)."
<<
std
::
endl
;
MPI_Reduce
(
&
timeUsed
,
&
minTime
,
1
,
MPI_DOUBLE
,
MPI_MIN
,
0
,
app
.
global
().
getComm
());
MPI_Reduce
(
&
timeUsed
,
&
maxTime
,
1
,
MPI_DOUBLE
,
MPI_MAX
,
0
,
app
.
global
().
getComm
());
if
(
app
.
global
().
processId
()
==
0
){
printf
(
"Reading and Inserting Particles Time used :
\t
MIN : %f
\t
MAX %f in s
\n
"
,
minTime
,
maxTime
);
}
}
// -----------------------------------------------------
{
// -----------------------------------------------------
std
::
cout
<<
"
\n
Chebyshev Interpolation FMM Proc (P="
<<
ORDER
<<
") ... "
<<
std
::
endl
;
time
.
tic
();
//
// Here we use a pointer due to the limited size of the stack
//
KernelClass
*
kernels
=
new
KernelClass
(
TreeHeight
,
loader
.
getBoxWidth
(),
loader
.
getCenterOfBox
(),
&
MatrixKernel
);
//
FmmClassProc
algorithm
(
app
.
global
(),
&
tree
,
kernels
);
//
algorithm
.
execute
();
// Here the call of the FMM algorithm
//
time
.
tac
();
double
timeUsed
=
time
.
elapsed
();
double
minTime
,
maxTime
;
std
::
cout
<<
"Done "
<<
"(@Algorithm = "
<<
time
.
elapsed
()
<<
" s)."
<<
std
::
endl
;
MPI_Reduce
(
&
timeUsed
,
&
minTime
,
1
,
MPI_DOUBLE
,
MPI_MIN
,
0
,
app
.
global
().
getComm
());
MPI_Reduce
(
&
timeUsed
,
&
maxTime
,
1
,
MPI_DOUBLE
,
MPI_MAX
,
0
,
app
.
global
().
getComm
());
if
(
app
.
global
().
processId
()
==
0
){
printf
(
"Time used :
\t
MIN : %f
\t
MAX %f
\n
"
,
minTime
,
maxTime
);
}
}
// -----------------------------------------------------
//
// Some output
//
//
{
// -----------------------------------------------------
long
int
N1
=
0
,
N2
=
loader
.
getNumberOfParticles
()
/
2
,
N3
=
(
loader
.
getNumberOfParticles
()
-
1
);
;
FReal
energy
=
0.0
;
//
// Loop over all leaves
//
std
::
cout
<<
std
::
endl
<<
" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "
<<
std
::
endl
;
std
::
cout
<<
std
::
scientific
;
std
::
cout
.
precision
(
10
)
;
tree
.
forEachLeaf
([
&
](
LeafClass
*
leaf
){
const
FReal
*
const
posX
=
leaf
->
getTargets
()
->
getPositions
()[
0
];
const
FReal
*
const
posY
=
leaf
->
getTargets
()
->
getPositions
()[
1
];
const
FReal
*
const
posZ
=
leaf
->
getTargets
()
->
getPositions
()[
2
];
const
FReal
*
const
potentials
=
leaf
->
getTargets
()
->
getPotentials
();
const
FReal
*
const
forcesX
=
leaf
->
getTargets
()
->
getForcesX
();
const
FReal
*
const
forcesY
=
leaf
->
getTargets
()
->
getForcesY
();
const
FReal
*
const
forcesZ
=
leaf
->
getTargets
()
->
getForcesZ
();
const
int
nbParticlesInLeaf
=
leaf
->
getTargets
()
->
getNbParticles
();
const
FReal
*
const
physicalValues
=
leaf
->
getTargets
()
->
getPhysicalValues
();
const
FVector
<
int
>&
indexes
=
leaf
->
getTargets
()
->
getIndexes
();
for
(
int
idxPart
=
0
;
idxPart
<
nbParticlesInLeaf
;
++
idxPart
){
const
int
indexPartOrig
=
indexes
[
idxPart
];
if
((
indexPartOrig
==
N1
)
||
(
indexPartOrig
==
N2
)
||
(
indexPartOrig
==
N3
)
)
{
std
::
cout
<<
"Proc "
<<
app
.
global
().
processId
()
<<
" Index "
<<
indexPartOrig
<<
" potential "
<<
potentials
[
idxPart
]
<<
" Pos "
<<
posX
[
idxPart
]
<<
" "
<<
posY
[
idxPart
]
<<
" "
<<
posZ
[
idxPart
]
<<
" Forces: "
<<
forcesX
[
idxPart
]
<<
" "
<<
forcesY
[
idxPart
]
<<
" "
<<
forcesZ
[
idxPart
]
<<
std
::
endl
;
}
energy
+=
potentials
[
idxPart
]
*
physicalValues
[
idxPart
]
;
}
});
FReal
gloEnergy
=
app
.
global
().
reduceSum
(
energy
);
if
(
0
==
app
.
global
().
processId
()){
std
::
cout
<<
std
::
endl
<<
"Proc "
<<
app
.
global
().
processId
()
<<
" Energy: "
<<
gloEnergy
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
<<
" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "
<<
std
::
endl
<<
std
::
endl
;
}
}
// -----------------------------------------------------
return
0
;
//
typedef
FFmmAlgorithmThreadProc
<
OctreeClass
,
CellClass
,
ContainerClass
,
KernelClass
,
LeafClass
>
FmmClassProc
;
// init oct-tree
OctreeClass
tree
(
TreeHeight
,
SubTreeHeight
,
loader
.
getBoxWidth
(),
loader
.
getCenterOfBox
());
{
// -----------------------------------------------------
if
(
app
.
global
().
processId
()
==
0
){
std
::
cout
<<
"Creating & Inserting "
<<
loader
.
getNumberOfParticles
()
<<
" particles ..."
<<
std
::
endl
;
std
::
cout
<<
"
\t
Height : "
<<
TreeHeight
<<
"
\t
sub-height : "
<<
SubTreeHeight
<<
std
::
endl
;
}
time
.
tic
();
//
struct
TestParticle
{
FSize
index
;
FPoint
<
FReal
>
position
;
FReal
physicalValue
;
const
FPoint
<
FReal
>&
getPosition
(){
return
position
;
}
};
TestParticle
*
particles
=
new
TestParticle
[
loader
.
getMyNumberOfParticles
()];
memset
(
particles
,
0
,
(
unsigned
int
)
(
sizeof
(
TestParticle
)
*
loader
.
getMyNumberOfParticles
()));
//idx (in file) of the first part that will be used by this proc.
FSize
idxStart
=
loader
.
getStart
();
printf
(
"Proc %d idxStart %lld
\n
"
,
app
.
global
().
processId
(),
idxStart
);
for
(
FSize
idxPart
=
0
;
idxPart
<
loader
.
getMyNumberOfParticles
()
;
++
idxPart
){
//Storage of the index (in the original file) of each part.
particles
[
idxPart
].
index
=
idxPart
+
idxStart
;
// Read particles from file
loader
.
fillParticle
(
&
particles
[
idxPart
].
position
,
&
particles
[
idxPart
].
physicalValue
);
}
FVector
<
TestParticle
>
finalParticles
;
FLeafBalance
balancer
;
// FMpiTreeBuilder< FReal,TestParticle >::ArrayToTree(app.global(), particles, loader.getMyNumberOfParticles(),
// tree.getBoxCenter(),
// tree.getBoxWidth(),
// tree.getHeight(), &finalParticles,&balancer);
FMpiTreeBuilder
<
FReal
,
TestParticle
>::
DistributeArrayToContainer
(
app
.
global
(),
particles
,
loader
.
getMyNumberOfParticles
(),
tree
.
getBoxCenter
(),
tree
.
getBoxWidth
(),
tree
.
getHeight
(),
&
finalParticles
,
&
balancer
);
for
(
int
idx
=
0
;
idx
<
finalParticles
.
getSize
();
++
idx
){
tree
.
insert
(
finalParticles
[
idx
].
position
,
finalParticles
[
idx
].
index
,
finalParticles
[
idx
].
physicalValue
);
}
printf
(
"%d parts have been inserted in Tree
\n
"
,
finalParticles
.
getSize
());
delete
[]
particles
;
time
.
tac
();
double
timeUsed
=
time
.
elapsed
();
double
minTime
,
maxTime
;
std
::
cout
<<
"Done "
<<
"(@Reading and Inserting Particles = "
<<
time
.
elapsed
()
<<
"s)."
<<
std
::
endl
;
MPI_Reduce
(
&
timeUsed
,
&
minTime
,
1
,
MPI_DOUBLE
,
MPI_MIN
,
0
,
app
.
global
().
getComm
());
MPI_Reduce
(
&
timeUsed
,
&
maxTime
,
1
,
MPI_DOUBLE
,
MPI_MAX
,
0
,
app
.
global
().
getComm
());
if
(
app
.
global
().
processId
()
==
0
){
printf
(
"Reading and Inserting Particles Time used :
\t
MIN : %f
\t
MAX %f in s
\n
"
,
minTime
,
maxTime
);
}
}
// -----------------------------------------------------
{
// -----------------------------------------------------
std
::
cout
<<
"
\n
Chebyshev Interpolation FMM Proc (P="
<<
ORDER
<<
") ... "
<<
std
::
endl
;
time
.
tic
();
//
// Here we use a pointer due to the limited size of the stack
//
KernelClass
*
kernels
=
new
KernelClass
(
TreeHeight
,
loader
.
getBoxWidth
(),
loader
.
getCenterOfBox
(),
&
MatrixKernel
);
//
FmmClassProc
algorithm
(
app
.
global
(),
&
tree
,
kernels
);
//
algorithm
.
execute
();
// Here the call of the FMM algorithm
//
time
.
tac
();
double
timeUsed
=
time
.
elapsed
();
double
minTime
,
maxTime
;
std
::
cout
<<
"Done "
<<
"(@Algorithm = "
<<
time
.
elapsed
()
<<
" s)."
<<
std
::
endl
;
MPI_Reduce
(
&
timeUsed
,
&
minTime
,
1
,
MPI_DOUBLE
,
MPI_MIN
,
0
,
app
.
global
().
getComm
());
MPI_Reduce
(
&
timeUsed
,
&
maxTime
,
1
,
MPI_DOUBLE
,
MPI_MAX
,
0
,
app
.
global
().
getComm
());
if
(
app
.
global
().
processId
()
==
0
){
printf
(
"Time used :
\t
MIN : %f
\t
MAX %f
\n
"
,
minTime
,
maxTime
);
}
delete
kernels
;
}
// -----------------------------------------------------
//
// Some output
//
//
{
// -----------------------------------------------------
long
int
N1
=
0
,
N2
=
loader
.
getNumberOfParticles
()
/
2
,
N3
=
(
loader
.
getNumberOfParticles
()
-
1
);
;
FReal
energy
=
0.0
;
//
// Loop over all leaves
//
std
::
cout
<<
std
::
endl
<<
" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "
<<
std
::
endl
;
std
::
cout
<<
std
::
scientific
;
std
::
cout
.
precision
(
10
)
;
tree
.
forEachLeaf
([
&
](
LeafClass
*
leaf
){
const
FReal
*
const
posX
=
leaf
->
getTargets
()
->
getPositions
()[
0
];
const
FReal
*
const
posY
=
leaf
->
getTargets
()
->
getPositions
()[
1
];
const
FReal
*
const
posZ
=
leaf
->
getTargets
()
->
getPositions
()[
2
];
const
FReal
*
const
potentials
=
leaf
->
getTargets
()
->
getPotentials
();
const
FReal
*
const
forcesX
=
leaf
->
getTargets
()
->
getForcesX
();
const
FReal
*
const
forcesY
=
leaf
->
getTargets
()
->
getForcesY
();
const
FReal
*
const
forcesZ
=
leaf
->
getTargets
()
->
getForcesZ
();
const
int
nbParticlesInLeaf
=
leaf
->
getTargets
()
->
getNbParticles
();
const
FReal
*
const
physicalValues
=
leaf
->
getTargets
()
->
getPhysicalValues
();
const
FVector
<
int
>&
indexes
=
leaf
->
getTargets
()
->
getIndexes
();