Commit c370ea26 authored by Berenger Bramas's avatar Berenger Bramas

remove FmmApi

parent 89fb25fe
# check if compiling into source directories
STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" insource)
if(insource)
MESSAGE(FATAL_ERROR "${PROJECT_NAME} requires an out of source build. Goto ./Build and tapes cmake ../")
endif(insource)
project(Addons_fmmapi_scalfmm CXX)
ADD_DEFINITIONS( ${ScaLFMM_CXX_FLAGS})
# Active language
# -----------------------
ENABLE_LANGUAGE(CXX )
MESSAGE(STATUS " CXX ${CMAKE_CXX_COMPILER_ID}" )
# Options
OPTION( SCALFMM_ADDON_FMMAPI "Set to ON to build ScaFMM FMM API interface" OFF )
# if ask to build addon
if(SCALFMM_ADDON_FMMAPI)
# first build lib scalfmmapi
set(LIBRARY_OUTPUT_PATH ../lib/${CMAKE_BUILD_TYPE})
# Searching all cpp file
file( GLOB_RECURSE source_lib_files Src/*.cpp )
# Adding cpp files to project
add_library( scalfmmapi ${source_lib_files} )
# Add blas library (even if it is set to off)
target_link_libraries( scalfmmapi scalfmm)
# Adding the entire project dir as an include dir
INCLUDE_DIRECTORIES(
${SCALFMM_BINARY_DIR}/Src
${SCALFMM_SOURCE_DIR}/Src
${SCALFMM_INCLUDES}
)
# Install lib
install( TARGETS scalfmmapi ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
# Install header
SET(my_include_dirs "Src")
file( GLOB hpp_in_dir Src/*.hpp )
INSTALL( FILES ${hpp_in_dir} DESTINATION include/ScalFmm/FmmApi )
file( GLOB_RECURSE source_tests_files Tests/*.cpp )
INCLUDE_DIRECTORIES( ${SCALFMM_BINARY_DIR}/Src )
# Then build test files
foreach(exec ${source_tests_files})
get_filename_component(
execname ${exec}
NAME_WE
)
set(compile_exec "TRUE")
foreach(fuse_key ${FUSE_LIST})
file(STRINGS "${exec}" lines_fuse REGEX "@FUSE_${fuse_key}")
if(lines_fuse)
if( NOT SCALFMM_USE_${fuse_key} )
MESSAGE( STATUS "This needs ${fuse_key} = ${exec}" )
set(compile_exec "FALSE")
endif()
endif()
endforeach()
# Dependency are OK
if( compile_exec )
add_executable( ${execname} ${exec} )
# link to scalfmm and scalfmmapi
target_link_libraries(
${execname}
${scalfmm_lib}
scalfmmapi
${BLAS_LIBRARIES}
${LAPACK_LIBRARIES}
${SCALFMM_LIBRARIES}
)
endif()
endforeach(exec)
endif()
// ===================================================================================
// Logiciel initial: ScalFmm Version 0.5
// Co-auteurs : Olivier Coulaud, Bérenger Bramas.
// Propriétaires : INRIA.
// Copyright © 2011-2012, diffusé sous les termes et conditions d’une licence propriétaire.
// Initial software: ScalFmm Version 0.5
// Co-authors: Olivier Coulaud, Bérenger Bramas.
// Owners: INRIA.
// Copyright © 2011-2012, spread under the terms and conditions of a proprietary license.
// ===================================================================================
#ifndef FMMAPI_H
#define FMMAPI_H
enum FmmApiErrors {
FMMAPI_NO_ERROR,
FMMAPI_SUPPORTED_PARAMETER,
FMMAPI_UNSUPPORTED_PARAMETER,
FMMAPI_UNKNOWN_PARAMETER
};
////////////////////// Opérateurs FMM Core : //////////////////////////
enum FmmApiCoreParameters {
FMMCORE_TREE_HEIGHT, // hombre de niveaux de l'arbre (int)
FMMCORE_ROOT_BOX_WIDTH, // taille de la boîte racine (FReal)
FMMCORE_ROOT_BOX_CENTER, // position du centre de la boîte racine (FReal[3])
FMMCORE_LEAF_BOX_WIDTH, // taille des boîtes feuilles (FReal)
FMMCORE_POINTS_PER_LEAF, // nombre moyen de points par feuille (FReal)
FMMCORE_MPI_COMMUNICATOR, // communicateur MPI (MPI_Comm)
FMMCORE_THREADS_NUMBER, // nombre de threads (int)
FMMCORE_THREAD_ID, // id du thread (int)
FMMCORE_RHS_NUMBER, // nombre de seconds membres (int)
//paramètres en lecture seule :
FMMCORE_HANDLES_P2P // renvoie 0 ou 1 pour dire si le FmmCore gère ou pas le P2P.
};
int FmmCore_init(void **fmmCore) ; /*alloue et initialise le FmmCore*/
int FmmCore_free(void *fmmCore) ; /*libère le FmmCore*/
int FmmCore_isParameterUsed(void */*fmmCore*/, int *name, int *flag);
int FmmCore_setParameter(void *fmmCore, int *name, void*value);
int FmmCore_setParameter(void *fmmCore, int name, void*value);
int FmmCore_getParameter(void *fmmCore, int *name, void*value);
int FmmCore_getParameter(void *fmmCore, int name, void*value);
int FmmCore_getRadius(void*fmmCore, void *boxId, FReal *radius);/*Renvoie le rayon de la boîte*/
int FmmCore_getCentre(void*/*fmmCore*/, void *boxId, FReal **centre); /*Renvoie dans le FReal[3] centre les coordonnées du centre*/
int FmmCore_getLevel(void*/*fmmCore*/, void *boxId, int *level); /*Renvoie dans level le niveau de la boîte boxId dans son arbre*/
int FmmCore_getMultipoleArray(void* /*fmmCore*/, void *boxId, void **F); /*Renvoie dans F l'adresse où stocker l'expansion multipôle associée à la boîte boxId*/
int FmmCore_getLocalArray(void* /*fmmCore*/, void *boxId, void **F); /*Renvoie dans F l'adresse où stocker l'expansion locale associée à la boîte boxId*/
int FmmCore_getCoord(void*/*fmmCore*/, void *boxId, int *coord); /*Renvoie dans coord la position dans l'arbre*/
/* Données potentiel/champ */
int FmmCore_getSource(void* /*fmmCore*/, void *boxId, FReal** position, void** potential, int *number); /* Appelé par P2P et P2M pour obtenir le nombre, la position et le potentiel des sources.
Les différents tableaux sont (éventuellement) alloués par le FmmCore. */
int FmmCore_releaseSource(void*fmmCore, void *boxId, void* potential, FReal* position); /* si le core veut libérer ces tableaux potentiel et position.*/
int FmmCore_getTargetPoints(void* /*fmmCore*/, void *boxId, FReal** position, int *number) ; /* : Appelé par P2P et L2P pour obtenir le nombre et la position des points cibles.*/
int FmmCore_releaseTargetPoints(void*fmmCore, void *boxId, FReal* position); /* si le core veut libérer ce tableau "position".*/
int FmmCore_getTargetField(void* /*fmmCore*/, void *boxId, FReal* F); /* obtient dans un tableau F alloué/libéré par L2P/P2P les valeurs des champs aux points cible
(pour le cas où P2P et L2P doivent sommer leurs résultats).*/
int FmmCore_setTargetField(void* /*fmmCore*/, void *boxId, FReal* F); /* transmets au FmmCore dans F les valeurs des champs aux points cibles mis à jour.*/
/* Entrée/sortie principale */
int FmmCore_setKernelData(void *fmmCore, void *fmmKernel); /* stocke l'identifiant du FmmKernel dans le FmmCore. Cela permet par la suite aux
opérateurs FMM d'accéder au FmmKernel, et donc d'accéder aux données spécifiques au kernel
(p.ex. fréquence dans le cas Helmholtz, …)*/
int FmmCore_getKernelData(void*fmmCore, void **fmmKernel); /* récupère l'identifiant du FmmKernel. */
int FmmCore_setPositions(void *fmmCore, int *nb, FReal *position) ; /* transmet au FmmCore les potentiels associés aux points sources.
Le tableau potential est alloué et libéré par la routine appelant, le FmmCore doit donc en faire une copie.*/
int FmmCore_setPotentials(void *fmmCore, void *potentials); /* transmet au FmmCore les potentiels associés aux points sources.
Le tableau potential est alloué et libéré par la routine appelant, le FmmCore doit donc en faire une copie.*/
int FmmCore_doComputation(void *fmmCore) ; /* réalise le produit multipôle. */
/* !!! Warning use *filed and not **field */
int FmmCore_getField(void *fmmCore, void *fields) ;/* récupère après le produit multipôle la valeur des champs en chaque point.
Le tableau field doit être alloué et libéré par la routine appelante. */
////////////////////// Opérateurs FMM Kernel : //////////////////////////
enum FmmApiKernelParameters {
FMMKERNEL_ACCURACY, // précision demandée à la FMM : 1e-3, 1e-6, ... (FReal)
FMMKERNEL_POTENTIAL_DATA_SIZE, // taille en octet de la donnée "potentiel" pour 1 point source (int)
FMMKERNEL_FIELD_DATA_SIZE, // taille en octet de la donnée "field" pour 1 point cible (int)
//paramètres en lecture seule :
FMMKERNEL_HANDLES_P2P // renvoie 0 ou 1 pour dire si le FmmKernel gère ou pas le P2P.
};
/******* Allocation : ******/
int FmmKernel_init(void *fmmCore, void **fmmKernel);/* : alloue et initialise le FmmKernel */
int FmmKernel_free(void *fmmKernel); /* libére le FmmKernel */
/******* Configuration : ***/
int FmmKernel_isParameterUsed(void * /*fmm*/, int *name, int *flag);
int FmmKernel_setParameter(void *fmmKernel, int *name, void*value);
int FmmKernel_setParameter(void *fmmKernel, int name, void*value);
int FmmKernel_getParameter(void *fmmKernel, int *name, void*value);
int FmmKernel_getParameter(void *fmmKernel, int name, void*value);
/****** Données FMM : *****/
int FmmKernel_getMultipoleArraySize(void *fmmCore, int *size); /* Renvoie dans size la taille (en octets) de l'expansion multipôle associée à la boîte boxId */
int FmmKernel_getLocalArraySize(void *fmmCore, int *size); /* Renvoie dans size la taille (en octets) de l'expansion locale associée à la boîte boxId*/
/******* Opérateurs FMM : **/
int FmmKernel_P2M(void *fmmCore, void* boxId);
int FmmKernel_L2P(void *fmmCore, void* boxId);
int FmmKernel_M2M(void *fmmCore, void *boxIdFather, void *boxIdSon);
int FmmKernel_L2L(void *fmmCore, void *boxIdFather, void *boxIdSon);
int FmmKernel_M2L(void *fmmCore, void *boxIdSrc, void *boxIdDest);
int FmmKernel_P2P_inner(void *fmmCore, void *boxIdSrcDest);
int FmmKernel_P2P(void *fmmCore, void *boxIdSrc, void *boxIdDest); /* pas mutuel, i.e. on fait seulement dans 1 sens. */
#endif // FMMAPI_H
This diff is collapsed.
This diff is collapsed.
// ===================================================================================
// Logiciel initial: ScalFmm Version 0.5
// Co-auteurs : Olivier Coulaud, Bérenger Bramas.
// Propriétaires : INRIA.
// Copyright © 2011-2012, diffusé sous les termes et conditions d’une licence propriétaire.
// Initial software: ScalFmm Version 0.5
// Co-authors: Olivier Coulaud, Bérenger Bramas.
// Owners: INRIA.
// Copyright © 2011-2012, spread under the terms and conditions of a proprietary license.
// ===================================================================================
#include <iostream>
#include <cstdio>
#include "../../Src/Utils/FParameters.hpp"
#include "../../Src/Utils/FTic.hpp"
#include "../../Src/Utils/FMemUtils.hpp"
#include "../../Src/Files/FRandomLoader.hpp"
#include "../Src/FmmApi.h"
/** This program show an example of use of the fmm api
*/
// Simply create particles and try the kernels
int main(int argc, char ** argv){
///////////////////////What we do/////////////////////////////
std::cout << ">> This executable has to be used to test the FMM API\n";
//////////////////////////////////////////////////////////////
int NbLevels = FParameters::getValue(argc,argv,"-h", 7);
int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3);
const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000);
FTic counter;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
FRandomLoader<FReal> loader(NbPart, 1, FPoint<FReal>(0.5,0.5,0.5), 1);
void* FmmCoreHandle;
FmmCore_init(&FmmCoreHandle);
FmmCore_setParameter(FmmCoreHandle, FMMCORE_TREE_HEIGHT, &NbLevels);
FReal boxWidth = loader.getBoxWidth();
FmmCore_setParameter(FmmCoreHandle, FMMCORE_ROOT_BOX_WIDTH, &boxWidth);
FmmCore_setParameter(FmmCoreHandle, FMMCORE_ROOT_BOX_CENTER, loader.getCenterOfBox().getDataValue());
void* FmmKernelHandle;
FmmKernel_init(FmmCoreHandle, &FmmKernelHandle);
FmmCore_setKernelData(FmmCoreHandle, FmmKernelHandle);
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Creating & Inserting " << NbPart << " particles ..." << std::endl;
std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl;
counter.tic();
FSize r.getNumberOfParticles();
FReal* potentials = new FReal[nbPart];
FReal* positions = new FReal[nbPart*3];
{
FPoint<FReal> part;
const FReal physicalValue = 0.1;
for(int idx = 0 ; idx < nbPart ; ++idx){
loader.fillParticle(&part);
potentials[idx] = physicalValue;
positions[3*idx] = part.getX();
positions[3*idx+1] = part.getY();
positions[3*idx+2] = part.getZ();
}
FmmCore_setPositions(FmmCoreHandle, &nbPart, positions);
FmmCore_setPotentials(FmmCoreHandle, potentials);
}
counter.tac();
std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Working on particles ..." << std::endl;
counter.tic();
FmmCore_doComputation(FmmCoreHandle);
counter.tac();
std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Getting results ..." << std::endl;
counter.tic();
FReal* fields = new FReal[4*nbPart];
FmmCore_getField(FmmCoreHandle, fields);
counter.tac();
std::cout << "Done " << "(@retrieve = " << counter.elapsed() << "s)." << std::endl;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Computing direct ..." << std::endl;
counter.tic();
FReal* fieldsdirect = new FReal[4*nbPart];
FMemUtils::setall(fieldsdirect, 0.0, nbPart * 4);
for(int idxTarget = 0 ; idxTarget < nbPart ; ++idxTarget){
for(int idxSource = idxTarget + 1 ; idxSource < nbPart ; ++idxSource){
FReal dx = positions[idxSource*3] - positions[idxTarget*3];
FReal dy = positions[idxSource*3+1] - positions[idxTarget*3+1];
FReal dz = positions[idxSource*3+2] - positions[idxTarget*3+2];
FReal inv_square_distance = FReal(1.0) / (dx*dx + dy*dy + dz*dz);
FReal inv_distance = FMath::Sqrt(inv_square_distance);
inv_square_distance *= inv_distance;
inv_square_distance *= potentials[idxTarget] * potentials[idxSource];
dx *= inv_square_distance;
dy *= inv_square_distance;
dz *= inv_square_distance;
fieldsdirect[4*idxTarget+1] += dx;
fieldsdirect[4*idxTarget+2] += dy;
fieldsdirect[4*idxTarget+3] += dz;
fieldsdirect[4*idxTarget+0] += inv_distance * potentials[idxSource];
fieldsdirect[4*idxSource+1] += -dx;
fieldsdirect[4*idxSource+2] += -dy;
fieldsdirect[4*idxSource+3] += -dz;
fieldsdirect[4*idxSource+0] += inv_distance * potentials[idxTarget];
}
}
counter.tac();
std::cout << "Done " << "(@direct = " << counter.elapsed() << "s)." << std::endl;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Comparing results ..." << std::endl;
counter.tic();
FMath::FAccurater<FReal> forces;
FMath::FAccurater<FReal> potential;
for(int idx = 0 ; idx < nbPart ; ++idx){
if(idx < 10){
std::cout << fieldsdirect[4*idx] << " fmm " << fields[4*idx] << std::endl;
}
forces.add( fieldsdirect[4*idx] ,fields[4*idx]);
forces.add( fieldsdirect[4*idx+1] ,fields[4*idx+1]);
forces.add( fieldsdirect[4*idx+2] ,fields[4*idx+2]);
potential.add( fieldsdirect[4*idx+3] ,fields[4*idx+3]);
}
counter.tac();
std::cout << "Done " << "(@comparing = " << counter.elapsed() << "s)." << std::endl;
std::cout << "\tForces inf " << forces.getInfNorm() << " normL2 " << forces.getL2Norm() << std::endl;
std::cout << "\tPotential inf " << potential.getInfNorm() << " normL2 " << potential.getL2Norm() << std::endl;
//////////////////////////////////////////////////////////////////////////////////
delete[] fieldsdirect;
delete[] fields;
delete[] potentials;
delete[] positions;
FmmCore_free(FmmCoreHandle);
FmmKernel_free(FmmKernelHandle);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment