Commit 73db0b9d authored by COULAUD Olivier's avatar COULAUD Olivier
parents b44b1753 3947aac0
......@@ -50,6 +50,7 @@ OPTION( ScalFMM_USE_DOUBLE_PRECISION "Set to ON to compile in double precision"
OPTION( ScalFMM_ATTACHE_SOURCE "Set to ON to compile with -g" OFF )
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 )
# Set scalfmm to default libraries
SET(SCALFMM_LIBRARIES "")
#
......@@ -90,9 +91,9 @@ else()
# Compile Release flags
#
SET(CMAKE_BUILD_TYPE Release)
# force -O2 in release
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
STRING(REPLACE "-O3" "" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} )
# force -O3 in release
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
STRING(REPLACE "-O2" "" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} )
# if compiler is intel add -ip
IF(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
SET(ScaLFMM_CXX_FLAGS "${ScaLFMM_CXX_FLAGS} -ip")
......@@ -104,9 +105,9 @@ else()
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" CACHE STRING "Set your optimization flags for release mode.")
SET(SCALFMM_FLAGS_OPTI_RELEASE "-m64 -ffast-math -flto -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" CACHE STRING "Set your optimization flags for release mode.")
SET(SCALFMM_FLAGS_OPTI_RELEASE "-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})
......@@ -175,6 +176,12 @@ endif()
# Use Mem stats
MESSAGE( STATUS "ScalFMM_USE_MEM_STATS = ${ScalFMM_USE_MEM_STATS}" )
# Use Log
MESSAGE( STATUS "ScalFMM_USE_LOG = ${ScalFMM_USE_LOG}" )
# Use Assert
MESSAGE( STATUS "ScalFMM_USE_ASSERT = ${ScalFMM_USE_ASSERT}" )
# Add CBLAS
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CBLAS_LIBRARIES}")
......
This diff is collapsed.
No preview for this file type
Please follow those rules when developing:
==========================================
Static (variables, members, attributes) should start with a capital letter
Class name should start with a capital letter
Mix capital and normal letter to write names (IAmAName) no underscore (but if you have several variables that looks the same be careful: thisIsAXVariable thisIsAYVariable)
Put const every where it is possible (method, value, pointer etc.)
Declare variables usually as late as possible (we are not in C so do not declare every thing at the beginning of a function)
Declare index in the for loop where they are used
Use pre-inc if possible
If an parameter is changed by a function use pointer else use const ref
Please do not name variables with one letter (except it is related to a mathematical formula but then this one should be in the comment in latex format)
Try not to have function bigger than 100 lines
Be consistent
Methods should start with a verb or an action (get, compute, print, etc...)
Please follow those rules when developing in scalfmm:
=====================================================
1 - Static (variables, members, attributes) should start with a capital letter
2 - Class name should start with a capital letter
3 - Mix capital and normal letter to write names (IAmAStaticName, iAmAName) no underscore (but if you have several variables that looks the same be careful: thisIsAXVariable thisIsAYVariable)
4 - Put const every where it is possible (method, value, pointer etc.)
5 - Declare variables usually as late as possible (we are not in old C so do not declare every thing at the beginning of a function). Of course, variable that are used in a loop but with always the same value can be declared at the function beginning.
6 - Declare index in the for loop where they are used (and their names should start with "idx")
7 - Use pre-inc if possible (even if the compiler will optimized post-inc for native type)
8 - If a parameter is changed by a function use pointer else use const ref (if the size of object is less than 20 Bytes you can pass it by value, moreover if it is intensively used!)
9 - Please do not name variables with one letter (except if it is related to a mathematical formula but then this one should be in the comment in latex format)
10 - Try not to have function bigger than 100 lines
11 - Be consistent
12 - Methods should start with a verb or an action (get, compute, print, etc...)
13 - If some code are here temporary (for testing, assertion, etc), put it in a section "{}", and add a comment that explicitly says that it can be removed "todo remove this section" for example.
14 - Sometime no comment is better than outdated (or wrong copy-pasted) comments.
15 - Plain-data struct can be used if it seams natural to use container without method.
Why everything is inside the HPP!? A discussion about why scalfmm should stay like this for now
......
/*! \page contacts Contacts
*
* \section authors Authors
* ScalFmm is a library for the Fast Multipole Method (FMM). It is
* written in C++ and use OpenMP and MPI to support parallel
* execution. It is developed by the HiePACS team at the INRIA.
* You can contact the development team for any questions at
* <ul>
* <li> scalfmm-public-support@lists.gforge.inria.fr</li>
* </ul>
* If you want to see others projects of HiePACS Inria teams, please
* see : https://team.inria.fr/hiepacs/ .
* \section contributors Contributors
*
* <ul>
* <li> Olivier Coulaud </li>
* <li> Bérenger Bramas </li>
* <li> Cyrille Piacibello </li>
* </ul>
*/
/*! \page install Downloading, Building and Installing ScalFMM
*
* \section download Download ScalFMM
*
* To download ScalFmm go on http://scalfmm-public.gforge.inria.fr/download.html.
*
* You can stay in touch of the updates and new version by registering
* to the users mailing list
* (scalfmm-public-users@lists.gforge.inria.fr) which has a very low
* traffic (one email per month) at :
* http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/scalfmm-public-users.
*
* \section secNecessary Require
*
* <ul>
* <li> CMake for compiling, ccmake for configuring the build </li>
* <li> Open MP </li>
* <li> MPI, if you want to use distributed version of the algorithm </li>
* <li> A compiler supporting C++ 2011 </li>
* </ul>
*
* \section build Build
* How to build ScalFMM
* <ul>
* <li> Go to scalfmm/Build directory </li>
* <li> type <b> $> cmake .. </b>
* <ul>
* <li> If you want to enable MPI, use <b> $> cmake .. -DSCALFMM_USE_MPI=ON </b> </li>
* </ul>
* </li>
* <li> then configure your build with <b> $> ccmake .. </b> if needed </li>
* <li> then type <b> $> make name_of_exec </b> </li>
* </ul>
*
* \subsection conf Configuration of the build
*
* This is all the build options you can modify.
*
* <ul>
* <li> CMAKE_INSTALL_PREFIX : to choose where to install ScalFmm </li>
* <li> DSCALFMM_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> SCALFMM_BUILD_DEBUG : to build in debug mode of cmake (with -O0) </li>
* <li> SCALFMM_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>
* <ul>
* <li> SCALFMM_ADDON_FMMAPI : to build Fmm Api </li>
* </ul>
* <li> SCALFMM_USE_DOUBLE_PRECISION : to build in double precision </li>
* <li> SCALFMM_USE_MEM_STATS : to use memory stats (which count any new/delete done during a simulation) </li>
* <li> SCALFMM_USE_BLAS : to enable blas (needed by most of the kernel) </li>
* <ul>
* <li> SCALFMM_USE_MKL_AS_BLAS : to use MKL as blas </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>
* </ul>
*
* Once the library is built, you may want to install it : <b> $> make
* install </b>. Note that it is not an obligation to install ScalFmm
* to use it. You can build it and use it from the Build directory.
* The whole project is documented using Doxygen. You can build the doc
* by typing <b> $> make doc </b> in the Build directory.
*
*
*/
/*! \page License License information
*
*
* The library is under LGPL + CeCILL-C licenses. In case of conflict
* the more restrictive has to be used. We encourage users to have a
* look to the official license websites in case of doubts.
*
* See the GNU General Public and CeCILL-C Licenses for more details.
* "http://www.cecill.info". "http://www.gnu.org/licenses".
*
* ScalFmm is under software patent number
* IDDN.FR.001.100030.000.S.P.2012.000.31235. If you need a more
* flexible license, please do not hesitate to contact us.
*
* 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.
*
*
*/
/*! \page quick Quick Start
* In this section, we present the data structure organization and the
* classes design to understand fully ScalFmm.
* \tableofcontents
* \section prerequisite Prerequisite
* In it is better to have built the library or at minimum to have
* downloaded the sources. The user needs to be comfortable with 'C++'
* language and if possible templates.
* \section classes Overview of general architecture
*
* \image html Classes.png "General architecture"
* \section data What Data
* In ScalFmm we proceed the Fast Multipole Method. New users should see
* this process has a way to estimate far interactions and compute
* accurately the close interactions in a group of particles. We then
* have some particles that we insert in a octree. The octree stores the
* particles in its leaves. From the root to the leaves there are the
* cells. At this point we only express primitives classes which hold
* data or primitives classes.
* Then, we need a kernel which is computational part of the FMM. It is a
* class that is able to compute the interactions between particles or
* cells, etc. There is several possible kernels depending on what we
* want to compute.
* Finally, the FMM Core algorithm is a class that takes the primitives
* classes and calls the kernel with the correct arguments. In our
* implementation, the user has to choose between sequential FMM or
* OpenMP FMM.
* \section primitivesclasses Primitives Classes
* \subsection particles Particles
* To be stored in the octree, a particle must inherites
* FAbstractParticleContainer. This is the class needed:
* <pre class='brush: cpp'>
* class FAbstractParticleContainer{
* template<typename... Args>
* void push(const FPoint& , Args ... ){
* };
* </pre>
* A class implements this minimum required methods, it is
* FBasicParticleContainer. This is what MUST proposes a particle
* class to be able to be inserted in the tree. Then, the user can add
* other methods to match the kernel requirement. For example, some
* kernel may need a particle to hold a physical value, a forces
* vector and a potential. See FRotationParticleContainer if you want
* an example of a Particle class.
* \subsection cells Cells
* The same principle apply to cells. There is a minimum sets of
* methods that must propose a cell class to be able to be used in the
* octree. And then, there are some other methods that you can add to
* make it usable per the kernel.
* The class Src/Components/FAbstractCell.hpp shows what should
* implement a cell:
* <pre class='brush: cpp'>
* class FAbstractCell{
* public:
* virtual ~FAbstractCell(){
* }
* virtual MortonIndex getMortonIndex() const = 0;
* virtual void setMortonIndex(const MortonIndex inIndex) = 0;
* virtual void setPosition(const FPoint& inPosition) = 0;
* virtual const FTreeCoordinate& getCoordinate() const = 0;
* virtual void setCoordinate(const long inX, const long inY, const long inZ) = 0;
* virtual bool hasSrcChild() const = 0;
* virtual bool hasTargetsChild() const = 0;
* virtual void setSrcChildTrue() = 0;
* virtual void setTargetsChildTrue() = 0;
* };
* </pre>
* The FBasicCell class provides an implementation of all these
* methods.
* \subsection leaves Leaves
* The leaf is the class responsible of hosting the particles. The
* octree uses this class and order to store a particle. Behind the
* scene, the leaf does what it wants. But, the octree also needs a way
* to get the particles it has inserted which can be targets or
* sources
* In the following class, FAbstractLeaf, one can see what is required
* by the algorithm :
* <pre>
* template< class ParticleClass, class ContainerClass >
* class FAbstractLeaf {
* public:
* // Default destructor
* virtual ~FAbstractLeaf(){
* }
* virtual void push(const ParticleClass& particle) = 0;
* virtual ContainerClass* getSrc() = 0;
* virtual ContainerClass* getTargets() = 0;
* };
* </pre>
* The FSimpleLeaf class provides an implementation of all thes
* methods.
* \section octree Octree
* The octree is templatized and then can host particles, cells and
* leaves. It also needs some information about the simulation like the
* size and the center of the box. Moreover, the user has to precise
* the height of the octree. The root is the level 0, so giving a
* height of 3 creates the root level, a cells level and the leaves
* level. The usual way of declaring the octree, taken from
* Tests/Utils/testOctree.cpp, is as follow:
* <pre>
* typedef FVector<FBasicParticle> ContainerClass;
* typedef FSimpleLeaf<FBasicParticle, ContainerClass > LeafClass;
* typedef FOctree<FBasicParticle, FBasicCell, ContainerClass , LeafClass > OctreeClass;
* OctreeClass tree(HEIGHT, SUBHEIGHT, BoxWidth, CenterOfBox);
* </pre>
* \subsection loading Loading Particle
* Once the octree is created, we need to put some particles in
* it. This is perform using classes called 'loader'.
* A loader should proposes theses methods :
* <pre>
* template <class ParticleClass>
* class FAbstractLoader {
* public:
* // Default destructor
* virtual ~FAbstractLoader(){
* }
* virtual FSize getNumberOfParticles() const = 0;
* virtual FPoint getCenterOfBox() const = 0;
* virtual FReal getBoxWidth() const = 0;
* virtual bool isOpen() const = 0;
* virtual void fillParticle(ParticleClass& inParticle) = 0;
* template <class OctreeClass>
* void fillTree(OctreeClass& tree){
* ParticleClass particleToFill;
* for(int idxPart = 0 ; idxPart < getNumberOfParticles() ; ++idxPart){
* fillParticle(particleToFill);
* tree.insert(particleToFill);
* }
* }
* };
* </pre>
* There exist several loaders; one per file format. Depending of the
* loader, the particle class should implement special methods. For
* example, the basic loader only fill the position of the
* particles. Whereas, the FMA loader also fill the physical value of
* the particles.
* The usual way of loading the particle is as follow :
* <pre>
* FRandomLoader<ParticleClass> loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1);
* OctreeClass tree(10, 3, loader.getBoxWidth(), loader.getCenterOfBox());
* loader.fillTree(tree);
* </pre>
* \subsection octreeIterator Iterating on an Octree
*If the user wants to iterate on the tree and access the particles or
*the cells. To do so, he needs to declare an iterator and use it to
*move from top to bottom and from left to right. It is critical that
*the octree is not empty!
* This next sample is taken from Tests/Utils/testOctreeIter.cpp and
* count the leaves :
* <pre>
* OctreeClass::Iterator octreeIterator(&tree);
* octreeIterator.gotoBottomLeft();
* int counter = 0;
* do{
* ++counter;
* } while(octreeIterator.moveRight());
* </pre>
* To iterate on the cells we can proceed as follow :
* <pre>
* OctreeClass::Iterator octreeIterator(&tree);
* octreeIterator.gotoBottomLeft();
* for(int idxLevel = NbLevels - 1 ; idxLevel >= 1 ; --idxLevel ){
* int counter = 0;
* do{
* ++counter;
* } while(octreeIterator.moveRight());
* octreeIterator.moveUp();
* octreeIterator.gotoLeft();
* std::cout << "Cells at level " << idxLevel << " = " << counter << " ...\n";
* }
* </pre>
* \section kernel The kernel
* The kernel is a class that should perform the usual FMM
* operators. Each kind of kernel may require special methods and
* needs on the particles and the cells.
* An empty kernel can be found in Src/Components/FBasicKernels.hpp,
* it implements the class definition FAbstractKernels :
* <pre>
* template< class ParticleClass, class CellClass, class ContainerClass> class FBasicKernels : public FAbstractKernels<ParticleClass,CellClass,ContainerClass> {
* public:
*
* // Default destructor
* virtual ~FBasicKernels(){}
* virtual void P2M(CellClass* const , const ContainerClass* const ) {}
* virtual void M2M(CellClass* const FRestrict , const CellClass*const FRestrict *const FRestrict , const int ) {}
* virtual void M2L(CellClass* const FRestrict , const CellClass* [], const int , const int ) {}
* virtual void L2L(const CellClass* const FRestrict , CellClass* FRestrict *const FRestrict , const int ) {}
* virtual void L2P(const CellClass* const , ContainerClass* const ){}
* virtual void P2P(const FTreeCoordinate& ,
* ContainerClass* const FRestrict , const ContainerClass* const FRestrict ,
* ContainerClass* const [27], const int ){}
* virtual void P2PRemote(const FTreeCoordinate& ,
* ContainerClass* const FRestrict , const ContainerClass* const FRestrict ,
* ContainerClass* const [27], const int ){}
* </pre>
* One example of kernel is the 'test' kernel called
* FTestKernels. This kernels simply sum the particles (one particle
* weigh = 1) so at the end of the simulation each particles should be
* have a weigh of N. We just declare this kernel based on the
* components type but usually do not call any method manually since
* this is performed per the FMM core.
* <pre>
* typedef FTestKernels<ParticleClass, CellClass, ContainerClass > KernelClass;
* KernelClass kernels;
* </pre>
* \section coreFMM The FMM Core
* We showed how to have an octree and a kernel. Now, we show how to use
* a Fmm Algorithm on the data. Remember, the FMM algorithm simply
* takes the data from the octree and call the method of the
* kernel. The goal is to have a FMM independent from the data.
* The next sample is taken from Tests/Utils/testFmmAlgorithm.cpp and
* use the basic sequential FMM :
* <pre>
* typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass;
* FmmClass algo(&tree,&kernels);
* algo.execute();
* </pre>
* To move to the OpenMP threaded FMM we can use the fallowing code by
* changing 'FFmmAlgorithm' per 'FFmmAlgorithmThread' :
* <pre>
* typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass;
* FmmClass algo(&tree,&kernels);
* algo.execute();
* </pre>
\section reasons The reasons why ...
* Of course the library is changing and re-factorized usually but
* lets discuss about 'The reasons why' :
* <ul>
* <li> Every things is templatized :
* <blockquote>
* The reason is to avoid the use of virtual and abstract class. In
* this page we present some abstract classes, but they are not really
* use. They only define the need, the minimum required to implement a
* particle or a cell. But the kernels should not work on an abstract
* type but on the real data. This enable lots of compiler
* optimizations and avoid the use of V-Table.
* </blockquote>
* </li>
* <li>
* Some destructors are not virtual :
* <blockquote>
* As we said, the objective of the class are not to be inherited. So
* a virtual destructor is not needed.
* </blockquote>
* </li>
* <li>
* Typedef is used like this :
* <blockquote>
* It can take some time to understand how it works. But all our users
* finally like the way of using typedef and template. As you will see
* in most of the example the struct is the same and you will not be
* lost since in any example 'ParticleClass' is used for the particle
* type and so on.
* </blockquote>
* </li>
* </ul>
*/
// This page contains the special doxygen pages and mainpage.
/*!
* @mainpage ScalFmm
*
* \section overV Overview
*
* ScalFMM is a software library to simulate N-body interactions using
* the Fast Multipole Method.
*
* The library offers two methods to compute interactions between
* bodies when the potential decays like 1/r. The first method is the
* classical FMM based on spherical harmonic expansions and the second is
* the Black-Box method which is an independent kernel formulation
* (introduced by E. Darve @ Stanford). With this method, we can now
* easily add new non oscillatory kernels in our library. For the
* classical method, two approaches are used to decrease the complexity
* of the operators. We consider either matrix formulation that allows us
* to use BLAS routines or rotation matrices to speed up the M2L
* operator.
*
* ScalFMM intends to offer all the functionalities needed to perform
* large parallel simulations while enabling an easy customization of
* the simulation components: kernels, particles and cells. It works
* in parallel in a shared/distributed memory model using OpenMP and
* MPI. The software architecture has been designed with two major
* objectives: being easy to maintain and easy to understand. There is
* two main parts:
* <ul>
* <li> the management of the octree and the
* parallelization of the method; </li>
* <li> The kernels. This new
* architecture allow us to easily add new FMM algorithm or kernels
* and new paradigm of parallelization. </li>
* </ul>
*
*
* To download build and install the application, please see \ref
* install.
*
* The \ref quick can help you to understand the architectur of the
* library.
*
* This software is distributed under a specific License. For more
* informations, see \ref License.
*
* If you want to cite the project and/or the team, please contact
* us. See \ref contacts page.
*
*/
......@@ -10,6 +10,7 @@ cmake ..
# Or if you want to use MPI
cmake .. -DScalFMM_USE_MPI=ON
# Configure, for example with:
ccmake ..
# turn on/off the options you want
......@@ -29,6 +30,3 @@ cd scalfmm/Build
make doc
# This will create a Html dir
browser scalfmm/Build/Doc/html/index.html
......@@ -19,7 +19,7 @@
#include "../Utils/FGlobal.hpp"
#include "../Utils/FPoint.hpp"
#include "../Containers/FVector.hpp"
#include "../Utils/FAssertable.hpp"
#include "../Utils/FAssert.hpp"
#include "../Utils/FGlobalPeriodic.hpp"
......@@ -37,13 +37,13 @@
* tree.
*/
template <class OctreeClass, class ContainerClass, class ParticleClass, class ConverterClass >
class FOctreeArranger : FAssertable {
class FOctreeArranger {
OctreeClass* const tree; //< The tree to work on
public:
/** Basic constructor */
FOctreeArranger(OctreeClass* const inTree) : tree(inTree) {
fassert(tree, "Tree cannot be null", __LINE__ , __FILE__ );
FAssertLF(tree, "Tree cannot be null" );
}
/** Arrange */
......
......@@ -18,7 +18,7 @@
#include "../Utils/FGlobal.hpp"
#include "../Containers/FVector.hpp"
#include "../Utils/FAssertable.hpp"
#include "../Utils/FAssert.hpp"
#include "../Utils/FMpi.hpp"
#include "../Utils/FGlobalPeriodic.hpp"
......@@ -36,7 +36,7 @@