Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
solverstack
ScalFMM
Commits
7a0e0bd9
Commit
7a0e0bd9
authored
Sep 03, 2014
by
BRAMAS Berenger
Browse files
Add an extremly basic C API in order to implement a kernel
parent
624f3999
Changes
4
Hide whitespace changes
Inline
Side-by-side
Addons/CKernelApi/CMakeLists.txt
0 → 100755
View file @
7a0e0bd9
# 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_ckernelapi_scalfmm CXX C
)
set
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
${
ScaLFMM_CXX_FLAGS
}
"
)
# Active language
# -----------------------
ENABLE_LANGUAGE
(
CXX C
)
MESSAGE
(
STATUS
" CXX
${
CMAKE_CXX_COMPILER_ID
}
"
)
# Options
OPTION
(
SCALFMM_ADDON_CKERNELAPI
"Set to ON to build ScaFMM FMM API interface"
OFF
)
# if ask to build addon
if
(
SCALFMM_ADDON_CKERNELAPI
)
# first build lib scalfmmckernelapi
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
(
scalfmmckernelapi STATIC
${
source_lib_files
}
)
# Add blas library (even if it is set to off)
target_link_libraries
(
scalfmmckernelapi scalfmm
)
# Adding the entire project dir as an include dir
INCLUDE_DIRECTORIES
(
${
CMAKE_BINARY_DIR
}
/Src
${
CMAKE_SOURCE_DIR
}
/Src
${
SCALFMM_INCLUDES
}
)
# Install lib
install
(
TARGETS scalfmmckernelapi ARCHIVE DESTINATION lib
)
# Install header
SET
(
my_include_dirs
"Src"
)
file
(
GLOB hpp_in_dir Src/*.hpp
)
INSTALL
(
FILES
${
hpp_in_dir
}
DESTINATION include/ScalFmm/CKernelApi
)
file
(
GLOB_RECURSE source_tests_files Tests/*.c
)
INCLUDE_DIRECTORIES
(
${
CMAKE_BINARY_DIR
}
/Src
)
# Then build test files
foreach
(
exec
${
source_tests_files
}
)
get_filename_component
(
execname
${
exec
}
NAME_WE
)
set
(
compile_exec
"TRUE"
)
# Test Blas dependency
file
(
STRINGS
"
${
exec
}
"
lines_blas REGEX
"@FUSE_BLAS"
)
if
(
lines_blas
)
if
(
NOT SCALFMM_USE_BLAS
)
MESSAGE
(
STATUS
"This needs BLAS =
${
exec
}
"
)
set
(
compile_exec
"FALSE"
)
endif
()
endif
()
# Test MPI dependency
file
(
STRINGS
"
${
exec
}
"
lines_mpi REGEX
"@FUSE_MPI"
)
if
(
lines_mpi
)
if
(
NOT SCALFMM_USE_MPI
)
MESSAGE
(
STATUS
"This needs MPI =
${
exec
}
"
)
set
(
compile_exec
"FALSE"
)
endif
()
endif
()
# Dependency are OK
if
(
compile_exec
)
add_executable
(
${
execname
}
${
exec
}
)
# link to scalfmm and scalfmmckernelapi
target_link_libraries
(
${
execname
}
${
scalfmm_lib
}
scalfmmckernelapi
# ${BLAS_LIBRARIES}
# ${LAPACK_LIBRARIES}
${
SCALFMM_LIBRARIES
}
)
endif
()
endforeach
(
exec
)
endif
()
Addons/CKernelApi/Src/CKernelApi.h
0 → 100755
View file @
7a0e0bd9
// ===================================================================================
// 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 CKERNELAPI_H
#define CKERNELAPI_H
/**
* This file defines the API for the USER.
* We briefly comment all the functions.
* The objective of the C Kernel API is to give a quick and easy way
* to anyone (who can program in C) to implement a kernel.
* Using C++ is advised but this is a simple alternative.
*/
///////////////////////////////////////////////////////////////////////////
/// Init part
///////////////////////////////////////////////////////////////////////////
//< For the user an handle is a void*
typedef
void
*
Scalfmm_Handle
;
//< Function to init the cells (should be given by the user when calling Scalfmm_init_cell)
//< it gives the level of the cell, its morton index, it position in term of box at that level
//< and the spatial position of its center
typedef
void
*
(
*
Callback_init_cell
)(
int
level
,
long
long
morton_index
,
int
*
tree_position
,
double
*
spatial_position
);
//< Function to destroy what have bee initalized by the user (should be give in Scalfmm_dealloc_handle)
typedef
void
(
*
Callback_free_cell
)(
void
*
);
//< This function init an handle (and an tree based on the given properties)
Scalfmm_Handle
Scalfmm_init_handle
(
int
treeHeight
,
double
boxWidth
,
double
*
boxCenter
);
//< This function should be used to dealloc our handle
void
Scalfmm_dealloc_handle
(
Scalfmm_Handle
handle
,
Callback_free_cell
cellDestroyer
);
//< This function should be used to insert an array of particle in the tree
//< The indexes are the one used on the particles operator
//< The posision of the particles should be composed of one triple per particle:
//< xyzxyzxyz...
void
Scalfmm_insert_array_of_particles
(
Scalfmm_Handle
handle
,
int
nbParticles
,
int
*
particleIndexes
,
double
*
particleXYZ
);
//< To insert one particle only
void
Scalfmm_one_particle
(
Scalfmm_Handle
handle
,
int
particleIndexe
,
double
x
,
double
y
,
double
z
);
//< This function should be called to init the cells
//< It must be called after all the particles have been inserted!
void
Scalfmm_init_cell
(
Scalfmm_Handle
handle
,
Callback_init_cell
cellInitializer
);
///////////////////////////////////////////////////////////////////////////
/// Kernel part
///////////////////////////////////////////////////////////////////////////
//< These function are the callbacks of the FMM operators
typedef
void
(
*
Callback_P2M
)(
void
*
leafCell
,
int
nbParticles
,
const
int
*
particleIndexes
,
void
*
userData
);
typedef
void
(
*
Callback_M2M
)(
int
level
,
void
*
parentCell
,
int
childPosition
,
void
*
childCell
,
void
*
userData
);
typedef
void
(
*
Callback_M2L
)(
int
level
,
void
*
targetCell
,
int
sourceCellPosition
,
void
*
sourceCell
,
void
*
userData
);
typedef
void
(
*
Callback_L2L
)(
int
level
,
void
*
parentCell
,
int
childPosition
,
void
*
childCell
,
void
*
userData
);
typedef
void
(
*
Callback_L2P
)(
void
*
leafCell
,
int
nbParticles
,
int
*
particleIndexes
,
void
*
userData
);
typedef
void
(
*
Callback_P2P
)(
int
nbParticles
,
const
int
*
particleIndexes
,
int
nbSourceParticles
,
const
int
*
sourceParticleIndexes
,
void
*
userData
);
typedef
void
(
*
Callback_P2PInner
)(
int
nbParticles
,
int
*
particleIndexes
,
void
*
userData
);
//< This structure should be filled (or filled with null) to call the FMM
struct
Scalfmm_Kernel_Descriptor
{
Callback_P2M
p2m
;
Callback_M2M
m2m
;
Callback_M2L
m2l
;
Callback_L2L
l2l
;
Callback_L2P
l2p
;
Callback_P2P
p2p
;
Callback_P2PInner
p2pinner
;
};
//< Execute one FMM using the given kernel, the userData is the one given in all the operators as last
//< parameter.
void
Scalfmm_execute_kernel
(
Scalfmm_Handle
handle
,
struct
Scalfmm_Kernel_Descriptor
userKernel
,
void
*
userData
);
///////////////////////////////////////////////////////////////////////////
/// Util functions
///////////////////////////////////////////////////////////////////////////
//< This function fill the childFullPosition[3] with [0;1] to know the position of a child relatively to
//< its position from its parent
inline
void
Scalfmm_utils_parentChildPosition
(
int
childPosition
,
int
*
childFullPosition
){
childFullPosition
[
0
]
=
childPosition
%
2
;
childFullPosition
[
1
]
=
(
childPosition
/
2
)
%
2
;
childFullPosition
[
2
]
=
(
childPosition
/
4
)
%
2
;
}
//< This function fill the childFullPosition[3] with [-3;3] to know the position of a interaction
//< cell relatively to its position from the target
inline
void
Scalfmm_utils_interactionPosition
(
int
interactionPosition
,
int
*
srcPosition
){
srcPosition
[
0
]
=
interactionPosition
%
7
-
3
;
srcPosition
[
1
]
=
(
interactionPosition
/
7
)
%
7
-
3
;
srcPosition
[
2
]
=
(
interactionPosition
/
49
)
%
7
-
3
;
}
#endif // CKERNELAPI_H
Addons/CKernelApi/Src/ScalfmmCKernelApiCore.cpp
0 → 100755
View file @
7a0e0bd9
// ===================================================================================
// 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 "../../Src/Containers/FOctree.hpp"
#include "../../Src/Containers/FVector.hpp"
#include "../../Src/Components/FSimpleLeaf.hpp"
#include "../../Src/Components/FBasicCell.hpp"
#include "../../Src/Utils/FPoint.hpp"
#include "../../Src/Core/FFmmAlgorithmThread.hpp"
#include "../../Src/Components/FBasicKernels.hpp"
#include "../../Src/Components/FBasicParticleContainer.hpp"
/** It should be compiled with C export */
extern
"C"
{
#include "CKernelApi.h"
}
/**
* This file contains the code to have a C Kernel API
* working. It is simply a wrapper with light cell and
* kernel in order to delegate the calls to the API.
*
* The user should allocate the cell data (and deallocate them).
*/
/**
* The core cell is a basic cell + data from the user.
* The cell is not responsible to allocate or deallocate the user data.
*/
class
CoreCell
:
public
FBasicCell
{
// Mutable in order to work with the API
mutable
void
*
userData
;
public:
CoreCell
()
:
userData
(
nullptr
)
{
}
~
CoreCell
(){
}
void
setContainer
(
void
*
inContainer
)
const
{
userData
=
inContainer
;
}
void
*
getContainer
()
const
{
return
userData
;
}
};
/**
* This class simply call the function pointers from Scalfmm_Kernel_Descriptor.
* If not pointer is set the calls are skipped.
* The userData is given at any calls.
*/
template
<
class
CellClass
,
class
ContainerClass
>
class
CoreKernel
:
public
FAbstractKernels
<
CellClass
,
ContainerClass
>
{
struct
Scalfmm_Kernel_Descriptor
kernel
;
void
*
userData
;
public:
CoreKernel
(
struct
Scalfmm_Kernel_Descriptor
inKernel
,
void
*
inUserData
)
:
kernel
(
inKernel
)
,
userData
(
inUserData
){
}
/** Default destructor */
virtual
~
CoreKernel
(){
}
/** Do nothing */
virtual
void
P2M
(
CellClass
*
const
cell
,
const
ContainerClass
*
const
container
)
{
if
(
kernel
.
p2m
)
kernel
.
p2m
(
cell
->
getContainer
(),
container
->
getNbParticles
(),
container
->
getAttribute
(
0
),
userData
);
}
/** Do nothing */
virtual
void
M2M
(
CellClass
*
const
FRestrict
cell
,
const
CellClass
*
const
FRestrict
*
const
FRestrict
children
,
const
int
level
)
{
if
(
kernel
.
m2m
){
for
(
int
idx
=
0
;
idx
<
8
;
++
idx
){
if
(
children
[
idx
]
){
kernel
.
m2m
(
level
,
cell
->
getContainer
(),
idx
,
children
[
idx
]
->
getContainer
(),
userData
);
}
}
}
}
/** Do nothing */
virtual
void
M2L
(
CellClass
*
const
FRestrict
cell
,
const
CellClass
*
interactions
[],
const
int
,
const
int
level
)
{
if
(
kernel
.
m2l
){
for
(
int
idx
=
0
;
idx
<
343
;
++
idx
){
if
(
interactions
[
idx
]
){
kernel
.
m2l
(
level
,
cell
->
getContainer
(),
idx
,
interactions
[
idx
]
->
getContainer
(),
userData
);
}
}
}
}
/** Do nothing */
virtual
void
L2L
(
const
CellClass
*
const
FRestrict
cell
,
CellClass
*
FRestrict
*
const
FRestrict
children
,
const
int
level
)
{
if
(
kernel
.
l2l
){
for
(
int
idx
=
0
;
idx
<
8
;
++
idx
){
if
(
children
[
idx
]
){
kernel
.
l2l
(
level
,
cell
->
getContainer
(),
idx
,
children
[
idx
]
->
getContainer
(),
userData
);
}
}
}
}
/** Do nothing */
virtual
void
L2P
(
const
CellClass
*
const
cell
,
ContainerClass
*
const
container
){
if
(
kernel
.
l2p
)
kernel
.
l2p
(
cell
->
getContainer
(),
container
->
getNbParticles
(),
container
->
getAttribute
(
0
),
userData
);
}
/** Do nothing */
virtual
void
P2P
(
const
FTreeCoordinate
&
,
ContainerClass
*
const
FRestrict
targets
,
const
ContainerClass
*
const
FRestrict
/*sources*/
,
ContainerClass
*
const
neighbors
[
27
],
const
int
){
if
(
kernel
.
p2pinner
)
kernel
.
p2pinner
(
targets
->
getNbParticles
(),
targets
->
getAttribute
(
0
),
userData
);
if
(
kernel
.
p2p
){
for
(
int
idx
=
0
;
idx
<
27
;
++
idx
){
if
(
neighbors
[
idx
]
){
kernel
.
p2p
(
targets
->
getNbParticles
(),
targets
->
getAttribute
(
0
),
neighbors
[
idx
]
->
getNbParticles
(),
neighbors
[
idx
]
->
getAttribute
(
0
),
userData
);
}
}
}
}
/** Do nothing */
virtual
void
P2PRemote
(
const
FTreeCoordinate
&
,
ContainerClass
*
const
FRestrict
,
const
ContainerClass
*
const
FRestrict
,
ContainerClass
*
const
[
27
],
const
int
){
}
};
// Here are all the type definition
typedef
FBasicParticleContainer
<
1
,
int
>
CoreContainerClass
;
typedef
FSimpleLeaf
<
CoreContainerClass
>
LeafClass
;
typedef
FOctree
<
CoreCell
,
CoreContainerClass
,
LeafClass
>
OctreeClass
;
typedef
CoreKernel
<
CoreCell
,
CoreContainerClass
>
CoreKernelClass
;
typedef
FFmmAlgorithmThread
<
OctreeClass
,
CoreCell
,
CoreContainerClass
,
CoreKernelClass
,
LeafClass
>
FmmClassThread
;
// Our scalfmm handle
struct
ScalFmmCoreHandle
{
struct
ScalFmmCoreConfig
{
//paramètres en lecture/écriture :
int
treeHeight
;
// hombre de niveaux de l'arbre (int)
FReal
boxWidth
;
// taille de la boîte racine (FReal)
FPoint
boxCenter
;
// position du centre de la boîte racine (FReal[3])
};
ScalFmmCoreConfig
config
;
OctreeClass
*
octree
;
};
// Allocate and init the handle
extern
"C"
Scalfmm_Handle
Scalfmm_init_handle
(
int
treeHeight
,
double
boxWidth
,
double
*
boxCenter
){
ScalFmmCoreHandle
*
corehandle
=
new
ScalFmmCoreHandle
;
memset
(
corehandle
,
0
,
sizeof
(
ScalFmmCoreHandle
));
corehandle
->
config
.
treeHeight
=
treeHeight
;
corehandle
->
config
.
boxWidth
=
boxWidth
;
corehandle
->
config
.
boxCenter
=
FPoint
(
boxCenter
[
0
],
boxCenter
[
1
],
boxCenter
[
2
]);
corehandle
->
octree
=
new
OctreeClass
(
corehandle
->
config
.
treeHeight
,
FMath
::
Min
(
3
,
corehandle
->
config
.
treeHeight
-
1
),
corehandle
->
config
.
boxWidth
,
corehandle
->
config
.
boxCenter
);
return
corehandle
;
}
// Init the cells (once the particles have been pushed)
extern
"C"
void
Scalfmm_init_cell
(
Scalfmm_Handle
handle
,
Callback_init_cell
cellInitializer
){
if
(
cellInitializer
){
ScalFmmCoreHandle
*
corehandle
=
(
ScalFmmCoreHandle
*
)
handle
;
double
boxWidth
=
corehandle
->
config
.
boxWidth
;
double
boxCorner
[
3
];
boxCorner
[
0
]
=
corehandle
->
config
.
boxCenter
.
getX
()
-
boxWidth
/
2.0
;
boxCorner
[
1
]
=
corehandle
->
config
.
boxCenter
.
getY
()
-
boxWidth
/
2.0
;
boxCorner
[
2
]
=
corehandle
->
config
.
boxCenter
.
getZ
()
-
boxWidth
/
2.0
;
corehandle
->
octree
->
forEachCellWithLevel
([
&
](
CoreCell
*
cell
,
int
level
){
int
coord
[
3
]
=
{
cell
->
getCoordinate
().
getX
(),
cell
->
getCoordinate
().
getY
(),
cell
->
getCoordinate
().
getZ
()
};
double
position
[
3
];
position
[
0
]
=
boxCorner
[
0
]
+
coord
[
0
]
*
boxWidth
/
double
(
1
<<
level
);
position
[
1
]
=
boxCorner
[
1
]
+
coord
[
1
]
*
boxWidth
/
double
(
1
<<
level
);
position
[
2
]
=
boxCorner
[
2
]
+
coord
[
2
]
*
boxWidth
/
double
(
1
<<
level
);
cell
->
setContainer
(
cellInitializer
(
level
,
cell
->
getMortonIndex
(),
coord
,
position
));
});
}
}
// Dealloc the handle and call the destroy function on the cells if given
extern
"C"
void
Scalfmm_dealloc_handle
(
Scalfmm_Handle
handle
,
Callback_free_cell
cellDestroyer
){
ScalFmmCoreHandle
*
corehandle
=
(
ScalFmmCoreHandle
*
)
handle
;
if
(
cellDestroyer
){
corehandle
->
octree
->
forEachCell
([
&
](
CoreCell
*
cell
){
cellDestroyer
(
cell
->
getContainer
());
});
}
delete
corehandle
->
octree
;
delete
corehandle
;
}
// Insert a full array of particles. Posisions are xyz.xyz.xyz...
extern
"C"
void
Scalfmm_insert_array_of_particles
(
Scalfmm_Handle
handle
,
int
nbParticles
,
int
*
particleIndexes
,
double
*
particleXYZ
){
ScalFmmCoreHandle
*
corehandle
=
(
ScalFmmCoreHandle
*
)
handle
;
for
(
int
idxPart
=
0
;
idxPart
<
nbParticles
;
++
idxPart
){
corehandle
->
octree
->
insert
(
FPoint
(
particleXYZ
[
idxPart
*
3
],
particleXYZ
[
idxPart
*
3
+
1
],
particleXYZ
[
idxPart
*
3
+
2
]),
particleIndexes
[
idxPart
]);
}
}
// Push one particle in the tree
extern
"C"
void
Scalfmm_one_particle
(
Scalfmm_Handle
handle
,
int
particleIndex
,
double
x
,
double
y
,
double
z
){
ScalFmmCoreHandle
*
corehandle
=
(
ScalFmmCoreHandle
*
)
handle
;
corehandle
->
octree
->
insert
(
FPoint
(
x
,
y
,
z
),
particleIndex
);
}
// Execute a kernel (by using the user functions callback).
extern
"C"
void
Scalfmm_execute_kernel
(
Scalfmm_Handle
handle
,
struct
Scalfmm_Kernel_Descriptor
userKernel
,
void
*
userData
){
ScalFmmCoreHandle
*
corehandle
=
(
ScalFmmCoreHandle
*
)
handle
;
CoreKernelClass
kernel
(
userKernel
,
userData
);
FmmClassThread
algorithm
(
corehandle
->
octree
,
&
kernel
);
algorithm
.
execute
();
}
Addons/CKernelApi/Tests/testCKernelApi.c
0 → 100755
View file @
7a0e0bd9
// ===================================================================================
// 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* In this file we implement a example kernel which is simply printing information
* about the cells and particles.
* It is recommanded to compile and execute this code in order to understand the behavior
* of the application.
* We mark some part with "JUST-PUT-HERE:" to give instruction to user to create its own kernel.
**/
// Include the FMM API (should be in a different folder for you)
#include "../Src/CKernelApi.h"
// Uncomment the next line to avoid the print in the kernel and verbosity
// #define NOT_TOO_MUCH_VERBOSE
#ifdef NOT_TOO_MUCH_VERBOSE
#define VerbosePrint(X...)
#else
#define VerbosePrint(X...) printf(X)
#endif
///////////////////////////////////////////////////////////////////////////
/// Cell struct and functions
///////////////////////////////////////////////////////////////////////////
// This represent a cell
struct
MyCellDescriptor
{
int
level
;
long
long
mortonIndex
;
int
coord
[
3
];
double
position
[
3
];
// JUST-PUT-HERE:
// You local and multipole arrays
};
// This is our function that init a cell (struct MyCellDescriptor)
void
*
my_Callback_init_cell
(
int
level
,
long
long
mortonIndex
,
int
*
coord
,
double
*
position
){
VerbosePrint
(
"
\t
Allocating cell for level %d, morton index %lld, coord %d/%d/%d
\n
"
,
level
,
mortonIndex
,
coord
[
0
],
coord
[
1
],
coord
[
2
]);
struct
MyCellDescriptor
*
cellData
=
(
struct
MyCellDescriptor
*
)
malloc
(
sizeof
(
struct
MyCellDescriptor
));
memset
(
cellData
,
0
,
sizeof
(
struct
MyCellDescriptor
));
cellData
->
level
=
level
;
cellData
->
mortonIndex
=
mortonIndex
;
memcpy
(
cellData
->
coord
,
coord
,
sizeof
(
int
)
*
3
);
memcpy
(
cellData
->
position
,
position
,
sizeof
(
double
)
*
3
);
// JUST-PUT-HERE:
// Fill your structure
return
cellData
;
}
// To dealloc a cell
void
my_Callback_free_cell
(
void
*
cellData
){
free
(
cellData
);
}
///////////////////////////////////////////////////////////////////////////
/// Kernel struct and functions
///////////////////////////////////////////////////////////////////////////
// This is the data passed to our kernel
struct
MyData
{
// We simply strore the number of call the and particle indexes
double
*
insertedPositions
;
int
countP2M
;
int
countM2M
;
int
countM2L
;
int
countL2L
;
int
countL2P
;
int
countP2PInner
;
int
countP2P
;
// JUST-PUT-HERE:
// everything your kernel will need for its computation
// pre-computed matrices, etc....
};
// Our P2M
void
my_Callback_P2M
(
void
*
cellData
,
int
nbParticlesInLeaf
,
const
int
*
particleIndexes
,
void
*
userData
){
struct
MyData
*
my_data
=
(
struct
MyData
*
)
userData
;
my_data
->
countP2M
+=
1
;
struct
MyCellDescriptor
*
my_cell
=
(
struct
MyCellDescriptor
*
)
cellData
;
VerbosePrint
(
"Cell morton %lld is doing P2M with %d particles :
\n
"
,
my_cell
->
mortonIndex
,
nbParticlesInLeaf
);
int
idxPart
;
for
(
idxPart
=
0
;
idxPart
<
nbParticlesInLeaf
;
++
idxPart
){
double
*
position
=
&
my_data
->
insertedPositions
[
particleIndexes
[
idxPart
]
*
3
];
VerbosePrint
(
"
\t
particle idx %d position %e/%e%e
\n
"
,
particleIndexes
[
idxPart
],
position
[
0
],
position
[
1
],
position
[
2
]);
// JUST-PUT-HERE:
// Your real P2M computation
}
}
void
my_Callback_M2M
(
int
level
,
void
*
cellData
,
int
childPosition
,
void
*
childData
,
void
*
userData
){
struct
MyData
*
my_data
=
(
struct
MyData
*
)
userData
;
my_data
->
countM2M
+=
1
;
struct
MyCellDescriptor
*
my_cell
=
(
struct
MyCellDescriptor
*
)
cellData
;
struct
MyCellDescriptor
*
my_child
=
(
struct
MyCellDescriptor
*
)
childData
;
int
childFullPosition
[
3
];
Scalfmm_utils_parentChildPosition
(
childPosition
,
childFullPosition
);
VerbosePrint
(
"Doing a M2M at level %d, between cells %lld and %lld (position %d/%d/%d)
\n
"
,
level
,
my_cell
->
mortonIndex
,
my_child
->
mortonIndex
,
childFullPosition
[
0
],
childFullPosition
[
1
],
childFullPosition
[
2
]);
// JUST-PUT-HERE: your real M2M computation
}
void
my_Callback_M2L
(
int
level
,
void
*
cellData
,
int
srcPosition
,
void
*
srcData
,
void
*
userData
){
struct
MyData
*
my_data
=
(
struct
MyData
*
)
userData
;
my_data
->
countM2L
+=
1
;
struct
MyCellDescriptor
*
my_cell
=
(
struct
MyCellDescriptor
*
)
cellData
;
struct
MyCellDescriptor
*
my_src_cell
=
(
struct
MyCellDescriptor
*
)
srcData
;
int
interactionFullPosition
[
3
];
Scalfmm_utils_interactionPosition
(
srcPosition
,
interactionFullPosition
);
VerbosePrint
(
"Doing a M2L at level %d, between cells %lld and %lld (position %d/%d/%d)
\n
"
,
level
,
my_cell
->
mortonIndex
,
my_src_cell
->
mortonIndex
,
interactionFullPosition
[
0
],
interactionFullPosition
[
1
],
interactionFullPosition
[
2
]);
// JUST-PUT-HERE: Your M2L
}
void
my_Callback_L2L
(
int
level
,
void
*
cellData
,
int
childPosition
,
void
*
childData
,
void
*
userData
){
struct
MyData
*
my_data
=
(
struct
MyData
*
)
userData
;
my_data
->
countL2L
+=
1
;
struct
MyCellDescriptor
*
my_cell
=
(
struct
MyCellDescriptor
*
)
cellData
;
struct
MyCellDescriptor
*
my_child
=
(
struct
MyCellDescriptor
*
)
childData
;
int
childFullPosition
[
3
];
Scalfmm_utils_parentChildPosition
(
childPosition
,
childFullPosition
);
VerbosePrint
(
"Doing a L2L at level %d, between cells %lld and %lld (position %d/%d/%d)
\n
"
,
level
,
my_cell
->
mortonIndex
,
my_child
->
mortonIndex
,
childFullPosition
[
0
],
childFullPosition
[
1
],
childFullPosition
[
2
]);