Commit ac4a7f0e authored by COULAUD Olivier's avatar COULAUD Olivier

Add scalability test in Utils/noDist

Fill variable SCALFMMCompileFlags and SCALFMMCompileLibs
parent 38606790
......@@ -70,25 +70,23 @@ OPTION( ScalFMM_USE_STARPU "Set to ON to build ScaFMM with StarPU" OFF )
endif()
# Set scalfmm to default libraries
SET(SCALFMM_LIBRARIES "")
SET(ScaLFMM_CXX_FLAGS "")
SET(ScaLFMM_CXX_FLAGS "-std=c++11 -fpic -Wall")
#
#
# Test if openmp is here
#
find_package (OpenMP)
if(OPENMP_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
# SET(ScaLFMM_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
else(OPENMP_FOUND)
MESSAGE(WARNING "OPENMP NOT FOUND")
endif(OPENMP_FOUND)
MESSAGE(STATUS "ScalFMM_BUILD_DEBUG = ${ScalFMM_BUILD_DEBUG}" )
MESSAGE(STATUS "ScalFMM_BUILD_DEBUG = ${ScalFMM_BUILD_DEBUG}" )
#
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(FLAGS_64bits "-m64")
else()
SET(FLAGS_64bits "")
SET(ScaLFMM_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} -m64")
endif()
##############################################################################
# Compile options #
......@@ -96,10 +94,8 @@ endif()
# -xHost -mfpmath=sse
# -Wall Wnosign-conversion
#
SET(ScaLFMM_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} -std=c++11 -fpic -Wall ")
#
if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
# INTEL
# INTEL
IF (APPLE)
SET(SSE_FLAGS "-msse4 -mfpmath=sse") # -mtune=native -march=native
ELSE(APPLE)
......@@ -139,9 +135,9 @@ if( ScalFMM_BUILD_DEBUG )
SET(SCALFMM_FLAGS_OPTI_DEBUG "-m64 -funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
ELSE(APPLE)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
SET(SCALFMM_FLAGS_OPTI_DEBUG "${FLAGS_64bits} -fp-model strict -funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
SET(SCALFMM_FLAGS_OPTI_DEBUG "-fp-model strict -funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
else()
SET(SCALFMM_FLAGS_OPTI_DEBUG "${FLAGS_64bits} -funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
SET(SCALFMM_FLAGS_OPTI_DEBUG "-funroll-loops" CACHE STRING "Set your optimization flags for debug mode.")
endif()
ENDIF(APPLE)
# ADD_DEFINITIONS(${SCALFMM_FLAGS_OPTI_DEBUG})
......@@ -164,24 +160,24 @@ else()
ELSE(APPLE)
# Not apple system - Check the compiler flags
if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
SET(SCALFMM_FLAGS_OPTI_RELEASE "${FLAGS_64bits} -fp-model precise -fp-model source -fimf-precision=low -funroll-loops -ftree-vectorize" CACHE STRING "Set your optimization flags for release mode.")
SET(SCALFMM_FLAGS_OPTI_RELEASE "-fp-model precise -fp-model source -fimf-precision=low -funroll-loops -ftree-vectorize" CACHE STRING "Set your optimization flags for release mode.")
else()
SET(SCALFMM_FLAGS_OPTI_RELEASE "${FLAGS_64bits} -ffast-math -funroll-loops -ftree-vectorize" CACHE STRING "Set your optimization flags for release mode.")
SET(SCALFMM_FLAGS_OPTI_RELEASE "-ffast-math -funroll-loops -ftree-vectorize" CACHE STRING "Set your optimization flags for release mode.")
endif()
ENDIF(APPLE)
#
SET(ScaLFMM_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} ${SCALFMM_FLAGS_OPTI_RELEASE}")
endif()
#
##############################################################################
# Attach source code to exec #
##############################################################################
MESSAGE(STATUS "ScalFMM_ATTACHE_SOURCE = ${ScalFMM_ATTACHE_SOURCE}" )
if( ScalFMM_ATTACHE_SOURCE )
MESSAGE( STATUS "Option -g is used, the code is attached to the binary." )
# ADD_DEFINITIONS(-g)
MESSAGE( STATUS "Option -g is used, the code is attached to the binary." )
SET(ScaLFMM_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} -g")
endif(ScalFMM_ATTACHE_SOURCE)
#
##############################################################################
# Blas option #
##############################################################################
......@@ -234,7 +230,6 @@ if( ScalFMM_USE_FFT )
SET(SCALFMM_INCLUDES "${SCALFMM_INCLUDES}; ${FFT_INCLUDES}")
MESSAGE(STATUS "SCALFMM_LIBRARIES = ${SCALFMM_LIBRARIES}")
MESSAGE(STATUS "SCALFMM_INCLUDES = ${SCALFMM_INCLUDES}")
endif(ScalFMM_USE_FFT)
# Compile option
......@@ -259,7 +254,10 @@ IF(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
endif()
endif()
endif()
#
##################################################################
##################################################################
#
if( ScalFMM_USE_STARPU )
SET(STARPU_LIBRARIES " -L$ENV{STARPU_LIB}; -lstarpu-1.1") # CACHE STRING "Set your STARPU flags"
......@@ -272,9 +270,7 @@ if( ScalFMM_USE_STARPU )
# SET(SCALFMM_INCLUDES "${SCALFMM_INCLUDES}; ${STARPU_INCLUDES}")
include_directories(${STARPU_INCLUDES})
endif(ScalFMM_USE_STARPU)
##############################################################################
##############################################################################
#
##################################################################
# Use SSE #
##################################################################
......@@ -347,10 +343,12 @@ ENDIF()
##################################################################
#
##################################################################
#
# Add CBLAS
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CBLAS_LIBRARIES}")
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CBLAS_LIBRARIES}")
# SI CBLAS necessaire utiliser la ligne cidessous
#SET(SCALFMM_LIBRARIES "${CBLAS_LIBRARIES} ${SCALFMM_LIBRARIES} ")
#
##################################################################
# #
# END SETTING VARIABLES #
......@@ -359,6 +357,8 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CBLAS_LIBRARIES}")
#
# Generate ScalFmmConfig.h
#
SET(ScalFMM_COMPILE_FLAGS "${ScaLFMM_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")
SET(ScalFMM_COMPILE_LIBS "${SCALFMM_LIBRARIES} ")
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/Src/ScalFmmConfig.h.cmake
${CMAKE_BINARY_DIR}/Src/ScalFmmConfig.h )
#
......@@ -438,7 +438,7 @@ endif()
# Build and export cmake files #
# #
##################################################################
#
MESSAGE(STATUS "ScalFMM_BINARY_DIR: " ${ScalFMM_BINARY_DIR})
CONFIGURE_FILE(${ScalFMM_SOURCE_DIR}/ScalFMMConfig.cmake.in
${ScalFMM_BINARY_DIR}/ScalFMMConfig.cmake
......@@ -503,11 +503,11 @@ MESSAGE( STATUS "ScalFMM_USE_LOG = ${ScalFMM_USE_LOG}" )
# Use Assert
MESSAGE( STATUS "ScalFMM_USE_ASSERT = ${ScalFMM_USE_ASSERT}" )
#
MESSAGE(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")
#MESSAGE(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
#SET(CMAKE_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")
MESSAGE(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
MESSAGE(STATUS "ScaLFMM_CXX_FLAGS = ${ScaLFMM_CXX_FLAGS}")
MESSAGE(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
MESSAGE(STATUS "SCALFMM_CXX_FLAGS = ${ScaLFMM_CXX_FLAGS}")
MESSAGE(STATUS "SCALFMM_LIBRARIES = ${SCALFMM_LIBRARIES}")
MESSAGE(STATUS "SCALFMM_INCLUDES = ${SCALFMM_INCLUDES}")
##################################################################
......
......@@ -106,7 +106,7 @@ const std::string SCALFMMDataPath("@CMAKE_SOURCE_DIR@/Data/");
///////////////////////////////////////////////////////
// Flags and libs used to compile
///////////////////////////////////////////////////////
const std::string SCALFMMCompileFlags("@CMAKE_COMPILE_FLAGS@");
const std::string SCALFMMCompileLibs("@CMAKE_COMPILE_LIBS@");
const std::string SCALFMMCompileFlags("@ScalFMM_COMPILE_FLAGS@");
const std::string SCALFMMCompileLibs("@ScalFMM_COMPILE_LIBS@");
#endif // CONFIG_H
/*
* genarateDistributions.cpp
*
* Created on: 23 mars 2014
* Author: Olivier Coulaud
*/
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
//
#include "Utils/FGlobal.hpp"
#include "Utils/FPoint.hpp"
#include "Files/FFmaGenericLoader.hpp"
#include "Files/FDlpolyLoader.hpp"
#include "Utils/FParameters.hpp"
#include "Utils/FGenerateDistribution.hpp"
//
/// \file stamp2Fma.cpp
//!
//! \brief changeFormat: Driver to transform a stamp format to FMA format and to build a visualization file
//!
//! Driver to transform a FMA format and/or to build a visualization file<br>
//! For a description of the FMA format see FFmaGenericLoader<br>
//! <b> General arguments:</b>
//! \param -help (-h) to see the parameters available in this driver
//! \param -fin name: file name to convert (with extension .fma (ascii) or bfma (binary)
//! \param -fdlpoly name file coming from a DLpoly simulation
//!
//! \param -fout name: generic name for files (without extension) and save data
//! with following format in name.fma or name.bfma if -bin is set"
//! \param -bin save output in binary mode (name file name.bfma
//! \param -visufmt format for the visu file (vtk, vtp, cvs or cosmo). vtp is the default
//!
//!
//! \b examples
//!
//! Transform an ascii file in a binary file
//!
//! changeFormat -fin unitCubeXYZQ100.fma -fout unitCubeXYZQ100 -bin
//
//
void genDistusage() {
std::cout << "Driver to change the format of the input file"
<< std::endl;
std::cout << "Options "<< std::endl
<< " -help to see the parameters " << std::endl
<< " Input: only one option is allowed" << std::endl
<< " -fin name: file name to convert (with extension .fma (ascii) or bfma (binary) " <<std::endl
<< " -fdlpoly name: file name to convert with extension (.bin if binary file) " <<std::endl
<< " Output " << std::endl
<< " -fout name: generic name for files (without extension) and save data" <<std::endl
<< " with following format in name.fma or name.bfma if -bin is set" <<std::endl
<< " -bin save output in binary mode (name file name.bfma)" <<std::endl
<< " -visufmt vtk, vtp, cosmo or cvs format for visualization " <<std::endl;
}
int main(int argc, char ** argv){
//
if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")|| (argc < 3 )){
genDistusage() ;
exit(-1);
}
FSize NbPoints;
FReal * particles = nullptr ;
FFmaGenericLoader * loader;
unsigned int nbData;
bool stampFile = false ;
if (FParameters::existParameter(argc, argv, "-fstamp")) {
stampFile = true ;
}
if (FParameters::existParameter(argc, argv, "-fin")) {
const std::string filename(FParameters::getStr(argc,argv,"-fin", "data.fma"));
if(stampFile) {
loader = new FFmaGenericLoader(filename,false);
}
else {
loader = new FFmaGenericLoader(filename) ;
}
//
// Allocation
//
NbPoints = loader->getNumberOfParticles();
nbData = loader->getNbRecordPerline() ;
const unsigned int arraySize =nbData*NbPoints;
//
particles = new FReal[arraySize] ;
std::memset(particles,0,arraySize*sizeof(FReal));
//
// Read Data
int j = 0 ;
for(int idxPart = 0 ; idxPart < NbPoints ;++idxPart, j+=nbData){
// //
loader->fillParticle(&particles[j],nbData);
// std::cout << "idxPart "<< idxPart << " ";
// for (int jj= 0 ; jj<nbData ; ++jj, ++k){
// std::cout << particles[k] << " ";
// }
// std::cout << std::endl;
}
if(stampFile) {
j=0 ;
FReal D= loader->getBoxWidth();
for(int idxPart = 0 ; idxPart < NbPoints ;++idxPart, j+=nbData){
particles[j] *= D ;
particles[j+1] *= D ;
particles[j+2] *= D ;
}
}
// if(FParameters::existParameter(argc, argv, "-fdlpoly")){
// FDlpolyLoader *loader = nullptr ;
// // if(FParameters::existParameter(argc, argv, "-bin")){
// // loader = new FDlpolyBinLoader(filenameEwaldIn.c_str());
// // }
// // else {
// // loader = new FDlpolyAsciiLoader(filenameEwaldIn.c_str());
// // }
// // NbPoints = loader->getNumberOfParticles() ;
// // particles = new FReal[arraySize] ;
// // std::memset(particles,0,arraySize*sizeof(FReal));
// // for(int idxPart = 0 ; idxPart < NbPoints ; ++idxPart){
// //
// // int index ;
// // FPoint P ; FReal t[3];
// /// / loader->fillParticle(&P, t, &physicalValue,&index);
// // particles[(index-1)*]
// //
// // totalCharge += physicalValue ;
// }
}
else {
genDistusage() ;
return 0;
}
//
/////////////////////////////////////////////////////////////////////////
// Save data
/////////////////////////////////////////////////////////////////////////
//
// Generate file for ScalFMM FMAGenericLoader
//
if(FParameters::existParameter(argc, argv, "-fout")){
std::string name(FParameters::getStr(argc,argv,"-fout", "output"));
std::string ext(".");
if(name.find(ext) !=std::string::npos) {
std::cout << "No file with extension permitted for output name : " << name << std::endl;
exit(-1);
}
if( FParameters::existParameter(argc, argv, "-bin")){
name += ".bfma";
}
else {
name += ".fma";
}
FFmaGenericWriter writer(name) ;
writer.writeHeader( loader->getCenterOfBox(), loader->getBoxWidth() , NbPoints, sizeof(FReal), nbData) ;
writer.writeArrayOfReal(particles, nbData, NbPoints);
}
//
// Generate file for visualization purpose
//
if(FParameters::existParameter(argc, argv, "-visufmt")){
std::string outfilename(FParameters::getStr(argc,argv,"-fout", "output"));
std::string visufile(""), fmt(FParameters::getStr(argc,argv,"-visufmt", "vtp"));
if( fmt == "vtp" ){
visufile = outfilename + ".vtp" ;
}
else if( fmt == "vtk" ){
visufile = outfilename + ".vtk" ;
}
else if( fmt == "cosmo" ){
if(nbData !=4) {
std::cerr << "Cosmos export accept only 4 data per particles. here: "<<nbData<<std::endl;
std::exit(EXIT_FAILURE);
}
visufile = outfilename + ".cosmo" ;
}
else {
visufile = outfilename + ".csv" ;
}
std::ofstream file( visufile, std::ofstream::out);
if(!file) {
std::cout << "Cannot open file."<< std::endl;
exit(-1) ;
} //
//
// Export data in cvs format
//
if( fmt == "vtp" ){
std::cout << "Writes in XML VTP format (visualization) in file "<< visufile <<std::endl ;
if(nbData==4){
exportVTKxml( file, particles, NbPoints) ;
}
else {
exportVTKxml( file, particles, NbPoints,nbData) ;
}
}
else if( fmt == "vtk" ){
std::cout << "Writes in VTK format (visualization) in file "<< visufile <<std::endl ;
exportVTK( file, particles, NbPoints,nbData) ;
}
else if( fmt == "cosmo" ){
std::cout << "Writes in COSMO format (visualization) in file "<< visufile <<std::endl ;
exportCOSMOS( file, particles, NbPoints) ;
}
else {
std::cout << "Writes in CVS format (visualization) in file "<<visufile<<std::endl ;
exportCVS( file, particles, NbPoints,nbData) ;
}
}
//
delete particles ;
//
return 1;
}
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas
// 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".
// ===================================================================================
// ==== CMAKE =====
// @FUSE_BLAS
// ================
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include "ScalFmmConfig.h"
#include "Files/FFmaGenericLoader.hpp"
#include "Kernels/Chebyshev/FChebCell.hpp"
#include "Kernels/Interpolation/FInterpMatrixKernel.hpp"
#include "Kernels/Chebyshev/FChebSymKernel.hpp"
#include "Components/FSimpleLeaf.hpp"
#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp"
#include "Utils/FParameters.hpp"
#include "Containers/FOctree.hpp"
#ifdef _OPENMP
#include "Core/FFmmAlgorithmThread.hpp"
#else
#include "Core/FFmmAlgorithm.hpp"
#endif
#include "Utils/FTemplate.hpp"
/**
* This program runs the FMM Algorithm with the Chebyshev kernel and compares the results with a direct computation.
*/
/// \file ChebyshevInterpolationFMM.cpp
//!
//! \brief This program runs the FMM Algorithm with the interpolation kernel based on Chebyshev interpolation (1/r kernel)
//! \authors B. Bramas, O. Coulaud
//!
//! This code is a short example to use the Chebyshev Interpolation approach for the 1/r kernel
//!
//!@Algorithm
//! <b> General arguments:</b>
//! \param -help(-h) to see the parameters available in this driver
//! \param -depth The depth of the octree
//! \param -subdepth Specifies the size of the sub octree
//! \param -t The number of threads
//!
//! \param -f name Name of the particles file with extension (.fma or .bfma). The data in file have to be in our FMA format
//!
//
void usage() {
std::cout << "Driver for Chebyshev interpolation kernel (1/r kernel)" << std::endl;
std::cout << "Options "<< std::endl
<< " -help to see the parameters " << std::endl
<< " -depth the depth of the octree "<< std::endl
<< " -subdepth specifies the size of the sub octree " << std::endl
<< " -f name name specifies the name of the particle distribution" << std::endl
<< " -t n specifies the number of threads used in the computations" << std::endl;
}
// Simply create particles and try the kernels
struct TempMainStruct{
template <const unsigned int ORDER>
static void Run(int argc, char* argv[])
{
const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma" );
const std::string filename = FParameters::getStr(argc,argv,"-f", defaultFile.c_str());
const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5);
const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2);
const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1);
if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){
usage() ;
exit(EXIT_SUCCESS);
}
#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 timer
FTic time;
// open particle file
////////////////////////////////////////////////////////////////////
//
FFmaGenericLoader loader(filename);
//
FSize nbParticles = loader.getNumberOfParticles() ;
FmaRWParticle<8,8>* const particles = new FmaRWParticle<8,8>[nbParticles];
loader.fillParticle(particles,nbParticles);
FReal energyD = 0.0 ;
/////////////////////////////////////////////////////////////////////////////////////////////////
// Compute direct energy
/////////////////////////////////////////////////////////////////////////////////////////////////
for(int idx = 0 ; idx < nbParticles ; ++idx){
energyD += particles[idx].getPotential()*particles[idx].getPhysicalValue() ;
}
//
////////////////////////////////////////////////////////////////////
// begin Chebyshev kernel
// accuracy
// typedefs
typedef FP2PParticleContainerIndexed<> ContainerClass;
typedef FSimpleLeaf< ContainerClass > LeafClass;
typedef FChebCell<ORDER> CellClass;
typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass;
//
typedef FInterpMatrixKernelR MatrixKernelClass;
typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass;
//
#ifdef _OPENMP
typedef FFmmAlgorithmThread<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass;
#else
typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass;
#endif
// init oct-tree
OctreeClass tree(TreeHeight, SubTreeHeight, loader.getBoxWidth(), loader.getCenterOfBox());
{ // -----------------------------------------------------
std::cout << "Creating & Inserting " <<nbParticles
<< " particles ..." << std::endl;
std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl;
time.tic();
//
for(int idxPart = 0 ; idxPart < nbParticles; ++idxPart){
//
// Read particle per particle from file
//
// put particle in octree
tree.insert(particles[idxPart].getPosition() , idxPart, particles[idxPart].getPhysicalValue() );
}
time.tac();
std::cout << "Done " << "(@Creating and Inserting Particles = "
<< time.elapsed() << " s) ." << std::endl;
} // -----------------------------------------------------
{ // -----------------------------------------------------
std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ") ... " << std::endl;
const MatrixKernelClass matrixClass;
time.tic();
//
KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(),&matrixClass);
//
FmmClass algorithm(&tree, &kernels);
//
algorithm.execute(); // Here the call of the FMM algorithm
//
time.tac();
std::cout << "Done " << "(@Algorithm = " << time.elapsed() << " s) ." << std::endl;
}
// -----------------------------------------------------
//
// Some output
//
//
{ // -----------------------------------------------------
FReal energy =0.0;
//
// Loop over all leaves
//
std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl;
std::cout << std::scientific;
std::cout.precision(10) ;
/////////////////////////////////////////////////////////////////////////////////////////////////
// Compare
/////////////////////////////////////////////////////////////////////////////////////////////////
printf("Compute Diff...");
FMath::FAccurater potentialDiff;
FMath::FAccurater fx, fy, fz, f;
{ // Check that each particle has been summed with all other
tree.forEachLeaf([&](LeafClass* leaf){
const FReal*const potentials = leaf->getTargets()->getPotentials();
const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues();
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 FVector<int>& indexes = leaf->getTargets()->getIndexes();
for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){
const int indexPartOrig = indexes[idxPart];
potentialDiff.add(particles[indexPartOrig].getPotential(),potentials[idxPart]);
fx.add(particles[indexPartOrig].getForces()[0],forcesX[idxPart]);